diff options
Diffstat (limited to 'scene')
55 files changed, 2152 insertions, 1055 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/light_3d.cpp b/scene/3d/light_3d.cpp index 81c0b5bb41..8478821ba1 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -375,15 +375,6 @@ DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const { return shadow_mode; } -void DirectionalLight3D::set_shadow_depth_range(ShadowDepthRange p_range) { - shadow_depth_range = p_range; - RS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, RS::LightDirectionalShadowDepthRangeMode(p_range)); -} - -DirectionalLight3D::ShadowDepthRange DirectionalLight3D::get_shadow_depth_range() const { - return shadow_depth_range; -} - void DirectionalLight3D::set_blend_splits(bool p_enable) { blend_splits = p_enable; RS::get_singleton()->light_directional_set_blend_splits(light, p_enable); @@ -406,9 +397,6 @@ void DirectionalLight3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode); ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode); - ClassDB::bind_method(D_METHOD("set_shadow_depth_range", "mode"), &DirectionalLight3D::set_shadow_depth_range); - ClassDB::bind_method(D_METHOD("get_shadow_depth_range"), &DirectionalLight3D::get_shadow_depth_range); - ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight3D::set_blend_splits); ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight3D::is_blend_splits_enabled); @@ -422,7 +410,6 @@ void DirectionalLight3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_RANGE, "0,8192,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_RANGE, "0,1024,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE); @@ -431,9 +418,6 @@ void DirectionalLight3D::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS); - - BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE); - BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_OPTIMIZED); } DirectionalLight3D::DirectionalLight3D() : @@ -444,7 +428,6 @@ DirectionalLight3D::DirectionalLight3D() : // Leave normal bias untouched as it doesn't benefit DirectionalLight3D as much as OmniLight3D. set_param(PARAM_SHADOW_BIAS, 0.05); set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); - set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE); blend_splits = false; } diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index e145b08b74..d0308a3025 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -149,15 +149,9 @@ public: SHADOW_PARALLEL_4_SPLITS, }; - enum ShadowDepthRange { - SHADOW_DEPTH_RANGE_STABLE = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, - SHADOW_DEPTH_RANGE_OPTIMIZED = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, - }; - private: bool blend_splits; ShadowMode shadow_mode; - ShadowDepthRange shadow_depth_range; bool sky_only = false; protected: @@ -167,9 +161,6 @@ public: void set_shadow_mode(ShadowMode p_mode); ShadowMode get_shadow_mode() const; - void set_shadow_depth_range(ShadowDepthRange p_range); - ShadowDepthRange get_shadow_depth_range() const; - void set_blend_splits(bool p_enable); bool is_blend_splits_enabled() const; @@ -180,7 +171,6 @@ public: }; VARIANT_ENUM_CAST(DirectionalLight3D::ShadowMode) -VARIANT_ENUM_CAST(DirectionalLight3D::ShadowDepthRange) class OmniLight3D : public Light3D { GDCLASS(OmniLight3D, Light3D); 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/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp index 935ec457aa..0871423fbd 100644 --- a/scene/animation/animation_blend_space_2d.cpp +++ b/scene/animation/animation_blend_space_2d.cpp @@ -532,10 +532,10 @@ float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) { float from = 0.0; if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) { //see how much animation remains - from = blend_node(blend_points[closest].name, blend_points[closest].node, p_time, true, 0.0, FILTER_IGNORE, false) - length_internal; + from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, 0.0, FILTER_IGNORE, false); } - mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false) + from; + mind = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, 1.0, FILTER_IGNORE, false); length_internal = from + mind; closest = new_closest; diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 7407ad5b8f..40a49dbb58 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -349,6 +349,7 @@ void BoxContainer::_bind_methods() { MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control *p_control, bool p_expand) { Label *l = memnew(Label); + l->set_theme_type_variation("HeaderSmall"); l->set_text(p_label); add_child(l); MarginContainer *mc = memnew(MarginContainer); 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/control.cpp b/scene/gui/control.cpp index 4063d404d1..718e754514 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -339,13 +339,6 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const { void Control::_get_property_list(List<PropertyInfo> *p_list) const { Ref<Theme> theme = Theme::get_default(); - /* Using the default theme since the properties below are meant for editor only - if (data.theme.is_valid()) { - theme = data.theme; - } else { - theme = Theme::get_default(); - - }*/ { List<StringName> names; @@ -421,6 +414,34 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const { } } +void Control::_validate_property(PropertyInfo &property) const { + if (property.name == "theme_type_variation") { + List<StringName> names; + + // Only the default theme and the project theme are used for the list of options. + // This is an imposed limitation to simplify the logic needed to leverage those options. + Theme::get_default()->get_type_variation_list(get_class_name(), &names); + if (Theme::get_project_default().is_valid()) { + Theme::get_project_default()->get_type_variation_list(get_class_name(), &names); + } + names.sort_custom<StringName::AlphCompare>(); + + Vector<StringName> unique_names; + String hint_string; + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + // Skip duplicate values. + if (unique_names.has(E->get())) { + continue; + } + + hint_string += String(E->get()) + ","; + unique_names.append(E->get()); + } + + property.hint_string = hint_string; + } +} + Control *Control::get_parent_control() const { return data.parent; } @@ -867,18 +888,19 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow } void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { - if (data.theme_custom_type != StringName()) { - p_list->push_back(data.theme_custom_type); + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { + if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) { + Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); + } else { + Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); } - Theme::get_type_dependencies(get_class_name(), p_list); } else { - Theme::get_type_dependencies(p_theme_type, p_list); + Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list); } } Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); if (tex) { return *tex; @@ -891,7 +913,7 @@ Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringNam } Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Ref<StyleBox> *style = data.style_override.getptr(p_name); if (style) { return *style; @@ -904,7 +926,7 @@ Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const String } Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Ref<Font> *font = data.font_override.getptr(p_name); if (font) { return *font; @@ -917,7 +939,7 @@ Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_ } int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const int *font_size = data.font_size_override.getptr(p_name); if (font_size) { return *font_size; @@ -930,7 +952,7 @@ int Control::get_theme_font_size(const StringName &p_name, const StringName &p_t } Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Color *color = data.color_override.getptr(p_name); if (color) { return *color; @@ -943,7 +965,7 @@ Color Control::get_theme_color(const StringName &p_name, const StringName &p_the } int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const int *constant = data.constant_override.getptr(p_name); if (constant) { return *constant; @@ -986,7 +1008,7 @@ bool Control::has_theme_constant_override(const StringName &p_name) const { } bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_icon_override(p_name)) { return true; } @@ -998,7 +1020,7 @@ bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme } bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_stylebox_override(p_name)) { return true; } @@ -1010,7 +1032,7 @@ bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_t } bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_font_override(p_name)) { return true; } @@ -1022,7 +1044,7 @@ bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme } bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_font_size_override(p_name)) { return true; } @@ -1034,7 +1056,7 @@ bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_ } bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_color_override(p_name)) { return true; } @@ -1046,7 +1068,7 @@ bool Control::has_theme_color(const StringName &p_name, const StringName &p_them } bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_custom_type) { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_constant_override(p_name)) { return true; } @@ -1488,7 +1510,7 @@ Point2 Control::get_global_position() const { Point2 Control::get_screen_position() const { ERR_FAIL_COND_V(!is_inside_tree(), Point2()); - Point2 global_pos = get_global_position(); + Point2 global_pos = get_viewport()->get_canvas_transform().xform(get_global_position()); Window *w = Object::cast_to<Window>(get_viewport()); if (w && !w->is_embedding_subwindows()) { global_pos += w->get_position(); @@ -2031,13 +2053,13 @@ Ref<Theme> Control::get_theme() const { return data.theme; } -void Control::set_theme_custom_type(const StringName &p_theme_type) { - data.theme_custom_type = p_theme_type; +void Control::set_theme_type_variation(const StringName &p_theme_type) { + data.theme_type_variation = p_theme_type; _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window); } -StringName Control::get_theme_custom_type() const { - return data.theme_custom_type; +StringName Control::get_theme_type_variation() const { + return data.theme_type_variation; } void Control::set_tooltip(const String &p_tooltip) { @@ -2660,8 +2682,8 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme); - ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Control::set_theme_custom_type); - ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Control::get_theme_custom_type); + ClassDB::bind_method(D_METHOD("set_theme_type_variation", "theme_type"), &Control::set_theme_type_variation); + ClassDB::bind_method(D_METHOD("get_theme_type_variation"), &Control::get_theme_type_variation); ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Control::add_theme_icon_override); ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override); @@ -2810,7 +2832,7 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio"); ADD_GROUP("Theme", "theme_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation"); ADD_GROUP("", ""); BIND_ENUM_CONSTANT(FOCUS_NONE); diff --git a/scene/gui/control.h b/scene/gui/control.h index 0642686a9f..fb01295668 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -202,7 +202,7 @@ private: Ref<Theme> theme; Control *theme_owner = nullptr; Window *theme_owner_window = nullptr; - StringName theme_custom_type; + StringName theme_type_variation; String tooltip; CursorShape default_cursor = CURSOR_ARROW; @@ -279,8 +279,8 @@ protected: void _get_property_list(List<PropertyInfo> *p_list) const; void _notification(int p_notification); - static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const override; //bind helpers @@ -402,8 +402,8 @@ public: void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; - void set_theme_custom_type(const StringName &p_theme_type); - StringName get_theme_custom_type() const; + void set_theme_type_variation(const StringName &p_theme_type); + StringName get_theme_type_variation() const; void set_h_size_flags(int p_flags); int get_h_size_flags() const; diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index f63ae7569f..9d0a6a3380 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -148,11 +148,11 @@ bool AcceptDialog::get_hide_on_ok() const { } void AcceptDialog::set_autowrap(bool p_autowrap) { - label->set_autowrap(p_autowrap); + label->set_autowrap_mode(p_autowrap ? Label::AUTOWRAP_WORD : Label::AUTOWRAP_OFF); } bool AcceptDialog::has_autowrap() { - return label->has_autowrap(); + return label->get_autowrap_mode() != Label::AUTOWRAP_OFF; } void AcceptDialog::register_text_enter(Control *p_line_edit) { @@ -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/label.cpp b/scene/gui/label.cpp index 6580d794d1..78b9ad2569 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -36,20 +36,20 @@ #include "servers/text_server.h" -void Label::set_autowrap(bool p_autowrap) { - if (autowrap != p_autowrap) { - autowrap = p_autowrap; +void Label::set_autowrap_mode(Label::AutowrapMode p_mode) { + if (autowrap_mode != p_mode) { + autowrap_mode = p_mode; lines_dirty = true; } update(); - if (clip) { + if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) { minimum_size_changed(); } } -bool Label::has_autowrap() const { - return autowrap; +Label::AutowrapMode Label::get_autowrap_mode() const { + return autowrap_mode; } void Label::set_uppercase(bool p_uppercase) { @@ -94,24 +94,76 @@ void Label::_shape() { dirty = false; lines_dirty = true; } + + uint8_t overrun_flags = TextServer::OVERRUN_NO_TRIMMING; if (lines_dirty) { for (int i = 0; i < lines_rid.size(); i++) { TS->free(lines_rid[i]); } lines_rid.clear(); - Vector<Vector2i> lines = TS->shaped_text_get_line_breaks(text_rid, width, 0, (autowrap) ? (TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) : TextServer::BREAK_MANDATORY); + uint8_t autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case AUTOWRAP_OFF: + break; + } + Vector<Vector2i> lines = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + for (int i = 0; i < lines.size(); i++) { RID line = TS->shaped_text_substr(text_rid, lines[i].x, lines[i].y - lines[i].x); + + switch (overrun_behavior) { + case OVERRUN_TRIM_WORD_ELLIPSIS: + overrun_flags |= TextServer::OVERRUN_TRIM; + overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; + overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + break; + case OVERRUN_TRIM_ELLIPSIS: + overrun_flags |= TextServer::OVERRUN_TRIM; + overrun_flags |= TextServer::OVERRUN_ADD_ELLIPSIS; + break; + case OVERRUN_TRIM_WORD: + overrun_flags |= TextServer::OVERRUN_TRIM; + overrun_flags |= TextServer::OVERRUN_TRIM_WORD_ONLY; + break; + case OVERRUN_TRIM_CHAR: + overrun_flags |= TextServer::OVERRUN_TRIM; + break; + case OVERRUN_NO_TRIMMING: + break; + } + + if (autowrap_mode == AUTOWRAP_OFF && align != ALIGN_FILL && overrun_behavior != OVERRUN_NO_TRIMMING) { + TS->shaped_text_overrun_trim_to_width(line, width, overrun_flags); + } + lines_rid.push_back(line); } + + if (autowrap_mode != AUTOWRAP_OFF && overrun_behavior != OVERRUN_NO_TRIMMING) { + int visible_lines = get_visible_line_count(); + + if (visible_lines < lines_rid.size() && visible_lines > 0) { + overrun_flags |= TextServer::OVERRUN_ENFORCE_ELLIPSIS; + TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); + } + } } if (xl_text.length() == 0) { minsize = Size2(1, get_line_height()); return; } - if (!autowrap) { + if (autowrap_mode == AUTOWRAP_OFF) { minsize.width = 0.0f; for (int i = 0; i < lines_rid.size(); i++) { if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) { @@ -120,10 +172,21 @@ void Label::_shape() { } } - if (lines_dirty) { // Fill after min_size calculation. + if (lines_dirty) { + // Fill after min_size calculation. if (align == ALIGN_FILL) { for (int i = 0; i < lines_rid.size(); i++) { - TS->shaped_text_fit_to_width(lines_rid.write[i], width); + if (overrun_behavior != OVERRUN_NO_TRIMMING && autowrap_mode == AUTOWRAP_OFF) { + float line_unaltered_width = TS->shaped_text_get_width(lines_rid[i]); + TS->shaped_text_fit_to_width(lines_rid[i], width); + float new_line_width = TS->shaped_text_get_width(lines_rid[i]); + // Begin trimming when there is no space between words available anymore. + if (new_line_width < line_unaltered_width) { + TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); + } + } else { + TS->shaped_text_fit_to_width(lines_rid[i], width); + } } } lines_dirty = false; @@ -131,7 +194,7 @@ void Label::_shape() { _update_visible(); - if (!autowrap || !clip) { + if (autowrap_mode == AUTOWRAP_OFF || !clip || overrun_behavior == OVERRUN_NO_TRIMMING) { minimum_size_changed(); } } @@ -370,13 +433,12 @@ Size2 Label::get_minimum_size() const { min_size.height = MAX(min_size.height, font->get_height(get_theme_font_size("font_size")) + font->get_spacing(Font::SPACING_TOP) + font->get_spacing(Font::SPACING_BOTTOM)); Size2 min_style = get_theme_stylebox("normal")->get_minimum_size(); - if (autowrap) { - return Size2(1, clip ? 1 : min_size.height) + min_style; + if (autowrap_mode != AUTOWRAP_OFF) { + return Size2(1, (clip || overrun_behavior != OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style; } else { - if (clip) { + if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) { min_size.width = 1; } - return min_size + min_style; } } @@ -536,6 +598,21 @@ bool Label::is_clipping_text() const { return clip; } +void Label::set_text_overrun_behavior(Label::OverrunBehavior p_behavior) { + if (overrun_behavior != p_behavior) { + overrun_behavior = p_behavior; + lines_dirty = true; + } + update(); + if (clip || overrun_behavior != OVERRUN_NO_TRIMMING) { + minimum_size_changed(); + } +} + +Label::OverrunBehavior Label::get_text_overrun_behavior() const { + return overrun_behavior; +} + String Label::get_text() const { return text; } @@ -663,10 +740,12 @@ void Label::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label::clear_opentype_features); ClassDB::bind_method(D_METHOD("set_language", "language"), &Label::set_language); ClassDB::bind_method(D_METHOD("get_language"), &Label::get_language); - ClassDB::bind_method(D_METHOD("set_autowrap", "enable"), &Label::set_autowrap); - ClassDB::bind_method(D_METHOD("has_autowrap"), &Label::has_autowrap); + ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label::set_autowrap_mode); + ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Label::get_autowrap_mode); ClassDB::bind_method(D_METHOD("set_clip_text", "enable"), &Label::set_clip_text); ClassDB::bind_method(D_METHOD("is_clipping_text"), &Label::is_clipping_text); + ClassDB::bind_method(D_METHOD("set_text_overrun_behavior", "overrun_behavior"), &Label::set_text_overrun_behavior); + ClassDB::bind_method(D_METHOD("get_text_overrun_behavior"), &Label::get_text_overrun_behavior); ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &Label::set_uppercase); ClassDB::bind_method(D_METHOD("is_uppercase"), &Label::is_uppercase); ClassDB::bind_method(D_METHOD("get_line_height", "line"), &Label::get_line_height, DEFVAL(-1)); @@ -696,13 +775,25 @@ void Label::_bind_methods() { BIND_ENUM_CONSTANT(VALIGN_BOTTOM); BIND_ENUM_CONSTANT(VALIGN_FILL); + BIND_ENUM_CONSTANT(AUTOWRAP_OFF); + BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY); + BIND_ENUM_CONSTANT(AUTOWRAP_WORD); + BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART); + + BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING); + BIND_ENUM_CONSTANT(OVERRUN_TRIM_CHAR); + BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD); + BIND_ENUM_CONSTANT(OVERRUN_TRIM_ELLIPSIS); + BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language"); ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); ADD_PROPERTY(PropertyInfo(Variant::INT, "valign", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_valign", "get_valign"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autowrap"), "set_autowrap", "has_autowrap"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim nothing,Trim characters,Trim words,Ellipsis,Word ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1", PROPERTY_USAGE_EDITOR), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); diff --git a/scene/gui/label.h b/scene/gui/label.h index 032b4112e1..8b48eb9670 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -51,13 +51,29 @@ public: VALIGN_FILL }; + enum AutowrapMode { + AUTOWRAP_OFF, + AUTOWRAP_ARBITRARY, + AUTOWRAP_WORD, + AUTOWRAP_WORD_SMART + }; + + enum OverrunBehavior { + OVERRUN_NO_TRIMMING, + OVERRUN_TRIM_CHAR, + OVERRUN_TRIM_WORD, + OVERRUN_TRIM_ELLIPSIS, + OVERRUN_TRIM_WORD_ELLIPSIS, + }; + private: Align align = ALIGN_LEFT; VAlign valign = VALIGN_TOP; String text; String xl_text; - bool autowrap = false; + AutowrapMode autowrap_mode = AUTOWRAP_OFF; bool clip = false; + OverrunBehavior overrun_behavior = OVERRUN_NO_TRIMMING; Size2 minsize; bool uppercase = false; @@ -118,8 +134,8 @@ public: void set_structured_text_bidi_override_options(Array p_args); Array get_structured_text_bidi_override_options() const; - void set_autowrap(bool p_autowrap); - bool has_autowrap() const; + void set_autowrap_mode(AutowrapMode p_mode); + AutowrapMode get_autowrap_mode() const; void set_uppercase(bool p_uppercase); bool is_uppercase() const; @@ -131,6 +147,9 @@ public: void set_clip_text(bool p_clip); bool is_clipping_text() const; + void set_text_overrun_behavior(OverrunBehavior p_behavior); + OverrunBehavior get_text_overrun_behavior() const; + void set_percent_visible(float p_percent); float get_percent_visible() const; @@ -150,5 +169,7 @@ public: VARIANT_ENUM_CAST(Label::Align); VARIANT_ENUM_CAST(Label::VAlign); +VARIANT_ENUM_CAST(Label::AutowrapMode); +VARIANT_ENUM_CAST(Label::OverrunBehavior); #endif 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/split_container.cpp b/scene/gui/split_container.cpp index df4cf9a740..9796b32c6b 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -38,7 +38,7 @@ Control *SplitContainer::_getch(int p_idx) const { for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c || !c->is_visible_in_tree()) { + if (!c || !c->is_visible()) { continue; } if (c->is_set_as_top_level()) { 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 aac15cd9a5..4d2cb81f23 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -99,39 +99,44 @@ void TreeItem::_change_tree(Tree *p_tree) { c = c->next; } - if (tree && tree->root == this) { - tree->root = nullptr; - } + if (tree) { + if (tree->root == this) { + tree->root = nullptr; + } - if (tree && tree->popup_edited_item == this) { - tree->popup_edited_item = nullptr; - tree->pressing_for_editor = false; - } + if (tree->popup_edited_item == this) { + tree->popup_edited_item = nullptr; + tree->pressing_for_editor = false; + } - if (tree && tree->cache.hover_item == this) { - tree->cache.hover_item = nullptr; - } + if (tree->cache.hover_item == this) { + tree->cache.hover_item = nullptr; + } - if (tree && tree->selected_item == this) { - tree->selected_item = nullptr; - } + if (tree->selected_item == this) { + tree->selected_item = nullptr; + } - if (tree && tree->drop_mode_over == this) { - tree->drop_mode_over = nullptr; - } + if (tree->drop_mode_over == this) { + tree->drop_mode_over = nullptr; + } - if (tree && tree->single_select_defer == this) { - tree->single_select_defer = nullptr; - } + if (tree->single_select_defer == this) { + tree->single_select_defer = nullptr; + } - if (tree && tree->edited_item == this) { - tree->edited_item = nullptr; - tree->pressing_for_editor = false; + if (tree->edited_item == this) { + tree->edited_item = nullptr; + tree->pressing_for_editor = false; + } + + tree->update(); } tree = p_tree; if (tree) { + tree->update(); cells.resize(tree->columns.size()); } } @@ -451,6 +456,7 @@ TreeItem *TreeItem::create_child(int p_idx) { TreeItem *ti = memnew(TreeItem(tree)); if (tree) { ti->cells.resize(tree->columns.size()); + tree->update(); } TreeItem *l_prev = nullptr; @@ -654,11 +660,7 @@ void TreeItem::move_before(TreeItem *p_item) { next = p_item; p_item->prev = this; - if (old_tree && old_tree != tree) { - old_tree->update(); - } - - if (tree) { + if (tree && old_tree == tree) { tree->update(); } } @@ -696,11 +698,7 @@ void TreeItem::move_after(TreeItem *p_item) { parent->children_cache.append(this); } - if (old_tree && old_tree != tree) { - old_tree->update(); - } - - if (tree) { + if (tree && old_tree == tree) { tree->update(); } } @@ -975,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) { @@ -1249,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"); @@ -1510,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; @@ -1556,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; @@ -1680,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) { @@ -2135,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()) { @@ -2164,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); @@ -2189,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); @@ -2204,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; } @@ -2217,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; } @@ -2234,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; @@ -2255,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; } @@ -2465,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 @@ -3143,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) { @@ -3496,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())); @@ -3504,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); } @@ -3515,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); @@ -3761,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; } @@ -3820,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(); @@ -3848,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; @@ -3868,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) { @@ -4549,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/viewport.cpp b/scene/main/viewport.cpp index 319e589036..9a2e0c5230 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3268,8 +3268,8 @@ Viewport::DebugDraw Viewport::get_debug_draw() const { return debug_draw; } -int Viewport::get_render_info(RenderInfo p_info) { - return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfo(p_info)); +int Viewport::get_render_info(RenderInfoType p_type, RenderInfo p_info) { + return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfoType(p_type), RS::ViewportRenderInfo(p_info)); } void Viewport::set_snap_controls_to_pixels(bool p_enable) { @@ -3499,7 +3499,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw); ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw); - ClassDB::bind_method(D_METHOD("get_render_info", "info"), &Viewport::get_render_info); + ClassDB::bind_method(D_METHOD("get_render_info", "type", "info"), &Viewport::get_render_info); ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr); ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr); @@ -3650,13 +3650,14 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(SCREEN_SPACE_AA_MAX); BIND_ENUM_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME); - BIND_ENUM_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME); - BIND_ENUM_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(RENDER_INFO_PRIMITIVES_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME); BIND_ENUM_CONSTANT(RENDER_INFO_MAX); + BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_VISIBLE); + BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_SHADOW); + BIND_ENUM_CONSTANT(RENDER_INFO_TYPE_MAX); + BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLED); BIND_ENUM_CONSTANT(DEBUG_DRAW_UNSHADED); BIND_ENUM_CONSTANT(DEBUG_DRAW_LIGHTING); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 29491a1178..0f3bb8707d 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -115,14 +115,17 @@ public: enum RenderInfo { RENDER_INFO_OBJECTS_IN_FRAME, - RENDER_INFO_VERTICES_IN_FRAME, - RENDER_INFO_MATERIAL_CHANGES_IN_FRAME, - RENDER_INFO_SHADER_CHANGES_IN_FRAME, - RENDER_INFO_SURFACE_CHANGES_IN_FRAME, + RENDER_INFO_PRIMITIVES_IN_FRAME, RENDER_INFO_DRAW_CALLS_IN_FRAME, RENDER_INFO_MAX }; + enum RenderInfoType { + RENDER_INFO_TYPE_VISIBLE, + RENDER_INFO_TYPE_SHADOW, + RENDER_INFO_TYPE_MAX + }; + enum DebugDraw { DEBUG_DRAW_DISABLED, DEBUG_DRAW_UNSHADED, @@ -596,7 +599,7 @@ public: void set_debug_draw(DebugDraw p_debug_draw); DebugDraw get_debug_draw() const; - int get_render_info(RenderInfo p_info); + int get_render_info(RenderInfoType p_type, RenderInfo p_info); void set_snap_controls_to_pixels(bool p_enable); bool is_snap_controls_to_pixels_enabled() const; @@ -699,6 +702,7 @@ VARIANT_ENUM_CAST(Viewport::SDFScale); VARIANT_ENUM_CAST(Viewport::SDFOversize); VARIANT_ENUM_CAST(SubViewport::ClearMode); VARIANT_ENUM_CAST(Viewport::RenderInfo); +VARIANT_ENUM_CAST(Viewport::RenderInfoType); VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter); VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureRepeat); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index d793be1869..c557fd0101 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -115,7 +115,7 @@ Size2i Window::get_max_size() const { void Window::set_min_size(const Size2i &p_min_size) { min_size = p_min_size; - if (window_id != DisplayServer::INVALID_WINDOW_ID) { + if (!wrap_controls && window_id != DisplayServer::INVALID_WINDOW_ID) { DisplayServer::get_singleton()->window_set_min_size(min_size, window_id); } _update_window_size(); @@ -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); @@ -541,6 +542,7 @@ void Window::_update_window_size() { embedder->_sub_window_update(this); } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { DisplayServer::get_singleton()->window_set_size(size, window_id); + DisplayServer::get_singleton()->window_set_min_size(size_limit, window_id); } //update the viewport @@ -1169,23 +1171,24 @@ Ref<Theme> Window::get_theme() const { return theme; } -void Window::set_theme_custom_type(const StringName &p_theme_type) { - theme_custom_type = p_theme_type; +void Window::set_theme_type_variation(const StringName &p_theme_type) { + theme_type_variation = p_theme_type; Control::_propagate_theme_changed(this, theme_owner, theme_owner_window); } -StringName Window::get_theme_custom_type() const { - return theme_custom_type; +StringName Window::get_theme_type_variation() const { + return theme_type_variation; } void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { - if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_custom_type) { - if (theme_custom_type != StringName()) { - p_list->push_back(theme_custom_type); + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(theme_type_variation) != StringName()) { + Theme::get_project_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list); + } else { + Theme::get_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list); } - Theme::get_type_dependencies(get_class_name(), p_list); } else { - Theme::get_type_dependencies(p_theme_type, p_list); + Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list); } } @@ -1339,6 +1342,34 @@ bool Window::is_layout_rtl() const { } } +void Window::_validate_property(PropertyInfo &property) const { + if (property.name == "theme_type_variation") { + List<StringName> names; + + // Only the default theme and the project theme are used for the list of options. + // This is an imposed limitation to simplify the logic needed to leverage those options. + Theme::get_default()->get_type_variation_list(get_class_name(), &names); + if (Theme::get_project_default().is_valid()) { + Theme::get_project_default()->get_type_variation_list(get_class_name(), &names); + } + names.sort_custom<StringName::AlphCompare>(); + + Vector<StringName> unique_names; + String hint_string; + for (List<StringName>::Element *E = names.front(); E; E = E->next()) { + // Skip duplicate values. + if (unique_names.has(E->get())) { + continue; + } + + hint_string += String(E->get()) + ","; + unique_names.append(E->get()); + } + + property.hint_string = hint_string; + } +} + void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title); ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title); @@ -1393,6 +1424,8 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("is_embedded"), &Window::is_embedded); + ClassDB::bind_method(D_METHOD("get_contents_minimum_size"), &Window::get_contents_minimum_size); + ClassDB::bind_method(D_METHOD("set_content_scale_size", "size"), &Window::set_content_scale_size); ClassDB::bind_method(D_METHOD("get_content_scale_size"), &Window::get_content_scale_size); @@ -1414,8 +1447,8 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme); - ClassDB::bind_method(D_METHOD("set_theme_custom_type", "theme_type"), &Window::set_theme_custom_type); - ClassDB::bind_method(D_METHOD("get_theme_custom_type"), &Window::get_theme_custom_type); + ClassDB::bind_method(D_METHOD("set_theme_type_variation", "theme_type"), &Window::set_theme_type_variation); + ClassDB::bind_method(D_METHOD("get_theme_type_variation"), &Window::get_theme_type_variation); ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Window::get_theme_icon, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Window::get_theme_stylebox, DEFVAL("")); @@ -1465,7 +1498,7 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect"); ADD_GROUP("Theme", "theme_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation"); ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"))); diff --git a/scene/main/window.h b/scene/main/window.h index 494c386606..e92b5e22ed 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -130,7 +130,7 @@ private: Ref<Theme> theme; Control *theme_owner = nullptr; Window *theme_owner_window = nullptr; - StringName theme_custom_type; + StringName theme_type_variation; Viewport *embedder = nullptr; @@ -151,6 +151,7 @@ protected: virtual Size2 _get_contents_minimum_size() const; static void _bind_methods(); void _notification(int p_what); + virtual void _validate_property(PropertyInfo &property) const override; virtual void add_child_notify(Node *p_child) override; virtual void remove_child_notify(Node *p_child) override; @@ -242,8 +243,8 @@ public: void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; - void set_theme_custom_type(const StringName &p_theme_type); - StringName get_theme_custom_type() const; + void set_theme_type_variation(const StringName &p_theme_type); + StringName get_theme_type_variation() const; _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const; Size2 get_contents_minimum_size() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index d069d5e963..9efe5c58fc 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -292,108 +292,108 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<Object>(); + GDREGISTER_CLASS(Object); - ClassDB::register_class<Node>(); - ClassDB::register_virtual_class<InstancePlaceholder>(); + GDREGISTER_CLASS(Node); + GDREGISTER_VIRTUAL_CLASS(InstancePlaceholder); - ClassDB::register_virtual_class<Viewport>(); - ClassDB::register_class<SubViewport>(); - ClassDB::register_class<ViewportTexture>(); - ClassDB::register_class<HTTPRequest>(); - ClassDB::register_class<Timer>(); - ClassDB::register_class<CanvasLayer>(); - ClassDB::register_class<CanvasModulate>(); - ClassDB::register_class<ResourcePreloader>(); - ClassDB::register_class<Window>(); + GDREGISTER_VIRTUAL_CLASS(Viewport); + GDREGISTER_CLASS(SubViewport); + GDREGISTER_CLASS(ViewportTexture); + GDREGISTER_CLASS(HTTPRequest); + GDREGISTER_CLASS(Timer); + GDREGISTER_CLASS(CanvasLayer); + GDREGISTER_CLASS(CanvasModulate); + GDREGISTER_CLASS(ResourcePreloader); + GDREGISTER_CLASS(Window); /* REGISTER GUI */ - ClassDB::register_class<ButtonGroup>(); - ClassDB::register_virtual_class<BaseButton>(); + GDREGISTER_CLASS(ButtonGroup); + GDREGISTER_VIRTUAL_CLASS(BaseButton); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<Shortcut>(); - ClassDB::register_class<Control>(); - ClassDB::register_class<Button>(); - ClassDB::register_class<Label>(); - ClassDB::register_virtual_class<ScrollBar>(); - ClassDB::register_class<HScrollBar>(); - ClassDB::register_class<VScrollBar>(); - ClassDB::register_class<ProgressBar>(); - ClassDB::register_virtual_class<Slider>(); - ClassDB::register_class<HSlider>(); - ClassDB::register_class<VSlider>(); - ClassDB::register_class<Popup>(); - ClassDB::register_class<PopupPanel>(); - ClassDB::register_class<MenuButton>(); - ClassDB::register_class<CheckBox>(); - ClassDB::register_class<CheckButton>(); - ClassDB::register_class<LinkButton>(); - ClassDB::register_class<Panel>(); - ClassDB::register_virtual_class<Range>(); + GDREGISTER_CLASS(Shortcut); + GDREGISTER_CLASS(Control); + GDREGISTER_CLASS(Button); + GDREGISTER_CLASS(Label); + GDREGISTER_VIRTUAL_CLASS(ScrollBar); + GDREGISTER_CLASS(HScrollBar); + GDREGISTER_CLASS(VScrollBar); + GDREGISTER_CLASS(ProgressBar); + GDREGISTER_VIRTUAL_CLASS(Slider); + GDREGISTER_CLASS(HSlider); + GDREGISTER_CLASS(VSlider); + GDREGISTER_CLASS(Popup); + GDREGISTER_CLASS(PopupPanel); + GDREGISTER_CLASS(MenuButton); + GDREGISTER_CLASS(CheckBox); + GDREGISTER_CLASS(CheckButton); + GDREGISTER_CLASS(LinkButton); + GDREGISTER_CLASS(Panel); + GDREGISTER_VIRTUAL_CLASS(Range); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<TextureRect>(); - ClassDB::register_class<ColorRect>(); - ClassDB::register_class<NinePatchRect>(); - ClassDB::register_class<ReferenceRect>(); - ClassDB::register_class<AspectRatioContainer>(); - ClassDB::register_class<TabContainer>(); - ClassDB::register_class<Tabs>(); - ClassDB::register_virtual_class<Separator>(); - ClassDB::register_class<HSeparator>(); - ClassDB::register_class<VSeparator>(); - ClassDB::register_class<TextureButton>(); - ClassDB::register_class<Container>(); - ClassDB::register_virtual_class<BoxContainer>(); - ClassDB::register_class<HBoxContainer>(); - ClassDB::register_class<VBoxContainer>(); - ClassDB::register_class<GridContainer>(); - ClassDB::register_class<CenterContainer>(); - ClassDB::register_class<ScrollContainer>(); - ClassDB::register_class<PanelContainer>(); + GDREGISTER_CLASS(TextureRect); + GDREGISTER_CLASS(ColorRect); + GDREGISTER_CLASS(NinePatchRect); + GDREGISTER_CLASS(ReferenceRect); + GDREGISTER_CLASS(AspectRatioContainer); + GDREGISTER_CLASS(TabContainer); + GDREGISTER_CLASS(Tabs); + GDREGISTER_VIRTUAL_CLASS(Separator); + GDREGISTER_CLASS(HSeparator); + GDREGISTER_CLASS(VSeparator); + GDREGISTER_CLASS(TextureButton); + GDREGISTER_CLASS(Container); + GDREGISTER_VIRTUAL_CLASS(BoxContainer); + GDREGISTER_CLASS(HBoxContainer); + GDREGISTER_CLASS(VBoxContainer); + GDREGISTER_CLASS(GridContainer); + GDREGISTER_CLASS(CenterContainer); + GDREGISTER_CLASS(ScrollContainer); + GDREGISTER_CLASS(PanelContainer); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<TextureProgressBar>(); - ClassDB::register_class<ItemList>(); + GDREGISTER_CLASS(TextureProgressBar); + GDREGISTER_CLASS(ItemList); - ClassDB::register_class<LineEdit>(); - ClassDB::register_class<VideoPlayer>(); + GDREGISTER_CLASS(LineEdit); + GDREGISTER_CLASS(VideoPlayer); #ifndef ADVANCED_GUI_DISABLED - ClassDB::register_class<FileDialog>(); - - ClassDB::register_class<PopupMenu>(); - ClassDB::register_class<Tree>(); - - ClassDB::register_class<TextEdit>(); - ClassDB::register_class<CodeEdit>(); - ClassDB::register_class<SyntaxHighlighter>(); - ClassDB::register_class<CodeHighlighter>(); - - ClassDB::register_virtual_class<TreeItem>(); - ClassDB::register_class<OptionButton>(); - ClassDB::register_class<SpinBox>(); - ClassDB::register_class<ColorPicker>(); - ClassDB::register_class<ColorPickerButton>(); - ClassDB::register_class<RichTextLabel>(); - ClassDB::register_class<RichTextEffect>(); - ClassDB::register_class<CharFXTransform>(); - - ClassDB::register_class<AcceptDialog>(); - ClassDB::register_class<ConfirmationDialog>(); - - ClassDB::register_class<MarginContainer>(); - ClassDB::register_class<SubViewportContainer>(); - ClassDB::register_virtual_class<SplitContainer>(); - ClassDB::register_class<HSplitContainer>(); - ClassDB::register_class<VSplitContainer>(); - ClassDB::register_class<GraphNode>(); - ClassDB::register_class<GraphEdit>(); + GDREGISTER_CLASS(FileDialog); + + GDREGISTER_CLASS(PopupMenu); + GDREGISTER_CLASS(Tree); + + GDREGISTER_CLASS(TextEdit); + GDREGISTER_CLASS(CodeEdit); + GDREGISTER_CLASS(SyntaxHighlighter); + GDREGISTER_CLASS(CodeHighlighter); + + GDREGISTER_VIRTUAL_CLASS(TreeItem); + GDREGISTER_CLASS(OptionButton); + GDREGISTER_CLASS(SpinBox); + GDREGISTER_CLASS(ColorPicker); + GDREGISTER_CLASS(ColorPickerButton); + GDREGISTER_CLASS(RichTextLabel); + GDREGISTER_CLASS(RichTextEffect); + GDREGISTER_CLASS(CharFXTransform); + + GDREGISTER_CLASS(AcceptDialog); + GDREGISTER_CLASS(ConfirmationDialog); + + GDREGISTER_CLASS(MarginContainer); + GDREGISTER_CLASS(SubViewportContainer); + GDREGISTER_VIRTUAL_CLASS(SplitContainer); + GDREGISTER_CLASS(HSplitContainer); + GDREGISTER_CLASS(VSplitContainer); + GDREGISTER_CLASS(GraphNode); + GDREGISTER_CLASS(GraphEdit); OS::get_singleton()->yield(); //may take time to init @@ -406,449 +406,451 @@ void register_scene_types() { /* REGISTER ANIMATION */ - ClassDB::register_class<AnimationPlayer>(); - ClassDB::register_class<Tween>(); - ClassDB::register_virtual_class<Tweener>(); - ClassDB::register_class<PropertyTweener>(); - ClassDB::register_class<IntervalTweener>(); - ClassDB::register_class<CallbackTweener>(); - ClassDB::register_class<MethodTweener>(); - - ClassDB::register_class<AnimationTree>(); - ClassDB::register_class<AnimationNode>(); - ClassDB::register_class<AnimationRootNode>(); - ClassDB::register_class<AnimationNodeBlendTree>(); - ClassDB::register_class<AnimationNodeBlendSpace1D>(); - ClassDB::register_class<AnimationNodeBlendSpace2D>(); - ClassDB::register_class<AnimationNodeStateMachine>(); - ClassDB::register_class<AnimationNodeStateMachinePlayback>(); - - ClassDB::register_class<AnimationNodeStateMachineTransition>(); - ClassDB::register_class<AnimationNodeOutput>(); - ClassDB::register_class<AnimationNodeOneShot>(); - ClassDB::register_class<AnimationNodeAnimation>(); - ClassDB::register_class<AnimationNodeAdd2>(); - ClassDB::register_class<AnimationNodeAdd3>(); - ClassDB::register_class<AnimationNodeBlend2>(); - ClassDB::register_class<AnimationNodeBlend3>(); - ClassDB::register_class<AnimationNodeTimeScale>(); - ClassDB::register_class<AnimationNodeTimeSeek>(); - ClassDB::register_class<AnimationNodeTransition>(); - - ClassDB::register_class<ShaderGlobalsOverride>(); //can be used in any shader + GDREGISTER_CLASS(AnimationPlayer); + GDREGISTER_CLASS(Tween); + GDREGISTER_VIRTUAL_CLASS(Tweener); + GDREGISTER_CLASS(PropertyTweener); + GDREGISTER_CLASS(IntervalTweener); + GDREGISTER_CLASS(CallbackTweener); + GDREGISTER_CLASS(MethodTweener); + + GDREGISTER_CLASS(AnimationTree); + GDREGISTER_CLASS(AnimationNode); + GDREGISTER_CLASS(AnimationRootNode); + GDREGISTER_CLASS(AnimationNodeBlendTree); + GDREGISTER_CLASS(AnimationNodeBlendSpace1D); + GDREGISTER_CLASS(AnimationNodeBlendSpace2D); + GDREGISTER_CLASS(AnimationNodeStateMachine); + GDREGISTER_CLASS(AnimationNodeStateMachinePlayback); + + GDREGISTER_CLASS(AnimationNodeStateMachineTransition); + GDREGISTER_CLASS(AnimationNodeOutput); + GDREGISTER_CLASS(AnimationNodeOneShot); + GDREGISTER_CLASS(AnimationNodeAnimation); + GDREGISTER_CLASS(AnimationNodeAdd2); + GDREGISTER_CLASS(AnimationNodeAdd3); + GDREGISTER_CLASS(AnimationNodeBlend2); + GDREGISTER_CLASS(AnimationNodeBlend3); + GDREGISTER_CLASS(AnimationNodeTimeScale); + GDREGISTER_CLASS(AnimationNodeTimeSeek); + GDREGISTER_CLASS(AnimationNodeTransition); + + GDREGISTER_CLASS(ShaderGlobalsOverride); //can be used in any shader OS::get_singleton()->yield(); //may take time to init /* REGISTER 3D */ #ifndef _3D_DISABLED - ClassDB::register_class<Node3D>(); - ClassDB::register_virtual_class<Node3DGizmo>(); - ClassDB::register_class<Skin>(); - ClassDB::register_virtual_class<SkinReference>(); - ClassDB::register_class<Skeleton3D>(); - ClassDB::register_virtual_class<VisualInstance3D>(); - ClassDB::register_virtual_class<GeometryInstance3D>(); - ClassDB::register_class<Camera3D>(); - ClassDB::register_class<ClippedCamera3D>(); - ClassDB::register_class<Listener3D>(); - ClassDB::register_class<XRCamera3D>(); - ClassDB::register_class<XRController3D>(); - ClassDB::register_class<XRAnchor3D>(); - ClassDB::register_class<XROrigin3D>(); - ClassDB::register_class<MeshInstance3D>(); - ClassDB::register_class<OccluderInstance3D>(); - ClassDB::register_class<Occluder3D>(); - ClassDB::register_virtual_class<SpriteBase3D>(); - ClassDB::register_class<Sprite3D>(); - ClassDB::register_class<AnimatedSprite3D>(); - ClassDB::register_virtual_class<Light3D>(); - ClassDB::register_class<DirectionalLight3D>(); - ClassDB::register_class<OmniLight3D>(); - ClassDB::register_class<SpotLight3D>(); - ClassDB::register_class<ReflectionProbe>(); - ClassDB::register_class<Decal>(); - ClassDB::register_class<VoxelGI>(); - ClassDB::register_class<VoxelGIData>(); - ClassDB::register_class<LightmapGI>(); - ClassDB::register_class<LightmapGIData>(); - ClassDB::register_class<LightmapProbe>(); - ClassDB::register_virtual_class<Lightmapper>(); - ClassDB::register_class<GPUParticles3D>(); - ClassDB::register_virtual_class<GPUParticlesCollision3D>(); - ClassDB::register_class<GPUParticlesCollisionBox>(); - ClassDB::register_class<GPUParticlesCollisionSphere>(); - ClassDB::register_class<GPUParticlesCollisionSDF>(); - ClassDB::register_class<GPUParticlesCollisionHeightField>(); - ClassDB::register_virtual_class<GPUParticlesAttractor3D>(); - ClassDB::register_class<GPUParticlesAttractorBox>(); - ClassDB::register_class<GPUParticlesAttractorSphere>(); - ClassDB::register_class<GPUParticlesAttractorVectorField>(); - ClassDB::register_class<CPUParticles3D>(); - ClassDB::register_class<Position3D>(); - - ClassDB::register_class<RootMotionView>(); + GDREGISTER_CLASS(Node3D); + GDREGISTER_VIRTUAL_CLASS(Node3DGizmo); + GDREGISTER_CLASS(Skin); + GDREGISTER_VIRTUAL_CLASS(SkinReference); + GDREGISTER_CLASS(Skeleton3D); + GDREGISTER_VIRTUAL_CLASS(VisualInstance3D); + GDREGISTER_VIRTUAL_CLASS(GeometryInstance3D); + GDREGISTER_CLASS(Camera3D); + GDREGISTER_CLASS(ClippedCamera3D); + GDREGISTER_CLASS(Listener3D); + GDREGISTER_CLASS(XRCamera3D); + GDREGISTER_CLASS(XRController3D); + GDREGISTER_CLASS(XRAnchor3D); + GDREGISTER_CLASS(XROrigin3D); + GDREGISTER_CLASS(MeshInstance3D); + GDREGISTER_CLASS(OccluderInstance3D); + GDREGISTER_CLASS(Occluder3D); + GDREGISTER_VIRTUAL_CLASS(SpriteBase3D); + GDREGISTER_CLASS(Sprite3D); + GDREGISTER_CLASS(AnimatedSprite3D); + GDREGISTER_VIRTUAL_CLASS(Light3D); + GDREGISTER_CLASS(DirectionalLight3D); + GDREGISTER_CLASS(OmniLight3D); + GDREGISTER_CLASS(SpotLight3D); + GDREGISTER_CLASS(ReflectionProbe); + GDREGISTER_CLASS(Decal); + GDREGISTER_CLASS(VoxelGI); + GDREGISTER_CLASS(VoxelGIData); + GDREGISTER_CLASS(LightmapGI); + GDREGISTER_CLASS(LightmapGIData); + GDREGISTER_CLASS(LightmapProbe); + GDREGISTER_VIRTUAL_CLASS(Lightmapper); + GDREGISTER_CLASS(GPUParticles3D); + GDREGISTER_VIRTUAL_CLASS(GPUParticlesCollision3D); + GDREGISTER_CLASS(GPUParticlesCollisionBox); + GDREGISTER_CLASS(GPUParticlesCollisionSphere); + GDREGISTER_CLASS(GPUParticlesCollisionSDF); + GDREGISTER_CLASS(GPUParticlesCollisionHeightField); + GDREGISTER_VIRTUAL_CLASS(GPUParticlesAttractor3D); + GDREGISTER_CLASS(GPUParticlesAttractorBox); + GDREGISTER_CLASS(GPUParticlesAttractorSphere); + GDREGISTER_CLASS(GPUParticlesAttractorVectorField); + GDREGISTER_CLASS(CPUParticles3D); + GDREGISTER_CLASS(Position3D); + + GDREGISTER_CLASS(RootMotionView); ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class<CollisionObject3D>(); - ClassDB::register_virtual_class<PhysicsBody3D>(); - ClassDB::register_class<StaticBody3D>(); - ClassDB::register_class<RigidBody3D>(); - ClassDB::register_class<KinematicCollision3D>(); - ClassDB::register_class<CharacterBody3D>(); - ClassDB::register_class<SpringArm3D>(); - - ClassDB::register_class<PhysicalBone3D>(); - ClassDB::register_class<SoftBody3D>(); - - ClassDB::register_class<SkeletonIK3D>(); - ClassDB::register_class<BoneAttachment3D>(); - - ClassDB::register_class<VehicleBody3D>(); - ClassDB::register_class<VehicleWheel3D>(); - ClassDB::register_class<Area3D>(); - ClassDB::register_class<ProximityGroup3D>(); - ClassDB::register_class<CollisionShape3D>(); - ClassDB::register_class<CollisionPolygon3D>(); - ClassDB::register_class<RayCast3D>(); - ClassDB::register_class<MultiMeshInstance3D>(); - - ClassDB::register_class<Curve3D>(); - ClassDB::register_class<Path3D>(); - ClassDB::register_class<PathFollow3D>(); - ClassDB::register_class<VisibleOnScreenNotifier3D>(); - ClassDB::register_class<VisibleOnScreenEnabler3D>(); - ClassDB::register_class<WorldEnvironment>(); - ClassDB::register_class<RemoteTransform3D>(); - - ClassDB::register_virtual_class<Joint3D>(); - ClassDB::register_class<PinJoint3D>(); - ClassDB::register_class<HingeJoint3D>(); - ClassDB::register_class<SliderJoint3D>(); - ClassDB::register_class<ConeTwistJoint3D>(); - ClassDB::register_class<Generic6DOFJoint3D>(); - - ClassDB::register_class<NavigationRegion3D>(); - ClassDB::register_class<NavigationAgent3D>(); - ClassDB::register_class<NavigationObstacle3D>(); + GDREGISTER_VIRTUAL_CLASS(CollisionObject3D); + GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D); + GDREGISTER_CLASS(StaticBody3D); + GDREGISTER_CLASS(RigidBody3D); + GDREGISTER_CLASS(KinematicCollision3D); + GDREGISTER_CLASS(CharacterBody3D); + GDREGISTER_CLASS(SpringArm3D); + + GDREGISTER_CLASS(PhysicalBone3D); + GDREGISTER_CLASS(SoftBody3D); + + GDREGISTER_CLASS(SkeletonIK3D); + GDREGISTER_CLASS(BoneAttachment3D); + + GDREGISTER_CLASS(VehicleBody3D); + GDREGISTER_CLASS(VehicleWheel3D); + GDREGISTER_CLASS(Area3D); + GDREGISTER_CLASS(ProximityGroup3D); + GDREGISTER_CLASS(CollisionShape3D); + GDREGISTER_CLASS(CollisionPolygon3D); + GDREGISTER_CLASS(RayCast3D); + GDREGISTER_CLASS(MultiMeshInstance3D); + + GDREGISTER_CLASS(Curve3D); + GDREGISTER_CLASS(Path3D); + GDREGISTER_CLASS(PathFollow3D); + GDREGISTER_CLASS(VisibleOnScreenNotifier3D); + GDREGISTER_CLASS(VisibleOnScreenEnabler3D); + GDREGISTER_CLASS(WorldEnvironment); + GDREGISTER_CLASS(RemoteTransform3D); + + GDREGISTER_VIRTUAL_CLASS(Joint3D); + GDREGISTER_CLASS(PinJoint3D); + GDREGISTER_CLASS(HingeJoint3D); + GDREGISTER_CLASS(SliderJoint3D); + GDREGISTER_CLASS(ConeTwistJoint3D); + GDREGISTER_CLASS(Generic6DOFJoint3D); + + GDREGISTER_CLASS(NavigationRegion3D); + GDREGISTER_CLASS(NavigationAgent3D); + GDREGISTER_CLASS(NavigationObstacle3D); OS::get_singleton()->yield(); //may take time to init #endif /* REGISTER SHADER */ - ClassDB::register_class<Shader>(); - ClassDB::register_class<VisualShader>(); - ClassDB::register_virtual_class<VisualShaderNode>(); - ClassDB::register_class<VisualShaderNodeCustom>(); - ClassDB::register_class<VisualShaderNodeInput>(); - ClassDB::register_virtual_class<VisualShaderNodeOutput>(); - ClassDB::register_virtual_class<VisualShaderNodeResizableBase>(); - ClassDB::register_virtual_class<VisualShaderNodeGroupBase>(); - ClassDB::register_virtual_class<VisualShaderNodeConstant>(); - ClassDB::register_class<VisualShaderNodeComment>(); - ClassDB::register_class<VisualShaderNodeFloatConstant>(); - ClassDB::register_class<VisualShaderNodeIntConstant>(); - ClassDB::register_class<VisualShaderNodeBooleanConstant>(); - ClassDB::register_class<VisualShaderNodeColorConstant>(); - ClassDB::register_class<VisualShaderNodeVec3Constant>(); - ClassDB::register_class<VisualShaderNodeTransformConstant>(); - ClassDB::register_class<VisualShaderNodeFloatOp>(); - ClassDB::register_class<VisualShaderNodeIntOp>(); - ClassDB::register_class<VisualShaderNodeVectorOp>(); - ClassDB::register_class<VisualShaderNodeColorOp>(); - ClassDB::register_class<VisualShaderNodeTransformMult>(); - ClassDB::register_class<VisualShaderNodeTransformVecMult>(); - ClassDB::register_class<VisualShaderNodeFloatFunc>(); - ClassDB::register_class<VisualShaderNodeIntFunc>(); - ClassDB::register_class<VisualShaderNodeVectorFunc>(); - ClassDB::register_class<VisualShaderNodeColorFunc>(); - ClassDB::register_class<VisualShaderNodeTransformFunc>(); - ClassDB::register_class<VisualShaderNodeUVFunc>(); - ClassDB::register_class<VisualShaderNodeDotProduct>(); - ClassDB::register_class<VisualShaderNodeVectorLen>(); - ClassDB::register_class<VisualShaderNodeDeterminant>(); - ClassDB::register_class<VisualShaderNodeScalarDerivativeFunc>(); - ClassDB::register_class<VisualShaderNodeVectorDerivativeFunc>(); - ClassDB::register_class<VisualShaderNodeClamp>(); - ClassDB::register_class<VisualShaderNodeFaceForward>(); - ClassDB::register_class<VisualShaderNodeOuterProduct>(); - ClassDB::register_class<VisualShaderNodeSmoothStep>(); - ClassDB::register_class<VisualShaderNodeStep>(); - ClassDB::register_class<VisualShaderNodeVectorDistance>(); - ClassDB::register_class<VisualShaderNodeVectorRefract>(); - ClassDB::register_class<VisualShaderNodeMix>(); - ClassDB::register_class<VisualShaderNodeVectorCompose>(); - ClassDB::register_class<VisualShaderNodeTransformCompose>(); - ClassDB::register_class<VisualShaderNodeVectorDecompose>(); - ClassDB::register_class<VisualShaderNodeTransformDecompose>(); - ClassDB::register_class<VisualShaderNodeTexture>(); - ClassDB::register_class<VisualShaderNodeCurveTexture>(); - ClassDB::register_virtual_class<VisualShaderNodeSample3D>(); - ClassDB::register_class<VisualShaderNodeTexture2DArray>(); - ClassDB::register_class<VisualShaderNodeTexture3D>(); - ClassDB::register_class<VisualShaderNodeCubemap>(); - ClassDB::register_virtual_class<VisualShaderNodeUniform>(); - ClassDB::register_class<VisualShaderNodeUniformRef>(); - ClassDB::register_class<VisualShaderNodeFloatUniform>(); - ClassDB::register_class<VisualShaderNodeIntUniform>(); - ClassDB::register_class<VisualShaderNodeBooleanUniform>(); - ClassDB::register_class<VisualShaderNodeColorUniform>(); - ClassDB::register_class<VisualShaderNodeVec3Uniform>(); - ClassDB::register_class<VisualShaderNodeTransformUniform>(); - ClassDB::register_class<VisualShaderNodeTextureUniform>(); - ClassDB::register_class<VisualShaderNodeTextureUniformTriplanar>(); - ClassDB::register_class<VisualShaderNodeTexture2DArrayUniform>(); - ClassDB::register_class<VisualShaderNodeTexture3DUniform>(); - ClassDB::register_class<VisualShaderNodeCubemapUniform>(); - ClassDB::register_class<VisualShaderNodeIf>(); - ClassDB::register_class<VisualShaderNodeSwitch>(); - ClassDB::register_class<VisualShaderNodeFresnel>(); - ClassDB::register_class<VisualShaderNodeExpression>(); - ClassDB::register_class<VisualShaderNodeGlobalExpression>(); - ClassDB::register_class<VisualShaderNodeIs>(); - ClassDB::register_class<VisualShaderNodeCompare>(); - ClassDB::register_class<VisualShaderNodeMultiplyAdd>(); - ClassDB::register_class<VisualShaderNodeBillboard>(); - - ClassDB::register_class<VisualShaderNodeSDFToScreenUV>(); - ClassDB::register_class<VisualShaderNodeScreenUVToSDF>(); - ClassDB::register_class<VisualShaderNodeTextureSDF>(); - ClassDB::register_class<VisualShaderNodeTextureSDFNormal>(); - ClassDB::register_class<VisualShaderNodeSDFRaymarch>(); - - ClassDB::register_class<VisualShaderNodeParticleOutput>(); - ClassDB::register_virtual_class<VisualShaderNodeParticleEmitter>(); - ClassDB::register_class<VisualShaderNodeParticleSphereEmitter>(); - ClassDB::register_class<VisualShaderNodeParticleBoxEmitter>(); - ClassDB::register_class<VisualShaderNodeParticleRingEmitter>(); - ClassDB::register_class<VisualShaderNodeParticleMultiplyByAxisAngle>(); - ClassDB::register_class<VisualShaderNodeParticleConeVelocity>(); - ClassDB::register_class<VisualShaderNodeParticleRandomness>(); - ClassDB::register_class<VisualShaderNodeParticleAccelerator>(); - ClassDB::register_class<VisualShaderNodeParticleEmit>(); - - ClassDB::register_class<ShaderMaterial>(); - ClassDB::register_virtual_class<CanvasItem>(); - ClassDB::register_class<CanvasTexture>(); - ClassDB::register_class<CanvasItemMaterial>(); + GDREGISTER_CLASS(Shader); + GDREGISTER_CLASS(VisualShader); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNode); + GDREGISTER_CLASS(VisualShaderNodeCustom); + GDREGISTER_CLASS(VisualShaderNodeInput); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeOutput); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeResizableBase); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeGroupBase); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeConstant); + GDREGISTER_CLASS(VisualShaderNodeComment); + GDREGISTER_CLASS(VisualShaderNodeFloatConstant); + GDREGISTER_CLASS(VisualShaderNodeIntConstant); + GDREGISTER_CLASS(VisualShaderNodeBooleanConstant); + GDREGISTER_CLASS(VisualShaderNodeColorConstant); + GDREGISTER_CLASS(VisualShaderNodeVec3Constant); + GDREGISTER_CLASS(VisualShaderNodeTransformConstant); + GDREGISTER_CLASS(VisualShaderNodeFloatOp); + GDREGISTER_CLASS(VisualShaderNodeIntOp); + GDREGISTER_CLASS(VisualShaderNodeVectorOp); + GDREGISTER_CLASS(VisualShaderNodeColorOp); + GDREGISTER_CLASS(VisualShaderNodeTransformMult); + GDREGISTER_CLASS(VisualShaderNodeTransformVecMult); + GDREGISTER_CLASS(VisualShaderNodeFloatFunc); + GDREGISTER_CLASS(VisualShaderNodeIntFunc); + GDREGISTER_CLASS(VisualShaderNodeVectorFunc); + GDREGISTER_CLASS(VisualShaderNodeColorFunc); + GDREGISTER_CLASS(VisualShaderNodeTransformFunc); + GDREGISTER_CLASS(VisualShaderNodeUVFunc); + GDREGISTER_CLASS(VisualShaderNodeDotProduct); + GDREGISTER_CLASS(VisualShaderNodeVectorLen); + GDREGISTER_CLASS(VisualShaderNodeDeterminant); + GDREGISTER_CLASS(VisualShaderNodeScalarDerivativeFunc); + GDREGISTER_CLASS(VisualShaderNodeVectorDerivativeFunc); + GDREGISTER_CLASS(VisualShaderNodeClamp); + GDREGISTER_CLASS(VisualShaderNodeFaceForward); + GDREGISTER_CLASS(VisualShaderNodeOuterProduct); + GDREGISTER_CLASS(VisualShaderNodeSmoothStep); + GDREGISTER_CLASS(VisualShaderNodeStep); + GDREGISTER_CLASS(VisualShaderNodeVectorDistance); + GDREGISTER_CLASS(VisualShaderNodeVectorRefract); + GDREGISTER_CLASS(VisualShaderNodeMix); + GDREGISTER_CLASS(VisualShaderNodeVectorCompose); + GDREGISTER_CLASS(VisualShaderNodeTransformCompose); + GDREGISTER_CLASS(VisualShaderNodeVectorDecompose); + GDREGISTER_CLASS(VisualShaderNodeTransformDecompose); + GDREGISTER_CLASS(VisualShaderNodeTexture); + GDREGISTER_CLASS(VisualShaderNodeCurveTexture); + GDREGISTER_CLASS(VisualShaderNodeCurve3Texture); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeSample3D); + GDREGISTER_CLASS(VisualShaderNodeTexture2DArray); + GDREGISTER_CLASS(VisualShaderNodeTexture3D); + GDREGISTER_CLASS(VisualShaderNodeCubemap); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeUniform); + GDREGISTER_CLASS(VisualShaderNodeUniformRef); + GDREGISTER_CLASS(VisualShaderNodeFloatUniform); + GDREGISTER_CLASS(VisualShaderNodeIntUniform); + GDREGISTER_CLASS(VisualShaderNodeBooleanUniform); + GDREGISTER_CLASS(VisualShaderNodeColorUniform); + GDREGISTER_CLASS(VisualShaderNodeVec3Uniform); + GDREGISTER_CLASS(VisualShaderNodeTransformUniform); + GDREGISTER_CLASS(VisualShaderNodeTextureUniform); + GDREGISTER_CLASS(VisualShaderNodeTextureUniformTriplanar); + GDREGISTER_CLASS(VisualShaderNodeTexture2DArrayUniform); + GDREGISTER_CLASS(VisualShaderNodeTexture3DUniform); + GDREGISTER_CLASS(VisualShaderNodeCubemapUniform); + GDREGISTER_CLASS(VisualShaderNodeIf); + GDREGISTER_CLASS(VisualShaderNodeSwitch); + GDREGISTER_CLASS(VisualShaderNodeFresnel); + GDREGISTER_CLASS(VisualShaderNodeExpression); + GDREGISTER_CLASS(VisualShaderNodeGlobalExpression); + GDREGISTER_CLASS(VisualShaderNodeIs); + GDREGISTER_CLASS(VisualShaderNodeCompare); + GDREGISTER_CLASS(VisualShaderNodeMultiplyAdd); + GDREGISTER_CLASS(VisualShaderNodeBillboard); + + GDREGISTER_CLASS(VisualShaderNodeSDFToScreenUV); + GDREGISTER_CLASS(VisualShaderNodeScreenUVToSDF); + GDREGISTER_CLASS(VisualShaderNodeTextureSDF); + GDREGISTER_CLASS(VisualShaderNodeTextureSDFNormal); + GDREGISTER_CLASS(VisualShaderNodeSDFRaymarch); + + GDREGISTER_CLASS(VisualShaderNodeParticleOutput); + GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeParticleEmitter); + GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter); + GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter); + GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter); + GDREGISTER_CLASS(VisualShaderNodeParticleMultiplyByAxisAngle); + GDREGISTER_CLASS(VisualShaderNodeParticleConeVelocity); + GDREGISTER_CLASS(VisualShaderNodeParticleRandomness); + GDREGISTER_CLASS(VisualShaderNodeParticleAccelerator); + GDREGISTER_CLASS(VisualShaderNodeParticleEmit); + + GDREGISTER_CLASS(ShaderMaterial); + GDREGISTER_VIRTUAL_CLASS(CanvasItem); + GDREGISTER_CLASS(CanvasTexture); + GDREGISTER_CLASS(CanvasItemMaterial); SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes); CanvasItemMaterial::init_shaders(); /* REGISTER 2D */ - ClassDB::register_class<Node2D>(); - ClassDB::register_class<CanvasGroup>(); - ClassDB::register_class<CPUParticles2D>(); - ClassDB::register_class<GPUParticles2D>(); - ClassDB::register_class<Sprite2D>(); - ClassDB::register_class<SpriteFrames>(); - ClassDB::register_class<AnimatedSprite2D>(); - ClassDB::register_class<Position2D>(); - ClassDB::register_class<Line2D>(); - ClassDB::register_class<MeshInstance2D>(); - ClassDB::register_class<MultiMeshInstance2D>(); - ClassDB::register_virtual_class<CollisionObject2D>(); - ClassDB::register_virtual_class<PhysicsBody2D>(); - ClassDB::register_class<StaticBody2D>(); - ClassDB::register_class<RigidBody2D>(); - ClassDB::register_class<CharacterBody2D>(); - ClassDB::register_class<KinematicCollision2D>(); - ClassDB::register_class<Area2D>(); - ClassDB::register_class<CollisionShape2D>(); - ClassDB::register_class<CollisionPolygon2D>(); - ClassDB::register_class<RayCast2D>(); - ClassDB::register_class<VisibleOnScreenNotifier2D>(); - ClassDB::register_class<VisibleOnScreenEnabler2D>(); - ClassDB::register_class<Polygon2D>(); - ClassDB::register_class<Skeleton2D>(); - ClassDB::register_class<Bone2D>(); - ClassDB::register_virtual_class<Light2D>(); - ClassDB::register_class<PointLight2D>(); - ClassDB::register_class<DirectionalLight2D>(); - ClassDB::register_class<LightOccluder2D>(); - ClassDB::register_class<OccluderPolygon2D>(); - ClassDB::register_class<BackBufferCopy>(); + GDREGISTER_CLASS(Node2D); + GDREGISTER_CLASS(CanvasGroup); + GDREGISTER_CLASS(CPUParticles2D); + GDREGISTER_CLASS(GPUParticles2D); + GDREGISTER_CLASS(Sprite2D); + GDREGISTER_CLASS(SpriteFrames); + GDREGISTER_CLASS(AnimatedSprite2D); + GDREGISTER_CLASS(Position2D); + GDREGISTER_CLASS(Line2D); + GDREGISTER_CLASS(MeshInstance2D); + GDREGISTER_CLASS(MultiMeshInstance2D); + GDREGISTER_VIRTUAL_CLASS(CollisionObject2D); + GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D); + GDREGISTER_CLASS(StaticBody2D); + GDREGISTER_CLASS(RigidBody2D); + GDREGISTER_CLASS(CharacterBody2D); + GDREGISTER_CLASS(KinematicCollision2D); + GDREGISTER_CLASS(Area2D); + GDREGISTER_CLASS(CollisionShape2D); + GDREGISTER_CLASS(CollisionPolygon2D); + GDREGISTER_CLASS(RayCast2D); + GDREGISTER_CLASS(VisibleOnScreenNotifier2D); + GDREGISTER_CLASS(VisibleOnScreenEnabler2D); + GDREGISTER_CLASS(Polygon2D); + GDREGISTER_CLASS(Skeleton2D); + GDREGISTER_CLASS(Bone2D); + GDREGISTER_VIRTUAL_CLASS(Light2D); + GDREGISTER_CLASS(PointLight2D); + GDREGISTER_CLASS(DirectionalLight2D); + GDREGISTER_CLASS(LightOccluder2D); + GDREGISTER_CLASS(OccluderPolygon2D); + GDREGISTER_CLASS(BackBufferCopy); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<Camera2D>(); - ClassDB::register_virtual_class<Joint2D>(); - ClassDB::register_class<PinJoint2D>(); - ClassDB::register_class<GrooveJoint2D>(); - ClassDB::register_class<DampedSpringJoint2D>(); - ClassDB::register_class<TileSet>(); - ClassDB::register_virtual_class<TileSetSource>(); - ClassDB::register_class<TileSetAtlasSource>(); - ClassDB::register_class<TileSetScenesCollectionSource>(); - ClassDB::register_class<TileData>(); - ClassDB::register_class<TileMap>(); - ClassDB::register_class<ParallaxBackground>(); - ClassDB::register_class<ParallaxLayer>(); - ClassDB::register_class<TouchScreenButton>(); - ClassDB::register_class<RemoteTransform2D>(); - - ClassDB::register_class<SkeletonModificationStack2D>(); - ClassDB::register_class<SkeletonModification2D>(); - ClassDB::register_class<SkeletonModification2DLookAt>(); - ClassDB::register_class<SkeletonModification2DCCDIK>(); - ClassDB::register_class<SkeletonModification2DFABRIK>(); - ClassDB::register_class<SkeletonModification2DJiggle>(); - ClassDB::register_class<SkeletonModification2DTwoBoneIK>(); - ClassDB::register_class<SkeletonModification2DStackHolder>(); - - ClassDB::register_class<PhysicalBone2D>(); - ClassDB::register_class<SkeletonModification2DPhysicalBones>(); + GDREGISTER_CLASS(Camera2D); + GDREGISTER_VIRTUAL_CLASS(Joint2D); + GDREGISTER_CLASS(PinJoint2D); + GDREGISTER_CLASS(GrooveJoint2D); + GDREGISTER_CLASS(DampedSpringJoint2D); + GDREGISTER_CLASS(TileSet); + GDREGISTER_VIRTUAL_CLASS(TileSetSource); + GDREGISTER_CLASS(TileSetAtlasSource); + GDREGISTER_CLASS(TileSetScenesCollectionSource); + GDREGISTER_CLASS(TileData); + GDREGISTER_CLASS(TileMap); + GDREGISTER_CLASS(ParallaxBackground); + GDREGISTER_CLASS(ParallaxLayer); + GDREGISTER_CLASS(TouchScreenButton); + GDREGISTER_CLASS(RemoteTransform2D); + + GDREGISTER_CLASS(SkeletonModificationStack2D); + GDREGISTER_CLASS(SkeletonModification2D); + GDREGISTER_CLASS(SkeletonModification2DLookAt); + GDREGISTER_CLASS(SkeletonModification2DCCDIK); + GDREGISTER_CLASS(SkeletonModification2DFABRIK); + GDREGISTER_CLASS(SkeletonModification2DJiggle); + GDREGISTER_CLASS(SkeletonModification2DTwoBoneIK); + GDREGISTER_CLASS(SkeletonModification2DStackHolder); + + GDREGISTER_CLASS(PhysicalBone2D); + GDREGISTER_CLASS(SkeletonModification2DPhysicalBones); OS::get_singleton()->yield(); //may take time to init /* REGISTER RESOURCES */ - ClassDB::register_virtual_class<Shader>(); - ClassDB::register_class<ParticlesMaterial>(); + GDREGISTER_VIRTUAL_CLASS(Shader); + GDREGISTER_CLASS(ParticlesMaterial); SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); ParticlesMaterial::init_shaders(); - ClassDB::register_class<ProceduralSkyMaterial>(); - ClassDB::register_class<PanoramaSkyMaterial>(); - ClassDB::register_class<PhysicalSkyMaterial>(); + GDREGISTER_CLASS(ProceduralSkyMaterial); + GDREGISTER_CLASS(PanoramaSkyMaterial); + GDREGISTER_CLASS(PhysicalSkyMaterial); - ClassDB::register_virtual_class<Mesh>(); - ClassDB::register_class<ArrayMesh>(); - ClassDB::register_class<ImmediateMesh>(); - ClassDB::register_class<MultiMesh>(); - ClassDB::register_class<SurfaceTool>(); - ClassDB::register_class<MeshDataTool>(); + GDREGISTER_VIRTUAL_CLASS(Mesh); + GDREGISTER_CLASS(ArrayMesh); + GDREGISTER_CLASS(ImmediateMesh); + GDREGISTER_CLASS(MultiMesh); + GDREGISTER_CLASS(SurfaceTool); + GDREGISTER_CLASS(MeshDataTool); #ifndef _3D_DISABLED - ClassDB::register_virtual_class<PrimitiveMesh>(); - ClassDB::register_class<BoxMesh>(); - ClassDB::register_class<CapsuleMesh>(); - ClassDB::register_class<CylinderMesh>(); - ClassDB::register_class<PlaneMesh>(); - ClassDB::register_class<PrismMesh>(); - ClassDB::register_class<QuadMesh>(); - ClassDB::register_class<SphereMesh>(); - ClassDB::register_class<TubeTrailMesh>(); - ClassDB::register_class<RibbonTrailMesh>(); - ClassDB::register_class<PointMesh>(); - ClassDB::register_virtual_class<Material>(); - ClassDB::register_virtual_class<BaseMaterial3D>(); - ClassDB::register_class<StandardMaterial3D>(); - ClassDB::register_class<ORMMaterial3D>(); + GDREGISTER_VIRTUAL_CLASS(PrimitiveMesh); + GDREGISTER_CLASS(BoxMesh); + GDREGISTER_CLASS(CapsuleMesh); + GDREGISTER_CLASS(CylinderMesh); + GDREGISTER_CLASS(PlaneMesh); + GDREGISTER_CLASS(PrismMesh); + GDREGISTER_CLASS(QuadMesh); + GDREGISTER_CLASS(SphereMesh); + GDREGISTER_CLASS(TubeTrailMesh); + GDREGISTER_CLASS(RibbonTrailMesh); + GDREGISTER_CLASS(PointMesh); + GDREGISTER_VIRTUAL_CLASS(Material); + GDREGISTER_VIRTUAL_CLASS(BaseMaterial3D); + GDREGISTER_CLASS(StandardMaterial3D); + GDREGISTER_CLASS(ORMMaterial3D); SceneTree::add_idle_callback(BaseMaterial3D::flush_changes); BaseMaterial3D::init_shaders(); - ClassDB::register_class<MeshLibrary>(); + GDREGISTER_CLASS(MeshLibrary); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class<Shape3D>(); - ClassDB::register_class<RayShape3D>(); - ClassDB::register_class<SphereShape3D>(); - ClassDB::register_class<BoxShape3D>(); - ClassDB::register_class<CapsuleShape3D>(); - ClassDB::register_class<CylinderShape3D>(); - ClassDB::register_class<HeightMapShape3D>(); - ClassDB::register_class<WorldMarginShape3D>(); - ClassDB::register_class<ConvexPolygonShape3D>(); - ClassDB::register_class<ConcavePolygonShape3D>(); + GDREGISTER_VIRTUAL_CLASS(Shape3D); + GDREGISTER_CLASS(RayShape3D); + GDREGISTER_CLASS(SphereShape3D); + GDREGISTER_CLASS(BoxShape3D); + GDREGISTER_CLASS(CapsuleShape3D); + GDREGISTER_CLASS(CylinderShape3D); + GDREGISTER_CLASS(HeightMapShape3D); + GDREGISTER_CLASS(WorldMarginShape3D); + GDREGISTER_CLASS(ConvexPolygonShape3D); + GDREGISTER_CLASS(ConcavePolygonShape3D); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<VelocityTracker3D>(); + GDREGISTER_CLASS(VelocityTracker3D); #endif - ClassDB::register_class<PhysicsMaterial>(); - ClassDB::register_class<World3D>(); - ClassDB::register_class<Environment>(); - ClassDB::register_class<CameraEffects>(); - ClassDB::register_class<World2D>(); - ClassDB::register_virtual_class<Texture>(); - ClassDB::register_virtual_class<Texture2D>(); - ClassDB::register_class<Sky>(); - ClassDB::register_class<StreamTexture2D>(); - ClassDB::register_class<ImageTexture>(); - ClassDB::register_class<AtlasTexture>(); - ClassDB::register_class<MeshTexture>(); - ClassDB::register_class<CurveTexture>(); - ClassDB::register_class<GradientTexture>(); - ClassDB::register_class<ProxyTexture>(); - ClassDB::register_class<AnimatedTexture>(); - ClassDB::register_class<CameraTexture>(); - ClassDB::register_virtual_class<TextureLayered>(); - ClassDB::register_virtual_class<ImageTextureLayered>(); - ClassDB::register_virtual_class<Texture3D>(); - ClassDB::register_class<ImageTexture3D>(); - ClassDB::register_class<StreamTexture3D>(); - ClassDB::register_class<Cubemap>(); - ClassDB::register_class<CubemapArray>(); - ClassDB::register_class<Texture2DArray>(); - ClassDB::register_virtual_class<StreamTextureLayered>(); - ClassDB::register_class<StreamCubemap>(); - ClassDB::register_class<StreamCubemapArray>(); - ClassDB::register_class<StreamTexture2DArray>(); - - ClassDB::register_class<Animation>(); - ClassDB::register_class<FontData>(); - ClassDB::register_class<Font>(); - ClassDB::register_class<Curve>(); - - ClassDB::register_class<TextFile>(); - ClassDB::register_class<TextLine>(); - ClassDB::register_class<TextParagraph>(); - - ClassDB::register_virtual_class<StyleBox>(); - ClassDB::register_class<StyleBoxEmpty>(); - ClassDB::register_class<StyleBoxTexture>(); - ClassDB::register_class<StyleBoxFlat>(); - ClassDB::register_class<StyleBoxLine>(); - ClassDB::register_class<Theme>(); - - ClassDB::register_class<PolygonPathFinder>(); - ClassDB::register_class<BitMap>(); - ClassDB::register_class<Gradient>(); + GDREGISTER_CLASS(PhysicsMaterial); + GDREGISTER_CLASS(World3D); + GDREGISTER_CLASS(Environment); + GDREGISTER_CLASS(CameraEffects); + GDREGISTER_CLASS(World2D); + GDREGISTER_VIRTUAL_CLASS(Texture); + GDREGISTER_VIRTUAL_CLASS(Texture2D); + GDREGISTER_CLASS(Sky); + GDREGISTER_CLASS(StreamTexture2D); + GDREGISTER_CLASS(ImageTexture); + GDREGISTER_CLASS(AtlasTexture); + GDREGISTER_CLASS(MeshTexture); + GDREGISTER_CLASS(CurveTexture); + GDREGISTER_CLASS(Curve3Texture); + GDREGISTER_CLASS(GradientTexture); + GDREGISTER_CLASS(ProxyTexture); + GDREGISTER_CLASS(AnimatedTexture); + GDREGISTER_CLASS(CameraTexture); + GDREGISTER_VIRTUAL_CLASS(TextureLayered); + GDREGISTER_VIRTUAL_CLASS(ImageTextureLayered); + GDREGISTER_VIRTUAL_CLASS(Texture3D); + GDREGISTER_CLASS(ImageTexture3D); + GDREGISTER_CLASS(StreamTexture3D); + GDREGISTER_CLASS(Cubemap); + GDREGISTER_CLASS(CubemapArray); + GDREGISTER_CLASS(Texture2DArray); + GDREGISTER_VIRTUAL_CLASS(StreamTextureLayered); + GDREGISTER_CLASS(StreamCubemap); + GDREGISTER_CLASS(StreamCubemapArray); + GDREGISTER_CLASS(StreamTexture2DArray); + + GDREGISTER_CLASS(Animation); + GDREGISTER_CLASS(FontData); + GDREGISTER_CLASS(Font); + GDREGISTER_CLASS(Curve); + + GDREGISTER_CLASS(TextFile); + GDREGISTER_CLASS(TextLine); + GDREGISTER_CLASS(TextParagraph); + + GDREGISTER_VIRTUAL_CLASS(StyleBox); + GDREGISTER_CLASS(StyleBoxEmpty); + GDREGISTER_CLASS(StyleBoxTexture); + GDREGISTER_CLASS(StyleBoxFlat); + GDREGISTER_CLASS(StyleBoxLine); + GDREGISTER_CLASS(Theme); + + GDREGISTER_CLASS(PolygonPathFinder); + GDREGISTER_CLASS(BitMap); + GDREGISTER_CLASS(Gradient); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<AudioStreamPlayer>(); - ClassDB::register_class<AudioStreamPlayer2D>(); + GDREGISTER_CLASS(AudioStreamPlayer); + GDREGISTER_CLASS(AudioStreamPlayer2D); #ifndef _3D_DISABLED - ClassDB::register_class<AudioStreamPlayer3D>(); + GDREGISTER_CLASS(AudioStreamPlayer3D); #endif - ClassDB::register_virtual_class<VideoStream>(); - ClassDB::register_class<AudioStreamSample>(); + GDREGISTER_VIRTUAL_CLASS(VideoStream); + GDREGISTER_CLASS(AudioStreamSample); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class<Shape2D>(); - ClassDB::register_class<LineShape2D>(); - ClassDB::register_class<SegmentShape2D>(); - ClassDB::register_class<RayShape2D>(); - ClassDB::register_class<CircleShape2D>(); - ClassDB::register_class<RectangleShape2D>(); - ClassDB::register_class<CapsuleShape2D>(); - ClassDB::register_class<ConvexPolygonShape2D>(); - ClassDB::register_class<ConcavePolygonShape2D>(); - ClassDB::register_class<Curve2D>(); - ClassDB::register_class<Path2D>(); - ClassDB::register_class<PathFollow2D>(); - - ClassDB::register_class<NavigationMesh>(); - ClassDB::register_class<NavigationPolygon>(); - ClassDB::register_class<NavigationRegion2D>(); - ClassDB::register_class<NavigationAgent2D>(); - ClassDB::register_class<NavigationObstacle2D>(); + GDREGISTER_VIRTUAL_CLASS(Shape2D); + GDREGISTER_CLASS(LineShape2D); + GDREGISTER_CLASS(SegmentShape2D); + GDREGISTER_CLASS(RayShape2D); + GDREGISTER_CLASS(CircleShape2D); + GDREGISTER_CLASS(RectangleShape2D); + GDREGISTER_CLASS(CapsuleShape2D); + GDREGISTER_CLASS(ConvexPolygonShape2D); + GDREGISTER_CLASS(ConcavePolygonShape2D); + GDREGISTER_CLASS(Curve2D); + GDREGISTER_CLASS(Path2D); + GDREGISTER_CLASS(PathFollow2D); + + GDREGISTER_CLASS(NavigationMesh); + GDREGISTER_CLASS(NavigationPolygon); + GDREGISTER_CLASS(NavigationRegion2D); + GDREGISTER_CLASS(NavigationAgent2D); + GDREGISTER_CLASS(NavigationObstacle2D); OS::get_singleton()->yield(); //may take time to init - ClassDB::register_virtual_class<SceneState>(); - ClassDB::register_class<PackedScene>(); + GDREGISTER_VIRTUAL_CLASS(SceneState); + GDREGISTER_CLASS(PackedScene); - ClassDB::register_class<SceneTree>(); - ClassDB::register_virtual_class<SceneTreeTimer>(); //sorry, you can't create it + GDREGISTER_CLASS(SceneTree); + GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); //sorry, you can't create it #ifndef DISABLE_DEPRECATED // Dropped in 4.0, near approximation. @@ -936,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/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 5464a46df4..1bbb84f43d 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -390,6 +390,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("shadow_outline_size", "Label", 1 * scale); theme->set_constant("line_spacing", "Label", 3 * scale); + theme->set_type_variation("HeaderSmall", "Label"); + theme->set_font_size("font_size", "HeaderSmall", default_font_size + 4); + + theme->set_type_variation("HeaderMedium", "Label"); + theme->set_font_size("font_size", "HeaderMedium", default_font_size + 8); + + theme->set_type_variation("HeaderLarge", "Label"); + theme->set_font_size("font_size", "HeaderLarge", default_font_size + 12); + // LineEdit theme->set_stylebox("normal", "LineEdit", make_stylebox(line_edit_png, 5, 5, 5, 5)); @@ -984,7 +993,7 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { Ref<StyleBox> default_style; Ref<Texture2D> default_icon; Ref<Font> default_font; - int default_font_size = 16; + if (p_font.is_valid()) { // Use the custom font defined in the Project Settings. default_font = p_font; diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index a7b2bec5a4..4cd781e814 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -33,6 +33,8 @@ #include "scene/resources/theme.h" +const int default_font_size = 16; + void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void make_default_theme(bool p_hidpi, Ref<Font> p_font); void clear_default_theme(); 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 ce942817c0..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; @@ -590,157 +611,320 @@ Transform3D Mesh::get_builtin_bind_pose(int p_index) const { Mesh::Mesh() { } -#if 0 -static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) { - enum ArrayType { - OLD_ARRAY_VERTEX = 0, - OLD_ARRAY_NORMAL = 1, - OLD_ARRAY_TANGENT = 2, - OLD_ARRAY_COLOR = 3, - OLD_ARRAY_TEX_UV = 4, - OLD_ARRAY_TEX_UV2 = 5, - OLD_ARRAY_BONES = 6, - OLD_ARRAY_WEIGHTS = 7, - OLD_ARRAY_INDEX = 8, - OLD_ARRAY_MAX = 9 - }; - - enum ArrayFormat { - /* OLD_ARRAY FORMAT FLAGS */ - OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory - OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL, - OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT, - OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR, - OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV, - OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2, - OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES, - OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS, - OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX, - - OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1), - OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE), - OLD_ARRAY_COMPRESS_DEFAULT = OLD_ARRAY_COMPRESS_NORMAL | OLD_ARRAY_COMPRESS_TANGENT | OLD_ARRAY_COMPRESS_COLOR | OLD_ARRAY_COMPRESS_TEX_UV | OLD_ARRAY_COMPRESS_TEX_UV2, - - OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1, - OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3, - }; - - bool vertex_16bit = p_format & ((1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE))); - bool has_bones = (p_format & OLD_ARRAY_FORMAT_BONES); - bool bone_8 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_INDEX << 2)); - bool weight_32 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_TEX_UV2 << 2)); - - print_line("convert vertex16: " + itos(vertex_16bit) + " convert bone 8 " + itos(bone_8) + " convert weight 32 " + itos(weight_32)); - - if (!vertex_16bit && !bone_8 && !weight_32) { - return p_src; - } +enum OldArrayType { + OLD_ARRAY_VERTEX, + OLD_ARRAY_NORMAL, + OLD_ARRAY_TANGENT, + OLD_ARRAY_COLOR, + OLD_ARRAY_TEX_UV, + OLD_ARRAY_TEX_UV2, + OLD_ARRAY_BONES, + OLD_ARRAY_WEIGHTS, + OLD_ARRAY_INDEX, + OLD_ARRAY_MAX, +}; - bool vertex_2d = (p_format & (OLD_ARRAY_COMPRESS_INDEX << 1)); +enum OldArrayFormat { + /* OLD_ARRAY FORMAT FLAGS */ + OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory + OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL, + OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT, + OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR, + OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV, + OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2, + OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES, + OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS, + OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX, + + OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1), + OLD_ARRAY_COMPRESS_VERTEX = 1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE), // mandatory + OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_BONES = 1 << (OLD_ARRAY_BONES + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_WEIGHTS = 1 << (OLD_ARRAY_WEIGHTS + OLD_ARRAY_COMPRESS_BASE), + OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE), + + OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1, + OLD_ARRAY_FLAG_USE_16_BIT_BONES = OLD_ARRAY_COMPRESS_INDEX << 2, + OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3, - uint32_t src_stride = p_src.size() / p_elements; - uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) + (bone_8 ? 4 : 0) - (weight_32 ? 8 : 0); +}; - Vector<uint8_t> ret = p_src; +static Array _convert_old_array(const Array &p_old) { + Array new_array; + new_array.resize(Mesh::ARRAY_MAX); + new_array[Mesh::ARRAY_VERTEX] = p_old[OLD_ARRAY_VERTEX]; + new_array[Mesh::ARRAY_NORMAL] = p_old[OLD_ARRAY_NORMAL]; + new_array[Mesh::ARRAY_TANGENT] = p_old[OLD_ARRAY_TANGENT]; + new_array[Mesh::ARRAY_COLOR] = p_old[OLD_ARRAY_COLOR]; + new_array[Mesh::ARRAY_TEX_UV] = p_old[OLD_ARRAY_TEX_UV]; + new_array[Mesh::ARRAY_TEX_UV2] = p_old[OLD_ARRAY_TEX_UV2]; + new_array[Mesh::ARRAY_BONES] = p_old[OLD_ARRAY_BONES]; + new_array[Mesh::ARRAY_WEIGHTS] = p_old[OLD_ARRAY_WEIGHTS]; + new_array[Mesh::ARRAY_INDEX] = p_old[OLD_ARRAY_INDEX]; + return new_array; +} + +static Mesh::PrimitiveType _old_primitives[7] = { + Mesh::PRIMITIVE_POINTS, + Mesh::PRIMITIVE_LINES, + Mesh::PRIMITIVE_LINE_STRIP, + Mesh::PRIMITIVE_LINES, + Mesh::PRIMITIVE_TRIANGLES, + Mesh::PRIMITIVE_TRIANGLE_STRIP, + Mesh::PRIMITIVE_TRIANGLE_STRIP +}; - ret.resize(dst_stride * p_elements); - { - uint8_t *w = ret.ptrw(); - const uint8_t *r = p_src.ptr(); - - for (uint32_t i = 0; i < p_elements; i++) { - uint32_t remaining = src_stride; - const uint8_t *src = (const uint8_t *)(r + src_stride * i); - uint8_t *dst = (uint8_t *)(w + dst_stride * i); - - if (!vertex_2d) { //3D - if (vertex_16bit) { - float *dstw = (float *)dst; - const uint16_t *srcr = (const uint16_t *)src; - dstw[0] = Math::half_to_float(srcr[0]); - dstw[1] = Math::half_to_float(srcr[1]); - dstw[2] = Math::half_to_float(srcr[2]); - remaining -= 8; - src += 8; +void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) { + uint32_t dst_vertex_stride; + uint32_t dst_attribute_stride; + uint32_t dst_skin_stride; + uint32_t dst_offsets[Mesh::ARRAY_MAX]; + RenderingServer::get_singleton()->mesh_surface_make_offsets_from_format(p_new_format & (~RS::ARRAY_FORMAT_INDEX), p_elements, 0, dst_offsets, dst_vertex_stride, dst_attribute_stride, dst_skin_stride); + + vertex_data.resize(dst_vertex_stride * p_elements); + attribute_data.resize(dst_attribute_stride * p_elements); + skin_data.resize(dst_skin_stride * p_elements); + + uint8_t *dst_vertex_ptr = vertex_data.ptrw(); + uint8_t *dst_attribute_ptr = attribute_data.ptrw(); + uint8_t *dst_skin_ptr = skin_data.ptrw(); + + const uint8_t *src_vertex_ptr = p_src.ptr(); + uint32_t src_vertex_stride = p_src.size() / p_elements; + + uint32_t src_offset = 0; + for (uint32_t j = 0; j < OLD_ARRAY_INDEX; j++) { + if (!(p_old_format & (1 << j))) { + continue; + } + switch (j) { + case OLD_ARRAY_VERTEX: { + if (p_old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { + if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + } + src_offset += sizeof(uint16_t) * 2; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = src[0]; + dst[1] = src[1]; + } + src_offset += sizeof(float) * 2; + } } else { - src += 12; - remaining -= 12; + if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + dst[2] = Math::half_to_float(src[2]); + } + src_offset += sizeof(uint16_t) * 4; //+pad + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; + float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + } + src_offset += sizeof(float) * 3; + } } - dst += 12; - } else { - if (vertex_16bit) { - float *dstw = (float *)dst; - const uint16_t *srcr = (const uint16_t *)src; - dstw[0] = Math::half_to_float(srcr[0]); - dstw[1] = Math::half_to_float(srcr[1]); - remaining -= 4; - src += 4; + } break; + case OLD_ARRAY_NORMAL: { + if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) { + const float multiplier = 1.f / 127.f * 1023.0f; + + for (uint32_t i = 0; i < p_elements; i++) { + const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * multiplier), 0, 1023); + *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20; + } + src_offset += sizeof(uint32_t); } else { - src += 8; - remaining -= 8; + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023); + *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20; + } + src_offset += sizeof(float) * 3; } - dst += 8; - } - - if (has_bones) { - remaining -= bone_8 ? 4 : 8; - remaining -= weight_32 ? 16 : 8; - } - - for (uint32_t j = 0; j < remaining; j++) { - dst[j] = src[j]; - } - if (has_bones) { - dst += remaining; - src += remaining; - - if (bone_8) { - const uint8_t *src_bones = (const uint8_t *)src; - uint16_t *dst_bones = (uint16_t *)dst; + } break; + case OLD_ARRAY_TANGENT: { + if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { + const float multiplier = 1.f / 127.f * 1023.0f; + + for (uint32_t i = 0; i < p_elements; i++) { + const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * multiplier), 0, 1023); + *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20; + if (src[3] > 0) { + *dst |= 3 << 30; + } + } + src_offset += sizeof(uint32_t); + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; + + *dst = 0; + *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023); + *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10; + *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20; + if (src[3] > 0) { + *dst |= 3 << 30; + } + } + src_offset += sizeof(float) * 4; + } - dst_bones[0] = src_bones[0]; - dst_bones[1] = src_bones[1]; - dst_bones[2] = src_bones[2]; - dst_bones[3] = src_bones[3]; + } break; + case OLD_ARRAY_COLOR: { + if (p_old_format & OLD_ARRAY_COMPRESS_COLOR) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint32_t *src = (const uint32_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint32_t *dst = (uint32_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; - src += 4; + *dst = *src; + } + src_offset += sizeof(uint32_t); } else { - for (uint32_t j = 0; j < 8; j++) { - dst[j] = src[j]; + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint8_t *dst = (uint8_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; + + dst[0] = uint8_t(CLAMP(src[0] * 255.0, 0.0, 255.0)); + dst[1] = uint8_t(CLAMP(src[1] * 255.0, 0.0, 255.0)); + dst[2] = uint8_t(CLAMP(src[2] * 255.0, 0.0, 255.0)); + dst[3] = uint8_t(CLAMP(src[3] * 255.0, 0.0, 255.0)); } - - src += 8; + src_offset += sizeof(float) * 4; } + } break; + case OLD_ARRAY_TEX_UV: { + if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; + + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + } + src_offset += sizeof(uint16_t) * 2; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; - dst += 8; + dst[0] = src[0]; + dst[1] = src[1]; + } + src_offset += sizeof(float) * 2; + } - if (weight_32) { - const float *src_weights = (const float *)src; - uint16_t *dst_weights = (uint16_t *)dst; + } break; + case OLD_ARRAY_TEX_UV2: { + if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV2) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; - dst_weights[0] = CLAMP(src_weights[0] * 65535, 0, 65535); //16bits unorm - dst_weights[1] = CLAMP(src_weights[1] * 65535, 0, 65535); - dst_weights[2] = CLAMP(src_weights[2] * 65535, 0, 65535); - dst_weights[3] = CLAMP(src_weights[3] * 65535, 0, 65535); + dst[0] = Math::half_to_float(src[0]); + dst[1] = Math::half_to_float(src[1]); + } + src_offset += sizeof(uint16_t) * 2; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; + dst[0] = src[0]; + dst[1] = src[1]; + } + src_offset += sizeof(float) * 2; + } + } break; + case OLD_ARRAY_BONES: { + if (p_old_format & OLD_ARRAY_FLAG_USE_16_BIT_BONES) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + src_offset += sizeof(uint16_t) * 4; + } else { + for (uint32_t i = 0; i < p_elements; i++) { + const uint8_t *src = (const uint8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + src_offset += sizeof(uint8_t) * 4; + } + } break; + case OLD_ARRAY_WEIGHTS: { + if (p_old_format & OLD_ARRAY_COMPRESS_WEIGHTS) { + for (uint32_t i = 0; i < p_elements; i++) { + const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + src_offset += sizeof(uint16_t) * 4; } else { - for (uint32_t j = 0; j < 8; j++) { - dst[j] = src[j]; + for (uint32_t i = 0; i < p_elements; i++) { + const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; + uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; + + dst[0] = uint16_t(CLAMP(src[0] * 65535.0, 0, 65535.0)); + dst[1] = uint16_t(CLAMP(src[1] * 65535.0, 0, 65535.0)); + dst[2] = uint16_t(CLAMP(src[2] * 65535.0, 0, 65535.0)); + dst[3] = uint16_t(CLAMP(src[3] * 65535.0, 0, 65535.0)); } + src_offset += sizeof(float) * 4; } + } break; + default: { } } } - - return ret; } -#endif bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; @@ -779,10 +963,13 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { if (d.has("arrays")) { //oldest format (2.x) ERR_FAIL_COND_V(!d.has("morph_arrays"), false); - add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]); + Array morph_arrays = d["morph_arrays"]; + for (int i = 0; i < morph_arrays.size(); i++) { + morph_arrays[i] = _convert_old_array(morph_arrays[i]); + } + add_surface_from_arrays(_old_primitives[int(d["primitive"])], _convert_old_array(d["arrays"]), morph_arrays); } else if (d.has("array_data")) { -#if 0 //print_line("array data (old style"); //older format (3.x) Vector<uint8_t> array_data = d["array_data"]; @@ -792,48 +979,76 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } ERR_FAIL_COND_V(!d.has("format"), false); - uint32_t format = d["format"]; + uint32_t old_format = d["format"]; uint32_t primitive = d["primitive"]; - uint32_t primitive_remap[7] = { - PRIMITIVE_POINTS, - PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP, - PRIMITIVE_LINES, - PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_TRIANGLE_STRIP - }; - - primitive = primitive_remap[primitive]; //compatibility + primitive = _old_primitives[primitive]; //compatibility ERR_FAIL_COND_V(!d.has("vertex_count"), false); int vertex_count = d["vertex_count"]; - array_data = _fix_array_compatibility(array_data, format, vertex_count); + uint32_t new_format = ARRAY_FORMAT_VERTEX; + + if (old_format & OLD_ARRAY_FORMAT_NORMAL) { + new_format |= ARRAY_FORMAT_NORMAL; + } + if (old_format & OLD_ARRAY_FORMAT_TANGENT) { + new_format |= ARRAY_FORMAT_TANGENT; + } + if (old_format & OLD_ARRAY_FORMAT_COLOR) { + new_format |= ARRAY_FORMAT_COLOR; + } + if (old_format & OLD_ARRAY_FORMAT_TEX_UV) { + new_format |= ARRAY_FORMAT_TEX_UV; + } + if (old_format & OLD_ARRAY_FORMAT_TEX_UV2) { + new_format |= ARRAY_FORMAT_TEX_UV2; + } + if (old_format & OLD_ARRAY_FORMAT_BONES) { + new_format |= ARRAY_FORMAT_BONES; + } + if (old_format & OLD_ARRAY_FORMAT_WEIGHTS) { + new_format |= ARRAY_FORMAT_WEIGHTS; + } + if (old_format & OLD_ARRAY_FORMAT_INDEX) { + new_format |= ARRAY_FORMAT_INDEX; + } + if (old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { + new_format |= OLD_ARRAY_FLAG_USE_2D_VERTICES; + } + + Vector<uint8_t> vertex_array; + Vector<uint8_t> attribute_array; + Vector<uint8_t> skin_array; + + _fix_array_compatibility(array_data, old_format, new_format, vertex_count, vertex_array, attribute_array, skin_array); int index_count = 0; if (d.has("index_count")) { index_count = d["index_count"]; } - Vector<Vector<uint8_t>> blend_shapes; + Vector<uint8_t> blend_shapes; if (d.has("blend_shape_data")) { Array blend_shape_data = d["blend_shape_data"]; for (int i = 0; i < blend_shape_data.size(); i++) { + Vector<uint8_t> blend_vertex_array; + Vector<uint8_t> blend_attribute_array; + Vector<uint8_t> blend_skin_array; + Vector<uint8_t> shape = blend_shape_data[i]; - shape = _fix_array_compatibility(shape, format, vertex_count); + _fix_array_compatibility(shape, old_format, new_format, vertex_count, blend_vertex_array, blend_attribute_array, blend_skin_array); - blend_shapes.push_back(shape); + blend_shapes.append_array(blend_vertex_array); } } //clear unused flags - print_line("format pre: " + itos(format)); - format &= ~uint32_t((1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE)) | (ARRAY_COMPRESS_INDEX << 2) | (ARRAY_COMPRESS_TEX_UV2 << 2)); - print_line("format post: " + itos(format)); + print_line("format pre: " + itos(old_format)); + + print_line("format post: " + itos(new_format)); ERR_FAIL_COND_V(!d.has("aabb"), false); AABB aabb = d["aabb"]; @@ -848,8 +1063,8 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } } - add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb); -#endif + add_surface(new_format, PrimitiveType(primitive), vertex_array, attribute_array, skin_array, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb); + } else { ERR_FAIL_V(false); } @@ -1120,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)); } } } @@ -1658,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 14f9504dc9..98997e482a 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1407,14 +1407,26 @@ void CurveTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_curve", "curve"), &CurveTexture::set_curve); ClassDB::bind_method(D_METHOD("get_curve"), &CurveTexture::get_curve); + ClassDB::bind_method(D_METHOD("set_texture_mode", "texture_mode"), &CurveTexture::set_texture_mode); + ClassDB::bind_method(D_METHOD("get_texture_mode"), &CurveTexture::get_texture_mode); + 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"); + + BIND_ENUM_CONSTANT(TEXTURE_MODE_RGB); + BIND_ENUM_CONSTANT(TEXTURE_MODE_RED); } void CurveTexture::set_width(int p_width) { ERR_FAIL_COND(p_width < 32 || p_width > 4096); + + if (_width == p_width) { + return; + } + _width = p_width; _update(); } @@ -1450,7 +1462,7 @@ void CurveTexture::set_curve(Ref<Curve> p_curve) { void CurveTexture::_update() { Vector<uint8_t> data; - data.resize(_width * sizeof(float)); + data.resize(_width * sizeof(float) * (texture_mode == TEXTURE_MODE_RGB ? 3 : 1)); // The array is locked in that scope { @@ -1461,24 +1473,42 @@ void CurveTexture::_update() { Curve &curve = **_curve; for (int i = 0; i < _width; ++i) { float t = i / static_cast<float>(_width); - wd[i] = curve.interpolate_baked(t); + if (texture_mode == TEXTURE_MODE_RGB) { + wd[i * 3 + 0] = curve.interpolate_baked(t); + wd[i * 3 + 1] = wd[i * 3 + 0]; + wd[i * 3 + 2] = wd[i * 3 + 0]; + } else { + wd[i] = curve.interpolate_baked(t); + } } } else { for (int i = 0; i < _width; ++i) { - wd[i] = 0; + if (texture_mode == TEXTURE_MODE_RGB) { + wd[i * 3 + 0] = 0; + wd[i * 3 + 1] = 0; + wd[i * 3 + 2] = 0; + } else { + wd[i] = 0; + } } } } - Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data)); + Ref<Image> image = memnew(Image(_width, 1, false, texture_mode == TEXTURE_MODE_RGB ? Image::FORMAT_RGBF : Image::FORMAT_RF, data)); if (_texture.is_valid()) { - RID new_texture = RS::get_singleton()->texture_2d_create(image); - RS::get_singleton()->texture_replace(_texture, new_texture); + if (_current_texture_mode != texture_mode || _current_width != _width) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(_texture, new_texture); + } else { + RS::get_singleton()->texture_2d_update(_texture, image); + } } else { _texture = RS::get_singleton()->texture_2d_create(image); } + _current_texture_mode = texture_mode; + _current_width = _width; emit_changed(); } @@ -1487,6 +1517,17 @@ Ref<Curve> CurveTexture::get_curve() const { return _curve; } +void CurveTexture::set_texture_mode(TextureMode p_mode) { + if (texture_mode == p_mode) { + return; + } + texture_mode = p_mode; + _update(); +} +CurveTexture::TextureMode CurveTexture::get_texture_mode() const { + return texture_mode; +} + RID CurveTexture::get_rid() const { if (!_texture.is_valid()) { _texture = RS::get_singleton()->texture_2d_placeholder_create(); @@ -1504,6 +1545,204 @@ CurveTexture::~CurveTexture() { ////////////////// +void Curve3Texture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &Curve3Texture::set_width); + + ClassDB::bind_method(D_METHOD("set_curve_x", "curve"), &Curve3Texture::set_curve_x); + ClassDB::bind_method(D_METHOD("get_curve_x"), &Curve3Texture::get_curve_x); + + ClassDB::bind_method(D_METHOD("set_curve_y", "curve"), &Curve3Texture::set_curve_y); + ClassDB::bind_method(D_METHOD("get_curve_y"), &Curve3Texture::get_curve_y); + + ClassDB::bind_method(D_METHOD("set_curve_z", "curve"), &Curve3Texture::set_curve_z); + ClassDB::bind_method(D_METHOD("get_curve_z"), &Curve3Texture::get_curve_z); + + ClassDB::bind_method(D_METHOD("_update"), &Curve3Texture::_update); + + 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"); +} + +void Curve3Texture::set_width(int p_width) { + ERR_FAIL_COND(p_width < 32 || p_width > 4096); + + if (_width == p_width) { + return; + } + + _width = p_width; + _update(); +} + +int Curve3Texture::get_width() const { + return _width; +} + +void Curve3Texture::ensure_default_setup(float p_min, float p_max) { + if (_curve_x.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve_x(curve); + } + + if (_curve_y.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve_y(curve); + } + + if (_curve_z.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); + set_curve_z(curve); + } +} + +void Curve3Texture::set_curve_x(Ref<Curve> p_curve) { + if (_curve_x != p_curve) { + if (_curve_x.is_valid()) { + _curve_x->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Curve3Texture::_update)); + } + _curve_x = p_curve; + if (_curve_x.is_valid()) { + _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Curve3Texture::_update), varray(), CONNECT_REFERENCE_COUNTED); + } + _update(); + } +} + +void Curve3Texture::set_curve_y(Ref<Curve> p_curve) { + if (_curve_y != p_curve) { + if (_curve_y.is_valid()) { + _curve_y->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Curve3Texture::_update)); + } + _curve_y = p_curve; + if (_curve_y.is_valid()) { + _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Curve3Texture::_update), varray(), CONNECT_REFERENCE_COUNTED); + } + _update(); + } +} + +void Curve3Texture::set_curve_z(Ref<Curve> p_curve) { + if (_curve_z != p_curve) { + if (_curve_z.is_valid()) { + _curve_z->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Curve3Texture::_update)); + } + _curve_z = p_curve; + if (_curve_z.is_valid()) { + _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Curve3Texture::_update), varray(), CONNECT_REFERENCE_COUNTED); + } + _update(); + } +} + +void Curve3Texture::_update() { + Vector<uint8_t> data; + data.resize(_width * sizeof(float) * 3); + + // The array is locked in that scope + { + uint8_t *wd8 = data.ptrw(); + float *wd = (float *)wd8; + + if (_curve_x.is_valid()) { + Curve &curve_x = **_curve_x; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + wd[i * 3 + 0] = curve_x.interpolate_baked(t); + } + + } else { + for (int i = 0; i < _width; ++i) { + wd[i * 3 + 0] = 0; + } + } + + if (_curve_y.is_valid()) { + Curve &curve_y = **_curve_y; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + wd[i * 3 + 1] = curve_y.interpolate_baked(t); + } + + } else { + for (int i = 0; i < _width; ++i) { + wd[i * 3 + 1] = 0; + } + } + + if (_curve_z.is_valid()) { + Curve &curve_z = **_curve_z; + for (int i = 0; i < _width; ++i) { + float t = i / static_cast<float>(_width); + wd[i * 3 + 2] = curve_z.interpolate_baked(t); + } + + } else { + for (int i = 0; i < _width; ++i) { + wd[i * 3 + 2] = 0; + } + } + } + + Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RGBF, data)); + + if (_texture.is_valid()) { + if (_current_width != _width) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(_texture, new_texture); + } else { + RS::get_singleton()->texture_2d_update(_texture, image); + } + } else { + _texture = RS::get_singleton()->texture_2d_create(image); + } + _current_width = _width; + + emit_changed(); +} + +Ref<Curve> Curve3Texture::get_curve_x() const { + return _curve_x; +} + +Ref<Curve> Curve3Texture::get_curve_y() const { + return _curve_y; +} + +Ref<Curve> Curve3Texture::get_curve_z() const { + return _curve_z; +} + +RID Curve3Texture::get_rid() const { + if (!_texture.is_valid()) { + _texture = RS::get_singleton()->texture_2d_placeholder_create(); + } + return _texture; +} + +Curve3Texture::Curve3Texture() {} + +Curve3Texture::~Curve3Texture() { + if (_texture.is_valid()) { + RS::get_singleton()->free(_texture); + } +} + +////////////////// + GradientTexture::GradientTexture() { _queue_update(); } @@ -1523,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/texture.h b/scene/resources/texture.h index 40193e3ff6..73390039cb 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -586,11 +586,19 @@ public: class CurveTexture : public Texture2D { GDCLASS(CurveTexture, Texture2D); RES_BASE_EXTENSION("curvetex") +public: + enum TextureMode { + TEXTURE_MODE_RGB, + TEXTURE_MODE_RED, + }; private: mutable RID _texture; Ref<Curve> _curve; int _width = 2048; + int _current_width = 0; + TextureMode texture_mode = TEXTURE_MODE_RGB; + TextureMode _current_texture_mode = TEXTURE_MODE_RGB; void _update(); @@ -601,6 +609,9 @@ public: void set_width(int p_width); int get_width() const override; + void set_texture_mode(TextureMode p_mode); + TextureMode get_texture_mode() const; + void ensure_default_setup(float p_min = 0, float p_max = 1); void set_curve(Ref<Curve> p_curve); @@ -614,18 +625,49 @@ public: CurveTexture(); ~CurveTexture(); }; -/* - enum CubeMapSide { - CUBEMAP_LEFT, - CUBEMAP_RIGHT, - CUBEMAP_BOTTOM, - CUBEMAP_TOP, - CUBEMAP_FRONT, - CUBEMAP_BACK, - }; -*/ -//VARIANT_ENUM_CAST( Texture::CubeMapSide ); +VARIANT_ENUM_CAST(CurveTexture::TextureMode) + +class Curve3Texture : public Texture2D { + GDCLASS(Curve3Texture, Texture2D); + RES_BASE_EXTENSION("curvetex") + +private: + mutable RID _texture; + Ref<Curve> _curve_x; + Ref<Curve> _curve_y; + Ref<Curve> _curve_z; + int _width = 2048; + int _current_width = 0; + + void _update(); + +protected: + static void _bind_methods(); + +public: + void set_width(int p_width); + int get_width() const override; + + void ensure_default_setup(float p_min = 0, float p_max = 1); + + void set_curve_x(Ref<Curve> p_curve); + Ref<Curve> get_curve_x() const; + + void set_curve_y(Ref<Curve> p_curve); + Ref<Curve> get_curve_y() const; + + void set_curve_z(Ref<Curve> p_curve); + Ref<Curve> get_curve_z() const; + + virtual RID get_rid() const override; + + virtual int get_height() const override { return 1; } + virtual bool has_alpha() const override { return false; } + + Curve3Texture(); + ~Curve3Texture(); +}; class GradientTexture : public Texture2D { GDCLASS(GradientTexture, Texture2D); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 89ac033207..303bbf38f4 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -263,6 +263,21 @@ Vector<String> Theme::_get_theme_item_type_list(DataType p_data_type) const { return Vector<String>(); } +Vector<String> Theme::_get_type_variation_list(const StringName &p_theme_type) const { + Vector<String> ilret; + List<StringName> il; + + get_type_variation_list(p_theme_type, &il); + ilret.resize(il.size()); + + int i = 0; + String *w = ilret.ptrw(); + for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { + w[i] = E->get(); + } + return ilret; +} + Vector<String> Theme::_get_type_list() const { Vector<String> ilret; List<StringName> il; @@ -292,10 +307,14 @@ bool Theme::_set(const StringName &p_name, const Variant &p_value) { set_stylebox(name, theme_type, p_value); } else if (type == "fonts") { set_font(name, theme_type, p_value); + } else if (type == "font_sizes") { + set_font_size(name, theme_type, p_value); } else if (type == "colors") { set_color(name, theme_type, p_value); } else if (type == "constants") { set_constant(name, theme_type, p_value); + } else if (type == "base_type") { + set_type_variation(theme_type, p_value); } else { return false; } @@ -332,10 +351,14 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const { } else { r_ret = get_font(name, theme_type); } + } else if (type == "font_sizes") { + r_ret = get_font_size(name, theme_type); } else if (type == "colors") { r_ret = get_color(name, theme_type); } else if (type == "constants") { r_ret = get_constant(name, theme_type); + } else if (type == "base_type") { + r_ret = get_type_variation_base(theme_type); } else { return false; } @@ -351,6 +374,14 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { const StringName *key = nullptr; + // Type variations. + while ((key = variation_map.next(key))) { + list.push_back(PropertyInfo(Variant::STRING_NAME, String() + *key + "/base_type")); + } + + key = nullptr; + + // Icons. while ((key = icon_map.next(key))) { const StringName *key2 = nullptr; @@ -361,6 +392,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { key = nullptr; + // Styles. while ((key = style_map.next(key))) { const StringName *key2 = nullptr; @@ -371,6 +403,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { key = nullptr; + // Fonts. while ((key = font_map.next(key))) { const StringName *key2 = nullptr; @@ -381,6 +414,18 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { key = nullptr; + // Font sizes. + while ((key = font_size_map.next(key))) { + const StringName *key2 = nullptr; + + while ((key2 = font_size_map[*key].next(key2))) { + list.push_back(PropertyInfo(Variant::INT, String() + *key + "/font_sizes/" + *key2)); + } + } + + key = nullptr; + + // Colors. while ((key = color_map.next(key))) { const StringName *key2 = nullptr; @@ -391,6 +436,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { key = nullptr; + // Constants. while ((key = constant_map.next(key))) { const StringName *key2 = nullptr; @@ -399,6 +445,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { } } + // Sort and store properties. list.sort(); for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) { p_list->push_back(E->get()); @@ -1183,6 +1230,63 @@ void Theme::get_theme_item_type_list(DataType p_data_type, List<StringName> *p_l } } +void Theme::set_type_variation(const StringName &p_theme_type, const StringName &p_base_type) { + ERR_FAIL_COND_MSG(p_theme_type == StringName(), "An empty theme type cannot be marked as a variation of another type."); + ERR_FAIL_COND_MSG(ClassDB::class_exists(p_theme_type), "A type associated with a built-in class cannot be marked as a variation of another type."); + ERR_FAIL_COND_MSG(p_base_type == StringName(), "An empty theme type cannot be the base type of a variation. Use clear_type_variation() instead if you want to unmark '" + String(p_theme_type) + "' as a variation."); + + if (variation_map.has(p_theme_type)) { + StringName old_base = variation_map[p_theme_type]; + variation_base_map[old_base].erase(p_theme_type); + } + + variation_map[p_theme_type] = p_base_type; + variation_base_map[p_base_type].push_back(p_theme_type); + + _emit_theme_changed(); +} + +bool Theme::is_type_variation(const StringName &p_theme_type, const StringName &p_base_type) const { + return (variation_map.has(p_theme_type) && variation_map[p_theme_type] == p_base_type); +} + +void Theme::clear_type_variation(const StringName &p_theme_type) { + ERR_FAIL_COND_MSG(!variation_map.has(p_theme_type), "Cannot clear the type variation '" + String(p_theme_type) + "' because it does not exist."); + + StringName base_type = variation_map[p_theme_type]; + variation_base_map[base_type].erase(p_theme_type); + variation_map.erase(p_theme_type); + + _emit_theme_changed(); +} + +StringName Theme::get_type_variation_base(const StringName &p_theme_type) const { + if (!variation_map.has(p_theme_type)) { + return StringName(); + } + + return variation_map[p_theme_type]; +} + +void Theme::get_type_variation_list(const StringName &p_base_type, List<StringName> *p_list) const { + ERR_FAIL_NULL(p_list); + + if (!variation_base_map.has(p_base_type)) { + return; + } + + for (const List<StringName>::Element *E = variation_base_map[p_base_type].front(); E; E = E->next()) { + // Prevent infinite loops if variants were set to be cross-dependent (that's still invalid usage, but handling for stability sake). + if (p_list->find(E->get())) { + continue; + } + + p_list->push_back(E->get()); + // Continue looking for sub-variations. + get_type_variation_list(E->get(), p_list); + } +} + void Theme::_freeze_change_propagation() { no_change_propagation = true; } @@ -1236,9 +1340,13 @@ void Theme::clear() { icon_map.clear(); style_map.clear(); font_map.clear(); + font_size_map.clear(); color_map.clear(); constant_map.clear(); + variation_map.clear(); + variation_base_map.clear(); + _emit_theme_changed(); } @@ -1291,6 +1399,9 @@ void Theme::copy_theme(const Ref<Theme> &p_other) { color_map = p_other->color_map; constant_map = p_other->constant_map; + variation_map = p_other->variation_map; + variation_base_map = p_other->variation_base_map; + _unfreeze_and_propagate_changes(); } @@ -1300,30 +1411,42 @@ void Theme::get_type_list(List<StringName> *p_list) const { Set<StringName> types; const StringName *key = nullptr; + // Icons. while ((key = icon_map.next(key))) { types.insert(*key); } key = nullptr; + // StyleBoxes. while ((key = style_map.next(key))) { types.insert(*key); } key = nullptr; + // Fonts. while ((key = font_map.next(key))) { types.insert(*key); } key = nullptr; + // Font sizes. + while ((key = font_size_map.next(key))) { + types.insert(*key); + } + + key = nullptr; + + // Colors. while ((key = color_map.next(key))) { types.insert(*key); } key = nullptr; + // Constants. while ((key = constant_map.next(key))) { types.insert(*key); } @@ -1333,10 +1456,25 @@ void Theme::get_type_list(List<StringName> *p_list) const { } } -void Theme::get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) { +void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) { ERR_FAIL_NULL(p_list); - StringName class_name = p_theme_type; + // Build the dependency chain for type variations. + if (p_type_variation != StringName()) { + StringName variation_name = p_type_variation; + while (variation_name != StringName()) { + p_list->push_back(variation_name); + variation_name = get_type_variation_base(variation_name); + + // If we have reached the base type dependency, it's safe to stop (assuming no funny business was done to the Theme). + if (variation_name == p_base_type) { + break; + } + } + } + + // Continue building the chain using native class hierarchy. + StringName class_name = p_base_type; while (class_name != StringName()) { p_list->push_back(class_name); class_name = ClassDB::get_parent_class_nocheck(class_name); @@ -1346,6 +1484,7 @@ void Theme::get_type_dependencies(const StringName &p_theme_type, List<StringNam void Theme::reset_state() { clear(); } + void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("set_icon", "name", "theme_type", "texture"), &Theme::set_icon); ClassDB::bind_method(D_METHOD("get_icon", "name", "theme_type"), &Theme::get_icon); @@ -1411,6 +1550,12 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("get_theme_item_list", "data_type", "theme_type"), &Theme::_get_theme_item_list); ClassDB::bind_method(D_METHOD("get_theme_item_type_list", "data_type"), &Theme::_get_theme_item_type_list); + ClassDB::bind_method(D_METHOD("set_type_variation", "theme_type", "base_type"), &Theme::set_type_variation); + ClassDB::bind_method(D_METHOD("is_type_variation", "theme_type", "base_type"), &Theme::is_type_variation); + ClassDB::bind_method(D_METHOD("clear_type_variation", "theme_type"), &Theme::clear_type_variation); + ClassDB::bind_method(D_METHOD("get_type_variation_base", "theme_type"), &Theme::get_type_variation_base); + ClassDB::bind_method(D_METHOD("get_type_variation_list", "base_type"), &Theme::_get_type_variation_list); + ClassDB::bind_method(D_METHOD("get_type_list"), &Theme::_get_type_list); ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index fe64fd7290..8a8fc28be1 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -69,6 +69,8 @@ private: HashMap<StringName, HashMap<StringName, int>> font_size_map; HashMap<StringName, HashMap<StringName, Color>> color_map; HashMap<StringName, HashMap<StringName, int>> constant_map; + HashMap<StringName, StringName> variation_map; + HashMap<StringName, List<StringName>> variation_base_map; Vector<String> _get_icon_list(const String &p_theme_type) const; Vector<String> _get_icon_type_list() const; @@ -85,6 +87,8 @@ private: Vector<String> _get_theme_item_list(DataType p_data_type, const String &p_theme_type) const; Vector<String> _get_theme_item_type_list(DataType p_data_type) const; + + Vector<String> _get_type_variation_list(const StringName &p_theme_type) const; Vector<String> _get_type_list() const; protected: @@ -197,8 +201,14 @@ public: void add_theme_item_type(DataType p_data_type, const StringName &p_theme_type); void get_theme_item_type_list(DataType p_data_type, List<StringName> *p_list) const; + void set_type_variation(const StringName &p_theme_type, const StringName &p_base_type); + bool is_type_variation(const StringName &p_theme_type, const StringName &p_base_type) const; + void clear_type_variation(const StringName &p_theme_type); + StringName get_type_variation_base(const StringName &p_theme_type) const; + void get_type_variation_list(const StringName &p_base_type, List<StringName> *p_list) const; + void get_type_list(List<StringName> *p_list) const; - static void get_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list); + void get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variant, List<StringName> *p_list); void copy_default_theme(); void copy_theme(const Ref<Theme> &p_other); 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); |