summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/area_2d.cpp8
-rw-r--r--scene/2d/collision_polygon_2d.cpp4
-rw-r--r--scene/2d/collision_shape_2d.cpp4
-rw-r--r--scene/2d/navigation_region_2d.cpp16
-rw-r--r--scene/3d/area_3d.cpp8
-rw-r--r--scene/3d/collision_shape_3d.cpp4
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp4
-rw-r--r--scene/3d/light_3d.cpp6
-rw-r--r--scene/3d/node_3d.cpp4
-rw-r--r--scene/3d/physics_body_3d.cpp8
-rw-r--r--scene/3d/physics_joint_3d.cpp16
-rw-r--r--scene/3d/ray_cast_3d.cpp37
-rw-r--r--scene/gui/graph_edit.cpp19
-rw-r--r--scene/gui/item_list.cpp8
-rw-r--r--scene/gui/item_list.h4
-rw-r--r--scene/gui/rich_text_label.cpp77
-rw-r--r--scene/gui/rich_text_label.h7
-rw-r--r--scene/gui/tab_container.cpp4
-rw-r--r--scene/gui/text_edit.cpp63
-rw-r--r--scene/main/node.cpp18
-rw-r--r--scene/main/node.h5
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/main/viewport.h4
-rw-r--r--scene/register_scene_types.cpp8
-rw-r--r--scene/resources/default_theme/default_theme.cpp14
-rwxr-xr-xscene/resources/default_theme/xpmfix.sh2
-rw-r--r--scene/resources/particles_material.cpp2
-rw-r--r--scene/resources/style_box.cpp4
-rw-r--r--scene/resources/style_box.h2
-rw-r--r--scene/resources/surface_tool.cpp2
-rw-r--r--scene/resources/surface_tool.h4
-rw-r--r--scene/resources/texture.cpp9
-rw-r--r--scene/resources/texture.h2
-rw-r--r--scene/resources/visual_shader.cpp18
-rw-r--r--scene/resources/visual_shader.h1
-rw-r--r--scene/resources/visual_shader_nodes.cpp5
-rw-r--r--scene/resources/visual_shader_nodes.h43
-rw-r--r--scene/resources/visual_shader_sdf_nodes.cpp283
-rw-r--r--scene/resources/visual_shader_sdf_nodes.h132
39 files changed, 721 insertions, 142 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index a4e15008a0..fae893a76c 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -590,13 +590,13 @@ void Area2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout);
ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape")));
- ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D")));
ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D")));
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 7347b7829a..851e40cda6 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -36,7 +36,7 @@
#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"
-#include "thirdparty/misc/triangulator.h"
+#include "thirdparty/misc/polypartition.h"
void CollisionPolygon2D::_build_polygon() {
parent->shape_owner_clear_shapes(owner_id);
@@ -194,6 +194,7 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2> &p_polygon) {
if (parent) {
_build_polygon();
+ _update_in_shape_owner();
}
update();
update_configuration_warning();
@@ -208,6 +209,7 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) {
build_mode = p_mode;
if (parent) {
_build_polygon();
+ _update_in_shape_owner();
}
}
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index acdde96df0..37bed577ac 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -141,6 +141,9 @@ void CollisionShape2D::_notification(int p_what) {
}
void CollisionShape2D::set_shape(const Ref<Shape2D> &p_shape) {
+ if (p_shape == shape) {
+ return;
+ }
if (shape.is_valid()) {
shape->disconnect("changed", callable_mp(this, &CollisionShape2D::_shape_changed));
}
@@ -151,6 +154,7 @@ void CollisionShape2D::set_shape(const Ref<Shape2D> &p_shape) {
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
}
+ _update_in_shape_owner();
}
if (shape.is_valid()) {
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 72dc8bd9ad..7360fce330 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -37,7 +37,7 @@
#include "navigation_2d.h"
#include "servers/navigation_server_2d.h"
-#include "thirdparty/misc/triangulator.h"
+#include "thirdparty/misc/polypartition.h"
#ifdef TOOLS_ENABLED
Rect2 NavigationPolygon::_edit_get_rect() const {
@@ -228,7 +228,7 @@ void NavigationPolygon::make_polygons_from_outlines() {
MutexLock lock(navmesh_generation);
navmesh.unref();
}
- List<TriangulatorPoly> in_poly, out_poly;
+ List<TPPLPoly> in_poly, out_poly;
Vector2 outside_point(-1e10, -1e10);
@@ -278,23 +278,23 @@ void NavigationPolygon::make_polygons_from_outlines() {
bool outer = (interscount % 2) == 0;
- TriangulatorPoly tp;
+ TPPLPoly tp;
tp.Init(olsize);
for (int j = 0; j < olsize; j++) {
tp[j] = r[j];
}
if (outer) {
- tp.SetOrientation(TRIANGULATOR_CCW);
+ tp.SetOrientation(TPPL_ORIENTATION_CCW);
} else {
- tp.SetOrientation(TRIANGULATOR_CW);
+ tp.SetOrientation(TPPL_ORIENTATION_CW);
tp.SetHole(true);
}
in_poly.push_back(tp);
}
- TriangulatorPartition tpart;
+ TPPLPartition tpart;
if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
ERR_PRINT("NavigationPolygon: Convex partition failed!");
return;
@@ -304,8 +304,8 @@ void NavigationPolygon::make_polygons_from_outlines() {
vertices.resize(0);
Map<Vector2, int> points;
- for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) {
- TriangulatorPoly &tp = I->get();
+ for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
+ TPPLPoly &tp = I->get();
struct Polygon p;
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index b69357387e..36312482cd 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -640,13 +640,13 @@ void Area3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity);
ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity);
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "area_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape")));
- ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "self_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape")));
ADD_SIGNAL(MethodInfo("area_entered", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D")));
ADD_SIGNAL(MethodInfo("area_exited", PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D")));
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index 47966c772b..503d1be104 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -93,7 +93,6 @@ void CollisionShape3D::_notification(int p_what) {
if (shape.is_valid()) {
parent->shape_owner_add_shape(owner_id, shape);
}
- _update_in_shape_owner();
}
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -170,6 +169,9 @@ void CollisionShape3D::_bind_methods() {
}
void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
+ if (p_shape == shape) {
+ return;
+ }
if (!shape.is_null()) {
shape->unregister_owner(this);
shape->disconnect("changed", callable_mp(this, &CollisionShape3D::_shape_changed));
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index 145b5afbd0..97241be60f 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -293,11 +293,11 @@ void GPUParticlesCollisionSDF::_find_closest_distance(const Vector3 &p_pos, cons
SGN(cb.cross(nor).dot(pb)) +
SGN(ac.cross(nor).dot(pc)) <
2.0) ?
- MIN(MIN(
+ MIN(MIN(
Vector3_dot2(ba * CLAMP(ba.dot(pa) / Vector3_dot2(ba), 0.0, 1.0) - pa),
Vector3_dot2(cb * CLAMP(cb.dot(pb) / Vector3_dot2(cb), 0.0, 1.0) - pb)),
Vector3_dot2(ac * CLAMP(ac.dot(pc) / Vector3_dot2(ac), 0.0, 1.0) - pc)) :
- nor.dot(pa) * nor.dot(pa) / Vector3_dot2(nor));
+ nor.dot(pa) * nor.dot(pa) / Vector3_dot2(nor));
closest_distance = MIN(closest_distance, inside_d);
}
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index b9293b364d..b998a1a400 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -212,6 +212,10 @@ void Light3D::_validate_property(PropertyInfo &property) const {
property.usage = 0;
}
+ if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_specular") {
+ property.usage = 0;
+ }
+
if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_projector") {
property.usage = 0;
}
@@ -257,7 +261,7 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_ENERGY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_projector", "get_projector");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,64,0.01,or_greater"), "set_param", "get_param", PARAM_SIZE);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 503dd5735b..2a49e60669 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -239,8 +239,8 @@ void Node3D::set_transform(const Transform &p_transform) {
void Node3D::set_global_transform(const Transform &p_transform) {
Transform xform =
(data.parent && !data.top_level_active) ?
- data.parent->get_global_transform().affine_inverse() * p_transform :
- p_transform;
+ data.parent->get_global_transform().affine_inverse() * p_transform :
+ p_transform;
set_transform(xform);
}
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 5645923f22..4d712069ec 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1716,6 +1716,10 @@ bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Varia
String path = p_name;
+ if (!path.begins_with("joint_constraints/")) {
+ return false;
+ }
+
Vector3::Axis axis;
{
const String axis_s = path.get_slicec('/', 1);
@@ -1872,6 +1876,10 @@ bool PhysicalBone3D::SixDOFJointData::_get(const StringName &p_name, Variant &r_
String path = p_name;
+ if (!path.begins_with("joint_constraints/")) {
+ return false;
+ }
+
int axis;
{
const String axis_s = path.get_slicec('/', 1);
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index 0a2af6b0cd..326b91b6ed 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -114,21 +114,23 @@ void Joint3D::_update_joint(bool p_only_free) {
return;
}
- if (!body_a) {
- SWAP(body_a, body_b);
- }
-
warning = String();
update_configuration_warning();
- joint = _configure_joint(body_a, body_b);
+ if (body_a) {
+ joint = _configure_joint(body_a, body_b);
+ } else if (body_b) {
+ joint = _configure_joint(body_b, nullptr);
+ }
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();
- body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree), make_binds(body_a->get_instance_id()));
+ if (body_a) {
+ ba = body_a->get_rid();
+ body_a->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Joint3D::_body_exit_tree), make_binds(body_a->get_instance_id()));
+ }
if (body_b) {
bb = body_b->get_rid();
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index 59b59c7163..0b7c15a023 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -148,14 +148,14 @@ void RayCast3D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled && !Engine::get_singleton()->is_editor_hint()) {
set_physics_process_internal(true);
-
- if (get_tree()->is_debugging_collisions_hint()) {
- _update_debug_shape();
- }
} else {
set_physics_process_internal(false);
}
+ if (get_tree()->is_debugging_collisions_hint()) {
+ _update_debug_shape();
+ }
+
if (Object::cast_to<CollisionObject3D>(get_parent())) {
if (exclude_parent_body) {
exclude.insert(Object::cast_to<CollisionObject3D>(get_parent())->get_rid());
@@ -348,23 +348,32 @@ void RayCast3D::_update_debug_shape() {
}
MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
- if (!mi->get_mesh().is_valid()) {
+ Ref<ArrayMesh> mesh = mi->get_mesh();
+ if (!mesh.is_valid()) {
return;
}
- Ref<ArrayMesh> mesh = mi->get_mesh();
- mesh->clear_surfaces();
-
- Array a;
- a.resize(Mesh::ARRAY_MAX);
-
Vector<Vector3> verts;
verts.push_back(Vector3());
verts.push_back(target_position);
- a[Mesh::ARRAY_VERTEX] = verts;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a);
- mesh->surface_set_material(0, debug_material);
+ if (mesh->get_surface_count() == 0) {
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX] = verts;
+
+ uint32_t flags = Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
+
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a, Array(), Dictionary(), flags);
+ mesh->surface_set_material(0, debug_material);
+ } else {
+ Vector<uint8_t> byte_array;
+ int array_size = sizeof(Vector3) * verts.size();
+ byte_array.resize(array_size);
+ copymem(byte_array.ptrw(), verts.ptr(), array_size);
+
+ RS::get_singleton()->mesh_surface_update_region(mesh->get_rid(), 0, 0, byte_array);
+ }
}
void RayCast3D::_clear_debug_shape() {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index d5b12b6bb6..6662992d46 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -401,7 +401,14 @@ void GraphEdit::add_child_notify(Node *p_child) {
void GraphEdit::remove_child_notify(Node *p_child) {
Control::remove_child_notify(p_child);
- if (is_inside_tree()) {
+ if (p_child == top_layer) {
+ top_layer = nullptr;
+ minimap = nullptr;
+ } else if (p_child == connections_layer) {
+ connections_layer = nullptr;
+ }
+
+ if (top_layer != nullptr && is_inside_tree()) {
top_layer->call_deferred("raise"); // Top layer always on top!
}
@@ -409,8 +416,14 @@ void GraphEdit::remove_child_notify(Node *p_child) {
if (gn) {
gn->disconnect("position_offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved));
gn->disconnect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised));
- gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update));
- gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update));
+
+ // In case of the whole GraphEdit being destroyed these references can already be freed.
+ if (connections_layer != nullptr && connections_layer->is_inside_tree()) {
+ gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update));
+ }
+ if (minimap != nullptr && minimap->is_inside_tree()) {
+ gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)minimap, &GraphEditMinimap::update));
+ }
}
}
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 69ca96b28e..03ce6bdd3d 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -50,7 +50,7 @@ void ItemList::_shape(int p_idx) {
}
}
-void ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bool p_selectable) {
+int ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bool p_selectable) {
Item item;
item.icon = p_texture;
item.icon_transposed = false;
@@ -64,14 +64,16 @@ void ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, b
item.tooltip_enabled = true;
item.custom_bg = Color(0, 0, 0, 0);
items.push_back(item);
+ int item_id = items.size() - 1;
_shape(items.size() - 1);
update();
shape_changed = true;
+ return item_id;
}
-void ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
+int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
Item item;
item.icon = p_item;
item.icon_transposed = false;
@@ -85,9 +87,11 @@ void ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
item.tooltip_enabled = true;
item.custom_bg = Color(0, 0, 0, 0);
items.push_back(item);
+ int item_id = items.size() - 1;
update();
shape_changed = true;
+ return item_id;
}
void ItemList::set_item_text(int p_idx, const String &p_text) {
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index d08823c398..4982a68071 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -130,8 +130,8 @@ protected:
static void _bind_methods();
public:
- void add_item(const String &p_item, const Ref<Texture2D> &p_texture = Ref<Texture2D>(), bool p_selectable = true);
- void add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable = true);
+ int add_item(const String &p_item, const Ref<Texture2D> &p_texture = Ref<Texture2D>(), bool p_selectable = true);
+ int add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable = true);
void set_item_text(int p_idx, const String &p_text);
String get_item_text(int p_idx) const;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index a1aa72b29a..e934772371 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -618,11 +618,11 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
}
}
-void RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &p_shadow_ofs) {
+int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &p_shadow_ofs) {
Vector2 off;
- ERR_FAIL_COND(p_frame == nullptr);
- ERR_FAIL_COND(p_line < 0 || p_line >= p_frame->lines.size());
+ ERR_FAIL_COND_V(p_frame == nullptr, 0);
+ ERR_FAIL_COND_V(p_line < 0 || p_line >= p_frame->lines.size(), 0);
Line &l = p_frame->lines.write[p_line];
@@ -631,7 +631,7 @@ void RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_
Variant meta;
if (it_from == nullptr) {
- return;
+ return 0;
}
RID ci = get_canvas_item();
@@ -699,14 +699,24 @@ void RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_
}
l.text_buf->draw_dropcap(ci, p_ofs + ((rtl) ? Vector2() : Vector2(l.offset.x, 0)), l.dc_color);
+ int line_count = 0;
+ Size2 ctrl_size = get_size();
// Draw text.
for (int line = 0; line < l.text_buf->get_line_count(); line++) {
RID rid = l.text_buf->get_line_rid(line);
+ if (p_ofs.y + off.y >= ctrl_size.height) {
+ break;
+ }
+ if (p_ofs.y + off.y + TS->shaped_text_get_size(rid).y <= 0) {
+ off.y += TS->shaped_text_get_size(rid).y;
+ continue;
+ }
float width = l.text_buf->get_width();
float length = TS->shaped_text_get_width(rid);
// Draw line.
+ line_count++;
if (rtl) {
off.x = p_width - l.offset.x - width;
@@ -1068,6 +1078,8 @@ void RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_
}
off.y += TS->shaped_text_get_descent(rid);
}
+
+ return line_count;
}
void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, ItemFrame **r_click_frame, int *r_click_line, Item **r_click_item, int *r_click_char, bool *r_outside) {
@@ -1392,13 +1404,14 @@ void RichTextLabel::_notification(int p_what) {
bool use_outline = get_theme_constant("shadow_as_outline");
Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
+ visible_paragraph_count = 0;
visible_line_count = 0;
// New cache draw.
Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs);
while (ofs.y < size.height && from_line < main->lines.size()) {
- visible_line_count++;
- _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_color_shadow, use_outline, shadow_ofs);
+ visible_paragraph_count++;
+ visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_color_shadow, use_outline, shadow_ofs);
ofs.y += main->lines[from_line].text_buf->get_size().y;
from_line++;
}
@@ -3367,14 +3380,46 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
return OK;
}
+void RichTextLabel::scroll_to_paragraph(int p_paragraph) {
+ ERR_FAIL_INDEX(p_paragraph, main->lines.size());
+ _validate_line_caches(main);
+ vscroll->set_value(main->lines[p_paragraph].offset.y);
+}
+
+int RichTextLabel::get_paragraph_count() const {
+ return current_frame->lines.size();
+}
+
+int RichTextLabel::get_visible_paragraph_count() const {
+ if (!is_visible()) {
+ return 0;
+ }
+ return visible_paragraph_count;
+}
+
void RichTextLabel::scroll_to_line(int p_line) {
- ERR_FAIL_INDEX(p_line, main->lines.size());
_validate_line_caches(main);
- vscroll->set_value(main->lines[p_line].offset.y);
+
+ int line_count = 0;
+ for (int i = 0; i < main->lines.size(); i++) {
+ if ((line_count <= p_line) && (line_count + main->lines[i].text_buf->get_line_count() >= p_line)) {
+ float line_offset = 0.f;
+ for (int j = 0; j < p_line - line_count; j++) {
+ line_offset += main->lines[i].text_buf->get_line_size(j).y;
+ }
+ vscroll->set_value(main->lines[i].offset.y + line_offset);
+ return;
+ }
+ line_count += main->lines[i].text_buf->get_line_count();
+ }
}
int RichTextLabel::get_line_count() const {
- return current_frame->lines.size();
+ int line_count = 0;
+ for (int i = 0; i < main->lines.size(); i++) {
+ line_count += main->lines[i].text_buf->get_line_count();
+ }
+ return line_count;
}
int RichTextLabel::get_visible_line_count() const {
@@ -3677,6 +3722,7 @@ void RichTextLabel::set_percent_visible(float p_percent) {
}
main->first_invalid_line = 0; //invalidate ALL
_validate_line_caches(main);
+ _change_notify("visible_characters");
update();
}
}
@@ -3782,6 +3828,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_v_scroll"), &RichTextLabel::get_v_scroll);
ClassDB::bind_method(D_METHOD("scroll_to_line", "line"), &RichTextLabel::scroll_to_line);
+ ClassDB::bind_method(D_METHOD("scroll_to_paragraph", "paragraph"), &RichTextLabel::scroll_to_paragraph);
ClassDB::bind_method(D_METHOD("set_tab_size", "spaces"), &RichTextLabel::set_tab_size);
ClassDB::bind_method(D_METHOD("get_tab_size"), &RichTextLabel::get_tab_size);
@@ -3812,6 +3859,9 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line_count"), &RichTextLabel::get_line_count);
ClassDB::bind_method(D_METHOD("get_visible_line_count"), &RichTextLabel::get_visible_line_count);
+ ClassDB::bind_method(D_METHOD("get_paragraph_count"), &RichTextLabel::get_paragraph_count);
+ ClassDB::bind_method(D_METHOD("get_visible_paragraph_count"), &RichTextLabel::get_visible_paragraph_count);
+
ClassDB::bind_method(D_METHOD("get_content_height"), &RichTextLabel::get_content_height);
ClassDB::bind_method(D_METHOD("parse_expressions_for_values", "expressions"), &RichTextLabel::parse_expressions_for_values);
@@ -3890,6 +3940,15 @@ void RichTextLabel::_bind_methods() {
void RichTextLabel::set_visible_characters(int p_visible) {
visible_characters = p_visible;
+ if (p_visible == -1) {
+ percent_visible = 1;
+ } else {
+ int total_char_count = get_total_character_count();
+ if (total_char_count > 0) {
+ percent_visible = (float)p_visible / (float)total_char_count;
+ }
+ }
+ _change_notify("percent_visible");
update();
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index a65cc5a451..ee37efb68b 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -337,6 +337,7 @@ private:
bool updating_scroll;
int current_idx = 1;
int current_char_ofs = 0;
+ int visible_paragraph_count;
int visible_line_count;
int tab_size;
@@ -393,7 +394,7 @@ private:
void _shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, int *r_char_offset);
void _resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width);
- void _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &shadow_ofs);
+ int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &shadow_ofs);
float _find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr);
String _roman(int p_num, bool p_capitalize) const;
@@ -507,6 +508,10 @@ public:
bool search(const String &p_string, bool p_from_selection = false, bool p_search_previous = false);
+ void scroll_to_paragraph(int p_paragraph);
+ int get_paragraph_count() const;
+ int get_visible_paragraph_count() const;
+
void scroll_to_line(int p_line);
int get_line_count() const;
int get_visible_line_count() const;
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 7f0d7b6e7b..64a2a1843d 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -789,6 +789,10 @@ Control *TabContainer::get_current_tab_control() const {
void TabContainer::remove_child_notify(Node *p_child) {
Container::remove_child_notify(p_child);
+ if (!Object::cast_to<Control>(p_child)) {
+ return;
+ }
+
call_deferred("_update_current_tab");
p_child->disconnect("renamed", callable_mp(this, &TabContainer::_child_renamed_callback));
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7557d36298..f25eb45b85 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1263,33 +1263,38 @@ void TextEdit::_notification(int p_what) {
}
}
- if (brace_matching_enabled) {
- if ((brace_open_match_line == line && brace_open_match_column == glyphs[j].start) ||
- (cursor.column == glyphs[j].start && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_open_matching || brace_open_mismatch))) {
- if (brace_open_mismatch) {
- current_color = cache.brace_mismatch_color;
+ int char_pos = char_ofs + char_margin + ofs_x;
+ if (char_pos >= xmargin_beg) {
+ if (brace_matching_enabled) {
+ if ((brace_open_match_line == line && brace_open_match_column == glyphs[j].start) ||
+ (cursor.column == glyphs[j].start && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_open_matching || brace_open_mismatch))) {
+ if (brace_open_mismatch) {
+ current_color = cache.brace_mismatch_color;
+ }
+ Rect2 rect = Rect2(char_pos, ofs_y + cache.font->get_underline_position(cache.font_size), glyphs[j].advance * glyphs[j].repeat, cache.font->get_underline_thickness(cache.font_size));
+ draw_rect(rect, current_color);
}
- Rect2 rect = Rect2(char_ofs + char_margin + ofs_x, ofs_y + cache.font->get_underline_position(cache.font_size), glyphs[j].advance * glyphs[j].repeat, cache.font->get_underline_thickness(cache.font_size));
- draw_rect(rect, current_color);
- }
- if ((brace_close_match_line == line && brace_close_match_column == glyphs[j].start) ||
- (cursor.column == glyphs[j].start + 1 && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_close_matching || brace_close_mismatch))) {
- if (brace_close_mismatch) {
- current_color = cache.brace_mismatch_color;
+ if ((brace_close_match_line == line && brace_close_match_column == glyphs[j].start) ||
+ (cursor.column == glyphs[j].start + 1 && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_close_matching || brace_close_mismatch))) {
+ if (brace_close_mismatch) {
+ current_color = cache.brace_mismatch_color;
+ }
+ Rect2 rect = Rect2(char_pos, ofs_y + cache.font->get_underline_position(cache.font_size), glyphs[j].advance * glyphs[j].repeat, cache.font->get_underline_thickness(cache.font_size));
+ draw_rect(rect, current_color);
}
- Rect2 rect = Rect2(char_ofs + char_margin + ofs_x, ofs_y + cache.font->get_underline_position(cache.font_size), glyphs[j].advance * glyphs[j].repeat, cache.font->get_underline_thickness(cache.font_size));
- draw_rect(rect, current_color);
+ }
+
+ if (draw_tabs && ((glyphs[j].flags & TextServer::GRAPHEME_IS_TAB) == TextServer::GRAPHEME_IS_TAB)) {
+ int yofs = (text_height - cache.tab_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
+ cache.tab_icon->draw(ci, Point2(char_pos, ofs_y + yofs), current_color);
+ } else if (draw_spaces && ((glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE)) {
+ int yofs = (text_height - cache.space_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
+ int xofs = (glyphs[j].advance * glyphs[j].repeat - cache.space_icon->get_width()) / 2;
+ cache.space_icon->draw(ci, Point2(char_pos + xofs, ofs_y + yofs), current_color);
}
}
- if (draw_tabs && ((glyphs[j].flags & TextServer::GRAPHEME_IS_TAB) == TextServer::GRAPHEME_IS_TAB)) {
- int yofs = (text_height - cache.tab_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
- cache.tab_icon->draw(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + yofs), current_color);
- } else if (draw_spaces && ((glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE)) {
- int yofs = (text_height - cache.space_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
- int xofs = (glyphs[j].advance * glyphs[j].repeat - cache.space_icon->get_width()) / 2;
- cache.space_icon->draw(ci, Point2(char_ofs + char_margin + ofs_x + xofs, ofs_y + yofs), current_color);
- }
+
for (int k = 0; k < glyphs[j].repeat; k++) {
if ((char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) {
if (glyphs[j].font_rid != RID()) {
@@ -1306,11 +1311,13 @@ void TextEdit::_notification(int p_what) {
}
if (line_wrap_index == line_wrap_amount && is_folded(line)) {
- int yofs = (text_height - cache.folded_eol_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
- int xofs = cache.folded_eol_icon->get_width() / 2;
- Color eol_color = cache.code_folding_color;
- eol_color.a = 1;
- cache.folded_eol_icon->draw(ci, Point2(char_ofs + char_margin + xofs + ofs_x, ofs_y + yofs), eol_color);
+ int xofs = char_ofs + char_margin + ofs_x + (cache.folded_eol_icon->get_width() / 2);
+ if (xofs >= xmargin_beg && xofs < xmargin_end) {
+ int yofs = (text_height - cache.folded_eol_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
+ Color eol_color = cache.code_folding_color;
+ eol_color.a = 1;
+ cache.folded_eol_icon->draw(ci, Point2(xofs, ofs_y + yofs), eol_color);
+ }
}
// Carets
@@ -1345,7 +1352,7 @@ void TextEdit::_notification(int p_what) {
cursor_pos.x = char_margin + ofs_x + t_caret.position.x;
}
- if (draw_caret) {
+ if (draw_caret && cursor_pos.x >= xmargin_beg && cursor_pos.x < xmargin_end) {
if (block_caret || insert_mode) {
//Block or underline caret, draw trailing carets at full height.
int h = cache.font->get_height(cache.font_size);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 1b6f73efe1..6a1b896b04 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1920,32 +1920,22 @@ String Node::get_editor_description() const {
void Node::set_editable_instance(Node *p_node, bool p_editable) {
ERR_FAIL_NULL(p_node);
ERR_FAIL_COND(!is_a_parent_of(p_node));
- NodePath p = get_path_to(p_node);
if (!p_editable) {
- data.editable_instances.erase(p);
+ p_node->data.editable_instance = false;
// Avoid this flag being needlessly saved;
// also give more visual feedback if editable children is re-enabled
set_display_folded(false);
} else {
- data.editable_instances[p] = true;
+ p_node->data.editable_instance = true;
}
}
bool Node::is_editable_instance(const Node *p_node) const {
if (!p_node) {
- return false; //easier, null is never editable :)
+ return false; // Easier, null is never editable. :)
}
ERR_FAIL_COND_V(!is_a_parent_of(p_node), false);
- NodePath p = get_path_to(p_node);
- return data.editable_instances.has(p);
-}
-
-void Node::set_editable_instances(const HashMap<NodePath, int> &p_editable_instances) {
- data.editable_instances = p_editable_instances;
-}
-
-HashMap<NodePath, int> Node::get_editable_instances() const {
- return data.editable_instances;
+ return p_node->data.editable_instance;
}
void Node::set_scene_instance_state(const Ref<SceneState> &p_state) {
diff --git a/scene/main/node.h b/scene/main/node.h
index fc7590c5a4..a0dca75791 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -88,8 +88,6 @@ private:
Ref<SceneState> instance_state;
Ref<SceneState> inherited_state;
- HashMap<NodePath, int> editable_instances;
-
Node *parent = nullptr;
Node *owner = nullptr;
Vector<Node *> children;
@@ -136,6 +134,7 @@ private:
bool use_placeholder = false;
bool display_folded = false;
+ bool editable_instance = false;
mutable NodePath *path_cache = nullptr;
@@ -325,8 +324,6 @@ public:
void set_editable_instance(Node *p_node, bool p_editable);
bool is_editable_instance(const Node *p_node) const;
- void set_editable_instances(const HashMap<NodePath, int> &p_editable_instances);
- HashMap<NodePath, int> get_editable_instances() const;
/* NOTIFICATIONS */
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index d687d31909..31496366de 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3605,6 +3605,10 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI_PROBES);
BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_BUFFER);
BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLE_LOD);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_OMNI_LIGHTS);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_SPOT_LIGHTS);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_DECALS);
+ BIND_ENUM_CONSTANT(DEBUG_DRAW_CLUSTER_REFLECTION_PROBES);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index f0818a9fed..7473b6937f 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -143,6 +143,10 @@ public:
DEBUG_DRAW_SDFGI_PROBES,
DEBUG_DRAW_GI_BUFFER,
DEBUG_DRAW_DISABLE_LOD,
+ DEBUG_DRAW_CLUSTER_OMNI_LIGHTS,
+ DEBUG_DRAW_CLUSTER_SPOT_LIGHTS,
+ DEBUG_DRAW_CLUSTER_DECALS,
+ DEBUG_DRAW_CLUSTER_REFLECTION_PROBES,
};
enum DefaultCanvasItemTextureFilter {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index b809eea43b..c349d090d8 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -175,6 +175,7 @@
#include "scene/resources/video_stream.h"
#include "scene/resources/visual_shader.h"
#include "scene/resources/visual_shader_nodes.h"
+#include "scene/resources/visual_shader_sdf_nodes.h"
#include "scene/resources/world_2d.h"
#include "scene/resources/world_3d.h"
#include "scene/resources/world_margin_shape_3d.h"
@@ -533,6 +534,7 @@ void register_scene_types() {
ClassDB::register_virtual_class<VisualShaderNodeOutput>();
ClassDB::register_virtual_class<VisualShaderNodeResizableBase>();
ClassDB::register_virtual_class<VisualShaderNodeGroupBase>();
+ ClassDB::register_virtual_class<VisualShaderNodeConstant>();
ClassDB::register_class<VisualShaderNodeFloatConstant>();
ClassDB::register_class<VisualShaderNodeIntConstant>();
ClassDB::register_class<VisualShaderNodeBooleanConstant>();
@@ -601,6 +603,12 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeCompare>();
ClassDB::register_class<VisualShaderNodeMultiplyAdd>();
+ ClassDB::register_class<VisualShaderNodeSDFToScreenUV>();
+ ClassDB::register_class<VisualShaderNodeScreenUVToSDF>();
+ ClassDB::register_class<VisualShaderNodeTextureSDF>();
+ ClassDB::register_class<VisualShaderNodeTextureSDFNormal>();
+ ClassDB::register_class<VisualShaderNodeSDFRaymarch>();
+
ClassDB::register_class<ShaderMaterial>();
ClassDB::register_virtual_class<CanvasItem>();
ClassDB::register_class<CanvasTexture>();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index dad5622117..982239fe4e 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -46,7 +46,7 @@ static TexCacheMap *tex_cache;
static float scale = 1;
template <class T>
-static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) {
+static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) {
Ref<ImageTexture> texture;
if (tex_cache->has(p_src)) {
@@ -66,11 +66,11 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, fl
style->set_texture(texture);
style->set_margin_size(SIDE_LEFT, p_left * scale);
style->set_margin_size(SIDE_RIGHT, p_right * scale);
- style->set_margin_size(SIDE_BOTTOM, p_botton * scale);
+ style->set_margin_size(SIDE_BOTTOM, p_bottom * scale);
style->set_margin_size(SIDE_TOP, p_top * scale);
style->set_default_margin(SIDE_LEFT, p_margin_left * scale);
style->set_default_margin(SIDE_RIGHT, p_margin_right * scale);
- style->set_default_margin(SIDE_BOTTOM, p_margin_botton * scale);
+ style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * scale);
style->set_default_margin(SIDE_TOP, p_margin_top * scale);
style->set_draw_center(p_draw_center);
@@ -88,11 +88,11 @@ static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left =
return style;
}
-static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox, float p_left, float p_top, float p_right, float p_botton) {
+static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox, float p_left, float p_top, float p_right, float p_bottom) {
p_sbox->set_expand_margin_size(SIDE_LEFT, p_left * scale);
p_sbox->set_expand_margin_size(SIDE_TOP, p_top * scale);
p_sbox->set_expand_margin_size(SIDE_RIGHT, p_right * scale);
- p_sbox->set_expand_margin_size(SIDE_BOTTOM, p_botton * scale);
+ p_sbox->set_expand_margin_size(SIDE_BOTTOM, p_bottom * scale);
return p_sbox;
}
@@ -127,12 +127,12 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false,
return texture;
}
-static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1) {
+static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBox> style(memnew(StyleBoxEmpty));
style->set_default_margin(SIDE_LEFT, p_margin_left * scale);
style->set_default_margin(SIDE_RIGHT, p_margin_right * scale);
- style->set_default_margin(SIDE_BOTTOM, p_margin_botton * scale);
+ style->set_default_margin(SIDE_BOTTOM, p_margin_bottom * scale);
style->set_default_margin(SIDE_TOP, p_margin_top * scale);
return style;
diff --git a/scene/resources/default_theme/xpmfix.sh b/scene/resources/default_theme/xpmfix.sh
deleted file mode 100755
index a24dede3c9..0000000000
--- a/scene/resources/default_theme/xpmfix.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-sed -i 's/static char/static const char/g' *.xpm
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 73b7a5cfe9..3aa9f9b3bc 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -646,7 +646,7 @@ void ParticlesMaterial::_update_shader() {
code += " for(int i=0;i<emit_count;i++) {\n";
code += " uint flags = FLAG_EMIT_POSITION|FLAG_EMIT_ROT_SCALE;\n";
code += " if (sub_emitter_keep_velocity) flags|=FLAG_EMIT_VELOCITY;\n";
- code += " emit_particle(TRANSFORM,VELOCITY,vec4(0.0),vec4(0.0),flags);\n";
+ code += " emit_subparticle(TRANSFORM,VELOCITY,vec4(0.0),vec4(0.0),flags);\n";
code += " }";
}
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 93bab1b042..a9d8eeef1c 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -395,10 +395,10 @@ void StyleBoxFlat::set_corner_radius_all(int radius) {
emit_changed();
}
-void StyleBoxFlat::set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_botton_right, const int radius_bottom_left) {
+void StyleBoxFlat::set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_bottom_right, const int radius_bottom_left) {
corner_radius[0] = radius_top_left;
corner_radius[1] = radius_top_right;
- corner_radius[2] = radius_botton_right;
+ corner_radius[2] = radius_bottom_right;
corner_radius[3] = radius_bottom_left;
emit_changed();
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 53ce72790a..c133f0c825 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -183,7 +183,7 @@ public:
//CORNER
void set_corner_radius_all(int radius);
- void set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_botton_right, const int radius_bottom_left);
+ void set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_bottom_right, const int radius_bottom_left);
void set_corner_radius(Corner p_corner, const int radius);
int get_corner_radius(Corner p_corner) const;
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index c1c87be42d..dbf5268762 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -35,6 +35,8 @@
SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr;
SurfaceTool::SimplifyFunc SurfaceTool::simplify_func = nullptr;
+SurfaceTool::SimplifyScaleFunc SurfaceTool::simplify_scale_func = nullptr;
+SurfaceTool::SimplifySloppyFunc SurfaceTool::simplify_sloppy_func = nullptr;
bool SurfaceTool::Vertex::operator==(const Vertex &p_vertex) const {
if (vertex != p_vertex.vertex) {
diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h
index dcb689bfc0..ea6069e7c1 100644
--- a/scene/resources/surface_tool.h
+++ b/scene/resources/surface_tool.h
@@ -78,6 +78,10 @@ public:
static OptimizeVertexCacheFunc optimize_vertex_cache_func;
typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_error);
static SimplifyFunc simplify_func;
+ typedef float (*SimplifyScaleFunc)(const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+ static SimplifyScaleFunc simplify_scale_func;
+ typedef size_t (*SimplifySloppyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *out_result_error);
+ static SimplifySloppyFunc simplify_sloppy_func;
private:
struct VertexHasher {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 342a97fd85..9a987ae8b1 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -2136,20 +2136,11 @@ AnimatedTexture::AnimatedTexture() {
pause = false;
oneshot = false;
RenderingServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy));
-
-#ifndef NO_THREADS
- rw_lock = RWLock::create();
-#else
- rw_lock = nullptr;
-#endif
}
AnimatedTexture::~AnimatedTexture() {
RS::get_singleton()->free(proxy);
RS::get_singleton()->free(proxy_ph);
- if (rw_lock) {
- memdelete(rw_lock);
- }
}
///////////////////////////////
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 3bbce050f7..83ef0c44ae 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -745,7 +745,7 @@ class AnimatedTexture : public Texture2D {
GDCLASS(AnimatedTexture, Texture2D);
//use readers writers lock for this, since its far more times read than written to
- RWLock *rw_lock;
+ RWLock rw_lock;
public:
enum {
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 2e2077d811..72724d5ee1 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -33,6 +33,7 @@
#include "core/templates/vmap.h"
#include "servers/rendering/shader_types.h"
#include "visual_shader_nodes.h"
+#include "visual_shader_sdf_nodes.h"
bool VisualShaderNode::is_simple_decl() const {
return simple_decl;
@@ -486,6 +487,22 @@ void VisualShader::remove_node(Type p_type, int p_id) {
_queue_update();
}
+void VisualShader::replace_node(Type p_type, int p_id, const StringName &p_new_class) {
+ ERR_FAIL_INDEX(p_type, TYPE_MAX);
+ ERR_FAIL_COND(p_id < 2);
+ Graph *g = &graph[p_type];
+ ERR_FAIL_COND(!g->nodes.has(p_id));
+
+ if (g->nodes[p_id].node->get_class_name() == p_new_class) {
+ return;
+ }
+ VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(p_new_class));
+ vsn->connect("changed", callable_mp(this, &VisualShader::_queue_update));
+ g->nodes[p_id].node = Ref<VisualShaderNode>(vsn);
+
+ _queue_update();
+}
+
bool VisualShader::is_node_connection(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const {
ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false);
const Graph *g = &graph[p_type];
@@ -1605,6 +1622,7 @@ void VisualShader::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_valid_node_id", "type"), &VisualShader::get_valid_node_id);
ClassDB::bind_method(D_METHOD("remove_node", "type", "id"), &VisualShader::remove_node);
+ ClassDB::bind_method(D_METHOD("replace_node", "type", "id", "new_class"), &VisualShader::replace_node);
ClassDB::bind_method(D_METHOD("is_node_connection", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::is_node_connection);
ClassDB::bind_method(D_METHOD("can_connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::can_connect_nodes);
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 3c59a922fc..9396a53e8b 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -152,6 +152,7 @@ public:
int find_node_id(Type p_type, const Ref<VisualShaderNode> &p_node) const;
void remove_node(Type p_type, int p_id);
+ void replace_node(Type p_type, int p_id, const StringName &p_new_class);
bool is_node_connection(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 7629f435a5..8b60c0a979 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -30,6 +30,11 @@
#include "visual_shader_nodes.h"
+////////////// Constants Base
+
+VisualShaderNodeConstant::VisualShaderNodeConstant() {
+}
+
////////////// Scalar(Float)
String VisualShaderNodeFloatConstant::get_caption() const {
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 35ecaaacb5..e968bbae25 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -37,8 +37,27 @@
/// CONSTANTS
///////////////////////////////////////
-class VisualShaderNodeFloatConstant : public VisualShaderNode {
- GDCLASS(VisualShaderNodeFloatConstant, VisualShaderNode);
+class VisualShaderNodeConstant : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeConstant, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override = 0;
+
+ virtual int get_input_port_count() const override = 0;
+ virtual PortType get_input_port_type(int p_port) const override = 0;
+ virtual String get_input_port_name(int p_port) const override = 0;
+
+ virtual int get_output_port_count() const override = 0;
+ virtual PortType get_output_port_type(int p_port) const override = 0;
+ virtual String get_output_port_name(int p_port) const override = 0;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override = 0;
+
+ VisualShaderNodeConstant();
+};
+
+class VisualShaderNodeFloatConstant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeFloatConstant, VisualShaderNodeConstant);
float constant = 0.0f;
protected:
@@ -67,8 +86,8 @@ public:
///////////////////////////////////////
-class VisualShaderNodeIntConstant : public VisualShaderNode {
- GDCLASS(VisualShaderNodeIntConstant, VisualShaderNode);
+class VisualShaderNodeIntConstant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeIntConstant, VisualShaderNodeConstant);
int constant = 0;
protected:
@@ -97,8 +116,8 @@ public:
///////////////////////////////////////
-class VisualShaderNodeBooleanConstant : public VisualShaderNode {
- GDCLASS(VisualShaderNodeBooleanConstant, VisualShaderNode);
+class VisualShaderNodeBooleanConstant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeBooleanConstant, VisualShaderNodeConstant);
bool constant = false;
protected:
@@ -127,8 +146,8 @@ public:
///////////////////////////////////////
-class VisualShaderNodeColorConstant : public VisualShaderNode {
- GDCLASS(VisualShaderNodeColorConstant, VisualShaderNode);
+class VisualShaderNodeColorConstant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeColorConstant, VisualShaderNodeConstant);
Color constant = Color(1, 1, 1, 1);
protected:
@@ -157,8 +176,8 @@ public:
///////////////////////////////////////
-class VisualShaderNodeVec3Constant : public VisualShaderNode {
- GDCLASS(VisualShaderNodeVec3Constant, VisualShaderNode);
+class VisualShaderNodeVec3Constant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeVec3Constant, VisualShaderNodeConstant);
Vector3 constant;
protected:
@@ -187,8 +206,8 @@ public:
///////////////////////////////////////
-class VisualShaderNodeTransformConstant : public VisualShaderNode {
- GDCLASS(VisualShaderNodeTransformConstant, VisualShaderNode);
+class VisualShaderNodeTransformConstant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeTransformConstant, VisualShaderNodeConstant);
Transform constant;
protected:
diff --git a/scene/resources/visual_shader_sdf_nodes.cpp b/scene/resources/visual_shader_sdf_nodes.cpp
new file mode 100644
index 0000000000..d25e32b070
--- /dev/null
+++ b/scene/resources/visual_shader_sdf_nodes.cpp
@@ -0,0 +1,283 @@
+/*************************************************************************/
+/* visual_shader_sdf_nodes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "visual_shader_sdf_nodes.h"
+
+// VisualShaderNodeSDFToScreenUV
+
+String VisualShaderNodeSDFToScreenUV::get_caption() const {
+ return "SDFToScreenUV";
+}
+
+int VisualShaderNodeSDFToScreenUV::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeSDFToScreenUV::PortType VisualShaderNodeSDFToScreenUV::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeSDFToScreenUV::get_input_port_name(int p_port) const {
+ return "sdf_pos";
+}
+
+int VisualShaderNodeSDFToScreenUV::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeSDFToScreenUV::PortType VisualShaderNodeSDFToScreenUV::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeSDFToScreenUV::get_output_port_name(int p_port) const {
+ return "";
+}
+
+String VisualShaderNodeSDFToScreenUV::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return "\t" + p_output_vars[0] + " = vec3(sdf_to_screen_uv(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
+}
+
+VisualShaderNodeSDFToScreenUV::VisualShaderNodeSDFToScreenUV() {
+}
+
+// VisualShaderNodeScreenUVToSDF
+
+String VisualShaderNodeScreenUVToSDF::get_caption() const {
+ return "ScreenUVToSDF";
+}
+
+int VisualShaderNodeScreenUVToSDF::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeScreenUVToSDF::PortType VisualShaderNodeScreenUVToSDF::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeScreenUVToSDF::get_input_port_name(int p_port) const {
+ return "uv";
+}
+
+int VisualShaderNodeScreenUVToSDF::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeScreenUVToSDF::PortType VisualShaderNodeScreenUVToSDF::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeScreenUVToSDF::get_output_port_name(int p_port) const {
+ return "";
+}
+
+String VisualShaderNodeScreenUVToSDF::get_input_port_default_hint(int p_port) const {
+ if (p_port == 0) {
+ return "default";
+ }
+ return "";
+}
+
+String VisualShaderNodeScreenUVToSDF::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return "\t" + p_output_vars[0] + " = vec3(screen_uv_to_sdf(" + (p_input_vars[0] == String() ? "SCREEN_UV" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
+}
+
+VisualShaderNodeScreenUVToSDF::VisualShaderNodeScreenUVToSDF() {
+}
+
+// VisualShaderNodeTextureSDF
+
+String VisualShaderNodeTextureSDF::get_caption() const {
+ return "TextureSDF";
+}
+
+int VisualShaderNodeTextureSDF::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeTextureSDF::PortType VisualShaderNodeTextureSDF::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeTextureSDF::get_input_port_name(int p_port) const {
+ return "sdf_pos";
+}
+
+int VisualShaderNodeTextureSDF::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeTextureSDF::PortType VisualShaderNodeTextureSDF::get_output_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeTextureSDF::get_output_port_name(int p_port) const {
+ return "";
+}
+
+String VisualShaderNodeTextureSDF::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return "\t" + p_output_vars[0] + " = texture_sdf(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + ");\n";
+}
+
+VisualShaderNodeTextureSDF::VisualShaderNodeTextureSDF() {
+}
+
+// VisualShaderNodeTextureSDFNormal
+
+String VisualShaderNodeTextureSDFNormal::get_caption() const {
+ return "TextureSDFNormal";
+}
+
+int VisualShaderNodeTextureSDFNormal::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeTextureSDFNormal::PortType VisualShaderNodeTextureSDFNormal::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeTextureSDFNormal::get_input_port_name(int p_port) const {
+ return "sdf_pos";
+}
+
+int VisualShaderNodeTextureSDFNormal::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeTextureSDFNormal::PortType VisualShaderNodeTextureSDFNormal::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeTextureSDFNormal::get_output_port_name(int p_port) const {
+ return "";
+}
+
+String VisualShaderNodeTextureSDFNormal::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return "\t" + p_output_vars[0] + " = vec3(texture_sdf_normal(" + (p_input_vars[0] == String() ? "vec2(0.0)" : p_input_vars[0] + ".xy") + "), 0.0f);\n";
+}
+
+VisualShaderNodeTextureSDFNormal::VisualShaderNodeTextureSDFNormal() {
+}
+
+// VisualShaderNodeSDFRaymarch
+
+String VisualShaderNodeSDFRaymarch::get_caption() const {
+ return "SDFRaymarch";
+}
+
+int VisualShaderNodeSDFRaymarch::get_input_port_count() const {
+ return 2;
+}
+
+VisualShaderNodeSDFRaymarch::PortType VisualShaderNodeSDFRaymarch::get_input_port_type(int p_port) const {
+ if (p_port == 0 || p_port == 1) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeSDFRaymarch::get_input_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "from_pos";
+ } else if (p_port == 1) {
+ return "to_pos";
+ }
+ return String();
+}
+
+int VisualShaderNodeSDFRaymarch::get_output_port_count() const {
+ return 3;
+}
+
+VisualShaderNodeSDFRaymarch::PortType VisualShaderNodeSDFRaymarch::get_output_port_type(int p_port) const {
+ if (p_port == 0) {
+ return PORT_TYPE_SCALAR;
+ } else if (p_port == 1) {
+ return PORT_TYPE_BOOLEAN;
+ } else if (p_port == 2) {
+ return PORT_TYPE_VECTOR;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeSDFRaymarch::get_output_port_name(int p_port) const {
+ if (p_port == 0) {
+ return "distance";
+ } else if (p_port == 1) {
+ return "hit";
+ } else if (p_port == 2) {
+ return "end_pos";
+ }
+ return String();
+}
+
+String VisualShaderNodeSDFRaymarch::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+
+ code += "\t{\n";
+
+ if (p_input_vars[0] == String()) {
+ code += "\t\tvec2 __from_pos = vec2(0.0f);\n";
+ } else {
+ code += "\t\tvec2 __from_pos = " + p_input_vars[0] + ".xy;\n";
+ }
+
+ if (p_input_vars[1] == String()) {
+ code += "\t\tvec2 __to_pos = vec2(0.0f);\n";
+ } else {
+ code += "\t\tvec2 __to_pos = " + p_input_vars[1] + ".xy;\n";
+ }
+
+ code += "\n\t\tvec2 __at = __from_pos;\n";
+ code += "\t\tfloat __max_dist = distance(__from_pos, __to_pos);\n";
+ code += "\t\tvec2 __dir = normalize(__to_pos - __from_pos);\n\n";
+
+ code += "\t\tfloat __accum = 0.0f;\n";
+ code += "\t\twhile(__accum < __max_dist) {\n";
+ code += "\t\t\tfloat __d = texture_sdf(__at);\n";
+ code += "\t\t\t__accum += __d;\n";
+ code += "\t\t\tif (__d < 0.01f) {\n";
+ code += "\t\t\t\tbreak;\n";
+ code += "\t\t\t}\n";
+ code += "\t\t\t__at += __d * __dir;\n";
+ code += "\t\t}\n";
+
+ code += "\t\tfloat __dist = min(__max_dist, __accum);\n";
+ code += "\t\t" + p_output_vars[0] + " = __dist;\n";
+ code += "\t\t" + p_output_vars[1] + " = __accum < __max_dist;\n";
+ code += "\t\t" + p_output_vars[2] + " = vec3(__from_pos + __dir * __dist, 0.0f);\n";
+
+ code += "\t}\n";
+
+ return code;
+}
+
+VisualShaderNodeSDFRaymarch::VisualShaderNodeSDFRaymarch() {
+ simple_decl = false;
+}
diff --git a/scene/resources/visual_shader_sdf_nodes.h b/scene/resources/visual_shader_sdf_nodes.h
new file mode 100644
index 0000000000..0fcf5ec0b5
--- /dev/null
+++ b/scene/resources/visual_shader_sdf_nodes.h
@@ -0,0 +1,132 @@
+/*************************************************************************/
+/* visual_shader_sdf_nodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 VISUAL_SHADER_SDF_NODES_H
+#define VISUAL_SHADER_SDF_NODES_H
+
+#include "scene/resources/visual_shader.h"
+
+class VisualShaderNodeSDFToScreenUV : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeSDFToScreenUV, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeSDFToScreenUV();
+};
+
+class VisualShaderNodeScreenUVToSDF : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeScreenUVToSDF, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String get_input_port_default_hint(int p_port) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeScreenUVToSDF();
+};
+
+class VisualShaderNodeTextureSDF : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeTextureSDF, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeTextureSDF();
+};
+
+class VisualShaderNodeTextureSDFNormal : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeTextureSDFNormal, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeTextureSDFNormal();
+};
+
+class VisualShaderNodeSDFRaymarch : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeSDFRaymarch, VisualShaderNode);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeSDFRaymarch();
+};
+
+#endif // VISUAL_SHADER_SDF_NODES_H