diff options
Diffstat (limited to 'scene')
28 files changed, 1072 insertions, 686 deletions
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 24f3301ce1..a341ba69ac 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -463,10 +463,6 @@ Vector2 CPUParticles2D::get_gravity() const { } void CPUParticles2D::_validate_property(PropertyInfo &property) const { - if (property.name == "color" && color_ramp.is_valid()) { - property.usage = PROPERTY_USAGE_NONE; - } - if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { property.usage = PROPERTY_USAGE_NONE; } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index be619ed60d..80aa99bf5e 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -86,11 +86,11 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_in // Restore direction of motion to be along original motion, // in order to avoid sliding due to recovery, // but only if collision depth is low enough to avoid tunneling. - real_t motion_length = p_motion.length(); - if (motion_length > CMP_EPSILON) { + if (p_cancel_sliding) { + real_t motion_length = p_motion.length(); real_t precision = 0.001; - if (colliding && p_cancel_sliding) { + if (colliding) { // Can't just use margin as a threshold because collision depth is calculated on unsafe motion, // so even in normal resting cases the depth can be a bit more than the margin. precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction); @@ -101,16 +101,21 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_in } if (p_cancel_sliding) { + // When motion is null, recovery is the resulting motion. + Vector2 motion_normal; + if (motion_length > CMP_EPSILON) { + motion_normal = p_motion / motion_length; + } + // Check depth of recovery. - Vector2 motion_normal = p_motion / motion_length; - real_t dot = r_result.motion.dot(motion_normal); - Vector2 recovery = r_result.motion - motion_normal * dot; + real_t projected_length = r_result.motion.dot(motion_normal); + Vector2 recovery = r_result.motion - motion_normal * projected_length; real_t recovery_length = recovery.length(); // Fixes cases where canceling slide causes the motion to go too deep into the ground, - // Becauses we're only taking rest information into account and not general recovery. + // because we're only taking rest information into account and not general recovery. if (recovery_length < (real_t)p_margin + precision) { // Apply adjustment to motion. - r_result.motion = motion_normal * dot; + r_result.motion = motion_normal * projected_length; r_result.remainder = p_motion - r_result.motion; } } @@ -978,8 +983,9 @@ void CharacterBody2D::move_and_slide() { floor_normal = Vector2(); floor_velocity = Vector2(); - // No sliding on first attempt to keep floor motion stable when possible. - bool sliding_enabled = false; + // No sliding on first attempt to keep floor motion stable when possible, + // when stop on slope is enabled. + bool sliding_enabled = !stop_on_slope; for (int iteration = 0; iteration < max_slides; ++iteration) { PhysicsServer2D::MotionResult result; bool found_collision = false; @@ -1018,7 +1024,11 @@ void CharacterBody2D::move_and_slide() { if (stop_on_slope) { if ((body_velocity_normal + up_direction).length() < 0.01) { Transform2D gt = get_global_transform(); - gt.elements[2] -= result.motion.slide(up_direction); + if (result.motion.length() > margin) { + gt.elements[2] -= result.motion.slide(up_direction); + } else { + gt.elements[2] -= result.motion; + } set_global_transform(gt); linear_velocity = Vector2(); return; @@ -1054,7 +1064,7 @@ void CharacterBody2D::move_and_slide() { // Apply snap. Transform2D gt = get_global_transform(); PhysicsServer2D::MotionResult result; - if (move_and_collide(snap, infinite_inertia, result, margin, false, true)) { + if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) { bool apply = true; if (up_direction != Vector2()) { if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { @@ -1065,9 +1075,12 @@ void CharacterBody2D::move_and_slide() { if (stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - result.motion = up_direction * up_direction.dot(result.motion); + if (result.motion.length() > margin) { + result.motion = up_direction * up_direction.dot(result.motion); + } else { + result.motion = Vector2(); + } } - } else { apply = false; } diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 6dc865ec0e..178a269f17 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -434,10 +434,6 @@ Vector3 CPUParticles3D::get_gravity() const { } void CPUParticles3D::_validate_property(PropertyInfo &property) const { - if (property.name == "color" && color_ramp.is_valid()) { - property.usage = PROPERTY_USAGE_NONE; - } - if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { property.usage = PROPERTY_USAGE_NONE; } 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/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index e7482d35e7..4568145458 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -125,11 +125,11 @@ bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_in // Restore direction of motion to be along original motion, // in order to avoid sliding due to recovery, // but only if collision depth is low enough to avoid tunneling. - real_t motion_length = p_motion.length(); - if (motion_length > CMP_EPSILON) { - real_t precision = CMP_EPSILON; + if (p_cancel_sliding) { + real_t motion_length = p_motion.length(); + real_t precision = 0.001; - if (colliding && p_cancel_sliding) { + if (colliding) { // Can't just use margin as a threshold because collision depth is calculated on unsafe motion, // so even in normal resting cases the depth can be a bit more than the margin. precision += motion_length * (r_result.collision_unsafe_fraction - r_result.collision_safe_fraction); @@ -140,16 +140,21 @@ bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_in } if (p_cancel_sliding) { + // When motion is null, recovery is the resulting motion. + Vector3 motion_normal; + if (motion_length > CMP_EPSILON) { + motion_normal = p_motion / motion_length; + } + // Check depth of recovery. - Vector3 motion_normal = p_motion / motion_length; - real_t dot = r_result.motion.dot(motion_normal); - Vector3 recovery = r_result.motion - motion_normal * dot; + real_t projected_length = r_result.motion.dot(motion_normal); + Vector3 recovery = r_result.motion - motion_normal * projected_length; real_t recovery_length = recovery.length(); // Fixes cases where canceling slide causes the motion to go too deep into the ground, - // Becauses we're only taking rest information into account and not general recovery. + // because we're only taking rest information into account and not general recovery. if (recovery_length < (real_t)p_margin + precision) { // Apply adjustment to motion. - r_result.motion = motion_normal * dot; + r_result.motion = motion_normal * projected_length; r_result.remainder = p_motion - r_result.motion; } } @@ -1012,8 +1017,9 @@ void CharacterBody3D::move_and_slide() { floor_normal = Vector3(); floor_velocity = Vector3(); - // No sliding on first attempt to keep motion stable when possible. - bool sliding_enabled = false; + // No sliding on first attempt to keep floor motion stable when possible, + // when stop on slope is enabled. + bool sliding_enabled = !stop_on_slope; for (int iteration = 0; iteration < max_slides; ++iteration) { PhysicsServer3D::MotionResult result; bool found_collision = false; @@ -1052,7 +1058,11 @@ void CharacterBody3D::move_and_slide() { if (stop_on_slope) { if ((body_velocity_normal + up_direction).length() < 0.01) { Transform3D gt = get_global_transform(); - gt.origin -= result.motion.slide(up_direction); + if (result.motion.length() > margin) { + gt.origin -= result.motion.slide(up_direction); + } else { + gt.origin -= result.motion; + } set_global_transform(gt); linear_velocity = Vector3(); return; @@ -1094,7 +1104,7 @@ void CharacterBody3D::move_and_slide() { // Apply snap. Transform3D gt = get_global_transform(); PhysicsServer3D::MotionResult result; - if (move_and_collide(snap, infinite_inertia, result, margin, false, true)) { + if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) { bool apply = true; if (up_direction != Vector3()) { if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { @@ -1105,7 +1115,11 @@ void CharacterBody3D::move_and_slide() { if (stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - result.motion = result.motion.project(up_direction); + if (result.motion.length() > margin) { + result.motion = result.motion.project(up_direction); + } else { + result.motion = Vector3(); + } } } else { apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. 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/base_button.cpp b/scene/gui/base_button.cpp index c1ae0479f5..8414c4dc78 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -226,6 +226,18 @@ void BaseButton::set_pressed(bool p_pressed) { update(); } +void BaseButton::set_pressed_no_signal(bool p_pressed) { + if (!toggle_mode) { + return; + } + if (status.pressed == p_pressed) { + return; + } + status.pressed = p_pressed; + + update(); +} + bool BaseButton::is_pressing() const { return status.press_attempt; } @@ -399,6 +411,7 @@ void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &BaseButton::_unhandled_key_input); ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed); ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed); + ClassDB::bind_method(D_METHOD("set_pressed_no_signal", "pressed"), &BaseButton::set_pressed_no_signal); ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered); ClassDB::bind_method(D_METHOD("set_toggle_mode", "enabled"), &BaseButton::set_toggle_mode); ClassDB::bind_method(D_METHOD("is_toggle_mode"), &BaseButton::is_toggle_mode); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 6c7a8f3433..d86b35daf0 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -98,7 +98,8 @@ public: bool is_pressing() const; ///< return whether button is pressed (toggled in) bool is_hovered() const; - void set_pressed(bool p_pressed); ///only works in toggle mode + void set_pressed(bool p_pressed); // Only works in toggle mode. + void set_pressed_no_signal(bool p_pressed); void set_toggle_mode(bool p_on); bool is_toggle_mode() const; 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/control.cpp b/scene/gui/control.cpp index d42b505f7b..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; } @@ -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 dceab00607..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) { 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/tree.cpp b/scene/gui/tree.cpp index 98de71d81c..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->edited_item == this) { + tree->edited_item = nullptr; + tree->pressing_for_editor = false; + } - if (tree && 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(); } } diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 9299f8d6be..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(); @@ -542,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 @@ -1170,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); } } @@ -1340,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); @@ -1417,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("")); @@ -1468,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 ea0df685a1..2d83f59bb5 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,451 +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_class<VisualShaderNodeCurve3Texture>(); - 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(VisualShaderNodeCurveXYZTexture); + 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<Curve3Texture>(); - 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(CurveXYZTexture); + 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. 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/particles_material.cpp b/scene/resources/particles_material.cpp index 2bde98abe0..00bea312b3 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -569,7 +569,7 @@ void ParticlesMaterial::_update_shader() { code += " vec4(1.250, -1.050, -0.203, 0.0),\n"; code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n"; if (color_ramp.is_valid()) { - code += " COLOR = hue_rot_mat * textureLod(color_ramp, vec2(tv, 0.0), 0.0);\n"; + code += " COLOR = hue_rot_mat * textureLod(color_ramp, vec2(tv, 0.0), 0.0) * color_value;\n"; } else { code += " COLOR = hue_rot_mat * color_value;\n"; } @@ -1046,10 +1046,6 @@ RID ParticlesMaterial::get_shader_rid() const { } void ParticlesMaterial::_validate_property(PropertyInfo &property) const { - if (property.name == "color" && color_ramp.is_valid()) { - property.usage = PROPERTY_USAGE_NONE; - } - if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { property.usage = PROPERTY_USAGE_NONE; } diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 98997e482a..26c0d432a9 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1545,19 +1545,19 @@ CurveTexture::~CurveTexture() { ////////////////// -void Curve3Texture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &Curve3Texture::set_width); +void CurveXYZTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveXYZTexture::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_x", "curve"), &CurveXYZTexture::set_curve_x); + ClassDB::bind_method(D_METHOD("get_curve_x"), &CurveXYZTexture::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_y", "curve"), &CurveXYZTexture::set_curve_y); + ClassDB::bind_method(D_METHOD("get_curve_y"), &CurveXYZTexture::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("set_curve_z", "curve"), &CurveXYZTexture::set_curve_z); + ClassDB::bind_method(D_METHOD("get_curve_z"), &CurveXYZTexture::get_curve_z); - ClassDB::bind_method(D_METHOD("_update"), &Curve3Texture::_update); + ClassDB::bind_method(D_METHOD("_update"), &CurveXYZTexture::_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"); @@ -1565,7 +1565,7 @@ void Curve3Texture::_bind_methods() { 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) { +void CurveXYZTexture::set_width(int p_width) { ERR_FAIL_COND(p_width < 32 || p_width > 4096); if (_width == p_width) { @@ -1576,11 +1576,11 @@ void Curve3Texture::set_width(int p_width) { _update(); } -int Curve3Texture::get_width() const { +int CurveXYZTexture::get_width() const { return _width; } -void Curve3Texture::ensure_default_setup(float p_min, float p_max) { +void CurveXYZTexture::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)); @@ -1609,46 +1609,46 @@ void Curve3Texture::ensure_default_setup(float p_min, float p_max) { } } -void Curve3Texture::set_curve_x(Ref<Curve> p_curve) { +void CurveXYZTexture::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->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_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); + _curve_x->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); } _update(); } } -void Curve3Texture::set_curve_y(Ref<Curve> p_curve) { +void CurveXYZTexture::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->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_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); + _curve_y->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); } _update(); } } -void Curve3Texture::set_curve_z(Ref<Curve> p_curve) { +void CurveXYZTexture::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->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_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); + _curve_z->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveXYZTexture::_update), varray(), CONNECT_REFERENCE_COUNTED); } _update(); } } -void Curve3Texture::_update() { +void CurveXYZTexture::_update() { Vector<uint8_t> data; data.resize(_width * sizeof(float) * 3); @@ -1714,28 +1714,28 @@ void Curve3Texture::_update() { emit_changed(); } -Ref<Curve> Curve3Texture::get_curve_x() const { +Ref<Curve> CurveXYZTexture::get_curve_x() const { return _curve_x; } -Ref<Curve> Curve3Texture::get_curve_y() const { +Ref<Curve> CurveXYZTexture::get_curve_y() const { return _curve_y; } -Ref<Curve> Curve3Texture::get_curve_z() const { +Ref<Curve> CurveXYZTexture::get_curve_z() const { return _curve_z; } -RID Curve3Texture::get_rid() const { +RID CurveXYZTexture::get_rid() const { if (!_texture.is_valid()) { _texture = RS::get_singleton()->texture_2d_placeholder_create(); } return _texture; } -Curve3Texture::Curve3Texture() {} +CurveXYZTexture::CurveXYZTexture() {} -Curve3Texture::~Curve3Texture() { +CurveXYZTexture::~CurveXYZTexture() { if (_texture.is_valid()) { RS::get_singleton()->free(_texture); } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 73390039cb..98aa61138d 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -628,8 +628,8 @@ public: VARIANT_ENUM_CAST(CurveTexture::TextureMode) -class Curve3Texture : public Texture2D { - GDCLASS(Curve3Texture, Texture2D); +class CurveXYZTexture : public Texture2D { + GDCLASS(CurveXYZTexture, Texture2D); RES_BASE_EXTENSION("curvetex") private: @@ -665,8 +665,8 @@ public: virtual int get_height() const override { return 1; } virtual bool has_alpha() const override { return false; } - Curve3Texture(); - ~Curve3Texture(); + CurveXYZTexture(); + ~CurveXYZTexture(); }; class GradientTexture : public 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/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 4e73b8db44..79ea9d72df 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -889,56 +889,56 @@ VisualShaderNodeCurveTexture::VisualShaderNodeCurveTexture() { allow_v_resize = false; } -////////////// Curve3Texture +////////////// CurveXYZTexture -String VisualShaderNodeCurve3Texture::get_caption() const { - return "Curve3Texture"; +String VisualShaderNodeCurveXYZTexture::get_caption() const { + return "CurveXYZTexture"; } -int VisualShaderNodeCurve3Texture::get_input_port_count() const { +int VisualShaderNodeCurveXYZTexture::get_input_port_count() const { return 1; } -VisualShaderNodeCurve3Texture::PortType VisualShaderNodeCurve3Texture::get_input_port_type(int p_port) const { +VisualShaderNodeCurveXYZTexture::PortType VisualShaderNodeCurveXYZTexture::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeCurve3Texture::get_input_port_name(int p_port) const { +String VisualShaderNodeCurveXYZTexture::get_input_port_name(int p_port) const { return String(); } -int VisualShaderNodeCurve3Texture::get_output_port_count() const { +int VisualShaderNodeCurveXYZTexture::get_output_port_count() const { return 1; } -VisualShaderNodeCurve3Texture::PortType VisualShaderNodeCurve3Texture::get_output_port_type(int p_port) const { +VisualShaderNodeCurveXYZTexture::PortType VisualShaderNodeCurveXYZTexture::get_output_port_type(int p_port) const { return PORT_TYPE_VECTOR; } -String VisualShaderNodeCurve3Texture::get_output_port_name(int p_port) const { +String VisualShaderNodeCurveXYZTexture::get_output_port_name(int p_port) const { return String(); } -void VisualShaderNodeCurve3Texture::set_texture(Ref<Curve3Texture> p_texture) { +void VisualShaderNodeCurveXYZTexture::set_texture(Ref<CurveXYZTexture> p_texture) { texture = p_texture; emit_changed(); } -Ref<Curve3Texture> VisualShaderNodeCurve3Texture::get_texture() const { +Ref<CurveXYZTexture> VisualShaderNodeCurveXYZTexture::get_texture() const { return texture; } -Vector<StringName> VisualShaderNodeCurve3Texture::get_editable_properties() const { +Vector<StringName> VisualShaderNodeCurveXYZTexture::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 { +String VisualShaderNodeCurveXYZTexture::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 { +String VisualShaderNodeCurveXYZTexture::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"; } @@ -948,7 +948,7 @@ String VisualShaderNodeCurve3Texture::generate_code(Shader::Mode p_mode, VisualS return code; } -Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurve3Texture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurveXYZTexture::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; @@ -957,18 +957,18 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurve3Texture::get_def 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); +void VisualShaderNodeCurveXYZTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &VisualShaderNodeCurveXYZTexture::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeCurveXYZTexture::get_texture); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Curve3Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "CurveXYZTexture"), "set_texture", "get_texture"); } -bool VisualShaderNodeCurve3Texture::is_use_prop_slots() const { +bool VisualShaderNodeCurveXYZTexture::is_use_prop_slots() const { return true; } -VisualShaderNodeCurve3Texture::VisualShaderNodeCurve3Texture() { +VisualShaderNodeCurveXYZTexture::VisualShaderNodeCurveXYZTexture() { simple_decl = true; allow_v_resize = false; } diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 3ae79723e9..33a45a4384 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -338,9 +338,9 @@ public: /////////////////////////////////////// -class VisualShaderNodeCurve3Texture : public VisualShaderNodeResizableBase { - GDCLASS(VisualShaderNodeCurve3Texture, VisualShaderNodeResizableBase); - Ref<Curve3Texture> texture; +class VisualShaderNodeCurveXYZTexture : public VisualShaderNodeResizableBase { + GDCLASS(VisualShaderNodeCurveXYZTexture, VisualShaderNodeResizableBase); + Ref<CurveXYZTexture> texture; protected: static void _bind_methods(); @@ -360,13 +360,13 @@ public: 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; + void set_texture(Ref<CurveXYZTexture> p_value); + Ref<CurveXYZTexture> get_texture() const; virtual Vector<StringName> get_editable_properties() const override; virtual bool is_use_prop_slots() const override; - VisualShaderNodeCurve3Texture(); + VisualShaderNodeCurveXYZTexture(); }; /////////////////////////////////////// |