diff options
Diffstat (limited to 'scene/resources/world_2d.cpp')
-rw-r--r-- | scene/resources/world_2d.cpp | 72 |
1 files changed, 18 insertions, 54 deletions
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 742ef106d9..1c753fdb91 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -38,9 +38,7 @@ #include "servers/rendering_server.h" struct SpatialIndexer2D { - struct CellRef { - int ref; _FORCE_INLINE_ int inc() { @@ -58,7 +56,6 @@ struct SpatialIndexer2D { }; struct CellKey { - union { struct { int32_t x; @@ -74,7 +71,6 @@ struct SpatialIndexer2D { }; struct CellData { - Map<VisibilityNotifier2D *, CellRef> notifiers; }; @@ -84,7 +80,6 @@ struct SpatialIndexer2D { Map<VisibilityNotifier2D *, Rect2> notifiers; struct ViewportData { - Map<VisibilityNotifier2D *, uint64_t> notifiers; Rect2 rect; }; @@ -96,30 +91,25 @@ struct SpatialIndexer2D { uint64_t pass; void _notifier_update_cells(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect, bool p_add) { - Point2i begin = p_rect.position; begin /= cell_size; Point2i end = p_rect.position + p_rect.size; end /= cell_size; for (int i = begin.x; i <= end.x; i++) { - for (int j = begin.y; j <= end.y; j++) { - CellKey ck; ck.x = i; ck.y = j; Map<CellKey, CellData>::Element *E = cells.find(ck); if (p_add) { - - if (!E) + if (!E) { E = cells.insert(ck, CellData()); + } E->get().notifiers[p_notifier].inc(); } else { - ERR_CONTINUE(!E); if (E->get().notifiers[p_notifier].dec() == 0) { - E->get().notifiers.erase(p_notifier); if (E->get().notifiers.empty()) { cells.erase(E); @@ -131,7 +121,6 @@ struct SpatialIndexer2D { } void _notifier_add(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { - ERR_FAIL_COND(notifiers.has(p_notifier)); notifiers[p_notifier] = p_rect; _notifier_update_cells(p_notifier, p_rect, true); @@ -139,11 +128,11 @@ struct SpatialIndexer2D { } void _notifier_update(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { - Map<VisibilityNotifier2D *, Rect2>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); - if (E->get() == p_rect) + if (E->get() == p_rect) { return; + } _notifier_update_cells(p_notifier, p_rect, true); _notifier_update_cells(p_notifier, E->get(), false); @@ -152,7 +141,6 @@ struct SpatialIndexer2D { } void _notifier_remove(VisibilityNotifier2D *p_notifier) { - Map<VisibilityNotifier2D *, Rect2>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); _notifier_update_cells(p_notifier, E->get(), false); @@ -160,7 +148,6 @@ struct SpatialIndexer2D { List<Viewport *> removed; for (Map<Viewport *, ViewportData>::Element *F = viewports.front(); F; F = F->next()) { - Map<VisibilityNotifier2D *, uint64_t>::Element *G = F->get().notifiers.find(p_notifier); if (G) { @@ -170,7 +157,6 @@ struct SpatialIndexer2D { } while (!removed.empty()) { - p_notifier->_exit_viewport(removed.front()->get()); removed.pop_front(); } @@ -179,7 +165,6 @@ struct SpatialIndexer2D { } void _add_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - ERR_FAIL_COND(viewports.has(p_viewport)); ViewportData vd; vd.rect = p_rect; @@ -188,11 +173,11 @@ struct SpatialIndexer2D { } void _update_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - Map<Viewport *, ViewportData>::Element *E = viewports.find(p_viewport); ERR_FAIL_COND(!E); - if (E->get().rect == p_rect) + if (E->get().rect == p_rect) { return; + } E->get().rect = p_rect; changed = true; } @@ -201,7 +186,6 @@ struct SpatialIndexer2D { ERR_FAIL_COND(!viewports.has(p_viewport)); List<VisibilityNotifier2D *> removed; for (Map<VisibilityNotifier2D *, uint64_t>::Element *E = viewports[p_viewport].notifiers.front(); E; E = E->next()) { - removed.push_back(E->key()); } @@ -214,12 +198,11 @@ struct SpatialIndexer2D { } void _update() { - - if (!changed) + if (!changed) { return; + } for (Map<Viewport *, ViewportData>::Element *E = viewports.front(); E; E = E->next()) { - Point2i begin = E->get().rect.position; begin /= cell_size; Point2i end = E->get().rect.position + E->get().rect.size; @@ -231,24 +214,22 @@ struct SpatialIndexer2D { int visible_cells = (end.x - begin.x) * (end.y - begin.y); if (visible_cells > 10000) { - //well you zoomed out a lot, it's your problem. To avoid freezing in the for loops below, we'll manually check cell by cell for (Map<CellKey, CellData>::Element *F = cells.front(); F; F = F->next()) { - const CellKey &ck = F->key(); - if (ck.x < begin.x || ck.x > end.x) + if (ck.x < begin.x || ck.x > end.x) { continue; - if (ck.y < begin.y || ck.y > end.y) + } + if (ck.y < begin.y || ck.y > end.y) { continue; + } //notifiers in cell for (Map<VisibilityNotifier2D *, CellRef>::Element *G = F->get().notifiers.front(); G; G = G->next()) { - Map<VisibilityNotifier2D *, uint64_t>::Element *H = E->get().notifiers.find(G->key()); if (!H) { - H = E->get().notifiers.insert(G->key(), pass); added.push_back(G->key()); } else { @@ -258,12 +239,9 @@ struct SpatialIndexer2D { } } else { - //check cells in grid fashion for (int i = begin.x; i <= end.x; i++) { - for (int j = begin.y; j <= end.y; j++) { - CellKey ck; ck.x = i; ck.y = j; @@ -275,10 +253,8 @@ struct SpatialIndexer2D { //notifiers in cell for (Map<VisibilityNotifier2D *, CellRef>::Element *G = F->get().notifiers.front(); G; G = G->next()) { - Map<VisibilityNotifier2D *, uint64_t>::Element *H = E->get().notifiers.find(G->key()); if (!H) { - H = E->get().notifiers.insert(G->key(), pass); added.push_back(G->key()); } else { @@ -290,9 +266,9 @@ struct SpatialIndexer2D { } for (Map<VisibilityNotifier2D *, uint64_t>::Element *F = E->get().notifiers.front(); F; F = F->next()) { - - if (F->get() != pass) + if (F->get() != pass) { removed.push_back(F->key()); + } } while (!added.empty()) { @@ -311,64 +287,55 @@ struct SpatialIndexer2D { } SpatialIndexer2D() { - pass = 0; changed = false; - cell_size = 100; //should be configurable with GLOBAL_DEF("") i guess + cell_size = GLOBAL_DEF("world/2d/cell_size", 100); } }; void World2D::_register_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - indexer->_add_viewport(p_viewport, p_rect); } void World2D::_update_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - indexer->_update_viewport(p_viewport, p_rect); } -void World2D::_remove_viewport(Viewport *p_viewport) { +void World2D::_remove_viewport(Viewport *p_viewport) { indexer->_remove_viewport(p_viewport); } void World2D::_register_notifier(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { - indexer->_notifier_add(p_notifier, p_rect); } -void World2D::_update_notifier(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { +void World2D::_update_notifier(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { indexer->_notifier_update(p_notifier, p_rect); } -void World2D::_remove_notifier(VisibilityNotifier2D *p_notifier) { +void World2D::_remove_notifier(VisibilityNotifier2D *p_notifier) { indexer->_notifier_remove(p_notifier); } void World2D::_update() { - indexer->_update(); } RID World2D::get_canvas() { - return canvas; } RID World2D::get_space() { - return space; } void World2D::get_viewport_list(List<Viewport *> *r_viewports) { - for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) { r_viewports->push_back(E->key()); } } void World2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas); ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space); @@ -380,12 +347,10 @@ void World2D::_bind_methods() { } PhysicsDirectSpaceState2D *World2D::get_direct_space_state() { - return PhysicsServer2D::get_singleton()->space_get_direct_state(space); } World2D::World2D() { - canvas = RenderingServer::get_singleton()->canvas_create(); space = PhysicsServer2D::get_singleton()->space_create(); @@ -401,7 +366,6 @@ World2D::World2D() { } World2D::~World2D() { - RenderingServer::get_singleton()->free(canvas); PhysicsServer2D::get_singleton()->free(space); memdelete(indexer); |