From a339f6fc49886dbbf4dfac5199bd381a6caf06df Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Sun, 8 Aug 2021 14:37:04 +0100 Subject: [PATCH] Portals - fix autolinking to internal rooms Portal autolinking was previously agnostic to room priorities, which meant that portals would link to the first room they found (often outside rooms). This PR fixes this by making the autolinking priority aware, and will preferentially link to internal rooms. --- scene/3d/room_manager.cpp | 43 ++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/scene/3d/room_manager.cpp b/scene/3d/room_manager.cpp index e30558463403..1d2b6645eae5 100644 --- a/scene/3d/room_manager.cpp +++ b/scene/3d/room_manager.cpp @@ -971,6 +971,9 @@ void RoomManager::_autolink_portals(Spatial *p_roomlist, LocalVector & Vector3 test_pos = portal->_pt_center_world + (dist * portal->_plane.normal); + int best_priority = -1000; + int best_room = -1; + for (int r = 0; r < _rooms.size(); r++) { Room *room = _rooms[r]; if (room->_room_ID == portal->_linkedroom_ID[0]) { @@ -993,25 +996,37 @@ void RoomManager::_autolink_portals(Spatial *p_roomlist, LocalVector & } // for through planes if (!outside) { - // great, we found a linked room! - convert_log("\t\tAUTOLINK OK from " + source_room->get_name() + " to " + room->get_name(), 1); - portal->_linkedroom_ID[1] = r; + // we found a suitable room, but we want the highest priority in + // case there are internal rooms... + if (room->_room_priority > best_priority) { + best_priority = room->_room_priority; + best_room = r; + } + } - // add the portal to the portals list for the receiving room - room->_portals.push_back(n); + } // for through rooms - // send complete link to visual server so the portal will be active in the visual server room system - VisualServer::get_singleton()->portal_link(portal->_portal_rid, source_room->_room_rid, room->_room_rid, portal->_settings_two_way); + // found a suitable link room + if (best_room != -1) { + Room *room = _rooms[best_room]; - // make the portal internal if necessary - // (this prevents the portal plane clipping the room bound) - portal->_internal = source_room->_room_priority > room->_room_priority; + // great, we found a linked room! + convert_log("\t\tAUTOLINK OK from " + source_room->get_name() + " to " + room->get_name(), 1); + portal->_linkedroom_ID[1] = best_room; - autolink_found = true; - break; - } + // add the portal to the portals list for the receiving room + room->_portals.push_back(n); - } // for through rooms + // send complete link to visual server so the portal will be active in the visual server room system + VisualServer::get_singleton()->portal_link(portal->_portal_rid, source_room->_room_rid, room->_room_rid, portal->_settings_two_way); + + // make the portal internal if necessary + // (this prevents the portal plane clipping the room bound) + portal->_internal = source_room->_room_priority > room->_room_priority; + + autolink_found = true; + break; + } } // for attempt