summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/joints_2d.cpp53
-rw-r--r--scene/2d/joints_2d.h3
-rw-r--r--scene/2d/light_occluder_2d.cpp14
-rw-r--r--scene/2d/light_occluder_2d.h5
-rw-r--r--scene/3d/physics_joint_3d.cpp55
-rw-r--r--scene/3d/physics_joint_3d.h3
-rw-r--r--scene/gui/aspect_ratio_container.cpp167
-rw-r--r--scene/gui/aspect_ratio_container.h80
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/main/scene_tree.cpp8
-rw-r--r--scene/main/viewport.cpp42
-rw-r--r--scene/main/viewport.h26
-rw-r--r--scene/register_scene_types.cpp2
-rw-r--r--scene/resources/visual_shader_nodes.cpp15
-rw-r--r--scene/resources/visual_shader_nodes.h1
15 files changed, 458 insertions, 18 deletions
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 0e4b1836da..f5d13fd641 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -47,29 +47,53 @@ void Joint2D::_update_joint(bool p_only_free) {
}
if (p_only_free || !is_inside_tree()) {
+ warning = String();
return;
}
Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)nullptr;
Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)nullptr;
- if (!node_a || !node_b) {
+ PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
+ PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
+
+ if (node_a && !body_a && node_b && !body_b) {
+ warning = TTR("Node A and Node B must be PhysicsBody2Ds");
+ update_configuration_warning();
return;
}
- PhysicsBody2D *body_a = Object::cast_to<PhysicsBody2D>(node_a);
- PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
+ if (node_a && !body_a) {
+ warning = TTR("Node A must be a PhysicsBody2D");
+ update_configuration_warning();
+ return;
+ }
- if (!body_a || !body_b) {
+ if (node_b && !body_b) {
+ warning = TTR("Node B must be a PhysicsBody2D");
+ update_configuration_warning();
return;
}
- joint = _configure_joint(body_a, body_b);
+ if (!body_a || !body_b) {
+ warning = TTR("Joint is not connected to two PhysicsBody2Ds");
+ update_configuration_warning();
+ return;
+ }
- if (!joint.is_valid()) {
+ if (body_a == body_b) {
+ warning = TTR("Node A and Node B must be different PhysicsBody2Ds");
+ update_configuration_warning();
return;
}
+ warning = String();
+ update_configuration_warning();
+
+ joint = _configure_joint(body_a, body_b);
+
+ ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
+
PhysicsServer2D::get_singleton()->get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias);
ba = body_a->get_rid();
@@ -141,6 +165,19 @@ bool Joint2D::get_exclude_nodes_from_collision() const {
return exclude_from_collision;
}
+String Joint2D::get_configuration_warning() const {
+ String node_warning = Node2D::get_configuration_warning();
+
+ if (!warning.empty()) {
+ if (!node_warning.empty()) {
+ node_warning += "\n\n";
+ }
+ node_warning += warning;
+ }
+
+ return node_warning;
+}
+
void Joint2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint2D::set_node_a);
ClassDB::bind_method(D_METHOD("get_node_a"), &Joint2D::get_node_a);
@@ -154,8 +191,8 @@ void Joint2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint2D::set_exclude_nodes_from_collision);
ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint2D::get_exclude_nodes_from_collision);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject2D"), "set_node_a", "get_node_a");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject2D"), "set_node_b", "get_node_b");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody2D"), "set_node_a", "get_node_a");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody2D"), "set_node_b", "get_node_b");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0,0.9,0.001"), "set_bias", "get_bias");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_collision"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision");
}
diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h
index 60534cae65..759e7de8a0 100644
--- a/scene/2d/joints_2d.h
+++ b/scene/2d/joints_2d.h
@@ -46,6 +46,7 @@ class Joint2D : public Node2D {
real_t bias;
bool exclude_from_collision;
+ String warning;
protected:
void _update_joint(bool p_only_free = false);
@@ -56,6 +57,8 @@ protected:
static void _bind_methods();
public:
+ virtual String get_configuration_warning() const override;
+
void set_node_a(const NodePath &p_node_a);
NodePath get_node_a() const;
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index 0531762ed8..6908fbeada 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -265,6 +265,14 @@ String LightOccluder2D::get_configuration_warning() const {
return warning;
}
+void LightOccluder2D::set_as_sdf_collision(bool p_enable) {
+ sdf_collision = p_enable;
+ RS::get_singleton()->canvas_light_occluder_set_as_sdf_collision(occluder, sdf_collision);
+}
+bool LightOccluder2D::is_set_as_sdf_collision() const {
+ return sdf_collision;
+}
+
void LightOccluder2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_occluder_polygon", "polygon"), &LightOccluder2D::set_occluder_polygon);
ClassDB::bind_method(D_METHOD("get_occluder_polygon"), &LightOccluder2D::get_occluder_polygon);
@@ -272,14 +280,20 @@ void LightOccluder2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask);
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask);
+ ClassDB::bind_method(D_METHOD("set_as_sdf_collision", "enable"), &LightOccluder2D::set_as_sdf_collision);
+ ClassDB::bind_method(D_METHOD("is_set_as_sdf_collision"), &LightOccluder2D::is_set_as_sdf_collision);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"), "set_occluder_polygon", "get_occluder_polygon");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdf_collision"), "set_as_sdf_collision", "is_set_as_sdf_collision");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
}
LightOccluder2D::LightOccluder2D() {
occluder = RS::get_singleton()->canvas_light_occluder_create();
mask = 1;
+
set_notify_transform(true);
+ set_as_sdf_collision(true);
}
LightOccluder2D::~LightOccluder2D() {
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
index 694097f985..97574af542 100644
--- a/scene/2d/light_occluder_2d.h
+++ b/scene/2d/light_occluder_2d.h
@@ -84,7 +84,7 @@ class LightOccluder2D : public Node2D {
bool enabled;
int mask;
Ref<OccluderPolygon2D> occluder_polygon;
-
+ bool sdf_collision;
void _poly_changed();
protected:
@@ -103,6 +103,9 @@ public:
void set_occluder_light_mask(int p_mask);
int get_occluder_light_mask() const;
+ void set_as_sdf_collision(bool p_enable);
+ bool is_set_as_sdf_collision() const;
+
String get_configuration_warning() const override;
LightOccluder2D();
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index af4d6ae152..ab9cdb9fd8 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -43,6 +43,7 @@ void Joint3D::_update_joint(bool p_only_free) {
}
if (p_only_free || !is_inside_tree()) {
+ warning = String();
return;
}
@@ -52,20 +53,47 @@ void Joint3D::_update_joint(bool p_only_free) {
PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a);
PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b);
- if (!body_a && body_b) {
- SWAP(body_a, body_b);
+ if (node_a && !body_a && node_b && !body_b) {
+ warning = TTR("Node A and Node B must be PhysicsBody3Ds");
+ update_configuration_warning();
+ return;
}
- if (!body_a) {
+ if (node_a && !body_a) {
+ warning = TTR("Node A must be a PhysicsBody3D");
+ update_configuration_warning();
return;
}
- joint = _configure_joint(body_a, body_b);
+ if (node_b && !body_b) {
+ warning = TTR("Node B must be a PhysicsBody3D");
+ update_configuration_warning();
+ return;
+ }
- if (!joint.is_valid()) {
+ if (!body_a && !body_b) {
+ warning = TTR("Joint is not connected to any PhysicsBody3Ds");
+ update_configuration_warning();
return;
}
+ if (body_a == body_b) {
+ warning = TTR("Node A and Node B must be different PhysicsBody3Ds");
+ update_configuration_warning();
+ return;
+ }
+
+ if (!body_a) {
+ SWAP(body_a, body_b);
+ }
+
+ warning = String();
+ update_configuration_warning();
+
+ joint = _configure_joint(body_a, body_b);
+
+ ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint.");
+
PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority);
ba = body_a->get_rid();
@@ -137,6 +165,19 @@ bool Joint3D::get_exclude_nodes_from_collision() const {
return exclude_from_collision;
}
+String Joint3D::get_configuration_warning() const {
+ String node_warning = Node3D::get_configuration_warning();
+
+ if (!warning.empty()) {
+ if (!node_warning.empty()) {
+ node_warning += "\n\n";
+ }
+ node_warning += warning;
+ }
+
+ return node_warning;
+}
+
void Joint3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint3D::set_node_a);
ClassDB::bind_method(D_METHOD("get_node_a"), &Joint3D::get_node_a);
@@ -150,8 +191,8 @@ void Joint3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint3D::set_exclude_nodes_from_collision);
ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint3D::get_exclude_nodes_from_collision);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "set_node_a", "get_node_a");
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "set_node_b", "get_node_b");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_a", "get_node_a");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_b", "get_node_b");
ADD_PROPERTY(PropertyInfo(Variant::INT, "solver/priority", PROPERTY_HINT_RANGE, "1,8,1"), "set_solver_priority", "get_solver_priority");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision/exclude_nodes"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision");
diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h
index d1a375ca5d..a65f6db3bf 100644
--- a/scene/3d/physics_joint_3d.h
+++ b/scene/3d/physics_joint_3d.h
@@ -46,6 +46,7 @@ class Joint3D : public Node3D {
int solver_priority;
bool exclude_from_collision;
+ String warning;
protected:
void _update_joint(bool p_only_free = false);
@@ -57,6 +58,8 @@ protected:
static void _bind_methods();
public:
+ virtual String get_configuration_warning() const override;
+
void set_node_a(const NodePath &p_node_a);
NodePath get_node_a() const;
diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp
new file mode 100644
index 0000000000..9f60131186
--- /dev/null
+++ b/scene/gui/aspect_ratio_container.cpp
@@ -0,0 +1,167 @@
+/*************************************************************************/
+/* aspect_ratio_container.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "aspect_ratio_container.h"
+
+Size2 AspectRatioContainer::get_minimum_size() const {
+ Size2 ms;
+ for (int i = 0; i < get_child_count(); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i));
+ if (!c) {
+ continue;
+ }
+ if (c->is_set_as_top_level()) {
+ continue;
+ }
+ if (!c->is_visible()) {
+ continue;
+ }
+ Size2 minsize = c->get_combined_minimum_size();
+ ms.width = MAX(ms.width, minsize.width);
+ ms.height = MAX(ms.height, minsize.height);
+ }
+ return ms;
+}
+
+void AspectRatioContainer::set_ratio(float p_ratio) {
+ ratio = p_ratio;
+ queue_sort();
+}
+
+void AspectRatioContainer::set_stretch_mode(StretchMode p_mode) {
+ stretch_mode = p_mode;
+ queue_sort();
+}
+
+void AspectRatioContainer::set_alignment_horizontal(AlignMode p_alignment_horizontal) {
+ alignment_horizontal = p_alignment_horizontal;
+ queue_sort();
+}
+
+void AspectRatioContainer::set_alignment_vertical(AlignMode p_alignment_vertical) {
+ alignment_vertical = p_alignment_vertical;
+ queue_sort();
+}
+
+void AspectRatioContainer::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_SORT_CHILDREN: {
+ Size2 size = get_size();
+ for (int i = 0; i < get_child_count(); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i));
+ if (!c) {
+ continue;
+ }
+ if (c->is_set_as_top_level()) {
+ continue;
+ }
+ Size2 child_minsize = c->get_combined_minimum_size();
+ Size2 child_size = Size2(ratio, 1.0);
+ float scale_factor = 1.0;
+
+ switch (stretch_mode) {
+ case STRETCH_WIDTH_CONTROLS_HEIGHT: {
+ scale_factor = size.x / child_size.x;
+ } break;
+ case STRETCH_HEIGHT_CONTROLS_WIDTH: {
+ scale_factor = size.y / child_size.y;
+ } break;
+ case STRETCH_FIT: {
+ scale_factor = MIN(size.x / child_size.x, size.y / child_size.y);
+ } break;
+ case STRETCH_COVER: {
+ scale_factor = MAX(size.x / child_size.x, size.y / child_size.y);
+ } break;
+ }
+ child_size *= scale_factor;
+ child_size.x = MAX(child_size.x, child_minsize.x);
+ child_size.y = MAX(child_size.y, child_minsize.y);
+
+ float align_x = 0.5;
+ switch (alignment_horizontal) {
+ case ALIGN_BEGIN: {
+ align_x = 0.0;
+ } break;
+ case ALIGN_CENTER: {
+ align_x = 0.5;
+ } break;
+ case ALIGN_END: {
+ align_x = 1.0;
+ } break;
+ }
+ float align_y = 0.5;
+ switch (alignment_vertical) {
+ case ALIGN_BEGIN: {
+ align_y = 0.0;
+ } break;
+ case ALIGN_CENTER: {
+ align_y = 0.5;
+ } break;
+ case ALIGN_END: {
+ align_y = 1.0;
+ } break;
+ }
+ Vector2 offset = (size - child_size) * Vector2(align_x, align_y);
+
+ fit_child_in_rect(c, Rect2(offset, child_size));
+ }
+ } break;
+ }
+}
+
+void AspectRatioContainer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_ratio", "ratio"), &AspectRatioContainer::set_ratio);
+ ClassDB::bind_method(D_METHOD("get_ratio"), &AspectRatioContainer::get_ratio);
+
+ ClassDB::bind_method(D_METHOD("set_stretch_mode", "stretch_mode"), &AspectRatioContainer::set_stretch_mode);
+ ClassDB::bind_method(D_METHOD("get_stretch_mode"), &AspectRatioContainer::get_stretch_mode);
+
+ ClassDB::bind_method(D_METHOD("set_alignment_horizontal", "alignment_horizontal"), &AspectRatioContainer::set_alignment_horizontal);
+ ClassDB::bind_method(D_METHOD("get_alignment_horizontal"), &AspectRatioContainer::get_alignment_horizontal);
+
+ ClassDB::bind_method(D_METHOD("set_alignment_vertical", "alignment_vertical"), &AspectRatioContainer::set_alignment_vertical);
+ ClassDB::bind_method(D_METHOD("get_alignment_vertical"), &AspectRatioContainer::get_alignment_vertical);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio"), "set_ratio", "get_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width controls height,Height controls width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");
+
+ ADD_GROUP("Alignment", "alignment_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment_horizontal", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment_horizontal", "get_alignment_horizontal");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment_vertical", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment_vertical", "get_alignment_vertical");
+
+ BIND_ENUM_CONSTANT(STRETCH_WIDTH_CONTROLS_HEIGHT);
+ BIND_ENUM_CONSTANT(STRETCH_HEIGHT_CONTROLS_WIDTH);
+ BIND_ENUM_CONSTANT(STRETCH_FIT);
+ BIND_ENUM_CONSTANT(STRETCH_COVER);
+
+ BIND_ENUM_CONSTANT(ALIGN_BEGIN);
+ BIND_ENUM_CONSTANT(ALIGN_CENTER);
+ BIND_ENUM_CONSTANT(ALIGN_END);
+}
diff --git a/scene/gui/aspect_ratio_container.h b/scene/gui/aspect_ratio_container.h
new file mode 100644
index 0000000000..8ffc4363c3
--- /dev/null
+++ b/scene/gui/aspect_ratio_container.h
@@ -0,0 +1,80 @@
+/*************************************************************************/
+/* aspect_ratio_container.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef ASPECT_RATIO_CONTAINER_H
+#define ASPECT_RATIO_CONTAINER_H
+
+#include "scene/gui/container.h"
+
+class AspectRatioContainer : public Container {
+ GDCLASS(AspectRatioContainer, Container);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+ virtual Size2 get_minimum_size() const override;
+
+public:
+ enum StretchMode {
+ STRETCH_WIDTH_CONTROLS_HEIGHT,
+ STRETCH_HEIGHT_CONTROLS_WIDTH,
+ STRETCH_FIT,
+ STRETCH_COVER,
+ };
+ enum AlignMode {
+ ALIGN_BEGIN,
+ ALIGN_CENTER,
+ ALIGN_END,
+ };
+
+private:
+ float ratio = 1.0;
+ StretchMode stretch_mode = STRETCH_FIT;
+ AlignMode alignment_horizontal = ALIGN_CENTER;
+ AlignMode alignment_vertical = ALIGN_CENTER;
+
+public:
+ void set_ratio(float p_ratio);
+ float get_ratio() const { return ratio; }
+
+ void set_stretch_mode(StretchMode p_mode);
+ StretchMode get_stretch_mode() const { return stretch_mode; }
+
+ void set_alignment_horizontal(AlignMode p_alignment_horizontal);
+ AlignMode get_alignment_horizontal() const { return alignment_horizontal; }
+
+ void set_alignment_vertical(AlignMode p_alignment_vertical);
+ AlignMode get_alignment_vertical() const { return alignment_vertical; }
+};
+
+VARIANT_ENUM_CAST(AspectRatioContainer::StretchMode);
+VARIANT_ENUM_CAST(AspectRatioContainer::AlignMode);
+
+#endif // ASPECT_RATIO_CONTAINER_H
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 85b3227884..e4fe0bb25d 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -157,8 +157,6 @@ private:
Vector2 scale;
Vector2 pivot_offset;
- bool pending_resize;
-
int h_size_flags;
int v_size_flags;
float expand;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index cc5f4e9598..304e8b9c6d 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1397,6 +1397,14 @@ SceneTree::SceneTree() {
bool snap_2d_vertices = GLOBAL_DEF("rendering/quality/2d/snap_2d_vertices_to_pixel", false);
root->set_snap_2d_vertices_to_pixel(snap_2d_vertices);
+ Viewport::SDFOversize sdf_oversize = Viewport::SDFOversize(int(GLOBAL_DEF("rendering/quality/2d_sdf/oversize", 1)));
+ root->set_sdf_oversize(sdf_oversize);
+ Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_DEF("rendering/quality/2d_sdf/scale", 1)));
+ root->set_sdf_scale(sdf_scale);
+
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d_sdf/oversize", PropertyInfo(Variant::INT, "rendering/quality/2d_sdf/oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/2d_sdf/scale", PropertyInfo(Variant::INT, "rendering/quality/2d_sdf/scale", PROPERTY_HINT_ENUM, "100%,50%,25%"));
+
{ //load default fallback environment
//get possible extensions
List<String> exts;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index f4498507f1..5be5c1b266 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3383,6 +3383,24 @@ void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) {
}
}
+void Viewport::set_sdf_oversize(SDFOversize p_sdf_oversize) {
+ ERR_FAIL_INDEX(p_sdf_oversize, SDF_OVERSIZE_MAX);
+ sdf_oversize = p_sdf_oversize;
+ RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
+}
+Viewport::SDFOversize Viewport::get_sdf_oversize() const {
+ return sdf_oversize;
+}
+
+void Viewport::set_sdf_scale(SDFScale p_sdf_scale) {
+ ERR_FAIL_INDEX(p_sdf_scale, SDF_SCALE_MAX);
+ sdf_scale = p_sdf_scale;
+ RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
+}
+Viewport::SDFScale Viewport::get_sdf_scale() const {
+ return sdf_scale;
+}
+
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
@@ -3482,6 +3500,12 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat);
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat);
+ ClassDB::bind_method(D_METHOD("set_sdf_oversize", "oversize"), &Viewport::set_sdf_oversize);
+ ClassDB::bind_method(D_METHOD("get_sdf_oversize"), &Viewport::get_sdf_oversize);
+
+ ClassDB::bind_method(D_METHOD("set_sdf_scale", "scale"), &Viewport::set_sdf_scale);
+ ClassDB::bind_method(D_METHOD("get_sdf_scale"), &Viewport::get_sdf_scale);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
@@ -3506,6 +3530,9 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint");
+ ADD_GROUP("SDF", "sdf_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");
ADD_GROUP("Shadow Atlas", "shadow_atlas_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
@@ -3575,6 +3602,17 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX);
+
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_100_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_120_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_150_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_200_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_OVERSIZE_MAX);
+
+ BIND_ENUM_CONSTANT(SDF_SCALE_100_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_SCALE_50_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_SCALE_25_PERCENT);
+ BIND_ENUM_CONSTANT(SDF_SCALE_MAX);
}
Viewport::Viewport() {
@@ -3661,6 +3699,10 @@ Viewport::Viewport() {
default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
+
+ sdf_oversize = SDF_OVERSIZE_120_PERCENT;
+ sdf_scale = SDF_SCALE_50_PERCENT;
+ set_sdf_oversize(SDF_OVERSIZE_120_PERCENT); //set to server
}
Viewport::~Viewport() {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 4be66ae79f..7ce202d27c 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -159,6 +159,21 @@ public:
DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX,
};
+ enum SDFOversize {
+ SDF_OVERSIZE_100_PERCENT,
+ SDF_OVERSIZE_120_PERCENT,
+ SDF_OVERSIZE_150_PERCENT,
+ SDF_OVERSIZE_200_PERCENT,
+ SDF_OVERSIZE_MAX
+ };
+
+ enum SDFScale {
+ SDF_SCALE_100_PERCENT,
+ SDF_SCALE_50_PERCENT,
+ SDF_SCALE_25_PERCENT,
+ SDF_SCALE_MAX
+ };
+
enum {
SUBWINDOW_CANVAS_LAYER = 1024
};
@@ -285,6 +300,9 @@ private:
Ref<ViewportTexture> default_texture;
Set<ViewportTexture *> viewport_textures;
+ SDFOversize sdf_oversize;
+ SDFScale sdf_scale;
+
enum SubWindowDrag {
SUB_WINDOW_DRAG_DISABLED,
SUB_WINDOW_DRAG_MOVE,
@@ -572,6 +590,12 @@ public:
bool gui_is_dragging() const;
+ void set_sdf_oversize(SDFOversize p_sdf_oversize);
+ SDFOversize get_sdf_oversize() const;
+
+ void set_sdf_scale(SDFScale p_sdf_scale);
+ SDFScale get_sdf_scale() const;
+
void set_default_canvas_item_texture_filter(DefaultCanvasItemTextureFilter p_filter);
DefaultCanvasItemTextureFilter get_default_canvas_item_texture_filter() const;
@@ -650,6 +674,8 @@ VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
VARIANT_ENUM_CAST(Viewport::MSAA);
VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA);
VARIANT_ENUM_CAST(Viewport::DebugDraw);
+VARIANT_ENUM_CAST(Viewport::SDFScale);
+VARIANT_ENUM_CAST(Viewport::SDFOversize);
VARIANT_ENUM_CAST(SubViewport::ClearMode);
VARIANT_ENUM_CAST(Viewport::RenderInfo);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 7997dc12e1..3ca4e6db3a 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -77,6 +77,7 @@
#include "scene/animation/tween.h"
#include "scene/audio/audio_stream_player.h"
#include "scene/debugger/scene_debugger.h"
+#include "scene/gui/aspect_ratio_container.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/center_container.h"
@@ -324,6 +325,7 @@ void register_scene_types() {
ClassDB::register_class<ColorRect>();
ClassDB::register_class<NinePatchRect>();
ClassDB::register_class<ReferenceRect>();
+ ClassDB::register_class<AspectRatioContainer>();
ClassDB::register_class<TabContainer>();
ClassDB::register_class<Tabs>();
ClassDB::register_virtual_class<Separator>();
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 704d1b2ea8..a3358ea8c7 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -724,6 +724,10 @@ Vector<StringName> VisualShaderNodeTexture::get_editable_properties() const {
}
String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+ if (is_input_port_connected(2) && source != SOURCE_PORT) {
+ return TTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
+ }
+
if (source == SOURCE_TEXTURE) {
return String(); // all good
}
@@ -980,6 +984,10 @@ void VisualShaderNodeSample3D::_bind_methods() {
}
String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+ if (is_input_port_connected(2) && source != SOURCE_PORT) {
+ return TTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
+ }
+
if (source == SOURCE_TEXTURE) {
return String(); // all good
}
@@ -1276,6 +1284,13 @@ Vector<StringName> VisualShaderNodeCubemap::get_editable_properties() const {
return props;
}
+String VisualShaderNodeCubemap::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+ if (is_input_port_connected(2) && source != SOURCE_PORT) {
+ return TTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
+ }
+ return String();
+}
+
void VisualShaderNodeCubemap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeCubemap::set_source);
ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeCubemap::get_source);
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index d4d6540baf..4b39c76388 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -448,6 +448,7 @@ public:
TextureType get_texture_type() const;
virtual Vector<StringName> get_editable_properties() const override;
+ virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
VisualShaderNodeCubemap();
};