Pārlūkot izejas kodu

Fix some ways to create inconsistent Viewport sizes

In the editor, it was possible to set the size of a `SubViewport` even
in cases where a parent `SubViewportContainer` had stretch enabled.

This PR disables editing a `SubViewport.size` while the parent disallows
it and it makes necessary adjustments during `NOTIFICATION_ENTER_TREE`.
Markus Sauermann 2 gadi atpakaļ
vecāks
revīzija
34a7fc7447

+ 8 - 14
scene/gui/subviewport_container.cpp

@@ -58,6 +58,7 @@ void SubViewportContainer::set_stretch(bool p_enable) {
 	}
 
 	stretch = p_enable;
+	recalc_force_viewport_sizes();
 	update_minimum_size();
 	queue_sort();
 	queue_redraw();
@@ -75,10 +76,16 @@ void SubViewportContainer::set_stretch_shrink(int p_shrink) {
 
 	shrink = p_shrink;
 
+	recalc_force_viewport_sizes();
+	queue_redraw();
+}
+
+void SubViewportContainer::recalc_force_viewport_sizes() {
 	if (!stretch) {
 		return;
 	}
 
+	// If stretch is enabled, make sure that all child SubViwewports have the correct size.
 	for (int i = 0; i < get_child_count(); i++) {
 		SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
 		if (!c) {
@@ -87,8 +94,6 @@ void SubViewportContainer::set_stretch_shrink(int p_shrink) {
 
 		c->set_size_force(get_size() / shrink);
 	}
-
-	queue_redraw();
 }
 
 int SubViewportContainer::get_stretch_shrink() const {
@@ -106,18 +111,7 @@ Vector<int> SubViewportContainer::get_allowed_size_flags_vertical() const {
 void SubViewportContainer::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_RESIZED: {
-			if (!stretch) {
-				return;
-			}
-
-			for (int i = 0; i < get_child_count(); i++) {
-				SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
-				if (!c) {
-					continue;
-				}
-
-				c->set_size_force(get_size() / shrink);
-			}
+			recalc_force_viewport_sizes();
 		} break;
 
 		case NOTIFICATION_ENTER_TREE:

+ 1 - 0
scene/gui/subviewport_container.h

@@ -58,6 +58,7 @@ public:
 	virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
 	void set_stretch_shrink(int p_shrink);
 	int get_stretch_shrink() const;
+	void recalc_force_viewport_sizes();
 
 	virtual Size2 get_minimum_size() const override;
 

+ 16 - 0
scene/main/viewport.cpp

@@ -4263,6 +4263,11 @@ void SubViewport::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			RS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
+
+			SubViewportContainer *parent_svc = Object::cast_to<SubViewportContainer>(get_parent());
+			if (parent_svc) {
+				parent_svc->recalc_force_viewport_sizes();
+			}
 		} break;
 
 		case NOTIFICATION_EXIT_TREE: {
@@ -4305,6 +4310,17 @@ void SubViewport::_bind_methods() {
 	BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
 }
 
+void SubViewport::_validate_property(PropertyInfo &p_property) const {
+	if (p_property.name == "size") {
+		SubViewportContainer *parent_svc = Object::cast_to<SubViewportContainer>(get_parent());
+		if (parent_svc && parent_svc->is_stretch_enabled()) {
+			p_property.usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY;
+		} else {
+			p_property.usage = PROPERTY_USAGE_DEFAULT;
+		}
+	}
+}
+
 SubViewport::SubViewport() {
 	RS::get_singleton()->viewport_set_size(get_viewport_rid(), get_size().width, get_size().height);
 }

+ 1 - 0
scene/main/viewport.h

@@ -784,6 +784,7 @@ public:
 	virtual Transform2D get_screen_transform_internal(bool p_absolute_position = false) const override;
 	virtual Transform2D get_popup_base_transform() const override;
 
+	void _validate_property(PropertyInfo &p_property) const;
 	SubViewport();
 	~SubViewport();
 };