2
0
Эх сурвалжийг харах

Merge pull request #50457 from lawnjelly/portals_config_warn

Rémi Verschelde 4 жил өмнө
parent
commit
bc40546406

+ 32 - 0
scene/3d/portal.cpp

@@ -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();

+ 2 - 0
scene/3d/portal.h

@@ -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();
 

+ 34 - 0
scene/3d/room.cpp

@@ -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) {

+ 35 - 0
scene/3d/room.h

@@ -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

+ 13 - 0
scene/3d/room_group.cpp

@@ -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;
 }

+ 2 - 0
scene/3d/room_group.h

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

+ 73 - 2
scene/3d/room_manager.cpp

@@ -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);

+ 5 - 6
scene/3d/room_manager.h

@@ -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;