summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/decal.cpp27
-rw-r--r--scene/3d/decal.h2
-rw-r--r--scene/3d/mesh_instance_3d.cpp12
-rw-r--r--scene/3d/mesh_instance_3d.h4
-rw-r--r--scene/3d/occluder_instance_3d.cpp28
-rw-r--r--scene/3d/occluder_instance_3d.h2
-rw-r--r--scene/3d/visual_instance_3d.cpp9
-rw-r--r--scene/gui/color_picker.cpp16
-rw-r--r--scene/gui/color_picker.h1
-rw-r--r--scene/gui/dialogs.cpp23
-rw-r--r--scene/gui/dialogs.h1
-rw-r--r--scene/gui/line_edit.cpp32
-rw-r--r--scene/gui/text_edit.cpp8
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/gui/tree.cpp152
-rw-r--r--scene/gui/tree.h15
-rw-r--r--scene/main/canvas_item.cpp2
-rw-r--r--scene/main/node.cpp8
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/scene_tree.cpp87
-rw-r--r--scene/main/scene_tree.h17
-rw-r--r--scene/main/shader_globals_override.cpp14
-rw-r--r--scene/main/window.cpp3
-rw-r--r--scene/register_scene_types.cpp3
-rw-r--r--scene/resources/material.cpp56
-rw-r--r--scene/resources/material.h7
-rw-r--r--scene/resources/mesh.cpp35
-rw-r--r--scene/resources/mesh.h6
-rw-r--r--scene/resources/particles_material.cpp36
-rw-r--r--scene/resources/primitive_meshes.cpp39
-rw-r--r--scene/resources/primitive_meshes.h8
-rw-r--r--scene/resources/sky_material.cpp6
-rw-r--r--scene/resources/texture.cpp6
-rw-r--r--scene/resources/tile_set.cpp32
-rw-r--r--scene/resources/visual_shader.cpp22
-rw-r--r--scene/resources/visual_shader.h1
-rw-r--r--scene/resources/visual_shader_nodes.cpp86
-rw-r--r--scene/resources/visual_shader_nodes.h33
38 files changed, 578 insertions, 267 deletions
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index 7d6abe458a..5af7b8ca07 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -45,6 +45,7 @@ void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) {
textures[p_type] = p_texture;
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RS::get_singleton()->decal_set_texture(decal, RS::DecalTexture(p_type), texture_rid);
+ update_configuration_warnings();
}
Ref<Texture2D> Decal::get_texture(DecalTexture p_type) const {
@@ -137,6 +138,7 @@ float Decal::get_distance_fade_length() const {
void Decal::set_cull_mask(uint32_t p_layers) {
cull_mask = p_layers;
RS::get_singleton()->decal_set_cull_mask(decal, cull_mask);
+ update_configuration_warnings();
}
uint32_t Decal::get_cull_mask() const {
@@ -160,6 +162,27 @@ void Decal::_validate_property(PropertyInfo &property) const {
}
}
+TypedArray<String> Decal::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (textures[TEXTURE_ALBEDO].is_null() && textures[TEXTURE_NORMAL].is_null() && textures[TEXTURE_ORM].is_null() && textures[TEXTURE_EMISSION].is_null()) {
+ warnings.push_back(TTR("The decal has no textures loaded into any of its texture properties, and will therefore not be visible."));
+ }
+
+ if ((textures[TEXTURE_NORMAL].is_valid() || textures[TEXTURE_ORM].is_valid()) && textures[TEXTURE_ALBEDO].is_null()) {
+ warnings.push_back(TTR("The decal has a Normal and/or ORM texture, but no Albedo texture is set.\nAn Albedo texture with an alpha channel is required to blend the normal/ORM maps onto the underlying surface.\nIf you don't want the Albedo texture to be visible, set Albedo Mix to 0."));
+ }
+
+ if (cull_mask == 0) {
+ // NOTE: This warning will not be emitted if none of the 20 checkboxes
+ // exposed in the editor are checked. This is because there are
+ // currently 12 unexposed layers in the editor inspector.
+ warnings.push_back(TTR("The decal's Cull Mask has no bits enabled, which means the decal will not paint objects on any layer.\nTo resolve this, enable at least one bit in the Cull Mask property."));
+ }
+
+ return warnings;
+}
+
void Decal::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &Decal::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &Decal::get_extents);
@@ -207,7 +230,9 @@ void Decal::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_emission_energy", "get_emission_energy");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "albedo_mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_albedo_mix", "get_albedo_mix");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_normal_fade", "get_normal_fade");
+ // A Normal Fade of 1.0 causes the decal to be invisible even if fully perpendicular to a surface.
+ // Due to this, limit Normal Fade to 0.999.
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_fade", PROPERTY_HINT_RANGE, "0,0.999,0.001"), "set_normal_fade", "get_normal_fade");
ADD_GROUP("Vertical Fade", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "upper_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_upper_fade", "get_upper_fade");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lower_fade", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_lower_fade", "get_lower_fade");
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index ce19e76de1..31a6315213 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -67,6 +67,8 @@ protected:
void _validate_property(PropertyInfo &property) const override;
public:
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 08dec232ab..28ccbd3e68 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -100,7 +100,7 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
if (mesh.is_valid()) {
for (int i = 0; i < mesh->get_surface_count(); i++) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_material_override/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_material_override/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE));
}
}
}
@@ -241,12 +241,12 @@ void MeshInstance3D::create_trimesh_collision() {
}
}
-Node *MeshInstance3D::create_convex_collision_node() {
+Node *MeshInstance3D::create_convex_collision_node(bool p_clean, bool p_simplify) {
if (mesh.is_null()) {
return nullptr;
}
- Ref<Shape3D> shape = mesh->create_convex_shape();
+ Ref<Shape3D> shape = mesh->create_convex_shape(p_clean, p_simplify);
if (shape.is_null()) {
return nullptr;
}
@@ -258,8 +258,8 @@ Node *MeshInstance3D::create_convex_collision_node() {
return static_body;
}
-void MeshInstance3D::create_convex_collision() {
- StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_convex_collision_node());
+void MeshInstance3D::create_convex_collision(bool p_clean, bool p_simplify) {
+ StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_convex_collision_node(p_clean, p_simplify));
ERR_FAIL_COND(!static_body);
static_body->set_name(String(get_name()) + "_col");
@@ -451,7 +451,7 @@ void MeshInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance3D::create_trimesh_collision);
ClassDB::set_method_flags("MeshInstance3D", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
- ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance3D::create_convex_collision);
+ ClassDB::bind_method(D_METHOD("create_convex_collision", "clean", "simplify"), &MeshInstance3D::create_convex_collision, DEFVAL(true), DEFVAL(false));
ClassDB::set_method_flags("MeshInstance3D", "create_convex_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance3D::create_multiple_convex_collisions);
ClassDB::set_method_flags("MeshInstance3D", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT);
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 9dea5804e0..e2d20d0a90 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -83,8 +83,8 @@ public:
Node *create_trimesh_collision_node();
void create_trimesh_collision();
- Node *create_convex_collision_node();
- void create_convex_collision();
+ Node *create_convex_collision_node(bool p_clean = true, bool p_simplify = false);
+ void create_convex_collision(bool p_clean = true, bool p_simplify = false);
Node *create_multiple_convex_collisions_node();
void create_multiple_convex_collisions();
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index b0b9668fd2..7b736e689c 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -174,10 +174,12 @@ void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) {
}
update_gizmo();
+ update_configuration_warnings();
}
void OccluderInstance3D::_occluder_changed() {
update_gizmo();
+ update_configuration_warnings();
}
Ref<Occluder3D> OccluderInstance3D::get_occluder() const {
@@ -186,6 +188,7 @@ Ref<Occluder3D> OccluderInstance3D::get_occluder() const {
void OccluderInstance3D::set_bake_mask(uint32_t p_mask) {
bake_mask = p_mask;
+ update_configuration_warnings();
}
uint32_t OccluderInstance3D::get_bake_mask() const {
@@ -314,6 +317,31 @@ OccluderInstance3D::BakeError OccluderInstance3D::bake(Node *p_from_node, String
return BAKE_ERROR_OK;
}
+TypedArray<String> OccluderInstance3D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (!bool(GLOBAL_GET("rendering/occlusion_culling/use_occlusion_culling"))) {
+ warnings.push_back(TTR("Occlusion culling is disabled in the Project Settings, which means occlusion culling won't be performed in the root viewport.\nTo resolve this, open the Project Settings and enable Rendering > Occlusion Culling > Use Occlusion Culling."));
+ }
+
+ if (bake_mask == 0) {
+ // NOTE: This warning will not be emitted if none of the 20 checkboxes
+ // exposed in the editor are checked. This is because there are
+ // currently 12 unexposed layers in the editor inspector.
+ warnings.push_back(TTR("The Bake Mask has no bits enabled, which means baking will not produce any occluder meshes for this OccluderInstance3D.\nTo resolve this, enable at least one bit in the Bake Mask property."));
+ }
+
+ if (occluder.is_null()) {
+ warnings.push_back(TTR("No occluder mesh is defined in the Occluder property, so no occlusion culling will be performed using this OccluderInstance3D.\nTo resolve this, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport."));
+ } else if (occluder->get_vertices().size() < 3) {
+ // Using the "New Occluder" dropdown button won't result in a correct occluder,
+ // so warn the user about this.
+ warnings.push_back(TTR("The occluder mesh has less than 3 vertices, so no occlusion culling will be performed using this OccluderInstance3D.\nTo generate a proper occluder mesh, select the OccluderInstance3D then use the Bake Occluders button at the top of the 3D editor viewport."));
+ }
+
+ return warnings;
+}
+
void OccluderInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bake_mask", "mask"), &OccluderInstance3D::set_bake_mask);
ClassDB::bind_method(D_METHOD("get_bake_mask"), &OccluderInstance3D::get_bake_mask);
diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h
index 4bb468274d..d382cd090e 100644
--- a/scene/3d/occluder_instance_3d.h
+++ b/scene/3d/occluder_instance_3d.h
@@ -82,6 +82,8 @@ protected:
static void _bind_methods();
public:
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
enum BakeError {
BAKE_ERROR_OK,
BAKE_ERROR_NO_SAVE_PATH,
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 471dc03d62..bd47af8100 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -293,7 +293,12 @@ void GeometryInstance3D::set_shader_instance_uniform(const StringName &p_uniform
instance_uniforms.erase(p_value);
} else {
instance_uniforms[p_uniform] = p_value;
- RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value);
+ if (p_value.get_type() == Variant::OBJECT) {
+ RID tex_id = p_value;
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, tex_id);
+ } else {
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_uniform, p_value);
+ }
}
}
@@ -389,7 +394,7 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance3D::get_aabb);
ADD_GROUP("Geometry", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias");
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 049de4c8c5..659d14ae70 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -40,6 +40,8 @@
#endif
#include "scene/main/window.h"
+List<Color> ColorPicker::preset_cache;
+
void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
@@ -57,11 +59,17 @@ void ColorPicker::_notification(int p_what) {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- PackedColorArray saved_presets = EditorSettings::get_singleton()->get_project_metadata("color_picker", "presets", PackedColorArray());
+ if (preset_cache.is_empty()) {
+ PackedColorArray saved_presets = EditorSettings::get_singleton()->get_project_metadata("color_picker", "presets", PackedColorArray());
+ for (int i = 0; i < saved_presets.size(); i++) {
+ preset_cache.push_back(saved_presets[i]);
+ }
+ }
- for (int i = 0; i < saved_presets.size(); i++) {
- add_preset(saved_presets[i]);
+ for (int i = 0; i < preset_cache.size(); i++) {
+ presets.push_back(preset_cache[i]);
}
+ preset->update();
}
#endif
} break;
@@ -413,6 +421,7 @@ void ColorPicker::add_preset(const Color &p_color) {
presets.move_to_back(presets.find(p_color));
} else {
presets.push_back(p_color);
+ preset_cache.push_back(p_color);
}
preset->update();
@@ -427,6 +436,7 @@ void ColorPicker::add_preset(const Color &p_color) {
void ColorPicker::erase_preset(const Color &p_color) {
if (presets.find(p_color)) {
presets.erase(presets.find(p_color));
+ preset_cache.erase(preset_cache.find(p_color));
preset->update();
#ifdef TOOLS_ENABLED
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 3bd2ff9375..60da3957aa 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -58,6 +58,7 @@ public:
private:
static Ref<Shader> wheel_shader;
static Ref<Shader> circle_shader;
+ static List<Color> preset_cache;
Control *screen = nullptr;
Control *uv_edit = memnew(Control);
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index f63ae7569f..dceab00607 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -263,6 +263,28 @@ Button *AcceptDialog::add_cancel_button(const String &p_cancel) {
return b;
}
+void AcceptDialog::remove_button(Control *p_button) {
+ Button *button = Object::cast_to<Button>(p_button);
+ ERR_FAIL_NULL(button);
+ ERR_FAIL_COND_MSG(button->get_parent() != hbc, vformat("Cannot remove button %s as it does not belong to this dialog.", button->get_name()));
+ ERR_FAIL_COND_MSG(button == ok, "Cannot remove dialog's OK button.");
+
+ Node *right_spacer = hbc->get_child(button->get_index() + 1);
+ // Should always be valid but let's avoid crashing
+ if (right_spacer) {
+ hbc->remove_child(right_spacer);
+ memdelete(right_spacer);
+ }
+ hbc->remove_child(button);
+
+ if (button->is_connected("pressed", callable_mp(this, &AcceptDialog::_custom_action))) {
+ button->disconnect("pressed", callable_mp(this, &AcceptDialog::_custom_action));
+ }
+ if (button->is_connected("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed))) {
+ button->disconnect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
+ }
+}
+
void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_ok_button"), &AcceptDialog::get_ok_button);
ClassDB::bind_method(D_METHOD("get_label"), &AcceptDialog::get_label);
@@ -270,6 +292,7 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_hide_on_ok"), &AcceptDialog::get_hide_on_ok);
ClassDB::bind_method(D_METHOD("add_button", "text", "right", "action"), &AcceptDialog::add_button, DEFVAL(false), DEFVAL(""));
ClassDB::bind_method(D_METHOD("add_cancel_button", "name"), &AcceptDialog::add_cancel_button);
+ ClassDB::bind_method(D_METHOD("remove_button", "button"), &AcceptDialog::remove_button);
ClassDB::bind_method(D_METHOD("register_text_enter", "line_edit"), &AcceptDialog::register_text_enter);
ClassDB::bind_method(D_METHOD("set_text", "text"), &AcceptDialog::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &AcceptDialog::get_text);
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index d389806fff..8e803a2a7c 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -82,6 +82,7 @@ public:
Button *get_ok_button() { return ok; }
Button *add_button(const String &p_text, bool p_right = false, const String &p_action = "");
Button *add_cancel_button(const String &p_cancel = "");
+ void remove_button(Control *p_button);
void set_hide_on_ok(bool p_hide);
bool get_hide_on_ok() const;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 089893e63b..f2d0d9bb22 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -1470,19 +1470,23 @@ int LineEdit::get_scroll_offset() const {
}
void LineEdit::insert_text_at_caret(String p_text) {
- if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) {
- String pre = text.substr(0, caret_column);
- String post = text.substr(caret_column, text.length() - caret_column);
- text = pre + p_text + post;
- _shape();
- TextServer::Direction dir = TS->shaped_text_get_dominant_direciton_in_range(text_rid, caret_column, caret_column + p_text.length());
- if (dir != TextServer::DIRECTION_AUTO) {
- input_direction = (TextDirection)dir;
+ if (max_length > 0) {
+ // Truncate text to append to fit in max_length, if needed.
+ int available_chars = max_length - text.length();
+ if (p_text.length() > available_chars) {
+ emit_signal("text_change_rejected", p_text.substr(available_chars));
+ p_text = p_text.substr(0, available_chars);
}
- set_caret_column(caret_column + p_text.length());
- } else {
- emit_signal("text_change_rejected");
}
+ String pre = text.substr(0, caret_column);
+ String post = text.substr(caret_column, text.length() - caret_column);
+ text = pre + p_text + post;
+ _shape();
+ TextServer::Direction dir = TS->shaped_text_get_dominant_direciton_in_range(text_rid, caret_column, caret_column + p_text.length());
+ if (dir != TextServer::DIRECTION_AUTO) {
+ input_direction = (TextDirection)dir;
+ }
+ set_caret_column(caret_column + p_text.length());
}
void LineEdit::clear_internal() {
@@ -2158,7 +2162,7 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
- ADD_SIGNAL(MethodInfo("text_change_rejected"));
+ ADD_SIGNAL(MethodInfo("text_change_rejected", PropertyInfo(Variant::STRING, "rejected_substring")));
ADD_SIGNAL(MethodInfo("text_submitted", PropertyInfo(Variant::STRING, "new_text")));
BIND_ENUM_CONSTANT(ALIGN_LEFT);
@@ -2198,7 +2202,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_max_length", "get_max_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character");
@@ -2221,7 +2225,7 @@ void LineEdit::_bind_methods() {
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "set_caret_blink_enabled", "is_caret_blink_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "set_caret_blink_speed", "get_caret_blink_speed");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_column"), "set_caret_column", "get_caret_column");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_column", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_caret_column", "get_caret_column");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_force_displayed"), "set_caret_force_displayed", "is_caret_force_displayed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled");
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 370fdd8b88..6f96b530a6 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4008,14 +4008,6 @@ bool TextEdit::is_wrap_enabled() const {
return wrap_enabled;
}
-void TextEdit::set_max_chars(int p_max_chars) {
- max_chars = p_max_chars;
-}
-
-int TextEdit::get_max_chars() const {
- return max_chars;
-}
-
void TextEdit::_reset_caret_blink_timer() {
if (caret_blink_enabled) {
draw_caret = true;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 146de50275..dcd5c6d0f8 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -258,7 +258,6 @@ private:
uint32_t version = 0;
uint32_t saved_version = 0;
- int max_chars = 0;
bool readonly = true; // Initialise to opposite first, so we get past the early-out in set_readonly.
Timer *caret_blink_timer;
@@ -678,9 +677,6 @@ public:
void set_readonly(bool p_readonly);
bool is_readonly() const;
- void set_max_chars(int p_max_chars);
- int get_max_chars() const;
-
void set_wrap_enabled(bool p_wrap_enabled);
bool is_wrap_enabled() const;
bool line_wraps(int line) const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 49e6832800..4d2cb81f23 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -973,6 +973,9 @@ Size2 TreeItem::get_minimum_size(int p_column) {
}
// Icon.
+ if (cell.mode == CELL_MODE_CHECK) {
+ size.width += tree->cache.checked->get_width() + tree->cache.hseparation;
+ }
if (cell.icon.is_valid()) {
Size2i icon_size = cell.get_icon_size();
if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
@@ -1247,6 +1250,9 @@ void Tree::update_cache() {
cache.item_margin = get_theme_constant("item_margin");
cache.button_margin = get_theme_constant("button_margin");
+ cache.font_outline_color = get_theme_color("font_outline_color");
+ cache.font_outline_size = get_theme_constant("outline_size");
+
cache.draw_guides = get_theme_constant("draw_guides");
cache.guide_color = get_theme_color("guide_color");
cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
@@ -1508,7 +1514,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int htotal = 0;
int label_h = compute_item_height(p_item);
- bool rtl = is_layout_rtl();
+ bool rtl = cache.rtl;
/* Calculate height of the label part */
label_h += cache.vseparation;
@@ -1554,6 +1560,20 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
+ if (!rtl && p_item->cells[i].buttons.size()) {
+ int button_w = 0;
+ for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
+ button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ }
+
+ int total_ofs = ofs - cache.offset.x;
+
+ if (total_ofs + w > p_draw_size.width) {
+ w = MAX(button_w, p_draw_size.width - total_ofs);
+ }
+ }
+
int bw = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
@@ -1678,8 +1698,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_selected_color" : "font_color");
- Color font_outline_color = get_theme_color("font_outline_color");
- int outline_size = get_theme_constant("outline_size");
+ Color font_outline_color = cache.font_outline_color;
+ int outline_size = cache.font_outline_size;
Color icon_col = p_item->cells[i].icon_color;
if (p_item->cells[i].dirty) {
@@ -2133,13 +2153,24 @@ void Tree::_range_click_timeout() {
}
}
+ if (!root) {
+ return;
+ }
+
click_handled = false;
Ref<InputEventMouseButton> mb;
mb.instantiate();
+ int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ if (h_scroll->is_visible()) {
+ x_limit -= h_scroll->get_minimum_size().width;
+ }
+
+ cache.rtl = is_layout_rtl();
+
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, false, root, MOUSE_BUTTON_LEFT, mb);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MOUSE_BUTTON_LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -2162,7 +2193,7 @@ void Tree::_range_click_timeout() {
}
}
-int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
+int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod) {
int item_h = compute_item_height(p_item) + cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -2187,6 +2218,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
int col = -1;
int col_ofs = 0;
int col_width = 0;
+
+ int limit_w = x_limit;
+
for (int i = 0; i < columns.size(); i++) {
col_width = get_column_width(i);
@@ -2202,6 +2236,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
if (x > col_width) {
col_ofs += col_width;
x -= col_width;
+ limit_w -= col_width;
continue;
}
@@ -2215,10 +2250,12 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
int margin = x_ofs + cache.item_margin; //-cache.hseparation;
//int lm = cache.bg->get_margin(SIDE_LEFT);
col_width -= margin;
+ limit_w -= margin;
col_ofs += margin;
x -= margin;
} else {
col_width -= cache.hseparation;
+ limit_w -= cache.hseparation;
x -= cache.hseparation;
}
@@ -2232,6 +2269,16 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
bool already_selected = c.selected;
bool already_cursor = (p_item == selected_item) && col == selected_col;
+ if (!cache.rtl && p_item->cells[col].buttons.size()) {
+ int button_w = 0;
+ for (int j = p_item->cells[col].buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = p_item->cells[col].buttons[j].texture;
+ button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ }
+
+ col_width = MAX(button_w, MIN(limit_w, col_width));
+ }
+
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
int w = b->get_size().width + cache.button_pressed->get_minimum_size().width;
@@ -2253,6 +2300,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
//emit_signal("button_pressed");
return -1;
}
+
col_width -= w + cache.button_margin;
}
@@ -2463,7 +2511,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
TreeItem *c = p_item->first_child;
while (c) {
- int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, p_double_click, c, p_button, p_mod);
+ int child_h = propagate_mouse_event(new_pos, x_ofs, y_ofs, x_limit, p_double_click, c, p_button, p_mod);
if (child_h < 0) {
return -1; // break, stop propagating, no need to anymore
@@ -3141,8 +3189,14 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
pressing_for_editor = false;
propagate_mouse_activated = false;
+ int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ if (h_scroll->is_visible()) {
+ x_limit -= h_scroll->get_minimum_size().width;
+ }
+
+ cache.rtl = is_layout_rtl();
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, b->is_double_click(), root, b->get_button_index(), b);
+ propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, b->is_double_click(), root, b->get_button_index(), b);
blocked--;
if (pressing_for_editor) {
@@ -3494,6 +3548,9 @@ void Tree::_notification(int p_what) {
Point2 draw_ofs;
draw_ofs += bg->get_offset();
Size2 draw_size = get_size() - bg->get_minimum_size();
+ if (h_scroll->is_visible()) {
+ draw_size.width -= h_scroll->get_minimum_size().width;
+ }
bg->draw(ci, Rect2(Point2(), get_size()));
@@ -3502,6 +3559,8 @@ void Tree::_notification(int p_what) {
draw_ofs.y += tbh;
draw_size.y -= tbh;
+ cache.rtl = is_layout_rtl();
+
if (root && get_size().x > 0 && get_size().y > 0) {
draw_item(Point2(), draw_ofs, draw_size, root);
}
@@ -3513,7 +3572,7 @@ void Tree::_notification(int p_what) {
Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button);
Ref<Font> f = cache.tb_font;
Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
- if (is_layout_rtl()) {
+ if (cache.rtl) {
tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
}
sb->draw(ci, tbrect);
@@ -3759,6 +3818,36 @@ void Tree::set_column_expand(int p_column, bool p_expand) {
update();
}
+void Tree::set_column_expand_ratio(int p_column, int p_ratio) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+ columns.write[p_column].expand_ratio = p_ratio;
+ update();
+}
+
+void Tree::set_column_clip_content(int p_column, bool p_fit) {
+ ERR_FAIL_INDEX(p_column, columns.size());
+
+ columns.write[p_column].clip_content = p_fit;
+ update();
+}
+
+bool Tree::is_column_expanding(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), false);
+
+ return columns[p_column].expand;
+}
+int Tree::get_column_expand_ratio(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), 1);
+
+ return columns[p_column].expand_ratio;
+}
+
+bool Tree::is_column_clipping_content(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, columns.size(), false);
+
+ return columns[p_column].clip_content;
+}
+
TreeItem *Tree::get_selected() const {
return selected_item;
}
@@ -3818,11 +3907,14 @@ TreeItem *Tree::get_next_selected(TreeItem *p_item) {
int Tree::get_column_minimum_width(int p_column) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
- if (columns[p_column].custom_min_width != 0) {
- return columns[p_column].custom_min_width;
- } else {
+ int min_width = columns[p_column].custom_min_width;
+
+ if (show_column_titles) {
+ min_width = MAX(cache.font->get_string_size(columns[p_column].title).width, min_width);
+ }
+
+ if (!columns[p_column].clip_content) {
int depth = 0;
- int min_width = 0;
TreeItem *next;
for (TreeItem *item = get_root(); item; item = next) {
next = item->get_next_visible();
@@ -3846,13 +3938,16 @@ int Tree::get_column_minimum_width(int p_column) const {
}
min_width = MAX(min_width, item_size.width);
}
- return min_width;
}
+
+ return min_width;
}
int Tree::get_column_width(int p_column) const {
ERR_FAIL_INDEX_V(p_column, columns.size(), -1);
+ int column_width = get_column_minimum_width(p_column);
+
if (columns[p_column].expand) {
int expand_area = get_size().width;
@@ -3866,31 +3961,24 @@ int Tree::get_column_width(int p_column) const {
expand_area -= v_scroll->get_combined_minimum_size().width;
}
- int expanding_columns = 0;
int expanding_total = 0;
for (int i = 0; i < columns.size(); i++) {
- if (!columns[i].expand) {
- expand_area -= get_column_minimum_width(i);
- } else {
- expanding_total += get_column_minimum_width(i);
- expanding_columns++;
+ expand_area -= get_column_minimum_width(i);
+ if (columns[i].expand) {
+ expanding_total += columns[i].expand_ratio;
}
}
- if (expand_area < expanding_total) {
- return get_column_minimum_width(p_column);
+ if (expand_area >= expanding_total && expanding_total > 0) {
+ column_width += expand_area * columns[p_column].expand_ratio / expanding_total;
}
+ }
- ERR_FAIL_COND_V(expanding_columns == 0, -1); // shouldn't happen
- if (expanding_total == 0) {
- return 0;
- } else {
- return expand_area * get_column_minimum_width(p_column) / expanding_total;
- }
- } else {
- return get_column_minimum_width(p_column);
+ if (p_column < columns.size() - 1) {
+ column_width += cache.hseparation;
}
+ return column_width;
}
void Tree::propagate_set_columns(TreeItem *p_item) {
@@ -4547,6 +4635,12 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root);
ClassDB::bind_method(D_METHOD("set_column_custom_minimum_width", "column", "min_width"), &Tree::set_column_custom_minimum_width);
ClassDB::bind_method(D_METHOD("set_column_expand", "column", "expand"), &Tree::set_column_expand);
+ ClassDB::bind_method(D_METHOD("set_column_expand_ratio", "column", "ratio"), &Tree::set_column_expand_ratio);
+ ClassDB::bind_method(D_METHOD("set_column_clip_content", "column", "enable"), &Tree::set_column_clip_content);
+ ClassDB::bind_method(D_METHOD("is_column_expanding", "column"), &Tree::is_column_expanding);
+ ClassDB::bind_method(D_METHOD("is_column_clipping_content", "column"), &Tree::is_column_clipping_content);
+ ClassDB::bind_method(D_METHOD("get_column_expand_ratio", "column"), &Tree::get_column_expand_ratio);
+
ClassDB::bind_method(D_METHOD("get_column_width", "column"), &Tree::get_column_width);
ClassDB::bind_method(D_METHOD("set_hide_root", "enable"), &Tree::set_hide_root);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index fd5fcd7838..10e6642303 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -411,7 +411,9 @@ private:
struct ColumnInfo {
int custom_min_width = 0;
+ int expand_ratio = 1;
bool expand = true;
+ bool clip_content = false;
String title;
Ref<TextLine> text_buf;
Dictionary opentype_features;
@@ -450,7 +452,7 @@ private:
void draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color);
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = nullptr, bool *r_in_range = nullptr, bool p_force_deselect = false);
- int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
+ int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
void _text_editor_submit(String p_text);
void _text_editor_modal_close();
void value_editor_changed(double p_value);
@@ -504,6 +506,7 @@ private:
Color parent_hl_line_color;
Color children_hl_line_color;
Color custom_button_font_highlight;
+ Color font_outline_color;
int hseparation = 0;
int vseparation = 0;
@@ -518,6 +521,7 @@ private:
int draw_guides = 0;
int scroll_border = 0;
int scroll_speed = 0;
+ int font_outline_size = 0;
enum ClickType {
CLICK_NONE,
@@ -540,6 +544,8 @@ private:
Point2i text_editor_position;
+ bool rtl = false;
+
} cache;
int _get_title_button_height() const;
@@ -547,6 +553,7 @@ private:
void _scroll_moved(float p_value);
HScrollBar *h_scroll;
VScrollBar *v_scroll;
+
bool h_scroll_enabled = true;
bool v_scroll_enabled = true;
@@ -632,8 +639,14 @@ public:
void set_column_custom_minimum_width(int p_column, int p_min_width);
void set_column_expand(int p_column, bool p_expand);
+ void set_column_expand_ratio(int p_column, int p_ratio);
+ void set_column_clip_content(int p_column, bool p_fit);
int get_column_minimum_width(int p_column) const;
int get_column_width(int p_column) const;
+ int get_column_expand_ratio(int p_column) const;
+
+ bool is_column_expanding(int p_column) const;
+ bool is_column_clipping_content(int p_column) const;
void set_hide_root(bool p_enabled);
bool is_root_hidden() const;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index db55f4feb7..f81a3ef630 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -1227,7 +1227,7 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
ADD_GROUP("Material", "");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material");
// ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),"set_transform_notify","is_transform_notify_enabled");
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index ac092d9862..787b283e8c 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -507,7 +507,7 @@ bool Node::is_network_master() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
+uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
for (int i = 0; i < data.rpc_methods.size(); i++) {
if (data.rpc_methods[i].name == p_method) {
MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i];
@@ -2493,7 +2493,9 @@ String Node::get_configuration_warnings_as_string() const {
if (i > 0) {
all_warnings += "\n\n";
}
- all_warnings += String(warnings[i]);
+ // Format as a bullet point list to make multiple warnings easier to distinguish
+ // from each other.
+ all_warnings += String::utf8("• ") + String(warnings[i]);
}
return all_warnings;
}
@@ -2621,7 +2623,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer);
ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
diff --git a/scene/main/node.h b/scene/main/node.h
index fc5af43829..c6727ce884 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -430,7 +430,7 @@ public:
int get_network_master() const;
bool is_network_master() const;
- uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
+ uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const;
void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 4b52c4e99f..fefe4c9f0d 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1142,26 +1142,6 @@ Array SceneTree::get_processed_tweens() {
return ret;
}
-void SceneTree::_network_peer_connected(int p_id) {
- emit_signal("network_peer_connected", p_id);
-}
-
-void SceneTree::_network_peer_disconnected(int p_id) {
- emit_signal("network_peer_disconnected", p_id);
-}
-
-void SceneTree::_connected_to_server() {
- emit_signal("connected_to_server");
-}
-
-void SceneTree::_connection_failed() {
- emit_signal("connection_failed");
-}
-
-void SceneTree::_server_disconnected() {
- emit_signal("server_disconnected");
-}
-
Ref<MultiplayerAPI> SceneTree::get_multiplayer() const {
return multiplayer;
}
@@ -1177,58 +1157,8 @@ bool SceneTree::is_multiplayer_poll_enabled() const {
void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
ERR_FAIL_COND(!p_multiplayer.is_valid());
- if (multiplayer.is_valid()) {
- multiplayer->disconnect("network_peer_connected", callable_mp(this, &SceneTree::_network_peer_connected));
- multiplayer->disconnect("network_peer_disconnected", callable_mp(this, &SceneTree::_network_peer_disconnected));
- multiplayer->disconnect("connected_to_server", callable_mp(this, &SceneTree::_connected_to_server));
- multiplayer->disconnect("connection_failed", callable_mp(this, &SceneTree::_connection_failed));
- multiplayer->disconnect("server_disconnected", callable_mp(this, &SceneTree::_server_disconnected));
- }
-
multiplayer = p_multiplayer;
multiplayer->set_root_node(root);
-
- multiplayer->connect("network_peer_connected", callable_mp(this, &SceneTree::_network_peer_connected));
- multiplayer->connect("network_peer_disconnected", callable_mp(this, &SceneTree::_network_peer_disconnected));
- multiplayer->connect("connected_to_server", callable_mp(this, &SceneTree::_connected_to_server));
- multiplayer->connect("connection_failed", callable_mp(this, &SceneTree::_connection_failed));
- multiplayer->connect("server_disconnected", callable_mp(this, &SceneTree::_server_disconnected));
-}
-
-void SceneTree::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer) {
- multiplayer->set_network_peer(p_network_peer);
-}
-
-Ref<NetworkedMultiplayerPeer> SceneTree::get_network_peer() const {
- return multiplayer->get_network_peer();
-}
-
-bool SceneTree::is_network_server() const {
- return multiplayer->is_network_server();
-}
-
-bool SceneTree::has_network_peer() const {
- return multiplayer->has_network_peer();
-}
-
-int SceneTree::get_network_unique_id() const {
- return multiplayer->get_network_unique_id();
-}
-
-Vector<int> SceneTree::get_network_connected_peers() const {
- return multiplayer->get_network_connected_peers();
-}
-
-int SceneTree::get_rpc_sender_id() const {
- return multiplayer->get_rpc_sender_id();
-}
-
-void SceneTree::set_refuse_new_network_connections(bool p_refuse) {
- multiplayer->set_refuse_new_network_connections(p_refuse);
-}
-
-bool SceneTree::is_refusing_new_network_connections() const {
- return multiplayer->is_refusing_new_network_connections();
}
void SceneTree::_bind_methods() {
@@ -1297,24 +1227,12 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer);
ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
- ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer);
- ClassDB::bind_method(D_METHOD("get_network_peer"), &SceneTree::get_network_peer);
- ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);
- ClassDB::bind_method(D_METHOD("has_network_peer"), &SceneTree::has_network_peer);
- ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &SceneTree::get_network_connected_peers);
- ClassDB::bind_method(D_METHOD("get_network_unique_id"), &SceneTree::get_network_unique_id);
- ClassDB::bind_method(D_METHOD("get_rpc_sender_id"), &SceneTree::get_rpc_sender_id);
- ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections);
- ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
- ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", PROPERTY_USAGE_NONE), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_multiplayer", "get_multiplayer");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
@@ -1330,11 +1248,6 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL(MethodInfo("physics_frame"));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen")));
- ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
- ADD_SIGNAL(MethodInfo("connected_to_server"));
- ADD_SIGNAL(MethodInfo("connection_failed"));
- ADD_SIGNAL(MethodInfo("server_disconnected"));
BIND_ENUM_CONSTANT(GROUP_CALL_DEFAULT);
BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE);
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 0e9ffb0f5f..0be0e185a5 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -159,13 +159,6 @@ private:
Ref<MultiplayerAPI> multiplayer;
bool multiplayer_poll = true;
- void _network_peer_connected(int p_id);
- void _network_peer_disconnected(int p_id);
-
- void _connected_to_server();
- void _connection_failed();
- void _server_disconnected();
-
static SceneTree *singleton;
friend class Node;
@@ -337,16 +330,6 @@ public:
void set_multiplayer_poll_enabled(bool p_enabled);
bool is_multiplayer_poll_enabled() const;
void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
- void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer);
- Ref<NetworkedMultiplayerPeer> get_network_peer() const;
- bool is_network_server() const;
- bool has_network_peer() const;
- int get_network_unique_id() const;
- Vector<int> get_network_connected_peers() const;
- int get_rpc_sender_id() const;
-
- void set_refuse_new_network_connections(bool p_refuse);
- bool is_refusing_new_network_connections() const;
static void add_idle_callback(IdleCallback p_callback);
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 3d65c12cb7..d22a6b2875 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -63,7 +63,12 @@ bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_valu
if (o) {
o->override = p_value;
if (active) {
- RS::get_singleton()->global_variable_set_override(*r, p_value);
+ if (o->override.get_type() == Variant::OBJECT) {
+ RID tex_rid = p_value;
+ RS::get_singleton()->global_variable_set_override(*r, tex_rid);
+ } else {
+ RS::get_singleton()->global_variable_set_override(*r, p_value);
+ }
}
o->in_use = p_value.get_type() != Variant::NIL;
return true;
@@ -228,7 +233,12 @@ void ShaderGlobalsOverride::_activate() {
while ((K = overrides.next(K))) {
Override *o = overrides.getptr(*K);
if (o->in_use && o->override.get_type() != Variant::NIL) {
- RS::get_singleton()->global_variable_set_override(*K, o->override);
+ if (o->override.get_type() == Variant::OBJECT) {
+ RID tex_rid = o->override;
+ RS::get_singleton()->global_variable_set_override(*K, tex_rid);
+ } else {
+ RS::get_singleton()->global_variable_set_override(*K, o->override);
+ }
}
}
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index cf2a6b2adf..9299f8d6be 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -227,7 +227,8 @@ void Window::_make_window() {
}
}
- window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), f, Rect2i(position, size));
+ DisplayServer::VSyncMode vsync_mode = DisplayServer::get_singleton()->window_get_vsync_mode(DisplayServer::MAIN_WINDOW_ID);
+ window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size));
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 85bd08529c..ea0df685a1 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -586,6 +586,7 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeTransformDecompose>();
ClassDB::register_class<VisualShaderNodeTexture>();
ClassDB::register_class<VisualShaderNodeCurveTexture>();
+ ClassDB::register_class<VisualShaderNodeCurve3Texture>();
ClassDB::register_virtual_class<VisualShaderNodeSample3D>();
ClassDB::register_class<VisualShaderNodeTexture2DArray>();
ClassDB::register_class<VisualShaderNodeTexture3D>();
@@ -937,14 +938,12 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Physics2DServerSW", "PhysicsServer2DSW");
ClassDB::add_compatibility_class("Physics2DServer", "PhysicsServer2D");
ClassDB::add_compatibility_class("Physics2DShapeQueryParameters", "PhysicsShapeQueryParameters2D");
- ClassDB::add_compatibility_class("Physics2DShapeQueryResult", "PhysicsShapeQueryResult2D");
ClassDB::add_compatibility_class("Physics2DTestMotionResult", "PhysicsTestMotionResult2D");
ClassDB::add_compatibility_class("PhysicsBody", "PhysicsBody3D");
ClassDB::add_compatibility_class("PhysicsDirectBodyState", "PhysicsDirectBodyState3D");
ClassDB::add_compatibility_class("PhysicsDirectSpaceState", "PhysicsDirectSpaceState3D");
ClassDB::add_compatibility_class("PhysicsServer", "PhysicsServer3D");
ClassDB::add_compatibility_class("PhysicsShapeQueryParameters", "PhysicsShapeQueryParameters3D");
- ClassDB::add_compatibility_class("PhysicsShapeQueryResult", "PhysicsShapeQueryResult3D");
ClassDB::add_compatibility_class("PinJoint", "PinJoint3D");
ClassDB::add_compatibility_class("PlaneShape", "WorldMarginShape3D");
ClassDB::add_compatibility_class("ProceduralSky", "Sky");
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index e522ce6774..a264c2d1eb 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -130,7 +130,7 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) {
}
}
if (pr) {
- RenderingServer::get_singleton()->material_set_param(_get_material(), pr, p_value);
+ set_shader_param(pr, p_value);
return true;
}
}
@@ -152,7 +152,12 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const {
}
if (pr) {
- r_ret = RenderingServer::get_singleton()->material_get_param(_get_material(), pr);
+ const Map<StringName, Variant>::Element *E = param_cache.find(pr);
+ if (E) {
+ r_ret = E->get();
+ } else {
+ r_ret = Variant();
+ }
return true;
}
}
@@ -219,11 +224,31 @@ Ref<Shader> ShaderMaterial::get_shader() const {
}
void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) {
- RS::get_singleton()->material_set_param(_get_material(), p_param, p_value);
+ if (p_value.get_type() == Variant::NIL) {
+ param_cache.erase(p_param);
+ RS::get_singleton()->material_set_param(_get_material(), p_param, Variant());
+ } else {
+ param_cache[p_param] = p_value;
+ if (p_value.get_type() == Variant::OBJECT) {
+ RID tex_rid = p_value;
+ if (tex_rid == RID()) {
+ param_cache.erase(p_param);
+ RS::get_singleton()->material_set_param(_get_material(), p_param, Variant());
+ } else {
+ RS::get_singleton()->material_set_param(_get_material(), p_param, tex_rid);
+ }
+ } else {
+ RS::get_singleton()->material_set_param(_get_material(), p_param, p_value);
+ }
+ }
}
Variant ShaderMaterial::get_shader_param(const StringName &p_param) const {
- return RS::get_singleton()->material_get_param(_get_material(), p_param);
+ if (param_cache.has(p_param)) {
+ return param_cache[p_param];
+ } else {
+ return Variant();
+ }
}
void ShaderMaterial::_shader_changed() {
@@ -345,7 +370,6 @@ void BaseMaterial3D::init_shaders() {
shader_names->refraction_texture_channel = "refraction_texture_channel";
shader_names->transmittance_color = "transmittance_color";
- shader_names->transmittance_curve = "transmittance_curve";
shader_names->transmittance_depth = "transmittance_depth";
shader_names->transmittance_boost = "transmittance_boost";
@@ -692,7 +716,6 @@ void BaseMaterial3D::_update_shader() {
code += "uniform vec4 transmittance_color : hint_color;\n";
code += "uniform float transmittance_depth;\n";
code += "uniform sampler2D texture_subsurface_transmittance : hint_white," + texfilter_str + ";\n";
- code += "uniform float transmittance_curve;\n";
code += "uniform float transmittance_boost;\n";
}
@@ -1001,9 +1024,9 @@ void BaseMaterial3D::_update_shader() {
code += "\tSPECULAR = specular;\n";
} else {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
- code += "\tfloat orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n";
+ code += "\tvec4 orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n";
} else {
- code += "\tfloat orm_tex = texture(texture_orm,base_uv);\n";
+ code += "\tvec4 orm_tex = texture(texture_orm,base_uv);\n";
}
code += "\tROUGHNESS = orm_tex.g;\n";
@@ -1194,7 +1217,6 @@ void BaseMaterial3D::_update_shader() {
code += "\tSSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n";
code += "\tSSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n";
- code += "\tSSS_TRANSMITTANCE_CURVE=transmittance_curve;\n";
code += "\tSSS_TRANSMITTANCE_BOOST=transmittance_boost;\n";
}
@@ -1438,15 +1460,6 @@ float BaseMaterial3D::get_transmittance_depth() const {
return transmittance_depth;
}
-void BaseMaterial3D::set_transmittance_curve(float p_curve) {
- transmittance_curve = p_curve;
- RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_curve, p_curve);
-}
-
-float BaseMaterial3D::get_transmittance_curve() const {
- return transmittance_curve;
-}
-
void BaseMaterial3D::set_transmittance_boost(float p_boost) {
transmittance_boost = p_boost;
RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_boost, p_boost);
@@ -1765,7 +1778,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NONE;
}
- if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture" || property.name == "subsurf_scatter_transmittance_curve")) {
+ if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture")) {
property.usage = PROPERTY_USAGE_NONE;
}
@@ -2269,9 +2282,6 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transmittance_depth", "depth"), &BaseMaterial3D::set_transmittance_depth);
ClassDB::bind_method(D_METHOD("get_transmittance_depth"), &BaseMaterial3D::get_transmittance_depth);
- ClassDB::bind_method(D_METHOD("set_transmittance_curve", "curve"), &BaseMaterial3D::set_transmittance_curve);
- ClassDB::bind_method(D_METHOD("get_transmittance_curve"), &BaseMaterial3D::get_transmittance_curve);
-
ClassDB::bind_method(D_METHOD("set_transmittance_boost", "boost"), &BaseMaterial3D::set_transmittance_boost);
ClassDB::bind_method(D_METHOD("get_transmittance_boost"), &BaseMaterial3D::get_transmittance_boost);
@@ -2506,7 +2516,6 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "subsurf_scatter_transmittance_color"), "set_transmittance_color", "get_transmittance_color");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_transmittance_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_TRANSMITTANCE);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_depth", PROPERTY_HINT_RANGE, "0.001,8,0.001,or_greater"), "set_transmittance_depth", "get_transmittance_depth");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_curve", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_transmittance_curve", "get_transmittance_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_boost", PROPERTY_HINT_RANGE, "0.00,1.0,0.01"), "set_transmittance_boost", "get_transmittance_boost");
ADD_GROUP("Back Lighting", "backlight_");
@@ -2723,7 +2732,6 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_backlight(Color(0, 0, 0));
set_transmittance_color(Color(1, 1, 1, 1));
set_transmittance_depth(0.1);
- set_transmittance_curve(1.0);
set_transmittance_boost(0.0);
set_refraction(0.05);
set_point_size(1);
diff --git a/scene/resources/material.h b/scene/resources/material.h
index cd91d05a60..e2838e1399 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -79,6 +79,8 @@ class ShaderMaterial : public Material {
GDCLASS(ShaderMaterial, Material);
Ref<Shader> shader;
+ Map<StringName, Variant> param_cache;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -389,7 +391,6 @@ private:
StringName heightmap_scale;
StringName subsurface_scattering_strength;
StringName transmittance_color;
- StringName transmittance_curve;
StringName transmittance_depth;
StringName transmittance_boost;
StringName backlight;
@@ -458,7 +459,6 @@ private:
float transmittance_amount;
Color transmittance_color;
float transmittance_depth;
- float transmittance_curve;
float transmittance_boost;
Color backlight;
@@ -602,9 +602,6 @@ public:
void set_transmittance_depth(float p_depth);
float get_transmittance_depth() const;
- void set_transmittance_curve(float p_curve);
- float get_transmittance_curve() const;
-
void set_transmittance_boost(float p_boost);
float get_transmittance_boost() const;
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index c5bfbc39db..2f92872ad5 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -30,6 +30,7 @@
#include "mesh.h"
+#include "core/math/convex_hull.h"
#include "core/templates/pair.h"
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
@@ -221,9 +222,17 @@ Vector<Face3> Mesh::get_faces() const {
*/
}
-Ref<Shape3D> Mesh::create_convex_shape() const {
- Vector<Vector3> vertices;
+Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const {
+ if (p_simplify) {
+ Vector<Ref<Shape3D>> decomposed = convex_decompose(1);
+ if (decomposed.size() == 1) {
+ return decomposed[0];
+ } else {
+ ERR_PRINT("Convex shape simplification failed, falling back to simpler process.");
+ }
+ }
+ Vector<Vector3> vertices;
for (int i = 0; i < get_surface_count(); i++) {
Array a = surface_get_arrays(i);
ERR_FAIL_COND_V(a.is_empty(), Ref<ConvexPolygonShape3D>());
@@ -232,6 +241,18 @@ Ref<Shape3D> Mesh::create_convex_shape() const {
}
Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D);
+
+ if (p_clean) {
+ Geometry3D::MeshData md;
+ Error err = ConvexHullComputer::convex_hull(vertices, md);
+ if (err == OK) {
+ shape->set_points(md.vertices);
+ return shape;
+ } else {
+ ERR_PRINT("Convex shape cleaning failed, falling back to simpler process.");
+ }
+ }
+
shape->set_points(vertices);
return shape;
}
@@ -543,12 +564,12 @@ void Mesh::clear_cache() const {
debug_lines.clear();
}
-Vector<Ref<Shape3D>> Mesh::convex_decompose() const {
+Vector<Ref<Shape3D>> Mesh::convex_decompose(int p_max_convex_hulls) const {
ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape3D>>());
const Vector<Face3> faces = get_faces();
- Vector<Vector<Face3>> decomposed = convex_composition_function(faces);
+ Vector<Vector<Face3>> decomposed = convex_composition_function(faces, p_max_convex_hulls);
Vector<Ref<Shape3D>> ret;
@@ -1314,9 +1335,9 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const {
for (int i = 0; i < surfaces.size(); i++) {
p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
if (surfaces[i].is_2d) {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial", PROPERTY_USAGE_EDITOR));
} else {
- p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_EDITOR));
}
}
}
@@ -1852,7 +1873,7 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("surface_set_name", "surf_idx", "name"), &ArrayMesh::surface_set_name);
ClassDB::bind_method(D_METHOD("surface_get_name", "surf_idx"), &ArrayMesh::surface_get_name);
ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape);
- ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape);
+ ClassDB::bind_method(D_METHOD("create_convex_shape", "clean", "simplify"), &ArrayMesh::create_convex_shape, DEFVAL(true), DEFVAL(false));
ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline);
ClassDB::bind_method(D_METHOD("regen_normal_maps"), &ArrayMesh::regen_normal_maps);
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normal_maps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 02cab9a5e1..27b0eb098b 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -149,7 +149,7 @@ public:
void generate_debug_mesh_indices(Vector<Vector3> &r_points);
Ref<Shape3D> create_trimesh_shape() const;
- Ref<Shape3D> create_convex_shape() const;
+ Ref<Shape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const;
Ref<Mesh> create_outline(float p_margin) const;
@@ -159,11 +159,11 @@ public:
Size2i get_lightmap_size_hint() const;
void clear_cache() const;
- typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &);
+ typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &p_faces, int p_max_convex_hulls);
static ConvexDecompositionFunc convex_composition_function;
- Vector<Ref<Shape3D>> convex_decompose() const;
+ Vector<Ref<Shape3D>> convex_decompose(int p_max_convex_hulls = -1) const;
virtual int get_builtin_bind_pose_count() const;
virtual Transform3D get_builtin_bind_pose(int p_index) const;
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index e95df31ccc..2bde98abe0 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -852,52 +852,54 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D
tex_parameters[p_param] = p_texture;
+ RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
+
switch (p_param) {
case PARAM_INITIAL_LINEAR_VELOCITY: {
//do none for this one
} break;
case PARAM_ANGULAR_VELOCITY: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, tex_rid);
_adjust_curve_range(p_texture, -360, 360);
} break;
case PARAM_ORBIT_VELOCITY: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, tex_rid);
_adjust_curve_range(p_texture, -500, 500);
} break;
case PARAM_LINEAR_ACCEL: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, tex_rid);
_adjust_curve_range(p_texture, -200, 200);
} break;
case PARAM_RADIAL_ACCEL: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, tex_rid);
_adjust_curve_range(p_texture, -200, 200);
} break;
case PARAM_TANGENTIAL_ACCEL: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, tex_rid);
_adjust_curve_range(p_texture, -200, 200);
} break;
case PARAM_DAMPING: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, tex_rid);
_adjust_curve_range(p_texture, 0, 100);
} break;
case PARAM_ANGLE: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, tex_rid);
_adjust_curve_range(p_texture, -360, 360);
} break;
case PARAM_SCALE: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, tex_rid);
_adjust_curve_range(p_texture, 0, 1);
} break;
case PARAM_HUE_VARIATION: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, tex_rid);
_adjust_curve_range(p_texture, -1, 1);
} break;
case PARAM_ANIM_SPEED: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, tex_rid);
_adjust_curve_range(p_texture, 0, 200);
} break;
case PARAM_ANIM_OFFSET: {
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture);
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, tex_rid);
} break;
case PARAM_MAX:
break; // Can't happen, but silences warning
@@ -923,7 +925,8 @@ Color ParticlesMaterial::get_color() const {
void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) {
color_ramp = p_texture;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture);
+ RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, tex_rid);
_queue_shader_change();
notify_property_list_changed();
}
@@ -965,17 +968,20 @@ void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) {
void ParticlesMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) {
emission_point_texture = p_points;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points);
+ RID tex_rid = p_points.is_valid() ? p_points->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, tex_rid);
}
void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) {
emission_normal_texture = p_normals;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals);
+ RID tex_rid = p_normals.is_valid() ? p_normals->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, tex_rid);
}
void ParticlesMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) {
emission_color_texture = p_colors;
- RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors);
+ RID tex_rid = p_colors.is_valid() ? p_colors->get_rid() : RID();
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, tex_rid);
_queue_shader_change();
}
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 2b2ebb5c16..dfa45cc810 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -207,7 +207,7 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
}
@@ -714,7 +714,7 @@ int BoxMesh::get_subdivide_depth() const {
BoxMesh::BoxMesh() {}
/**
- CylinderMesh
+ CylinderMesh
*/
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
@@ -955,7 +955,7 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
u /= (subdivide_w + 1.0);
v /= (subdivide_d + 1.0);
- points.push_back(Vector3(-x, 0.0, -z));
+ points.push_back(Vector3(-x, 0.0, -z) + center_offset);
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
@@ -993,10 +993,13 @@ void PlaneMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
+ ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset);
+ ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
}
void PlaneMesh::set_size(const Size2 &p_size) {
@@ -1026,6 +1029,15 @@ int PlaneMesh::get_subdivide_depth() const {
return subdivide_d;
}
+void PlaneMesh::set_center_offset(const Vector3 p_offset) {
+ center_offset = p_offset;
+ _request_update();
+}
+
+Vector3 PlaneMesh::get_center_offset() const {
+ return center_offset;
+}
+
PlaneMesh::PlaneMesh() {}
/**
@@ -1326,10 +1338,10 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f);
Vector3 quad_faces[4] = {
- Vector3(-_size.x, -_size.y, 0),
- Vector3(-_size.x, _size.y, 0),
- Vector3(_size.x, _size.y, 0),
- Vector3(_size.x, -_size.y, 0),
+ Vector3(-_size.x, -_size.y, 0) + center_offset,
+ Vector3(-_size.x, _size.y, 0) + center_offset,
+ Vector3(_size.x, _size.y, 0) + center_offset,
+ Vector3(_size.x, -_size.y, 0) + center_offset,
};
static const int indices[6] = {
@@ -1365,7 +1377,11 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const {
void QuadMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size);
ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size);
+ ClassDB::bind_method(D_METHOD("set_center_offset", "center_offset"), &QuadMesh::set_center_offset);
+ ClassDB::bind_method(D_METHOD("get_center_offset"), &QuadMesh::get_center_offset);
+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
}
QuadMesh::QuadMesh() {
@@ -1381,6 +1397,15 @@ Size2 QuadMesh::get_size() const {
return size;
}
+void QuadMesh::set_center_offset(Vector3 p_center_offset) {
+ center_offset = p_center_offset;
+ _request_update();
+}
+
+Vector3 QuadMesh::get_center_offset() const {
+ return center_offset;
+}
+
/**
SphereMesh
*/
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index bd6f94921e..a3de34d3e3 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -211,6 +211,7 @@ private:
Size2 size = Size2(2.0, 2.0);
int subdivide_w = 0;
int subdivide_d = 0;
+ Vector3 center_offset;
protected:
static void _bind_methods();
@@ -226,6 +227,9 @@ public:
void set_subdivide_depth(const int p_divisions);
int get_subdivide_depth() const;
+ void set_center_offset(const Vector3 p_offset);
+ Vector3 get_center_offset() const;
+
PlaneMesh();
};
@@ -274,6 +278,7 @@ class QuadMesh : public PrimitiveMesh {
private:
Size2 size = Size2(1.0, 1.0);
+ Vector3 center_offset;
protected:
static void _bind_methods();
@@ -284,6 +289,9 @@ public:
void set_size(const Size2 &p_size);
Size2 get_size() const;
+
+ void set_center_offset(const Vector3 p_offset);
+ Vector3 get_center_offset() const;
};
/**
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 9d79c22159..89b3336118 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -270,7 +270,8 @@ ProceduralSkyMaterial::~ProceduralSkyMaterial() {
void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) {
panorama = p_panorama;
- RS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama);
+ RID tex_rid = p_panorama.is_valid() ? p_panorama->get_rid() : RID();
+ RS::get_singleton()->material_set_param(_get_material(), "source_panorama", tex_rid);
}
Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const {
@@ -411,7 +412,8 @@ float PhysicalSkyMaterial::get_dither_strength() const {
void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) {
night_sky = p_night_sky;
- RS::get_singleton()->material_set_param(_get_material(), "night_sky", night_sky);
+ RID tex_rid = p_night_sky.is_valid() ? p_night_sky->get_rid() : RID();
+ RS::get_singleton()->material_set_param(_get_material(), "night_sky", tex_rid);
}
Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index d09a1d9f90..98997e482a 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -1412,7 +1412,7 @@ void CurveTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "RGB,Red"), "set_texture_mode", "get_texture_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
@@ -1559,7 +1559,7 @@ void Curve3Texture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &Curve3Texture::_update);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_x", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_x", "get_curve_x");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_y", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_y", "get_curve_y");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve_z", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve_z", "get_curve_z");
@@ -1762,7 +1762,7 @@ void GradientTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_gradient", "get_gradient");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,4096"), "set_width", "get_width");
}
void GradientTexture::set_gradient(Ref<Gradient> p_gradient) {
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 4f854ff229..deee22f05f 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -2245,22 +2245,22 @@ void TileSet::_bind_methods() {
BIND_ENUM_CONSTANT(TILE_OFFSET_AXIS_HORIZONTAL);
BIND_ENUM_CONSTANT(TILE_OFFSET_AXIS_VERTICAL);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_RIGHT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_RIGHT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_LEFT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_LEFT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_LEFT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_LEFT_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_CORNER);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_RIGHT_SIDE);
- BIND_ENUM_CONSTANT(TileSet::CELL_NEIGHBOR_TOP_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_RIGHT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_BOTTOM_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_LEFT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_LEFT_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_CORNER);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_RIGHT_SIDE);
+ BIND_ENUM_CONSTANT(CELL_NEIGHBOR_TOP_RIGHT_CORNER);
BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_CORNERS_AND_SIDES);
BIND_ENUM_CONSTANT(TERRAIN_MODE_MATCH_CORNERS);
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 54bc7382db..36a1c206c8 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -2708,6 +2708,28 @@ VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_
return UniformType::UNIFORM_TYPE_FLOAT;
}
+VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < uniforms.size()) {
+ switch (uniforms[p_idx].type) {
+ case UniformType::UNIFORM_TYPE_FLOAT:
+ return PORT_TYPE_SCALAR;
+ case UniformType::UNIFORM_TYPE_INT:
+ return PORT_TYPE_SCALAR_INT;
+ case UniformType::UNIFORM_TYPE_SAMPLER:
+ return PORT_TYPE_SAMPLER;
+ case UniformType::UNIFORM_TYPE_VECTOR:
+ return PORT_TYPE_VECTOR;
+ case UniformType::UNIFORM_TYPE_TRANSFORM:
+ return PORT_TYPE_TRANSFORM;
+ case UniformType::UNIFORM_TYPE_COLOR:
+ return PORT_TYPE_VECTOR;
+ default:
+ break;
+ }
+ }
+ return PORT_TYPE_SCALAR;
+}
+
String VisualShaderNodeUniformRef::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 {
switch (uniform_type) {
case UniformType::UNIFORM_TYPE_FLOAT:
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 454012b7ed..880c401b29 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -517,6 +517,7 @@ public:
String get_uniform_name_by_index(int p_idx) const;
UniformType get_uniform_type_by_name(const String &p_name) const;
UniformType get_uniform_type_by_index(int p_idx) const;
+ PortType get_port_type_by_index(int p_idx) const;
virtual Vector<StringName> get_editable_properties() const override;
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index d3b094de31..4e73b8db44 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -805,7 +805,7 @@ void VisualShaderNodeTexture::_bind_methods() {
VisualShaderNodeTexture::VisualShaderNodeTexture() {
}
-////////////// Curve
+////////////// CurveTexture
String VisualShaderNodeCurveTexture::get_caption() const {
return "CurveTexture";
@@ -889,6 +889,90 @@ VisualShaderNodeCurveTexture::VisualShaderNodeCurveTexture() {
allow_v_resize = false;
}
+////////////// Curve3Texture
+
+String VisualShaderNodeCurve3Texture::get_caption() const {
+ return "Curve3Texture";
+}
+
+int VisualShaderNodeCurve3Texture::get_input_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeCurve3Texture::PortType VisualShaderNodeCurve3Texture::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeCurve3Texture::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeCurve3Texture::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeCurve3Texture::PortType VisualShaderNodeCurve3Texture::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR;
+}
+
+String VisualShaderNodeCurve3Texture::get_output_port_name(int p_port) const {
+ return String();
+}
+
+void VisualShaderNodeCurve3Texture::set_texture(Ref<Curve3Texture> p_texture) {
+ texture = p_texture;
+ emit_changed();
+}
+
+Ref<Curve3Texture> VisualShaderNodeCurve3Texture::get_texture() const {
+ return texture;
+}
+
+Vector<StringName> VisualShaderNodeCurve3Texture::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("texture");
+ return props;
+}
+
+String VisualShaderNodeCurve3Texture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return "uniform sampler2D " + make_unique_id(p_type, p_id, "curve3d") + ";\n";
+}
+
+String VisualShaderNodeCurve3Texture::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 {
+ if (p_input_vars[0] == String()) {
+ return "\t" + p_output_vars[0] + " = vec3(0.0);\n";
+ }
+ String id = make_unique_id(p_type, p_id, "curve3d");
+ String code;
+ code += "\t" + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).rgb;\n";
+ return code;
+}
+
+Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurve3Texture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
+ VisualShader::DefaultTextureParam dtp;
+ dtp.name = make_unique_id(p_type, p_id, "curve3d");
+ dtp.param = texture;
+ Vector<VisualShader::DefaultTextureParam> ret;
+ ret.push_back(dtp);
+ return ret;
+}
+
+void VisualShaderNodeCurve3Texture::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &VisualShaderNodeCurve3Texture::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeCurve3Texture::get_texture);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Curve3Texture"), "set_texture", "get_texture");
+}
+
+bool VisualShaderNodeCurve3Texture::is_use_prop_slots() const {
+ return true;
+}
+
+VisualShaderNodeCurve3Texture::VisualShaderNodeCurve3Texture() {
+ simple_decl = true;
+ allow_v_resize = false;
+}
+
////////////// Sample3D
int VisualShaderNodeSample3D::get_input_port_count() const {
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 5b44e9f776..3ae79723e9 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -338,6 +338,39 @@ public:
///////////////////////////////////////
+class VisualShaderNodeCurve3Texture : public VisualShaderNodeResizableBase {
+ GDCLASS(VisualShaderNodeCurve3Texture, VisualShaderNodeResizableBase);
+ Ref<Curve3Texture> texture;
+
+protected:
+ static void _bind_methods();
+
+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 Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) 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;
+
+ void set_texture(Ref<Curve3Texture> p_value);
+ Ref<Curve3Texture> get_texture() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+ virtual bool is_use_prop_slots() const override;
+
+ VisualShaderNodeCurve3Texture();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeSample3D : public VisualShaderNode {
GDCLASS(VisualShaderNodeSample3D, VisualShaderNode);