Merge pull request #50457 from lawnjelly/portals_config_warn

This commit is contained in:
Rémi Verschelde 2021-07-15 12:30:33 +02:00 committed by GitHub
commit bc40546406
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 196 additions and 8 deletions

View file

@ -33,6 +33,7 @@
#include "core/engine.h"
#include "mesh_instance.h"
#include "room.h"
#include "room_group.h"
#include "room_manager.h"
#include "scene/main/viewport.h"
#include "servers/visual_server.h"
@ -69,6 +70,37 @@ Portal::~Portal() {
}
}
String Portal::get_configuration_warning() const {
String warning = Spatial::get_configuration_warning();
auto lambda = [](const Node *p_node) {
return static_cast<bool>((Object::cast_to<RoomManager>(p_node) || Object::cast_to<Room>(p_node) || Object::cast_to<RoomGroup>(p_node)));
};
if (Room::detect_nodes_using_lambda(this, lambda)) {
if (Room::detect_nodes_of_type<RoomManager>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("The RoomManager should not be a child or grandchild of a Portal.");
}
if (Room::detect_nodes_of_type<Room>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("A Room should not be a child or grandchild of a Portal.");
}
if (Room::detect_nodes_of_type<RoomGroup>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("A RoomGroup should not be a child or grandchild of a Portal.");
}
}
return warning;
}
void Portal::set_points(const PoolVector<Vector2> &p_points) {
_pts_local_raw = p_points;
_sanitize_points();

View file

@ -79,6 +79,8 @@ public:
void set_points(const PoolVector<Vector2> &p_points);
PoolVector<Vector2> get_points() const;
String get_configuration_warning() const;
Portal();
~Portal();

View file

@ -31,6 +31,7 @@
#include "room.h"
#include "portal.h"
#include "room_group.h"
#include "room_manager.h"
#include "servers/visual_server.h"
@ -180,6 +181,39 @@ PoolVector<Vector3> Room::generate_points() {
return pts_returned;
}
String Room::get_configuration_warning() const {
String warning = Spatial::get_configuration_warning();
auto lambda = [](const Node *p_node) {
return static_cast<bool>((Object::cast_to<Room>(p_node) || Object::cast_to<RoomManager>(p_node) || Object::cast_to<RoomGroup>(p_node)));
};
if (detect_nodes_using_lambda(this, lambda)) {
if (detect_nodes_of_type<Room>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("A Room cannot have another Room as a child or grandchild.");
}
if (detect_nodes_of_type<RoomManager>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("The RoomManager should not be placed inside a Room.");
}
if (detect_nodes_of_type<RoomGroup>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("A RoomGroup should not be placed inside a Room.");
}
}
return warning;
}
// extra editor links to the room manager to allow unloading
// on change, or re-converting
void Room::_changed(bool p_regenerate_bounds) {

View file

@ -74,9 +74,15 @@ public:
// editor only
PoolVector<Vector3> generate_points();
String get_configuration_warning() const;
private:
void clear();
void _changed(bool p_regenerate_bounds = false);
template <class T>
static bool detect_nodes_of_type(const Node *p_node, bool p_ignore_first_node = true);
template <typename T>
static bool detect_nodes_using_lambda(const Node *p_node, T p_lambda, bool p_ignore_first_node = true);
// planes forming convex hull of room
LocalVector<Plane, int32_t> _planes;
@ -128,4 +134,33 @@ protected:
void _notification(int p_what);
};
template <class T>
bool Room::detect_nodes_of_type(const Node *p_node, bool p_ignore_first_node) {
if (Object::cast_to<T>(p_node) && (!p_ignore_first_node)) {
return true;
}
for (int n = 0; n < p_node->get_child_count(); n++) {
if (detect_nodes_of_type<T>(p_node->get_child(n), false)) {
return true;
}
}
return false;
}
template <typename T>
bool Room::detect_nodes_using_lambda(const Node *p_node, T p_lambda, bool p_ignore_first_node) {
if (p_lambda(p_node) && !p_ignore_first_node) {
return true;
}
for (int n = 0; n < p_node->get_child_count(); n++) {
if (detect_nodes_using_lambda(p_node->get_child(n), p_lambda, false)) {
return true;
}
}
return false;
}
#endif

View file

@ -50,6 +50,19 @@ RoomGroup::~RoomGroup() {
}
}
String RoomGroup::get_configuration_warning() const {
String warning = Spatial::get_configuration_warning();
if (Room::detect_nodes_of_type<RoomManager>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("The RoomManager should not be placed inside a RoomGroup.");
}
return warning;
}
void RoomGroup::clear() {
_roomgroup_ID = -1;
}

View file

@ -55,6 +55,8 @@ public:
}
int get_roomgroup_priority() const { return _settings_priority; }
String get_configuration_warning() const;
private:
void clear();
void _changed();

View file

@ -75,6 +75,69 @@ RoomManager::~RoomManager() {
active_room_manager = nullptr;
#endif
}
String RoomManager::get_configuration_warning() const {
String warning = Spatial::get_configuration_warning();
if (_settings_path_roomlist == NodePath()) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("The RoomList has not been assigned.");
} else {
Spatial *roomlist = _resolve_path<Spatial>(_settings_path_roomlist);
if (!roomlist || (roomlist->get_class_name() != StringName("Spatial"))) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("The RoomList should be a Spatial.");
}
}
if (_settings_portal_depth_limit == 0) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("Portal Depth Limit is set to Zero.\nOnly the Room that the Camera is in will render.");
}
auto lambda = [](const Node *p_node) {
return static_cast<bool>((Object::cast_to<Room>(p_node) || Object::cast_to<RoomGroup>(p_node) || Object::cast_to<Portal>(p_node) || Object::cast_to<RoomManager>(p_node)));
};
if (Room::detect_nodes_using_lambda(this, lambda)) {
if (Room::detect_nodes_of_type<Room>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("Rooms should not be children of the RoomManager.");
}
if (Room::detect_nodes_of_type<RoomGroup>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("RoomGroups should not be children of the RoomManager.");
}
if (Room::detect_nodes_of_type<Portal>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("Portals should not be children of the RoomManager.");
}
if (Room::detect_nodes_of_type<RoomManager>(this)) {
if (!warning.empty()) {
warning += "\n\n";
}
warning += TTR("There should only be one RoomManager in the SceneTree.");
}
}
return warning;
}
void RoomManager::_preview_camera_update() {
Ref<World> world = get_world();
RID scenario = world->get_scenario();
@ -180,6 +243,9 @@ void RoomManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pvs_mode", "pvs_mode"), &RoomManager::set_pvs_mode);
ClassDB::bind_method(D_METHOD("get_pvs_mode"), &RoomManager::get_pvs_mode);
ClassDB::bind_method(D_METHOD("set_roomlist_path", "p_path"), &RoomManager::set_roomlist_path);
ClassDB::bind_method(D_METHOD("get_roomlist_path"), &RoomManager::get_roomlist_path);
// These are commented out for now, but available in case we want to cache PVS to disk, the functionality exists
// ClassDB::bind_method(D_METHOD("set_pvs_filename", "pvs_filename"), &RoomManager::set_pvs_filename);
// ClassDB::bind_method(D_METHOD("get_pvs_filename"), &RoomManager::get_pvs_filename);
@ -200,7 +266,7 @@ void RoomManager::_bind_methods() {
ADD_GROUP("Main", "");
LIMPL_PROPERTY(Variant::BOOL, active, rooms_set_active, rooms_get_active);
LIMPL_PROPERTY(Variant::NODE_PATH, roomlist, set_roomlist_path, get_roomlist_path);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "roomlist", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_roomlist_path", "get_roomlist_path");
ADD_GROUP("PVS", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "pvs_mode", PROPERTY_HINT_ENUM, "Disabled,Partial,Full"), "set_pvs_mode", "get_pvs_mode");
@ -234,6 +300,11 @@ void RoomManager::_bind_methods() {
#undef LPORTAL_TOSTRING
}
void RoomManager::set_roomlist_path(const NodePath &p_path) {
_settings_path_roomlist = p_path;
update_configuration_warning();
}
void RoomManager::set_preview_camera_path(const NodePath &p_path) {
_settings_path_preview_camera = p_path;
@ -281,7 +352,7 @@ bool RoomManager::get_flip_portal_meshes() const {
}
void RoomManager::set_portal_depth_limit(int p_limit) {
_portal_depth_limit = p_limit;
_settings_portal_depth_limit = p_limit;
if (is_inside_world() && get_world().is_valid()) {
VisualServer::get_singleton()->rooms_set_params(get_world()->get_scenario(), p_limit);

View file

@ -53,10 +53,7 @@ public:
PVS_MODE_FULL,
};
void set_roomlist_path(const NodePath &p_path) {
_settings_path_roomlist = p_path;
}
void set_roomlist_path(const NodePath &p_path);
NodePath get_roomlist_path() const {
return _settings_path_roomlist;
}
@ -95,7 +92,7 @@ public:
int get_overlap_warning_threshold() const { return (int)_overlap_warning_threshold; }
void set_portal_depth_limit(int p_limit);
int get_portal_depth_limit() const { return _portal_depth_limit; }
int get_portal_depth_limit() const { return _settings_portal_depth_limit; }
void set_flip_portal_meshes(bool p_flip);
bool get_flip_portal_meshes() const;
@ -119,6 +116,8 @@ public:
void rooms_clear();
void rooms_flip_portals();
String get_configuration_warning() const;
// for internal use in the editor..
// either we can clear the rooms and unload,
// or reconvert.
@ -253,7 +252,7 @@ private:
real_t _default_portal_margin = 1.0;
real_t _overlap_warning_threshold = 1.0;
Room::SimplifyInfo _room_simplify_info;
int _portal_depth_limit = 16;
int _settings_portal_depth_limit = 16;
// debug override camera
ObjectID _godot_preview_camera_ID = -1;