summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/area_2d.cpp20
-rw-r--r--scene/2d/cpu_particles_2d.cpp34
-rw-r--r--scene/2d/line_builder.cpp10
-rw-r--r--scene/2d/navigation_link_2d.cpp284
-rw-r--r--scene/2d/navigation_link_2d.h (renamed from scene/resources/camera_effects.h)103
-rw-r--r--scene/2d/path_2d.cpp12
-rw-r--r--scene/2d/physics_body_2d.cpp10
-rw-r--r--scene/2d/touch_screen_button.cpp2
-rw-r--r--scene/3d/area_3d.cpp25
-rw-r--r--scene/3d/camera_3d.cpp60
-rw-r--r--scene/3d/camera_3d.h15
-rw-r--r--scene/3d/cpu_particles_3d.cpp36
-rw-r--r--scene/3d/fog_volume.cpp1
-rw-r--r--scene/3d/label_3d.cpp3
-rw-r--r--scene/3d/light_3d.cpp91
-rw-r--r--scene/3d/light_3d.h9
-rw-r--r--scene/3d/lightmap_gi.cpp49
-rw-r--r--scene/3d/lightmap_gi.h11
-rw-r--r--scene/3d/lightmapper.h2
-rw-r--r--scene/3d/navigation_link_3d.cpp389
-rw-r--r--scene/3d/navigation_link_3d.h (renamed from scene/gui/gradient_edit.h)94
-rw-r--r--scene/3d/node_3d.cpp4
-rw-r--r--scene/3d/occluder_instance_3d.cpp8
-rw-r--r--scene/3d/occluder_instance_3d.h6
-rw-r--r--scene/3d/path_3d.cpp20
-rw-r--r--scene/3d/physics_body_3d.cpp14
-rw-r--r--scene/3d/sprite_3d.cpp19
-rw-r--r--scene/3d/sprite_3d.h4
-rw-r--r--scene/3d/visual_instance_3d.cpp28
-rw-r--r--scene/3d/visual_instance_3d.h4
-rw-r--r--scene/3d/voxel_gi.cpp23
-rw-r--r--scene/3d/voxel_gi.h7
-rw-r--r--scene/3d/voxelizer.cpp10
-rw-r--r--scene/3d/voxelizer.h3
-rw-r--r--scene/3d/world_environment.cpp54
-rw-r--r--scene/3d/world_environment.h10
-rw-r--r--scene/animation/animation_blend_tree.cpp4
-rw-r--r--scene/animation/animation_node_state_machine.cpp61
-rw-r--r--scene/gui/box_container.cpp38
-rw-r--r--scene/gui/box_container.h17
-rw-r--r--scene/gui/button.cpp134
-rw-r--r--scene/gui/button.h38
-rw-r--r--scene/gui/check_box.cpp96
-rw-r--r--scene/gui/check_box.h17
-rw-r--r--scene/gui/check_button.cpp90
-rw-r--r--scene/gui/check_button.h17
-rw-r--r--scene/gui/color_picker.cpp2
-rw-r--r--scene/gui/control.cpp10
-rw-r--r--scene/gui/control.h4
-rw-r--r--scene/gui/dialogs.cpp31
-rw-r--r--scene/gui/dialogs.h7
-rw-r--r--scene/gui/file_dialog.cpp107
-rw-r--r--scene/gui/file_dialog.h21
-rw-r--r--scene/gui/flow_container.cpp52
-rw-r--r--scene/gui/flow_container.h18
-rw-r--r--scene/gui/gradient_edit.cpp446
-rw-r--r--scene/gui/grid_container.cpp27
-rw-r--r--scene/gui/grid_container.h7
-rw-r--r--scene/gui/item_list.cpp141
-rw-r--r--scene/gui/item_list.h28
-rw-r--r--scene/gui/label.cpp65
-rw-r--r--scene/gui/label.h17
-rw-r--r--scene/gui/line_edit.cpp103
-rw-r--r--scene/gui/line_edit.h26
-rw-r--r--scene/gui/link_button.cpp44
-rw-r--r--scene/gui/link_button.h19
-rw-r--r--scene/gui/margin_container.cpp29
-rw-r--r--scene/gui/margin_container.h9
-rw-r--r--scene/gui/menu_bar.cpp108
-rw-r--r--scene/gui/menu_bar.h29
-rw-r--r--scene/gui/option_button.cpp69
-rw-r--r--scene/gui/option_button.h18
-rw-r--r--scene/gui/panel.cpp9
-rw-r--r--scene/gui/panel.h6
-rw-r--r--scene/gui/panel_container.cpp42
-rw-r--r--scene/gui/panel_container.h5
-rw-r--r--scene/gui/popup.cpp30
-rw-r--r--scene/gui/popup.h11
-rw-r--r--scene/gui/popup_menu.cpp207
-rw-r--r--scene/gui/popup_menu.h45
-rw-r--r--scene/gui/progress_bar.cpp60
-rw-r--r--scene/gui/progress_bar.h13
-rw-r--r--scene/gui/rich_text_label.cpp262
-rw-r--r--scene/gui/rich_text_label.h41
-rw-r--r--scene/gui/scroll_bar.cpp76
-rw-r--r--scene/gui/scroll_bar.h19
-rw-r--r--scene/gui/scroll_container.cpp20
-rw-r--r--scene/gui/scroll_container.h5
-rw-r--r--scene/gui/separator.cpp18
-rw-r--r--scene/gui/separator.h8
-rw-r--r--scene/gui/slider.cpp57
-rw-r--r--scene/gui/slider.h15
-rw-r--r--scene/gui/spin_box.cpp16
-rw-r--r--scene/gui/spin_box.h5
-rw-r--r--scene/gui/split_container.cpp81
-rw-r--r--scene/gui/split_container.h21
-rw-r--r--scene/gui/tab_bar.cpp204
-rw-r--r--scene/gui/tab_bar.h29
-rw-r--r--scene/gui/tab_container.cpp132
-rw-r--r--scene/gui/tab_container.h35
-rw-r--r--scene/gui/texture_button.cpp2
-rw-r--r--scene/gui/tree.cpp512
-rw-r--r--scene/gui/tree.h12
-rw-r--r--scene/main/canvas_item.cpp1
-rw-r--r--scene/main/multiplayer_peer.cpp110
-rw-r--r--scene/main/multiplayer_peer.h67
-rw-r--r--scene/main/scene_tree.cpp25
-rw-r--r--scene/main/shader_globals_override.cpp14
-rw-r--r--scene/main/viewport.cpp63
-rw-r--r--scene/main/viewport.h1
-rw-r--r--scene/main/window.cpp70
-rw-r--r--scene/main/window.h18
-rw-r--r--scene/register_scene_types.cpp64
-rw-r--r--scene/resources/bit_map.cpp150
-rw-r--r--scene/resources/bit_map.h27
-rw-r--r--scene/resources/camera_attributes.cpp493
-rw-r--r--scene/resources/camera_attributes.h183
-rw-r--r--scene/resources/camera_effects.cpp206
-rw-r--r--scene/resources/curve.cpp58
-rw-r--r--scene/resources/curve.h22
-rw-r--r--scene/resources/default_theme/default_theme.cpp15
-rw-r--r--scene/resources/environment.cpp157
-rw-r--r--scene/resources/environment.h31
-rw-r--r--scene/resources/gradient.cpp2
-rw-r--r--scene/resources/gradient.h2
-rw-r--r--scene/resources/material.cpp81
-rw-r--r--scene/resources/material.h14
-rw-r--r--scene/resources/primitive_meshes.cpp8
-rw-r--r--scene/resources/rectangle_shape_2d.cpp8
-rw-r--r--scene/resources/rectangle_shape_2d.h6
-rw-r--r--scene/resources/shader.cpp40
-rw-r--r--scene/resources/shader.h8
-rw-r--r--scene/resources/sky_material.cpp82
-rw-r--r--scene/resources/sky_material.h26
-rw-r--r--scene/resources/style_box.cpp2
-rw-r--r--scene/resources/text_paragraph.cpp2
-rw-r--r--scene/resources/texture.cpp16
-rw-r--r--scene/resources/tile_set.cpp25
-rw-r--r--scene/resources/tile_set.h6
-rw-r--r--scene/resources/visual_shader.cpp344
-rw-r--r--scene/resources/visual_shader.h80
-rw-r--r--scene/resources/visual_shader_nodes.cpp767
-rw-r--r--scene/resources/visual_shader_nodes.h119
-rw-r--r--scene/resources/world_2d.cpp1
-rw-r--r--scene/resources/world_3d.cpp23
-rw-r--r--scene/resources/world_3d.h8
146 files changed, 5384 insertions, 3482 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 75f1497edc..f168d0c139 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -426,36 +426,36 @@ bool Area2D::is_monitorable() const {
}
TypedArray<Node2D> Area2D::get_overlapping_bodies() const {
- ERR_FAIL_COND_V_MSG(!monitoring, Array(), "Can't find overlapping bodies when monitoring is off.");
TypedArray<Node2D> ret;
+ ERR_FAIL_COND_V_MSG(!monitoring, ret, "Can't find overlapping bodies when monitoring is off.");
ret.resize(body_map.size());
int idx = 0;
for (const KeyValue<ObjectID, BodyState> &E : body_map) {
Object *obj = ObjectDB::get_instance(E.key);
- if (!obj) {
- ret.resize(ret.size() - 1); //ops
- } else {
- ret[idx++] = obj;
+ if (obj) {
+ ret[idx] = obj;
+ idx++;
}
}
+ ret.resize(idx);
return ret;
}
TypedArray<Area2D> Area2D::get_overlapping_areas() const {
- ERR_FAIL_COND_V_MSG(!monitoring, Array(), "Can't find overlapping bodies when monitoring is off.");
TypedArray<Area2D> ret;
+ ERR_FAIL_COND_V_MSG(!monitoring, ret, "Can't find overlapping areas when monitoring is off.");
ret.resize(area_map.size());
int idx = 0;
for (const KeyValue<ObjectID, AreaState> &E : area_map) {
Object *obj = ObjectDB::get_instance(E.key);
- if (!obj) {
- ret.resize(ret.size() - 1); //ops
- } else {
- ret[idx++] = obj;
+ if (obj) {
+ ret[idx] = obj;
+ idx++;
}
}
+ ret.resize(idx);
return ret;
}
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index dfe2ce0ec3..58e357ab5f 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -719,17 +719,17 @@ void CPUParticles2D::_particles_process(double p_delta) {
/*real_t tex_linear_velocity = 0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0);
+ tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->sample(0);
}*/
real_t tex_angle = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
- tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
+ tex_angle = curve_parameters[PARAM_ANGLE]->sample(tv);
}
real_t tex_anim_offset = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
- tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv);
+ tex_anim_offset = curve_parameters[PARAM_ANGLE]->sample(tv);
}
p.seed = Math::rand();
@@ -825,51 +825,51 @@ void CPUParticles2D::_particles_process(double p_delta) {
real_t tex_linear_velocity = 1.0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv);
+ tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->sample(tv);
}
real_t tex_orbit_velocity = 1.0;
if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
- tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv);
+ tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->sample(tv);
}
real_t tex_angular_velocity = 1.0;
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
- tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv);
+ tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->sample(tv);
}
real_t tex_linear_accel = 1.0;
if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
- tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv);
+ tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->sample(tv);
}
real_t tex_tangential_accel = 1.0;
if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
- tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv);
+ tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->sample(tv);
}
real_t tex_radial_accel = 1.0;
if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
- tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv);
+ tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->sample(tv);
}
real_t tex_damping = 1.0;
if (curve_parameters[PARAM_DAMPING].is_valid()) {
- tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv);
+ tex_damping = curve_parameters[PARAM_DAMPING]->sample(tv);
}
real_t tex_angle = 1.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
- tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
+ tex_angle = curve_parameters[PARAM_ANGLE]->sample(tv);
}
real_t tex_anim_speed = 1.0;
if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
- tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv);
+ tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->sample(tv);
}
real_t tex_anim_offset = 1.0;
if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
- tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv);
+ tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->sample(tv);
}
Vector2 force = gravity;
@@ -921,18 +921,18 @@ void CPUParticles2D::_particles_process(double p_delta) {
Vector2 tex_scale = Vector2(1.0, 1.0);
if (split_scale) {
if (scale_curve_x.is_valid()) {
- tex_scale.x = scale_curve_x->interpolate(tv);
+ tex_scale.x = scale_curve_x->sample(tv);
} else {
tex_scale.x = 1.0;
}
if (scale_curve_y.is_valid()) {
- tex_scale.y = scale_curve_y->interpolate(tv);
+ tex_scale.y = scale_curve_y->sample(tv);
} else {
tex_scale.y = 1.0;
}
} else {
if (curve_parameters[PARAM_SCALE].is_valid()) {
- real_t tmp_scale = curve_parameters[PARAM_SCALE]->interpolate(tv);
+ real_t tmp_scale = curve_parameters[PARAM_SCALE]->sample(tv);
tex_scale.x = tmp_scale;
tex_scale.y = tmp_scale;
}
@@ -940,7 +940,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
real_t tex_hue_variation = 0.0;
if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) {
- tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv);
+ tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->sample(tv);
}
real_t hue_rot_angle = (tex_hue_variation)*Math_TAU * Math::lerp(parameters_min[PARAM_HUE_VARIATION], parameters_max[PARAM_HUE_VARIATION], p.hue_rot_rand);
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
index 25eb9b9851..2bbe88b0e0 100644
--- a/scene/2d/line_builder.cpp
+++ b/scene/2d/line_builder.cpp
@@ -137,14 +137,14 @@ void LineBuilder::build() {
// The line's outer length will be a little higher due to begin and end caps
if (begin_cap_mode == Line2D::LINE_CAP_BOX || begin_cap_mode == Line2D::LINE_CAP_ROUND) {
if (retrieve_curve) {
- total_distance += width * curve->interpolate_baked(0.f) * 0.5f;
+ total_distance += width * curve->sample_baked(0.f) * 0.5f;
} else {
total_distance += width * 0.5f;
}
}
if (end_cap_mode == Line2D::LINE_CAP_BOX || end_cap_mode == Line2D::LINE_CAP_ROUND) {
if (retrieve_curve) {
- total_distance += width * curve->interpolate_baked(1.f) * 0.5f;
+ total_distance += width * curve->sample_baked(1.f) * 0.5f;
} else {
total_distance += width * 0.5f;
}
@@ -160,7 +160,7 @@ void LineBuilder::build() {
float uvx1 = 0.f;
if (retrieve_curve) {
- width_factor = curve->interpolate_baked(0.f);
+ width_factor = curve->sample_baked(0.f);
}
pos_up0 += u0 * hw * width_factor;
@@ -219,7 +219,7 @@ void LineBuilder::build() {
color1 = gradient->get_color_at_offset(current_distance1 / total_distance);
}
if (retrieve_curve) {
- width_factor = curve->interpolate_baked(current_distance1 / total_distance);
+ width_factor = curve->sample_baked(current_distance1 / total_distance);
}
Vector2 inner_normal0, inner_normal1;
@@ -383,7 +383,7 @@ void LineBuilder::build() {
color1 = gradient->get_color(gradient->get_points_count() - 1);
}
if (retrieve_curve) {
- width_factor = curve->interpolate_baked(1.f);
+ width_factor = curve->sample_baked(1.f);
}
Vector2 pos_up1 = pos1 + u0 * hw * width_factor;
diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp
new file mode 100644
index 0000000000..38a03aaf97
--- /dev/null
+++ b/scene/2d/navigation_link_2d.cpp
@@ -0,0 +1,284 @@
+/*************************************************************************/
+/* navigation_link_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "navigation_link_2d.h"
+
+#include "core/math/geometry_2d.h"
+#include "scene/resources/world_2d.h"
+#include "servers/navigation_server_2d.h"
+#include "servers/navigation_server_3d.h"
+
+void NavigationLink2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
+ ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink2D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink2D::get_navigation_layers);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink2D::set_navigation_layer_value);
+ ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink2D::get_navigation_layer_value);
+
+ ClassDB::bind_method(D_METHOD("set_start_location", "location"), &NavigationLink2D::set_start_location);
+ ClassDB::bind_method(D_METHOD("get_start_location"), &NavigationLink2D::get_start_location);
+
+ ClassDB::bind_method(D_METHOD("set_end_location", "location"), &NavigationLink2D::set_end_location);
+ ClassDB::bind_method(D_METHOD("get_end_location"), &NavigationLink2D::get_end_location);
+
+ ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost);
+ ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost);
+
+ ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink2D::set_travel_cost);
+ ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink2D::get_travel_cost);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_location"), "set_start_location", "get_start_location");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "end_location"), "set_end_location", "get_end_location");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
+}
+
+void NavigationLink2D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (enabled) {
+ NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
+
+ // Update global positions for the link.
+ Transform2D gt = get_global_transform();
+ NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
+ NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
+ }
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ // Update global positions for the link.
+ Transform2D gt = get_global_transform();
+ NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
+ NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ NavigationServer2D::get_singleton()->link_set_map(link, RID());
+ } break;
+ case NOTIFICATION_DRAW: {
+#ifdef DEBUG_ENABLED
+ if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) {
+ Color color;
+ if (enabled) {
+ color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
+ } else {
+ color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
+ }
+
+ real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());
+
+ draw_line(get_start_location(), get_end_location(), color);
+ draw_arc(get_start_location(), radius, 0, Math_TAU, 10, color);
+ draw_arc(get_end_location(), radius, 0, Math_TAU, 10, color);
+ }
+#endif // DEBUG_ENABLED
+ } break;
+ }
+}
+
+#ifdef TOOLS_ENABLED
+Rect2 NavigationLink2D::_edit_get_rect() const {
+ real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());
+
+ Rect2 rect(get_start_location(), Size2());
+ rect.expand_to(get_end_location());
+ rect.grow_by(radius);
+ return rect;
+}
+
+bool NavigationLink2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+ Point2 segment[2] = { get_start_location(), get_end_location() };
+
+ Vector2 closest_point = Geometry2D::get_closest_point_to_segment(p_point, segment);
+ return p_point.distance_to(closest_point) < p_tolerance;
+}
+#endif // TOOLS_ENABLED
+
+void NavigationLink2D::set_enabled(bool p_enabled) {
+ if (enabled == p_enabled) {
+ return;
+ }
+
+ enabled = p_enabled;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (!enabled) {
+ NavigationServer2D::get_singleton()->link_set_map(link, RID());
+ } else {
+ NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
+ }
+
+#ifdef DEBUG_ENABLED
+ if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
+ queue_redraw();
+ }
+#endif // DEBUG_ENABLED
+}
+
+void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
+ if (bidirectional == p_bidirectional) {
+ return;
+ }
+
+ bidirectional = p_bidirectional;
+
+ NavigationServer2D::get_singleton()->link_set_bidirectional(link, bidirectional);
+}
+
+void NavigationLink2D::set_navigation_layers(uint32_t p_navigation_layers) {
+ if (navigation_layers == p_navigation_layers) {
+ return;
+ }
+
+ navigation_layers = p_navigation_layers;
+
+ NavigationServer2D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
+}
+
+void NavigationLink2D::set_navigation_layer_value(int p_layer_number, bool p_value) {
+ ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
+ ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
+
+ uint32_t _navigation_layers = get_navigation_layers();
+
+ if (p_value) {
+ _navigation_layers |= 1 << (p_layer_number - 1);
+ } else {
+ _navigation_layers &= ~(1 << (p_layer_number - 1));
+ }
+
+ set_navigation_layers(_navigation_layers);
+}
+
+bool NavigationLink2D::get_navigation_layer_value(int p_layer_number) const {
+ ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
+ ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
+
+ return get_navigation_layers() & (1 << (p_layer_number - 1));
+}
+
+void NavigationLink2D::set_start_location(Vector2 p_location) {
+ if (start_location.is_equal_approx(p_location)) {
+ return;
+ }
+
+ start_location = p_location;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ Transform2D gt = get_global_transform();
+ NavigationServer2D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
+
+ update_configuration_warnings();
+
+#ifdef DEBUG_ENABLED
+ if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
+ queue_redraw();
+ }
+#endif // DEBUG_ENABLED
+}
+
+void NavigationLink2D::set_end_location(Vector2 p_location) {
+ if (end_location.is_equal_approx(p_location)) {
+ return;
+ }
+
+ end_location = p_location;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ Transform2D gt = get_global_transform();
+ NavigationServer2D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
+
+ update_configuration_warnings();
+
+#ifdef DEBUG_ENABLED
+ if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
+ queue_redraw();
+ }
+#endif // DEBUG_ENABLED
+}
+
+void NavigationLink2D::set_enter_cost(real_t p_enter_cost) {
+ ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
+ if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
+ return;
+ }
+
+ enter_cost = p_enter_cost;
+
+ NavigationServer2D::get_singleton()->link_set_enter_cost(link, enter_cost);
+}
+
+void NavigationLink2D::set_travel_cost(real_t p_travel_cost) {
+ ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
+ if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
+ return;
+ }
+
+ travel_cost = p_travel_cost;
+
+ NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost);
+}
+
+TypedArray<String> NavigationLink2D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (start_location.is_equal_approx(end_location)) {
+ warnings.push_back(RTR("NavigationLink2D start location should be different than the end location to be useful."));
+ }
+
+ return warnings;
+}
+
+NavigationLink2D::NavigationLink2D() {
+ link = NavigationServer2D::get_singleton()->link_create();
+ set_notify_transform(true);
+}
+
+NavigationLink2D::~NavigationLink2D() {
+ NavigationServer2D::get_singleton()->free(link);
+ link = RID();
+}
diff --git a/scene/resources/camera_effects.h b/scene/2d/navigation_link_2d.h
index 7353931d16..5990ea082c 100644
--- a/scene/resources/camera_effects.h
+++ b/scene/2d/navigation_link_2d.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* camera_effects.h */
+/* navigation_link_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,68 +28,61 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CAMERA_EFFECTS_H
-#define CAMERA_EFFECTS_H
+#ifndef NAVIGATION_LINK_2D_H
+#define NAVIGATION_LINK_2D_H
-#include "core/io/resource.h"
-#include "core/templates/rid.h"
+#include "scene/2d/node_2d.h"
-class CameraEffects : public Resource {
- GDCLASS(CameraEffects, Resource);
+class NavigationLink2D : public Node2D {
+ GDCLASS(NavigationLink2D, Node2D);
-private:
- RID camera_effects;
+ bool enabled = true;
+ RID link = RID();
+ bool bidirectional = true;
+ uint32_t navigation_layers = 1;
+ Vector2 end_location = Vector2();
+ Vector2 start_location = Vector2();
+ real_t enter_cost = 0.0;
+ real_t travel_cost = 1.0;
- // DOF blur
- bool dof_blur_far_enabled = false;
- float dof_blur_far_distance = 10.0;
- float dof_blur_far_transition = 5.0;
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
- bool dof_blur_near_enabled = false;
- float dof_blur_near_distance = 2.0;
- float dof_blur_near_transition = 1.0;
+public:
+#ifdef TOOLS_ENABLED
+ virtual Rect2 _edit_get_rect() const override;
+ virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override;
+#endif
- float dof_blur_amount = 0.1;
- void _update_dof_blur();
+ void set_enabled(bool p_enabled);
+ bool is_enabled() const { return enabled; }
- // Override exposure
- bool override_exposure_enabled = false;
- float override_exposure = 1.0;
- void _update_override_exposure();
+ void set_bidirectional(bool p_bidirectional);
+ bool is_bidirectional() const { return bidirectional; }
-protected:
- static void _bind_methods();
- void _validate_property(PropertyInfo &p_property) const;
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const { return navigation_layers; }
-public:
- virtual RID get_rid() const override;
-
- // DOF blur
- void set_dof_blur_far_enabled(bool p_enabled);
- bool is_dof_blur_far_enabled() const;
- void set_dof_blur_far_distance(float p_distance);
- float get_dof_blur_far_distance() const;
- void set_dof_blur_far_transition(float p_distance);
- float get_dof_blur_far_transition() const;
-
- void set_dof_blur_near_enabled(bool p_enabled);
- bool is_dof_blur_near_enabled() const;
- void set_dof_blur_near_distance(float p_distance);
- float get_dof_blur_near_distance() const;
- void set_dof_blur_near_transition(float p_distance);
- float get_dof_blur_near_transition() const;
-
- void set_dof_blur_amount(float p_amount);
- float get_dof_blur_amount() const;
-
- // Override exposure
- void set_override_exposure_enabled(bool p_enabled);
- bool is_override_exposure_enabled() const;
- void set_override_exposure(float p_exposure);
- float get_override_exposure() const;
-
- CameraEffects();
- ~CameraEffects();
+ void set_navigation_layer_value(int p_layer_number, bool p_value);
+ bool get_navigation_layer_value(int p_layer_number) const;
+
+ void set_start_location(Vector2 p_location);
+ Vector2 get_start_location() const { return start_location; }
+
+ void set_end_location(Vector2 p_location);
+ Vector2 get_end_location() const { return end_location; }
+
+ void set_enter_cost(real_t p_enter_cost);
+ real_t get_enter_cost() const { return enter_cost; }
+
+ void set_travel_cost(real_t p_travel_cost);
+ real_t get_travel_cost() const { return travel_cost; }
+
+ TypedArray<String> get_configuration_warnings() const override;
+
+ NavigationLink2D();
+ ~NavigationLink2D();
};
-#endif // CAMERA_EFFECTS_H
+#endif // NAVIGATION_LINK_2D_H
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index b883d14a41..be17299f07 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -47,7 +47,7 @@ Rect2 Path2D::_edit_get_rect() const {
for (int i = 0; i < curve->get_point_count(); i++) {
for (int j = 0; j <= 8; j++) {
real_t frac = j / 8.0;
- Vector2 p = curve->interpolate(i, frac);
+ Vector2 p = curve->sample(i, frac);
aabb.expand_to(p);
}
}
@@ -70,7 +70,7 @@ bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
for (int j = 1; j <= 8; j++) {
real_t frac = j / 8.0;
- s[1] = curve->interpolate(i, frac);
+ s[1] = curve->sample(i, frac);
Vector2 p = Geometry2D::get_closest_point_to_segment(p_point, s);
if (p.distance_to(p_point) <= p_tolerance) {
@@ -112,7 +112,7 @@ void Path2D::_notification(int p_what) {
for (int i = 0; i < curve->get_point_count(); i++) {
for (int j = 0; j < 8; j++) {
real_t frac = j * (1.0 / 8.0);
- Vector2 p = curve->interpolate(i, frac);
+ Vector2 p = curve->sample(i, frac);
_cached_draw_pts.set(count++, p);
}
}
@@ -175,7 +175,7 @@ void PathFollow2D::_update_transform() {
if (path_length == 0) {
return;
}
- Vector2 pos = c->interpolate_baked(progress, cubic);
+ Vector2 pos = c->sample_baked(progress, cubic);
if (rotates) {
real_t ahead = progress + lookahead;
@@ -195,14 +195,14 @@ void PathFollow2D::_update_transform() {
}
}
- Vector2 ahead_pos = c->interpolate_baked(ahead, cubic);
+ Vector2 ahead_pos = c->sample_baked(ahead, cubic);
Vector2 tangent_to_curve;
if (ahead_pos == pos) {
// This will happen at the end of non-looping or non-closed paths.
// We'll try a look behind instead, in order to get a meaningful angle.
tangent_to_curve =
- (pos - c->interpolate_baked(progress - lookahead, cubic)).normalized();
+ (pos - c->sample_baked(progress - lookahead, cubic)).normalized();
} else {
tangent_to_curve = (ahead_pos - pos).normalized();
}
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 43158344b4..61fe00669a 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1142,7 +1142,7 @@ bool CharacterBody2D::move_and_slide() {
on_ceiling = false;
on_wall = false;
- if (!current_platform_velocity.is_equal_approx(Vector2())) {
+ if (!current_platform_velocity.is_zero_approx()) {
PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
parameters.exclude_bodies.insert(platform_rid);
@@ -1241,7 +1241,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
break;
}
- if (result.remainder.is_equal_approx(Vector2())) {
+ if (result.remainder.is_zero_approx()) {
motion = Vector2();
break;
}
@@ -1325,7 +1325,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
sliding_enabled = true;
first_slide = false;
- if (!collided || motion.is_equal_approx(Vector2())) {
+ if (!collided || motion.is_zero_approx()) {
break;
}
}
@@ -1371,7 +1371,7 @@ void CharacterBody2D::_move_and_slide_floating(double p_delta) {
motion_results.push_back(result);
_set_collision_direction(result);
- if (result.remainder.is_equal_approx(Vector2())) {
+ if (result.remainder.is_zero_approx()) {
motion = Vector2();
break;
}
@@ -1390,7 +1390,7 @@ void CharacterBody2D::_move_and_slide_floating(double p_delta) {
}
}
- if (!collided || motion.is_equal_approx(Vector2())) {
+ if (!collided || motion.is_zero_approx()) {
break;
}
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index b620f58ed7..a02f322ef1 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -264,7 +264,7 @@ bool TouchScreenButton::_is_point_inside(const Point2 &p_point) {
if (bitmask.is_valid()) {
check_rect = false;
if (!touched && Rect2(Point2(), bitmask->get_size()).has_point(coord)) {
- if (bitmask->get_bit(coord)) {
+ if (bitmask->get_bitv(coord)) {
touched = true;
}
}
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index db7c3233f6..92e6d53139 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -473,19 +473,19 @@ bool Area3D::is_monitoring() const {
}
TypedArray<Node3D> Area3D::get_overlapping_bodies() const {
- ERR_FAIL_COND_V(!monitoring, Array());
- Array ret;
+ TypedArray<Node3D> ret;
+ ERR_FAIL_COND_V_MSG(!monitoring, ret, "Can't find overlapping bodies when monitoring is off.");
ret.resize(body_map.size());
int idx = 0;
for (const KeyValue<ObjectID, BodyState> &E : body_map) {
Object *obj = ObjectDB::get_instance(E.key);
- if (!obj) {
- ret.resize(ret.size() - 1); //ops
- } else {
- ret[idx++] = obj;
+ if (obj) {
+ ret[idx] = obj;
+ idx++;
}
}
+ ret.resize(idx);
return ret;
}
@@ -506,19 +506,18 @@ bool Area3D::is_monitorable() const {
}
TypedArray<Area3D> Area3D::get_overlapping_areas() const {
- ERR_FAIL_COND_V(!monitoring, Array());
- Array ret;
+ TypedArray<Area3D> ret;
+ ERR_FAIL_COND_V_MSG(!monitoring, ret, "Can't find overlapping areas when monitoring is off.");
ret.resize(area_map.size());
int idx = 0;
for (const KeyValue<ObjectID, AreaState> &E : area_map) {
Object *obj = ObjectDB::get_instance(E.key);
- if (!obj) {
- ret.resize(ret.size() - 1); //ops
- } else {
- ret[idx++] = obj;
+ if (obj) {
+ ret[idx] = obj;
+ idx++;
}
}
-
+ ret.resize(idx);
return ret;
}
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index b8b6296c45..304e56326d 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -31,6 +31,7 @@
#include "camera_3d.h"
#include "collision_object_3d.h"
+#include "core/core_string_names.h"
#include "core/math/projection.h"
#include "scene/main/viewport.h"
@@ -71,6 +72,17 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
+
+ if (attributes.is_valid()) {
+ const CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
+ if (physical_attributes) {
+ if (p_property.name == "near" || p_property.name == "far" || p_property.name == "fov" || p_property.name == "keep_aspect") {
+ p_property.usage = PROPERTY_USAGE_READ_ONLY | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR;
+ }
+ }
+ }
+
+ Node3D::_validate_property(p_property);
}
void Camera3D::_update_camera() {
@@ -400,18 +412,44 @@ Ref<Environment> Camera3D::get_environment() const {
return environment;
}
-void Camera3D::set_effects(const Ref<CameraEffects> &p_effects) {
- effects = p_effects;
- if (effects.is_valid()) {
- RS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid());
+void Camera3D::set_attributes(const Ref<CameraAttributes> &p_attributes) {
+ if (attributes.is_valid()) {
+ CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
+ if (physical_attributes) {
+ attributes->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Camera3D::_attributes_changed));
+ }
+ }
+
+ attributes = p_attributes;
+
+ if (attributes.is_valid()) {
+ CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
+ if (physical_attributes) {
+ attributes->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Camera3D::_attributes_changed));
+ _attributes_changed();
+ }
+
+ RS::get_singleton()->camera_set_camera_attributes(camera, attributes->get_rid());
} else {
- RS::get_singleton()->camera_set_camera_effects(camera, RID());
+ RS::get_singleton()->camera_set_camera_attributes(camera, RID());
}
- _update_camera_mode();
+
+ notify_property_list_changed();
}
-Ref<CameraEffects> Camera3D::get_effects() const {
- return effects;
+Ref<CameraAttributes> Camera3D::get_attributes() const {
+ return attributes;
+}
+
+void Camera3D::_attributes_changed() {
+ CameraAttributesPhysical *physical_attributes = Object::cast_to<CameraAttributesPhysical>(attributes.ptr());
+ ERR_FAIL_COND(!physical_attributes);
+
+ fov = physical_attributes->get_fov();
+ near = physical_attributes->get_near();
+ far = physical_attributes->get_far();
+ keep_aspect = KEEP_HEIGHT;
+ _update_camera_mode();
}
void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) {
@@ -479,8 +517,8 @@ void Camera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera3D::get_cull_mask);
ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera3D::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &Camera3D::get_environment);
- ClassDB::bind_method(D_METHOD("set_effects", "env"), &Camera3D::set_effects);
- ClassDB::bind_method(D_METHOD("get_effects"), &Camera3D::get_effects);
+ ClassDB::bind_method(D_METHOD("set_attributes", "env"), &Camera3D::set_attributes);
+ ClassDB::bind_method(D_METHOD("get_attributes"), &Camera3D::get_attributes);
ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera3D::set_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera3D::get_keep_aspect_mode);
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking);
@@ -498,7 +536,7 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_effects", "get_effects");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_attributes", "get_attributes");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "v_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index bba9b7d1e4..f150a23e27 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -33,7 +33,7 @@
#include "scene/3d/node_3d.h"
#include "scene/3d/velocity_tracker_3d.h"
-#include "scene/resources/camera_effects.h"
+#include "scene/resources/camera_attributes.h"
#include "scene/resources/environment.h"
class Camera3D : public Node3D {
@@ -64,11 +64,11 @@ private:
ProjectionType mode = PROJECTION_PERSPECTIVE;
- real_t fov = 0.0;
+ real_t fov = 75.0;
real_t size = 1.0;
Vector2 frustum_offset;
- real_t near = 0.0;
- real_t far = 0.0;
+ real_t near = 0.05;
+ real_t far = 4000.0;
real_t v_offset = 0.0;
real_t h_offset = 0.0;
KeepAspect keep_aspect = KEEP_HEIGHT;
@@ -81,7 +81,8 @@ private:
uint32_t layers = 0xfffff;
Ref<Environment> environment;
- Ref<CameraEffects> effects;
+ Ref<CameraAttributes> attributes;
+ void _attributes_changed();
// void _camera_make_current(Node *p_camera);
friend class Viewport;
@@ -159,8 +160,8 @@ public:
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
- void set_effects(const Ref<CameraEffects> &p_effects);
- Ref<CameraEffects> get_effects() const;
+ void set_attributes(const Ref<CameraAttributes> &p_effects);
+ Ref<CameraAttributes> get_attributes() const;
void set_keep_aspect_mode(KeepAspect p_aspect);
KeepAspect get_keep_aspect_mode() const;
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 9dc61b35af..e14bb1aa94 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -739,17 +739,17 @@ void CPUParticles3D::_particles_process(double p_delta) {
/*real_t tex_linear_velocity = 0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0);
+ tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->sample(0);
}*/
real_t tex_angle = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
- tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
+ tex_angle = curve_parameters[PARAM_ANGLE]->sample(tv);
}
real_t tex_anim_offset = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
- tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv);
+ tex_anim_offset = curve_parameters[PARAM_ANGLE]->sample(tv);
}
p.seed = Math::rand();
@@ -907,53 +907,53 @@ void CPUParticles3D::_particles_process(double p_delta) {
real_t tex_linear_velocity = 1.0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv);
+ tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->sample(tv);
}
real_t tex_orbit_velocity = 1.0;
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
- tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv);
+ tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->sample(tv);
}
}
real_t tex_angular_velocity = 1.0;
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
- tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv);
+ tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->sample(tv);
}
real_t tex_linear_accel = 1.0;
if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
- tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv);
+ tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->sample(tv);
}
real_t tex_tangential_accel = 1.0;
if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
- tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv);
+ tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->sample(tv);
}
real_t tex_radial_accel = 1.0;
if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
- tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv);
+ tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->sample(tv);
}
real_t tex_damping = 1.0;
if (curve_parameters[PARAM_DAMPING].is_valid()) {
- tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv);
+ tex_damping = curve_parameters[PARAM_DAMPING]->sample(tv);
}
real_t tex_angle = 1.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
- tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
+ tex_angle = curve_parameters[PARAM_ANGLE]->sample(tv);
}
real_t tex_anim_speed = 1.0;
if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
- tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv);
+ tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->sample(tv);
}
real_t tex_anim_offset = 1.0;
if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
- tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv);
+ tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->sample(tv);
}
Vector3 force = gravity;
@@ -1016,23 +1016,23 @@ void CPUParticles3D::_particles_process(double p_delta) {
Vector3 tex_scale = Vector3(1.0, 1.0, 1.0);
if (split_scale) {
if (scale_curve_x.is_valid()) {
- tex_scale.x = scale_curve_x->interpolate(tv);
+ tex_scale.x = scale_curve_x->sample(tv);
} else {
tex_scale.x = 1.0;
}
if (scale_curve_y.is_valid()) {
- tex_scale.y = scale_curve_y->interpolate(tv);
+ tex_scale.y = scale_curve_y->sample(tv);
} else {
tex_scale.y = 1.0;
}
if (scale_curve_z.is_valid()) {
- tex_scale.z = scale_curve_z->interpolate(tv);
+ tex_scale.z = scale_curve_z->sample(tv);
} else {
tex_scale.z = 1.0;
}
} else {
if (curve_parameters[PARAM_SCALE].is_valid()) {
- float tmp_scale = curve_parameters[PARAM_SCALE]->interpolate(tv);
+ float tmp_scale = curve_parameters[PARAM_SCALE]->sample(tv);
tex_scale.x = tmp_scale;
tex_scale.y = tmp_scale;
tex_scale.z = tmp_scale;
@@ -1041,7 +1041,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
real_t tex_hue_variation = 0.0;
if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) {
- tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv);
+ tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->sample(tv);
}
real_t hue_rot_angle = (tex_hue_variation)*Math_TAU * Math::lerp(parameters_min[PARAM_HUE_VARIATION], parameters_max[PARAM_HUE_VARIATION], p.hue_rot_rand);
diff --git a/scene/3d/fog_volume.cpp b/scene/3d/fog_volume.cpp
index 319129603e..cfee7028d4 100644
--- a/scene/3d/fog_volume.cpp
+++ b/scene/3d/fog_volume.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "fog_volume.h"
+#include "scene/resources/environment.h"
///////////////////////////
diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp
index e4a7cf6ee5..d977874911 100644
--- a/scene/3d/label_3d.cpp
+++ b/scene/3d/label_3d.cpp
@@ -486,8 +486,9 @@ void Label3D::_shape() {
case TextServer::AUTOWRAP_OFF:
break;
}
- PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
+ autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
float max_line_w = 0.0;
for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 8d96d13f0c..e51f06e083 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#include "core/config/project_settings.h"
+
#include "light_3d.h"
void Light3D::set_param(Param p_param, real_t p_value) {
@@ -122,7 +124,14 @@ uint32_t Light3D::get_cull_mask() const {
void Light3D::set_color(const Color &p_color) {
color = p_color;
- RS::get_singleton()->light_set_color(light, p_color);
+
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ Color combined = color.srgb_to_linear();
+ combined *= correlated_color.srgb_to_linear();
+ RS::get_singleton()->light_set_color(light, combined.linear_to_srgb());
+ } else {
+ RS::get_singleton()->light_set_color(light, color);
+ }
// The gizmo color depends on the light color, so update it.
update_gizmos();
}
@@ -181,6 +190,56 @@ void Light3D::owner_changed_notify() {
_update_visibility();
}
+// Temperature expressed in Kelvins. Valid range 1000 - 15000
+// First converts to CIE 1960 then to sRGB
+// As explained in the Filament documentation: https://google.github.io/filament/Filament.md.html#lighting/directlighting/lightsparameterization
+Color _color_from_temperature(float p_temperature) {
+ float T2 = p_temperature * p_temperature;
+ float u = (0.860117757f + 1.54118254e-4f * p_temperature + 1.28641212e-7f * T2) /
+ (1.0f + 8.42420235e-4f * p_temperature + 7.08145163e-7f * T2);
+ float v = (0.317398726f + 4.22806245e-5f * p_temperature + 4.20481691e-8f * T2) /
+ (1.0f - 2.89741816e-5f * p_temperature + 1.61456053e-7f * T2);
+
+ // Convert to xyY space.
+ float d = 1.0f / (2.0f * u - 8.0f * v + 4.0f);
+ float x = 3.0f * u * d;
+ float y = 2.0f * v * d;
+
+ // Convert to XYZ space
+ const float a = 1.0 / MAX(y, 1e-5f);
+ Vector3 xyz = Vector3(x * a, 1.0, (1.0f - x - y) * a);
+
+ // Convert from XYZ to sRGB(linear)
+ Vector3 linear = Vector3(3.2404542f * xyz.x - 1.5371385f * xyz.y - 0.4985314f * xyz.z,
+ -0.9692660f * xyz.x + 1.8760108f * xyz.y + 0.0415560f * xyz.z,
+ 0.0556434f * xyz.x - 0.2040259f * xyz.y + 1.0572252f * xyz.z);
+ linear /= MAX(1e-5f, linear[linear.max_axis_index()]);
+ // Normalize, clamp, and convert to sRGB.
+ return Color(linear.x, linear.y, linear.z).clamp().linear_to_srgb();
+}
+
+void Light3D::set_temperature(const float p_temperature) {
+ temperature = p_temperature;
+ if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ return;
+ }
+ correlated_color = _color_from_temperature(temperature);
+
+ Color combined = color.srgb_to_linear() * correlated_color.srgb_to_linear();
+
+ RS::get_singleton()->light_set_color(light, combined.linear_to_srgb());
+ // The gizmo color depends on the light color, so update it.
+ update_gizmos();
+}
+
+Color Light3D::get_correlated_color() const {
+ return correlated_color;
+}
+
+float Light3D::get_temperature() const {
+ return temperature;
+}
+
void Light3D::_update_visibility() {
if (!is_inside_tree()) {
return;
@@ -224,12 +283,18 @@ bool Light3D::is_editor_only() const {
}
void Light3D::_validate_property(PropertyInfo &p_property) const {
- if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_fog_fade" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow")) {
+ if (!shadow && (p_property.name == "shadow_bias" || p_property.name == "shadow_normal_bias" || p_property.name == "shadow_reverse_cull_face" || p_property.name == "shadow_transmittance_bias" || p_property.name == "shadow_opacity" || p_property.name == "shadow_blur" || p_property.name == "distance_fade_shadow")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
- if (get_light_type() != RS::LIGHT_DIRECTIONAL && p_property.name == "light_angular_distance") {
- // Angular distance is only used in DirectionalLight3D.
+ if (get_light_type() != RS::LIGHT_DIRECTIONAL && (p_property.name == "light_angular_distance" || p_property.name == "light_intensity_lux")) {
+ // Angular distance and Light Intensity Lux are only used in DirectionalLight3D.
+ p_property.usage = PROPERTY_USAGE_NONE;
+ } else if (get_light_type() == RS::LIGHT_DIRECTIONAL && p_property.name == "light_intensity_lumens") {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+
+ if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && (p_property.name == "light_intensity_lumens" || p_property.name == "light_intensity_lux" || p_property.name == "light_temperature")) {
p_property.usage = PROPERTY_USAGE_NONE;
}
@@ -278,10 +343,18 @@ void Light3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_projector", "projector"), &Light3D::set_projector);
ClassDB::bind_method(D_METHOD("get_projector"), &Light3D::get_projector);
+ ClassDB::bind_method(D_METHOD("set_temperature", "temperature"), &Light3D::set_temperature);
+ ClassDB::bind_method(D_METHOD("get_temperature"), &Light3D::get_temperature);
+ ClassDB::bind_method(D_METHOD("get_correlated_color"), &Light3D::get_correlated_color);
+
ADD_GROUP("Light", "light_");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_intensity_lumens", PROPERTY_HINT_RANGE, "0,100000.0,0.01,or_greater,suffix:lm"), "set_param", "get_param", PARAM_INTENSITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_intensity_lux", PROPERTY_HINT_RANGE, "0,150000.0,0.01,or_greater,suffix:lx"), "set_param", "get_param", PARAM_INTENSITY);
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "light_temperature", PROPERTY_HINT_RANGE, "1000,15000.0,1.0,suffix:k"), "set_temperature", "get_temperature");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_volumetric_fog_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_VOLUMETRIC_FOG_ENERGY);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_projector", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_projector", "get_projector");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"), "set_param", "get_param", PARAM_SIZE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01,degrees"), "set_param", "get_param", PARAM_SIZE);
@@ -296,7 +369,6 @@ void Light3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_OPACITY);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BLUR);
@@ -313,6 +385,7 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_ENERGY);
BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY);
+ BIND_ENUM_CONSTANT(PARAM_VOLUMETRIC_FOG_ENERGY);
BIND_ENUM_CONSTANT(PARAM_SPECULAR);
BIND_ENUM_CONSTANT(PARAM_RANGE);
BIND_ENUM_CONSTANT(PARAM_SIZE);
@@ -329,8 +402,8 @@ void Light3D::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE);
BIND_ENUM_CONSTANT(PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR);
- BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS);
+ BIND_ENUM_CONSTANT(PARAM_INTENSITY);
BIND_ENUM_CONSTANT(PARAM_MAX);
BIND_ENUM_CONSTANT(BAKE_DISABLED);
@@ -363,6 +436,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_ENERGY, 1);
set_param(PARAM_INDIRECT_ENERGY, 1);
+ set_param(PARAM_VOLUMETRIC_FOG_ENERGY, 1);
set_param(PARAM_SPECULAR, 0.5);
set_param(PARAM_RANGE, 5);
set_param(PARAM_SIZE, 0);
@@ -380,8 +454,10 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_BIAS, 0.03);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
- set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 0.1);
set_param(PARAM_SHADOW_FADE_START, 1);
+ // For OmniLight3D and SpotLight3D, specified in Lumens.
+ set_param(PARAM_INTENSITY, 1000.0);
+ set_temperature(6500.0); // Nearly white.
set_disable_scale(true);
}
@@ -487,6 +563,7 @@ DirectionalLight3D::DirectionalLight3D() :
set_param(PARAM_SHADOW_FADE_START, 0.8);
// Increase the default shadow bias to better suit most scenes.
set_param(PARAM_SHADOW_BIAS, 0.1);
+ set_param(PARAM_INTENSITY, 100000.0); // Specified in Lux, approximate mid-day sun.
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
blend_splits = false;
set_sky_mode(SKY_MODE_LIGHT_AND_SKY);
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 035ba50e42..e43d6f0419 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -40,6 +40,7 @@ public:
enum Param {
PARAM_ENERGY = RS::LIGHT_PARAM_ENERGY,
PARAM_INDIRECT_ENERGY = RS::LIGHT_PARAM_INDIRECT_ENERGY,
+ PARAM_VOLUMETRIC_FOG_ENERGY = RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY,
PARAM_SPECULAR = RS::LIGHT_PARAM_SPECULAR,
PARAM_RANGE = RS::LIGHT_PARAM_RANGE,
PARAM_SIZE = RS::LIGHT_PARAM_SIZE,
@@ -56,8 +57,8 @@ public:
PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
PARAM_SHADOW_OPACITY = RS::LIGHT_PARAM_SHADOW_OPACITY,
PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR,
- PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS,
+ PARAM_INTENSITY = RS::LIGHT_PARAM_INTENSITY,
PARAM_MAX = RS::LIGHT_PARAM_MAX
};
@@ -83,6 +84,8 @@ private:
void _update_visibility();
BakeMode bake_mode = BAKE_DYNAMIC;
Ref<Texture2D> projector;
+ Color correlated_color = Color(1.0, 1.0, 1.0);
+ float temperature = 6500.0;
// bind helpers
@@ -139,6 +142,10 @@ public:
void set_projector(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_projector() const;
+ void set_temperature(const float p_temperature);
+ float get_temperature() const;
+ Color get_correlated_color() const;
+
virtual AABB get_aabb() const override;
Light3D();
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 7efda6db32..41a537f7cb 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -30,10 +30,14 @@
#include "lightmap_gi.h"
+#include "core/config/project_settings.h"
#include "core/io/config_file.h"
#include "core/math/delaunay_3d.h"
#include "lightmap_probe.h"
#include "scene/3d/mesh_instance_3d.h"
+#include "scene/resources/camera_attributes.h"
+#include "scene/resources/environment.h"
+#include "scene/resources/sky.h"
void LightmapGIData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) {
User user;
@@ -207,7 +211,7 @@ bool LightmapGIData::is_using_spherical_harmonics() const {
return uses_spherical_harmonics;
}
-void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure) {
if (p_points.size()) {
int pc = p_points.size();
ERR_FAIL_COND(pc * 9 != p_point_sh.size());
@@ -221,6 +225,8 @@ void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, con
RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB());
RS::get_singleton()->lightmap_set_probe_interior(lightmap, false);
}
+ RS::get_singleton()->lightmap_set_baked_exposure_normalization(lightmap, p_baked_exposure);
+ baked_exposure = p_baked_exposure;
interior = p_interior;
bounds = p_bounds;
}
@@ -249,6 +255,10 @@ bool LightmapGIData::is_interior() const {
return interior;
}
+float LightmapGIData::get_baked_exposure() const {
+ return baked_exposure;
+}
+
void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("bounds"));
ERR_FAIL_COND(!p_data.has("points"));
@@ -256,7 +266,8 @@ void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("bsp"));
ERR_FAIL_COND(!p_data.has("sh"));
ERR_FAIL_COND(!p_data.has("interior"));
- set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"]);
+ ERR_FAIL_COND(!p_data.has("baked_exposure"));
+ set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"], p_data["baked_exposure"]);
}
Dictionary LightmapGIData::_get_probe_data() const {
@@ -267,6 +278,7 @@ Dictionary LightmapGIData::_get_probe_data() const {
d["bsp"] = get_capture_bsp_tree();
d["sh"] = get_capture_sh();
d["interior"] = is_interior();
+ d["baked_exposure"] = get_baked_exposure();
return d;
}
@@ -977,15 +989,21 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
Transform3D xf = lights_found[i].xform;
Color linear_color = light->get_color().srgb_to_linear();
+ float energy = light->get_param(Light3D::PARAM_ENERGY);
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ energy *= light->get_param(Light3D::PARAM_INTENSITY);
+ linear_color *= light->get_correlated_color().srgb_to_linear();
+ }
+
if (Object::cast_to<DirectionalLight3D>(light)) {
DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
- lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
+ lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy, l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
} else if (Object::cast_to<OmniLight3D>(light)) {
OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
- lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
+ lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, energy * (1.0 / (Math_PI * 4.0)), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
} else if (Object::cast_to<SpotLight3D>(light)) {
SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
- lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
+ lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy * (1.0 / Math_PI), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
}
}
for (int i = 0; i < probes_found.size(); i++) {
@@ -1040,7 +1058,12 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
}
}
- Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud);
+ float exposure_normalization = 1.0;
+ if (camera_attributes.is_valid()) {
+ exposure_normalization = camera_attributes->calculate_exposure_normalization() * camera_attributes->get_exposure_multiplier();
+ }
+
+ Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, max_texture_size, directional, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud, exposure_normalization);
if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) {
return BAKE_ERROR_MESHES_INVALID;
@@ -1214,7 +1237,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
/* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */
- data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array);
+ data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array, exposure_normalization);
/* Compute a BSP tree of the simplices, so it's easy to find the exact one */
}
@@ -1410,6 +1433,14 @@ LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const {
return gen_probes;
}
+void LightmapGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
+ camera_attributes = p_camera_attributes;
+}
+
+Ref<CameraAttributes> LightmapGI::get_camera_attributes() const {
+ return camera_attributes;
+}
+
void LightmapGI::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
p_property.usage = PROPERTY_USAGE_NONE;
@@ -1462,6 +1493,9 @@ void LightmapGI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_directional", "directional"), &LightmapGI::set_directional);
ClassDB::bind_method(D_METHOD("is_directional"), &LightmapGI::is_directional);
+ ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &LightmapGI::set_camera_attributes);
+ ClassDB::bind_method(D_METHOD("get_camera_attributes"), &LightmapGI::get_camera_attributes);
+
// ClassDB::bind_method(D_METHOD("bake", "from_node"), &LightmapGI::bake, DEFVAL(Variant()));
ADD_GROUP("Tweaks", "");
@@ -1477,6 +1511,7 @@ void LightmapGI::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
ADD_GROUP("Gen Probes", "generate_probes_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes");
ADD_GROUP("Data", "");
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
index 87add9facc..0062a4a093 100644
--- a/scene/3d/lightmap_gi.h
+++ b/scene/3d/lightmap_gi.h
@@ -36,6 +36,9 @@
#include "scene/3d/lightmapper.h"
#include "scene/3d/visual_instance_3d.h"
+class Sky;
+class CameraAttributes;
+
class LightmapGIData : public Resource {
GDCLASS(LightmapGIData, Resource);
RES_BASE_EXTENSION("lmbake")
@@ -47,6 +50,7 @@ class LightmapGIData : public Resource {
RID lightmap;
AABB bounds;
+ float baked_exposure = 1.0;
struct User {
NodePath path;
@@ -83,8 +87,9 @@ public:
bool is_using_spherical_harmonics() const;
bool is_interior() const;
+ float get_baked_exposure() const;
- void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
+ void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure);
PackedVector3Array get_capture_points() const;
PackedColorArray get_capture_sh() const;
PackedInt32Array get_capture_tetrahedra() const;
@@ -147,6 +152,7 @@ private:
float environment_custom_energy = 1.0;
bool directional = false;
GenerateProbes gen_probes = GENERATE_PROBES_DISABLED;
+ Ref<CameraAttributes> camera_attributes;
Ref<LightmapGIData> light_data;
@@ -260,6 +266,9 @@ public:
void set_generate_probes(GenerateProbes p_generate_probes);
GenerateProbes get_generate_probes() const;
+ void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
+ Ref<CameraAttributes> get_camera_attributes() const;
+
AABB get_aabb() const override;
BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);
diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h
index 9b973fd6bc..5b5c6cf53a 100644
--- a/scene/3d/lightmapper.h
+++ b/scene/3d/lightmapper.h
@@ -180,7 +180,7 @@ public:
virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) = 0;
virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) = 0;
virtual void add_probe(const Vector3 &p_position) = 0;
- virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr) = 0;
+ virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, float p_exposure_normalization = 1.0) = 0;
virtual int get_bake_texture_count() const = 0;
virtual Ref<Image> get_bake_texture(int p_index) const = 0;
diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp
new file mode 100644
index 0000000000..47b602c966
--- /dev/null
+++ b/scene/3d/navigation_link_3d.cpp
@@ -0,0 +1,389 @@
+/*************************************************************************/
+/* navigation_link_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "navigation_link_3d.h"
+
+#include "mesh_instance_3d.h"
+#include "servers/navigation_server_3d.h"
+
+#ifdef DEBUG_ENABLED
+void NavigationLink3D::_update_debug_mesh() {
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // don't update inside Editor as node 3d gizmo takes care of this
+ // as collisions and selections for Editor Viewport need to be updated
+ return;
+ }
+
+ if (!NavigationServer3D::get_singleton()->get_debug_enabled()) {
+ if (debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_visible(debug_instance, false);
+ }
+ return;
+ }
+
+ if (!debug_instance.is_valid()) {
+ debug_instance = RenderingServer::get_singleton()->instance_create();
+ }
+
+ if (!debug_mesh.is_valid()) {
+ debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ }
+
+ RID nav_map = get_world_3d()->get_navigation_map();
+ real_t search_radius = NavigationServer3D::get_singleton()->map_get_link_connection_radius(nav_map);
+ Vector3 up_vector = NavigationServer3D::get_singleton()->map_get_up(nav_map);
+ Vector3::Axis up_axis = up_vector.max_axis_index();
+
+ debug_mesh->clear_surfaces();
+
+ Vector<Vector3> lines;
+
+ // Draw line between the points.
+ lines.push_back(start_location);
+ lines.push_back(end_location);
+
+ // Draw start location search radius
+ for (int i = 0; i < 30; i++) {
+ // Create a circle
+ const float ra = Math::deg_to_rad((float)(i * 12));
+ const float rb = Math::deg_to_rad((float)((i + 1) * 12));
+ const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
+ const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
+
+ // Draw axis-aligned circle
+ switch (up_axis) {
+ case Vector3::AXIS_X:
+ lines.append(start_location + Vector3(0, a.x, a.y));
+ lines.append(start_location + Vector3(0, b.x, b.y));
+ break;
+ case Vector3::AXIS_Y:
+ lines.append(start_location + Vector3(a.x, 0, a.y));
+ lines.append(start_location + Vector3(b.x, 0, b.y));
+ break;
+ case Vector3::AXIS_Z:
+ lines.append(start_location + Vector3(a.x, a.y, 0));
+ lines.append(start_location + Vector3(b.x, b.y, 0));
+ break;
+ }
+ }
+
+ // Draw end location search radius
+ for (int i = 0; i < 30; i++) {
+ // Create a circle
+ const float ra = Math::deg_to_rad((float)(i * 12));
+ const float rb = Math::deg_to_rad((float)((i + 1) * 12));
+ const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * search_radius;
+ const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * search_radius;
+
+ // Draw axis-aligned circle
+ switch (up_axis) {
+ case Vector3::AXIS_X:
+ lines.append(end_location + Vector3(0, a.x, a.y));
+ lines.append(end_location + Vector3(0, b.x, b.y));
+ break;
+ case Vector3::AXIS_Y:
+ lines.append(end_location + Vector3(a.x, 0, a.y));
+ lines.append(end_location + Vector3(b.x, 0, b.y));
+ break;
+ case Vector3::AXIS_Z:
+ lines.append(end_location + Vector3(a.x, a.y, 0));
+ lines.append(end_location + Vector3(b.x, b.y, 0));
+ break;
+ }
+ }
+
+ Array mesh_array;
+ mesh_array.resize(Mesh::ARRAY_MAX);
+ mesh_array[Mesh::ARRAY_VERTEX] = lines;
+
+ debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_array);
+
+ RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
+ RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
+ RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+
+ Ref<StandardMaterial3D> link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_material();
+ Ref<StandardMaterial3D> disabled_link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_disabled_material();
+
+ if (enabled) {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, link_material->get_rid());
+ } else {
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, disabled_link_material->get_rid());
+ }
+}
+#endif // DEBUG_ENABLED
+
+void NavigationLink3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink3D::set_bidirectional);
+ ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink3D::is_bidirectional);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationLink3D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationLink3D::get_navigation_layers);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationLink3D::set_navigation_layer_value);
+ ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationLink3D::get_navigation_layer_value);
+
+ ClassDB::bind_method(D_METHOD("set_start_location", "location"), &NavigationLink3D::set_start_location);
+ ClassDB::bind_method(D_METHOD("get_start_location"), &NavigationLink3D::get_start_location);
+
+ ClassDB::bind_method(D_METHOD("set_end_location", "location"), &NavigationLink3D::set_end_location);
+ ClassDB::bind_method(D_METHOD("get_end_location"), &NavigationLink3D::get_end_location);
+
+ ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink3D::set_enter_cost);
+ ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink3D::get_enter_cost);
+
+ ClassDB::bind_method(D_METHOD("set_travel_cost", "travel_cost"), &NavigationLink3D::set_travel_cost);
+ ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationLink3D::get_travel_cost);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bidirectional"), "set_bidirectional", "is_bidirectional");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_location"), "set_start_location", "get_start_location");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "end_location"), "set_end_location", "get_end_location");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "enter_cost"), "set_enter_cost", "get_enter_cost");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "travel_cost"), "set_travel_cost", "get_travel_cost");
+}
+
+void NavigationLink3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (enabled) {
+ NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
+
+ // Update global positions for the link.
+ Transform3D gt = get_global_transform();
+ NavigationServer3D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
+ NavigationServer3D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
+ }
+
+#ifdef DEBUG_ENABLED
+ _update_debug_mesh();
+#endif // DEBUG_ENABLED
+ } break;
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ // Update global positions for the link.
+ Transform3D gt = get_global_transform();
+ NavigationServer3D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
+ NavigationServer3D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
+
+#ifdef DEBUG_ENABLED
+ if (is_inside_tree() && debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+ }
+#endif // DEBUG_ENABLED
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ NavigationServer3D::get_singleton()->link_set_map(link, RID());
+
+#ifdef DEBUG_ENABLED
+ if (debug_instance.is_valid()) {
+ RS::get_singleton()->instance_set_scenario(debug_instance, RID());
+ RS::get_singleton()->instance_set_visible(debug_instance, false);
+ }
+#endif // DEBUG_ENABLED
+ } break;
+ }
+}
+
+NavigationLink3D::NavigationLink3D() {
+ link = NavigationServer3D::get_singleton()->link_create();
+ set_notify_transform(true);
+}
+
+NavigationLink3D::~NavigationLink3D() {
+ NavigationServer3D::get_singleton()->free(link);
+ link = RID();
+
+#ifdef DEBUG_ENABLED
+ if (debug_instance.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_instance);
+ }
+ if (debug_mesh.is_valid()) {
+ RenderingServer::get_singleton()->free(debug_mesh->get_rid());
+ }
+#endif // DEBUG_ENABLED
+}
+
+void NavigationLink3D::set_enabled(bool p_enabled) {
+ if (enabled == p_enabled) {
+ return;
+ }
+
+ enabled = p_enabled;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (enabled) {
+ NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
+ } else {
+ NavigationServer3D::get_singleton()->link_set_map(link, RID());
+ }
+
+#ifdef DEBUG_ENABLED
+ if (debug_instance.is_valid() && debug_mesh.is_valid()) {
+ if (enabled) {
+ Ref<StandardMaterial3D> link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_material();
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, link_material->get_rid());
+ } else {
+ Ref<StandardMaterial3D> disabled_link_material = NavigationServer3D::get_singleton_mut()->get_debug_navigation_link_connections_disabled_material();
+ RS::get_singleton()->instance_set_surface_override_material(debug_instance, 0, disabled_link_material->get_rid());
+ }
+ }
+#endif // DEBUG_ENABLED
+
+ update_gizmos();
+}
+
+void NavigationLink3D::set_bidirectional(bool p_bidirectional) {
+ if (bidirectional == p_bidirectional) {
+ return;
+ }
+
+ bidirectional = p_bidirectional;
+
+ NavigationServer3D::get_singleton()->link_set_bidirectional(link, bidirectional);
+}
+
+void NavigationLink3D::set_navigation_layers(uint32_t p_navigation_layers) {
+ if (navigation_layers == p_navigation_layers) {
+ return;
+ }
+
+ navigation_layers = p_navigation_layers;
+
+ NavigationServer3D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
+}
+
+void NavigationLink3D::set_navigation_layer_value(int p_layer_number, bool p_value) {
+ ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
+ ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
+
+ uint32_t _navigation_layers = get_navigation_layers();
+
+ if (p_value) {
+ _navigation_layers |= 1 << (p_layer_number - 1);
+ } else {
+ _navigation_layers &= ~(1 << (p_layer_number - 1));
+ }
+
+ set_navigation_layers(_navigation_layers);
+}
+
+bool NavigationLink3D::get_navigation_layer_value(int p_layer_number) const {
+ ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
+ ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
+
+ return get_navigation_layers() & (1 << (p_layer_number - 1));
+}
+
+void NavigationLink3D::set_start_location(Vector3 p_location) {
+ if (start_location.is_equal_approx(p_location)) {
+ return;
+ }
+
+ start_location = p_location;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ Transform3D gt = get_global_transform();
+ NavigationServer3D::get_singleton()->link_set_start_location(link, gt.xform(start_location));
+
+#ifdef DEBUG_ENABLED
+ _update_debug_mesh();
+#endif // DEBUG_ENABLED
+
+ update_gizmos();
+ update_configuration_warnings();
+}
+
+void NavigationLink3D::set_end_location(Vector3 p_location) {
+ if (end_location.is_equal_approx(p_location)) {
+ return;
+ }
+
+ end_location = p_location;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ Transform3D gt = get_global_transform();
+ NavigationServer3D::get_singleton()->link_set_end_location(link, gt.xform(end_location));
+
+#ifdef DEBUG_ENABLED
+ _update_debug_mesh();
+#endif // DEBUG_ENABLED
+
+ update_gizmos();
+ update_configuration_warnings();
+}
+
+void NavigationLink3D::set_enter_cost(real_t p_enter_cost) {
+ ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
+ if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
+ return;
+ }
+
+ enter_cost = p_enter_cost;
+
+ NavigationServer3D::get_singleton()->link_set_enter_cost(link, enter_cost);
+}
+
+void NavigationLink3D::set_travel_cost(real_t p_travel_cost) {
+ ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
+ if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
+ return;
+ }
+
+ travel_cost = p_travel_cost;
+
+ NavigationServer3D::get_singleton()->link_set_travel_cost(link, travel_cost);
+}
+
+TypedArray<String> NavigationLink3D::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ if (start_location.is_equal_approx(end_location)) {
+ warnings.push_back(RTR("NavigationLink3D start location should be different than the end location to be useful."));
+ }
+
+ return warnings;
+}
diff --git a/scene/gui/gradient_edit.h b/scene/3d/navigation_link_3d.h
index b7c99f1f1c..1f88075527 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/3d/navigation_link_3d.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* gradient_edit.h */
+/* navigation_link_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,59 +28,63 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GRADIENT_EDIT_H
-#define GRADIENT_EDIT_H
+#ifndef NAVIGATION_LINK_3D_H
+#define NAVIGATION_LINK_3D_H
-#include "scene/gui/color_picker.h"
-#include "scene/gui/popup.h"
-#include "scene/resources/gradient.h"
+#include "scene/3d/node_3d.h"
-class GradientEdit : public Control {
- GDCLASS(GradientEdit, Control);
+class NavigationLink3D : public Node3D {
+ GDCLASS(NavigationLink3D, Node3D);
- PopupPanel *popup = nullptr;
- ColorPicker *picker = nullptr;
+ bool enabled = true;
+ RID link = RID();
+ bool bidirectional = true;
+ uint32_t navigation_layers = 1;
+ Vector3 end_location = Vector3();
+ Vector3 start_location = Vector3();
+ real_t enter_cost = 0.0;
+ real_t travel_cost = 1.0;
- bool grabbing = false;
- int grabbed = -1;
- Vector<Gradient::Point> points;
- Gradient::InterpolationMode interpolation_mode = Gradient::GRADIENT_INTERPOLATE_LINEAR;
+#ifdef DEBUG_ENABLED
+ RID debug_instance;
+ Ref<ArrayMesh> debug_mesh;
- Ref<Gradient> gradient_cache;
- Ref<GradientTexture1D> preview_texture;
-
- // Make sure to use the scaled value below.
- const int BASE_SPACING = 3;
- const int BASE_POINT_WIDTH = 8;
-
- int draw_spacing = BASE_SPACING;
- int draw_point_width = BASE_POINT_WIDTH;
-
- void _draw_checker(int x, int y, int w, int h);
- void _color_changed(const Color &p_color);
- int _get_point_from_pos(int x);
- void _show_color_picker();
+ void _update_debug_mesh();
+#endif // DEBUG_ENABLED
protected:
- virtual void gui_input(const Ref<InputEvent> &p_event) override;
- void _notification(int p_what);
static void _bind_methods();
+ void _notification(int p_what);
public:
- void set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors);
- Vector<float> get_offsets() const;
- Vector<Color> get_colors() const;
- void set_points(Vector<Gradient::Point> &p_points);
- Vector<Gradient::Point> &get_points();
- void set_interpolation_mode(Gradient::InterpolationMode p_interp_mode);
- Gradient::InterpolationMode get_interpolation_mode();
- ColorPicker *get_picker();
- PopupPanel *get_popup();
-
- virtual Size2 get_minimum_size() const override;
-
- GradientEdit();
- virtual ~GradientEdit();
+ NavigationLink3D();
+ ~NavigationLink3D();
+
+ void set_enabled(bool p_enabled);
+ bool is_enabled() const { return enabled; }
+
+ void set_bidirectional(bool p_bidirectional);
+ bool is_bidirectional() const { return bidirectional; }
+
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const { return navigation_layers; }
+
+ void set_navigation_layer_value(int p_layer_number, bool p_value);
+ bool get_navigation_layer_value(int p_layer_number) const;
+
+ void set_start_location(Vector3 p_location);
+ Vector3 get_start_location() const { return start_location; }
+
+ void set_end_location(Vector3 p_location);
+ Vector3 get_end_location() const { return end_location; }
+
+ void set_enter_cost(real_t p_enter_cost);
+ real_t get_enter_cost() const { return enter_cost; }
+
+ void set_travel_cost(real_t p_travel_cost);
+ real_t get_travel_cost() const { return travel_cost; }
+
+ TypedArray<String> get_configuration_warnings() const override;
};
-#endif // GRADIENT_EDIT_H
+#endif // NAVIGATION_LINK_3D_H
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 426a8c1684..095aeef560 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -792,8 +792,8 @@ void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up) {
void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) {
ERR_FAIL_COND_MSG(p_pos.is_equal_approx(p_target), "Node origin and target are in the same position, look_at() failed.");
- ERR_FAIL_COND_MSG(p_up.is_equal_approx(Vector3()), "The up vector can't be zero, look_at() failed.");
- ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos).is_equal_approx(Vector3()), "Up vector and direction between node origin and target are aligned, look_at() failed.");
+ ERR_FAIL_COND_MSG(p_up.is_zero_approx(), "The up vector can't be zero, look_at() failed.");
+ ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos).is_zero_approx(), "Up vector and direction between node origin and target are aligned, look_at() failed.");
Transform3D lookat = Transform3D(Basis::looking_at(p_target - p_pos, p_up), p_pos);
Vector3 original_scale = get_scale();
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index c1c309fdbe..015cb9a21d 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -186,21 +186,21 @@ ArrayOccluder3D::~ArrayOccluder3D() {
/////////////////////////////////////////////////
-void QuadOccluder3D::set_size(const Vector2 &p_size) {
+void QuadOccluder3D::set_size(const Size2 &p_size) {
if (size == p_size) {
return;
}
- size = p_size.max(Vector2());
+ size = p_size.max(Size2());
_update();
}
-Vector2 QuadOccluder3D::get_size() const {
+Size2 QuadOccluder3D::get_size() const {
return size;
}
void QuadOccluder3D::_update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) {
- Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f);
+ Size2 _size = Size2(size.x / 2.0f, size.y / 2.0f);
r_vertices = {
Vector3(-_size.x, -_size.y, 0),
diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h
index 11d731b989..69a80e63fc 100644
--- a/scene/3d/occluder_instance_3d.h
+++ b/scene/3d/occluder_instance_3d.h
@@ -88,15 +88,15 @@ class QuadOccluder3D : public Occluder3D {
GDCLASS(QuadOccluder3D, Occluder3D);
private:
- Vector2 size = Vector2(1.0f, 1.0f);
+ Size2 size = Vector2(1.0f, 1.0f);
protected:
virtual void _update_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) override;
static void _bind_methods();
public:
- Vector2 get_size() const;
- void set_size(const Vector2 &p_size);
+ Size2 get_size() const;
+ void set_size(const Size2 &p_size);
QuadOccluder3D();
~QuadOccluder3D();
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 7d79d9b4fd..3d23206e6b 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -198,17 +198,17 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
}
- Vector3 pos = c->interpolate_baked(progress, cubic);
+ Vector3 pos = c->sample_baked(progress, cubic);
Transform3D t = get_transform();
// Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
// will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
if (rotation_mode == ROTATION_ORIENTED) {
- Vector3 forward = c->interpolate_baked(o_next, cubic) - pos;
+ Vector3 forward = c->sample_baked(o_next, cubic) - pos;
// Try with the previous position
if (forward.length_squared() < CMP_EPSILON2) {
- forward = pos - c->interpolate_baked(o_prev, cubic);
+ forward = pos - c->sample_baked(o_prev, cubic);
}
if (forward.length_squared() < CMP_EPSILON2) {
@@ -217,10 +217,10 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
forward.normalize();
}
- Vector3 up = c->interpolate_baked_up_vector(progress, true);
+ Vector3 up = c->sample_baked_up_vector(progress, true);
if (o_next < progress) {
- Vector3 up1 = c->interpolate_baked_up_vector(o_next, true);
+ Vector3 up1 = c->sample_baked_up_vector(o_next, true);
Vector3 axis = up.cross(up1);
if (axis.length_squared() < CMP_EPSILON2) {
@@ -249,10 +249,10 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
t.origin = pos;
if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
real_t sample_distance = bi * 0.01;
- Vector3 t_prev_pos_a = c->interpolate_baked(prev_offset - sample_distance, cubic);
- Vector3 t_prev_pos_b = c->interpolate_baked(prev_offset + sample_distance, cubic);
- Vector3 t_cur_pos_a = c->interpolate_baked(progress - sample_distance, cubic);
- Vector3 t_cur_pos_b = c->interpolate_baked(progress + sample_distance, cubic);
+ Vector3 t_prev_pos_a = c->sample_baked(prev_offset - sample_distance, cubic);
+ Vector3 t_prev_pos_b = c->sample_baked(prev_offset + sample_distance, cubic);
+ Vector3 t_cur_pos_a = c->sample_baked(progress - sample_distance, cubic);
+ Vector3 t_cur_pos_b = c->sample_baked(progress + sample_distance, cubic);
Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized();
Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized();
@@ -277,7 +277,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
// do the additional tilting
- real_t tilt_angle = c->interpolate_baked_tilt(progress);
+ real_t tilt_angle = c->sample_baked_tilt(progress);
Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 5534bc28f1..86dbcc2306 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1208,7 +1208,7 @@ bool CharacterBody3D::move_and_slide() {
last_motion = Vector3();
- if (!current_platform_velocity.is_equal_approx(Vector3())) {
+ if (!current_platform_velocity.is_zero_approx()) {
PhysicsServer3D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
@@ -1315,7 +1315,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
break;
}
- if (result.remainder.is_equal_approx(Vector3())) {
+ if (result.remainder.is_zero_approx()) {
motion = Vector3();
break;
}
@@ -1428,7 +1428,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
const PhysicsServer3D::MotionCollision &collision = result.collisions[0];
Vector3 slide_motion = result.remainder.slide(collision.normal);
- if (collision_state.floor && !collision_state.wall && !motion_slide_up.is_equal_approx(Vector3())) {
+ if (collision_state.floor && !collision_state.wall && !motion_slide_up.is_zero_approx()) {
// Slide using the intersection between the motion plane and the floor plane,
// in order to keep the direction intact.
real_t motion_length = slide_motion.length();
@@ -1469,7 +1469,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
total_travel += result.travel;
// Apply Constant Speed.
- if (p_was_on_floor && floor_constant_speed && can_apply_constant_speed && collision_state.floor && !motion.is_equal_approx(Vector3())) {
+ if (p_was_on_floor && floor_constant_speed && can_apply_constant_speed && collision_state.floor && !motion.is_zero_approx()) {
Vector3 travel_slide_up = total_travel.slide(up_direction);
motion = motion.normalized() * MAX(0, (motion_slide_up.length() - travel_slide_up.length()));
}
@@ -1492,7 +1492,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
collided = true;
}
- if (!collided || motion.is_equal_approx(Vector3())) {
+ if (!collided || motion.is_zero_approx()) {
break;
}
@@ -1533,7 +1533,7 @@ void CharacterBody3D::_move_and_slide_floating(double p_delta) {
CollisionState result_state;
_set_collision_direction(result, result_state);
- if (result.remainder.is_equal_approx(Vector3())) {
+ if (result.remainder.is_zero_approx()) {
motion = Vector3();
break;
}
@@ -1557,7 +1557,7 @@ void CharacterBody3D::_move_and_slide_floating(double p_delta) {
}
}
- if (!collided || motion.is_equal_approx(Vector3())) {
+ if (!collided || motion.is_zero_approx()) {
break;
}
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 669c3eb7fd..4515277dc3 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -1174,7 +1174,7 @@ void AnimatedSprite3D::_res_changed() {
_queue_update();
}
-void AnimatedSprite3D::_set_playing(bool p_playing) {
+void AnimatedSprite3D::set_playing(bool p_playing) {
if (playing == p_playing) {
return;
}
@@ -1183,7 +1183,7 @@ void AnimatedSprite3D::_set_playing(bool p_playing) {
set_process_internal(playing);
}
-bool AnimatedSprite3D::_is_playing() const {
+bool AnimatedSprite3D::is_playing() const {
return playing;
}
@@ -1191,15 +1191,11 @@ void AnimatedSprite3D::play(const StringName &p_animation) {
if (p_animation) {
set_animation(p_animation);
}
- _set_playing(true);
+ set_playing(true);
}
void AnimatedSprite3D::stop() {
- _set_playing(false);
-}
-
-bool AnimatedSprite3D::is_playing() const {
- return playing;
+ set_playing(false);
}
void AnimatedSprite3D::_reset_timeout() {
@@ -1262,12 +1258,11 @@ void AnimatedSprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation", "animation"), &AnimatedSprite3D::set_animation);
ClassDB::bind_method(D_METHOD("get_animation"), &AnimatedSprite3D::get_animation);
- ClassDB::bind_method(D_METHOD("_set_playing", "playing"), &AnimatedSprite3D::_set_playing);
- ClassDB::bind_method(D_METHOD("_is_playing"), &AnimatedSprite3D::_is_playing);
+ ClassDB::bind_method(D_METHOD("set_playing", "playing"), &AnimatedSprite3D::set_playing);
+ ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite3D::is_playing);
ClassDB::bind_method(D_METHOD("play", "anim"), &AnimatedSprite3D::play, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("stop"), &AnimatedSprite3D::stop);
- ClassDB::bind_method(D_METHOD("is_playing"), &AnimatedSprite3D::is_playing);
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame);
ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame);
@@ -1280,7 +1275,7 @@ void AnimatedSprite3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "set_playing", "is_playing");
}
AnimatedSprite3D::AnimatedSprite3D() {
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 03688cf787..84244a2476 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -219,8 +219,6 @@ class AnimatedSprite3D : public SpriteBase3D {
void _res_changed();
void _reset_timeout();
- void _set_playing(bool p_playing);
- bool _is_playing() const;
RID last_shader;
RID last_texture;
@@ -237,6 +235,8 @@ public:
void play(const StringName &p_animation = StringName());
void stop();
+
+ void set_playing(bool p_playing);
bool is_playing() const;
void set_animation(const StringName &p_animation);
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 5af06cff29..db9f68544b 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -242,7 +242,7 @@ const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringNa
bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) {
const StringName *r = _instance_uniform_get_remap(p_name);
if (r) {
- set_instance_shader_uniform(*r, p_value);
+ set_instance_shader_parameter(*r, p_value);
return true;
}
#ifndef DISABLE_DEPRECATED
@@ -262,7 +262,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value)
bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
const StringName *r = _instance_uniform_get_remap(p_name);
if (r) {
- r_ret = get_instance_shader_uniform(*r);
+ r_ret = get_instance_shader_parameter(*r);
return true;
}
@@ -271,10 +271,10 @@ bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
List<PropertyInfo> pinfo;
- RS::get_singleton()->instance_geometry_get_shader_uniform_list(get_instance(), &pinfo);
+ RS::get_singleton()->instance_geometry_get_shader_parameter_list(get_instance(), &pinfo);
for (PropertyInfo &pi : pinfo) {
bool has_def_value = false;
- Variant def_value = RS::get_singleton()->instance_geometry_get_shader_uniform_default_value(get_instance(), pi.name);
+ Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), pi.name);
if (def_value.get_type() != Variant::NIL) {
has_def_value = true;
}
@@ -319,24 +319,24 @@ float GeometryInstance3D::get_lod_bias() const {
return lod_bias;
}
-void GeometryInstance3D::set_instance_shader_uniform(const StringName &p_uniform, const Variant &p_value) {
+void GeometryInstance3D::set_instance_shader_parameter(const StringName &p_name, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
- Variant def_value = RS::get_singleton()->instance_geometry_get_shader_uniform_default_value(get_instance(), p_uniform);
- RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, def_value);
+ Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_name);
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_name, def_value);
instance_uniforms.erase(p_value);
} else {
- instance_uniforms[p_uniform] = p_value;
+ instance_uniforms[p_name] = p_value;
if (p_value.get_type() == Variant::OBJECT) {
RID tex_id = p_value;
- RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, tex_id);
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_name, tex_id);
} else {
- RS::get_singleton()->instance_geometry_set_shader_uniform(get_instance(), p_uniform, p_value);
+ RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_name, p_value);
}
}
}
-Variant GeometryInstance3D::get_instance_shader_uniform(const StringName &p_uniform) const {
- return RS::get_singleton()->instance_geometry_get_shader_uniform(get_instance(), p_uniform);
+Variant GeometryInstance3D::get_instance_shader_parameter(const StringName &p_name) const {
+ return RS::get_singleton()->instance_geometry_get_shader_parameter(get_instance(), p_name);
}
void GeometryInstance3D::set_custom_aabb(AABB aabb) {
@@ -434,8 +434,8 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_visibility_range_fade_mode", "mode"), &GeometryInstance3D::set_visibility_range_fade_mode);
ClassDB::bind_method(D_METHOD("get_visibility_range_fade_mode"), &GeometryInstance3D::get_visibility_range_fade_mode);
- ClassDB::bind_method(D_METHOD("set_instance_shader_uniform", "uniform", "value"), &GeometryInstance3D::set_instance_shader_uniform);
- ClassDB::bind_method(D_METHOD("get_instance_shader_uniform", "uniform"), &GeometryInstance3D::get_instance_shader_uniform);
+ ClassDB::bind_method(D_METHOD("set_instance_shader_parameter", "name", "value"), &GeometryInstance3D::set_instance_shader_parameter);
+ ClassDB::bind_method(D_METHOD("get_instance_shader_parameter", "name"), &GeometryInstance3D::get_instance_shader_parameter);
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance3D::set_extra_cull_margin);
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance3D::get_extra_cull_margin);
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index f7cdcbf411..100d8d8836 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -178,8 +178,8 @@ public:
void set_lightmap_scale(LightmapScale p_scale);
LightmapScale get_lightmap_scale() const;
- void set_instance_shader_uniform(const StringName &p_uniform, const Variant &p_value);
- Variant get_instance_shader_uniform(const StringName &p_uniform) const;
+ void set_instance_shader_parameter(const StringName &p_name, const Variant &p_value);
+ Variant get_instance_shader_parameter(const StringName &p_name) const;
void set_custom_aabb(AABB aabb);
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index ae231026a7..c97af087bf 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -30,8 +30,10 @@
#include "voxel_gi.h"
+#include "core/core_string_names.h"
#include "mesh_instance_3d.h"
#include "multimesh_instance_3d.h"
+#include "scene/resources/camera_attributes.h"
#include "voxelizer.h"
void VoxelGIData::_set_data(const Dictionary &p_data) {
@@ -281,6 +283,14 @@ Vector3 VoxelGI::get_extents() const {
return extents;
}
+void VoxelGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
+ camera_attributes = p_camera_attributes;
+}
+
+Ref<CameraAttributes> VoxelGI::get_camera_attributes() const {
+ return camera_attributes;
+}
+
void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) {
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) {
@@ -370,9 +380,14 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) {
p_from_node = p_from_node ? p_from_node : get_parent();
ERR_FAIL_NULL(p_from_node);
+ float exposure_normalization = 1.0;
+ if (camera_attributes.is_valid()) {
+ exposure_normalization = camera_attributes->calculate_exposure_normalization() * camera_attributes->get_exposure_multiplier();
+ }
+
Voxelizer baker;
- baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0));
+ baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0), exposure_normalization);
List<PlotMesh> mesh_list;
@@ -428,6 +443,8 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) {
Vector<uint8_t> df = baker.get_sdf_3d_image();
+ RS::get_singleton()->voxel_gi_set_baked_exposure_normalization(probe_data->get_rid(), exposure_normalization);
+
probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count());
set_probe_data(probe_data);
@@ -472,12 +489,16 @@ void VoxelGI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &VoxelGI::set_extents);
ClassDB::bind_method(D_METHOD("get_extents"), &VoxelGI::get_extents);
+ ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &VoxelGI::set_camera_attributes);
+ ClassDB::bind_method(D_METHOD("get_camera_attributes"), &VoxelGI::get_camera_attributes);
+
ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &VoxelGI::bake, DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("debug_bake"), &VoxelGI::_debug_bake);
ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_NONE, "suffix:m"), "set_extents", "get_extents");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data");
BIND_ENUM_CONSTANT(SUBDIV_64);
diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h
index 6d173dea87..b31ae4cd95 100644
--- a/scene/3d/voxel_gi.h
+++ b/scene/3d/voxel_gi.h
@@ -33,6 +33,8 @@
#include "scene/3d/visual_instance_3d.h"
+class CameraAttributes;
+
class VoxelGIData : public Resource {
GDCLASS(VoxelGIData, Resource);
@@ -117,6 +119,7 @@ private:
Subdiv subdiv = SUBDIV_128;
Vector3 extents = Vector3(10, 10, 10);
+ Ref<CameraAttributes> camera_attributes;
struct PlotMesh {
Ref<Material> override_material;
@@ -144,6 +147,10 @@ public:
void set_extents(const Vector3 &p_extents);
Vector3 get_extents() const;
+
+ void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
+ Ref<CameraAttributes> get_camera_attributes() const;
+
Vector3i get_estimated_cell_size() const;
void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index 9380d1cf32..6daa9e0aec 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -30,6 +30,8 @@
#include "voxelizer.h"
+#include "core/config/project_settings.h"
+
static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
if (p_pos.is_equal_approx(p_vtx[0])) {
r_uv = p_uv[0];
@@ -348,7 +350,10 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material
Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
Color emission_col = mat->get_emission();
- float emission_energy = mat->get_emission_energy();
+ float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization;
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ emission_energy *= mat->get_emission_intensity();
+ }
Ref<Image> img_emission;
@@ -608,10 +613,11 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) {
}
}
-void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
+void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization) {
sorted = false;
original_bounds = p_bounds;
cell_subdiv = p_subdiv;
+ exposure_normalization = p_exposure_normalization;
bake_cells.resize(1);
material_cache.clear();
diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h
index 68bce768b7..f5bb9af107 100644
--- a/scene/3d/voxelizer.h
+++ b/scene/3d/voxelizer.h
@@ -87,6 +87,7 @@ private:
};
HashMap<Ref<Material>, MaterialCache> material_cache;
+ float exposure_normalization = 1.0;
AABB original_bounds;
AABB po2_bounds;
int axis_cell_size[3] = {};
@@ -111,7 +112,7 @@ private:
void _sort();
public:
- void begin_bake(int p_subdiv, const AABB &p_bounds);
+ void begin_bake(int p_subdiv, const AABB &p_bounds, float p_exposure_normalization);
void plot_mesh(const Transform3D &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material>> &p_materials, const Ref<Material> &p_override_material);
void end_bake();
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index fe9d9ae4dd..ae7d79e8b0 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -42,9 +42,9 @@ void WorldEnvironment::_notification(int p_what) {
_update_current_environment();
}
- if (camera_effects.is_valid()) {
- add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
- _update_current_camera_effects();
+ if (camera_attributes.is_valid()) {
+ add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_camera_attributes();
}
} break;
@@ -55,9 +55,9 @@ void WorldEnvironment::_notification(int p_what) {
_update_current_environment();
}
- if (camera_effects.is_valid()) {
- remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
- _update_current_camera_effects();
+ if (camera_attributes.is_valid()) {
+ remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_camera_attributes();
}
} break;
}
@@ -74,15 +74,15 @@ void WorldEnvironment::_update_current_environment() {
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings");
}
-void WorldEnvironment::_update_current_camera_effects() {
- WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
+void WorldEnvironment::_update_current_camera_attributes() {
+ WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
if (first) {
- get_viewport()->find_world_3d()->set_camera_effects(first->camera_effects);
+ get_viewport()->find_world_3d()->set_camera_attributes(first->camera_attributes);
} else {
- get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ get_viewport()->find_world_3d()->set_camera_attributes(Ref<CameraAttributes>());
}
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings");
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, "_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings");
}
void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
@@ -110,36 +110,36 @@ Ref<Environment> WorldEnvironment::get_environment() const {
return environment;
}
-void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
- if (camera_effects == p_camera_effects) {
+void WorldEnvironment::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
+ if (camera_attributes == p_camera_attributes) {
return;
}
- if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
- remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ if (is_inside_tree() && camera_attributes.is_valid() && get_viewport()->find_world_3d()->get_camera_attributes() == camera_attributes) {
+ remove_from_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
- camera_effects = p_camera_effects;
- if (is_inside_tree() && camera_effects.is_valid()) {
- add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ camera_attributes = p_camera_attributes;
+ if (is_inside_tree() && camera_attributes.is_valid()) {
+ add_to_group("_world_camera_attributes_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
if (is_inside_tree()) {
- _update_current_camera_effects();
+ _update_current_camera_attributes();
} else {
update_configuration_warnings();
}
}
-Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
- return camera_effects;
+Ref<CameraAttributes> WorldEnvironment::get_camera_attributes() const {
+ return camera_attributes;
}
TypedArray<String> WorldEnvironment::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
- if (!environment.is_valid() && !camera_effects.is_valid()) {
- warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Effects\" property to contain a CameraEffects resource, or both."));
+ if (!environment.is_valid() && !camera_attributes.is_valid()) {
+ warnings.push_back(RTR("To have any visible effect, WorldEnvironment requires its \"Environment\" property to contain an Environment, its \"Camera Attributes\" property to contain a CameraAttributes resource, or both."));
}
if (!is_inside_tree()) {
@@ -150,7 +150,7 @@ TypedArray<String> WorldEnvironment::get_configuration_warnings() const {
warnings.push_back(("Only the first Environment has an effect in a scene (or set of instantiated scenes)."));
}
- if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() != camera_effects) {
+ if (camera_attributes.is_valid() && get_viewport()->find_world_3d()->get_camera_attributes() != camera_attributes) {
warnings.push_back(RTR("Only one WorldEnvironment is allowed per scene (or set of instantiated scenes)."));
}
@@ -162,9 +162,9 @@ void WorldEnvironment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment::get_environment);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
- ClassDB::bind_method(D_METHOD("set_camera_effects", "env"), &WorldEnvironment::set_camera_effects);
- ClassDB::bind_method(D_METHOD("get_camera_effects"), &WorldEnvironment::get_camera_effects);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
+ ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &WorldEnvironment::set_camera_attributes);
+ ClassDB::bind_method(D_METHOD("get_camera_attributes"), &WorldEnvironment::get_camera_attributes);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
}
WorldEnvironment::WorldEnvironment() {
diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h
index 9955aa72a8..07f243c750 100644
--- a/scene/3d/world_environment.h
+++ b/scene/3d/world_environment.h
@@ -32,17 +32,17 @@
#define WORLD_ENVIRONMENT_H
#include "scene/main/node.h"
-#include "scene/resources/camera_effects.h"
+#include "scene/resources/camera_attributes.h"
#include "scene/resources/environment.h"
class WorldEnvironment : public Node {
GDCLASS(WorldEnvironment, Node);
Ref<Environment> environment;
- Ref<CameraEffects> camera_effects;
+ Ref<CameraAttributes> camera_attributes;
void _update_current_environment();
- void _update_current_camera_effects();
+ void _update_current_camera_attributes();
protected:
void _notification(int p_what);
@@ -52,8 +52,8 @@ public:
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
- void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
- Ref<CameraEffects> get_camera_effects() const;
+ void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
+ Ref<CameraAttributes> get_camera_attributes() const;
TypedArray<String> get_configuration_warnings() const override;
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 61f068408c..3d81b6b9e8 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -750,7 +750,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_
float blend = xfade_time == 0 ? 0 : (prev_xfading / xfade_time);
if (xfade_curve.is_valid()) {
- blend = xfade_curve->interpolate(blend);
+ blend = xfade_curve->sample(blend);
}
if (from_start && !p_seek && switched) { //just switched, seek to start of current
@@ -810,7 +810,7 @@ void AnimationNodeTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_from_start", "from_start"), &AnimationNodeTransition::set_from_start);
ClassDB::bind_method(D_METHOD("is_from_start"), &AnimationNodeTransition::is_from_start);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_inputs", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_xfade_time", "get_xfade_time");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start");
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index afb52de307..49a59de9b2 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -344,6 +344,15 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta
}
double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek, bool p_seek_root) {
+ if (p_time == -1) {
+ Ref<AnimationNodeStateMachine> anodesm = p_state_machine->states[current].node;
+ if (anodesm.is_valid()) {
+ p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
+ }
+ playing = false;
+ return 0;
+ }
+
//if not playing and it can restart, then restart
if (!playing && start_request == StringName()) {
if (!stop_request && p_state_machine->start_node) {
@@ -433,7 +442,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
if (current_curve.is_valid()) {
- fade_blend = current_curve->interpolate(fade_blend);
+ fade_blend = current_curve->sample(fade_blend);
}
float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, true);
@@ -491,7 +500,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
// handles start_node: if previous state machine is pointing to a node inside the current state machine, starts the current machine from start_node to prev_local_to
if (p_state_machine->start_node == current && p_state_machine->transitions[i].local_from == current) {
if (p_state_machine->prev_state_machine != nullptr) {
- Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter("playback");
+ Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter(p_state_machine->playback);
if (prev_playback.is_valid()) {
StringName prev_local_to = String(prev_playback->current_transition.next).replace_first(String(p_state_machine->state_machine_name) + "/", "");
@@ -530,7 +539,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
AnimationNodeStateMachine *prev_state_machine = p_state_machine->prev_state_machine;
if (prev_state_machine != nullptr) {
- Ref<AnimationNodeStateMachinePlayback> prev_playback = prev_state_machine->get_parameter("playback");
+ Ref<AnimationNodeStateMachinePlayback> prev_playback = prev_state_machine->get_parameter(p_state_machine->playback);
if (prev_playback.is_valid()) {
if (next_xfade) {
@@ -578,7 +587,6 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
if (goto_next) { //end_loop should be used because fade time may be too small or zero and animation may have looped
-
if (next_xfade) {
//time to fade, baby
fading_from = current;
@@ -592,7 +600,16 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (path.size()) { //if it came from path, remove path
path.remove_at(0);
}
+
+ { // if the current node is a state machine, update the "playing" variable to false by passing -1 in p_time
+ Ref<AnimationNodeStateMachine> anodesm = p_state_machine->states[current].node;
+ if (anodesm.is_valid()) {
+ p_state_machine->blend_node(current, p_state_machine->states[current].node, -1, p_seek, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
+ }
+ }
+
current = next;
+
if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) {
len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_seek_root, 0, AnimationNode::FILTER_IGNORE, true);
pos_current = MIN(pos_current, len_current);
@@ -607,15 +624,16 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
}
}
- // time left must always be 1 because the end node don't length to compute
- if (p_state_machine->end_node != current) {
- rem = 1;
+ if (current != p_state_machine->end_node) {
+ rem = 1; // the time remaining must always be 1 because there is no way to predict how long it takes for the entire state machine to complete
} else {
- Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter("playback");
+ if (p_state_machine->prev_state_machine != nullptr) {
+ Ref<AnimationNodeStateMachinePlayback> prev_playback = p_state_machine->prev_state_machine->get_parameter(p_state_machine->playback);
- if (prev_playback.is_valid()) {
- prev_playback->current_transition = current_transition;
- prev_playback->force_auto_advance = true;
+ if (prev_playback.is_valid()) {
+ prev_playback->current_transition = current_transition;
+ prev_playback->force_auto_advance = true;
+ }
}
}
@@ -690,23 +708,6 @@ void AnimationNodeStateMachine::get_parameter_list(List<PropertyInfo> *r_list) c
for (const StringName &E : advance_conditions) {
r_list->push_back(PropertyInfo(Variant::BOOL, E));
}
-
- // for (const KeyValue<StringName, State> &E : states) {
- // if (E->node == ansm) {
- // for (int i = 0; i < E->node->transitions.size(); i++) {
- // StringName ac = E->node->transitions[i].transition->get_advance_condition_name();
- // if (ac != StringName() && advance_conditions.find(ac) == nullptr) {
- // advance_conditions.push_back(ac);
- // }
- // }
-
- // advance_conditions.sort_custom<StringName::AlphCompare>();
-
- // for (const StringName &E : advance_conditions) {
- // r_list->push_back(PropertyInfo(Variant::BOOL, E));
- // }
- // }
- // }
}
Variant AnimationNodeStateMachine::get_parameter_default_value(const StringName &p_parameter) const {
@@ -900,10 +901,6 @@ void AnimationNodeStateMachine::_rename_transitions(const StringName &p_name, co
void AnimationNodeStateMachine::get_node_list(List<StringName> *r_nodes) const {
List<StringName> nodes;
for (const KeyValue<StringName, State> &E : states) {
- if (E.key == end_node && prev_state_machine == nullptr) {
- continue;
- }
-
nodes.push_back(E.key);
}
nodes.sort_custom<StringName::AlphCompare>();
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index a56a51a547..151b0b93d4 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -44,7 +44,6 @@ void BoxContainer::_resort() {
Size2i new_size = get_size();
- int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
bool rtl = is_layout_rtl();
bool first = true;
@@ -90,7 +89,7 @@ void BoxContainer::_resort() {
return;
}
- int stretch_max = (vertical ? new_size.height : new_size.width) - (children_count - 1) * sep;
+ int stretch_max = (vertical ? new_size.height : new_size.width) - (children_count - 1) * theme_cache.separation;
int stretch_diff = stretch_max - stretch_min;
if (stretch_diff < 0) {
//avoid negative stretch space
@@ -214,7 +213,7 @@ void BoxContainer::_resort() {
if (first) {
first = false;
} else {
- ofs += sep;
+ ofs += theme_cache.separation;
}
int from = ofs;
@@ -248,7 +247,6 @@ Size2 BoxContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
bool first = true;
@@ -273,7 +271,7 @@ Size2 BoxContainer::get_minimum_size() const {
minimum.width = size.width;
}
- minimum.height += size.height + (first ? 0 : sep);
+ minimum.height += size.height + (first ? 0 : theme_cache.separation);
} else { /* HORIZONTAL */
@@ -281,7 +279,7 @@ Size2 BoxContainer::get_minimum_size() const {
minimum.height = size.height;
}
- minimum.width += size.width + (first ? 0 : sep);
+ minimum.width += size.width + (first ? 0 : theme_cache.separation);
}
first = false;
@@ -290,6 +288,12 @@ Size2 BoxContainer::get_minimum_size() const {
return minimum;
}
+void BoxContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.separation = get_theme_constant(SNAME("separation"));
+}
+
void BoxContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
@@ -307,6 +311,12 @@ void BoxContainer::_notification(int p_what) {
}
}
+void BoxContainer::_validate_property(PropertyInfo &p_property) const {
+ if (is_fixed && p_property.name == "vertical") {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+}
+
void BoxContainer::set_alignment(AlignmentMode p_alignment) {
if (alignment == p_alignment) {
return;
@@ -319,6 +329,17 @@ BoxContainer::AlignmentMode BoxContainer::get_alignment() const {
return alignment;
}
+void BoxContainer::set_vertical(bool p_vertical) {
+ ERR_FAIL_COND_MSG(is_fixed, "Can't change orientation of " + get_class() + ".");
+ vertical = p_vertical;
+ update_minimum_size();
+ _resort();
+}
+
+bool BoxContainer::is_vertical() const {
+ return vertical;
+}
+
Control *BoxContainer::add_spacer(bool p_begin) {
Control *c = memnew(Control);
c->set_mouse_filter(MOUSE_FILTER_PASS); //allow spacer to pass mouse events
@@ -367,14 +388,17 @@ BoxContainer::BoxContainer(bool p_vertical) {
void BoxContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_spacer", "begin"), &BoxContainer::add_spacer);
- ClassDB::bind_method(D_METHOD("get_alignment"), &BoxContainer::get_alignment);
ClassDB::bind_method(D_METHOD("set_alignment", "alignment"), &BoxContainer::set_alignment);
+ ClassDB::bind_method(D_METHOD("get_alignment"), &BoxContainer::get_alignment);
+ ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &BoxContainer::set_vertical);
+ ClassDB::bind_method(D_METHOD("is_vertical"), &BoxContainer::is_vertical);
BIND_ENUM_CONSTANT(ALIGNMENT_BEGIN);
BIND_ENUM_CONSTANT(ALIGNMENT_CENTER);
BIND_ENUM_CONSTANT(ALIGNMENT_END);
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment", "get_alignment");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
}
MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control *p_control, bool p_expand) {
diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h
index 3043c3ea45..0ee5bd1772 100644
--- a/scene/gui/box_container.h
+++ b/scene/gui/box_container.h
@@ -47,11 +47,19 @@ private:
bool vertical = false;
AlignmentMode alignment = ALIGNMENT_BEGIN;
+ struct ThemeCache {
+ int separation = 0;
+ } theme_cache;
+
void _resort();
protected:
- void _notification(int p_what);
+ bool is_fixed = false;
+
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
public:
@@ -60,6 +68,9 @@ public:
void set_alignment(AlignmentMode p_alignment);
AlignmentMode get_alignment() const;
+ void set_vertical(bool p_vertical);
+ bool is_vertical() const;
+
virtual Size2 get_minimum_size() const override;
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
@@ -73,7 +84,7 @@ class HBoxContainer : public BoxContainer {
public:
HBoxContainer() :
- BoxContainer(false) {}
+ BoxContainer(false) { is_fixed = true; }
};
class MarginContainer;
@@ -84,7 +95,7 @@ public:
MarginContainer *add_margin_child(const String &p_label, Control *p_control, bool p_expand = false);
VBoxContainer() :
- BoxContainer(true) {}
+ BoxContainer(true) { is_fixed = true; }
};
VARIANT_ENUM_CAST(BoxContainer::AlignmentMode);
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 0b7280619e..c2b82e01d1 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -36,7 +36,7 @@
Size2 Button::get_minimum_size() const {
Ref<Texture2D> _icon = icon;
if (_icon.is_null() && has_theme_icon(SNAME("icon"))) {
- _icon = Control::get_theme_icon(SNAME("icon"));
+ _icon = theme_cache.icon;
}
return get_minimum_size_for_text_and_icon("", _icon);
@@ -46,6 +46,45 @@ void Button::_set_internal_margin(Side p_side, float p_value) {
_internal_margin[p_side] = p_value;
}
+void Button::_update_theme_item_cache() {
+ BaseButton::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+ theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
+ theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
+ theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
+ theme_cache.hover = get_theme_stylebox(SNAME("hover"));
+ theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
+ theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
+ theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+ theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
+ theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
+ theme_cache.focus = get_theme_stylebox(SNAME("focus"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.icon_normal_color = get_theme_color(SNAME("icon_normal_color"));
+ theme_cache.icon_focus_color = get_theme_color(SNAME("icon_focus_color"));
+ theme_cache.icon_pressed_color = get_theme_color(SNAME("icon_pressed_color"));
+ theme_cache.icon_hover_color = get_theme_color(SNAME("icon_hover_color"));
+ theme_cache.icon_hover_pressed_color = get_theme_color(SNAME("icon_hover_pressed_color"));
+ theme_cache.icon_disabled_color = get_theme_color(SNAME("icon_disabled_color"));
+
+ theme_cache.icon = get_theme_icon(SNAME("icon"));
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+}
+
void Button::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
@@ -73,15 +112,15 @@ void Button::_notification(int p_what) {
Color color;
Color color_icon(1, 1, 1, 1);
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
switch (get_draw_mode()) {
case DRAW_NORMAL: {
if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
- style = get_theme_stylebox(SNAME("normal_mirrored"));
+ style = theme_cache.normal_mirrored;
} else {
- style = get_theme_stylebox(SNAME("normal"));
+ style = theme_cache.normal;
}
if (!flat) {
@@ -90,14 +129,14 @@ void Button::_notification(int p_what) {
// Focus colors only take precedence over normal state.
if (has_focus()) {
- color = get_theme_color(SNAME("font_focus_color"));
+ color = theme_cache.font_focus_color;
if (has_theme_color(SNAME("icon_focus_color"))) {
- color_icon = get_theme_color(SNAME("icon_focus_color"));
+ color_icon = theme_cache.icon_focus_color;
}
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
if (has_theme_color(SNAME("icon_normal_color"))) {
- color_icon = get_theme_color(SNAME("icon_normal_color"));
+ color_icon = theme_cache.icon_normal_color;
}
}
} break;
@@ -105,19 +144,19 @@ void Button::_notification(int p_what) {
// Edge case for CheckButton and CheckBox.
if (has_theme_stylebox("hover_pressed")) {
if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+ style = theme_cache.hover_pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover_pressed"));
+ style = theme_cache.hover_pressed;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
if (has_theme_color(SNAME("font_hover_pressed_color"))) {
- color = get_theme_color(SNAME("font_hover_pressed_color"));
+ color = theme_cache.font_hover_pressed_color;
}
if (has_theme_color(SNAME("icon_hover_pressed_color"))) {
- color_icon = get_theme_color(SNAME("icon_hover_pressed_color"));
+ color_icon = theme_cache.icon_hover_pressed_color;
}
break;
@@ -126,53 +165,53 @@ void Button::_notification(int p_what) {
}
case DRAW_PRESSED: {
if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("pressed_mirrored"));
+ style = theme_cache.pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("pressed"));
+ style = theme_cache.pressed;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
if (has_theme_color(SNAME("font_pressed_color"))) {
- color = get_theme_color(SNAME("font_pressed_color"));
+ color = theme_cache.font_pressed_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
if (has_theme_color(SNAME("icon_pressed_color"))) {
- color_icon = get_theme_color(SNAME("icon_pressed_color"));
+ color_icon = theme_cache.icon_pressed_color;
}
} break;
case DRAW_HOVER: {
if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_mirrored"));
+ style = theme_cache.hover_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover"));
+ style = theme_cache.hover;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color(SNAME("font_hover_color"));
+ color = theme_cache.font_hover_color;
if (has_theme_color(SNAME("icon_hover_color"))) {
- color_icon = get_theme_color(SNAME("icon_hover_color"));
+ color_icon = theme_cache.icon_hover_color;
}
} break;
case DRAW_DISABLED: {
if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
- style = get_theme_stylebox(SNAME("disabled_mirrored"));
+ style = theme_cache.disabled_mirrored;
} else {
- style = get_theme_stylebox(SNAME("disabled"));
+ style = theme_cache.disabled;
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
- color = get_theme_color(SNAME("font_disabled_color"));
+ color = theme_cache.font_disabled_color;
if (has_theme_color(SNAME("icon_disabled_color"))) {
- color_icon = get_theme_color(SNAME("icon_disabled_color"));
+ color_icon = theme_cache.icon_disabled_color;
} else {
color_icon.a = 0.4;
}
@@ -181,13 +220,13 @@ void Button::_notification(int p_what) {
}
if (has_focus()) {
- Ref<StyleBox> style2 = get_theme_stylebox(SNAME("focus"));
+ Ref<StyleBox> style2 = theme_cache.focus;
style2->draw(ci, Rect2(Point2(), size));
}
Ref<Texture2D> _icon;
if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
- _icon = Control::get_theme_icon(SNAME("icon"));
+ _icon = theme_cache.icon;
} else {
_icon = icon;
}
@@ -217,21 +256,21 @@ void Button::_notification(int p_what) {
if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_LEFT) {
style_offset.x = style->get_margin(SIDE_LEFT);
if (_internal_margin[SIDE_LEFT] > 0) {
- icon_ofs_region = _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
+ icon_ofs_region = _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
}
} else if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
style_offset.x = 0.0;
} else if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_RIGHT) {
style_offset.x = -style->get_margin(SIDE_RIGHT);
if (_internal_margin[SIDE_RIGHT] > 0) {
- icon_ofs_region = -_internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("h_separation"));
+ icon_ofs_region = -_internal_margin[SIDE_RIGHT] - theme_cache.h_separation;
}
}
style_offset.y = style->get_margin(SIDE_TOP);
if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2;
- int icon_text_separation = text.is_empty() ? 0 : get_theme_constant(SNAME("h_separation"));
+ int icon_text_separation = text.is_empty() ? 0 : theme_cache.h_separation;
_size.width -= icon_text_separation + icon_ofs_region;
if (!clip_text && icon_align_rtl_checked != HORIZONTAL_ALIGNMENT_CENTER) {
_size.width -= text_buf->get_size().width;
@@ -261,7 +300,7 @@ void Button::_notification(int p_what) {
}
}
- Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant(SNAME("h_separation")), 0) : Point2();
+ Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + theme_cache.h_separation, 0) : Point2();
if (align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER && icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
icon_ofs.x = 0.0;
}
@@ -271,10 +310,10 @@ void Button::_notification(int p_what) {
int text_width = MAX(1, (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
if (_internal_margin[SIDE_LEFT] > 0) {
- text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
+ text_clip -= _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
}
if (_internal_margin[SIDE_RIGHT] > 0) {
- text_clip -= _internal_margin[SIDE_RIGHT] + get_theme_constant(SNAME("h_separation"));
+ text_clip -= _internal_margin[SIDE_RIGHT] + theme_cache.h_separation;
}
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[SIDE_RIGHT] - _internal_margin[SIDE_LEFT], 0)) / 2.0;
@@ -288,7 +327,7 @@ void Button::_notification(int p_what) {
icon_ofs.x = 0.0;
}
if (_internal_margin[SIDE_LEFT] > 0) {
- text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
+ text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
} else {
text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x;
}
@@ -305,7 +344,7 @@ void Button::_notification(int p_what) {
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
if (_internal_margin[SIDE_RIGHT] > 0) {
- text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("h_separation"));
+ text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - theme_cache.h_separation;
} else {
text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width;
}
@@ -316,8 +355,8 @@ void Button::_notification(int p_what) {
} break;
}
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
@@ -346,7 +385,7 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) {
minsize.width += p_icon->get_width();
if (!xl_text.is_empty() || !p_text.is_empty()) {
- minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
+ minsize.width += MAX(0, theme_cache.h_separation);
}
} else {
minsize.width = MAX(minsize.width, p_icon->get_width());
@@ -354,12 +393,12 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
}
if (!xl_text.is_empty() || !p_text.is_empty()) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- float font_height = font->get_height(get_theme_font_size(SNAME("font_size")));
+ Ref<Font> font = theme_cache.font;
+ float font_height = font->get_height(theme_cache.font_size);
minsize.height = MAX(font_height, minsize.height);
}
- return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize;
+ return theme_cache.normal->get_minimum_size() + minsize;
}
void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
@@ -371,10 +410,15 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
p_text = xl_text;
}
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
p_paragraph->clear();
+
+ Ref<Font> font = theme_cache.font;
+ int font_size = theme_cache.font_size;
+ if (font.is_null() || font_size == 0) {
+ // Can't shape without a valid font and a non-zero size.
+ return;
+ }
+
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
@@ -544,7 +588,7 @@ void Button::_bind_methods() {
Button::Button(const String &p_text) {
text_buf.instantiate();
- text_buf->set_break_flags(TextServer::BREAK_MANDATORY);
+ text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_TRIM_EDGE_SPACES);
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 23b5c78166..9d9f9763db 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -54,10 +54,48 @@ private:
HorizontalAlignment icon_alignment = HORIZONTAL_ALIGNMENT_LEFT;
float _internal_margin[4] = {};
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+ Ref<StyleBox> normal_mirrored;
+ Ref<StyleBox> pressed;
+ Ref<StyleBox> pressed_mirrored;
+ Ref<StyleBox> hover;
+ Ref<StyleBox> hover_mirrored;
+ Ref<StyleBox> hover_pressed;
+ Ref<StyleBox> hover_pressed_mirrored;
+ Ref<StyleBox> disabled;
+ Ref<StyleBox> disabled_mirrored;
+ Ref<StyleBox> focus;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+
+ Ref<Font> font;
+ int font_size = 0;
+ int outline_size = 0;
+ Color font_outline_color;
+
+ Color icon_normal_color;
+ Color icon_focus_color;
+ Color icon_pressed_color;
+ Color icon_hover_color;
+ Color icon_hover_pressed_color;
+ Color icon_disabled_color;
+
+ Ref<Texture2D> icon;
+
+ int h_separation = 0;
+ } theme_cache;
+
void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");
protected:
void _set_internal_margin(Side p_side, float p_value);
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 26edc1f1b0..37db7d53f0 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -33,39 +33,30 @@
#include "servers/rendering_server.h"
Size2 CheckBox::get_icon_size() const {
- Ref<Texture2D> checked = Control::get_theme_icon(SNAME("checked"));
- Ref<Texture2D> unchecked = Control::get_theme_icon(SNAME("unchecked"));
- Ref<Texture2D> radio_checked = Control::get_theme_icon(SNAME("radio_checked"));
- Ref<Texture2D> radio_unchecked = Control::get_theme_icon(SNAME("radio_unchecked"));
- Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
- Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
- Ref<Texture2D> radio_checked_disabled = Control::get_theme_icon(SNAME("radio_checked_disabled"));
- Ref<Texture2D> radio_unchecked_disabled = Control::get_theme_icon(SNAME("radio_unchecked_disabled"));
-
Size2 tex_size = Size2(0, 0);
- if (!checked.is_null()) {
- tex_size = Size2(checked->get_width(), checked->get_height());
+ if (!theme_cache.checked.is_null()) {
+ tex_size = Size2(theme_cache.checked->get_width(), theme_cache.checked->get_height());
}
- if (!unchecked.is_null()) {
- tex_size = Size2(MAX(tex_size.width, unchecked->get_width()), MAX(tex_size.height, unchecked->get_height()));
+ if (!theme_cache.unchecked.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.unchecked->get_width()), MAX(tex_size.height, theme_cache.unchecked->get_height()));
}
- if (!radio_checked.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_checked->get_width()), MAX(tex_size.height, radio_checked->get_height()));
+ if (!theme_cache.radio_checked.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_checked->get_width()), MAX(tex_size.height, theme_cache.radio_checked->get_height()));
}
- if (!radio_unchecked.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_unchecked->get_width()), MAX(tex_size.height, radio_unchecked->get_height()));
+ if (!theme_cache.radio_unchecked.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_unchecked->get_width()), MAX(tex_size.height, theme_cache.radio_unchecked->get_height()));
}
- if (!checked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, checked_disabled->get_width()), MAX(tex_size.height, checked_disabled->get_height()));
+ if (!theme_cache.checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.checked_disabled->get_width()), MAX(tex_size.height, theme_cache.checked_disabled->get_height()));
}
- if (!unchecked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, unchecked_disabled->get_width()), MAX(tex_size.height, unchecked_disabled->get_height()));
+ if (!theme_cache.unchecked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.unchecked_disabled->get_width()), MAX(tex_size.height, theme_cache.unchecked_disabled->get_height()));
}
- if (!radio_checked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_checked_disabled->get_width()), MAX(tex_size.height, radio_checked_disabled->get_height()));
+ if (!theme_cache.radio_checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_checked_disabled->get_width()), MAX(tex_size.height, theme_cache.radio_checked_disabled->get_height()));
}
- if (!radio_unchecked_disabled.is_null()) {
- tex_size = Size2(MAX(tex_size.width, radio_unchecked_disabled->get_width()), MAX(tex_size.height, radio_unchecked_disabled->get_height()));
+ if (!theme_cache.radio_unchecked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, theme_cache.radio_unchecked_disabled->get_width()), MAX(tex_size.height, theme_cache.radio_unchecked_disabled->get_height()));
}
return tex_size;
}
@@ -75,14 +66,30 @@ Size2 CheckBox::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
+ minsize.width += MAX(0, theme_cache.h_separation);
}
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
- minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
+ minsize.height = MAX(minsize.height, tex_size.height + theme_cache.normal_style->get_margin(SIDE_TOP) + theme_cache.normal_style->get_margin(SIDE_BOTTOM));
return minsize;
}
+void CheckBox::_update_theme_item_cache() {
+ Button::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.check_v_adjust = get_theme_constant(SNAME("check_v_adjust"));
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+
+ theme_cache.checked = get_theme_icon(SNAME("checked"));
+ theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
+ theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
+ theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
+ theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
+ theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
+ theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
+}
+
void CheckBox::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
@@ -100,22 +107,39 @@ void CheckBox::_notification(int p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
- Ref<Texture2D> on = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_checked" : "checked", is_disabled() ? "_disabled" : ""));
- Ref<Texture2D> off = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_unchecked" : "unchecked", is_disabled() ? "_disabled" : ""));
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
+ Ref<Texture2D> on_tex;
+ Ref<Texture2D> off_tex;
+
+ if (is_radio()) {
+ if (is_disabled()) {
+ on_tex = theme_cache.radio_checked_disabled;
+ off_tex = theme_cache.radio_unchecked_disabled;
+ } else {
+ on_tex = theme_cache.radio_checked;
+ off_tex = theme_cache.radio_unchecked;
+ }
+ } else {
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled;
+ off_tex = theme_cache.unchecked_disabled;
+ } else {
+ on_tex = theme_cache.checked;
+ off_tex = theme_cache.unchecked;
+ }
+ }
Vector2 ofs;
if (is_layout_rtl()) {
- ofs.x = get_size().x - sb->get_margin(SIDE_RIGHT) - get_icon_size().width;
+ ofs.x = get_size().x - theme_cache.normal_style->get_margin(SIDE_RIGHT) - get_icon_size().width;
} else {
- ofs.x = sb->get_margin(SIDE_LEFT);
+ ofs.x = theme_cache.normal_style->get_margin(SIDE_LEFT);
}
- ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant(SNAME("check_v_adjust"));
+ ofs.y = int((get_size().height - get_icon_size().height) / 2) + theme_cache.check_v_adjust;
if (is_pressed()) {
- on->draw(ci, ofs);
+ on_tex->draw(ci, ofs);
} else {
- off->draw(ci, ofs);
+ off_tex->draw(ci, ofs);
}
} break;
}
diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h
index fcdb2ce08c..beafece3dc 100644
--- a/scene/gui/check_box.h
+++ b/scene/gui/check_box.h
@@ -36,9 +36,26 @@
class CheckBox : public Button {
GDCLASS(CheckBox, Button);
+ struct ThemeCache {
+ int h_separation = 0;
+ int check_v_adjust = 0;
+ Ref<StyleBox> normal_style;
+
+ Ref<Texture2D> checked;
+ Ref<Texture2D> unchecked;
+ Ref<Texture2D> radio_checked;
+ Ref<Texture2D> radio_unchecked;
+ Ref<Texture2D> checked_disabled;
+ Ref<Texture2D> unchecked_disabled;
+ Ref<Texture2D> radio_checked_disabled;
+ Ref<Texture2D> radio_unchecked_disabled;
+ } theme_cache;
+
protected:
Size2 get_icon_size() const;
Size2 get_minimum_size() const override;
+
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
bool is_radio();
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index b9674ca41e..b01081e31b 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -34,14 +34,33 @@
#include "servers/rendering_server.h"
Size2 CheckButton::get_icon_size() const {
- Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
- Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
+ Ref<Texture2D> on_tex;
+ Ref<Texture2D> off_tex;
+
+ if (is_layout_rtl()) {
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled_mirrored;
+ off_tex = theme_cache.unchecked_disabled_mirrored;
+ } else {
+ on_tex = theme_cache.checked_mirrored;
+ off_tex = theme_cache.unchecked_mirrored;
+ }
+ } else {
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled;
+ off_tex = theme_cache.unchecked_disabled;
+ } else {
+ on_tex = theme_cache.checked;
+ off_tex = theme_cache.unchecked;
+ }
+ }
+
Size2 tex_size = Size2(0, 0);
- if (!on.is_null()) {
- tex_size = Size2(on->get_width(), on->get_height());
+ if (!on_tex.is_null()) {
+ tex_size = Size2(on_tex->get_width(), on_tex->get_height());
}
- if (!off.is_null()) {
- tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height()));
+ if (!off_tex.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, off_tex->get_width()), MAX(tex_size.height, off_tex->get_height()));
}
return tex_size;
@@ -52,14 +71,30 @@ Size2 CheckButton::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
+ minsize.width += MAX(0, theme_cache.h_separation);
}
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
- minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
+ minsize.height = MAX(minsize.height, tex_size.height + theme_cache.normal_style->get_margin(SIDE_TOP) + theme_cache.normal_style->get_margin(SIDE_BOTTOM));
return minsize;
}
+void CheckButton::_update_theme_item_cache() {
+ Button::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.check_v_adjust = get_theme_constant(SNAME("check_v_adjust"));
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+
+ theme_cache.checked = get_theme_icon(SNAME("on"));
+ theme_cache.unchecked = get_theme_icon(SNAME("off"));
+ theme_cache.checked_disabled = get_theme_icon(SNAME("on_disabled"));
+ theme_cache.unchecked_disabled = get_theme_icon(SNAME("off_disabled"));
+ theme_cache.checked_mirrored = get_theme_icon(SNAME("on_mirrored"));
+ theme_cache.unchecked_mirrored = get_theme_icon(SNAME("off_mirrored"));
+ theme_cache.checked_disabled_mirrored = get_theme_icon(SNAME("on_disabled_mirrored"));
+ theme_cache.unchecked_disabled_mirrored = get_theme_icon(SNAME("off_disabled_mirrored"));
+}
+
void CheckButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED:
@@ -78,34 +113,41 @@ void CheckButton::_notification(int p_what) {
RID ci = get_canvas_item();
bool rtl = is_layout_rtl();
- Ref<Texture2D> on;
- if (rtl) {
- on = Control::get_theme_icon(is_disabled() ? "on_disabled_mirrored" : "on_mirrored");
- } else {
- on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
- }
- Ref<Texture2D> off;
+ Ref<Texture2D> on_tex;
+ Ref<Texture2D> off_tex;
+
if (rtl) {
- off = Control::get_theme_icon(is_disabled() ? "off_disabled_mirrored" : "off_mirrored");
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled_mirrored;
+ off_tex = theme_cache.unchecked_disabled_mirrored;
+ } else {
+ on_tex = theme_cache.checked_mirrored;
+ off_tex = theme_cache.unchecked_mirrored;
+ }
} else {
- off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
+ if (is_disabled()) {
+ on_tex = theme_cache.checked_disabled;
+ off_tex = theme_cache.unchecked_disabled;
+ } else {
+ on_tex = theme_cache.checked;
+ off_tex = theme_cache.unchecked;
+ }
}
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
Vector2 ofs;
Size2 tex_size = get_icon_size();
if (rtl) {
- ofs.x = sb->get_margin(SIDE_LEFT);
+ ofs.x = theme_cache.normal_style->get_margin(SIDE_LEFT);
} else {
- ofs.x = get_size().width - (tex_size.width + sb->get_margin(SIDE_RIGHT));
+ ofs.x = get_size().width - (tex_size.width + theme_cache.normal_style->get_margin(SIDE_RIGHT));
}
- ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant(SNAME("check_v_adjust"));
+ ofs.y = (get_size().height - tex_size.height) / 2 + theme_cache.check_v_adjust;
if (is_pressed()) {
- on->draw(ci, ofs);
+ on_tex->draw(ci, ofs);
} else {
- off->draw(ci, ofs);
+ off_tex->draw(ci, ofs);
}
} break;
}
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index 7d4bb8bdfc..e71472c870 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -36,9 +36,26 @@
class CheckButton : public Button {
GDCLASS(CheckButton, Button);
+ struct ThemeCache {
+ int h_separation = 0;
+ int check_v_adjust = 0;
+ Ref<StyleBox> normal_style;
+
+ Ref<Texture2D> checked;
+ Ref<Texture2D> unchecked;
+ Ref<Texture2D> checked_disabled;
+ Ref<Texture2D> unchecked_disabled;
+ Ref<Texture2D> checked_mirrored;
+ Ref<Texture2D> unchecked_mirrored;
+ Ref<Texture2D> checked_disabled_mirrored;
+ Ref<Texture2D> unchecked_disabled_mirrored;
+ } theme_cache;
+
protected:
Size2 get_icon_size() const;
virtual Size2 get_minimum_size() const override;
+
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
public:
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 3030fdff8d..41ed1d16c4 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -853,7 +853,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
} else if (p_which == 2) {
c->draw_rect(Rect2(Point2(), c->get_size()), Color(1, 1, 1));
if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) {
- circle_mat->set_shader_uniform("v", v);
+ circle_mat->set_shader_parameter("v", v);
}
}
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 5e8d5a567f..06819283fa 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2330,6 +2330,9 @@ void Control::_invalidate_theme_cache() {
data.theme_constant_cache.clear();
}
+void Control::_update_theme_item_cache() {
+}
+
void Control::set_theme(const Ref<Theme> &p_theme) {
if (data.theme == p_theme) {
return;
@@ -3103,6 +3106,11 @@ void Control::remove_child_notify(Node *p_child) {
void Control::_notification(int p_notification) {
switch (p_notification) {
+ case NOTIFICATION_POSTINITIALIZE: {
+ _invalidate_theme_cache();
+ _update_theme_item_cache();
+ } break;
+
case NOTIFICATION_ENTER_TREE: {
// Need to defer here, because theme owner information might be set in
// add_child_notify, which doesn't get called until right after this.
@@ -3236,6 +3244,7 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_THEME_CHANGED: {
emit_signal(SceneStringNames::get_singleton()->theme_changed);
_invalidate_theme_cache();
+ _update_theme_item_cache();
update_minimum_size();
queue_redraw();
} break;
@@ -3257,6 +3266,7 @@ void Control::_notification(int p_notification) {
if (is_inside_tree()) {
data.is_rtl_dirty = true;
_invalidate_theme_cache();
+ _update_theme_item_cache();
_size_changed();
}
} break;
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 6215594ae0..ac5d481f3a 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -325,6 +325,10 @@ protected:
bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
+ // Theming.
+
+ virtual void _update_theme_item_cache();
+
// Internationalization.
virtual TypedArray<Vector2i> structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index b4e0747ab8..0a1aeeda71 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -50,6 +50,14 @@ void AcceptDialog::_parent_focused() {
}
}
+void AcceptDialog::_update_theme_item_cache() {
+ Window::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+ theme_cache.margin = get_theme_constant(SNAME("margin"));
+ theme_cache.button_margin = get_theme_constant(SNAME("button_margin"));
+}
+
void AcceptDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -69,7 +77,10 @@ void AcceptDialog::_notification(int p_what) {
} break;
case NOTIFICATION_THEME_CHANGED: {
- bg->add_theme_style_override("panel", bg->get_theme_stylebox(SNAME("panel"), SNAME("AcceptDialog")));
+ bg->add_theme_style_override("panel", theme_cache.panel_style);
+
+ label->set_begin(Point2(theme_cache.margin, theme_cache.margin));
+ label->set_end(Point2(-theme_cache.margin, -theme_cache.button_margin - 10));
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -185,12 +196,12 @@ void AcceptDialog::_update_child_rects() {
if (label->get_text().is_empty()) {
label_size.height = 0;
}
- int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
+
Size2 size = get_size();
Size2 hminsize = hbc->get_combined_minimum_size();
- Vector2 cpos(margin, margin + label_size.height);
- Vector2 csize(size.x - margin * 2, size.y - margin * 3 - hminsize.y - label_size.height);
+ Vector2 cpos(theme_cache.margin, theme_cache.margin + label_size.height);
+ Vector2 csize(size.x - theme_cache.margin * 2, size.y - theme_cache.margin * 3 - hminsize.y - label_size.height);
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -206,7 +217,7 @@ void AcceptDialog::_update_child_rects() {
c->set_size(csize);
}
- cpos.y += csize.y + margin;
+ cpos.y += csize.y + theme_cache.margin;
csize.y = hminsize.y;
hbc->set_position(cpos);
@@ -217,7 +228,6 @@ void AcceptDialog::_update_child_rects() {
}
Size2 AcceptDialog::_get_contents_minimum_size() const {
- int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
Size2 minsize = label->get_combined_minimum_size();
for (int i = 0; i < get_child_count(); i++) {
@@ -238,8 +248,8 @@ Size2 AcceptDialog::_get_contents_minimum_size() const {
Size2 hminsize = hbc->get_combined_minimum_size();
minsize.x = MAX(hminsize.x, minsize.x);
minsize.y += hminsize.y;
- minsize.x += margin * 2;
- minsize.y += margin * 3; //one as separation between hbc and child
+ minsize.x += theme_cache.margin * 2;
+ minsize.y += theme_cache.margin * 3; //one as separation between hbc and child
Size2 wmsize = get_min_size();
minsize.x = MAX(wmsize.x, minsize.x);
@@ -350,14 +360,9 @@ AcceptDialog::AcceptDialog() {
hbc = memnew(HBoxContainer);
- int margin = hbc->get_theme_constant(SNAME("margin"), SNAME("Dialogs"));
- int button_margin = hbc->get_theme_constant(SNAME("button_margin"), SNAME("Dialogs"));
-
label = memnew(Label);
label->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
label->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
- label->set_begin(Point2(margin, margin));
- label->set_end(Point2(-margin, -button_margin - 10));
add_child(label, false, INTERNAL_MODE_FRONT);
add_child(hbc, false, INTERNAL_MODE_FRONT);
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 9ebf5ddfb2..8ba9c93861 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -52,6 +52,12 @@ class AcceptDialog : public Window {
bool hide_on_ok = true;
bool close_on_escape = true;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ int margin = 0;
+ int button_margin = 0;
+ } theme_cache;
+
void _custom_action(const String &p_action);
void _update_child_rects();
@@ -62,6 +68,7 @@ class AcceptDialog : public Window {
protected:
virtual Size2 _get_contents_minimum_size() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 2a56d6d222..a0cf5f5970 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -59,36 +59,26 @@ VBoxContainer *FileDialog::get_vbox() {
return vbox;
}
-void FileDialog::_theme_changed() {
- Color font_color = vbox->get_theme_color(SNAME("font_color"), SNAME("Button"));
- Color font_hover_color = vbox->get_theme_color(SNAME("font_hover_color"), SNAME("Button"));
- Color font_focus_color = vbox->get_theme_color(SNAME("font_focus_color"), SNAME("Button"));
- Color font_pressed_color = vbox->get_theme_color(SNAME("font_pressed_color"), SNAME("Button"));
-
- dir_up->add_theme_color_override("icon_normal_color", font_color);
- dir_up->add_theme_color_override("icon_hover_color", font_hover_color);
- dir_up->add_theme_color_override("icon_focus_color", font_focus_color);
- dir_up->add_theme_color_override("icon_pressed_color", font_pressed_color);
-
- dir_prev->add_theme_color_override("icon_color_normal", font_color);
- dir_prev->add_theme_color_override("icon_color_hover", font_hover_color);
- dir_prev->add_theme_color_override("icon_focus_color", font_focus_color);
- dir_prev->add_theme_color_override("icon_color_pressed", font_pressed_color);
-
- dir_next->add_theme_color_override("icon_color_normal", font_color);
- dir_next->add_theme_color_override("icon_color_hover", font_hover_color);
- dir_next->add_theme_color_override("icon_focus_color", font_focus_color);
- dir_next->add_theme_color_override("icon_color_pressed", font_pressed_color);
-
- refresh->add_theme_color_override("icon_normal_color", font_color);
- refresh->add_theme_color_override("icon_hover_color", font_hover_color);
- refresh->add_theme_color_override("icon_focus_color", font_focus_color);
- refresh->add_theme_color_override("icon_pressed_color", font_pressed_color);
-
- show_hidden->add_theme_color_override("icon_normal_color", font_color);
- show_hidden->add_theme_color_override("icon_hover_color", font_hover_color);
- show_hidden->add_theme_color_override("icon_focus_color", font_focus_color);
- show_hidden->add_theme_color_override("icon_pressed_color", font_pressed_color);
+void FileDialog::_update_theme_item_cache() {
+ ConfirmationDialog::_update_theme_item_cache();
+
+ theme_cache.parent_folder = get_theme_icon(SNAME("parent_folder"));
+ theme_cache.forward_folder = get_theme_icon(SNAME("forward_folder"));
+ theme_cache.back_folder = get_theme_icon(SNAME("back_folder"));
+ theme_cache.reload = get_theme_icon(SNAME("reload"));
+ theme_cache.toggle_hidden = get_theme_icon(SNAME("toggle_hidden"));
+ theme_cache.folder = get_theme_icon(SNAME("folder"));
+ theme_cache.file = get_theme_icon(SNAME("file"));
+
+ theme_cache.folder_icon_modulate = get_theme_color(SNAME("folder_icon_modulate"));
+ theme_cache.file_icon_modulate = get_theme_color(SNAME("file_icon_modulate"));
+ theme_cache.files_disabled = get_theme_color(SNAME("files_disabled"));
+
+ // TODO: Define own colors?
+ theme_cache.icon_normal_color = get_theme_color(SNAME("font_color"), SNAME("Button"));
+ theme_cache.icon_hover_color = get_theme_color(SNAME("font_hover_color"), SNAME("Button"));
+ theme_cache.icon_focus_color = get_theme_color(SNAME("font_focus_color"), SNAME("Button"));
+ theme_cache.icon_pressed_color = get_theme_color(SNAME("font_pressed_color"), SNAME("Button"));
}
void FileDialog::_notification(int p_what) {
@@ -99,18 +89,42 @@ void FileDialog::_notification(int p_what) {
}
} break;
- case NOTIFICATION_ENTER_TREE: {
- dir_up->set_icon(vbox->get_theme_icon(SNAME("parent_folder"), SNAME("FileDialog")));
+ case NOTIFICATION_THEME_CHANGED: {
+ dir_up->set_icon(theme_cache.parent_folder);
if (vbox->is_layout_rtl()) {
- dir_prev->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog")));
- dir_next->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog")));
+ dir_prev->set_icon(theme_cache.forward_folder);
+ dir_next->set_icon(theme_cache.back_folder);
} else {
- dir_prev->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog")));
- dir_next->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog")));
+ dir_prev->set_icon(theme_cache.back_folder);
+ dir_next->set_icon(theme_cache.forward_folder);
}
- refresh->set_icon(vbox->get_theme_icon(SNAME("reload"), SNAME("FileDialog")));
- show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog")));
- _theme_changed();
+ refresh->set_icon(theme_cache.reload);
+ show_hidden->set_icon(theme_cache.toggle_hidden);
+
+ dir_up->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color);
+ dir_up->add_theme_color_override("icon_hover_color", theme_cache.icon_hover_color);
+ dir_up->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ dir_up->add_theme_color_override("icon_pressed_color", theme_cache.icon_pressed_color);
+
+ dir_prev->add_theme_color_override("icon_color_normal", theme_cache.icon_normal_color);
+ dir_prev->add_theme_color_override("icon_color_hover", theme_cache.icon_hover_color);
+ dir_prev->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ dir_prev->add_theme_color_override("icon_color_pressed", theme_cache.icon_pressed_color);
+
+ dir_next->add_theme_color_override("icon_color_normal", theme_cache.icon_normal_color);
+ dir_next->add_theme_color_override("icon_color_hover", theme_cache.icon_hover_color);
+ dir_next->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ dir_next->add_theme_color_override("icon_color_pressed", theme_cache.icon_pressed_color);
+
+ refresh->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color);
+ refresh->add_theme_color_override("icon_hover_color", theme_cache.icon_hover_color);
+ refresh->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ refresh->add_theme_color_override("icon_pressed_color", theme_cache.icon_pressed_color);
+
+ show_hidden->add_theme_color_override("icon_normal_color", theme_cache.icon_normal_color);
+ show_hidden->add_theme_color_override("icon_hover_color", theme_cache.icon_hover_color);
+ show_hidden->add_theme_color_override("icon_focus_color", theme_cache.icon_focus_color);
+ show_hidden->add_theme_color_override("icon_pressed_color", theme_cache.icon_pressed_color);
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -506,10 +520,6 @@ void FileDialog::update_file_list() {
}
TreeItem *root = tree->create_item();
- Ref<Texture2D> folder = vbox->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
- Ref<Texture2D> file_icon = vbox->get_theme_icon(SNAME("file"), SNAME("FileDialog"));
- const Color folder_color = vbox->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
- const Color file_color = vbox->get_theme_color(SNAME("file_icon_modulate"), SNAME("FileDialog"));
List<String> files;
List<String> dirs;
@@ -541,8 +551,8 @@ void FileDialog::update_file_list() {
String &dir_name = dirs.front()->get();
TreeItem *ti = tree->create_item(root);
ti->set_text(0, dir_name);
- ti->set_icon(0, folder);
- ti->set_icon_modulate(0, folder_color);
+ ti->set_icon(0, theme_cache.folder);
+ ti->set_icon_modulate(0, theme_cache.folder_icon_modulate);
Dictionary d;
d["name"] = dir_name;
@@ -601,12 +611,12 @@ void FileDialog::update_file_list() {
Ref<Texture2D> icon = get_icon_func(base_dir.path_join(files.front()->get()));
ti->set_icon(0, icon);
} else {
- ti->set_icon(0, file_icon);
+ ti->set_icon(0, theme_cache.file);
}
- ti->set_icon_modulate(0, file_color);
+ ti->set_icon_modulate(0, theme_cache.file_icon_modulate);
if (mode == FILE_MODE_OPEN_DIR) {
- ti->set_custom_color(0, vbox->get_theme_color(SNAME("files_disabled"), SNAME("FileDialog")));
+ ti->set_custom_color(0, theme_cache.files_disabled);
ti->set_selectable(0, false);
}
Dictionary d;
@@ -1006,7 +1016,6 @@ FileDialog::FileDialog() {
vbox = memnew(VBoxContainer);
add_child(vbox, false, INTERNAL_MODE_FRONT);
- vbox->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed));
mode = FILE_MODE_SAVE_FILE;
set_title(TTRC("Save a File"));
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 4945094086..5c892288b5 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -109,6 +109,25 @@ private:
bool invalidated = true;
+ struct ThemeCache {
+ Ref<Texture2D> parent_folder;
+ Ref<Texture2D> forward_folder;
+ Ref<Texture2D> back_folder;
+ Ref<Texture2D> reload;
+ Ref<Texture2D> toggle_hidden;
+ Ref<Texture2D> folder;
+ Ref<Texture2D> file;
+
+ Color folder_icon_modulate;
+ Color file_icon_modulate;
+ Color files_disabled;
+
+ Color icon_normal_color;
+ Color icon_hover_color;
+ Color icon_focus_color;
+ Color icon_pressed_color;
+ } theme_cache;
+
void update_dir();
void update_file_name();
void update_file_list();
@@ -143,7 +162,7 @@ private:
virtual void _post_popup() override;
protected:
- void _theme_changed();
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp
index 30b694da76..b0d15aa7f4 100644
--- a/scene/gui/flow_container.cpp
+++ b/scene/gui/flow_container.cpp
@@ -44,9 +44,6 @@ void FlowContainer::_resort() {
return;
}
- int separation_horizontal = get_theme_constant(SNAME("h_separation"));
- int separation_vertical = get_theme_constant(SNAME("v_separation"));
-
bool rtl = is_layout_rtl();
HashMap<Control *, Size2i> children_minsize_cache;
@@ -74,14 +71,14 @@ void FlowContainer::_resort() {
if (vertical) { /* VERTICAL */
if (children_in_current_line > 0) {
- ofs.y += separation_vertical;
+ ofs.y += theme_cache.v_separation;
}
if (ofs.y + child_msc.y > current_container_size) {
- line_length = ofs.y - separation_vertical;
+ line_length = ofs.y - theme_cache.v_separation;
lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total });
// Move in new column (vertical line).
- ofs.x += line_height + separation_horizontal;
+ ofs.x += line_height + theme_cache.h_separation;
ofs.y = 0;
line_height = 0;
line_stretch_ratio_total = 0;
@@ -96,14 +93,14 @@ void FlowContainer::_resort() {
} else { /* HORIZONTAL */
if (children_in_current_line > 0) {
- ofs.x += separation_horizontal;
+ ofs.x += theme_cache.h_separation;
}
if (ofs.x + child_msc.x > current_container_size) {
- line_length = ofs.x - separation_horizontal;
+ line_length = ofs.x - theme_cache.h_separation;
lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total });
// Move in new line.
- ofs.y += line_height + separation_vertical;
+ ofs.y += line_height + theme_cache.v_separation;
ofs.x = 0;
line_height = 0;
line_stretch_ratio_total = 0;
@@ -146,11 +143,11 @@ void FlowContainer::_resort() {
current_line_idx++;
child_idx_in_line = 0;
if (vertical) {
- ofs.x += line_data.min_line_height + separation_horizontal;
+ ofs.x += line_data.min_line_height + theme_cache.h_separation;
ofs.y = 0;
} else {
ofs.x = 0;
- ofs.y += line_data.min_line_height + separation_vertical;
+ ofs.y += line_data.min_line_height + theme_cache.v_separation;
}
line_data = lines_data[current_line_idx];
}
@@ -184,9 +181,9 @@ void FlowContainer::_resort() {
fit_child_in_rect(child, child_rect);
if (vertical) { /* VERTICAL */
- ofs.y += child_size.height + separation_vertical;
+ ofs.y += child_size.height + theme_cache.v_separation;
} else { /* HORIZONTAL */
- ofs.x += child_size.width + separation_horizontal;
+ ofs.x += child_size.width + theme_cache.h_separation;
}
child_idx_in_line++;
@@ -250,6 +247,13 @@ Vector<int> FlowContainer::get_allowed_size_flags_vertical() const {
return flags;
}
+void FlowContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+}
+
void FlowContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
@@ -268,14 +272,36 @@ void FlowContainer::_notification(int p_what) {
}
}
+void FlowContainer::_validate_property(PropertyInfo &p_property) const {
+ if (is_fixed && p_property.name == "vertical") {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+}
+
int FlowContainer::get_line_count() const {
return cached_line_count;
}
+void FlowContainer::set_vertical(bool p_vertical) {
+ ERR_FAIL_COND_MSG(is_fixed, "Can't change orientation of " + get_class() + ".");
+ vertical = p_vertical;
+ update_minimum_size();
+ _resort();
+}
+
+bool FlowContainer::is_vertical() const {
+ return vertical;
+}
+
FlowContainer::FlowContainer(bool p_vertical) {
vertical = p_vertical;
}
void FlowContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_line_count"), &FlowContainer::get_line_count);
+
+ ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &FlowContainer::set_vertical);
+ ClassDB::bind_method(D_METHOD("is_vertical"), &FlowContainer::is_vertical);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
}
diff --git a/scene/gui/flow_container.h b/scene/gui/flow_container.h
index a2da43e071..536df27ad6 100644
--- a/scene/gui/flow_container.h
+++ b/scene/gui/flow_container.h
@@ -42,16 +42,28 @@ private:
bool vertical = false;
+ struct ThemeCache {
+ int h_separation = 0;
+ int v_separation = 0;
+ } theme_cache;
+
void _resort();
protected:
- void _notification(int p_what);
+ bool is_fixed = false;
+
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
public:
int get_line_count() const;
+ void set_vertical(bool p_vertical);
+ bool is_vertical() const;
+
virtual Size2 get_minimum_size() const override;
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
@@ -65,7 +77,7 @@ class HFlowContainer : public FlowContainer {
public:
HFlowContainer() :
- FlowContainer(false) {}
+ FlowContainer(false) { is_fixed = true; }
};
class VFlowContainer : public FlowContainer {
@@ -73,7 +85,7 @@ class VFlowContainer : public FlowContainer {
public:
VFlowContainer() :
- FlowContainer(true) {}
+ FlowContainer(true) { is_fixed = true; }
};
#endif // FLOW_CONTAINER_H
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
deleted file mode 100644
index 5e56be7c29..0000000000
--- a/scene/gui/gradient_edit.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*************************************************************************/
-/* gradient_edit.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "gradient_edit.h"
-
-#include "core/os/keyboard.h"
-
-GradientEdit::GradientEdit() {
- set_focus_mode(FOCUS_ALL);
-
- popup = memnew(PopupPanel);
- picker = memnew(ColorPicker);
- popup->add_child(picker);
-
- gradient_cache.instantiate();
- preview_texture.instantiate();
-
- preview_texture->set_width(1024);
- add_child(popup, false, INTERNAL_MODE_FRONT);
-}
-
-int GradientEdit::_get_point_from_pos(int x) {
- int result = -1;
- int total_w = get_size().width - get_size().height - draw_spacing;
- float min_distance = 1e20;
- for (int i = 0; i < points.size(); i++) {
- // Check if we clicked at point.
- float distance = ABS(x - points[i].offset * total_w);
- float min = (draw_point_width / 2 * 1.7); //make it easier to grab
- if (distance <= min && distance < min_distance) {
- result = i;
- min_distance = distance;
- }
- }
- return result;
-}
-
-void GradientEdit::_show_color_picker() {
- if (grabbed == -1) {
- return;
- }
- picker->set_pick_color(points[grabbed].color);
- Size2 minsize = popup->get_contents_minimum_size();
- bool show_above = false;
- if (get_global_position().y + get_size().y + minsize.y > get_viewport_rect().size.y) {
- show_above = true;
- }
- if (show_above) {
- popup->set_position(get_screen_position() - Vector2(0, minsize.y));
- } else {
- popup->set_position(get_screen_position() + Vector2(0, get_size().y));
- }
- popup->popup();
-}
-
-GradientEdit::~GradientEdit() {
-}
-
-void GradientEdit::gui_input(const Ref<InputEvent> &p_event) {
- ERR_FAIL_COND(p_event.is_null());
-
- Ref<InputEventKey> k = p_event;
-
- if (k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && grabbed != -1) {
- points.remove_at(grabbed);
- grabbed = -1;
- grabbing = false;
- queue_redraw();
- emit_signal(SNAME("ramp_changed"));
- accept_event();
- }
-
- Ref<InputEventMouseButton> mb = p_event;
- // Show color picker on double click.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) {
- grabbed = _get_point_from_pos(mb->get_position().x);
- _show_color_picker();
- accept_event();
- }
-
- // Delete point on right click.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
- grabbed = _get_point_from_pos(mb->get_position().x);
- if (grabbed != -1) {
- points.remove_at(grabbed);
- grabbed = -1;
- grabbing = false;
- queue_redraw();
- emit_signal(SNAME("ramp_changed"));
- accept_event();
- }
- }
-
- // Hold alt key to duplicate selected color.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && mb->is_alt_pressed()) {
- int x = mb->get_position().x;
- grabbed = _get_point_from_pos(x);
-
- if (grabbed != -1) {
- int total_w = get_size().width - get_size().height - draw_spacing;
- Gradient::Point new_point = points[grabbed];
- new_point.offset = CLAMP(x / float(total_w), 0, 1);
-
- points.push_back(new_point);
- points.sort();
- for (int i = 0; i < points.size(); ++i) {
- if (points[i].offset == new_point.offset) {
- grabbed = i;
- break;
- }
- }
-
- emit_signal(SNAME("ramp_changed"));
- queue_redraw();
- }
- }
-
- // Select.
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) {
- queue_redraw();
- int x = mb->get_position().x;
- int total_w = get_size().width - get_size().height - draw_spacing;
-
- //Check if color selector was clicked.
- if (x > total_w + draw_spacing) {
- _show_color_picker();
- return;
- }
-
- grabbing = true;
-
- grabbed = _get_point_from_pos(x);
- //grab or select
- if (grabbed != -1) {
- return;
- }
-
- // Insert point.
- Gradient::Point new_point;
- new_point.offset = CLAMP(x / float(total_w), 0, 1);
-
- Gradient::Point prev;
- Gradient::Point next;
-
- int pos = -1;
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset < new_point.offset) {
- pos = i;
- }
- }
-
- if (pos == -1) {
- prev.color = Color(0, 0, 0);
- prev.offset = 0;
- if (points.size()) {
- next = points[0];
- } else {
- next.color = Color(1, 1, 1);
- next.offset = 1.0;
- }
- } else {
- if (pos == points.size() - 1) {
- next.color = Color(1, 1, 1);
- next.offset = 1.0;
- } else {
- next = points[pos + 1];
- }
- prev = points[pos];
- }
-
- new_point.color = prev.color.lerp(next.color, (new_point.offset - prev.offset) / (next.offset - prev.offset));
-
- points.push_back(new_point);
- points.sort();
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset == new_point.offset) {
- grabbed = i;
- break;
- }
- }
-
- emit_signal(SNAME("ramp_changed"));
- }
-
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) {
- if (grabbing) {
- grabbing = false;
- emit_signal(SNAME("ramp_changed"));
- }
- queue_redraw();
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid() && grabbing) {
- int total_w = get_size().width - get_size().height - draw_spacing;
-
- int x = mm->get_position().x;
-
- float newofs = CLAMP(x / float(total_w), 0, 1);
-
- // Snap to "round" coordinates if holding Ctrl.
- // Be more precise if holding Shift as well.
- if (mm->is_ctrl_pressed()) {
- newofs = Math::snapped(newofs, mm->is_shift_pressed() ? 0.025 : 0.1);
- } else if (mm->is_shift_pressed()) {
- // Snap to nearest point if holding just Shift
- const float snap_threshold = 0.03;
- float smallest_ofs = snap_threshold;
- bool found = false;
- int nearest_point = 0;
- for (int i = 0; i < points.size(); ++i) {
- if (i != grabbed) {
- float temp_ofs = ABS(points[i].offset - newofs);
- if (temp_ofs < smallest_ofs) {
- smallest_ofs = temp_ofs;
- nearest_point = i;
- if (found) {
- break;
- }
- found = true;
- }
- }
- }
- if (found) {
- if (points[nearest_point].offset < newofs) {
- newofs = points[nearest_point].offset + 0.00001;
- } else {
- newofs = points[nearest_point].offset - 0.00001;
- }
- newofs = CLAMP(newofs, 0, 1);
- }
- }
-
- bool valid = true;
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset == newofs && i != grabbed) {
- valid = false;
- break;
- }
- }
-
- if (!valid || grabbed == -1) {
- return;
- }
- points.write[grabbed].offset = newofs;
-
- points.sort();
- for (int i = 0; i < points.size(); i++) {
- if (points[i].offset == newofs) {
- grabbed = i;
- break;
- }
- }
-
- emit_signal(SNAME("ramp_changed"));
-
- queue_redraw();
- }
-}
-
-void GradientEdit::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- if (!picker->is_connected("color_changed", callable_mp(this, &GradientEdit::_color_changed))) {
- picker->connect("color_changed", callable_mp(this, &GradientEdit::_color_changed));
- }
- [[fallthrough]];
- }
- case NOTIFICATION_THEME_CHANGED: {
- draw_spacing = BASE_SPACING * get_theme_default_base_scale();
- draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale();
- } break;
-
- case NOTIFICATION_DRAW: {
- int w = get_size().x;
- int h = get_size().y;
-
- if (w == 0 || h == 0) {
- return; // Safety check. We have division by 'h'. And in any case there is nothing to draw with such size.
- }
-
- int total_w = get_size().width - get_size().height - draw_spacing;
-
- // Draw checker pattern for ramp.
- draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true);
-
- // Draw color ramp.
- gradient_cache->set_points(points);
- gradient_cache->set_interpolation_mode(interpolation_mode);
- preview_texture->set_gradient(gradient_cache);
- draw_texture_rect(preview_texture, Rect2(0, 0, total_w, h));
-
- // Draw point markers.
- for (int i = 0; i < points.size(); i++) {
- Color col = points[i].color.inverted();
- col.a = 0.9;
-
- draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col);
- Rect2 rect = Rect2(points[i].offset * total_w - draw_point_width / 2, h / 2, draw_point_width, h / 2);
- draw_rect(rect, points[i].color, true);
- draw_rect(rect, col, false);
- if (grabbed == i) {
- rect = rect.grow(-1);
- if (has_focus()) {
- draw_rect(rect, Color(1, 0, 0, 0.9), false);
- } else {
- draw_rect(rect, Color(0.6, 0, 0, 0.9), false);
- }
-
- rect = rect.grow(-1);
- draw_rect(rect, col, false);
- }
- }
-
- // Draw "button" for color selector.
- draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + draw_spacing, 0, h, h), true);
- if (grabbed != -1) {
- // Draw with selection color.
- draw_rect(Rect2(total_w + draw_spacing, 0, h, h), points[grabbed].color);
- } else {
- // If no color selected draw grey color with 'X' on top.
- draw_rect(Rect2(total_w + draw_spacing, 0, h, h), Color(0.5, 0.5, 0.5, 1));
- draw_line(Vector2(total_w + draw_spacing, 0), Vector2(total_w + draw_spacing + h, h), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6));
- }
-
- // Draw borders around color ramp if in focus.
- if (has_focus()) {
- draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
- draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
- }
- } break;
-
- case NOTIFICATION_VISIBILITY_CHANGED: {
- if (!is_visible()) {
- grabbing = false;
- }
- } break;
- }
-}
-
-Size2 GradientEdit::get_minimum_size() const {
- return Vector2(0, 16);
-}
-
-void GradientEdit::_color_changed(const Color &p_color) {
- if (grabbed == -1) {
- return;
- }
- points.write[grabbed].color = p_color;
- queue_redraw();
- emit_signal(SNAME("ramp_changed"));
-}
-
-void GradientEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) {
- ERR_FAIL_COND(p_offsets.size() != p_colors.size());
- points.clear();
- for (int i = 0; i < p_offsets.size(); i++) {
- Gradient::Point p;
- p.offset = p_offsets[i];
- p.color = p_colors[i];
- points.push_back(p);
- }
-
- points.sort();
- queue_redraw();
-}
-
-Vector<float> GradientEdit::get_offsets() const {
- Vector<float> ret;
- for (int i = 0; i < points.size(); i++) {
- ret.push_back(points[i].offset);
- }
- return ret;
-}
-
-Vector<Color> GradientEdit::get_colors() const {
- Vector<Color> ret;
- for (int i = 0; i < points.size(); i++) {
- ret.push_back(points[i].color);
- }
- return ret;
-}
-
-void GradientEdit::set_points(Vector<Gradient::Point> &p_points) {
- if (points.size() != p_points.size()) {
- grabbed = -1;
- }
- points.clear();
- points = p_points;
- points.sort();
-}
-
-Vector<Gradient::Point> &GradientEdit::get_points() {
- return points;
-}
-
-void GradientEdit::set_interpolation_mode(Gradient::InterpolationMode p_interp_mode) {
- interpolation_mode = p_interp_mode;
-}
-
-Gradient::InterpolationMode GradientEdit::get_interpolation_mode() {
- return interpolation_mode;
-}
-
-ColorPicker *GradientEdit::get_picker() {
- return picker;
-}
-
-PopupPanel *GradientEdit::get_popup() {
- return popup;
-}
-
-void GradientEdit::_bind_methods() {
- ADD_SIGNAL(MethodInfo("ramp_changed"));
-}
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 3163d17846..8dc890eccb 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -31,6 +31,13 @@
#include "grid_container.h"
#include "core/templates/rb_set.h"
+void GridContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+}
+
void GridContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
@@ -39,9 +46,6 @@ void GridContainer::_notification(int p_what) {
RBSet<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
RBSet<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.
- int hsep = get_theme_constant(SNAME("h_separation"));
- int vsep = get_theme_constant(SNAME("v_separation"));
-
// Compute the per-column/per-row data.
int valid_controls_index = 0;
for (int i = 0; i < get_child_count(); i++) {
@@ -98,8 +102,8 @@ void GridContainer::_notification(int p_what) {
remaining_space.height -= E.value;
}
}
- remaining_space.height -= vsep * MAX(max_row - 1, 0);
- remaining_space.width -= hsep * MAX(max_col - 1, 0);
+ remaining_space.height -= theme_cache.v_separation * MAX(max_row - 1, 0);
+ remaining_space.width -= theme_cache.h_separation * MAX(max_col - 1, 0);
bool can_fit = false;
while (!can_fit && col_expanded.size() > 0) {
@@ -202,7 +206,7 @@ void GridContainer::_notification(int p_what) {
col_ofs = 0;
}
if (row > 0) {
- row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;
+ row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + theme_cache.v_separation;
if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) {
// Apply the remaining pixel of the previous row.
@@ -224,11 +228,11 @@ void GridContainer::_notification(int p_what) {
if (rtl) {
Point2 p(col_ofs - s.width, row_ofs);
fit_child_in_rect(c, Rect2(p, s));
- col_ofs -= s.width + hsep;
+ col_ofs -= s.width + theme_cache.h_separation;
} else {
Point2 p(col_ofs, row_ofs);
fit_child_in_rect(c, Rect2(p, s));
- col_ofs += s.width + hsep;
+ col_ofs += s.width + theme_cache.h_separation;
}
}
} break;
@@ -271,9 +275,6 @@ Size2 GridContainer::get_minimum_size() const {
RBMap<int, int> col_minw;
RBMap<int, int> row_minh;
- int hsep = get_theme_constant(SNAME("h_separation"));
- int vsep = get_theme_constant(SNAME("v_separation"));
-
int max_row = 0;
int max_col = 0;
@@ -313,8 +314,8 @@ Size2 GridContainer::get_minimum_size() const {
ms.height += E.value;
}
- ms.height += vsep * max_row;
- ms.width += hsep * max_col;
+ ms.height += theme_cache.v_separation * max_row;
+ ms.width += theme_cache.h_separation * max_col;
return ms;
}
diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h
index 9d77f90ab3..522046f694 100644
--- a/scene/gui/grid_container.h
+++ b/scene/gui/grid_container.h
@@ -38,7 +38,14 @@ class GridContainer : public Container {
int columns = 1;
+ struct ThemeCache {
+ int h_separation = 0;
+ int v_separation = 0;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index e3a27ba7d5..8c49353105 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -43,9 +43,9 @@ void ItemList::_shape(int p_idx) {
} else {
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
}
- item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
+ item.text_buf->add_string(item.text, theme_cache.font, theme_cache.font_size, item.language);
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
} else {
item.text_buf->set_break_flags(TextServer::BREAK_NONE);
}
@@ -532,7 +532,7 @@ void ItemList::set_max_text_lines(int p_lines) {
max_text_lines = p_lines;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
items.write[i].text_buf->set_max_lines_visible(p_lines);
} else {
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
@@ -582,7 +582,7 @@ void ItemList::set_icon_mode(IconMode p_mode) {
icon_mode = p_mode;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
- items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
+ items.write[i].text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
} else {
items.write[i].text_buf->set_break_flags(TextServer::BREAK_NONE);
}
@@ -655,8 +655,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && mb->is_pressed()) {
search_string = ""; //any mousepress cancels
Vector2 pos = mb->get_position();
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- pos -= bg->get_offset();
+ pos -= theme_cache.bg_style->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
@@ -980,6 +979,31 @@ static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) {
return Rect2(ofs_x, ofs_y, tex_width, tex_height);
}
+void ItemList::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+
+ theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
+ theme_cache.bg_focus_style = get_theme_stylebox(SNAME("bg_focus"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
+ theme_cache.icon_margin = get_theme_constant(SNAME("icon_margin"));
+ theme_cache.selected_style = get_theme_stylebox(SNAME("selected"));
+ theme_cache.selected_focus_style = get_theme_stylebox(SNAME("selected_focus"));
+ theme_cache.cursor_style = get_theme_stylebox(SNAME("cursor_unfocused"));
+ theme_cache.cursor_focus_style = get_theme_stylebox(SNAME("cursor"));
+ theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
+}
+
void ItemList::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_RESIZED: {
@@ -998,37 +1022,32 @@ void ItemList::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
-
int mw = scroll_bar->get_minimum_size().x;
scroll_bar->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -mw);
scroll_bar->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, 0);
- scroll_bar->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, bg->get_margin(SIDE_TOP));
- scroll_bar->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -bg->get_margin(SIDE_BOTTOM));
+ scroll_bar->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, theme_cache.bg_style->get_margin(SIDE_TOP));
+ scroll_bar->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -theme_cache.bg_style->get_margin(SIDE_BOTTOM));
Size2 size = get_size();
- int width = size.width - bg->get_minimum_size().width;
+ int width = size.width - theme_cache.bg_style->get_minimum_size().width;
- draw_style_box(bg, Rect2(Point2(), size));
+ draw_style_box(theme_cache.bg_style, Rect2(Point2(), size));
- int hseparation = get_theme_constant(SNAME("h_separation"));
- int vseparation = get_theme_constant(SNAME("v_separation"));
- int icon_margin = get_theme_constant(SNAME("icon_margin"));
- int line_separation = get_theme_constant(SNAME("line_separation"));
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Ref<StyleBox> sbsel;
+ Ref<StyleBox> cursor;
- Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox(SNAME("selected_focus")) : get_theme_stylebox(SNAME("selected"));
- Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox(SNAME("cursor")) : get_theme_stylebox(SNAME("cursor_unfocused"));
+ if (has_focus()) {
+ sbsel = theme_cache.selected_focus_style;
+ cursor = theme_cache.cursor_focus_style;
+ } else {
+ sbsel = theme_cache.selected_style;
+ cursor = theme_cache.cursor_style;
+ }
bool rtl = is_layout_rtl();
- Color guide_color = get_theme_color(SNAME("guide_color"));
- Color font_color = get_theme_color(SNAME("font_color"));
- Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
-
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true);
- draw_style_box(get_theme_stylebox(SNAME("bg_focus")), Rect2(Point2(), size));
+ draw_style_box(theme_cache.bg_focus_style, Rect2(Point2(), size));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false);
}
@@ -1047,9 +1066,9 @@ void ItemList::_notification(int p_what) {
if (!items[i].text.is_empty()) {
if (icon_mode == ICON_MODE_TOP) {
- minsize.y += icon_margin;
+ minsize.y += theme_cache.icon_margin;
} else {
- minsize.x += icon_margin;
+ minsize.x += theme_cache.icon_margin;
}
}
}
@@ -1067,7 +1086,7 @@ void ItemList::_notification(int p_what) {
if (icon_mode == ICON_MODE_TOP) {
minsize.x = MAX(minsize.x, s.width);
if (max_text_lines > 0) {
- minsize.y += s.height + line_separation * max_text_lines;
+ minsize.y += s.height + theme_cache.line_separation * max_text_lines;
} else {
minsize.y += s.height;
}
@@ -1084,13 +1103,13 @@ void ItemList::_notification(int p_what) {
max_column_width = MAX(max_column_width, minsize.x);
// elements need to adapt to the selected size
- minsize.y += vseparation;
- minsize.x += hseparation;
+ minsize.y += theme_cache.v_separation;
+ minsize.x += theme_cache.h_separation;
items.write[i].rect_cache.size = minsize;
items.write[i].min_rect_cache.size = minsize;
}
- int fit_size = size.x - bg->get_minimum_size().width - mw;
+ int fit_size = size.x - theme_cache.bg_style->get_minimum_size().width - mw;
//2-attempt best fit
current_columns = 0x7FFFFFFF;
@@ -1118,11 +1137,11 @@ void ItemList::_notification(int p_what) {
}
items.write[i].rect_cache.position = ofs;
max_h = MAX(max_h, items[i].rect_cache.size.y);
- ofs.x += items[i].rect_cache.size.x + hseparation;
+ ofs.x += items[i].rect_cache.size.x + theme_cache.h_separation;
col++;
if (col == current_columns) {
if (i < items.size() - 1) {
- separators.push_back(ofs.y + max_h + vseparation / 2);
+ separators.push_back(ofs.y + max_h + theme_cache.v_separation / 2);
}
for (int j = i; j >= 0 && col > 0; j--, col--) {
@@ -1130,7 +1149,7 @@ void ItemList::_notification(int p_what) {
}
ofs.x = 0;
- ofs.y += max_h + vseparation;
+ ofs.y += max_h + theme_cache.v_separation;
col = 0;
max_h = 0;
}
@@ -1141,10 +1160,10 @@ void ItemList::_notification(int p_what) {
}
if (all_fit) {
- float page = MAX(0, size.height - bg->get_minimum_size().height);
+ float page = MAX(0, size.height - theme_cache.bg_style->get_minimum_size().height);
float max = MAX(page, ofs.y + max_h);
if (auto_height) {
- auto_height_value = ofs.y + max_h + bg->get_minimum_size().height;
+ auto_height_value = ofs.y + max_h + theme_cache.bg_style->get_minimum_size().height;
}
scroll_bar->set_max(max);
scroll_bar->set_page(page);
@@ -1185,7 +1204,7 @@ void ItemList::_notification(int p_what) {
ensure_selected_visible = false;
- Vector2 base_ofs = bg->get_offset();
+ Vector2 base_ofs = theme_cache.bg_style->get_offset();
base_ofs.y -= int(scroll_bar->get_value());
const Rect2 clip(-base_ofs, size); // visible frame, don't need to draw outside of there
@@ -1229,10 +1248,10 @@ void ItemList::_notification(int p_what) {
if (items[i].selected) {
Rect2 r = rcache;
r.position += base_ofs;
- r.position.y -= vseparation / 2;
- r.size.y += vseparation;
- r.position.x -= hseparation / 2;
- r.size.x += hseparation;
+ r.position.y -= theme_cache.v_separation / 2;
+ r.size.y += theme_cache.v_separation;
+ r.position.x -= theme_cache.h_separation / 2;
+ r.size.x += theme_cache.h_separation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
@@ -1245,10 +1264,10 @@ void ItemList::_notification(int p_what) {
r.position += base_ofs;
// Size rect to make the align the temperature colors
- r.position.y -= vseparation / 2;
- r.size.y += vseparation;
- r.position.x -= hseparation / 2;
- r.size.x += hseparation;
+ r.position.y -= theme_cache.v_separation / 2;
+ r.size.y += theme_cache.v_separation;
+ r.position.x -= theme_cache.h_separation / 2;
+ r.size.x += theme_cache.h_separation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
@@ -1274,11 +1293,11 @@ void ItemList::_notification(int p_what) {
if (icon_mode == ICON_MODE_TOP) {
pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width) / 2);
- pos.y += icon_margin;
- text_ofs.y = icon_size.height + icon_margin * 2;
+ pos.y += theme_cache.icon_margin;
+ text_ofs.y = icon_size.height + theme_cache.icon_margin * 2;
} else {
pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2);
- text_ofs.x = icon_size.width + icon_margin;
+ text_ofs.x = icon_size.width + theme_cache.icon_margin;
}
Rect2 draw_rect = Rect2(pos, icon_size);
@@ -1329,7 +1348,7 @@ void ItemList::_notification(int p_what) {
max_len = size2.x;
}
- Color modulate = items[i].selected ? font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color);
+ Color modulate = items[i].selected ? theme_cache.font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : theme_cache.font_color);
if (items[i].disabled) {
modulate.a *= 0.5;
}
@@ -1344,8 +1363,8 @@ void ItemList::_notification(int p_what) {
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
@@ -1375,8 +1394,8 @@ void ItemList::_notification(int p_what) {
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_LEFT);
}
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
if (width - text_ofs.x > 0) {
@@ -1388,10 +1407,10 @@ void ItemList::_notification(int p_what) {
if (select_mode == SELECT_MULTI && i == current) {
Rect2 r = rcache;
r.position += base_ofs;
- r.position.y -= vseparation / 2;
- r.size.y += vseparation;
- r.position.x -= hseparation / 2;
- r.size.x += hseparation;
+ r.position.y -= theme_cache.v_separation / 2;
+ r.size.y += theme_cache.v_separation;
+ r.position.x -= theme_cache.h_separation / 2;
+ r.size.x += theme_cache.h_separation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
@@ -1423,7 +1442,7 @@ void ItemList::_notification(int p_what) {
}
const int y = base_ofs.y + separators[i];
- draw_line(Vector2(bg->get_margin(SIDE_LEFT), y), Vector2(width, y), guide_color);
+ draw_line(Vector2(theme_cache.bg_style->get_margin(SIDE_LEFT), y), Vector2(width, y), theme_cache.guide_color);
}
} break;
}
@@ -1435,8 +1454,7 @@ void ItemList::_scroll_changed(double) {
int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- pos -= bg->get_offset();
+ pos -= theme_cache.bg_style->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
@@ -1473,8 +1491,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
}
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- pos -= bg->get_offset();
+ pos -= theme_cache.bg_style->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 21bd22759c..63bc771185 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -109,23 +109,45 @@ private:
int max_columns = 1;
Size2 fixed_icon_size;
-
Size2 max_item_size_cache;
int defer_select_single = -1;
-
bool allow_rmb_select = false;
-
bool allow_reselect = false;
real_t icon_scale = 1.0;
bool do_autoscroll_to_bottom = false;
+ struct ThemeCache {
+ int h_separation = 0;
+ int v_separation = 0;
+
+ Ref<StyleBox> bg_style;
+ Ref<StyleBox> bg_focus_style;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Color font_color;
+ Color font_selected_color;
+ int font_outline_size = 0;
+ Color font_outline_color;
+
+ int line_separation = 0;
+ int icon_margin = 0;
+ Ref<StyleBox> selected_style;
+ Ref<StyleBox> selected_focus_style;
+ Ref<StyleBox> cursor_style;
+ Ref<StyleBox> cursor_focus_style;
+ Color guide_color;
+ } theme_cache;
+
void _scroll_changed(double);
void _shape(int p_idx);
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index cd68d1f001..306ca3d340 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -71,7 +71,7 @@ bool Label::is_uppercase() const {
}
int Label::get_line_height(int p_line) const {
- Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
+ Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
if (p_line >= 0 && p_line < lines_rid.size()) {
return TS->shaped_text_get_size(lines_rid[p_line]).y;
} else if (lines_rid.size() > 0) {
@@ -81,13 +81,13 @@ int Label::get_line_height(int p_line) const {
}
return h;
} else {
- int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
return font->get_height(font_size);
}
}
void Label::_shape() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
+ Ref<StyleBox> style = theme_cache.normal_style;
int width = (get_size().width - style->get_minimum_size().width);
if (dirty || font_dirty) {
@@ -99,8 +99,8 @@ void Label::_shape() {
} else {
TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction);
}
- const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
- int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
+ int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
ERR_FAIL_COND(font.is_null());
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
@@ -143,8 +143,9 @@ void Label::_shape() {
case TextServer::AUTOWRAP_OFF:
break;
}
- PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
+ autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
for (int i = 0; i < line_breaks.size(); i = i + 2) {
RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
lines_rid.push_back(line);
@@ -231,8 +232,8 @@ void Label::_shape() {
}
void Label::_update_visible() {
- int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"), SNAME("Label"));
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
+ Ref<StyleBox> style = theme_cache.normal_style;
int lines_visible = lines_rid.size();
if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
@@ -271,6 +272,22 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col
}
}
+void Label::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+ theme_cache.font = get_theme_font(SNAME("font"));
+
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
+ theme_cache.font_shadow_offset = Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
+}
+
void Label::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -306,15 +323,15 @@ void Label::_notification(int p_what) {
Size2 string_size;
Size2 size = get_size();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
- Color font_color = has_settings ? settings->get_font_color() : get_theme_color(SNAME("font_color"));
- Color font_shadow_color = has_settings ? settings->get_shadow_color() : get_theme_color(SNAME("font_shadow_color"));
- Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
- int line_spacing = has_settings ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
- Color font_outline_color = has_settings ? settings->get_outline_color() : get_theme_color(SNAME("font_outline_color"));
- int outline_size = has_settings ? settings->get_outline_size() : get_theme_constant(SNAME("outline_size"));
- int shadow_outline_size = has_settings ? settings->get_shadow_size() : get_theme_constant(SNAME("shadow_outline_size"));
+ Ref<StyleBox> style = theme_cache.normal_style;
+ Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
+ Color font_color = has_settings ? settings->get_font_color() : theme_cache.font_color;
+ Color font_shadow_color = has_settings ? settings->get_shadow_color() : theme_cache.font_shadow_color;
+ Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : theme_cache.font_shadow_offset;
+ int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing;
+ Color font_outline_color = has_settings ? settings->get_outline_color() : theme_cache.font_outline_color;
+ int outline_size = has_settings ? settings->get_outline_size() : theme_cache.font_outline_size;
+ int shadow_outline_size = has_settings ? settings->get_shadow_size() : theme_cache.font_shadow_outline_size;
bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL);
bool rtl_layout = is_layout_rtl();
@@ -561,12 +578,12 @@ Size2 Label::get_minimum_size() const {
Size2 min_size = minsize;
- const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
- int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
+ int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
min_size.height = MAX(min_size.height, font->get_height(font_size) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM));
- Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
+ Size2 min_style = theme_cache.normal_style->get_minimum_size();
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
return Size2(1, (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style;
} else {
@@ -589,8 +606,8 @@ int Label::get_line_count() const {
}
int Label::get_visible_line_count() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
+ Ref<StyleBox> style = theme_cache.normal_style;
+ int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
int lines_visible = 0;
float total_h = 0.0;
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
@@ -788,10 +805,10 @@ int Label::get_visible_characters() const {
void Label::set_visible_ratio(float p_ratio) {
if (visible_ratio != p_ratio) {
- if (visible_ratio >= 1.0) {
+ if (p_ratio >= 1.0) {
visible_chars = -1;
visible_ratio = 1.0;
- } else if (visible_ratio < 0.0) {
+ } else if (p_ratio < 0.0) {
visible_chars = 0;
visible_ratio = 0.0;
} else {
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 65831cab6e..b79c94a5ba 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -67,13 +67,28 @@ private:
Ref<LabelSettings> settings;
+ struct ThemeCache {
+ Ref<StyleBox> normal_style;
+ Ref<Font> font;
+
+ int font_size = 0;
+ int line_spacing = 0;
+ Color font_color;
+ Color font_shadow_color;
+ Point2 font_shadow_offset;
+ Color font_outline_color;
+ int font_outline_size;
+ int font_shadow_outline_size;
+ } theme_cache;
+
void _update_visible();
void _shape();
void _invalidate();
protected:
- void _notification(int p_what);
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index aa8a825014..c2ce4bdb83 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -448,7 +448,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
if (context_menu_enabled) {
if (k->is_action("ui_menu", true)) {
_ensure_menu();
- Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")))) / 2);
+ Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + theme_cache.font->get_height(theme_cache.font_size)) / 2);
menu->set_position(get_screen_position() + pos);
menu->reset_size();
menu->popup();
@@ -696,11 +696,38 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
if (!clear_button_enabled || !has_point(p_pos)) {
return false;
}
- Ref<Texture2D> icon = Control::get_theme_icon(SNAME("clear"));
- int x_ofs = get_theme_stylebox(SNAME("normal"))->get_margin(SIDE_RIGHT);
+ Ref<Texture2D> icon = theme_cache.clear_icon;
+ int x_ofs = theme_cache.normal->get_margin(SIDE_RIGHT);
return p_pos.x > get_size().width - icon->get_width() - x_ofs;
}
+void LineEdit::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+ theme_cache.read_only = get_theme_stylebox(SNAME("read_only"));
+ theme_cache.focus = get_theme_stylebox(SNAME("focus"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_uneditable_color = get_theme_color(SNAME("font_uneditable_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color"));
+ theme_cache.caret_width = get_theme_constant(SNAME("caret_width"));
+ theme_cache.caret_color = get_theme_color(SNAME("caret_color"));
+ theme_cache.minimum_character_width = get_theme_constant(SNAME("minimum_character_width"));
+ theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
+
+ theme_cache.clear_icon = get_theme_icon(SNAME("clear"));
+ theme_cache.clear_button_color = get_theme_color(SNAME("clear_button_color"));
+ theme_cache.clear_button_color_pressed = get_theme_color(SNAME("clear_button_color_pressed"));
+
+ theme_cache.base_scale = get_theme_default_base_scale();
+}
+
void LineEdit::_notification(int p_what) {
switch (p_what) {
#ifdef TOOLS_ENABLED
@@ -771,19 +798,19 @@ void LineEdit::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
if (!is_editable()) {
- style = get_theme_stylebox(SNAME("read_only"));
+ style = theme_cache.read_only;
draw_caret = false;
}
- Ref<Font> font = get_theme_font(SNAME("font"));
+ Ref<Font> font = theme_cache.font;
if (!flat) {
style->draw(ci, Rect2(Point2(), size));
}
if (has_focus()) {
- get_theme_stylebox(SNAME("focus"))->draw(ci, Rect2(Point2(), size));
+ theme_cache.focus->draw(ci, Rect2(Point2(), size));
}
int x_ofs = 0;
@@ -821,25 +848,30 @@ void LineEdit::_notification(int p_what) {
int y_area = height - style->get_minimum_size().height;
int y_ofs = style->get_offset().y + (y_area - text_height) / 2;
- Color selection_color = get_theme_color(SNAME("selection_color"));
- Color font_color = get_theme_color(is_editable() ? SNAME("font_color") : SNAME("font_uneditable_color"));
- Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
- Color caret_color = get_theme_color(SNAME("caret_color"));
+ Color selection_color = theme_cache.selection_color;
+ Color font_color;
+ if (is_editable()) {
+ font_color = theme_cache.font_color;
+ } else {
+ font_color = theme_cache.font_uneditable_color;
+ }
+ Color font_selected_color = theme_cache.font_selected_color;
+ Color caret_color = theme_cache.caret_color;
// Draw placeholder color.
if (using_placeholder) {
- font_color = get_theme_color(SNAME("font_placeholder_color"));
+ font_color = theme_cache.font_placeholder_color;
}
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9);
if (display_clear_icon) {
if (clear_button_status.press_attempt && clear_button_status.pressing_inside) {
- color_icon = get_theme_color(SNAME("clear_button_color_pressed"));
+ color_icon = theme_cache.clear_button_color_pressed;
} else {
- color_icon = get_theme_color(SNAME("clear_button_color"));
+ color_icon = theme_cache.clear_button_color;
}
}
@@ -879,8 +911,8 @@ void LineEdit::_notification(int p_what) {
// Draw text.
ofs.y += TS->shaped_text_get_ascent(text_rid);
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.font_outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
Vector2 oofs = ofs;
for (int i = 0; i < gl_size; i++) {
@@ -918,7 +950,7 @@ void LineEdit::_notification(int p_what) {
ofs.x = x_ofs + scroll_offset;
if (draw_caret || drag_caret_force_displayed) {
// Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1).
- const int caret_width = get_theme_constant(SNAME("caret_width")) * MAX(1, get_theme_default_base_scale());
+ const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale);
if (ime_text.length() == 0) {
// Normal caret.
@@ -926,7 +958,7 @@ void LineEdit::_notification(int p_what) {
if (caret.l_caret == Rect2() && caret.t_caret == Rect2()) {
// No carets, add one at the start.
- int h = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
+ int h = theme_cache.font->get_height(theme_cache.font_size);
int y = style->get_offset().y + (y_area - h) / 2;
if (rtl) {
caret.l_dir = TextServer::DIRECTION_RTL;
@@ -1193,7 +1225,7 @@ void LineEdit::shift_selection_check_post(bool p_shift) {
}
void LineEdit::set_caret_at_pixel_pos(int p_x) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1226,7 +1258,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
if (Math::is_zero_approx(scroll_offset)) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1241,7 +1273,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
}
Vector2 LineEdit::get_caret_pixel_pos() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1274,7 +1306,7 @@ Vector2 LineEdit::get_caret_pixel_pos() {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
if (Math::is_zero_approx(scroll_offset)) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1559,7 +1591,7 @@ void LineEdit::set_caret_column(int p_column) {
return;
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
bool rtl = is_layout_rtl();
int x_ofs = 0;
@@ -1593,7 +1625,7 @@ void LineEdit::set_caret_column(int p_column) {
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
if (Math::is_zero_approx(scroll_offset)) {
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
@@ -1664,15 +1696,15 @@ void LineEdit::clear_internal() {
}
Size2 LineEdit::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ Ref<StyleBox> style = theme_cache.normal;
+ Ref<Font> font = theme_cache.font;
+ int font_size = theme_cache.font_size;
Size2 min_size;
// Minimum size of text.
float em_space_size = font->get_char_size('M', font_size).x;
- min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
+ min_size.width = theme_cache.minimum_character_width * em_space_size;
if (expand_to_text_length) {
// Add a space because some fonts are too exact, and because caret needs a bit more when at the end.
@@ -1688,9 +1720,8 @@ Size2 LineEdit::get_minimum_size() const {
icon_max_width = right_icon->get_width();
}
if (clear_button_enabled) {
- Ref<Texture2D> clear_icon = Control::get_theme_icon(SNAME("clear"));
- min_size.height = MAX(min_size.height, clear_icon->get_height());
- icon_max_width = MAX(icon_max_width, clear_icon->get_width());
+ min_size.height = MAX(min_size.height, theme_cache.clear_icon->get_height());
+ icon_max_width = MAX(icon_max_width, theme_cache.clear_icon->get_width());
}
min_size.width += icon_max_width;
@@ -2155,8 +2186,8 @@ void LineEdit::_shape() {
}
TS->shaped_text_set_preserve_control(text_rid, draw_control_chars);
- const Ref<Font> &font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ const Ref<Font> &font = theme_cache.font;
+ int font_size = theme_cache.font_size;
ERR_FAIL_COND(font.is_null());
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), language);
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
@@ -2176,12 +2207,12 @@ void LineEdit::_shape() {
void LineEdit::_fit_to_width() {
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
int t_width = get_size().width - style->get_margin(SIDE_RIGHT) - style->get_margin(SIDE_LEFT);
bool using_placeholder = text.is_empty() && ime_text.is_empty();
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
t_width -= r_icon->get_width();
}
TS->shaped_text_fit_to_width(text_rid, MAX(t_width, full_width));
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index dabdaa3395..0122a5da69 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -174,6 +174,31 @@ private:
double caret_blink_timer = 0.0;
bool caret_blinking = false;
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+ Ref<StyleBox> read_only;
+ Ref<StyleBox> focus;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Color font_color;
+ Color font_uneditable_color;
+ Color font_selected_color;
+ int font_outline_size;
+ Color font_outline_color;
+ Color font_placeholder_color;
+ int caret_width = 0;
+ Color caret_color;
+ int minimum_character_width = 0;
+ Color selection_color;
+
+ Ref<Texture2D> clear_icon;
+ Color clear_button_color;
+ Color clear_button_color_pressed;
+
+ float base_scale = 1.0;
+ } theme_cache;
+
bool _is_over_clear_button(const Point2 &p_pos) const;
void _clear_undo_stack();
@@ -215,6 +240,7 @@ private:
void _ensure_menu();
protected:
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index b0252ac685..7219e86f52 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -33,8 +33,8 @@
#include "core/string/translation.h"
void LinkButton::_shape() {
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ Ref<Font> font = theme_cache.font;
+ int font_size = theme_cache.font_size;
text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
@@ -125,6 +125,26 @@ Size2 LinkButton::get_minimum_size() const {
return text_buf->get_size();
}
+void LinkButton::_update_theme_item_cache() {
+ BaseButton::_update_theme_item_cache();
+
+ theme_cache.focus = get_theme_stylebox(SNAME("focus"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.underline_spacing = get_theme_constant(SNAME("underline_spacing"));
+}
+
void LinkButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -153,9 +173,9 @@ void LinkButton::_notification(int p_what) {
switch (get_draw_mode()) {
case DRAW_NORMAL: {
if (has_focus()) {
- color = get_theme_color(SNAME("font_focus_color"));
+ color = theme_cache.font_focus_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
@@ -163,35 +183,35 @@ void LinkButton::_notification(int p_what) {
case DRAW_HOVER_PRESSED:
case DRAW_PRESSED: {
if (has_theme_color(SNAME("font_pressed_color"))) {
- color = get_theme_color(SNAME("font_pressed_color"));
+ color = theme_cache.font_pressed_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_HOVER: {
- color = get_theme_color(SNAME("font_hover_color"));
+ color = theme_cache.font_hover_color;
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_DISABLED: {
- color = get_theme_color(SNAME("font_disabled_color"));
+ color = theme_cache.font_disabled_color;
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
} break;
}
if (has_focus()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("focus"));
+ Ref<StyleBox> style = theme_cache.focus;
style->draw(ci, Rect2(Point2(), size));
}
int width = text_buf->get_line_width();
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.outline_size;
if (is_layout_rtl()) {
if (outline_size > 0 && font_outline_color.a > 0) {
text_buf->draw_outline(get_canvas_item(), Vector2(size.width - width, 0), outline_size, font_outline_color);
@@ -205,7 +225,7 @@ void LinkButton::_notification(int p_what) {
}
if (do_underline) {
- int underline_spacing = get_theme_constant(SNAME("underline_spacing")) + text_buf->get_line_underline_position();
+ int underline_spacing = theme_cache.underline_spacing + text_buf->get_line_underline_position();
int y = text_buf->get_line_ascent() + underline_spacing;
if (is_layout_rtl()) {
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index 12a6a7618f..accd848163 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -55,10 +55,29 @@ private:
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
+ struct ThemeCache {
+ Ref<StyleBox> focus;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+
+ Ref<Font> font;
+ int font_size = 0;
+ int outline_size = 0;
+ Color font_outline_color;
+
+ int underline_spacing = 0;
+ } theme_cache;
+
void _shape();
protected:
virtual Size2 get_minimum_size() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index fac37a8634..60fe681824 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -30,12 +30,16 @@
#include "margin_container.h"
-Size2 MarginContainer::get_minimum_size() const {
- int margin_left = get_theme_constant(SNAME("margin_left"));
- int margin_top = get_theme_constant(SNAME("margin_top"));
- int margin_right = get_theme_constant(SNAME("margin_right"));
- int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
+void MarginContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.margin_left = get_theme_constant(SNAME("margin_left"));
+ theme_cache.margin_top = get_theme_constant(SNAME("margin_top"));
+ theme_cache.margin_right = get_theme_constant(SNAME("margin_right"));
+ theme_cache.margin_bottom = get_theme_constant(SNAME("margin_bottom"));
+}
+Size2 MarginContainer::get_minimum_size() const {
Size2 max;
for (int i = 0; i < get_child_count(); i++) {
@@ -59,8 +63,8 @@ Size2 MarginContainer::get_minimum_size() const {
}
}
- max.width += (margin_left + margin_right);
- max.height += (margin_top + margin_bottom);
+ max.width += (theme_cache.margin_left + theme_cache.margin_right);
+ max.height += (theme_cache.margin_top + theme_cache.margin_bottom);
return max;
}
@@ -86,11 +90,6 @@ Vector<int> MarginContainer::get_allowed_size_flags_vertical() const {
void MarginContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
- int margin_left = get_theme_constant(SNAME("margin_left"));
- int margin_top = get_theme_constant(SNAME("margin_top"));
- int margin_right = get_theme_constant(SNAME("margin_right"));
- int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
-
Size2 s = get_size();
for (int i = 0; i < get_child_count(); i++) {
@@ -102,9 +101,9 @@ void MarginContainer::_notification(int p_what) {
continue;
}
- int w = s.width - margin_left - margin_right;
- int h = s.height - margin_top - margin_bottom;
- fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h));
+ int w = s.width - theme_cache.margin_left - theme_cache.margin_right;
+ int h = s.height - theme_cache.margin_top - theme_cache.margin_bottom;
+ fit_child_in_rect(c, Rect2(theme_cache.margin_left, theme_cache.margin_top, w, h));
}
} break;
diff --git a/scene/gui/margin_container.h b/scene/gui/margin_container.h
index f8a3c5bb11..5c33785170 100644
--- a/scene/gui/margin_container.h
+++ b/scene/gui/margin_container.h
@@ -36,7 +36,16 @@
class MarginContainer : public Container {
GDCLASS(MarginContainer, Container);
+ struct ThemeCache {
+ int margin_left = 0;
+ int margin_top = 0;
+ int margin_right = 0;
+ int margin_bottom = 0;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
public:
diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp
index 8aad14e1ec..0613652bdf 100644
--- a/scene/gui/menu_bar.cpp
+++ b/scene/gui/menu_bar.cpp
@@ -149,10 +149,6 @@ void MenuBar::_open_popup(int p_index, bool p_focus_item) {
void MenuBar::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
- if (is_native_menu()) {
- return;
- }
-
if (!_is_focus_owner_in_shortcut_context()) {
return;
}
@@ -253,7 +249,7 @@ void MenuBar::_update_submenu(const String &p_menu_name, PopupMenu *p_child) {
DisplayServer::get_singleton()->global_menu_add_submenu_item(p_menu_name, p_child->get_item_text(i), p_menu_name + "/" + itos(i));
_update_submenu(p_menu_name + "/" + itos(i), pm);
} else {
- int index = DisplayServer::get_singleton()->global_menu_add_item(p_menu_name, p_child->get_item_text(i), callable_mp(p_child, &PopupMenu::activate_item), i);
+ int index = DisplayServer::get_singleton()->global_menu_add_item(p_menu_name, p_child->get_item_text(i), callable_mp(p_child, &PopupMenu::activate_item), Callable(), i);
if (p_child->is_item_checkable(i)) {
DisplayServer::get_singleton()->global_menu_set_item_checkable(p_menu_name, index, true);
@@ -340,6 +336,35 @@ void MenuBar::_update_menu() {
queue_redraw();
}
+void MenuBar::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+ theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
+ theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
+ theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
+ theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
+ theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
+ theme_cache.hover = get_theme_stylebox(SNAME("hover"));
+ theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
+ theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
+ theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+}
+
void MenuBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -376,12 +401,24 @@ void MenuBar::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
MutexLock lock(mutex);
+ if (is_native_menu()) {
+ // Handled by OS.
+ return;
+ }
+
Vector2 pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted - get_global_position();
+ if (pos == old_mouse_pos) {
+ return;
+ }
+ old_mouse_pos = pos;
+
int index = _get_index_at_point(pos);
if (index >= 0 && index != active_menu) {
selected_menu = index;
focused_menu = selected_menu;
- get_menu_popup(active_menu)->hide();
+ if (active_menu >= 0) {
+ get_menu_popup(active_menu)->hide();
+ }
_open_popup(index);
}
} break;
@@ -389,8 +426,7 @@ void MenuBar::_notification(int p_what) {
}
int MenuBar::_get_index_at_point(const Point2 &p_point) const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int hsep = get_theme_constant(SNAME("h_separation"));
+ Ref<StyleBox> style = theme_cache.normal;
int offset = 0;
for (int i = 0; i < menu_cache.size(); i++) {
if (menu_cache[i].hidden) {
@@ -402,7 +438,7 @@ int MenuBar::_get_index_at_point(const Point2 &p_point) const {
return i;
}
}
- offset += size.x + hsep;
+ offset += size.x + theme_cache.h_separation;
}
return -1;
}
@@ -410,8 +446,7 @@ int MenuBar::_get_index_at_point(const Point2 &p_point) const {
Rect2 MenuBar::_get_menu_item_rect(int p_index) const {
ERR_FAIL_INDEX_V(p_index, menu_cache.size(), Rect2());
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- int hsep = get_theme_constant(SNAME("h_separation"));
+ Ref<StyleBox> style = theme_cache.normal;
int offset = 0;
for (int i = 0; i < p_index; i++) {
@@ -419,7 +454,7 @@ Rect2 MenuBar::_get_menu_item_rect(int p_index) const {
continue;
}
Size2 size = menu_cache[i].text_buf->get_size() + style->get_minimum_size();
- offset += size.x + hsep;
+ offset += size.x + theme_cache.h_separation;
}
return Rect2(Point2(offset, 0), menu_cache[p_index].text_buf->get_size() + style->get_minimum_size());
@@ -438,76 +473,76 @@ void MenuBar::_draw_menu_item(int p_index) {
}
Color color;
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
Rect2 item_rect = _get_menu_item_rect(p_index);
if (menu_cache[p_index].disabled) {
if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
- style = get_theme_stylebox(SNAME("disabled_mirrored"));
+ style = theme_cache.disabled_mirrored;
} else {
- style = get_theme_stylebox(SNAME("disabled"));
+ style = theme_cache.disabled;
}
if (!flat) {
style->draw(ci, item_rect);
}
- color = get_theme_color(SNAME("font_disabled_color"));
+ color = theme_cache.font_disabled_color;
} else if (hovered && pressed && has_theme_stylebox("hover_pressed")) {
if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
+ style = theme_cache.hover_pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover_pressed"));
+ style = theme_cache.hover_pressed;
}
if (!flat) {
style->draw(ci, item_rect);
}
if (has_theme_color(SNAME("font_hover_pressed_color"))) {
- color = get_theme_color(SNAME("font_hover_pressed_color"));
+ color = theme_cache.font_hover_pressed_color;
}
} else if (pressed) {
if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
- style = get_theme_stylebox(SNAME("pressed_mirrored"));
+ style = theme_cache.pressed_mirrored;
} else {
- style = get_theme_stylebox(SNAME("pressed"));
+ style = theme_cache.pressed;
}
if (!flat) {
style->draw(ci, item_rect);
}
if (has_theme_color(SNAME("font_pressed_color"))) {
- color = get_theme_color(SNAME("font_pressed_color"));
+ color = theme_cache.font_pressed_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
} else if (hovered) {
if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
- style = get_theme_stylebox(SNAME("hover_mirrored"));
+ style = theme_cache.hover_mirrored;
} else {
- style = get_theme_stylebox(SNAME("hover"));
+ style = theme_cache.hover;
}
if (!flat) {
style->draw(ci, item_rect);
}
- color = get_theme_color(SNAME("font_hover_color"));
+ color = theme_cache.font_hover_color;
} else {
if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
- style = get_theme_stylebox(SNAME("normal_mirrored"));
+ style = theme_cache.normal_mirrored;
} else {
- style = get_theme_stylebox(SNAME("normal"));
+ style = theme_cache.normal;
}
if (!flat) {
style->draw(ci, item_rect);
}
// Focus colors only take precedence over normal state.
if (has_focus()) {
- color = get_theme_color(SNAME("font_focus_color"));
+ color = theme_cache.font_focus_color;
} else {
- color = get_theme_color(SNAME("font_color"));
+ color = theme_cache.font_color;
}
}
Point2 text_ofs = item_rect.position + Point2(style->get_margin(SIDE_LEFT), style->get_margin(SIDE_TOP));
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
menu_cache[p_index].text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
}
@@ -515,16 +550,13 @@ void MenuBar::_draw_menu_item(int p_index) {
}
void MenuBar::shape(Menu &p_menu) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
p_menu.text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
p_menu.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
p_menu.text_buf->set_direction((TextServer::Direction)text_direction);
}
- p_menu.text_buf->add_string(p_menu.name, font, font_size, language);
+ p_menu.text_buf->add_string(p_menu.name, theme_cache.font, theme_cache.font_size, language);
}
void MenuBar::_refresh_menu_names() {
@@ -754,7 +786,7 @@ Size2 MenuBar::get_minimum_size() const {
return Size2();
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
+ Ref<StyleBox> style = theme_cache.normal;
Vector2 size;
for (int i = 0; i < menu_cache.size(); i++) {
@@ -766,7 +798,7 @@ Size2 MenuBar::get_minimum_size() const {
size.x += sz.x;
}
if (menu_cache.size() > 1) {
- size.x += get_theme_constant(SNAME("h_separation")) * (menu_cache.size() - 1);
+ size.x += theme_cache.h_separation * (menu_cache.size() - 1);
}
return size;
}
diff --git a/scene/gui/menu_bar.h b/scene/gui/menu_bar.h
index b7d9933ab2..f7ef19e98b 100644
--- a/scene/gui/menu_bar.h
+++ b/scene/gui/menu_bar.h
@@ -73,8 +73,36 @@ class MenuBar : public Control {
int active_menu = -1;
Vector2i mouse_pos_adjusted;
+ Vector2i old_mouse_pos;
ObjectID shortcut_context;
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+ Ref<StyleBox> normal_mirrored;
+ Ref<StyleBox> disabled;
+ Ref<StyleBox> disabled_mirrored;
+ Ref<StyleBox> pressed;
+ Ref<StyleBox> pressed_mirrored;
+ Ref<StyleBox> hover;
+ Ref<StyleBox> hover_mirrored;
+ Ref<StyleBox> hover_pressed;
+ Ref<StyleBox> hover_pressed_mirrored;
+
+ Ref<Font> font;
+ int font_size = 0;
+ int outline_size = 0;
+ Color font_outline_color;
+
+ Color font_color;
+ Color font_disabled_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_focus_color;
+
+ int h_separation = 0;
+ } theme_cache;
+
int _get_index_at_point(const Point2 &p_point) const;
Rect2 _get_menu_item_rect(int p_index) const;
void _draw_menu_item(int p_index);
@@ -95,6 +123,7 @@ class MenuBar : public Control {
protected:
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
virtual void add_child_notify(Node *p_child) override;
virtual void move_child_notify(Node *p_child) override;
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index a87c46e8ac..0dd9666858 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -43,11 +43,11 @@ Size2 OptionButton::get_minimum_size() const {
}
if (has_theme_icon(SNAME("arrow"))) {
- const Size2 padding = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
- const Size2 arrow_size = Control::get_theme_icon(SNAME("arrow"))->get_size();
+ const Size2 padding = theme_cache.normal->get_minimum_size();
+ const Size2 arrow_size = theme_cache.arrow_icon->get_size();
Size2 content_size = minsize - padding;
- content_size.width += arrow_size.width + MAX(0, get_theme_constant(SNAME("h_separation")));
+ content_size.width += arrow_size.width + MAX(0, theme_cache.h_separation);
content_size.height = MAX(content_size.height, arrow_size.height);
minsize = content_size + padding;
@@ -56,35 +56,63 @@ Size2 OptionButton::get_minimum_size() const {
return minsize;
}
+void OptionButton::_update_theme_item_cache() {
+ Button::_update_theme_item_cache();
+
+ theme_cache.normal = get_theme_stylebox(SNAME("normal"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
+ theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+
+ theme_cache.arrow_icon = get_theme_icon(SNAME("arrow"));
+ theme_cache.arrow_margin = get_theme_constant(SNAME("arrow_margin"));
+ theme_cache.modulate_arrow = get_theme_constant(SNAME("modulate_arrow"));
+}
+
void OptionButton::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_POSTINITIALIZE: {
+ if (has_theme_icon(SNAME("arrow"))) {
+ if (is_layout_rtl()) {
+ _set_internal_margin(SIDE_LEFT, theme_cache.arrow_icon->get_width());
+ } else {
+ _set_internal_margin(SIDE_RIGHT, theme_cache.arrow_icon->get_width());
+ }
+ }
+ } break;
+
case NOTIFICATION_DRAW: {
if (!has_theme_icon(SNAME("arrow"))) {
return;
}
RID ci = get_canvas_item();
- Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"));
Color clr = Color(1, 1, 1);
- if (get_theme_constant(SNAME("modulate_arrow"))) {
+ if (theme_cache.modulate_arrow) {
switch (get_draw_mode()) {
case DRAW_PRESSED:
- clr = get_theme_color(SNAME("font_pressed_color"));
+ clr = theme_cache.font_pressed_color;
break;
case DRAW_HOVER:
- clr = get_theme_color(SNAME("font_hover_color"));
+ clr = theme_cache.font_hover_color;
break;
case DRAW_HOVER_PRESSED:
- clr = get_theme_color(SNAME("font_hover_pressed_color"));
+ clr = theme_cache.font_hover_pressed_color;
break;
case DRAW_DISABLED:
- clr = get_theme_color(SNAME("font_disabled_color"));
+ clr = theme_cache.font_disabled_color;
break;
default:
if (has_focus()) {
- clr = get_theme_color(SNAME("font_focus_color"));
+ clr = theme_cache.font_focus_color;
} else {
- clr = get_theme_color(SNAME("font_color"));
+ clr = theme_cache.font_color;
}
}
}
@@ -93,11 +121,11 @@ void OptionButton::_notification(int p_what) {
Point2 ofs;
if (is_layout_rtl()) {
- ofs = Point2(get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ ofs = Point2(theme_cache.arrow_margin, int(Math::abs((size.height - theme_cache.arrow_icon->get_height()) / 2)));
} else {
- ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ ofs = Point2(size.width - theme_cache.arrow_icon->get_width() - theme_cache.arrow_margin, int(Math::abs((size.height - theme_cache.arrow_icon->get_height()) / 2)));
}
- arrow->draw(ci, ofs, clr);
+ theme_cache.arrow_icon->draw(ci, ofs, clr);
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
@@ -108,11 +136,11 @@ void OptionButton::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
if (has_theme_icon(SNAME("arrow"))) {
if (is_layout_rtl()) {
- _set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
+ _set_internal_margin(SIDE_LEFT, theme_cache.arrow_icon->get_width());
_set_internal_margin(SIDE_RIGHT, 0.f);
} else {
_set_internal_margin(SIDE_LEFT, 0.f);
- _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
+ _set_internal_margin(SIDE_RIGHT, theme_cache.arrow_icon->get_width());
}
}
_refresh_size_cache();
@@ -540,15 +568,6 @@ OptionButton::OptionButton(const String &p_text) :
Button(p_text) {
set_toggle_mode(true);
set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
- if (is_layout_rtl()) {
- if (has_theme_icon(SNAME("arrow"))) {
- _set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
- }
- } else {
- if (has_theme_icon(SNAME("arrow"))) {
- _set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
- }
- }
set_action_mode(ACTION_MODE_BUTTON_PRESS);
popup = memnew(PopupMenu);
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index cd709b8f5f..2c7e0510f5 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -43,6 +43,23 @@ class OptionButton : public Button {
Vector2 _cached_size;
bool cache_refresh_pending = false;
+ struct ThemeCache {
+ Ref<StyleBox> normal;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_pressed_color;
+ Color font_hover_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+
+ int h_separation = 0;
+
+ Ref<Texture2D> arrow_icon;
+ int arrow_margin = 0;
+ int modulate_arrow = 0;
+ } theme_cache;
+
void _focused(int p_which);
void _selected(int p_which);
void _select(int p_which, bool p_emit = false);
@@ -54,6 +71,7 @@ class OptionButton : public Button {
protected:
Size2 get_minimum_size() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp
index 1ac6cf57ab..09bc295513 100644
--- a/scene/gui/panel.cpp
+++ b/scene/gui/panel.cpp
@@ -30,12 +30,17 @@
#include "panel.h"
+void Panel::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void Panel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
- style->draw(ci, Rect2(Point2(), get_size()));
+ theme_cache.panel_style->draw(ci, Rect2(Point2(), get_size()));
} break;
}
}
diff --git a/scene/gui/panel.h b/scene/gui/panel.h
index 5d2e912680..f9bd721681 100644
--- a/scene/gui/panel.h
+++ b/scene/gui/panel.h
@@ -36,7 +36,13 @@
class Panel : public Control {
GDCLASS(Panel, Control);
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
public:
diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp
index fe01712a89..eeaded1788 100644
--- a/scene/gui/panel_container.cpp
+++ b/scene/gui/panel_container.cpp
@@ -31,14 +31,6 @@
#include "panel_container.h"
Size2 PanelContainer::get_minimum_size() const {
- Ref<StyleBox> style;
-
- if (has_theme_stylebox(SNAME("panel"))) {
- style = get_theme_stylebox(SNAME("panel"));
- } else {
- style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
- }
-
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -54,8 +46,8 @@ Size2 PanelContainer::get_minimum_size() const {
ms.height = MAX(ms.height, minsize.height);
}
- if (style.is_valid()) {
- ms += style->get_minimum_size();
+ if (theme_cache.panel_style.is_valid()) {
+ ms += theme_cache.panel_style->get_minimum_size();
}
return ms;
}
@@ -78,35 +70,25 @@ Vector<int> PanelContainer::get_allowed_size_flags_vertical() const {
return flags;
}
+void PanelContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void PanelContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
- Ref<StyleBox> style;
-
- if (has_theme_stylebox(SNAME("panel"))) {
- style = get_theme_stylebox(SNAME("panel"));
- } else {
- style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
- }
-
- style->draw(ci, Rect2(Point2(), get_size()));
+ theme_cache.panel_style->draw(ci, Rect2(Point2(), get_size()));
} break;
case NOTIFICATION_SORT_CHILDREN: {
- Ref<StyleBox> style;
-
- if (has_theme_stylebox(SNAME("panel"))) {
- style = get_theme_stylebox(SNAME("panel"));
- } else {
- style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
- }
-
Size2 size = get_size();
Point2 ofs;
- if (style.is_valid()) {
- size -= style->get_minimum_size();
- ofs += style->get_offset();
+ if (theme_cache.panel_style.is_valid()) {
+ size -= theme_cache.panel_style->get_minimum_size();
+ ofs += theme_cache.panel_style->get_offset();
}
for (int i = 0; i < get_child_count(); i++) {
diff --git a/scene/gui/panel_container.h b/scene/gui/panel_container.h
index 8f07ce38eb..97d0cdc872 100644
--- a/scene/gui/panel_container.h
+++ b/scene/gui/panel_container.h
@@ -36,7 +36,12 @@
class PanelContainer : public Container {
GDCLASS(PanelContainer, Container);
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
public:
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index c4396f636a..ceae3791f3 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -68,6 +68,12 @@ void Popup::_deinitialize_visible_parents() {
}
}
+void Popup::_update_theme_item_cache() {
+ Window::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void Popup::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -186,8 +192,6 @@ Popup::~Popup() {
}
Size2 PopupPanel::_get_contents_minimum_size() const {
- Ref<StyleBox> p = get_theme_stylebox(SNAME("panel"), get_class_name());
-
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
@@ -205,14 +209,12 @@ Size2 PopupPanel::_get_contents_minimum_size() const {
ms.y = MAX(cms.y, ms.y);
}
- return ms + p->get_minimum_size();
+ return ms + theme_cache.panel_style->get_minimum_size();
}
void PopupPanel::_update_child_rects() {
- Ref<StyleBox> p = get_theme_stylebox(SNAME("panel"), get_class_name());
-
- Vector2 cpos(p->get_offset());
- Vector2 csize(get_size() - p->get_minimum_size());
+ Vector2 cpos(theme_cache.panel_style->get_offset());
+ Vector2 csize(get_size() - theme_cache.panel_style->get_minimum_size());
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@@ -234,15 +236,17 @@ void PopupPanel::_update_child_rects() {
}
}
+void PopupPanel::_update_theme_item_cache() {
+ Popup::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+}
+
void PopupPanel::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_READY:
case NOTIFICATION_THEME_CHANGED: {
- panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), get_class_name()));
- } break;
-
- case NOTIFICATION_ENTER_TREE:
- case NOTIFICATION_READY: {
- panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), get_class_name()));
+ panel->add_theme_style_override("panel", theme_cache.panel_style);
_update_child_rects();
} break;
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index 70eb8722d0..0d6ca25c18 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -43,6 +43,10 @@ class Popup : public Window {
LocalVector<Window *> visible_parents;
bool popped_up = false;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
void _input_from_window(const Ref<InputEvent> &p_event);
void _initialize_visible_parents();
@@ -52,6 +56,7 @@ protected:
void _close_pressed();
virtual Rect2i _popup_adjust_rect() const override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
@@ -69,8 +74,14 @@ class PopupPanel : public Popup {
Panel *panel = nullptr;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ } theme_cache;
+
protected:
void _update_child_rects();
+
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
virtual Size2 _get_contents_minimum_size() const override;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index c3060bf242..9afcd566b9 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -48,15 +48,12 @@ String PopupMenu::_get_accel_text(const Item &p_item) const {
}
Size2 PopupMenu::_get_contents_minimum_size() const {
- int vseparation = get_theme_constant(SNAME("v_separation"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
- Size2 minsize = get_theme_stylebox(SNAME("panel"))->get_minimum_size(); // Accounts for margin in the margin container
+ Size2 minsize = theme_cache.panel_style->get_minimum_size(); // Accounts for margin in the margin container
minsize.x += scroll_container->get_v_scroll_bar()->get_size().width * 2; // Adds a buffer so that the scrollbar does not render over the top of content
float max_w = 0.0;
float icon_w = 0.0;
- int check_w = MAX(get_theme_icon(SNAME("checked"))->get_width(), get_theme_icon(SNAME("radio_checked"))->get_width()) + hseparation;
+ int check_w = MAX(theme_cache.checked->get_width(), theme_cache.radio_checked->get_width()) + theme_cache.h_separation;
int accel_max_w = 0;
bool has_check = false;
@@ -67,23 +64,23 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
size.height = _get_item_height(i);
icon_w = MAX(icon_size.width, icon_w);
- size.width += items[i].indent * get_theme_constant(SNAME("indent"));
+ size.width += items[i].indent * theme_cache.indent;
if (items[i].checkable_type && !items[i].separator) {
has_check = true;
}
size.width += items[i].text_buf->get_size().x;
- size.height += vseparation;
+ size.height += theme_cache.v_separation;
if (items[i].accel != Key::NONE || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) {
- int accel_w = hseparation * 2;
+ int accel_w = theme_cache.h_separation * 2;
accel_w += items[i].accel_text_buf->get_size().x;
accel_max_w = MAX(accel_w, accel_max_w);
}
if (!items[i].submenu.is_empty()) {
- size.width += get_theme_icon(SNAME("submenu"))->get_width();
+ size.width += theme_cache.submenu->get_width();
}
max_w = MAX(max_w, size.width);
@@ -91,7 +88,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
minsize.height += size.height;
}
- int item_side_padding = get_theme_constant(SNAME("item_start_padding")) + get_theme_constant(SNAME("item_end_padding"));
+ int item_side_padding = theme_cache.item_start_padding + theme_cache.item_end_padding;
minsize.width += max_w + icon_w + accel_max_w + item_side_padding;
if (has_check) {
@@ -113,33 +110,31 @@ int PopupMenu::_get_item_height(int p_item) const {
int icon_height = items[p_item].get_icon_size().height;
if (items[p_item].checkable_type && !items[p_item].separator) {
- icon_height = MAX(icon_height, MAX(get_theme_icon(SNAME("checked"))->get_height(), get_theme_icon(SNAME("radio_checked"))->get_height()));
+ icon_height = MAX(icon_height, MAX(theme_cache.checked->get_height(), theme_cache.radio_checked->get_height()));
}
int text_height = items[p_item].text_buf->get_size().height;
if (text_height == 0 && !items[p_item].separator) {
- text_height = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
+ text_height = theme_cache.font->get_height(theme_cache.font_size);
}
int separator_height = 0;
if (items[p_item].separator) {
- separator_height = MAX(get_theme_stylebox(SNAME("separator"))->get_minimum_size().height, MAX(get_theme_stylebox(SNAME("labeled_separator_left"))->get_minimum_size().height, get_theme_stylebox(SNAME("labeled_separator_right"))->get_minimum_size().height));
+ separator_height = MAX(theme_cache.separator_style->get_minimum_size().height, MAX(theme_cache.labeled_separator_left->get_minimum_size().height, theme_cache.labeled_separator_right->get_minimum_size().height));
}
return MAX(separator_height, MAX(text_height, icon_height));
}
int PopupMenu::_get_items_total_height() const {
- int vsep = get_theme_constant(SNAME("v_separation"));
-
// Get total height of all items by taking max of icon height and font height
int items_total_height = 0;
for (int i = 0; i < items.size(); i++) {
- items_total_height += _get_item_height(i) + vsep;
+ items_total_height += _get_item_height(i) + theme_cache.v_separation;
}
// Subtract a separator which is not needed for the last item.
- return items_total_height - vsep;
+ return items_total_height - theme_cache.v_separation;
}
int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
@@ -147,18 +142,15 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
return -1;
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel")); // Accounts for margin in the margin container
-
- int vseparation = get_theme_constant(SNAME("v_separation"));
-
- Point2 ofs = style->get_offset() + Point2(0, vseparation / 2);
+ // Accounts for margin in the margin container
+ Point2 ofs = theme_cache.panel_style->get_offset() + Point2(0, theme_cache.v_separation / 2);
if (ofs.y > p_over.y) {
return -1;
}
for (int i = 0; i < items.size(); i++) {
- ofs.y += i > 0 ? vseparation : (float)vseparation / 2;
+ ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2;
ofs.y += _get_item_height(i);
@@ -179,9 +171,6 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
return; // Already visible.
}
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
- int vsep = get_theme_constant(SNAME("v_separation"));
-
Point2 this_pos = get_position();
Rect2 this_rect(this_pos, get_size());
@@ -231,7 +220,7 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
// Set autohide areas.
Rect2 safe_area = this_rect;
- safe_area.position.y += items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2;
+ safe_area.position.y += items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2;
safe_area.size.y = items[p_over]._height_cache;
DisplayServer::get_singleton()->window_set_popup_safe_rect(submenu_popup->get_window_id(), safe_area);
@@ -240,11 +229,11 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
// Autohide area above the submenu item.
submenu_pum->clear_autohide_areas();
- submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2));
+ submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + theme_cache.panel_style->get_offset().height - theme_cache.v_separation / 2));
// If there is an area below the submenu item, add an autohide area there.
if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) {
- int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height;
+ int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + theme_cache.v_separation / 2 + theme_cache.panel_style->get_offset().height;
submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
}
}
@@ -442,7 +431,7 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
- if (m->get_velocity().is_equal_approx(Vector2())) {
+ if (m->get_velocity().is_zero_approx()) {
return;
}
activated_by_keyboard = false;
@@ -528,34 +517,17 @@ void PopupMenu::_draw_items() {
margin_size.height = margin_container->get_theme_constant(SNAME("margin_top")) + margin_container->get_theme_constant(SNAME("margin_bottom"));
// Space between the item content and the sides of popup menu.
- int item_start_padding = get_theme_constant(SNAME("item_start_padding"));
- int item_end_padding = get_theme_constant(SNAME("item_end_padding"));
-
bool rtl = control->is_layout_rtl();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
- Ref<StyleBox> hover = get_theme_stylebox(SNAME("hover"));
// In Item::checkable_type enum order (less the non-checkable member), with disabled repeated at the end.
- Ref<Texture2D> check[] = { get_theme_icon(SNAME("checked")), get_theme_icon(SNAME("radio_checked")), get_theme_icon(SNAME("checked_disabled")), get_theme_icon(SNAME("radio_checked_disabled")) };
- Ref<Texture2D> uncheck[] = { get_theme_icon(SNAME("unchecked")), get_theme_icon(SNAME("radio_unchecked")), get_theme_icon(SNAME("unchecked_disabled")), get_theme_icon(SNAME("radio_unchecked_disabled")) };
+ Ref<Texture2D> check[] = { theme_cache.checked, theme_cache.radio_checked, theme_cache.checked_disabled, theme_cache.radio_checked_disabled };
+ Ref<Texture2D> uncheck[] = { theme_cache.unchecked, theme_cache.radio_unchecked, theme_cache.unchecked_disabled, theme_cache.radio_unchecked_disabled };
Ref<Texture2D> submenu;
if (rtl) {
- submenu = get_theme_icon(SNAME("submenu_mirrored"));
+ submenu = theme_cache.submenu_mirrored;
} else {
- submenu = get_theme_icon(SNAME("submenu"));
+ submenu = theme_cache.submenu;
}
- Ref<StyleBox> separator = get_theme_stylebox(SNAME("separator"));
- Ref<StyleBox> labeled_separator_left = get_theme_stylebox(SNAME("labeled_separator_left"));
- Ref<StyleBox> labeled_separator_right = get_theme_stylebox(SNAME("labeled_separator_right"));
-
- int vseparation = get_theme_constant(SNAME("v_separation"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
- Color font_color = get_theme_color(SNAME("font_color"));
- Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
- Color font_accelerator_color = get_theme_color(SNAME("font_accelerator_color"));
- Color font_hover_color = get_theme_color(SNAME("font_hover_color"));
- Color font_separator_color = get_theme_color(SNAME("font_separator_color"));
-
float scroll_width = scroll_container->get_v_scroll_bar()->is_visible_in_tree() ? scroll_container->get_v_scroll_bar()->get_size().width : 0;
float display_width = control->get_size().width - scroll_width;
@@ -574,7 +546,7 @@ void PopupMenu::_draw_items() {
}
}
if (icon_ofs > 0.0) {
- icon_ofs += hseparation;
+ icon_ofs += theme_cache.h_separation;
}
float check_ofs = 0.0;
@@ -583,7 +555,7 @@ void PopupMenu::_draw_items() {
check_ofs = MAX(check_ofs, check[i]->get_width());
check_ofs = MAX(check_ofs, uncheck[i]->get_width());
}
- check_ofs += hseparation;
+ check_ofs += theme_cache.h_separation;
}
Point2 ofs = Point2();
@@ -591,7 +563,7 @@ void PopupMenu::_draw_items() {
// Loop through all items and draw each.
for (int i = 0; i < items.size(); i++) {
// For the first item only add half a separation. For all other items, add a whole separation to the offset.
- ofs.y += i > 0 ? vseparation : (float)vseparation / 2;
+ ofs.y += i > 0 ? theme_cache.v_separation : (float)theme_cache.v_separation / 2;
_shape_item(i);
@@ -601,47 +573,47 @@ void PopupMenu::_draw_items() {
if (i == mouse_over) {
if (rtl) {
- hover->draw(ci, Rect2(item_ofs + Point2(scroll_width, -vseparation / 2), Size2(display_width, h + vseparation)));
+ theme_cache.hover_style->draw(ci, Rect2(item_ofs + Point2(scroll_width, -theme_cache.v_separation / 2), Size2(display_width, h + theme_cache.v_separation)));
} else {
- hover->draw(ci, Rect2(item_ofs + Point2(0, -vseparation / 2), Size2(display_width, h + vseparation)));
+ theme_cache.hover_style->draw(ci, Rect2(item_ofs + Point2(0, -theme_cache.v_separation / 2), Size2(display_width, h + theme_cache.v_separation)));
}
}
String text = items[i].xl_text;
// Separator
- item_ofs.x += items[i].indent * get_theme_constant(SNAME("indent"));
+ item_ofs.x += items[i].indent * theme_cache.indent;
if (items[i].separator) {
if (!text.is_empty() || !items[i].icon.is_null()) {
- int content_size = items[i].text_buf->get_size().width + hseparation * 2;
+ int content_size = items[i].text_buf->get_size().width + theme_cache.h_separation * 2;
if (!items[i].icon.is_null()) {
- content_size += icon_size.width + hseparation;
+ content_size += icon_size.width + theme_cache.h_separation;
}
int content_center = display_width / 2;
int content_left = content_center - content_size / 2;
int content_right = content_center + content_size / 2;
if (content_left > item_ofs.x) {
- int sep_h = labeled_separator_left->get_center_size().height + labeled_separator_left->get_minimum_size().height;
+ int sep_h = theme_cache.labeled_separator_left->get_center_size().height + theme_cache.labeled_separator_left->get_minimum_size().height;
int sep_ofs = Math::floor((h - sep_h) / 2.0);
- labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(MAX(0, content_left - item_ofs.x), sep_h)));
+ theme_cache.labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(MAX(0, content_left - item_ofs.x), sep_h)));
}
if (content_right < display_width) {
- int sep_h = labeled_separator_right->get_center_size().height + labeled_separator_right->get_minimum_size().height;
+ int sep_h = theme_cache.labeled_separator_right->get_center_size().height + theme_cache.labeled_separator_right->get_minimum_size().height;
int sep_ofs = Math::floor((h - sep_h) / 2.0);
- labeled_separator_right->draw(ci, Rect2(Point2(content_right, item_ofs.y + sep_ofs), Size2(MAX(0, display_width - content_right), sep_h)));
+ theme_cache.labeled_separator_right->draw(ci, Rect2(Point2(content_right, item_ofs.y + sep_ofs), Size2(MAX(0, display_width - content_right), sep_h)));
}
} else {
- int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
+ int sep_h = theme_cache.separator_style->get_center_size().height + theme_cache.separator_style->get_minimum_size().height;
int sep_ofs = Math::floor((h - sep_h) / 2.0);
- separator->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(display_width, sep_h)));
+ theme_cache.separator_style->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(display_width, sep_h)));
}
}
Color icon_color(1, 1, 1, items[i].disabled && !items[i].separator ? 0.5 : 1);
// For non-separator items, add some padding for the content.
- item_ofs.x += item_start_padding;
+ item_ofs.x += theme_cache.item_start_padding;
// Checkboxes
if (items[i].checkable_type && !items[i].separator) {
@@ -659,7 +631,7 @@ void PopupMenu::_draw_items() {
// Icon
if (!items[i].icon.is_null()) {
if (items[i].separator) {
- separator_ofs -= (icon_size.width + hseparation) / 2;
+ separator_ofs -= (icon_size.width + theme_cache.h_separation) / 2;
if (rtl) {
items[i].icon->draw(ci, Size2(control->get_size().width - item_ofs.x - separator_ofs - icon_size.width, item_ofs.y) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
@@ -678,61 +650,55 @@ void PopupMenu::_draw_items() {
// Submenu arrow on right hand side.
if (!items[i].submenu.is_empty()) {
if (rtl) {
- submenu->draw(ci, Point2(scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ submenu->draw(ci, Point2(scroll_width + theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
} else {
- submenu->draw(ci, Point2(display_width - style->get_margin(SIDE_RIGHT) - submenu->get_width() - item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ submenu->draw(ci, Point2(display_width - theme_cache.panel_style->get_margin(SIDE_RIGHT) - submenu->get_width() - theme_cache.item_end_padding, item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
}
}
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
-
// Text
if (items[i].separator) {
- Color font_separator_outline_color = get_theme_color(SNAME("font_separator_outline_color"));
- int separator_outline_size = get_theme_constant(SNAME("separator_outline_size"));
-
if (!text.is_empty()) {
Vector2 text_pos = Point2(separator_ofs, item_ofs.y + Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
if (!rtl && !items[i].icon.is_null()) {
- text_pos.x += icon_size.width + hseparation;
+ text_pos.x += icon_size.width + theme_cache.h_separation;
}
- if (separator_outline_size > 0 && font_separator_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, separator_outline_size, font_separator_outline_color);
+ if (theme_cache.font_separator_outline_size > 0 && theme_cache.font_separator_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_separator_outline_size, theme_cache.font_separator_outline_color);
}
- items[i].text_buf->draw(ci, text_pos, font_separator_color);
+ items[i].text_buf->draw(ci, text_pos, theme_cache.font_separator_color);
}
} else {
item_ofs.x += icon_ofs + check_ofs;
if (rtl) {
Vector2 text_pos = Size2(control->get_size().width - items[i].text_buf->get_size().width - item_ofs.x, item_ofs.y) + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- items[i].text_buf->draw(ci, text_pos, items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
+ items[i].text_buf->draw(ci, text_pos, items[i].disabled ? theme_cache.font_disabled_color : (i == mouse_over ? theme_cache.font_hover_color : theme_cache.font_color));
} else {
Vector2 text_pos = item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- items[i].text_buf->draw(ci, text_pos, items[i].disabled ? font_disabled_color : (i == mouse_over ? font_hover_color : font_color));
+ items[i].text_buf->draw(ci, text_pos, items[i].disabled ? theme_cache.font_disabled_color : (i == mouse_over ? theme_cache.font_hover_color : theme_cache.font_color));
}
}
// Accelerator / Shortcut
if (items[i].accel != Key::NONE || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) {
if (rtl) {
- item_ofs.x = scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding;
+ item_ofs.x = scroll_width + theme_cache.panel_style->get_margin(SIDE_LEFT) + theme_cache.item_end_padding;
} else {
- item_ofs.x = display_width - style->get_margin(SIDE_RIGHT) - items[i].accel_text_buf->get_size().x - item_end_padding;
+ item_ofs.x = display_width - theme_cache.panel_style->get_margin(SIDE_RIGHT) - items[i].accel_text_buf->get_size().x - theme_cache.item_end_padding;
}
Vector2 text_pos = item_ofs + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].accel_text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ items[i].accel_text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- items[i].accel_text_buf->draw(ci, text_pos, i == mouse_over ? font_hover_color : font_accelerator_color);
+ items[i].accel_text_buf->draw(ci, text_pos, i == mouse_over ? theme_cache.font_hover_color : theme_cache.font_accelerator_color);
}
// Cache the item vertical offset from the first item and the height.
@@ -744,9 +710,8 @@ void PopupMenu::_draw_items() {
}
void PopupMenu::_draw_background() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
RID ci2 = margin_container->get_canvas_item();
- style->draw(ci2, Rect2(Point2(), margin_container->get_size()));
+ theme_cache.panel_style->draw(ci2, Rect2(Point2(), margin_container->get_size()));
}
void PopupMenu::_minimum_lifetime_timeout() {
@@ -778,8 +743,8 @@ void PopupMenu::_shape_item(int p_item) {
if (items.write[p_item].dirty) {
items.write[p_item].text_buf->clear();
- Ref<Font> font = get_theme_font(items[p_item].separator ? SNAME("font_separator") : SNAME("font"));
- int font_size = get_theme_font_size(items[p_item].separator ? SNAME("font_separator_size") : SNAME("font_size"));
+ Ref<Font> font = items[p_item].separator ? theme_cache.font_separator : theme_cache.font;
+ int font_size = items[p_item].separator ? theme_cache.font_separator_size : theme_cache.font_size;
if (items[p_item].text_direction == Control::TEXT_DIRECTION_INHERITED) {
items.write[p_item].text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
@@ -821,6 +786,51 @@ void PopupMenu::remove_child_notify(Node *p_child) {
_menu_changed();
}
+void PopupMenu::_update_theme_item_cache() {
+ Popup::_update_theme_item_cache();
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+ theme_cache.hover_style = get_theme_stylebox(SNAME("hover"));
+
+ theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
+ theme_cache.labeled_separator_left = get_theme_stylebox(SNAME("labeled_separator_left"));
+ theme_cache.labeled_separator_right = get_theme_stylebox(SNAME("labeled_separator_right"));
+
+ theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.indent = get_theme_constant(SNAME("indent"));
+ theme_cache.item_start_padding = get_theme_constant(SNAME("item_start_padding"));
+ theme_cache.item_end_padding = get_theme_constant(SNAME("item_end_padding"));
+
+ theme_cache.checked = get_theme_icon(SNAME("checked"));
+ theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
+ theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
+ theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
+ theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
+ theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
+ theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
+
+ theme_cache.submenu = get_theme_icon(SNAME("submenu"));
+ theme_cache.submenu_mirrored = get_theme_icon(SNAME("submenu_mirrored"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_separator = get_theme_font(SNAME("font_separator"));
+ theme_cache.font_separator_size = get_theme_font_size(SNAME("font_separator_size"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_accelerator_color = get_theme_color(SNAME("font_accelerator_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.font_separator_color = get_theme_color(SNAME("font_separator_color"));
+ theme_cache.font_separator_outline_size = get_theme_constant(SNAME("separator_outline_size"));
+ theme_cache.font_separator_outline_color = get_theme_color(SNAME("font_separator_outline_color"));
+}
+
void PopupMenu::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -909,11 +919,10 @@ void PopupMenu::_notification(int p_what) {
}
// Set margin on the margin container
- Ref<StyleBox> panel_style = get_theme_stylebox(SNAME("panel"));
- margin_container->add_theme_constant_override("margin_left", panel_style->get_margin(Side::SIDE_LEFT));
- margin_container->add_theme_constant_override("margin_top", panel_style->get_margin(Side::SIDE_TOP));
- margin_container->add_theme_constant_override("margin_right", panel_style->get_margin(Side::SIDE_RIGHT));
- margin_container->add_theme_constant_override("margin_bottom", panel_style->get_margin(Side::SIDE_BOTTOM));
+ margin_container->add_theme_constant_override("margin_left", theme_cache.panel_style->get_margin(Side::SIDE_LEFT));
+ margin_container->add_theme_constant_override("margin_top", theme_cache.panel_style->get_margin(Side::SIDE_TOP));
+ margin_container->add_theme_constant_override("margin_right", theme_cache.panel_style->get_margin(Side::SIDE_RIGHT));
+ margin_container->add_theme_constant_override("margin_bottom", theme_cache.panel_style->get_margin(Side::SIDE_BOTTOM));
}
} break;
}
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index d3ad0762e4..c8c598bd50 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -129,6 +129,49 @@ class PopupMenu : public Popup {
ScrollContainer *scroll_container = nullptr;
Control *control = nullptr;
+ struct ThemeCache {
+ Ref<StyleBox> panel_style;
+ Ref<StyleBox> hover_style;
+
+ Ref<StyleBox> separator_style;
+ Ref<StyleBox> labeled_separator_left;
+ Ref<StyleBox> labeled_separator_right;
+
+ int v_separation = 0;
+ int h_separation = 0;
+ int indent = 0;
+ int item_start_padding = 0;
+ int item_end_padding = 0;
+
+ Ref<Texture2D> checked;
+ Ref<Texture2D> checked_disabled;
+ Ref<Texture2D> unchecked;
+ Ref<Texture2D> unchecked_disabled;
+ Ref<Texture2D> radio_checked;
+ Ref<Texture2D> radio_checked_disabled;
+ Ref<Texture2D> radio_unchecked;
+ Ref<Texture2D> radio_unchecked_disabled;
+
+ Ref<Texture2D> submenu;
+ Ref<Texture2D> submenu_mirrored;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Ref<Font> font_separator;
+ int font_separator_size = 0;
+
+ Color font_color;
+ Color font_hover_color;
+ Color font_disabled_color;
+ Color font_accelerator_color;
+ int font_outline_size = 0;
+ Color font_outline_color;
+
+ Color font_separator_color;
+ int font_separator_outline_size = 0;
+ Color font_separator_outline_color;
+ } theme_cache;
+
void _draw_items();
void _draw_background();
@@ -137,6 +180,8 @@ class PopupMenu : public Popup {
void _menu_changed();
protected:
+ virtual void _update_theme_item_cache() override;
+
virtual void add_child_notify(Node *p_child) override;
virtual void remove_child_notify(Node *p_child) override;
void _notification(int p_what);
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 63a2db4569..fe609dd834 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -33,18 +33,13 @@
#include "scene/resources/text_line.h"
Size2 ProgressBar::get_minimum_size() const {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
- Size2 minimum_size = bg->get_minimum_size();
- minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height);
- minimum_size.width = MAX(minimum_size.width, fg->get_minimum_size().width);
+ Size2 minimum_size = theme_cache.bg_style->get_minimum_size();
+ minimum_size.height = MAX(minimum_size.height, theme_cache.fg_style->get_minimum_size().height);
+ minimum_size.width = MAX(minimum_size.width, theme_cache.fg_style->get_minimum_size().width);
if (percent_visible) {
String txt = "100%";
- TextLine tl = TextLine(txt, font, font_size);
- minimum_size.height = MAX(minimum_size.height, bg->get_minimum_size().height + tl.get_size().y);
+ TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
+ minimum_size.height = MAX(minimum_size.height, theme_cache.bg_style->get_minimum_size().height + tl.get_size().y);
} else { // this is needed, else the progressbar will collapse
minimum_size.width = MAX(minimum_size.width, 1);
minimum_size.height = MAX(minimum_size.height, 1);
@@ -52,23 +47,30 @@ Size2 ProgressBar::get_minimum_size() const {
return minimum_size;
}
+void ProgressBar::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
+ theme_cache.fg_style = get_theme_stylebox(SNAME("fg"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+}
+
void ProgressBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
- Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
- Color font_color = get_theme_color(SNAME("font_color"));
-
- draw_style_box(bg, Rect2(Point2(), get_size()));
+ draw_style_box(theme_cache.bg_style, Rect2(Point2(), get_size()));
float r = get_as_ratio();
switch (mode) {
case FILL_BEGIN_TO_END:
case FILL_END_TO_BEGIN: {
- int mp = fg->get_minimum_size().width;
+ int mp = theme_cache.fg_style->get_minimum_size().width;
int p = round(r * (get_size().width - mp));
// We want FILL_BEGIN_TO_END to map to right to left when UI layout is RTL,
// and left to right otherwise. And likewise for FILL_END_TO_BEGIN.
@@ -76,23 +78,23 @@ void ProgressBar::_notification(int p_what) {
if (p > 0) {
if (right_to_left) {
int p_remaining = round((1.0 - r) * (get_size().width - mp));
- draw_style_box(fg, Rect2(Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(p_remaining, 0), Size2(p + theme_cache.fg_style->get_minimum_size().width, get_size().height)));
} else {
- draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(0, 0), Size2(p + theme_cache.fg_style->get_minimum_size().width, get_size().height)));
}
}
} break;
case FILL_TOP_TO_BOTTOM:
case FILL_BOTTOM_TO_TOP: {
- int mp = fg->get_minimum_size().height;
+ int mp = theme_cache.fg_style->get_minimum_size().height;
int p = round(r * (get_size().height - mp));
if (p > 0) {
if (mode == FILL_TOP_TO_BOTTOM) {
- draw_style_box(fg, Rect2(Point2(0, 0), Size2(get_size().width, p + fg->get_minimum_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(0, 0), Size2(get_size().width, p + theme_cache.fg_style->get_minimum_size().height)));
} else {
int p_remaining = round((1.0 - r) * (get_size().height - mp));
- draw_style_box(fg, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + fg->get_minimum_size().height)));
+ draw_style_box(theme_cache.fg_style, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + theme_cache.fg_style->get_minimum_size().height)));
}
}
} break;
@@ -102,14 +104,14 @@ void ProgressBar::_notification(int p_what) {
if (percent_visible) {
String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
- TextLine tl = TextLine(txt, font, font_size);
+ TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
- if (outline_size > 0 && font_outline_color.a > 0) {
- tl.draw_outline(get_canvas_item(), text_pos, outline_size, font_outline_color);
+
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ tl.draw_outline(get_canvas_item(), text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- tl.draw(get_canvas_item(), text_pos, font_color);
+
+ tl.draw(get_canvas_item(), text_pos, theme_cache.font_color);
}
} break;
}
diff --git a/scene/gui/progress_bar.h b/scene/gui/progress_bar.h
index 5ba21ad7d5..c79b901928 100644
--- a/scene/gui/progress_bar.h
+++ b/scene/gui/progress_bar.h
@@ -38,7 +38,20 @@ class ProgressBar : public Range {
bool percent_visible = true;
+ struct ThemeCache {
+ Ref<StyleBox> bg_style;
+ Ref<StyleBox> fg_style;
+
+ Ref<Font> font;
+ int font_size = 0;
+ Color font_color;
+ int font_outline_size = 0;
+ Color font_outline_color;
+ } theme_cache;
+
protected:
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index c9a903153d..99cad80cde 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -134,8 +134,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) co
}
Rect2 RichTextLabel::_get_text_rect() {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
+ return Rect2(theme_cache.normal_style->get_offset(), get_size() - theme_cache.normal_style->get_minimum_size());
}
RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item_from, RichTextLabel::Item *p_item_to, int p_position) {
@@ -287,8 +286,6 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
switch (it->type) {
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
- int hseparation = get_theme_constant(SNAME("table_h_separation"));
- int vseparation = get_theme_constant(SNAME("table_v_separation"));
int col_count = table->columns.size();
for (int i = 0; i < col_count; i++) {
@@ -309,12 +306,12 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
}
// Compute minimum width for each cell.
- const int available_width = p_width - hseparation * (col_count - 1);
+ const int available_width = p_width - theme_cache.table_h_separation * (col_count - 1);
// Compute available width and total ratio (for expanders).
int total_ratio = 0;
int remaining_width = available_width;
- table->total_width = hseparation;
+ table->total_width = theme_cache.table_h_separation;
for (int i = 0; i < col_count; i++) {
remaining_width -= table->columns[i].min_width;
@@ -332,7 +329,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) {
table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
}
- table->total_width += table->columns[i].width + hseparation;
+ table->total_width += table->columns[i].width + theme_cache.table_h_separation;
}
// Resize to max_width if needed and distribute the remaining space.
@@ -394,9 +391,9 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
frame->lines[i].offset.y = prev_h;
frame->lines[i].offset += offset;
- float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * get_theme_constant(SNAME("line_separation"));
+ float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) {
- h += get_theme_constant(SNAME("line_separation"));
+ h += theme_cache.line_separation;
}
if (frame->min_size_over.y > 0) {
h = MAX(h, frame->min_size_over.y);
@@ -405,15 +402,15 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
h = MIN(h, frame->max_size_over.y);
}
yofs += h;
- prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation;
}
yofs += frame->padding.size.y;
- offset.x += table->columns[column].width + hseparation + frame->padding.size.x;
+ offset.x += table->columns[column].width + theme_cache.table_h_separation + frame->padding.size.x;
row_height = MAX(yofs, row_height);
if (column == col_count - 1) {
offset.x = 0;
- row_height += vseparation;
+ row_height += theme_cache.table_v_separation;
table->total_height += row_height;
offset.y += row_height;
table->rows.push_back(row_height);
@@ -453,6 +450,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
case TextServer::AUTOWRAP_OFF:
break;
}
+ autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
// Clear cache.
l.text_buf->clear();
@@ -550,8 +548,6 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
- int hseparation = get_theme_constant(SNAME("table_h_separation"));
- int vseparation = get_theme_constant(SNAME("table_v_separation"));
int col_count = table->columns.size();
int t_char_count = 0;
// Set minimums to zero.
@@ -561,7 +557,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
table->columns[i].width = 0;
}
// Compute minimum width for each cell.
- const int available_width = p_width - hseparation * (col_count - 1);
+ const int available_width = p_width - theme_cache.table_h_separation * (col_count - 1);
int idx = 0;
for (Item *E : table->subitems) {
@@ -590,7 +586,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
// Compute available width and total ratio (for expanders).
int total_ratio = 0;
int remaining_width = available_width;
- table->total_width = hseparation;
+ table->total_width = theme_cache.table_h_separation;
for (int i = 0; i < col_count; i++) {
remaining_width -= table->columns[i].min_width;
@@ -608,7 +604,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) {
table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
}
- table->total_width += table->columns[i].width + hseparation;
+ table->total_width += table->columns[i].width + theme_cache.table_h_separation;
}
// Resize to max_width if needed and distribute the remaining space.
@@ -671,9 +667,9 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
frame->lines[i].offset.y = prev_h;
frame->lines[i].offset += offset;
- float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * get_theme_constant(SNAME("line_separation"));
+ float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) {
- h += get_theme_constant(SNAME("line_separation"));
+ h += theme_cache.line_separation;
}
if (frame->min_size_over.y > 0) {
h = MAX(h, frame->min_size_over.y);
@@ -682,16 +678,16 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
h = MIN(h, frame->max_size_over.y);
}
yofs += h;
- prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation;
}
yofs += frame->padding.size.y;
- offset.x += table->columns[column].width + hseparation + frame->padding.size.x;
+ offset.x += table->columns[column].width + theme_cache.table_h_separation + frame->padding.size.x;
row_height = MAX(yofs, row_height);
// Add row height after last column of the row or last cell of the table.
if (column == col_count - 1 || E->next() == nullptr) {
offset.x = 0;
- row_height += vseparation;
+ row_height += theme_cache.table_v_separation;
table->total_height += row_height;
offset.y += row_height;
table->rows.push_back(row_height);
@@ -722,7 +718,6 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
ERR_FAIL_COND_V(p_line < 0 || p_line >= (int)p_frame->lines.size(), 0);
Vector2 off;
- int line_spacing = get_theme_constant(SNAME("line_separation"));
Line &l = p_frame->lines[p_line];
MutexLock lock(l.text_buf->get_mutex());
@@ -774,8 +769,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}
if (!prefix.is_empty()) {
- Ref<Font> font = get_theme_font(SNAME("normal_font"));
- int font_size = get_theme_font_size(SNAME("normal_font_size"));
+ Ref<Font> font = theme_cache.normal_font;
+ int font_size = theme_cache.normal_font_size;
ItemFont *font_it = _find_font(l.from);
if (font_it) {
@@ -818,7 +813,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw text.
for (int line = 0; line < l.text_buf->get_line_count(); line++) {
if (line > 0) {
- off.y += line_spacing;
+ off.y += theme_cache.line_separation;
}
if (p_ofs.y + off.y >= ctrl_size.height) {
@@ -893,10 +888,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
- Color odd_row_bg = get_theme_color(SNAME("table_odd_row_bg"));
- Color even_row_bg = get_theme_color(SNAME("table_even_row_bg"));
- Color border = get_theme_color(SNAME("table_border"));
- int hseparation = get_theme_constant(SNAME("table_h_separation"));
+ Color odd_row_bg = theme_cache.table_odd_row_bg;
+ Color even_row_bg = theme_cache.table_even_row_bg;
+ Color border = theme_cache.table_border;
+ int hseparation = theme_cache.table_h_separation;
+
int col_count = table->columns.size();
int row_count = table->rows.size();
@@ -1092,8 +1088,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
_draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 0);
// Draw main text.
- Color selection_fg = get_theme_color(SNAME("font_selected_color"));
- Color selection_bg = get_theme_color(SNAME("selection_color"));
+ Color selection_fg = theme_cache.font_selected_color;
+ Color selection_bg = theme_cache.selection_color;
int sel_start = -1;
int sel_end = -1;
@@ -1135,7 +1131,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (ul_started) {
ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (_find_hint(it, nullptr) && underline_hint) {
@@ -1148,7 +1144,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (dot_ul_started) {
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
}
if (_find_strikethrough(it)) {
@@ -1161,7 +1157,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (st_started) {
st_started = false;
float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
}
@@ -1300,19 +1296,19 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (ul_started) {
ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (dot_ul_started) {
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
}
if (st_started) {
st_started = false;
float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
}
}
@@ -1322,19 +1318,19 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (ul_started) {
ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (dot_ul_started) {
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
}
if (st_started) {
st_started = false;
float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
- float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
+ float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
}
// Draw foreground color box
@@ -1370,7 +1366,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
while (ofs.y < size.height && from_line < to_line) {
MutexLock lock(main->lines[from_line].text_buf->get_mutex());
_find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char, false, p_meta);
- ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * theme_cache.line_separation;
if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) {
if (r_outside != nullptr) {
*r_outside = false;
@@ -1448,9 +1444,6 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) {
switch (it->type) {
case ITEM_TABLE: {
- int hseparation = get_theme_constant(SNAME("table_h_separation"));
- int vseparation = get_theme_constant(SNAME("table_v_separation"));
-
ItemTable *table = static_cast<ItemTable *>(it);
int idx = 0;
@@ -1468,7 +1461,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (rtl) {
coff.x = rect.size.width - table->columns[col].width - coff.x;
}
- Rect2 crect = Rect2(rect.position + coff - frame->padding.position, Size2(table->columns[col].width + hseparation, table->rows[row] + vseparation) + frame->padding.position + frame->padding.size);
+ Rect2 crect = Rect2(rect.position + coff - frame->padding.position, Size2(table->columns[col].width + theme_cache.table_h_separation, table->rows[row] + theme_cache.table_v_separation) + frame->padding.position + frame->padding.size);
if (col == col_count - 1) {
if (rtl) {
crect.size.x = crect.position.x + crect.size.x;
@@ -1507,7 +1500,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
}
Rect2 rect = Rect2(p_ofs + off - Vector2(0, TS->shaped_text_get_ascent(rid)) - p_frame->padding.position, TS->shaped_text_get_size(rid) + p_frame->padding.position + p_frame->padding.size);
if (p_table) {
- rect.size.y += get_theme_constant(SNAME("table_v_separation"));
+ rect.size.y += theme_cache.table_v_separation;
}
if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) {
@@ -1546,7 +1539,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
return table_offy;
}
- off.y += TS->shaped_text_get_descent(rid) + get_theme_constant(SNAME("line_separation"));
+ off.y += TS->shaped_text_get_descent(rid) + theme_cache.line_separation;
}
// Text line hit.
@@ -1561,8 +1554,8 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
int stop = text_rect_begin;
*r_click_item = _find_indentable(it);
while (*r_click_item) {
- Ref<Font> font = get_theme_font(SNAME("normal_font"));
- int font_size = get_theme_font_size(SNAME("normal_font_size"));
+ Ref<Font> font = theme_cache.normal_font;
+ int font_size = theme_cache.normal_font_size;
ItemFont *font_it = _find_font(*r_click_item);
if (font_it) {
if (font_it->font.is_valid()) {
@@ -1675,7 +1668,49 @@ int RichTextLabel::_find_first_line(int p_from, int p_to, int p_vofs) const {
}
_FORCE_INLINE_ float RichTextLabel::_calculate_line_vertical_offset(const RichTextLabel::Line &line) const {
- return line.get_height(get_theme_constant(SNAME("line_separation")));
+ return line.get_height(theme_cache.line_separation);
+}
+
+void RichTextLabel::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
+ theme_cache.focus_style = get_theme_stylebox(SNAME("focus"));
+ theme_cache.progress_bg_style = get_theme_stylebox(SNAME("bg"), SNAME("ProgressBar"));
+ theme_cache.progress_fg_style = get_theme_stylebox(SNAME("fg"), SNAME("ProgressBar"));
+
+ theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
+
+ theme_cache.normal_font = get_theme_font(SNAME("normal_font"));
+ theme_cache.normal_font_size = get_theme_font_size(SNAME("normal_font_size"));
+
+ theme_cache.default_color = get_theme_color(SNAME("default_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
+ theme_cache.shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
+ theme_cache.shadow_offset_x = get_theme_constant(SNAME("shadow_offset_x"));
+ theme_cache.shadow_offset_y = get_theme_constant(SNAME("shadow_offset_y"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+ theme_cache.outline_color = get_theme_color(SNAME("outline_color"));
+
+ theme_cache.bold_font = get_theme_font(SNAME("bold_font"));
+ theme_cache.bold_font_size = get_theme_font_size(SNAME("bold_font_size"));
+ theme_cache.bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
+ theme_cache.bold_italics_font_size = get_theme_font_size(SNAME("bold_italics_font_size"));
+ theme_cache.italics_font = get_theme_font(SNAME("italics_font"));
+ theme_cache.italics_font_size = get_theme_font_size(SNAME("italics_font_size"));
+ theme_cache.mono_font = get_theme_font(SNAME("mono_font"));
+ theme_cache.mono_font_size = get_theme_font_size(SNAME("mono_font_size"));
+
+ theme_cache.table_h_separation = get_theme_constant(SNAME("table_h_separation"));
+ theme_cache.table_v_separation = get_theme_constant(SNAME("table_v_separation"));
+ theme_cache.table_odd_row_bg = get_theme_color(SNAME("table_odd_row_bg"));
+ theme_cache.table_even_row_bg = get_theme_color(SNAME("table_even_row_bg"));
+ theme_cache.table_border = get_theme_color(SNAME("table_border"));
+
+ theme_cache.base_scale = get_theme_default_base_scale();
}
void RichTextLabel::_notification(int p_what) {
@@ -1731,11 +1766,11 @@ void RichTextLabel::_notification(int p_what) {
RID ci = get_canvas_item();
Size2 size = get_size();
- draw_style_box(get_theme_stylebox(SNAME("normal")), Rect2(Point2(), size));
+ draw_style_box(theme_cache.normal_style, Rect2(Point2(), size));
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- draw_style_box(get_theme_stylebox(SNAME("focus")), Rect2(Point2(), size));
+ draw_style_box(theme_cache.focus_style, Rect2(Point2(), size));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
@@ -1745,24 +1780,20 @@ void RichTextLabel::_notification(int p_what) {
} else {
// Draw loading progress bar.
if ((progress_delay > 0) && (OS::get_singleton()->get_ticks_msec() - loading_started >= (uint64_t)progress_delay)) {
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"), SNAME("ProgressBar"));
- Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"), SNAME("ProgressBar"));
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
-
- Vector2 p_size = Vector2(size.width - (style->get_offset().x + vscroll->get_combined_minimum_size().width) * 2, vscroll->get_combined_minimum_size().width);
- Vector2 p_pos = Vector2(style->get_offset().x, size.height - style->get_offset().y - vscroll->get_combined_minimum_size().width);
+ Vector2 p_size = Vector2(size.width - (theme_cache.normal_style->get_offset().x + vscroll->get_combined_minimum_size().width) * 2, vscroll->get_combined_minimum_size().width);
+ Vector2 p_pos = Vector2(theme_cache.normal_style->get_offset().x, size.height - theme_cache.normal_style->get_offset().y - vscroll->get_combined_minimum_size().width);
- draw_style_box(bg, Rect2(p_pos, p_size));
+ draw_style_box(theme_cache.progress_bg_style, Rect2(p_pos, p_size));
bool right_to_left = is_layout_rtl();
double r = loaded.load();
- int mp = fg->get_minimum_size().width;
+ int mp = theme_cache.progress_fg_style->get_minimum_size().width;
int p = round(r * (p_size.width - mp));
if (right_to_left) {
int p_remaining = round((1.0 - r) * (p_size.width - mp));
- draw_style_box(fg, Rect2(p_pos + Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, p_size.height)));
+ draw_style_box(theme_cache.progress_fg_style, Rect2(p_pos + Point2(p_remaining, 0), Size2(p + theme_cache.progress_fg_style->get_minimum_size().width, p_size.height)));
} else {
- draw_style_box(fg, Rect2(p_pos, Size2(p + fg->get_minimum_size().width, p_size.height)));
+ draw_style_box(theme_cache.progress_fg_style, Rect2(p_pos, Size2(p + theme_cache.progress_fg_style->get_minimum_size().width, p_size.height)));
}
}
}
@@ -1775,13 +1806,7 @@ void RichTextLabel::_notification(int p_what) {
int to_line = main->first_invalid_line.load();
int from_line = _find_first_line(0, to_line, vofs);
- Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
- Color base_color = get_theme_color(SNAME("default_color"));
- Color outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
- Color font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
- int shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
- Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
+ Point2 shadow_ofs(theme_cache.shadow_offset_x, theme_cache.shadow_offset_y);
visible_paragraph_count = 0;
visible_line_count = 0;
@@ -1793,8 +1818,8 @@ void RichTextLabel::_notification(int p_what) {
MutexLock lock(main->lines[from_line].text_buf->get_mutex());
visible_paragraph_count++;
- visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, shadow_outline_size, shadow_ofs, processed_glyphs);
- ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, theme_cache.default_color, theme_cache.outline_size, theme_cache.font_outline_color, theme_cache.font_shadow_color, theme_cache.shadow_outline_size, shadow_ofs, processed_glyphs);
+ ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * theme_cache.line_separation;
from_line++;
}
} break;
@@ -2002,11 +2027,11 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
handled = true;
}
if (k->is_action("ui_up") && vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() - get_theme_font(SNAME("normal_font"))->get_height(get_theme_font_size(SNAME("normal_font_size"))));
+ vscroll->set_value(vscroll->get_value() - theme_cache.normal_font->get_height(theme_cache.normal_font_size));
handled = true;
}
if (k->is_action("ui_down") && vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() + get_theme_font(SNAME("normal_font"))->get_height(get_theme_font_size(SNAME("normal_font_size"))));
+ vscroll->set_value(vscroll->get_value() + theme_cache.normal_font->get_height(theme_cache.normal_font_size));
handled = true;
}
if (k->is_action("ui_home") && vscroll->is_visible_in_tree()) {
@@ -2586,14 +2611,12 @@ bool RichTextLabel::_validate_line_caches() {
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
- Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
- int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
int ctrl_height = get_size().height;
// Update fonts.
if (main->first_invalid_font_line.load() != (int)main->lines.size()) {
for (int i = main->first_invalid_font_line.load(); i < (int)main->lines.size(); i++) {
- _update_line_font(main, i, base_font, base_font_size);
+ _update_line_font(main, i, theme_cache.normal_font, theme_cache.normal_font_size);
}
main->first_resized_line.store(main->first_invalid_font_line.load());
main->first_invalid_font_line.store(main->lines.size());
@@ -2608,7 +2631,7 @@ bool RichTextLabel::_validate_line_caches() {
float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
- total_height = _resize_line(main, i, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
+ total_height = _resize_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height);
updating_scroll = true;
bool exceeds = total_height > ctrl_height && scroll_active;
@@ -2628,7 +2651,7 @@ bool RichTextLabel::_validate_line_caches() {
total_height = 0;
for (int j = 0; j <= i; j++) {
- total_height = _resize_line(main, j, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
+ total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height);
main->first_resized_line.store(j);
}
@@ -2675,15 +2698,13 @@ void RichTextLabel::_process_line_caches() {
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
- int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
- Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int ctrl_height = get_size().height;
int fi = main->first_invalid_line.load();
int total_chars = (fi == 0) ? 0 : (main->lines[fi].char_offset + main->lines[fi].char_count);
float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
- total_height = _shape_line(main, i, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
+ total_height = _shape_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
updating_scroll = true;
bool exceeds = total_height > ctrl_height && scroll_active;
if (exceeds != scroll_visible) {
@@ -2704,7 +2725,7 @@ void RichTextLabel::_process_line_caches() {
// since scroll was added or removed we need to resize all lines
total_height = 0;
for (int j = 0; j <= i; j++) {
- total_height = _resize_line(main, j, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
+ total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height);
main->first_invalid_line.store(j);
main->first_resized_line.store(j);
@@ -2997,38 +3018,33 @@ void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) {
}
void RichTextLabel::push_normal() {
- Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
- ERR_FAIL_COND(normal_font.is_null());
+ ERR_FAIL_COND(theme_cache.normal_font.is_null());
- push_font(normal_font, get_theme_font_size(SNAME("normal_font_size")));
+ push_font(theme_cache.normal_font, theme_cache.normal_font_size);
}
void RichTextLabel::push_bold() {
- Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
- ERR_FAIL_COND(bold_font.is_null());
+ ERR_FAIL_COND(theme_cache.bold_font.is_null());
- push_font(bold_font, get_theme_font_size(SNAME("bold_font_size")));
+ push_font(theme_cache.bold_font, theme_cache.bold_font_size);
}
void RichTextLabel::push_bold_italics() {
- Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
- ERR_FAIL_COND(bold_italics_font.is_null());
+ ERR_FAIL_COND(theme_cache.bold_italics_font.is_null());
- push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
+ push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
}
void RichTextLabel::push_italics() {
- Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
- ERR_FAIL_COND(italics_font.is_null());
+ ERR_FAIL_COND(theme_cache.italics_font.is_null());
- push_font(italics_font, get_theme_font_size(SNAME("italics_font_size")));
+ push_font(theme_cache.italics_font, theme_cache.italics_font_size);
}
void RichTextLabel::push_mono() {
- Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
- ERR_FAIL_COND(mono_font.is_null());
+ ERR_FAIL_COND(theme_cache.mono_font.is_null());
- push_font(mono_font, get_theme_font_size(SNAME("mono_font_size")));
+ push_font(theme_cache.mono_font, theme_cache.mono_font_size);
}
void RichTextLabel::push_font_size(int p_font_size) {
@@ -3475,13 +3491,6 @@ void RichTextLabel::append_text(const String &p_bbcode) {
int pos = 0;
List<String> tag_stack;
- Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
- Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
- Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
- Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
- Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
-
- Color base_color = get_theme_color(SNAME("default_color"));
int indent_level = 0;
@@ -3626,9 +3635,9 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use bold font
in_bold = true;
if (in_italics) {
- push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
+ push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
} else {
- push_font(bold_font, get_theme_font_size(SNAME("bold_font_size")));
+ push_font(theme_cache.bold_font, theme_cache.bold_font_size);
}
pos = brk_end + 1;
tag_stack.push_front(tag);
@@ -3636,15 +3645,15 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use italics font
in_italics = true;
if (in_bold) {
- push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
+ push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
} else {
- push_font(italics_font, get_theme_font_size(SNAME("italics_font_size")));
+ push_font(theme_cache.italics_font, theme_cache.italics_font_size);
}
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
//use monospace font
- push_font(mono_font, get_theme_font_size(SNAME("mono_font_size")));
+ push_font(theme_cache.mono_font, theme_cache.mono_font_size);
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag.begins_with("table=")) {
@@ -3929,11 +3938,11 @@ void RichTextLabel::append_text(const String &p_bbcode) {
tag_stack.push_front("hint");
} else if (tag.begins_with("dropcap")) {
Vector<String> subtag = tag.substr(5, tag.length()).split(" ");
- int fs = get_theme_font_size(SNAME("normal_font_size")) * 3;
- Ref<Font> f = get_theme_font(SNAME("normal_font"));
- Color color = get_theme_color(SNAME("default_color"));
- Color outline_color = get_theme_color(SNAME("outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ int fs = theme_cache.normal_font_size * 3;
+ Ref<Font> f = theme_cache.normal_font;
+ Color color = theme_cache.default_color;
+ Color outline_color = theme_cache.outline_color;
+ int outline_size = theme_cache.outline_size;
Rect2 dropcap_margins = Rect2();
for (int i = 0; i < subtag.size(); i++) {
@@ -4051,14 +4060,14 @@ void RichTextLabel::append_text(const String &p_bbcode) {
tag_stack.push_front(bbcode_name);
} else if (tag.begins_with("color=")) {
String color_str = tag.substr(6, tag.length());
- Color color = Color::from_string(color_str, base_color);
+ Color color = Color::from_string(color_str, theme_cache.default_color);
push_color(color);
pos = brk_end + 1;
tag_stack.push_front("color");
} else if (tag.begins_with("outline_color=")) {
String color_str = tag.substr(14, tag.length());
- Color color = Color::from_string(color_str, base_color);
+ Color color = Color::from_string(color_str, theme_cache.default_color);
push_outline_color(color);
pos = brk_end + 1;
tag_stack.push_front("outline_color");
@@ -4073,7 +4082,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
String fnt_ftr = tag.substr(18, tag.length());
Vector<String> subtag = fnt_ftr.split(",");
if (subtag.size() > 0) {
- Ref<Font> font = normal_font;
+ Ref<Font> font = theme_cache.normal_font;
int font_size = 0;
ItemFont *font_it = _find_font(current);
if (font_it) {
@@ -4285,7 +4294,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
} else if (tag.begins_with("bgcolor=")) {
String color_str = tag.substr(8, tag.length());
- Color color = Color::from_string(color_str, base_color);
+ Color color = Color::from_string(color_str, theme_cache.default_color);
push_bgcolor(color);
pos = brk_end + 1;
@@ -4293,7 +4302,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
} else if (tag.begins_with("fgcolor=")) {
String color_str = tag.substr(8, tag.length());
- Color color = Color::from_string(color_str, base_color);
+ Color color = Color::from_string(color_str, theme_cache.default_color);
push_fgcolor(color);
pos = brk_end + 1;
@@ -4372,7 +4381,7 @@ void RichTextLabel::scroll_to_line(int p_line) {
if ((line_count <= p_line) && (line_count + main->lines[i].text_buf->get_line_count() >= p_line)) {
float line_offset = 0.f;
for (int j = 0; j < p_line - line_count; j++) {
- line_offset += main->lines[i].text_buf->get_line_size(j).y + get_theme_constant(SNAME("line_separation"));
+ line_offset += main->lines[i].text_buf->get_line_size(j).y + theme_cache.line_separation;
}
vscroll->set_value(main->lines[i].offset.y + line_offset);
return;
@@ -4390,7 +4399,7 @@ float RichTextLabel::get_line_offset(int p_line) {
if ((line_count <= p_line) && (p_line <= line_count + main->lines[i].text_buf->get_line_count())) {
float line_offset = 0.f;
for (int j = 0; j < p_line - line_count; j++) {
- line_offset += main->lines[i].text_buf->get_line_size(j).y + get_theme_constant(SNAME("line_separation"));
+ line_offset += main->lines[i].text_buf->get_line_size(j).y + theme_cache.line_separation;
}
return main->lines[i].offset.y + line_offset;
}
@@ -4944,10 +4953,10 @@ void RichTextLabel::set_visible_ratio(float p_ratio) {
if (visible_ratio != p_ratio) {
_stop_thread();
- if (visible_ratio >= 1.0) {
+ if (p_ratio >= 1.0) {
visible_characters = -1;
visible_ratio = 1.0;
- } else if (visible_ratio < 0.0) {
+ } else if (p_ratio < 0.0) {
visible_characters = 0;
visible_ratio = 0.0;
} else {
@@ -4996,7 +5005,7 @@ int RichTextLabel::get_content_height() const {
int to_line = main->first_invalid_line.load();
if (to_line) {
MutexLock lock(main->lines[to_line - 1].text_buf->get_mutex());
- total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
+ total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * theme_cache.line_separation;
}
return total_height;
}
@@ -5366,8 +5375,7 @@ void RichTextLabel::set_fixed_size_to_width(int p_width) {
}
Size2 RichTextLabel::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
- Size2 size = style->get_minimum_size();
+ Size2 size = theme_cache.normal_style->get_minimum_size();
if (fixed_width != -1) {
size.x += fixed_width;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 79f9c62539..8bc28a9ecf 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -83,6 +83,7 @@ public:
};
protected:
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
@@ -512,6 +513,46 @@ private:
bool fit_content_height = false;
+ struct ThemeCache {
+ Ref<StyleBox> normal_style;
+ Ref<StyleBox> focus_style;
+ Ref<StyleBox> progress_bg_style;
+ Ref<StyleBox> progress_fg_style;
+
+ int line_separation;
+
+ Ref<Font> normal_font;
+ int normal_font_size;
+
+ Color default_color;
+ Color font_selected_color;
+ Color selection_color;
+ Color font_outline_color;
+ Color font_shadow_color;
+ int shadow_outline_size;
+ int shadow_offset_x;
+ int shadow_offset_y;
+ int outline_size;
+ Color outline_color;
+
+ Ref<Font> bold_font;
+ int bold_font_size;
+ Ref<Font> bold_italics_font;
+ int bold_italics_font_size;
+ Ref<Font> italics_font;
+ int italics_font_size;
+ Ref<Font> mono_font;
+ int mono_font_size;
+
+ int table_h_separation;
+ int table_v_separation;
+ Color table_odd_row_bg;
+ Color table_even_row_bg;
+ Color table_border;
+
+ float base_scale = 1.0;
+ } theme_cache;
+
public:
String get_parsed_text() const;
void add_text(const String &p_text);
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 2555318f39..374ce6feea 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -70,8 +70,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
if (b->is_pressed()) {
double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x;
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
+ Ref<Texture2D> incr = theme_cache.increment_icon;
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -146,7 +146,7 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
if (drag.active) {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
ofs -= decr_size;
@@ -156,8 +156,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
set_as_ratio(drag.value_at_click + diff);
} else {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
+ Ref<Texture2D> incr = theme_cache.increment_icon;
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -217,6 +217,24 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
}
}
+void ScrollBar::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.scroll_style = get_theme_stylebox(SNAME("scroll"));
+ theme_cache.scroll_focus_style = get_theme_stylebox(SNAME("scroll_focus"));
+ theme_cache.scroll_offset_style = get_theme_stylebox(SNAME("hscroll"));
+ theme_cache.grabber_style = get_theme_stylebox(SNAME("grabber"));
+ theme_cache.grabber_hl_style = get_theme_stylebox(SNAME("grabber_highlight"));
+ theme_cache.grabber_pressed_style = get_theme_stylebox(SNAME("grabber_pressed"));
+
+ theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
+ theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
+ theme_cache.increment_pressed_icon = get_theme_icon(SNAME("increment_pressed"));
+ theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
+ theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
+ theme_cache.decrement_pressed_icon = get_theme_icon(SNAME("decrement_pressed"));
+}
+
void ScrollBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
@@ -225,30 +243,30 @@ void ScrollBar::_notification(int p_what) {
Ref<Texture2D> decr, incr;
if (decr_active) {
- decr = get_theme_icon(SNAME("decrement_pressed"));
+ decr = theme_cache.decrement_pressed_icon;
} else if (highlight == HIGHLIGHT_DECR) {
- decr = get_theme_icon(SNAME("decrement_highlight"));
+ decr = theme_cache.decrement_hl_icon;
} else {
- decr = get_theme_icon(SNAME("decrement"));
+ decr = theme_cache.decrement_icon;
}
if (incr_active) {
- incr = get_theme_icon(SNAME("increment_pressed"));
+ incr = theme_cache.increment_pressed_icon;
} else if (highlight == HIGHLIGHT_INCR) {
- incr = get_theme_icon(SNAME("increment_highlight"));
+ incr = theme_cache.increment_hl_icon;
} else {
- incr = get_theme_icon(SNAME("increment"));
+ incr = theme_cache.increment_icon;
}
- Ref<StyleBox> bg = has_focus() ? get_theme_stylebox(SNAME("scroll_focus")) : get_theme_stylebox(SNAME("scroll"));
+ Ref<StyleBox> bg = has_focus() ? theme_cache.scroll_focus_style : theme_cache.scroll_style;
Ref<StyleBox> grabber;
if (drag.active) {
- grabber = get_theme_stylebox(SNAME("grabber_pressed"));
+ grabber = theme_cache.grabber_pressed_style;
} else if (highlight == HIGHLIGHT_RANGE) {
- grabber = get_theme_stylebox(SNAME("grabber_highlight"));
+ grabber = theme_cache.grabber_hl_style;
} else {
- grabber = get_theme_stylebox(SNAME("grabber"));
+ grabber = theme_cache.grabber_style;
}
Point2 ofs;
@@ -414,7 +432,7 @@ void ScrollBar::_notification(int p_what) {
}
double ScrollBar::get_grabber_min_size() const {
- Ref<StyleBox> grabber = get_theme_stylebox(SNAME("grabber"));
+ Ref<StyleBox> grabber = theme_cache.grabber_style;
Size2 gminsize = grabber->get_minimum_size() + grabber->get_center_size();
return (orientation == VERTICAL) ? gminsize.height : gminsize.width;
}
@@ -435,17 +453,17 @@ double ScrollBar::get_area_size() const {
switch (orientation) {
case VERTICAL: {
double area = get_size().height;
- area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().height;
- area -= get_theme_icon(SNAME("increment"))->get_height();
- area -= get_theme_icon(SNAME("decrement"))->get_height();
+ area -= theme_cache.scroll_style->get_minimum_size().height;
+ area -= theme_cache.increment_icon->get_height();
+ area -= theme_cache.decrement_icon->get_height();
area -= get_grabber_min_size();
return area;
} break;
case HORIZONTAL: {
double area = get_size().width;
- area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().width;
- area -= get_theme_icon(SNAME("increment"))->get_width();
- area -= get_theme_icon(SNAME("decrement"))->get_width();
+ area -= theme_cache.scroll_style->get_minimum_size().width;
+ area -= theme_cache.increment_icon->get_width();
+ area -= theme_cache.decrement_icon->get_width();
area -= get_grabber_min_size();
return area;
} break;
@@ -459,13 +477,13 @@ double ScrollBar::get_area_offset() const {
double ofs = 0.0;
if (orientation == VERTICAL) {
- ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_TOP);
- ofs += get_theme_icon(SNAME("decrement"))->get_height();
+ ofs += theme_cache.scroll_offset_style->get_margin(SIDE_TOP);
+ ofs += theme_cache.decrement_icon->get_height();
}
if (orientation == HORIZONTAL) {
- ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_LEFT);
- ofs += get_theme_icon(SNAME("decrement"))->get_width();
+ ofs += theme_cache.scroll_offset_style->get_margin(SIDE_LEFT);
+ ofs += theme_cache.decrement_icon->get_width();
}
return ofs;
@@ -476,9 +494,9 @@ double ScrollBar::get_grabber_offset() const {
}
Size2 ScrollBar::get_minimum_size() const {
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- Ref<StyleBox> bg = get_theme_stylebox(SNAME("scroll"));
+ Ref<Texture2D> incr = theme_cache.increment_icon;
+ Ref<Texture2D> decr = theme_cache.decrement_icon;
+ Ref<StyleBox> bg = theme_cache.scroll_style;
Size2 minsize;
if (orientation == VERTICAL) {
diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h
index 1823f86a67..13ca62d7ff 100644
--- a/scene/gui/scroll_bar.h
+++ b/scene/gui/scroll_bar.h
@@ -86,14 +86,31 @@ class ScrollBar : public Range {
double target_scroll = 0.0;
bool smooth_scroll_enabled = false;
+ struct ThemeCache {
+ Ref<StyleBox> scroll_style;
+ Ref<StyleBox> scroll_focus_style;
+ Ref<StyleBox> scroll_offset_style;
+ Ref<StyleBox> grabber_style;
+ Ref<StyleBox> grabber_hl_style;
+ Ref<StyleBox> grabber_pressed_style;
+
+ Ref<Texture2D> increment_icon;
+ Ref<Texture2D> increment_hl_icon;
+ Ref<Texture2D> increment_pressed_icon;
+ Ref<Texture2D> decrement_icon;
+ Ref<Texture2D> decrement_hl_icon;
+ Ref<Texture2D> decrement_pressed_icon;
+ } theme_cache;
+
void _drag_node_exit();
void _drag_node_input(const Ref<InputEvent> &p_input);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
protected:
- void _notification(int p_what);
+ virtual void _update_theme_item_cache() override;
+ void _notification(int p_what);
static void _bind_methods();
public:
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index cd595446bb..f68cebd657 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -35,7 +35,6 @@
#include "scene/main/window.h"
Size2 ScrollContainer::get_minimum_size() const {
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
Size2 min_size;
// Calculated in this function, as it needs to traverse all child controls once to calculate;
@@ -77,10 +76,16 @@ Size2 ScrollContainer::get_minimum_size() const {
min_size.x += v_scroll->get_minimum_size().x;
}
- min_size += sb->get_minimum_size();
+ min_size += theme_cache.bg_style->get_minimum_size();
return min_size;
}
+void ScrollContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
+}
+
void ScrollContainer::_cancel_drag() {
set_physics_process_internal(false);
drag_touching_deaccel = false;
@@ -271,9 +276,8 @@ void ScrollContainer::_reposition_children() {
Size2 size = get_size();
Point2 ofs;
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
- size -= sb->get_minimum_size();
- ofs += sb->get_offset();
+ size -= theme_cache.bg_style->get_minimum_size();
+ ofs += theme_cache.bg_style->get_offset();
bool rtl = is_layout_rtl();
if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) { //scrolls may have been moved out for reasons
@@ -337,8 +341,7 @@ void ScrollContainer::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
- draw_style_box(sb, Rect2(Vector2(), get_size()));
+ draw_style_box(theme_cache.bg_style, Rect2(Vector2(), get_size()));
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -413,8 +416,7 @@ void ScrollContainer::_notification(int p_what) {
void ScrollContainer::update_scrollbars() {
Size2 size = get_size();
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
- size -= sb->get_minimum_size();
+ size -= theme_cache.bg_style->get_minimum_size();
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index bfa74cfd0f..fa1f09ab3f 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -69,9 +69,14 @@ private:
int deadzone = 0;
bool follow_focus = false;
+ struct ThemeCache {
+ Ref<StyleBox> bg_style;
+ } theme_cache;
+
void _cancel_drag();
protected:
+ virtual void _update_theme_item_cache() override;
Size2 get_minimum_size() const override;
void _gui_focus_changed(Control *p_control);
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index e3400d9c8f..8177c1e469 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -33,24 +33,30 @@
Size2 Separator::get_minimum_size() const {
Size2 ms(3, 3);
if (orientation == VERTICAL) {
- ms.x = get_theme_constant(SNAME("separation"));
+ ms.x = theme_cache.separation;
} else { // HORIZONTAL
- ms.y = get_theme_constant(SNAME("separation"));
+ ms.y = theme_cache.separation;
}
return ms;
}
+void Separator::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.separation = get_theme_constant(SNAME("separation"));
+ theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
+}
+
void Separator::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
Size2i size = get_size();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("separator"));
- Size2i ssize = style->get_minimum_size() + style->get_center_size();
+ Size2i ssize = theme_cache.separator_style->get_minimum_size() + theme_cache.separator_style->get_center_size();
if (orientation == VERTICAL) {
- style->draw(get_canvas_item(), Rect2((size.x - ssize.x) / 2, 0, ssize.x, size.y));
+ theme_cache.separator_style->draw(get_canvas_item(), Rect2((size.x - ssize.x) / 2, 0, ssize.x, size.y));
} else {
- style->draw(get_canvas_item(), Rect2(0, (size.y - ssize.y) / 2, size.x, ssize.y));
+ theme_cache.separator_style->draw(get_canvas_item(), Rect2(0, (size.y - ssize.y) / 2, size.x, ssize.y));
}
} break;
}
diff --git a/scene/gui/separator.h b/scene/gui/separator.h
index e6578a4d04..44e18a3f00 100644
--- a/scene/gui/separator.h
+++ b/scene/gui/separator.h
@@ -35,8 +35,16 @@
class Separator : public Control {
GDCLASS(Separator, Control);
+ struct ThemeCache {
+ int separation = 0;
+ Ref<StyleBox> separator_style;
+ } theme_cache;
+
protected:
Orientation orientation = Orientation::HORIZONTAL;
+
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
public:
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 7bf61e3541..ff3adfb9ac 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -33,11 +33,8 @@
#include "core/os/keyboard.h"
Size2 Slider::get_minimum_size() const {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
- Size2i ss = style->get_minimum_size() + style->get_center_size();
-
- Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
- Size2i rs = grabber->get_size();
+ Size2i ss = theme_cache.slider_style->get_minimum_size() + theme_cache.slider_style->get_center_size();
+ Size2i rs = theme_cache.grabber_icon->get_size();
if (orientation == HORIZONTAL) {
return Size2i(ss.width, MAX(ss.height, rs.height));
@@ -58,7 +55,13 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
- Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
+ Ref<Texture2D> grabber;
+ if (mouse_inside || has_focus()) {
+ grabber = theme_cache.grabber_hl_icon;
+ } else {
+ grabber = theme_cache.grabber_icon;
+ }
+
grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x;
double grab_width = (double)grabber->get_size().width;
@@ -95,7 +98,7 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
if (grab.active) {
Size2i size = get_size();
- Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
+ Ref<Texture2D> grabber = theme_cache.grabber_icon;
double motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
if (orientation == VERTICAL) {
motion = -motion;
@@ -145,6 +148,19 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
}
}
+void Slider::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.slider_style = get_theme_stylebox(SNAME("slider"));
+ theme_cache.grabber_area_style = get_theme_stylebox(SNAME("grabber_area"));
+ theme_cache.grabber_area_hl_style = get_theme_stylebox(SNAME("grabber_area_highlight"));
+
+ theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
+ theme_cache.grabber_hl_icon = get_theme_icon(SNAME("grabber_highlight"));
+ theme_cache.grabber_disabled_icon = get_theme_icon(SNAME("grabber_disabled"));
+ theme_cache.tick_icon = get_theme_icon(SNAME("tick"));
+}
+
void Slider::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
@@ -171,13 +187,30 @@ void Slider::_notification(int p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
Size2i size = get_size();
- Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
- bool highlighted = mouse_inside || has_focus();
- Ref<StyleBox> grabber_area = get_theme_stylebox(highlighted ? "grabber_area_highlight" : "grabber_area");
- Ref<Texture2D> grabber = get_theme_icon(editable ? (highlighted ? "grabber_highlight" : "grabber") : "grabber_disabled");
- Ref<Texture2D> tick = get_theme_icon(SNAME("tick"));
double ratio = Math::is_nan(get_as_ratio()) ? 0 : get_as_ratio();
+ Ref<StyleBox> style = theme_cache.slider_style;
+ Ref<Texture2D> tick = theme_cache.tick_icon;
+
+ bool highlighted = mouse_inside || has_focus();
+ Ref<Texture2D> grabber;
+ if (editable) {
+ if (highlighted) {
+ grabber = theme_cache.grabber_hl_icon;
+ } else {
+ grabber = theme_cache.grabber_icon;
+ }
+ } else {
+ grabber = theme_cache.grabber_disabled_icon;
+ }
+
+ Ref<StyleBox> grabber_area;
+ if (highlighted) {
+ grabber_area = theme_cache.grabber_area_hl_style;
+ } else {
+ grabber_area = theme_cache.grabber_area_style;
+ }
+
if (orientation == VERTICAL) {
int widget_width = style->get_minimum_size().width + style->get_center_size().width;
double areasize = size.height - grabber->get_size().height;
diff --git a/scene/gui/slider.h b/scene/gui/slider.h
index 5abaee27aa..51adb354fb 100644
--- a/scene/gui/slider.h
+++ b/scene/gui/slider.h
@@ -49,11 +49,24 @@ class Slider : public Range {
bool editable = true;
bool scrollable = true;
+ struct ThemeCache {
+ Ref<StyleBox> slider_style;
+ Ref<StyleBox> grabber_area_style;
+ Ref<StyleBox> grabber_area_hl_style;
+
+ Ref<Texture2D> grabber_icon;
+ Ref<Texture2D> grabber_hl_icon;
+ Ref<Texture2D> grabber_disabled_icon;
+ Ref<Texture2D> tick_icon;
+ } theme_cache;
+
protected:
+ bool ticks_on_borders = false;
+
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
- bool ticks_on_borders = false;
public:
virtual Size2 get_minimum_size() const override;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 900249ddd9..fe14049d93 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -210,25 +210,29 @@ inline void SpinBox::_adjust_width_for_icon(const Ref<Texture2D> &icon) {
}
}
+void SpinBox::_update_theme_item_cache() {
+ Range::_update_theme_item_cache();
+
+ theme_cache.updown_icon = get_theme_icon(SNAME("updown"));
+}
+
void SpinBox::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- Ref<Texture2D> updown = get_theme_icon(SNAME("updown"));
-
- _adjust_width_for_icon(updown);
+ _adjust_width_for_icon(theme_cache.updown_icon);
RID ci = get_canvas_item();
Size2i size = get_size();
if (is_layout_rtl()) {
- updown->draw(ci, Point2i(0, (size.height - updown->get_height()) / 2));
+ theme_cache.updown_icon->draw(ci, Point2i(0, (size.height - theme_cache.updown_icon->get_height()) / 2));
} else {
- updown->draw(ci, Point2i(size.width - updown->get_width(), (size.height - updown->get_height()) / 2));
+ theme_cache.updown_icon->draw(ci, Point2i(size.width - theme_cache.updown_icon->get_width(), (size.height - theme_cache.updown_icon->get_height()) / 2));
}
} break;
case NOTIFICATION_ENTER_TREE: {
- _adjust_width_for_icon(get_theme_icon(SNAME("updown")));
+ _adjust_width_for_icon(theme_cache.updown_icon);
_value_changed(0);
} break;
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 3fcb85ac99..c2f2ac3f5a 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -69,9 +69,14 @@ class SpinBox : public Range {
inline void _adjust_width_for_icon(const Ref<Texture2D> &icon);
+ struct ThemeCache {
+ Ref<Texture2D> updown_icon;
+ } theme_cache;
+
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index b7e1f2a914..04bd5b3282 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -55,6 +55,18 @@ Control *SplitContainer::_getch(int p_idx) const {
return nullptr;
}
+Ref<Texture2D> SplitContainer::_get_grabber_icon() const {
+ if (is_fixed) {
+ return theme_cache.grabber_icon;
+ } else {
+ if (vertical) {
+ return theme_cache.grabber_icon_v;
+ } else {
+ return theme_cache.grabber_icon_h;
+ }
+ }
+}
+
void SplitContainer::_resort() {
int axis = vertical ? 1 : 0;
@@ -76,9 +88,8 @@ void SplitContainer::_resort() {
bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
// Determine the separation between items
- Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
- int sep = get_theme_constant(SNAME("separation"));
- sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
+ Ref<Texture2D> g = _get_grabber_icon();
+ int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0;
// Compute the minimum size
Size2 ms_first = first->get_combined_minimum_size();
@@ -128,12 +139,9 @@ void SplitContainer::_resort() {
}
Size2 SplitContainer::get_minimum_size() const {
- /* Calculate MINIMUM SIZE */
-
Size2i minimum;
- Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
- int sep = get_theme_constant(SNAME("separation"));
- sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
+ Ref<Texture2D> g = _get_grabber_icon();
+ int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0;
for (int i = 0; i < 2; i++) {
if (!_getch(i)) {
@@ -162,6 +170,16 @@ Size2 SplitContainer::get_minimum_size() const {
return minimum;
}
+void SplitContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.separation = get_theme_constant(SNAME("separation"));
+ theme_cache.autohide = get_theme_constant(SNAME("autohide"));
+ theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
+ theme_cache.grabber_icon_h = get_theme_icon(SNAME("h_grabber"));
+ theme_cache.grabber_icon_v = get_theme_icon(SNAME("v_grabber"));
+}
+
void SplitContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
@@ -175,7 +193,7 @@ void SplitContainer::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
mouse_inside = false;
- if (get_theme_constant(SNAME("autohide"))) {
+ if (theme_cache.autohide) {
queue_redraw();
}
} break;
@@ -185,7 +203,7 @@ void SplitContainer::_notification(int p_what) {
return;
}
- if (collapsed || (!dragging && !mouse_inside && get_theme_constant(SNAME("autohide")))) {
+ if (collapsed || (!dragging && !mouse_inside && theme_cache.autohide)) {
return;
}
@@ -193,8 +211,8 @@ void SplitContainer::_notification(int p_what) {
return;
}
- int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant(SNAME("separation")) : 0;
- Ref<Texture2D> tex = get_theme_icon(SNAME("grabber"));
+ int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? theme_cache.separation : 0;
+ Ref<Texture2D> tex = theme_cache.grabber_icon;
Size2 size = get_size();
if (vertical) {
@@ -210,6 +228,12 @@ void SplitContainer::_notification(int p_what) {
}
}
+void SplitContainer::_validate_property(PropertyInfo &p_property) const {
+ if (is_fixed && p_property.name == "vertical") {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+}
+
void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
@@ -222,16 +246,14 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
if (mb.is_valid()) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
- int sep = get_theme_constant(SNAME("separation"));
-
if (vertical) {
- if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + sep) {
+ if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + theme_cache.separation) {
dragging = true;
drag_from = mb->get_position().y;
drag_ofs = split_offset;
}
} else {
- if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + sep) {
+ if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + theme_cache.separation) {
dragging = true;
drag_from = mb->get_position().x;
drag_ofs = split_offset;
@@ -248,14 +270,14 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
if (mm.is_valid()) {
bool mouse_inside_state = false;
if (vertical) {
- mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant(SNAME("separation"));
+ mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + theme_cache.separation;
} else {
- mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant(SNAME("separation"));
+ mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + theme_cache.separation;
}
if (mouse_inside != mouse_inside_state) {
mouse_inside = mouse_inside_state;
- if (get_theme_constant(SNAME("autohide"))) {
+ if (theme_cache.autohide) {
queue_redraw();
}
}
@@ -281,14 +303,12 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const
}
if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) {
- int sep = get_theme_constant(SNAME("separation"));
-
if (vertical) {
- if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) {
+ if (p_pos.y > middle_sep && p_pos.y < middle_sep + theme_cache.separation) {
return CURSOR_VSPLIT;
}
} else {
- if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep) {
+ if (p_pos.x > middle_sep && p_pos.x < middle_sep + theme_cache.separation) {
return CURSOR_HSPLIT;
}
}
@@ -344,6 +364,17 @@ bool SplitContainer::is_collapsed() const {
return collapsed;
}
+void SplitContainer::set_vertical(bool p_vertical) {
+ ERR_FAIL_COND_MSG(is_fixed, "Can't change orientation of " + get_class() + ".");
+ vertical = p_vertical;
+ update_minimum_size();
+ _resort();
+}
+
+bool SplitContainer::is_vertical() const {
+ return vertical;
+}
+
Vector<int> SplitContainer::get_allowed_size_flags_horizontal() const {
Vector<int> flags;
flags.append(SIZE_FILL);
@@ -379,11 +410,15 @@ void SplitContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_dragger_visibility", "mode"), &SplitContainer::set_dragger_visibility);
ClassDB::bind_method(D_METHOD("get_dragger_visibility"), &SplitContainer::get_dragger_visibility);
+ ClassDB::bind_method(D_METHOD("set_vertical", "vertical"), &SplitContainer::set_vertical);
+ ClassDB::bind_method(D_METHOD("is_vertical"), &SplitContainer::is_vertical);
+
ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::INT, "offset")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_split_offset", "get_split_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collapsed"), "set_collapsed", "is_collapsed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden and Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical");
BIND_ENUM_CONSTANT(DRAGGER_VISIBLE);
BIND_ENUM_CONSTANT(DRAGGER_HIDDEN);
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index a69ffe4de9..8ab0779d4b 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -55,13 +55,27 @@ private:
DraggerVisibility dragger_visibility = DRAGGER_VISIBLE;
bool mouse_inside = false;
+ struct ThemeCache {
+ int separation = 0;
+ int autohide = 0;
+ Ref<Texture2D> grabber_icon;
+ Ref<Texture2D> grabber_icon_h;
+ Ref<Texture2D> grabber_icon_v;
+ } theme_cache;
+
Control *_getch(int p_idx) const;
+ Ref<Texture2D> _get_grabber_icon() const;
void _resort();
protected:
+ bool is_fixed = false;
+
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
public:
@@ -75,6 +89,9 @@ public:
void set_dragger_visibility(DraggerVisibility p_visibility);
DraggerVisibility get_dragger_visibility() const;
+ void set_vertical(bool p_vertical);
+ bool is_vertical() const;
+
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
virtual Size2 get_minimum_size() const override;
@@ -92,7 +109,7 @@ class HSplitContainer : public SplitContainer {
public:
HSplitContainer() :
- SplitContainer(false) {}
+ SplitContainer(false) { is_fixed = true; }
};
class VSplitContainer : public SplitContainer {
@@ -100,7 +117,7 @@ class VSplitContainer : public SplitContainer {
public:
VSplitContainer() :
- SplitContainer(true) {}
+ SplitContainer(true) { is_fixed = true; }
};
#endif // SPLIT_CONTAINER_H
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index 61cf8e8a86..4d18af7743 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -44,14 +44,7 @@ Size2 TabBar::get_minimum_size() const {
return ms;
}
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- Ref<StyleBox> button_highlight = get_theme_stylebox(SNAME("button_highlight"));
- Ref<Texture2D> close = get_theme_icon(SNAME("close"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
- int y_margin = MAX(MAX(tab_unselected->get_minimum_size().height, tab_selected->get_minimum_size().height), tab_disabled->get_minimum_size().height);
+ int y_margin = MAX(MAX(theme_cache.tab_unselected_style->get_minimum_size().height, theme_cache.tab_selected_style->get_minimum_size().height), theme_cache.tab_disabled_style->get_minimum_size().height);
for (int i = 0; i < tabs.size(); i++) {
if (tabs[i].hidden) {
@@ -62,22 +55,22 @@ Size2 TabBar::get_minimum_size() const {
Ref<StyleBox> style;
if (tabs[i].disabled) {
- style = tab_disabled;
+ style = theme_cache.tab_disabled_style;
} else if (current == i) {
- style = tab_selected;
+ style = theme_cache.tab_selected_style;
} else {
- style = tab_unselected;
+ style = theme_cache.tab_unselected_style;
}
ms.width += style->get_minimum_size().width;
Ref<Texture2D> tex = tabs[i].icon;
if (tex.is_valid()) {
ms.height = MAX(ms.height, tex->get_size().height + y_margin);
- ms.width += tex->get_size().width + hseparation;
+ ms.width += tex->get_size().width + theme_cache.h_separation;
}
if (!tabs[i].text.is_empty()) {
- ms.width += tabs[i].size_text + hseparation;
+ ms.width += tabs[i].size_text + theme_cache.h_separation;
}
ms.height = MAX(ms.height, tabs[i].text_buf->get_size().y + y_margin);
@@ -87,22 +80,22 @@ Size2 TabBar::get_minimum_size() const {
Ref<Texture2D> rb = tabs[i].right_button;
if (close_visible) {
- ms.width += button_highlight->get_minimum_size().width + rb->get_width();
+ ms.width += theme_cache.button_hl_style->get_minimum_size().width + rb->get_width();
} else {
- ms.width += button_highlight->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
+ ms.width += theme_cache.button_hl_style->get_margin(SIDE_LEFT) + rb->get_width() + theme_cache.h_separation;
}
ms.height = MAX(ms.height, rb->get_height() + y_margin);
}
if (close_visible) {
- ms.width += button_highlight->get_margin(SIDE_LEFT) + close->get_width() + hseparation;
+ ms.width += theme_cache.button_hl_style->get_margin(SIDE_LEFT) + theme_cache.close_icon->get_width() + theme_cache.h_separation;
- ms.height = MAX(ms.height, close->get_height() + y_margin);
+ ms.height = MAX(ms.height, theme_cache.close_icon->get_height() + y_margin);
}
if (ms.width - ofs > style->get_minimum_size().width) {
- ms.width -= hseparation;
+ ms.width -= theme_cache.h_separation;
}
}
@@ -122,16 +115,13 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
Point2 pos = mm->get_position();
if (buttons_visible) {
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
if (is_layout_rtl()) {
- if (pos.x < decr->get_width()) {
+ if (pos.x < theme_cache.decrement_icon->get_width()) {
if (highlight_arrow != 1) {
highlight_arrow = 1;
queue_redraw();
}
- } else if (pos.x < incr->get_width() + decr->get_width()) {
+ } else if (pos.x < theme_cache.increment_icon->get_width() + theme_cache.decrement_icon->get_width()) {
if (highlight_arrow != 0) {
highlight_arrow = 0;
queue_redraw();
@@ -141,8 +131,8 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
queue_redraw();
}
} else {
- int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
- if (pos.x > limit_minus_buttons + decr->get_width()) {
+ int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
+ if (pos.x > limit_minus_buttons + theme_cache.decrement_icon->get_width()) {
if (highlight_arrow != 1) {
highlight_arrow = 1;
queue_redraw();
@@ -214,18 +204,15 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
Point2 pos = mb->get_position();
if (buttons_visible) {
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
if (is_layout_rtl()) {
- if (pos.x < decr->get_width()) {
+ if (pos.x < theme_cache.decrement_icon->get_width()) {
if (missing_right) {
offset++;
_update_cache();
queue_redraw();
}
return;
- } else if (pos.x < incr->get_width() + decr->get_width()) {
+ } else if (pos.x < theme_cache.increment_icon->get_width() + theme_cache.decrement_icon->get_width()) {
if (offset > 0) {
offset--;
_update_cache();
@@ -234,8 +221,8 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
return;
}
} else {
- int limit = get_size().width - incr->get_width() - decr->get_width();
- if (pos.x > limit + decr->get_width()) {
+ int limit = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
+ if (pos.x > limit + theme_cache.decrement_icon->get_width()) {
if (missing_right) {
offset++;
_update_cache();
@@ -299,9 +286,6 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
}
void TabBar::_shape(int p_tab) {
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
-
tabs.write[p_tab].xl_text = atr(tabs[p_tab].text);
tabs.write[p_tab].text_buf->clear();
tabs.write[p_tab].text_buf->set_width(-1);
@@ -311,7 +295,37 @@ void TabBar::_shape(int p_tab) {
tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction);
}
- tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].language);
+ tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, theme_cache.font, theme_cache.font_size, tabs[p_tab].language);
+}
+
+void TabBar::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
+
+ theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
+ theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
+ theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
+
+ theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
+ theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
+ theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
+ theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
+ theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
+ theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.close_icon = get_theme_icon(SNAME("close"));
+ theme_cache.button_pressed_style = get_theme_stylebox(SNAME("button_pressed"));
+ theme_cache.button_hl_style = get_theme_stylebox(SNAME("button_highlight"));
}
void TabBar::_notification(int p_what) {
@@ -352,18 +366,9 @@ void TabBar::_notification(int p_what) {
return;
}
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
- Color font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
- Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
bool rtl = is_layout_rtl();
Vector2 size = get_size();
- int limit_minus_buttons = size.width - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = size.width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int ofs = tabs[offset].ofs_cache;
@@ -378,14 +383,14 @@ void TabBar::_notification(int p_what) {
Color col;
if (tabs[i].disabled) {
- sb = tab_disabled;
- col = font_disabled_color;
+ sb = theme_cache.tab_disabled_style;
+ col = theme_cache.font_disabled_color;
} else if (i == current) {
- sb = tab_selected;
- col = font_selected_color;
+ sb = theme_cache.tab_selected_style;
+ col = theme_cache.font_selected_color;
} else {
- sb = tab_unselected;
- col = font_unselected_color;
+ sb = theme_cache.tab_unselected_style;
+ col = theme_cache.font_unselected_color;
}
_draw_tab(sb, col, i, rtl ? size.width - ofs - tabs[i].size_cache : ofs);
@@ -396,41 +401,38 @@ void TabBar::_notification(int p_what) {
// Draw selected tab in the front, but only if it's visible.
if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) {
- Ref<StyleBox> sb = tabs[current].disabled ? tab_disabled : tab_selected;
+ Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style;
float x = rtl ? size.width - tabs[current].ofs_cache - tabs[current].size_cache : tabs[current].ofs_cache;
- _draw_tab(sb, font_selected_color, current, x);
+ _draw_tab(sb, theme_cache.font_selected_color, current, x);
}
if (buttons_visible) {
- Ref<Texture2D> incr_hl = get_theme_icon(SNAME("increment_highlight"));
- Ref<Texture2D> decr_hl = get_theme_icon(SNAME("decrement_highlight"));
-
- int vofs = (size.height - incr->get_size().height) / 2;
+ int vofs = (size.height - theme_cache.increment_icon->get_size().height) / 2;
if (rtl) {
if (missing_right) {
- draw_texture(highlight_arrow == 1 ? decr_hl : decr, Point2(0, vofs));
+ draw_texture(highlight_arrow == 1 ? theme_cache.decrement_hl_icon : theme_cache.decrement_icon, Point2(0, vofs));
} else {
- draw_texture(decr, Point2(0, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.decrement_icon, Point2(0, vofs), Color(1, 1, 1, 0.5));
}
if (offset > 0) {
- draw_texture(highlight_arrow == 0 ? incr_hl : incr, Point2(incr->get_size().width, vofs));
+ draw_texture(highlight_arrow == 0 ? theme_cache.increment_hl_icon : theme_cache.increment_icon, Point2(theme_cache.increment_icon->get_size().width, vofs));
} else {
- draw_texture(incr, Point2(incr->get_size().width, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.increment_icon, Point2(theme_cache.increment_icon->get_size().width, vofs), Color(1, 1, 1, 0.5));
}
} else {
if (offset > 0) {
- draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit_minus_buttons, vofs));
+ draw_texture(highlight_arrow == 0 ? theme_cache.decrement_hl_icon : theme_cache.decrement_icon, Point2(limit_minus_buttons, vofs));
} else {
- draw_texture(decr, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.decrement_icon, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
}
if (missing_right) {
- draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit_minus_buttons + decr->get_size().width, vofs));
+ draw_texture(highlight_arrow == 1 ? theme_cache.increment_hl_icon : theme_cache.increment_icon, Point2(limit_minus_buttons + theme_cache.decrement_icon->get_size().width, vofs));
} else {
- draw_texture(incr, Point2(limit_minus_buttons + decr->get_size().width, vofs), Color(1, 1, 1, 0.5));
+ draw_texture(theme_cache.increment_icon, Point2(limit_minus_buttons + theme_cache.decrement_icon->get_size().width, vofs), Color(1, 1, 1, 0.5));
}
}
}
@@ -462,10 +464,7 @@ void TabBar::_notification(int p_what) {
}
}
- Ref<Texture2D> drop_mark = get_theme_icon(SNAME("drop_mark"));
- Color drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
-
- drop_mark->draw(get_canvas_item(), Point2(x - drop_mark->get_width() / 2, (size.height - drop_mark->get_height()) / 2), drop_mark_color);
+ theme_cache.drop_mark_icon->draw(get_canvas_item(), Point2(x - theme_cache.drop_mark_icon->get_width() / 2, (size.height - theme_cache.drop_mark_icon->get_height()) / 2), theme_cache.drop_mark_color);
}
} break;
}
@@ -475,10 +474,6 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
RID ci = get_canvas_item();
bool rtl = is_layout_rtl();
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
Rect2 sb_rect = Rect2(p_x, 0, tabs[p_index].size_cache, get_size().height);
p_tab_style->draw(ci, sb_rect);
@@ -491,7 +486,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (icon.is_valid()) {
icon->draw(ci, Point2i(rtl ? p_x - icon->get_width() : p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
- p_x = rtl ? p_x - icon->get_width() - hseparation : p_x + icon->get_width() + hseparation;
+ p_x = rtl ? p_x - icon->get_width() - theme_cache.h_separation : p_x + icon->get_width() + theme_cache.h_separation;
}
// Draw the text.
@@ -499,17 +494,17 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
Point2i text_pos = Point2i(rtl ? p_x - tabs[p_index].size_text : p_x,
p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[p_index].text_buf->get_size().y) / 2);
- if (outline_size > 0 && font_outline_color.a > 0) {
- tabs[p_index].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ tabs[p_index].text_buf->draw_outline(ci, text_pos, theme_cache.outline_size, theme_cache.font_outline_color);
}
tabs[p_index].text_buf->draw(ci, text_pos, p_font_color);
- p_x = rtl ? p_x - tabs[p_index].size_text - hseparation : p_x + tabs[p_index].size_text + hseparation;
+ p_x = rtl ? p_x - tabs[p_index].size_text - theme_cache.h_separation : p_x + tabs[p_index].size_text + theme_cache.h_separation;
}
// Draw and calculate rect of the right button.
if (tabs[p_index].right_button.is_valid()) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
+ Ref<StyleBox> style = theme_cache.button_hl_style;
Ref<Texture2D> rb = tabs[p_index].right_button;
Rect2 rb_rect;
@@ -521,7 +516,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (rb_hover == p_index) {
if (rb_pressing) {
- get_theme_stylebox(SNAME("button_pressed"))->draw(ci, rb_rect);
+ theme_cache.button_pressed_style->draw(ci, rb_rect);
} else {
style->draw(ci, rb_rect);
}
@@ -534,8 +529,8 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
// Draw and calculate rect of the close button.
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_index == current)) {
- Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
- Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
+ Ref<StyleBox> style = theme_cache.button_hl_style;
+ Ref<Texture2D> cb = theme_cache.close_icon;
Rect2 cb_rect;
cb_rect.size = style->get_minimum_size() + cb->get_size();
@@ -546,7 +541,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (!tabs[p_index].disabled && cb_hover == p_index) {
if (cb_pressing) {
- get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
+ theme_cache.button_pressed_style->draw(ci, cb_rect);
} else {
style->draw(ci, cb_rect);
}
@@ -849,14 +844,8 @@ void TabBar::_update_cache() {
return;
}
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
-
int limit = get_size().width;
- int limit_minus_buttons = limit - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = limit - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int w = 0;
@@ -1258,52 +1247,47 @@ void TabBar::move_tab(int p_from, int p_to) {
int TabBar::get_tab_width(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
- Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
- Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
- Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
- int hseparation = get_theme_constant(SNAME("h_separation"));
-
Ref<StyleBox> style;
if (tabs[p_idx].disabled) {
- style = tab_disabled;
+ style = theme_cache.tab_disabled_style;
} else if (current == p_idx) {
- style = tab_selected;
+ style = theme_cache.tab_selected_style;
} else {
- style = tab_unselected;
+ style = theme_cache.tab_unselected_style;
}
int x = style->get_minimum_size().width;
Ref<Texture2D> tex = tabs[p_idx].icon;
if (tex.is_valid()) {
- x += tex->get_width() + hseparation;
+ x += tex->get_width() + theme_cache.h_separation;
}
if (!tabs[p_idx].text.is_empty()) {
- x += tabs[p_idx].size_text + hseparation;
+ x += tabs[p_idx].size_text + theme_cache.h_separation;
}
bool close_visible = cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current);
if (tabs[p_idx].right_button.is_valid()) {
- Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
+ Ref<StyleBox> btn_style = theme_cache.button_hl_style;
Ref<Texture2D> rb = tabs[p_idx].right_button;
if (close_visible) {
x += btn_style->get_minimum_size().width + rb->get_width();
} else {
- x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
+ x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + theme_cache.h_separation;
}
}
if (close_visible) {
- Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
- Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
- x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + hseparation;
+ Ref<StyleBox> btn_style = theme_cache.button_hl_style;
+ Ref<Texture2D> cb = theme_cache.close_icon;
+ x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + theme_cache.h_separation;
}
if (x > style->get_minimum_size().width) {
- x -= hseparation;
+ x -= theme_cache.h_separation;
}
return x;
@@ -1314,9 +1298,7 @@ void TabBar::_ensure_no_over_offset() {
return;
}
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int prev_offset = offset;
@@ -1359,9 +1341,7 @@ void TabBar::ensure_tab_visible(int p_idx) {
return;
}
- Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
- Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
- int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
+ int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
int total_w = tabs[max_drawn_tab].ofs_cache - tabs[offset].ofs_cache;
for (int i = max_drawn_tab; i <= p_idx; i++) {
diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h
index d123385e47..ac4a6a195e 100644
--- a/scene/gui/tab_bar.h
+++ b/scene/gui/tab_bar.h
@@ -104,6 +104,34 @@ private:
bool scroll_to_selected = true;
int tabs_rearrange_group = -1;
+ struct ThemeCache {
+ int h_separation = 0;
+
+ Ref<StyleBox> tab_unselected_style;
+ Ref<StyleBox> tab_selected_style;
+ Ref<StyleBox> tab_disabled_style;
+
+ Ref<Texture2D> increment_icon;
+ Ref<Texture2D> increment_hl_icon;
+ Ref<Texture2D> decrement_icon;
+ Ref<Texture2D> decrement_hl_icon;
+ Ref<Texture2D> drop_mark_icon;
+ Color drop_mark_color;
+
+ Ref<Font> font;
+ int font_size;
+ int outline_size = 0;
+
+ Color font_selected_color;
+ Color font_unselected_color;
+ Color font_disabled_color;
+ Color font_outline_color;
+
+ Ref<Texture2D> close_icon;
+ Ref<StyleBox> button_pressed_style;
+ Ref<StyleBox> button_hl_style;
+ } theme_cache;
+
int get_tab_width(int p_idx) const;
void _ensure_no_over_offset();
@@ -117,6 +145,7 @@ private:
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 3e04ebee6a..f45d132a66 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -60,26 +60,24 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
}
// Handle menu button.
- Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
-
if (is_layout_rtl()) {
- if (popup && pos.x < menu->get_width()) {
+ if (popup && pos.x < theme_cache.menu_icon->get_width()) {
emit_signal(SNAME("pre_popup_pressed"));
Vector2 popup_pos = get_screen_position();
- popup_pos.y += menu->get_height();
+ popup_pos.y += theme_cache.menu_icon->get_height();
popup->set_position(popup_pos);
popup->popup();
return;
}
} else {
- if (popup && pos.x > size.width - menu->get_width()) {
+ if (popup && pos.x > size.width - theme_cache.menu_icon->get_width()) {
emit_signal(SNAME("pre_popup_pressed"));
Vector2 popup_pos = get_screen_position();
popup_pos.x += size.width - popup->get_size().width;
- popup_pos.y += menu->get_height();
+ popup_pos.y += theme_cache.menu_icon->get_height();
popup->set_position(popup_pos);
popup->popup();
@@ -103,10 +101,9 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
return;
}
- Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
if (popup) {
if (is_layout_rtl()) {
- if (pos.x <= menu->get_width()) {
+ if (pos.x <= theme_cache.menu_icon->get_width()) {
if (!menu_hovered) {
menu_hovered = true;
queue_redraw();
@@ -117,7 +114,7 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
queue_redraw();
}
} else {
- if (pos.x >= size.width - menu->get_width()) {
+ if (pos.x >= size.width - theme_cache.menu_icon->get_width()) {
if (!menu_hovered) {
menu_hovered = true;
queue_redraw();
@@ -136,6 +133,41 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
}
}
+void TabContainer::_update_theme_item_cache() {
+ Container::_update_theme_item_cache();
+
+ theme_cache.side_margin = get_theme_constant(SNAME("side_margin"));
+
+ theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
+ theme_cache.tabbar_style = get_theme_stylebox(SNAME("tabbar_background"));
+
+ theme_cache.menu_icon = get_theme_icon(SNAME("menu"));
+ theme_cache.menu_hl_icon = get_theme_icon(SNAME("menu_highlight"));
+
+ // TabBar overrides.
+ theme_cache.icon_separation = get_theme_constant(SNAME("icon_separation"));
+ theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
+
+ theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
+ theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
+ theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
+
+ theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
+ theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
+ theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
+ theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
+ theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
+ theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
+
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
+ theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+
+ theme_cache.tab_font = get_theme_font(SNAME("font"));
+ theme_cache.tab_font_size = get_theme_font_size(SNAME("font_size"));
+}
+
void TabContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -155,31 +187,26 @@ void TabContainer::_notification(int p_what) {
Size2 size = get_size();
// Draw only the tab area if the header is hidden.
- Ref<StyleBox> panel = get_theme_stylebox(SNAME("panel"));
if (!tabs_visible) {
- panel->draw(canvas, Rect2(0, 0, size.width, size.height));
+ theme_cache.panel_style->draw(canvas, Rect2(0, 0, size.width, size.height));
return;
}
int header_height = _get_top_margin();
// Draw background for the tabbar.
- Ref<StyleBox> tabbar_background = get_theme_stylebox(SNAME("tabbar_background"));
- tabbar_background->draw(canvas, Rect2(0, 0, size.width, header_height));
+ theme_cache.tabbar_style->draw(canvas, Rect2(0, 0, size.width, header_height));
// Draw the background for the tab's content.
- panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
+ theme_cache.panel_style->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
// Draw the popup menu.
if (get_popup()) {
- Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
- Ref<Texture2D> menu_hl = get_theme_icon(SNAME("menu_highlight"));
-
- int x = is_layout_rtl() ? 0 : get_size().width - menu->get_width();
+ int x = is_layout_rtl() ? 0 : get_size().width - theme_cache.menu_icon->get_width();
if (menu_hovered) {
- menu_hl->draw(get_canvas_item(), Point2(x, (header_height - menu_hl->get_height()) / 2));
+ theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_hl_icon->get_height()) / 2));
} else {
- menu->draw(get_canvas_item(), Point2(x, (header_height - menu->get_height()) / 2));
+ theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_icon->get_height()) / 2));
}
}
} break;
@@ -198,23 +225,27 @@ void TabContainer::_on_theme_changed() {
return;
}
- tab_bar->add_theme_style_override(SNAME("tab_unselected"), get_theme_stylebox(SNAME("tab_unselected")));
- tab_bar->add_theme_style_override(SNAME("tab_selected"), get_theme_stylebox(SNAME("tab_selected")));
- tab_bar->add_theme_style_override(SNAME("tab_disabled"), get_theme_stylebox(SNAME("tab_disabled")));
- tab_bar->add_theme_icon_override(SNAME("increment"), get_theme_icon(SNAME("increment")));
- tab_bar->add_theme_icon_override(SNAME("increment_highlight"), get_theme_icon(SNAME("increment_highlight")));
- tab_bar->add_theme_icon_override(SNAME("decrement"), get_theme_icon(SNAME("decrement")));
- tab_bar->add_theme_icon_override(SNAME("decrement_highlight"), get_theme_icon(SNAME("decrement_highlight")));
- tab_bar->add_theme_icon_override(SNAME("drop_mark"), get_theme_icon(SNAME("drop_mark")));
- tab_bar->add_theme_color_override(SNAME("drop_mark_color"), get_theme_color(SNAME("drop_mark_color")));
- tab_bar->add_theme_color_override(SNAME("font_selected_color"), get_theme_color(SNAME("font_selected_color")));
- tab_bar->add_theme_color_override(SNAME("font_unselected_color"), get_theme_color(SNAME("font_unselected_color")));
- tab_bar->add_theme_color_override(SNAME("font_disabled_color"), get_theme_color(SNAME("font_disabled_color")));
- tab_bar->add_theme_color_override(SNAME("font_outline_color"), get_theme_color(SNAME("font_outline_color")));
- tab_bar->add_theme_font_override(SNAME("font"), get_theme_font(SNAME("font")));
- tab_bar->add_theme_font_size_override(SNAME("font_size"), get_theme_font_size(SNAME("font_size")));
- tab_bar->add_theme_constant_override(SNAME("h_separation"), get_theme_constant(SNAME("icon_separation")));
- tab_bar->add_theme_constant_override(SNAME("outline_size"), get_theme_constant(SNAME("outline_size")));
+ tab_bar->add_theme_style_override(SNAME("tab_unselected"), theme_cache.tab_unselected_style);
+ tab_bar->add_theme_style_override(SNAME("tab_selected"), theme_cache.tab_selected_style);
+ tab_bar->add_theme_style_override(SNAME("tab_disabled"), theme_cache.tab_disabled_style);
+
+ tab_bar->add_theme_icon_override(SNAME("increment"), theme_cache.increment_icon);
+ tab_bar->add_theme_icon_override(SNAME("increment_highlight"), theme_cache.increment_hl_icon);
+ tab_bar->add_theme_icon_override(SNAME("decrement"), theme_cache.decrement_icon);
+ tab_bar->add_theme_icon_override(SNAME("decrement_highlight"), theme_cache.decrement_hl_icon);
+ tab_bar->add_theme_icon_override(SNAME("drop_mark"), theme_cache.drop_mark_icon);
+ tab_bar->add_theme_color_override(SNAME("drop_mark_color"), theme_cache.drop_mark_color);
+
+ tab_bar->add_theme_color_override(SNAME("font_selected_color"), theme_cache.font_selected_color);
+ tab_bar->add_theme_color_override(SNAME("font_unselected_color"), theme_cache.font_unselected_color);
+ tab_bar->add_theme_color_override(SNAME("font_disabled_color"), theme_cache.font_disabled_color);
+ tab_bar->add_theme_color_override(SNAME("font_outline_color"), theme_cache.font_outline_color);
+
+ tab_bar->add_theme_font_override(SNAME("font"), theme_cache.tab_font);
+ tab_bar->add_theme_font_size_override(SNAME("font_size"), theme_cache.tab_font_size);
+
+ tab_bar->add_theme_constant_override(SNAME("h_separation"), theme_cache.icon_separation);
+ tab_bar->add_theme_constant_override(SNAME("outline_size"), theme_cache.outline_size);
_update_margins();
if (get_tab_count() > 0) {
@@ -228,7 +259,6 @@ void TabContainer::_on_theme_changed() {
}
void TabContainer::_repaint() {
- Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"));
Vector<Control *> controls = _get_tab_controls();
int current = get_current_tab();
@@ -243,10 +273,10 @@ void TabContainer::_repaint() {
c->set_offset(SIDE_TOP, _get_top_margin());
}
- c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + sb->get_margin(SIDE_TOP));
- c->set_offset(SIDE_LEFT, c->get_offset(SIDE_LEFT) + sb->get_margin(SIDE_LEFT));
- c->set_offset(SIDE_RIGHT, c->get_offset(SIDE_RIGHT) - sb->get_margin(SIDE_RIGHT));
- c->set_offset(SIDE_BOTTOM, c->get_offset(SIDE_BOTTOM) - sb->get_margin(SIDE_BOTTOM));
+ c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_TOP));
+ c->set_offset(SIDE_LEFT, c->get_offset(SIDE_LEFT) + theme_cache.panel_style->get_margin(SIDE_LEFT));
+ c->set_offset(SIDE_RIGHT, c->get_offset(SIDE_RIGHT) - theme_cache.panel_style->get_margin(SIDE_RIGHT));
+ c->set_offset(SIDE_BOTTOM, c->get_offset(SIDE_BOTTOM) - theme_cache.panel_style->get_margin(SIDE_BOTTOM));
} else {
c->hide();
}
@@ -256,8 +286,7 @@ void TabContainer::_repaint() {
}
void TabContainer::_update_margins() {
- int menu_width = get_theme_icon(SNAME("menu"))->get_width();
- int side_margin = get_theme_constant(SNAME("side_margin"));
+ int menu_width = theme_cache.menu_icon->get_width();
// Directly check for validity, to avoid errors when quitting.
bool has_popup = popup_obj_id.is_valid();
@@ -271,7 +300,7 @@ void TabContainer::_update_margins() {
switch (get_tab_alignment()) {
case TabBar::ALIGNMENT_LEFT: {
- tab_bar->set_offset(SIDE_LEFT, side_margin);
+ tab_bar->set_offset(SIDE_LEFT, theme_cache.side_margin);
tab_bar->set_offset(SIDE_RIGHT, has_popup ? -menu_width : 0);
} break;
@@ -293,10 +322,10 @@ void TabContainer::_update_margins() {
int total_tabs_width = last_tab_rect.position.x - first_tab_pos + last_tab_rect.size.width;
// Calculate if all the tabs would still fit if the margin was present.
- if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + side_margin) > get_size().width))) {
+ if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + theme_cache.side_margin) > get_size().width))) {
tab_bar->set_offset(SIDE_RIGHT, has_popup ? -menu_width : 0);
} else {
- tab_bar->set_offset(SIDE_RIGHT, -side_margin);
+ tab_bar->set_offset(SIDE_RIGHT, -theme_cache.side_margin);
}
} break;
@@ -798,13 +827,12 @@ Size2 TabContainer::get_minimum_size() const {
if (!get_clip_tabs()) {
if (get_popup()) {
- ms.x += get_theme_icon(SNAME("menu"))->get_width();
+ ms.x += theme_cache.menu_icon->get_width();
}
- int side_margin = get_theme_constant(SNAME("side_margin"));
- if (side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
+ if (theme_cache.side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
(get_tab_alignment() != TabBar::ALIGNMENT_RIGHT || !get_popup())) {
- ms.x += side_margin;
+ ms.x += theme_cache.side_margin;
}
}
}
@@ -824,7 +852,7 @@ Size2 TabContainer::get_minimum_size() const {
}
ms.y += max_control_height;
- Size2 panel_ms = get_theme_stylebox(SNAME("panel"))->get_minimum_size();
+ Size2 panel_ms = theme_cache.panel_style->get_minimum_size();
ms.x = MAX(ms.x, panel_ms.x);
ms.y += panel_ms.y;
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index 60c8130939..b552aa459b 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -48,6 +48,39 @@ class TabContainer : public Container {
bool theme_changing = false;
Node *child_removing = nullptr;
+ struct ThemeCache {
+ int side_margin = 0;
+
+ Ref<StyleBox> panel_style;
+ Ref<StyleBox> tabbar_style;
+
+ Ref<Texture2D> menu_icon;
+ Ref<Texture2D> menu_hl_icon;
+
+ // TabBar overrides.
+ int icon_separation = 0;
+ int outline_size = 0;
+
+ Ref<StyleBox> tab_unselected_style;
+ Ref<StyleBox> tab_selected_style;
+ Ref<StyleBox> tab_disabled_style;
+
+ Ref<Texture2D> increment_icon;
+ Ref<Texture2D> increment_hl_icon;
+ Ref<Texture2D> decrement_icon;
+ Ref<Texture2D> decrement_hl_icon;
+ Ref<Texture2D> drop_mark_icon;
+ Color drop_mark_color;
+
+ Color font_selected_color;
+ Color font_unselected_color;
+ Color font_disabled_color;
+ Color font_outline_color;
+
+ Ref<Font> tab_font;
+ int tab_font_size;
+ } theme_cache;
+
int _get_top_margin() const;
Vector<Control *> _get_tab_controls() const;
void _on_theme_changed();
@@ -65,6 +98,8 @@ class TabContainer : public Container {
protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
+ virtual void _update_theme_item_cache() override;
+
void _notification(int p_what);
virtual void add_child_notify(Node *p_child) override;
virtual void move_child_notify(Node *p_child) override;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index e2fd903e0e..2efb6593d3 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -112,7 +112,7 @@ bool TextureButton::has_point(const Point2 &p_point) const {
}
Point2i p = point;
- return click_mask->get_bit(p);
+ return click_mask->get_bitv(p);
}
return Control::has_point(p_point);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 3c6be008f2..e8164b5728 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1286,14 +1286,14 @@ Size2 TreeItem::get_minimum_size(int p_column) {
// Icon.
if (cell.mode == CELL_MODE_CHECK) {
- size.width += tree->cache.checked->get_width() + tree->cache.hseparation;
+ size.width += tree->theme_cache.checked->get_width() + tree->theme_cache.hseparation;
}
if (cell.icon.is_valid()) {
Size2i icon_size = cell.get_icon_size();
if (cell.icon_max_w > 0 && icon_size.width > cell.icon_max_w) {
icon_size.width = cell.icon_max_w;
}
- size.width += icon_size.width + tree->cache.hseparation;
+ size.width += icon_size.width + tree->theme_cache.hseparation;
size.height = MAX(size.height, icon_size.height);
}
@@ -1301,13 +1301,13 @@ Size2 TreeItem::get_minimum_size(int p_column) {
for (int i = 0; i < cell.buttons.size(); i++) {
Ref<Texture2D> texture = cell.buttons[i].texture;
if (texture.is_valid()) {
- Size2 button_size = texture->get_size() + tree->cache.button_pressed->get_minimum_size();
+ Size2 button_size = texture->get_size() + tree->theme_cache.button_pressed->get_minimum_size();
size.width += button_size.width;
size.height = MAX(size.height, button_size.height);
}
}
if (cell.buttons.size() >= 2) {
- size.width += (cell.buttons.size() - 1) * tree->cache.button_margin;
+ size.width += (cell.buttons.size() - 1) * tree->theme_cache.button_margin;
}
cells.write[p_column].cached_minimum_size = size;
@@ -1535,68 +1535,66 @@ TreeItem::~TreeItem() {
/**********************************************/
/**********************************************/
-void Tree::update_cache() {
- cache.font = get_theme_font(SNAME("font"));
- cache.font_size = get_theme_font_size(SNAME("font_size"));
- cache.tb_font = get_theme_font(SNAME("title_button_font"));
- cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
- cache.bg = get_theme_stylebox(SNAME("bg"));
- cache.selected = get_theme_stylebox(SNAME("selected"));
- cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
- cache.cursor = get_theme_stylebox(SNAME("cursor"));
- cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
- cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
-
- cache.checked = get_theme_icon(SNAME("checked"));
- cache.unchecked = get_theme_icon(SNAME("unchecked"));
- cache.indeterminate = get_theme_icon(SNAME("indeterminate"));
- if (is_layout_rtl()) {
- cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
- } else {
- cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
- }
- cache.arrow = get_theme_icon(SNAME("arrow"));
- cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
- cache.updown = get_theme_icon(SNAME("updown"));
-
- cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
- cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
- cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
- cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
-
- cache.font_color = get_theme_color(SNAME("font_color"));
- cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
- cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
- cache.hseparation = get_theme_constant(SNAME("h_separation"));
- cache.vseparation = get_theme_constant(SNAME("v_separation"));
- cache.item_margin = get_theme_constant(SNAME("item_margin"));
- cache.button_margin = get_theme_constant(SNAME("button_margin"));
-
- cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
- cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
-
- cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
- cache.guide_color = get_theme_color(SNAME("guide_color"));
- cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
- cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
- cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
- cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
- cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
- cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
- cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
- cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
-
- cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
- cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
-
- cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
- cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
- cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
- cache.title_button_color = get_theme_color(SNAME("title_button_color"));
-
- cache.base_scale = get_theme_default_base_scale();
-
- v_scroll->set_custom_step(cache.font->get_height(cache.font_size));
+void Tree::_update_theme_item_cache() {
+ Control::_update_theme_item_cache();
+
+ theme_cache.font = get_theme_font(SNAME("font"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
+ theme_cache.tb_font = get_theme_font(SNAME("title_button_font"));
+ theme_cache.tb_font_size = get_theme_font_size(SNAME("title_button_font_size"));
+ theme_cache.bg = get_theme_stylebox(SNAME("bg"));
+ theme_cache.bg_focus = get_theme_stylebox(SNAME("bg_focus"));
+ theme_cache.selected = get_theme_stylebox(SNAME("selected"));
+ theme_cache.selected_focus = get_theme_stylebox(SNAME("selected_focus"));
+ theme_cache.cursor = get_theme_stylebox(SNAME("cursor"));
+ theme_cache.cursor_unfocus = get_theme_stylebox(SNAME("cursor_unfocused"));
+ theme_cache.button_pressed = get_theme_stylebox(SNAME("button_pressed"));
+
+ theme_cache.checked = get_theme_icon(SNAME("checked"));
+ theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
+ theme_cache.indeterminate = get_theme_icon(SNAME("indeterminate"));
+ theme_cache.arrow = get_theme_icon(SNAME("arrow"));
+ theme_cache.arrow_collapsed = get_theme_icon(SNAME("arrow_collapsed"));
+ theme_cache.arrow_collapsed_mirrored = get_theme_icon(SNAME("arrow_collapsed_mirrored"));
+ theme_cache.select_arrow = get_theme_icon(SNAME("select_arrow"));
+ theme_cache.updown = get_theme_icon(SNAME("updown"));
+
+ theme_cache.custom_button = get_theme_stylebox(SNAME("custom_button"));
+ theme_cache.custom_button_hover = get_theme_stylebox(SNAME("custom_button_hover"));
+ theme_cache.custom_button_pressed = get_theme_stylebox(SNAME("custom_button_pressed"));
+ theme_cache.custom_button_font_highlight = get_theme_color(SNAME("custom_button_font_highlight"));
+
+ theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
+ theme_cache.drop_position_color = get_theme_color(SNAME("drop_position_color"));
+ theme_cache.hseparation = get_theme_constant(SNAME("h_separation"));
+ theme_cache.vseparation = get_theme_constant(SNAME("v_separation"));
+ theme_cache.item_margin = get_theme_constant(SNAME("item_margin"));
+ theme_cache.button_margin = get_theme_constant(SNAME("button_margin"));
+
+ theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
+ theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
+
+ theme_cache.draw_guides = get_theme_constant(SNAME("draw_guides"));
+ theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
+ theme_cache.draw_relationship_lines = get_theme_constant(SNAME("draw_relationship_lines"));
+ theme_cache.relationship_line_width = get_theme_constant(SNAME("relationship_line_width"));
+ theme_cache.parent_hl_line_width = get_theme_constant(SNAME("parent_hl_line_width"));
+ theme_cache.children_hl_line_width = get_theme_constant(SNAME("children_hl_line_width"));
+ theme_cache.parent_hl_line_margin = get_theme_constant(SNAME("parent_hl_line_margin"));
+ theme_cache.relationship_line_color = get_theme_color(SNAME("relationship_line_color"));
+ theme_cache.parent_hl_line_color = get_theme_color(SNAME("parent_hl_line_color"));
+ theme_cache.children_hl_line_color = get_theme_color(SNAME("children_hl_line_color"));
+
+ theme_cache.scroll_border = get_theme_constant(SNAME("scroll_border"));
+ theme_cache.scroll_speed = get_theme_constant(SNAME("scroll_speed"));
+
+ theme_cache.title_button = get_theme_stylebox(SNAME("title_button_normal"));
+ theme_cache.title_button_pressed = get_theme_stylebox(SNAME("title_button_pressed"));
+ theme_cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));
+ theme_cache.title_button_color = get_theme_color(SNAME("title_button_color"));
+
+ theme_cache.base_scale = get_theme_default_base_scale();
}
int Tree::compute_item_height(TreeItem *p_item) const {
@@ -1604,7 +1602,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
return 0;
}
- ERR_FAIL_COND_V(cache.font.is_null(), 0);
+ ERR_FAIL_COND_V(theme_cache.font.is_null(), 0);
int height = 0;
for (int i = 0; i < columns.size(); i++) {
@@ -1622,7 +1620,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
switch (p_item->cells[i].mode) {
case TreeItem::CELL_MODE_CHECK: {
- int check_icon_h = cache.checked->get_height();
+ int check_icon_h = theme_cache.checked->get_height();
if (height < check_icon_h) {
height = check_icon_h;
}
@@ -1642,7 +1640,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
}
}
if (p_item->cells[i].mode == TreeItem::CELL_MODE_CUSTOM && p_item->cells[i].custom_button) {
- height += cache.custom_button->get_minimum_size().height;
+ height += theme_cache.custom_button->get_minimum_size().height;
}
} break;
@@ -1655,7 +1653,7 @@ int Tree::compute_item_height(TreeItem *p_item) const {
height = item_min_height;
}
- height += cache.vseparation;
+ height += theme_cache.vseparation;
return height;
}
@@ -1665,7 +1663,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
return 0;
}
int height = compute_item_height(p_item);
- height += cache.vseparation;
+ height += theme_cache.vseparation;
if (!p_item->collapsed) { /* if not collapsed, check the children */
@@ -1682,7 +1680,7 @@ int Tree::get_item_height(TreeItem *p_item) const {
}
void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Color &p_color, const Color &p_icon_color, int p_ol_size, const Color &p_ol_color) {
- ERR_FAIL_COND(cache.font.is_null());
+ ERR_FAIL_COND(theme_cache.font.is_null());
Rect2i rect = p_rect;
Size2 ts = p_cell.text_buf->get_size();
@@ -1694,7 +1692,7 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
if (p_cell.icon_max_w > 0 && bmsize.width > p_cell.icon_max_w) {
bmsize.width = p_cell.icon_max_w;
}
- w += bmsize.width + cache.hseparation;
+ w += bmsize.width + theme_cache.hseparation;
if (rect.size.width > 0 && (w + ts.width) > rect.size.width) {
ts.width = rect.size.width - w;
}
@@ -1728,8 +1726,8 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
p_cell.text_buf->draw_outline(ci, draw_pos, p_ol_size, p_ol_color);
}
p_cell.text_buf->draw(ci, draw_pos, p_color);
- rect.position.x += ts.width + cache.hseparation;
- rect.size.x -= ts.width + cache.hseparation;
+ rect.position.x += ts.width + theme_cache.hseparation;
+ rect.size.x -= ts.width + theme_cache.hseparation;
}
if (!p_cell.icon.is_null()) {
@@ -1741,8 +1739,8 @@ void Tree::draw_item_rect(TreeItem::Cell &p_cell, const Rect2i &p_rect, const Co
}
p_cell.draw_icon(ci, rect.position + Size2i(0, Math::floor((real_t)(rect.size.y - bmsize.y) / 2)), bmsize, p_icon_color);
- rect.position.x += bmsize.x + cache.hseparation;
- rect.size.x -= bmsize.x + cache.hseparation;
+ rect.position.x += bmsize.x + theme_cache.hseparation;
+ rect.size.x -= bmsize.x + theme_cache.hseparation;
}
if (!rtl) {
@@ -1764,7 +1762,7 @@ void Tree::update_column(int p_col) {
columns.write[p_col].text_buf->set_direction((TextServer::Direction)columns[p_col].text_direction);
}
- columns.write[p_col].text_buf->add_string(columns[p_col].title, cache.font, cache.font_size, columns[p_col].language);
+ columns.write[p_col].text_buf->add_string(columns[p_col].title, theme_cache.font, theme_cache.font_size, columns[p_col].language);
}
void Tree::update_item_cell(TreeItem *p_item, int p_col) {
@@ -1813,14 +1811,14 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
if (p_item->cells[p_col].custom_font.is_valid()) {
font = p_item->cells[p_col].custom_font;
} else {
- font = cache.font;
+ font = theme_cache.font;
}
int font_size;
if (p_item->cells[p_col].custom_font_size > 0) {
font_size = p_item->cells[p_col].custom_font_size;
} else {
- font_size = cache.font_size;
+ font_size = theme_cache.font_size;
}
p_item->cells.write[p_col].text_buf->add_string(valtext, font, font_size, p_item->cells[p_col].language);
TS->shaped_text_set_bidi_override(p_item->cells[p_col].text_buf->get_rid(), structured_text_parser(p_item->cells[p_col].st_parser, p_item->cells[p_col].st_args, valtext));
@@ -1840,7 +1838,7 @@ void Tree::update_item_cache(TreeItem *p_item) {
}
int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item) {
- if (p_pos.y - cache.offset.y > (p_draw_size.height)) {
+ if (p_pos.y - theme_cache.offset.y > (p_draw_size.height)) {
return -1; //draw no more!
}
@@ -1856,18 +1854,18 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
bool rtl = cache.rtl;
/* Calculate height of the label part */
- label_h += cache.vseparation;
+ label_h += theme_cache.vseparation;
/* Draw label, if height fits */
bool skip = (p_item == root && hide_root);
- if (!skip && (p_pos.y + label_h - cache.offset.y) > 0) {
+ if (!skip && (p_pos.y + label_h - theme_cache.offset.y) > 0) {
// Draw separation.
- ERR_FAIL_COND_V(cache.font.is_null(), -1);
+ ERR_FAIL_COND_V(theme_cache.font.is_null(), -1);
- int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
+ int ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.hseparation : theme_cache.item_margin);
int skip2 = 0;
for (int i = 0; i < columns.size(); i++) {
if (skip2) {
@@ -1885,8 +1883,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
continue;
}
} else {
- ofs += cache.hseparation;
- w -= cache.hseparation;
+ ofs += theme_cache.hseparation;
+ w -= theme_cache.hseparation;
}
if (p_item->cells[i].expand_right) {
@@ -1902,10 +1900,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int button_w = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
- button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ button_w += b->get_size().width + theme_cache.button_pressed->get_minimum_size().width + theme_cache.button_margin;
}
- int total_ofs = ofs - cache.offset.x;
+ int total_ofs = ofs - theme_cache.offset.x;
if (total_ofs + w > p_draw_size.width) {
w = MAX(button_w, p_draw_size.width - total_ofs);
@@ -1915,9 +1913,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int bw = 0;
for (int j = p_item->cells[i].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[i].buttons[j].texture;
- Size2 s = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 s = b->get_size() + theme_cache.button_pressed->get_minimum_size();
- Point2i o = Point2i(ofs + w - s.width, p_pos.y) - cache.offset + p_draw_ofs;
+ Point2i o = Point2i(ofs + w - s.width, p_pos.y) - theme_cache.offset + p_draw_ofs;
if (cache.click_type == Cache::CLICK_BUTTON && cache.click_item == p_item && cache.click_column == i && cache.click_index == j && !p_item->cells[i].buttons[j].disabled) {
// Being pressed.
@@ -1925,48 +1923,48 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (rtl) {
od.x = get_size().width - od.x - s.x;
}
- cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, s.width, MAX(s.height, label_h)));
+ theme_cache.button_pressed->draw(get_canvas_item(), Rect2(od.x, od.y, s.width, MAX(s.height, label_h)));
}
o.y += (label_h - s.height) / 2;
- o += cache.button_pressed->get_offset();
+ o += theme_cache.button_pressed->get_offset();
if (rtl) {
o.x = get_size().width - o.x - b->get_width();
}
b->draw(ci, o, p_item->cells[i].buttons[j].disabled ? Color(1, 1, 1, 0.5) : p_item->cells[i].buttons[j].color);
- w -= s.width + cache.button_margin;
- bw += s.width + cache.button_margin;
+ w -= s.width + theme_cache.button_margin;
+ bw += s.width + theme_cache.button_margin;
}
- Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - cache.offset + p_draw_ofs, Size2i(w, label_h));
+ Rect2i item_rect = Rect2i(Point2i(ofs, p_pos.y) - theme_cache.offset + p_draw_ofs, Size2i(w, label_h));
Rect2i cell_rect = item_rect;
if (i != 0) {
- cell_rect.position.x -= cache.hseparation;
- cell_rect.size.x += cache.hseparation;
+ cell_rect.position.x -= theme_cache.hseparation;
+ cell_rect.size.x += theme_cache.hseparation;
}
- if (cache.draw_guides) {
+ if (theme_cache.draw_guides) {
Rect2 r = cell_rect;
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(r.position.x, r.position.y + r.size.height), r.position + r.size, cache.guide_color, 1);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(r.position.x, r.position.y + r.size.height), r.position + r.size, theme_cache.guide_color, 1);
}
if (i == 0) {
if (p_item->cells[0].selected && select_mode == SELECT_ROW) {
- Rect2i row_rect = Rect2i(Point2i(cache.bg->get_margin(SIDE_LEFT), item_rect.position.y), Size2i(get_size().width - cache.bg->get_minimum_size().width, item_rect.size.y));
+ Rect2i row_rect = Rect2i(Point2i(theme_cache.bg->get_margin(SIDE_LEFT), item_rect.position.y), Size2i(get_size().width - theme_cache.bg->get_minimum_size().width, item_rect.size.y));
//Rect2 r = Rect2i(row_rect.pos,row_rect.size);
//r.grow(cache.selected->get_margin(SIDE_LEFT));
if (rtl) {
row_rect.position.x = get_size().width - row_rect.position.x - row_rect.size.x;
}
if (has_focus()) {
- cache.selected_focus->draw(ci, row_rect);
+ theme_cache.selected_focus->draw(ci, row_rect);
} else {
- cache.selected->draw(ci, row_rect);
+ theme_cache.selected->draw(ci, row_rect);
}
}
}
@@ -1982,9 +1980,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
if (p_item->cells[i].selected) {
if (has_focus()) {
- cache.selected_focus->draw(ci, r);
+ theme_cache.selected_focus->draw(ci, r);
} else {
- cache.selected->draw(ci, r);
+ theme_cache.selected->draw(ci, r);
}
}
}
@@ -1996,8 +1994,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
r.position.x = p_draw_ofs.x;
r.size.x = w + ofs;
} else {
- r.position.x -= cache.hseparation;
- r.size.x += cache.hseparation;
+ r.position.x -= theme_cache.hseparation;
+ r.size.x += theme_cache.hseparation;
}
if (rtl) {
r.position.x = get_size().width - r.position.x - r.size.x;
@@ -2020,28 +2018,34 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (drop_mode_over == p_item) {
if (drop_mode_section == 0 || drop_mode_section == -1) {
// Line above.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), theme_cache.drop_position_color);
}
if (drop_mode_section == 0) {
// Side lines.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), cache.drop_position_color);
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), theme_cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), theme_cache.drop_position_color);
}
if (drop_mode_section == 0 || (drop_mode_section == 1 && (!p_item->get_first_child() || p_item->is_collapsed()))) {
// Line below.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), theme_cache.drop_position_color);
}
} else if (drop_mode_over == p_item->get_parent()) {
if (drop_mode_section == 1 && !p_item->get_prev() /* && !drop_mode_over->is_collapsed() */) { // The drop_mode_over shouldn't ever be collapsed in here, otherwise we would be drawing a child of a collapsed item.
// Line above.
- RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color);
+ RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), theme_cache.drop_position_color);
}
}
}
- Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_selected_color" : "font_color");
- Color font_outline_color = cache.font_outline_color;
- int outline_size = cache.font_outline_size;
+ Color col;
+ if (p_item->cells[i].custom_color) {
+ col = p_item->cells[i].color;
+ } else {
+ col = p_item->cells[i].selected ? theme_cache.font_selected_color : theme_cache.font_color;
+ }
+
+ Color font_outline_color = theme_cache.font_outline_color;
+ int outline_size = theme_cache.font_outline_size;
Color icon_col = p_item->cells[i].icon_color;
if (p_item->cells[i].dirty) {
@@ -2061,9 +2065,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
draw_item_rect(p_item->cells.write[i], item_rect, col, icon_col, outline_size, font_outline_color);
} break;
case TreeItem::CELL_MODE_CHECK: {
- Ref<Texture2D> checked = cache.checked;
- Ref<Texture2D> unchecked = cache.unchecked;
- Ref<Texture2D> indeterminate = cache.indeterminate;
+ Ref<Texture2D> checked = theme_cache.checked;
+ Ref<Texture2D> unchecked = theme_cache.unchecked;
+ Ref<Texture2D> indeterminate = theme_cache.indeterminate;
Point2i check_ofs = item_rect.position;
check_ofs.y += Math::floor((real_t)(item_rect.size.y - checked->get_height()) / 2);
@@ -2075,7 +2079,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
unchecked->draw(ci, check_ofs);
}
- int check_w = checked->get_width() + cache.hseparation;
+ int check_w = checked->get_width() + theme_cache.hseparation;
text_pos.x += check_w;
@@ -2091,7 +2095,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
break;
}
- Ref<Texture2D> downarrow = cache.select_arrow;
+ Ref<Texture2D> downarrow = theme_cache.select_arrow;
int cell_width = item_rect.size.x - downarrow->get_width();
p_item->cells.write[i].text_buf->set_width(cell_width);
@@ -2113,7 +2117,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
downarrow->draw(ci, arrow_pos);
} else {
- Ref<Texture2D> updown = cache.updown;
+ Ref<Texture2D> updown = theme_cache.updown;
int cell_width = item_rect.size.x - updown->get_width();
@@ -2170,7 +2174,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
break;
}
- Ref<Texture2D> downarrow = cache.select_arrow;
+ Ref<Texture2D> downarrow = theme_cache.select_arrow;
Rect2i ir = item_rect;
@@ -2182,16 +2186,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].custom_button) {
if (cache.hover_item == p_item && cache.hover_cell == i) {
if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
- draw_style_box(cache.custom_button_pressed, ir);
+ draw_style_box(theme_cache.custom_button_pressed, ir);
} else {
- draw_style_box(cache.custom_button_hover, ir);
- col = cache.custom_button_font_highlight;
+ draw_style_box(theme_cache.custom_button_hover, ir);
+ col = theme_cache.custom_button_font_highlight;
}
} else {
- draw_style_box(cache.custom_button, ir);
+ draw_style_box(theme_cache.custom_button, ir);
}
- ir.size -= cache.custom_button->get_minimum_size();
- ir.position += cache.custom_button->get_offset();
+ ir.size -= theme_cache.custom_button->get_minimum_size();
+ ir.position += theme_cache.custom_button->get_offset();
}
draw_item_rect(p_item->cells.write[i], ir, col, icon_col, outline_size, font_outline_color);
@@ -2212,9 +2216,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
cell_rect.position.x = get_size().width - cell_rect.position.x - cell_rect.size.x;
}
if (has_focus()) {
- cache.cursor->draw(ci, cell_rect);
+ theme_cache.cursor->draw(ci, cell_rect);
} else {
- cache.cursor_unfocus->draw(ci, cell_rect);
+ theme_cache.cursor_unfocus->draw(ci, cell_rect);
}
}
}
@@ -2224,13 +2228,17 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
Ref<Texture2D> arrow;
if (p_item->collapsed) {
- arrow = cache.arrow_collapsed;
+ if (is_layout_rtl()) {
+ arrow = theme_cache.arrow_collapsed_mirrored;
+ } else {
+ arrow = theme_cache.arrow_collapsed;
+ }
} else {
- arrow = cache.arrow;
+ arrow = theme_cache.arrow;
}
- Point2 apos = p_pos + Point2i(0, (label_h - arrow->get_height()) / 2) - cache.offset + p_draw_ofs;
- apos.x += cache.item_margin - arrow->get_width();
+ Point2 apos = p_pos + Point2i(0, (label_h - arrow->get_height()) / 2) - theme_cache.offset + p_draw_ofs;
+ apos.x += theme_cache.item_margin - arrow->get_width();
if (rtl) {
apos.x = get_size().width - apos.x - arrow->get_width();
@@ -2243,7 +2251,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
Point2 children_pos = p_pos;
if (!skip) {
- children_pos.x += cache.item_margin;
+ children_pos.x += theme_cache.item_margin;
htotal += label_h;
children_pos.y += htotal;
}
@@ -2251,7 +2259,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (!p_item->collapsed) { /* if not collapsed, check the children */
TreeItem *c = p_item->first_child;
- int base_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
+ int base_ofs = children_pos.y - theme_cache.offset.y + p_draw_ofs.y;
int prev_ofs = base_ofs;
int prev_hl_ofs = base_ofs;
@@ -2262,20 +2270,20 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
// Draw relationship lines.
- if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
- int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
- int parent_ofs = p_pos.x + cache.item_margin;
- Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
+ if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) {
+ int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.hseparation : theme_cache.item_margin);
+ int parent_ofs = p_pos.x + theme_cache.item_margin;
+ Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - theme_cache.offset + p_draw_ofs;
if (c->get_visible_child_count() > 0) {
- root_pos -= Point2i(cache.arrow->get_width(), 0);
+ root_pos -= Point2i(theme_cache.arrow->get_width(), 0);
}
- float line_width = cache.relationship_line_width * Math::round(cache.base_scale);
- float parent_line_width = cache.parent_hl_line_width * Math::round(cache.base_scale);
- float children_line_width = cache.children_hl_line_width * Math::round(cache.base_scale);
+ float line_width = theme_cache.relationship_line_width * Math::round(theme_cache.base_scale);
+ float parent_line_width = theme_cache.parent_hl_line_width * Math::round(theme_cache.base_scale);
+ float children_line_width = theme_cache.children_hl_line_width * Math::round(theme_cache.base_scale);
- Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
+ Point2i parent_pos = Point2i(parent_ofs - theme_cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + theme_cache.arrow->get_height() / 2) - theme_cache.offset + p_draw_ofs;
int more_prev_ofs = 0;
@@ -2289,43 +2297,43 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (_is_branch_selected(c)) {
// If this item or one of its children is selected, we draw the line using parent highlight style.
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), theme_cache.parent_hl_line_color, parent_line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
- more_prev_ofs = cache.parent_hl_line_margin;
+ more_prev_ofs = theme_cache.parent_hl_line_margin;
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} else if (p_item->is_selected(0)) {
// If parent item is selected (but this item is not), we draw the line using children highlight style.
// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
if (_is_sibling_branch_selected(c)) {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), theme_cache.children_hl_line_color, children_line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} else {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), theme_cache.children_hl_line_color, children_line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), cache.children_hl_line_color, children_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), theme_cache.children_hl_line_color, children_line_width);
}
} else {
// If nothing of the above is true, we draw the line using normal style.
// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
if (_is_sibling_branch_selected(c)) {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + cache.parent_hl_line_margin, root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + theme_cache.parent_hl_line_margin, root_pos.y), theme_cache.relationship_line_color, line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} else {
if (htotal >= 0) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), theme_cache.relationship_line_color, line_width);
}
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), cache.relationship_line_color, line_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), theme_cache.relationship_line_color, line_width);
}
}
}
@@ -2338,12 +2346,12 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
break; // Last loop done, stop.
}
- if (cache.draw_relationship_lines == 0) {
+ if (theme_cache.draw_relationship_lines == 0) {
return -1; // No need to draw anymore, full stop.
}
htotal = -1;
- children_pos.y = cache.offset.y + p_draw_size.height;
+ children_pos.y = theme_cache.offset.y + p_draw_size.height;
} else {
htotal += child_h;
children_pos.y += child_h;
@@ -2494,7 +2502,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
void Tree::_range_click_timeout() {
if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) {
- Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
+ Point2 pos = get_local_mouse_position() - theme_cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
@@ -2512,7 +2520,7 @@ void Tree::_range_click_timeout() {
Ref<InputEventMouseButton> mb;
mb.instantiate();
- int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ int x_limit = get_size().width - theme_cache.bg->get_minimum_size().width;
if (h_scroll->is_visible()) {
x_limit -= h_scroll->get_minimum_size().width;
}
@@ -2521,7 +2529,7 @@ void Tree::_range_click_timeout() {
propagate_mouse_activated = false; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, false, root, MouseButton::LEFT, mb);
+ propagate_mouse_event(pos + theme_cache.offset, 0, 0, x_limit + theme_cache.offset.width, false, root, MouseButton::LEFT, mb);
blocked--;
if (range_click_timer->is_one_shot()) {
@@ -2550,7 +2558,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return 0;
}
- int item_h = compute_item_height(p_item) + cache.vseparation;
+ int item_h = compute_item_height(p_item) + theme_cache.vseparation;
bool skip = (p_item == root && hide_root);
@@ -2561,7 +2569,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return -1;
}
- if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + cache.item_margin))) {
+ if (!p_item->disable_folding && !hide_folding && p_item->first_child && (p_pos.x >= x_ofs && p_pos.x < (x_ofs + theme_cache.item_margin))) {
p_item->set_collapsed(!p_item->is_collapsed());
return -1;
}
@@ -2580,7 +2588,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (p_item->cells[i].expand_right) {
int plus = 1;
while (i + plus < columns.size() && !p_item->cells[i + plus].editable && p_item->cells[i + plus].mode == TreeItem::CELL_MODE_STRING && p_item->cells[i + plus].text.is_empty() && p_item->cells[i + plus].icon.is_null()) {
- col_width += cache.hseparation;
+ col_width += theme_cache.hseparation;
col_width += get_column_width(i + plus);
plus++;
}
@@ -2600,16 +2608,16 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
if (col == -1) {
return -1;
} else if (col == 0) {
- int margin = x_ofs + cache.item_margin; //-cache.hseparation;
- //int lm = cache.bg->get_margin(SIDE_LEFT);
+ int margin = x_ofs + theme_cache.item_margin; //-theme_cache.hseparation;
+ //int lm = theme_cache.bg->get_margin(SIDE_LEFT);
col_width -= margin;
limit_w -= margin;
col_ofs += margin;
x -= margin;
} else {
- col_width -= cache.hseparation;
- limit_w -= cache.hseparation;
- x -= cache.hseparation;
+ col_width -= theme_cache.hseparation;
+ limit_w -= theme_cache.hseparation;
+ x -= theme_cache.hseparation;
}
if (!p_item->disable_folding && !hide_folding && !p_item->cells[col].editable && !p_item->cells[col].selectable && p_item->get_first_child()) {
@@ -2626,7 +2634,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
int button_w = 0;
for (int j = p_item->cells[col].buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = p_item->cells[col].buttons[j].texture;
- button_w += b->get_size().width + cache.button_pressed->get_minimum_size().width + cache.button_margin;
+ button_w += b->get_size().width + theme_cache.button_pressed->get_minimum_size().width + theme_cache.button_margin;
}
col_width = MAX(button_w, MIN(limit_w, col_width));
@@ -2634,7 +2642,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- int w = b->get_size().width + cache.button_pressed->get_minimum_size().width;
+ int w = b->get_size().width + theme_cache.button_pressed->get_minimum_size().width;
if (x > col_width - w) {
if (c.buttons[j].disabled) {
@@ -2662,7 +2670,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
return -1;
}
- col_width -= w + cache.button_margin;
+ col_width -= w + theme_cache.button_margin;
}
if (p_button == MouseButton::LEFT || (p_button == MouseButton::RIGHT && allow_rmb_select)) {
@@ -2742,7 +2750,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
case TreeItem::CELL_MODE_CHECK: {
bring_up_editor = false; //checkboxes are not edited with editor
if (force_edit_checkbox_only_on_checkbox) {
- if (x < cache.checked->get_width()) {
+ if (x < theme_cache.checked->get_width()) {
p_item->set_checked(col, !c.checked);
item_edited(col, p_item, p_button);
}
@@ -2764,7 +2772,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
popup_menu->set_size(Size2(col_width, 0));
- popup_menu->set_position(get_screen_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - cache.offset);
+ popup_menu->set_position(get_screen_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h) - theme_cache.offset);
popup_menu->popup();
popup_edited_item = p_item;
popup_edited_item_col = col;
@@ -2822,9 +2830,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
case TreeItem::CELL_MODE_CUSTOM: {
edited_item = p_item;
edited_col = col;
- bool on_arrow = x > col_width - cache.select_arrow->get_width();
+ bool on_arrow = x > col_width - theme_cache.select_arrow->get_width();
- custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - cache.offset.y), Size2(get_column_width(col), item_h));
+ custom_popup_rect = Rect2i(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs + item_h - theme_cache.offset.y), Size2(get_column_width(col), item_h));
if (on_arrow || !p_item->cells[col].custom_button) {
emit_signal(SNAME("custom_popup_edited"), ((bool)(x >= (col_width - item_h / 2))));
@@ -2846,7 +2854,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
popup_pressing_edited_item = p_item;
popup_pressing_edited_item_column = col;
- pressing_item_rect = Rect2(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - cache.offset, Size2(col_width, item_h));
+ pressing_item_rect = Rect2(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - theme_cache.offset, Size2(col_width, item_h));
pressing_for_editor_text = editor_text;
pressing_for_editor = true;
@@ -2855,8 +2863,8 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
Point2i new_pos = p_pos;
if (!skip) {
- x_ofs += cache.item_margin;
- //new_pos.x-=cache.item_margin;
+ x_ofs += theme_cache.item_margin;
+ //new_pos.x-=theme_cache.item_margin;
y_ofs += item_h;
new_pos.y -= item_h;
}
@@ -3300,18 +3308,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
- update_cache();
- }
-
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
bool rtl = is_layout_rtl();
Point2 pos = mm->get_position();
if (rtl) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
Cache::ClickType old_hover = cache.hover_type;
int old_index = cache.hover_index;
@@ -3321,7 +3325,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (show_column_titles) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- pos.x += cache.offset.x;
+ pos.x += theme_cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
@@ -3339,7 +3343,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (rtl) {
mpos.x = get_size().width - mpos.x;
}
- mpos -= cache.bg->get_offset();
+ mpos -= theme_cache.bg->get_offset();
mpos.y -= _get_title_button_height();
if (mpos.y >= 0) {
if (h_scroll->is_visible_in_tree()) {
@@ -3430,10 +3434,6 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
- update_cache();
- }
-
bool rtl = is_layout_rtl();
if (!mb->is_pressed()) {
@@ -3443,12 +3443,12 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
if (rtl) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- pos.x += cache.offset.x;
+ pos.x += theme_cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
@@ -3537,7 +3537,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
switch (mb->get_button_index()) {
case MouseButton::RIGHT:
case MouseButton::LEFT: {
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
Point2 pos = mb->get_position();
if (rtl) {
@@ -3549,7 +3549,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
pos.y -= _get_title_button_height();
if (pos.y < 0) {
- pos.x += cache.offset.x;
+ pos.x += theme_cache.offset.x;
int len = 0;
for (int i = 0; i < columns.size(); i++) {
len += get_column_width(i);
@@ -3572,14 +3572,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
pressing_for_editor = false;
propagate_mouse_activated = false;
- int x_limit = get_size().width - cache.bg->get_minimum_size().width;
+ int x_limit = get_size().width - theme_cache.bg->get_minimum_size().width;
if (h_scroll->is_visible()) {
x_limit -= h_scroll->get_minimum_size().width;
}
cache.rtl = is_layout_rtl();
blocked++;
- propagate_mouse_event(pos + cache.offset, 0, 0, x_limit + cache.offset.width, mb->is_double_click(), root, mb->get_button_index(), mb);
+ propagate_mouse_event(pos + theme_cache.offset, 0, 0, x_limit + theme_cache.offset.width, mb->is_double_click(), root, mb->get_button_index(), mb);
blocked--;
if (pressing_for_editor) {
@@ -3766,7 +3766,7 @@ bool Tree::is_editing() {
}
Size2 Tree::get_internal_min_size() const {
- Size2i size = cache.bg->get_offset();
+ Size2i size = theme_cache.bg->get_offset();
if (root) {
size.height += get_item_height(root);
}
@@ -3789,23 +3789,23 @@ void Tree::update_scrollbars() {
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
- v_scroll->set_begin(Point2(size.width - vmin.width, cache.bg->get_margin(SIDE_TOP)));
- v_scroll->set_end(Point2(size.width, size.height - cache.bg->get_margin(SIDE_TOP) - cache.bg->get_margin(SIDE_BOTTOM)));
+ v_scroll->set_begin(Point2(size.width - vmin.width, theme_cache.bg->get_margin(SIDE_TOP)));
+ v_scroll->set_end(Point2(size.width, size.height - theme_cache.bg->get_margin(SIDE_TOP) - theme_cache.bg->get_margin(SIDE_BOTTOM)));
h_scroll->set_begin(Point2(0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - vmin.width, size.height));
Size2 internal_min_size = get_internal_min_size();
- bool display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) > size.height;
- bool display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) > size.width;
+ bool display_vscroll = internal_min_size.height + theme_cache.bg->get_margin(SIDE_TOP) > size.height;
+ bool display_hscroll = internal_min_size.width + theme_cache.bg->get_margin(SIDE_LEFT) > size.width;
for (int i = 0; i < 2; i++) {
// Check twice, as both values are dependent on each other.
if (display_hscroll) {
- display_vscroll = internal_min_size.height + cache.bg->get_margin(SIDE_TOP) + hmin.height > size.height;
+ display_vscroll = internal_min_size.height + theme_cache.bg->get_margin(SIDE_TOP) + hmin.height > size.height;
}
if (display_vscroll) {
- display_hscroll = internal_min_size.width + cache.bg->get_margin(SIDE_LEFT) + vmin.width > size.width;
+ display_hscroll = internal_min_size.width + theme_cache.bg->get_margin(SIDE_LEFT) + vmin.width > size.width;
}
}
@@ -3813,29 +3813,29 @@ void Tree::update_scrollbars() {
v_scroll->show();
v_scroll->set_max(internal_min_size.height);
v_scroll->set_page(size.height - hmin.height - tbh);
- cache.offset.y = v_scroll->get_value();
+ theme_cache.offset.y = v_scroll->get_value();
} else {
v_scroll->hide();
- cache.offset.y = 0;
+ theme_cache.offset.y = 0;
}
if (display_hscroll) {
h_scroll->show();
h_scroll->set_max(internal_min_size.width);
h_scroll->set_page(size.width - vmin.width);
- cache.offset.x = h_scroll->get_value();
+ theme_cache.offset.x = h_scroll->get_value();
} else {
h_scroll->hide();
- cache.offset.x = 0;
+ theme_cache.offset.x = 0;
}
}
int Tree::_get_title_button_height() const {
- ERR_FAIL_COND_V(cache.font.is_null() || cache.title_button.is_null(), 0);
+ ERR_FAIL_COND_V(theme_cache.font.is_null() || theme_cache.title_button.is_null(), 0);
int h = 0;
if (show_column_titles) {
for (int i = 0; i < columns.size(); i++) {
- h = MAX(h, columns[i].text_buf->get_size().y + cache.title_button->get_minimum_size().height);
+ h = MAX(h, columns[i].text_buf->get_size().y + theme_cache.title_button->get_minimum_size().height);
}
}
return h;
@@ -3860,10 +3860,6 @@ void Tree::_notification(int p_what) {
drag_touching = false;
} break;
- case NOTIFICATION_ENTER_TREE: {
- update_cache();
- } break;
-
case NOTIFICATION_DRAG_END: {
drop_mode_flags = 0;
scrolling = false;
@@ -3873,7 +3869,7 @@ void Tree::_notification(int p_what) {
case NOTIFICATION_DRAG_BEGIN: {
single_select_defer = nullptr;
- if (cache.scroll_speed > 0) {
+ if (theme_cache.scroll_speed > 0) {
scrolling = true;
set_physics_process_internal(true);
}
@@ -3917,22 +3913,22 @@ void Tree::_notification(int p_what) {
}
Point2 mouse_position = get_viewport()->get_mouse_position() - get_global_position();
- if (scrolling && get_rect().grow(cache.scroll_border).has_point(mouse_position)) {
+ if (scrolling && get_rect().grow(theme_cache.scroll_border).has_point(mouse_position)) {
Point2 point;
- if ((ABS(mouse_position.x) < ABS(mouse_position.x - get_size().width)) && (ABS(mouse_position.x) < cache.scroll_border)) {
- point.x = mouse_position.x - cache.scroll_border;
- } else if (ABS(mouse_position.x - get_size().width) < cache.scroll_border) {
- point.x = mouse_position.x - (get_size().width - cache.scroll_border);
+ if ((ABS(mouse_position.x) < ABS(mouse_position.x - get_size().width)) && (ABS(mouse_position.x) < theme_cache.scroll_border)) {
+ point.x = mouse_position.x - theme_cache.scroll_border;
+ } else if (ABS(mouse_position.x - get_size().width) < theme_cache.scroll_border) {
+ point.x = mouse_position.x - (get_size().width - theme_cache.scroll_border);
}
- if ((ABS(mouse_position.y) < ABS(mouse_position.y - get_size().height)) && (ABS(mouse_position.y) < cache.scroll_border)) {
- point.y = mouse_position.y - cache.scroll_border;
- } else if (ABS(mouse_position.y - get_size().height) < cache.scroll_border) {
- point.y = mouse_position.y - (get_size().height - cache.scroll_border);
+ if ((ABS(mouse_position.y) < ABS(mouse_position.y - get_size().height)) && (ABS(mouse_position.y) < theme_cache.scroll_border)) {
+ point.y = mouse_position.y - theme_cache.scroll_border;
+ } else if (ABS(mouse_position.y - get_size().height) < theme_cache.scroll_border) {
+ point.y = mouse_position.y - (get_size().height - theme_cache.scroll_border);
}
- point *= cache.scroll_speed * get_physics_process_delta_time();
+ point *= theme_cache.scroll_speed * get_physics_process_delta_time();
point += get_scroll();
h_scroll->set_value(point.x);
v_scroll->set_value(point.y);
@@ -3940,13 +3936,12 @@ void Tree::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
- update_cache();
+ v_scroll->set_custom_step(theme_cache.font->get_height(theme_cache.font_size));
+
update_scrollbars();
RID ci = get_canvas_item();
- Ref<StyleBox> bg = cache.bg;
- Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
- int outline_size = get_theme_constant(SNAME("outline_size"));
+ Ref<StyleBox> bg = theme_cache.bg;
Point2 draw_ofs;
draw_ofs += bg->get_offset();
@@ -3970,11 +3965,11 @@ void Tree::_notification(int p_what) {
if (show_column_titles) {
//title buttons
- int ofs2 = cache.bg->get_margin(SIDE_LEFT);
+ int ofs2 = theme_cache.bg->get_margin(SIDE_LEFT);
for (int i = 0; i < columns.size(); i++) {
- Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? cache.title_button_hover : cache.title_button);
- Ref<Font> f = cache.tb_font;
- Rect2 tbrect = Rect2(ofs2 - cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
+ Ref<StyleBox> sb = (cache.click_type == Cache::CLICK_TITLE && cache.click_index == i) ? theme_cache.title_button_pressed : ((cache.hover_type == Cache::CLICK_TITLE && cache.hover_index == i) ? theme_cache.title_button_hover : theme_cache.title_button);
+ Ref<Font> f = theme_cache.tb_font;
+ Rect2 tbrect = Rect2(ofs2 - theme_cache.offset.x, bg->get_margin(SIDE_TOP), get_column_width(i), tbh);
if (cache.rtl) {
tbrect.position.x = get_size().width - tbrect.size.x - tbrect.position.x;
}
@@ -3985,10 +3980,10 @@ void Tree::_notification(int p_what) {
columns.write[i].text_buf->set_width(clip_w);
Vector2 text_pos = tbrect.position + Point2i(sb->get_offset().x + (tbrect.size.width - columns[i].text_buf->get_size().x) / 2, (tbrect.size.height - columns[i].text_buf->get_size().y) / 2);
- if (outline_size > 0 && font_outline_color.a > 0) {
- columns[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
+ columns[i].text_buf->draw_outline(ci, text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
}
- columns[i].text_buf->draw(ci, text_pos, cache.title_button_color);
+ columns[i].text_buf->draw(ci, text_pos, theme_cache.title_button_color);
}
}
@@ -3996,8 +3991,7 @@ void Tree::_notification(int p_what) {
// Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- const Ref<StyleBox> bg_focus = get_theme_stylebox(SNAME("bg_focus"));
- bg_focus->draw(ci, Rect2(Point2(), get_size()));
+ theme_cache.bg_focus->draw(ci, Rect2(Point2(), get_size()));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
} break;
@@ -4005,7 +3999,6 @@ void Tree::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED: {
- update_cache();
_update_all();
} break;
@@ -4040,7 +4033,7 @@ Size2 Tree::get_minimum_size() const {
return Size2();
} else {
Vector2 min_size = get_internal_min_size();
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
if (bg.is_valid()) {
min_size.x += bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
min_size.y += bg->get_margin(SIDE_TOP) + bg->get_margin(SIDE_BOTTOM);
@@ -4336,7 +4329,7 @@ int Tree::get_column_minimum_width(int p_column) const {
// Check if the visible title of the column is wider.
if (show_column_titles) {
- min_width = MAX(cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, cache.font_size).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
+ min_width = MAX(theme_cache.font->get_string_size(columns[p_column].title, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + theme_cache.bg->get_margin(SIDE_LEFT) + theme_cache.bg->get_margin(SIDE_RIGHT), min_width);
}
if (!columns[p_column].clip_content) {
@@ -4360,9 +4353,9 @@ int Tree::get_column_minimum_width(int p_column) const {
// Get the item minimum size.
Size2 item_size = item->get_minimum_size(p_column);
if (p_column == 0) {
- item_size.width += cache.item_margin * depth;
+ item_size.width += theme_cache.item_margin * depth;
} else {
- item_size.width += cache.hseparation;
+ item_size.width += theme_cache.hseparation;
}
// Check if the item is wider.
@@ -4381,7 +4374,7 @@ int Tree::get_column_width(int p_column) const {
if (columns[p_column].expand) {
int expand_area = get_size().width;
- Ref<StyleBox> bg = cache.bg;
+ Ref<StyleBox> bg = theme_cache.bg;
if (bg.is_valid()) {
expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT);
@@ -4458,7 +4451,7 @@ int Tree::get_item_offset(TreeItem *p_item) const {
ofs += compute_item_height(it);
if (it != root || !hide_root) {
- ofs += cache.vseparation;
+ ofs += theme_cache.vseparation;
}
if (it->first_child && !it->collapsed) {
@@ -4489,14 +4482,14 @@ void Tree::ensure_cursor_is_visible() {
return; // Nothing under cursor.
}
- const Size2 area_size = get_size() - cache.bg->get_minimum_size();
+ const Size2 area_size = get_size() - theme_cache.bg->get_minimum_size();
int y_offset = get_item_offset(selected_item);
if (y_offset != -1) {
const int tbh = _get_title_button_height();
y_offset -= tbh;
- const int cell_h = compute_item_height(selected_item) + cache.vseparation;
+ const int cell_h = compute_item_height(selected_item) + theme_cache.vseparation;
const int screen_h = area_size.height - h_scroll->get_combined_minimum_size().height - tbh;
if (cell_h > screen_h) { // Screen size is too small, maybe it was not resized yet.
@@ -4563,7 +4556,7 @@ Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column, int p_button) const {
Vector2 ofst = Vector2(r.position.x + r.size.x, r.position.y);
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size();
ofst.x -= size.x;
if (j == p_button) {
@@ -4596,9 +4589,6 @@ void Tree::set_column_title(int p_column, const String &p_title) {
return;
}
- if (cache.font.is_null()) { // avoid a strange case that may corrupt stuff
- update_cache();
- }
columns.write[p_column].title = p_title;
update_column(p_column);
queue_redraw();
@@ -4660,7 +4650,7 @@ void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
const real_t tree_height = get_size().y;
const Rect2 item_rect = get_item_rect(p_item);
const real_t item_y = item_rect.position.y;
- const real_t item_height = item_rect.size.y + cache.vseparation;
+ const real_t item_height = item_rect.size.y + theme_cache.vseparation;
if (p_center_on_item) {
v_scroll->set_value(item_y - (tree_height - item_height) / 2.0f);
@@ -4784,7 +4774,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
Point2 pos = p_pos;
if ((root != p_item || !hide_root) && p_item->is_visible()) {
- h = compute_item_height(p_item) + cache.vseparation;
+ h = compute_item_height(p_item) + theme_cache.vseparation;
if (pos.y < h) {
if (drop_mode_flags == DROP_MODE_ON_ITEM) {
section = 0;
@@ -4841,7 +4831,7 @@ int Tree::get_column_at_position(const Point2 &p_pos) const {
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return -1;
@@ -4871,7 +4861,7 @@ int Tree::get_drop_section_at_position(const Point2 &p_pos) const {
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return -100;
@@ -4901,7 +4891,7 @@ TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const {
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return nullptr;
@@ -4928,7 +4918,7 @@ TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const {
int Tree::get_button_id_at_position(const Point2 &p_pos) const {
if (root) {
Point2 pos = p_pos;
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return -1;
@@ -4954,7 +4944,7 @@ int Tree::get_button_id_at_position(const Point2 &p_pos) const {
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size();
if (pos.x > col_width - size.width) {
return c.buttons[j].id;
}
@@ -4969,7 +4959,7 @@ int Tree::get_button_id_at_position(const Point2 &p_pos) const {
String Tree::get_tooltip(const Point2 &p_pos) const {
if (root) {
Point2 pos = p_pos;
- pos -= cache.bg->get_offset();
+ pos -= theme_cache.bg->get_offset();
pos.y -= _get_title_button_height();
if (pos.y < 0) {
return Control::get_tooltip(p_pos);
@@ -4995,7 +4985,7 @@ String Tree::get_tooltip(const Point2 &p_pos) const {
for (int j = c.buttons.size() - 1; j >= 0; j--) {
Ref<Texture2D> b = c.buttons[j].texture;
- Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ Size2 size = b->get_size() + theme_cache.button_pressed->get_minimum_size();
if (pos.x > col_width - size.width) {
String tooltip = c.buttons[j].tooltip;
if (!tooltip.is_empty()) {
@@ -5231,8 +5221,6 @@ Tree::Tree() {
set_mouse_filter(MOUSE_FILTER_STOP);
set_clip_contents(true);
-
- update_cache();
}
Tree::~Tree() {
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 8eabdd60a1..b4ee686bab 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -482,12 +482,13 @@ private:
void propagate_set_columns(TreeItem *p_item);
- struct Cache {
+ struct ThemeCache {
Ref<Font> font;
Ref<Font> tb_font;
int font_size = 0;
int tb_font_size = 0;
Ref<StyleBox> bg;
+ Ref<StyleBox> bg_focus;
Ref<StyleBox> selected;
Ref<StyleBox> selected_focus;
Ref<StyleBox> cursor;
@@ -505,8 +506,9 @@ private:
Ref<Texture2D> checked;
Ref<Texture2D> unchecked;
Ref<Texture2D> indeterminate;
- Ref<Texture2D> arrow_collapsed;
Ref<Texture2D> arrow;
+ Ref<Texture2D> arrow_collapsed;
+ Ref<Texture2D> arrow_collapsed_mirrored;
Ref<Texture2D> select_arrow;
Ref<Texture2D> updown;
@@ -536,7 +538,9 @@ private:
int scroll_border = 0;
int scroll_speed = 0;
int font_outline_size = 0;
+ } theme_cache;
+ struct Cache {
enum ClickType {
CLICK_NONE,
CLICK_TITLE,
@@ -559,7 +563,6 @@ private:
Point2i text_editor_position;
bool rtl = false;
-
} cache;
int _get_title_button_height() const;
@@ -572,7 +575,6 @@ private:
bool v_scroll_enabled = true;
Size2 get_internal_min_size() const;
- void update_cache();
void update_scrollbars();
Rect2 search_item_rect(TreeItem *p_from, TreeItem *p_item);
@@ -620,6 +622,8 @@ private:
bool _scroll(bool p_horizontal, float p_pages);
protected:
+ virtual void _update_theme_item_cache() override;
+
static void _bind_methods();
public:
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 61a7600664..65e7ba3e67 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -338,6 +338,7 @@ void CanvasItem::_notification(int p_what) {
}
if (window) {
window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
+ window = nullptr;
}
global_invalid = true;
parent_visible_in_tree = false;
diff --git a/scene/main/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp
index aad5baccab..9b63118f7c 100644
--- a/scene/main/multiplayer_peer.cpp
+++ b/scene/main/multiplayer_peer.cpp
@@ -120,19 +120,10 @@ void MultiplayerPeer::_bind_methods() {
/*************/
-int MultiplayerPeerExtension::get_available_packet_count() const {
- int count;
- if (GDVIRTUAL_CALL(_get_available_packet_count, count)) {
- return count;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_available_packet_count is unimplemented!");
- return -1;
-}
-
Error MultiplayerPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
- int err;
+ Error err;
if (GDVIRTUAL_CALL(_get_packet, r_buffer, &r_buffer_size, err)) {
- return (Error)err;
+ return err;
}
if (GDVIRTUAL_IS_OVERRIDDEN(_get_packet_script)) {
if (!GDVIRTUAL_CALL(_get_packet_script, script_buffer)) {
@@ -153,9 +144,9 @@ Error MultiplayerPeerExtension::get_packet(const uint8_t **r_buffer, int &r_buff
}
Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
- int err;
+ Error err;
if (GDVIRTUAL_CALL(_put_packet, p_buffer, p_buffer_size, err)) {
- return (Error)err;
+ return err;
}
if (GDVIRTUAL_IS_OVERRIDDEN(_put_packet_script)) {
PackedByteArray a;
@@ -171,87 +162,6 @@ Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer
return FAILED;
}
-int MultiplayerPeerExtension::get_max_packet_size() const {
- int size;
- if (GDVIRTUAL_CALL(_get_max_packet_size, size)) {
- return size;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_max_packet_size is unimplemented!");
- return 0;
-}
-
-void MultiplayerPeerExtension::set_transfer_channel(int p_channel) {
- if (GDVIRTUAL_CALL(_set_transfer_channel, p_channel)) {
- return;
- }
- MultiplayerPeer::set_transfer_channel(p_channel);
-}
-
-int MultiplayerPeerExtension::get_transfer_channel() const {
- int channel;
- if (GDVIRTUAL_CALL(_get_transfer_channel, channel)) {
- return channel;
- }
- return MultiplayerPeer::get_transfer_channel();
-}
-
-void MultiplayerPeerExtension::set_transfer_mode(TransferMode p_mode) {
- if (GDVIRTUAL_CALL(_set_transfer_mode, p_mode)) {
- return;
- }
- MultiplayerPeer::set_transfer_mode(p_mode);
-}
-
-MultiplayerPeer::TransferMode MultiplayerPeerExtension::get_transfer_mode() const {
- int mode;
- if (GDVIRTUAL_CALL(_get_transfer_mode, mode)) {
- return (MultiplayerPeer::TransferMode)mode;
- }
- return MultiplayerPeer::get_transfer_mode();
-}
-
-void MultiplayerPeerExtension::set_target_peer(int p_peer_id) {
- if (GDVIRTUAL_CALL(_set_target_peer, p_peer_id)) {
- return;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_set_target_peer is unimplemented!");
-}
-
-int MultiplayerPeerExtension::get_packet_peer() const {
- int peer;
- if (GDVIRTUAL_CALL(_get_packet_peer, peer)) {
- return peer;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_packet_peer is unimplemented!");
- return 0;
-}
-
-bool MultiplayerPeerExtension::is_server() const {
- bool server;
- if (GDVIRTUAL_CALL(_is_server, server)) {
- return server;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_is_server is unimplemented!");
- return false;
-}
-
-void MultiplayerPeerExtension::poll() {
- int err;
- if (GDVIRTUAL_CALL(_poll, err)) {
- return;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_poll is unimplemented!");
-}
-
-int MultiplayerPeerExtension::get_unique_id() const {
- int id;
- if (GDVIRTUAL_CALL(_get_unique_id, id)) {
- return id;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_unique_id is unimplemented!");
- return 0;
-}
-
void MultiplayerPeerExtension::set_refuse_new_connections(bool p_enable) {
if (GDVIRTUAL_CALL(_set_refuse_new_connections, p_enable)) {
return;
@@ -267,15 +177,6 @@ bool MultiplayerPeerExtension::is_refusing_new_connections() const {
return MultiplayerPeer::is_refusing_new_connections();
}
-MultiplayerPeer::ConnectionStatus MultiplayerPeerExtension::get_connection_status() const {
- int status;
- if (GDVIRTUAL_CALL(_get_connection_status, status)) {
- return (ConnectionStatus)status;
- }
- WARN_PRINT_ONCE("MultiplayerPeerExtension::_get_connection_status is unimplemented!");
- return CONNECTION_DISCONNECTED;
-}
-
void MultiplayerPeerExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_packet, "r_buffer", "r_buffer_size");
GDVIRTUAL_BIND(_put_packet, "p_buffer", "p_buffer_size");
@@ -300,4 +201,7 @@ void MultiplayerPeerExtension::_bind_methods() {
GDVIRTUAL_BIND(_set_refuse_new_connections, "p_enable");
GDVIRTUAL_BIND(_is_refusing_new_connections);
GDVIRTUAL_BIND(_get_connection_status);
+
+ ADD_PROPERTY_DEFAULT("transfer_mode", TRANSFER_MODE_RELIABLE);
+ ADD_PROPERTY_DEFAULT("transfer_channel", 0);
}
diff --git a/scene/main/multiplayer_peer.h b/scene/main/multiplayer_peer.h
index 8a012d7520..ab7483ece5 100644
--- a/scene/main/multiplayer_peer.h
+++ b/scene/main/multiplayer_peer.h
@@ -33,6 +33,7 @@
#include "core/io/packet_peer.h"
+#include "core/extension/ext_wrappers.gen.inc"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/script_language.h"
#include "core/variant/native_ptr.h"
@@ -103,55 +104,35 @@ protected:
PackedByteArray script_buffer;
public:
- /* PacketPeer */
- virtual int get_available_packet_count() const override;
+ /* PacketPeer extension */
virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) override; ///< buffer is GONE after next get_packet
- virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
- virtual int get_max_packet_size() const override;
-
- /* MultiplayerPeer */
- virtual void set_transfer_channel(int p_channel) override;
- virtual int get_transfer_channel() const override;
- virtual void set_transfer_mode(TransferMode p_mode) override;
- virtual TransferMode get_transfer_mode() const override;
- virtual void set_target_peer(int p_peer_id) override;
-
- virtual int get_packet_peer() const override;
-
- virtual bool is_server() const override;
+ GDVIRTUAL2R(Error, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
+ GDVIRTUAL0R(PackedByteArray, _get_packet_script); // For GDScript.
- virtual void poll() override;
+ virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
+ GDVIRTUAL2R(Error, _put_packet, GDNativeConstPtr<const uint8_t>, int);
+ GDVIRTUAL1R(Error, _put_packet_script, PackedByteArray); // For GDScript.
- virtual int get_unique_id() const override;
+ EXBIND0RC(int, get_available_packet_count);
+ EXBIND0RC(int, get_max_packet_size);
+ /* MultiplayerPeer extension */
virtual void set_refuse_new_connections(bool p_enable) override;
- virtual bool is_refusing_new_connections() const override;
+ GDVIRTUAL1(_set_refuse_new_connections, bool); // Optional.
- virtual ConnectionStatus get_connection_status() const override;
-
- /* PacketPeer GDExtension */
- GDVIRTUAL0RC(int, _get_available_packet_count);
- GDVIRTUAL2R(int, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>);
- GDVIRTUAL2R(int, _put_packet, GDNativeConstPtr<const uint8_t>, int);
- GDVIRTUAL0RC(int, _get_max_packet_size);
-
- /* PacketPeer GDScript */
- GDVIRTUAL0R(PackedByteArray, _get_packet_script);
- GDVIRTUAL1R(int, _put_packet_script, PackedByteArray);
-
- /* MultiplayerPeer GDExtension */
- GDVIRTUAL1(_set_transfer_channel, int);
- GDVIRTUAL0RC(int, _get_transfer_channel);
- GDVIRTUAL1(_set_transfer_mode, int);
- GDVIRTUAL0RC(int, _get_transfer_mode);
- GDVIRTUAL1(_set_target_peer, int);
- GDVIRTUAL0RC(int, _get_packet_peer);
- GDVIRTUAL0RC(bool, _is_server);
- GDVIRTUAL0R(int, _poll);
- GDVIRTUAL0RC(int, _get_unique_id);
- GDVIRTUAL1(_set_refuse_new_connections, bool);
- GDVIRTUAL0RC(bool, _is_refusing_new_connections);
- GDVIRTUAL0RC(int, _get_connection_status);
+ virtual bool is_refusing_new_connections() const override;
+ GDVIRTUAL0RC(bool, _is_refusing_new_connections); // Optional.
+
+ EXBIND1(set_transfer_channel, int);
+ EXBIND0RC(int, get_transfer_channel);
+ EXBIND1(set_transfer_mode, TransferMode);
+ EXBIND0RC(TransferMode, get_transfer_mode);
+ EXBIND1(set_target_peer, int);
+ EXBIND0RC(int, get_packet_peer);
+ EXBIND0RC(bool, is_server);
+ EXBIND0(poll);
+ EXBIND0RC(int, get_unique_id);
+ EXBIND0RC(ConnectionStatus, get_connection_status);
};
#endif // MULTIPLAYER_PEER_H
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index ec98ff36a0..268b381029 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -46,6 +46,7 @@
#include "scene/debugger/scene_debugger.h"
#include "scene/main/multiplayer_api.h"
#include "scene/main/viewport.h"
+#include "scene/resources/environment.h"
#include "scene/resources/font.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
@@ -1472,18 +1473,18 @@ SceneTree::SceneTree() {
}
}
- int shadowmap_size = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size", 4096);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_size.mobile", 2048);
- bool shadowmap_16_bits = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_16_bits", true);
- int atlas_q0 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", 2);
- int atlas_q1 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", 2);
- int atlas_q2 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", 3);
- int atlas_q3 = GLOBAL_DEF("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", 4);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ int shadowmap_size = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size", 4096);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_size", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"));
+ GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_size.mobile", 2048);
+ bool shadowmap_16_bits = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_16_bits", true);
+ int atlas_q0 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", 2);
+ int atlas_q1 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", 2);
+ int atlas_q2 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", 3);
+ int atlas_q3 = GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", 4);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
root->set_positional_shadow_atlas_size(shadowmap_size);
root->set_positional_shadow_atlas_16_bits(shadowmap_16_bits);
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index a621aea9c8..13034c5447 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -64,9 +64,9 @@ bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_valu
if (active) {
if (o->override.get_type() == Variant::OBJECT) {
RID tex_rid = p_value;
- RS::get_singleton()->global_shader_uniform_set_override(*r, tex_rid);
+ RS::get_singleton()->global_shader_parameter_set_override(*r, tex_rid);
} else {
- RS::get_singleton()->global_shader_uniform_set_override(*r, p_value);
+ RS::get_singleton()->global_shader_parameter_set_override(*r, p_value);
}
}
o->in_use = p_value.get_type() != Variant::NIL;
@@ -93,13 +93,13 @@ bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const
void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const {
Vector<StringName> variables;
- variables = RS::get_singleton()->global_shader_uniform_get_list();
+ variables = RS::get_singleton()->global_shader_parameter_get_list();
for (int i = 0; i < variables.size(); i++) {
PropertyInfo pinfo;
pinfo.name = "params/" + variables[i];
pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- switch (RS::get_singleton()->global_shader_uniform_get_type(variables[i])) {
+ switch (RS::get_singleton()->global_shader_parameter_get_type(variables[i])) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
pinfo.type = Variant::BOOL;
} break;
@@ -234,9 +234,9 @@ void ShaderGlobalsOverride::_activate() {
if (o->in_use && o->override.get_type() != Variant::NIL) {
if (o->override.get_type() == Variant::OBJECT) {
RID tex_rid = o->override;
- RS::get_singleton()->global_shader_uniform_set_override(E.key, tex_rid);
+ RS::get_singleton()->global_shader_parameter_set_override(E.key, tex_rid);
} else {
- RS::get_singleton()->global_shader_uniform_set_override(E.key, o->override);
+ RS::get_singleton()->global_shader_parameter_set_override(E.key, o->override);
}
}
@@ -258,7 +258,7 @@ void ShaderGlobalsOverride::_notification(int p_what) {
for (const KeyValue<StringName, Override> &E : overrides) {
const Override *o = &E.value;
if (o->in_use) {
- RS::get_singleton()->global_shader_uniform_set_override(E.key, Variant());
+ RS::get_singleton()->global_shader_parameter_set_override(E.key, Variant());
}
}
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index a738c6eabc..1bb1faacdd 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -190,14 +190,7 @@ void Viewport::_sub_window_register(Window *p_window) {
}
void Viewport::_sub_window_update(Window *p_window) {
- int index = -1;
- for (int i = 0; i < gui.sub_windows.size(); i++) {
- if (gui.sub_windows[i].window == p_window) {
- index = i;
- break;
- }
- }
-
+ int index = _sub_window_find(p_window);
ERR_FAIL_COND(index == -1);
const SubWindow &sw = gui.sub_windows[index];
@@ -257,14 +250,7 @@ void Viewport::_sub_window_grab_focus(Window *p_window) {
return;
}
- int index = -1;
- for (int i = 0; i < gui.sub_windows.size(); i++) {
- if (gui.sub_windows[i].window == p_window) {
- index = i;
- break;
- }
- }
-
+ int index = _sub_window_find(p_window);
ERR_FAIL_COND(index == -1);
if (p_window->get_flag(Window::FLAG_NO_FOCUS)) {
@@ -312,13 +298,11 @@ void Viewport::_sub_window_grab_focus(Window *p_window) {
}
void Viewport::_sub_window_remove(Window *p_window) {
- for (int i = 0; i < gui.sub_windows.size(); i++) {
- if (gui.sub_windows[i].window == p_window) {
- RS::get_singleton()->free(gui.sub_windows[i].canvas_item);
- gui.sub_windows.remove_at(i);
- break;
- }
- }
+ int index = _sub_window_find(p_window);
+ ERR_FAIL_COND(index == -1);
+
+ RS::get_singleton()->free(gui.sub_windows[index].canvas_item);
+ gui.sub_windows.remove_at(index);
if (gui.sub_windows.size() == 0) {
RS::get_singleton()->free(subwindow_canvas);
@@ -326,27 +310,46 @@ void Viewport::_sub_window_remove(Window *p_window) {
}
if (gui.subwindow_focused == p_window) {
+ Window *new_focused_window;
Window *parent_visible = p_window->get_parent_visible_window();
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
- if (parent_visible && parent_visible != this) {
- gui.subwindow_focused = parent_visible;
- gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
+ if (parent_visible) {
+ new_focused_window = parent_visible;
} else {
- gui.subwindow_focused = nullptr;
- Window *this_window = Object::cast_to<Window>(this);
- if (this_window) {
- this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
+ new_focused_window = Object::cast_to<Window>(this);
+ }
+
+ if (new_focused_window) {
+ int new_focused_index = _sub_window_find(new_focused_window);
+ if (new_focused_index != -1) {
+ gui.subwindow_focused = new_focused_window;
+ } else {
+ gui.subwindow_focused = nullptr;
}
+
+ new_focused_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
+ } else {
+ gui.subwindow_focused = nullptr;
}
}
RenderingServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID());
}
+int Viewport::_sub_window_find(Window *p_window) {
+ for (int i = 0; i < gui.sub_windows.size(); i++) {
+ if (gui.sub_windows[i].window == p_window) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
void Viewport::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 0b3853ba79..afea3ea56c 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -461,6 +461,7 @@ private:
void _sub_window_update(Window *p_window);
void _sub_window_grab_focus(Window *p_window);
void _sub_window_remove(Window *p_window);
+ int _sub_window_find(Window *p_window);
bool _sub_windows_forward_input(const Ref<InputEvent> &p_event);
SubWindowResize _sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point);
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 1e52b644a3..79a1c71064 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -799,6 +799,11 @@ Viewport *Window::_get_embedder() const {
void Window::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_POSTINITIALIZE: {
+ _invalidate_theme_cache();
+ _update_theme_item_cache();
+ } break;
+
case NOTIFICATION_ENTER_TREE: {
bool embedded = false;
{
@@ -858,6 +863,8 @@ void Window::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ _invalidate_theme_cache();
+ _update_theme_item_cache();
} break;
case NOTIFICATION_READY: {
@@ -867,6 +874,9 @@ void Window::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
+ _invalidate_theme_cache();
+ _update_theme_item_cache();
+
if (embedder) {
embedder->_sub_window_update(this);
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
@@ -1342,6 +1352,18 @@ void Window::_theme_changed() {
}
}
+void Window::_invalidate_theme_cache() {
+ theme_icon_cache.clear();
+ theme_style_cache.clear();
+ theme_font_cache.clear();
+ theme_font_size_cache.clear();
+ theme_color_cache.clear();
+ theme_constant_cache.clear();
+}
+
+void Window::_update_theme_item_cache() {
+}
+
void Window::set_theme_type_variation(const StringName &p_theme_type) {
theme_type_variation = p_theme_type;
if (is_inside_tree()) {
@@ -1366,39 +1388,75 @@ void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<S
}
Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ if (theme_icon_cache.has(p_theme_type) && theme_icon_cache[p_theme_type].has(p_name)) {
+ return theme_icon_cache[p_theme_type][p_name];
+ }
+
List<StringName> theme_types;
_get_theme_type_dependencies(p_theme_type, &theme_types);
- return Control::get_theme_item_in_types<Ref<Texture2D>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
+ Ref<Texture2D> icon = Control::get_theme_item_in_types<Ref<Texture2D>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_ICON, p_name, theme_types);
+ theme_icon_cache[p_theme_type][p_name] = icon;
+ return icon;
}
Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ if (theme_style_cache.has(p_theme_type) && theme_style_cache[p_theme_type].has(p_name)) {
+ return theme_style_cache[p_theme_type][p_name];
+ }
+
List<StringName> theme_types;
_get_theme_type_dependencies(p_theme_type, &theme_types);
- return Control::get_theme_item_in_types<Ref<StyleBox>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
+ Ref<StyleBox> style = Control::get_theme_item_in_types<Ref<StyleBox>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_STYLEBOX, p_name, theme_types);
+ theme_style_cache[p_theme_type][p_name] = style;
+ return style;
}
Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
+ if (theme_font_cache.has(p_theme_type) && theme_font_cache[p_theme_type].has(p_name)) {
+ return theme_font_cache[p_theme_type][p_name];
+ }
+
List<StringName> theme_types;
_get_theme_type_dependencies(p_theme_type, &theme_types);
- return Control::get_theme_item_in_types<Ref<Font>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
+ Ref<Font> font = Control::get_theme_item_in_types<Ref<Font>>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT, p_name, theme_types);
+ theme_font_cache[p_theme_type][p_name] = font;
+ return font;
}
int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ if (theme_font_size_cache.has(p_theme_type) && theme_font_size_cache[p_theme_type].has(p_name)) {
+ return theme_font_size_cache[p_theme_type][p_name];
+ }
+
List<StringName> theme_types;
_get_theme_type_dependencies(p_theme_type, &theme_types);
- return Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
+ int font_size = Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types);
+ theme_font_size_cache[p_theme_type][p_name] = font_size;
+ return font_size;
}
Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const {
+ if (theme_color_cache.has(p_theme_type) && theme_color_cache[p_theme_type].has(p_name)) {
+ return theme_color_cache[p_theme_type][p_name];
+ }
+
List<StringName> theme_types;
_get_theme_type_dependencies(p_theme_type, &theme_types);
- return Control::get_theme_item_in_types<Color>(theme_owner, theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
+ Color color = Control::get_theme_item_in_types<Color>(theme_owner, theme_owner_window, Theme::DATA_TYPE_COLOR, p_name, theme_types);
+ theme_color_cache[p_theme_type][p_name] = color;
+ return color;
}
int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ if (theme_constant_cache.has(p_theme_type) && theme_constant_cache[p_theme_type].has(p_name)) {
+ return theme_constant_cache[p_theme_type][p_name];
+ }
+
List<StringName> theme_types;
_get_theme_type_dependencies(p_theme_type, &theme_types);
- return Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
+ int constant = Control::get_theme_item_in_types<int>(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);
+ theme_constant_cache[p_theme_type][p_name] = constant;
+ return constant;
}
bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const {
diff --git a/scene/main/window.h b/scene/main/window.h
index 238be484c0..5a42c5bb83 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -32,12 +32,12 @@
#define WINDOW_H
#include "scene/main/viewport.h"
+#include "scene/resources/theme.h"
class Control;
class Font;
class Shortcut;
class StyleBox;
-class Theme;
class Window : public Viewport {
GDCLASS(Window, Viewport)
@@ -141,6 +141,18 @@ private:
Window *theme_owner_window = nullptr;
StringName theme_type_variation;
+ mutable HashMap<StringName, Theme::ThemeIconMap> theme_icon_cache;
+ mutable HashMap<StringName, Theme::ThemeStyleMap> theme_style_cache;
+ mutable HashMap<StringName, Theme::ThemeFontMap> theme_font_cache;
+ mutable HashMap<StringName, Theme::ThemeFontSizeMap> theme_font_size_cache;
+ mutable HashMap<StringName, Theme::ThemeColorMap> theme_color_cache;
+ mutable HashMap<StringName, Theme::ThemeConstantMap> theme_constant_cache;
+
+ _FORCE_INLINE_ void _get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const;
+
+ void _theme_changed();
+ void _invalidate_theme_cache();
+
Viewport *embedder = nullptr;
friend class Viewport; //friend back, can call the methods below
@@ -158,6 +170,8 @@ protected:
Viewport *_get_embedder() const;
virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
+ virtual void _update_theme_item_cache();
+
virtual void _post_popup() {}
virtual Size2 _get_contents_minimum_size() const;
static void _bind_methods();
@@ -259,11 +273,9 @@ public:
void set_theme(const Ref<Theme> &p_theme);
Ref<Theme> get_theme() const;
- void _theme_changed();
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 6c7bc552bf..a9470596b2 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -54,6 +54,7 @@
#include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/multimesh_instance_2d.h"
#include "scene/2d/navigation_agent_2d.h"
+#include "scene/2d/navigation_link_2d.h"
#include "scene/2d/navigation_obstacle_2d.h"
#include "scene/2d/parallax_background.h"
#include "scene/2d/parallax_layer.h"
@@ -142,7 +143,7 @@
#include "scene/resources/bit_map.h"
#include "scene/resources/bone_map.h"
#include "scene/resources/box_shape_3d.h"
-#include "scene/resources/camera_effects.h"
+#include "scene/resources/camera_attributes.h"
#include "scene/resources/capsule_shape_2d.h"
#include "scene/resources/capsule_shape_3d.h"
#include "scene/resources/circle_shape_2d.h"
@@ -152,6 +153,7 @@
#include "scene/resources/convex_polygon_shape_3d.h"
#include "scene/resources/cylinder_shape_3d.h"
#include "scene/resources/default_theme/default_theme.h"
+#include "scene/resources/environment.h"
#include "scene/resources/font.h"
#include "scene/resources/gradient.h"
#include "scene/resources/height_map_shape_3d.h"
@@ -239,6 +241,7 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h"
#include "scene/3d/navigation_agent_3d.h"
+#include "scene/3d/navigation_link_3d.h"
#include "scene/3d/navigation_obstacle_3d.h"
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/node_3d.h"
@@ -377,14 +380,14 @@ void register_scene_types() {
GDREGISTER_CLASS(VSeparator);
GDREGISTER_CLASS(TextureButton);
GDREGISTER_CLASS(Container);
- GDREGISTER_ABSTRACT_CLASS(BoxContainer);
+ GDREGISTER_CLASS(BoxContainer);
GDREGISTER_CLASS(HBoxContainer);
GDREGISTER_CLASS(VBoxContainer);
GDREGISTER_CLASS(GridContainer);
GDREGISTER_CLASS(CenterContainer);
GDREGISTER_CLASS(ScrollContainer);
GDREGISTER_CLASS(PanelContainer);
- GDREGISTER_ABSTRACT_CLASS(FlowContainer);
+ GDREGISTER_CLASS(FlowContainer);
GDREGISTER_CLASS(HFlowContainer);
GDREGISTER_CLASS(VFlowContainer);
@@ -421,7 +424,7 @@ void register_scene_types() {
GDREGISTER_CLASS(MarginContainer);
GDREGISTER_CLASS(SubViewportContainer);
- GDREGISTER_ABSTRACT_CLASS(SplitContainer);
+ GDREGISTER_CLASS(SplitContainer);
GDREGISTER_CLASS(HSplitContainer);
GDREGISTER_CLASS(VSplitContainer);
@@ -576,6 +579,7 @@ void register_scene_types() {
GDREGISTER_CLASS(NavigationRegion3D);
GDREGISTER_CLASS(NavigationAgent3D);
GDREGISTER_CLASS(NavigationObstacle3D);
+ GDREGISTER_CLASS(NavigationLink3D);
OS::get_singleton()->yield(); // may take time to init
#endif // _3D_DISABLED
@@ -638,21 +642,22 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeTexture2DArray);
GDREGISTER_CLASS(VisualShaderNodeTexture3D);
GDREGISTER_CLASS(VisualShaderNodeCubemap);
- GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeUniform);
- GDREGISTER_CLASS(VisualShaderNodeUniformRef);
- GDREGISTER_CLASS(VisualShaderNodeFloatUniform);
- GDREGISTER_CLASS(VisualShaderNodeIntUniform);
- GDREGISTER_CLASS(VisualShaderNodeBooleanUniform);
- GDREGISTER_CLASS(VisualShaderNodeColorUniform);
- GDREGISTER_CLASS(VisualShaderNodeVec2Uniform);
- GDREGISTER_CLASS(VisualShaderNodeVec3Uniform);
- GDREGISTER_CLASS(VisualShaderNodeVec4Uniform);
- GDREGISTER_CLASS(VisualShaderNodeTransformUniform);
- GDREGISTER_CLASS(VisualShaderNodeTextureUniform);
- GDREGISTER_CLASS(VisualShaderNodeTextureUniformTriplanar);
- GDREGISTER_CLASS(VisualShaderNodeTexture2DArrayUniform);
- GDREGISTER_CLASS(VisualShaderNodeTexture3DUniform);
- GDREGISTER_CLASS(VisualShaderNodeCubemapUniform);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeParameter);
+ GDREGISTER_CLASS(VisualShaderNodeParameterRef);
+ GDREGISTER_CLASS(VisualShaderNodeFloatParameter);
+ GDREGISTER_CLASS(VisualShaderNodeIntParameter);
+ GDREGISTER_CLASS(VisualShaderNodeBooleanParameter);
+ GDREGISTER_CLASS(VisualShaderNodeColorParameter);
+ GDREGISTER_CLASS(VisualShaderNodeVec2Parameter);
+ GDREGISTER_CLASS(VisualShaderNodeVec3Parameter);
+ GDREGISTER_CLASS(VisualShaderNodeVec4Parameter);
+ GDREGISTER_CLASS(VisualShaderNodeTransformParameter);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeTextureParameter);
+ GDREGISTER_CLASS(VisualShaderNodeTexture2DParameter);
+ GDREGISTER_CLASS(VisualShaderNodeTextureParameterTriplanar);
+ GDREGISTER_CLASS(VisualShaderNodeTexture2DArrayParameter);
+ GDREGISTER_CLASS(VisualShaderNodeTexture3DParameter);
+ GDREGISTER_CLASS(VisualShaderNodeCubemapParameter);
GDREGISTER_CLASS(VisualShaderNodeLinearSceneDepth);
GDREGISTER_CLASS(VisualShaderNodeIf);
GDREGISTER_CLASS(VisualShaderNodeSwitch);
@@ -836,7 +841,9 @@ void register_scene_types() {
GDREGISTER_CLASS(PhysicsMaterial);
GDREGISTER_CLASS(World3D);
GDREGISTER_CLASS(Environment);
- GDREGISTER_CLASS(CameraEffects);
+ GDREGISTER_VIRTUAL_CLASS(CameraAttributes);
+ GDREGISTER_CLASS(CameraAttributesPhysical);
+ GDREGISTER_CLASS(CameraAttributesPractical);
GDREGISTER_CLASS(World2D);
GDREGISTER_VIRTUAL_CLASS(Texture);
GDREGISTER_VIRTUAL_CLASS(Texture2D);
@@ -931,6 +938,7 @@ void register_scene_types() {
GDREGISTER_CLASS(NavigationRegion2D);
GDREGISTER_CLASS(NavigationAgent2D);
GDREGISTER_CLASS(NavigationObstacle2D);
+ GDREGISTER_CLASS(NavigationLink2D);
OS::get_singleton()->yield(); // may take time to init
@@ -1081,10 +1089,12 @@ void register_scene_types() {
ClassDB::add_compatibility_class("VisibilityNotifier2D", "VisibleOnScreenNotifier2D");
ClassDB::add_compatibility_class("VisibilityNotifier3D", "VisibleOnScreenNotifier3D");
ClassDB::add_compatibility_class("VisualServer", "RenderingServer");
+ ClassDB::add_compatibility_class("World", "World3D");
+
+ // VisualShader classes.
ClassDB::add_compatibility_class("VisualShaderNodeScalarConstant", "VisualShaderNodeFloatConstant");
ClassDB::add_compatibility_class("VisualShaderNodeScalarFunc", "VisualShaderNodeFloatFunc");
ClassDB::add_compatibility_class("VisualShaderNodeScalarOp", "VisualShaderNodeFloatOp");
- ClassDB::add_compatibility_class("VisualShaderNodeScalarUniform", "VisualShaderNodeFloatUniform");
ClassDB::add_compatibility_class("VisualShaderNodeScalarClamp", "VisualShaderNodeClamp");
ClassDB::add_compatibility_class("VisualShaderNodeVectorClamp", "VisualShaderNodeClamp");
ClassDB::add_compatibility_class("VisualShaderNodeScalarInterp", "VisualShaderNodeMix");
@@ -1098,7 +1108,17 @@ void register_scene_types() {
ClassDB::add_compatibility_class("VisualShaderNodeScalarTransformMult", "VisualShaderNodeTransformOp");
ClassDB::add_compatibility_class("VisualShaderNodeScalarDerivativeFunc", "VisualShaderNodeDerivativeFunc");
ClassDB::add_compatibility_class("VisualShaderNodeVectorDerivativeFunc", "VisualShaderNodeDerivativeFunc");
- ClassDB::add_compatibility_class("World", "World3D");
+
+ ClassDB::add_compatibility_class("VisualShaderNodeBooleanUniform", "VisualShaderNodeBooleanParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeColorUniform", "VisualShaderNodeColorParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeScalarUniform", "VisualShaderNodeFloatParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeCubeMapUniform", "VisualShaderNodeCubeMapParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeTextureUniform", "VisualShaderNodeTexture2DParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeTextureUniformTriplanar", "VisualShaderNodeTextureParameterTriplanar");
+ ClassDB::add_compatibility_class("VisualShaderNodeTransformUniform", "VisualShaderNodeTransformParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeVec3Uniform", "VisualShaderNodeVec3Parameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeUniform", "VisualShaderNodeParameter");
+ ClassDB::add_compatibility_class("VisualShaderNodeUniformRef", "VisualShaderNodeParameterRef");
// Renamed during 4.0 alpha, added to ease transition between alphas.
ClassDB::add_compatibility_class("AudioStreamOGGVorbis", "AudioStreamOggVorbis");
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp
index 9b1adde00a..0505f6b559 100644
--- a/scene/resources/bit_map.cpp
+++ b/scene/resources/bit_map.cpp
@@ -33,13 +33,18 @@
#include "core/io/image_loader.h"
#include "core/variant/typed_array.h"
-void BitMap::create(const Size2 &p_size) {
+void BitMap::create(const Size2i &p_size) {
ERR_FAIL_COND(p_size.width < 1);
ERR_FAIL_COND(p_size.height < 1);
+ ERR_FAIL_COND(static_cast<int64_t>(p_size.width) * static_cast<int64_t>(p_size.height) > INT32_MAX);
+
+ Error err = bitmask.resize((((p_size.width * p_size.height) - 1) / 8) + 1);
+ ERR_FAIL_COND(err != OK);
+
width = p_size.width;
height = p_size.height;
- bitmask.resize((((width * height) - 1) / 8) + 1);
+
memset(bitmask.ptrw(), 0, bitmask.size());
}
@@ -49,7 +54,7 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshol
img->convert(Image::FORMAT_LA8);
ERR_FAIL_COND(img->get_format() != Image::FORMAT_LA8);
- create(img->get_size());
+ create(Size2i(img->get_width(), img->get_height()));
const uint8_t *r = img->get_data().ptr();
uint8_t *w = bitmask.ptrw();
@@ -63,7 +68,7 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshol
}
}
-void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) {
+void BitMap::set_bit_rect(const Rect2i &p_rect, bool p_value) {
Rect2i current = Rect2i(0, 0, width, height).intersection(p_rect);
uint8_t *data = bitmask.ptrw();
@@ -91,7 +96,7 @@ int BitMap::get_true_bit_count() const {
const uint8_t *d = bitmask.ptr();
int c = 0;
- //fast, almost branchless version
+ // Fast, almost branchless version.
for (int i = 0; i < ds; i++) {
c += (d[i] & (1 << 7)) >> 7;
@@ -107,14 +112,15 @@ int BitMap::get_true_bit_count() const {
return c;
}
-void BitMap::set_bit(const Point2 &p_pos, bool p_value) {
- int x = p_pos.x;
- int y = p_pos.y;
+void BitMap::set_bitv(const Point2i &p_pos, bool p_value) {
+ set_bit(p_pos.x, p_pos.y, p_value);
+}
- ERR_FAIL_INDEX(x, width);
- ERR_FAIL_INDEX(y, height);
+void BitMap::set_bit(int p_x, int p_y, bool p_value) {
+ ERR_FAIL_INDEX(p_x, width);
+ ERR_FAIL_INDEX(p_y, height);
- int ofs = width * y + x;
+ int ofs = width * p_y + p_x;
int bbyte = ofs / 8;
int bbit = ofs % 8;
@@ -129,21 +135,23 @@ void BitMap::set_bit(const Point2 &p_pos, bool p_value) {
bitmask.write[bbyte] = b;
}
-bool BitMap::get_bit(const Point2 &p_pos) const {
- int x = Math::fast_ftoi(p_pos.x);
- int y = Math::fast_ftoi(p_pos.y);
- ERR_FAIL_INDEX_V(x, width, false);
- ERR_FAIL_INDEX_V(y, height, false);
+bool BitMap::get_bitv(const Point2i &p_pos) const {
+ return get_bit(p_pos.x, p_pos.y);
+}
+
+bool BitMap::get_bit(int p_x, int p_y) const {
+ ERR_FAIL_INDEX_V(p_x, width, false);
+ ERR_FAIL_INDEX_V(p_y, height, false);
- int ofs = width * y + x;
+ int ofs = width * p_y + p_x;
int bbyte = ofs / 8;
int bbit = ofs % 8;
return (bitmask[bbyte] & (1 << bbit)) != 0;
}
-Size2 BitMap::get_size() const {
- return Size2(width, height);
+Size2i BitMap::get_size() const {
+ return Size2i(width, height);
}
void BitMap::_set_data(const Dictionary &p_d) {
@@ -161,13 +169,13 @@ Dictionary BitMap::_get_data() const {
return d;
}
-Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const {
+Vector<Vector2> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const {
int stepx = 0;
int stepy = 0;
int prevx = 0;
int prevy = 0;
- int startx = start.x;
- int starty = start.y;
+ int startx = p_start.x;
+ int starty = p_start.y;
int curx = startx;
int cury = starty;
unsigned int count = 0;
@@ -176,7 +184,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start)
Vector<Vector2> _points;
do {
int sv = 0;
- { //square value
+ { // Square value
/*
checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent
@@ -187,13 +195,13 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start)
+---+---+
*/
Point2i tl = Point2i(curx - 1, cury - 1);
- sv += (rect.has_point(tl) && get_bit(tl)) ? 1 : 0;
+ sv += (p_rect.has_point(tl) && get_bitv(tl)) ? 1 : 0;
Point2i tr = Point2i(curx, cury - 1);
- sv += (rect.has_point(tr) && get_bit(tr)) ? 2 : 0;
+ sv += (p_rect.has_point(tr) && get_bitv(tr)) ? 2 : 0;
Point2i bl = Point2i(curx - 1, cury);
- sv += (rect.has_point(bl) && get_bit(bl)) ? 4 : 0;
+ sv += (p_rect.has_point(bl) && get_bitv(bl)) ? 4 : 0;
Point2i br = Point2i(curx, cury);
- sv += (rect.has_point(br) && get_bit(br)) ? 8 : 0;
+ sv += (p_rect.has_point(br) && get_bitv(br)) ? 8 : 0;
ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>());
}
@@ -303,16 +311,16 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start)
default:
ERR_PRINT("this shouldn't happen.");
}
- //little optimization
- // if previous direction is same as current direction,
- // then we should modify the last vec to current
+ // Small optimization:
+ // If the previous direction is same as the current direction,
+ // then we should modify the last vector to current.
curx += stepx;
cury += stepy;
if (stepx == prevx && stepy == prevy) {
- _points.write[_points.size() - 1].x = (float)(curx - rect.position.x);
- _points.write[_points.size() - 1].y = (float)(cury + rect.position.y);
+ _points.write[_points.size() - 1].x = (float)(curx - p_rect.position.x);
+ _points.write[_points.size() - 1].y = (float)(cury + p_rect.position.y);
} else {
- _points.push_back(Vector2((float)(curx - rect.position.x), (float)(cury + rect.position.y)));
+ _points.push_back(Vector2((float)(curx - p_rect.position.x), (float)(cury + p_rect.position.y)));
}
count++;
@@ -348,7 +356,7 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) {
int index = -1;
float dist = 0.0;
- //not looping first and last point
+ // Not looping first and last point.
for (size_t i = 1, size = v.size(); i < size - 1; ++i) {
float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]);
if (cdist > dist) {
@@ -385,9 +393,9 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) {
static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, float epsilon) {
int size = points.size();
- // if there are less than 3 points, then we have nothing
+ // If there are less than 3 points, then we have nothing.
ERR_FAIL_COND_V(size < 3, Vector<Vector2>());
- // if there are less than 9 points (but more than 3), then we don't need to reduce it
+ // If there are less than 9 points (but more than 3), then we don't need to reduce it.
if (size < 9) {
return points;
}
@@ -412,9 +420,9 @@ struct FillBitsStackEntry {
};
static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) {
- // Using a custom stack to work iteratively to avoid stack overflow on big bitmaps
+ // Using a custom stack to work iteratively to avoid stack overflow on big bitmaps.
Vector<FillBitsStackEntry> stack;
- // Tracking size since we won't be shrinking the stack vector
+ // Tracking size since we won't be shrinking the stack vector.
int stack_size = 0;
Point2i pos = p_pos;
@@ -433,10 +441,10 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
for (int i = next_i; i <= pos.x + 1; i++) {
for (int j = next_j; j <= pos.y + 1; j++) {
if (popped) {
- // The next loop over j must start normally
+ // The next loop over j must start normally.
next_j = pos.y;
popped = false;
- // Skip because an iteration was already executed with current counter values
+ // Skip because an iteration was already executed with current counter values.
continue;
}
@@ -447,11 +455,11 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
continue;
}
- if (p_map->get_bit(Vector2(i, j))) {
+ if (p_map->get_bit(i, j)) {
continue;
- } else if (p_src->get_bit(Vector2(i, j))) {
- p_map->set_bit(Vector2(i, j), true);
+ } else if (p_src->get_bit(i, j)) {
+ p_map->set_bit(i, j, true);
FillBitsStackEntry se = { pos, i, j };
stack.resize(MAX(stack_size + 1, stack.size()));
@@ -482,7 +490,7 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_
print_verbose("BitMap: Max stack size: " + itos(stack.size()));
}
-Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const {
+Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, float p_epsilon) const {
Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect);
print_verbose("BitMap: Rect: " + r);
@@ -494,7 +502,7 @@ Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, flo
Vector<Vector<Vector2>> polygons;
for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
- if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) {
+ if (!fill->get_bit(j, i) && get_bit(j, i)) {
fill_bits(this, fill, Point2i(j, i), r);
Vector<Vector2> polygon = _march_square(r, Point2i(j, i));
@@ -515,7 +523,7 @@ Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, flo
return polygons;
}
-void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
+void BitMap::grow_mask(int p_pixels, const Rect2i &p_rect) {
if (p_pixels == 0) {
return;
}
@@ -532,7 +540,7 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
- if (bit_value == get_bit(Point2(j, i))) {
+ if (bit_value == get_bit(j, i)) {
continue;
}
@@ -543,7 +551,7 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
bool outside = false;
if ((x < p_rect.position.x) || (x >= p_rect.position.x + p_rect.size.x) || (y < p_rect.position.y) || (y >= p_rect.position.y + p_rect.size.y)) {
- // outside of rectangle counts as bit not set
+ // Outside of rectangle counts as bit not set.
if (!bit_value) {
outside = true;
} else {
@@ -556,7 +564,7 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
continue;
}
- if (outside || (bit_value == copy->get_bit(Point2(x, y)))) {
+ if (outside || (bit_value == copy->get_bit(x, y))) {
found = true;
break;
}
@@ -567,20 +575,20 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
}
if (found) {
- set_bit(Point2(j, i), bit_value);
+ set_bit(j, i, bit_value);
}
}
}
}
-void BitMap::shrink_mask(int p_pixels, const Rect2 &p_rect) {
+void BitMap::shrink_mask(int p_pixels, const Rect2i &p_rect) {
grow_mask(-p_pixels, p_rect);
}
-TypedArray<PackedVector2Array> BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const {
+TypedArray<PackedVector2Array> BitMap::_opaque_to_polygons_bind(const Rect2i &p_rect, float p_epsilon) const {
Vector<Vector<Vector2>> result = clip_opaque_to_polygons(p_rect, p_epsilon);
- // Convert result to bindable types
+ // Convert result to bindable types.
TypedArray<PackedVector2Array> result_array;
result_array.resize(result.size());
@@ -603,15 +611,25 @@ TypedArray<PackedVector2Array> BitMap::_opaque_to_polygons_bind(const Rect2 &p_r
return result_array;
}
-void BitMap::resize(const Size2 &p_new_size) {
+void BitMap::resize(const Size2i &p_new_size) {
+ ERR_FAIL_COND(p_new_size.width < 0 || p_new_size.height < 0);
+ if (p_new_size == get_size()) {
+ return;
+ }
+
Ref<BitMap> new_bitmap;
new_bitmap.instantiate();
new_bitmap->create(p_new_size);
- int lw = MIN(width, p_new_size.width);
- int lh = MIN(height, p_new_size.height);
+ // also allow for upscaling
+ int lw = (width == 0) ? 0 : p_new_size.width;
+ int lh = (height == 0) ? 0 : p_new_size.height;
+
+ float scale_x = ((float)width / p_new_size.width);
+ float scale_y = ((float)height / p_new_size.height);
for (int x = 0; x < lw; x++) {
for (int y = 0; y < lh; y++) {
- new_bitmap->set_bit(Vector2(x, y), get_bit(Vector2(x, y)));
+ bool new_bit = get_bit(x * scale_x, y * scale_y);
+ new_bitmap->set_bit(x, y, new_bit);
}
}
@@ -627,14 +645,16 @@ Ref<Image> BitMap::convert_to_image() const {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
- image->set_pixel(i, j, get_bit(Point2(i, j)) ? Color(1, 1, 1) : Color(0, 0, 0));
+ image->set_pixel(i, j, get_bit(i, j) ? Color(1, 1, 1) : Color(0, 0, 0));
}
}
return image;
}
-void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) {
+void BitMap::blit(const Vector2i &p_pos, const Ref<BitMap> &p_bitmap) {
+ ERR_FAIL_COND_MSG(p_bitmap.is_null(), "It's not a reference to a valid BitMap object.");
+
int x = p_pos.x;
int y = p_pos.y;
int w = p_bitmap->get_size().width;
@@ -650,8 +670,8 @@ void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) {
if (py < 0 || py >= height) {
continue;
}
- if (p_bitmap->get_bit(Vector2(i, j))) {
- set_bit(Vector2(x, y), true);
+ if (p_bitmap->get_bit(i, j)) {
+ set_bit(px, py, true);
}
}
}
@@ -661,8 +681,10 @@ void BitMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create);
ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1));
- ClassDB::bind_method(D_METHOD("set_bit", "position", "bit"), &BitMap::set_bit);
- ClassDB::bind_method(D_METHOD("get_bit", "position"), &BitMap::get_bit);
+ ClassDB::bind_method(D_METHOD("set_bitv", "position", "bit"), &BitMap::set_bitv);
+ ClassDB::bind_method(D_METHOD("set_bit", "x", "y", "bit"), &BitMap::set_bit);
+ ClassDB::bind_method(D_METHOD("get_bitv", "position"), &BitMap::get_bitv);
+ ClassDB::bind_method(D_METHOD("get_bit", "x", "y"), &BitMap::get_bit);
ClassDB::bind_method(D_METHOD("set_bit_rect", "rect", "bit"), &BitMap::set_bit_rect);
ClassDB::bind_method(D_METHOD("get_true_bit_count"), &BitMap::get_true_bit_count);
@@ -681,5 +703,3 @@ void BitMap::_bind_methods() {
}
BitMap::BitMap() {}
-
-//////////////////////////////////////
diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h
index d8507dfa8b..291ed8c4d0 100644
--- a/scene/resources/bit_map.h
+++ b/scene/resources/bit_map.h
@@ -46,9 +46,9 @@ class BitMap : public Resource {
int width = 0;
int height = 0;
- Vector<Vector2> _march_square(const Rect2i &rect, const Point2i &start) const;
+ Vector<Vector2> _march_square(const Rect2i &p_rect, const Point2i &p_start) const;
- TypedArray<PackedVector2Array> _opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const;
+ TypedArray<PackedVector2Array> _opaque_to_polygons_bind(const Rect2i &p_rect, float p_epsilon) const;
protected:
void _set_data(const Dictionary &p_d);
@@ -57,24 +57,27 @@ protected:
static void _bind_methods();
public:
- void create(const Size2 &p_size);
+ void create(const Size2i &p_size);
void create_from_image_alpha(const Ref<Image> &p_image, float p_threshold = 0.1);
- void set_bit(const Point2 &p_pos, bool p_value);
- bool get_bit(const Point2 &p_pos) const;
- void set_bit_rect(const Rect2 &p_rect, bool p_value);
+ void set_bitv(const Point2i &p_pos, bool p_value);
+ void set_bit(int p_x, int p_y, bool p_value);
+ void set_bit_rect(const Rect2i &p_rect, bool p_value);
+ bool get_bitv(const Point2i &p_pos) const;
+ bool get_bit(int p_x, int p_y) const;
+
int get_true_bit_count() const;
- Size2 get_size() const;
- void resize(const Size2 &p_new_size);
+ Size2i get_size() const;
+ void resize(const Size2i &p_new_size);
- void grow_mask(int p_pixels, const Rect2 &p_rect);
- void shrink_mask(int p_pixels, const Rect2 &p_rect);
+ void grow_mask(int p_pixels, const Rect2i &p_rect);
+ void shrink_mask(int p_pixels, const Rect2i &p_rect);
- void blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap);
+ void blit(const Vector2i &p_pos, const Ref<BitMap> &p_bitmap);
Ref<Image> convert_to_image() const;
- Vector<Vector<Vector2>> clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon = 2.0) const;
+ Vector<Vector<Vector2>> clip_opaque_to_polygons(const Rect2i &p_rect, float p_epsilon = 2.0) const;
BitMap();
};
diff --git a/scene/resources/camera_attributes.cpp b/scene/resources/camera_attributes.cpp
new file mode 100644
index 0000000000..3c322f32b6
--- /dev/null
+++ b/scene/resources/camera_attributes.cpp
@@ -0,0 +1,493 @@
+/*************************************************************************/
+/* camera_attributes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "camera_attributes.h"
+
+#include "core/config/project_settings.h"
+#include "servers/rendering_server.h"
+
+void CameraAttributes::set_exposure_multiplier(float p_multiplier) {
+ exposure_multiplier = p_multiplier;
+ _update_exposure();
+ emit_changed();
+}
+
+float CameraAttributes::get_exposure_multiplier() const {
+ return exposure_multiplier;
+}
+
+void CameraAttributes::set_exposure_sensitivity(float p_sensitivity) {
+ exposure_sensitivity = p_sensitivity;
+ _update_exposure();
+ emit_changed();
+}
+
+float CameraAttributes::get_exposure_sensitivity() const {
+ return exposure_sensitivity;
+}
+
+void CameraAttributes::_update_exposure() {
+ float exposure_normalization = 1.0;
+ // Ignore physical properties if not using physical light units.
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ exposure_normalization = calculate_exposure_normalization();
+ }
+
+ RS::get_singleton()->camera_attributes_set_exposure(camera_attributes, exposure_multiplier, exposure_normalization);
+}
+
+void CameraAttributes::set_auto_exposure_enabled(bool p_enabled) {
+ auto_exposure_enabled = p_enabled;
+ _update_auto_exposure();
+ notify_property_list_changed();
+}
+
+bool CameraAttributes::is_auto_exposure_enabled() const {
+ return auto_exposure_enabled;
+}
+
+void CameraAttributes::set_auto_exposure_speed(float p_auto_exposure_speed) {
+ auto_exposure_speed = p_auto_exposure_speed;
+ _update_auto_exposure();
+}
+
+float CameraAttributes::get_auto_exposure_speed() const {
+ return auto_exposure_speed;
+}
+
+void CameraAttributes::set_auto_exposure_scale(float p_auto_exposure_scale) {
+ auto_exposure_scale = p_auto_exposure_scale;
+ _update_auto_exposure();
+}
+
+float CameraAttributes::get_auto_exposure_scale() const {
+ return auto_exposure_scale;
+}
+
+RID CameraAttributes::get_rid() const {
+ return camera_attributes;
+}
+
+void CameraAttributes::_validate_property(PropertyInfo &p_property) const {
+ if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && p_property.name == "exposure_sensitivity") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+ return;
+ }
+
+ if (p_property.name.begins_with("auto_exposure_") && p_property.name != "auto_exposure_enabled" && !auto_exposure_enabled) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+ return;
+ }
+}
+
+void CameraAttributes::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_exposure_multiplier", "multiplier"), &CameraAttributes::set_exposure_multiplier);
+ ClassDB::bind_method(D_METHOD("get_exposure_multiplier"), &CameraAttributes::get_exposure_multiplier);
+ ClassDB::bind_method(D_METHOD("set_exposure_sensitivity", "sensitivity"), &CameraAttributes::set_exposure_sensitivity);
+ ClassDB::bind_method(D_METHOD("get_exposure_sensitivity"), &CameraAttributes::get_exposure_sensitivity);
+
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_enabled", "enabled"), &CameraAttributes::set_auto_exposure_enabled);
+ ClassDB::bind_method(D_METHOD("is_auto_exposure_enabled"), &CameraAttributes::is_auto_exposure_enabled);
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_speed", "exposure_speed"), &CameraAttributes::set_auto_exposure_speed);
+ ClassDB::bind_method(D_METHOD("get_auto_exposure_speed"), &CameraAttributes::get_auto_exposure_speed);
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_scale", "exposure_grey"), &CameraAttributes::set_auto_exposure_scale);
+ ClassDB::bind_method(D_METHOD("get_auto_exposure_scale"), &CameraAttributes::get_auto_exposure_scale);
+
+ ADD_GROUP("Exposure", "exposure");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_sensitivity", PROPERTY_HINT_RANGE, "0.1,32000.0,0.1,suffix:ISO"), "set_exposure_sensitivity", "get_exposure_sensitivity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_multiplier", PROPERTY_HINT_RANGE, "0.0,2048.0,0.001"), "set_exposure_multiplier", "get_exposure_multiplier");
+
+ ADD_GROUP("Auto Exposure", "auto_exposure_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_auto_exposure_enabled", "is_auto_exposure_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_auto_exposure_scale", "get_auto_exposure_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_auto_exposure_speed", "get_auto_exposure_speed");
+}
+
+CameraAttributes::CameraAttributes() {
+ camera_attributes = RS::get_singleton()->camera_attributes_create();
+}
+
+CameraAttributes::~CameraAttributes() {
+ RS::get_singleton()->free(camera_attributes);
+}
+
+//////////////////////////////////////////////////////
+/* CameraAttributesPractical */
+
+void CameraAttributesPractical::set_dof_blur_far_enabled(bool p_enabled) {
+ dof_blur_far_enabled = p_enabled;
+ _update_dof_blur();
+ notify_property_list_changed();
+}
+
+bool CameraAttributesPractical::is_dof_blur_far_enabled() const {
+ return dof_blur_far_enabled;
+}
+
+void CameraAttributesPractical::set_dof_blur_far_distance(float p_distance) {
+ dof_blur_far_distance = p_distance;
+ _update_dof_blur();
+}
+
+float CameraAttributesPractical::get_dof_blur_far_distance() const {
+ return dof_blur_far_distance;
+}
+
+void CameraAttributesPractical::set_dof_blur_far_transition(float p_distance) {
+ dof_blur_far_transition = p_distance;
+ _update_dof_blur();
+}
+
+float CameraAttributesPractical::get_dof_blur_far_transition() const {
+ return dof_blur_far_transition;
+}
+
+void CameraAttributesPractical::set_dof_blur_near_enabled(bool p_enabled) {
+ dof_blur_near_enabled = p_enabled;
+ _update_dof_blur();
+ notify_property_list_changed();
+}
+
+bool CameraAttributesPractical::is_dof_blur_near_enabled() const {
+ return dof_blur_near_enabled;
+}
+
+void CameraAttributesPractical::set_dof_blur_near_distance(float p_distance) {
+ dof_blur_near_distance = p_distance;
+ _update_dof_blur();
+}
+
+float CameraAttributesPractical::get_dof_blur_near_distance() const {
+ return dof_blur_near_distance;
+}
+
+void CameraAttributesPractical::set_dof_blur_near_transition(float p_distance) {
+ dof_blur_near_transition = p_distance;
+ _update_dof_blur();
+}
+
+float CameraAttributesPractical::get_dof_blur_near_transition() const {
+ return dof_blur_near_transition;
+}
+
+void CameraAttributesPractical::set_dof_blur_amount(float p_amount) {
+ dof_blur_amount = p_amount;
+ _update_dof_blur();
+}
+
+float CameraAttributesPractical::get_dof_blur_amount() const {
+ return dof_blur_amount;
+}
+
+void CameraAttributesPractical::_update_dof_blur() {
+ RS::get_singleton()->camera_attributes_set_dof_blur(
+ get_rid(),
+ dof_blur_far_enabled,
+ dof_blur_far_distance,
+ dof_blur_far_transition,
+ dof_blur_near_enabled,
+ dof_blur_near_distance,
+ dof_blur_near_transition,
+ dof_blur_amount);
+}
+
+float CameraAttributesPractical::calculate_exposure_normalization() const {
+ return exposure_sensitivity / 3072007.0; // Matches exposure normalization for default CameraAttributesPhysical at ISO 100.
+}
+
+void CameraAttributesPractical::set_auto_exposure_min_sensitivity(float p_min) {
+ auto_exposure_min = p_min;
+ _update_auto_exposure();
+}
+
+float CameraAttributesPractical::get_auto_exposure_min_sensitivity() const {
+ return auto_exposure_min;
+}
+
+void CameraAttributesPractical::set_auto_exposure_max_sensitivity(float p_max) {
+ auto_exposure_max = p_max;
+ _update_auto_exposure();
+}
+
+float CameraAttributesPractical::get_auto_exposure_max_sensitivity() const {
+ return auto_exposure_max;
+}
+
+void CameraAttributesPractical::_update_auto_exposure() {
+ RS::get_singleton()->camera_attributes_set_auto_exposure(
+ get_rid(),
+ auto_exposure_enabled,
+ auto_exposure_min * ((12.5 / 100.0) / exposure_sensitivity), // Convert from Sensitivity to Luminance
+ auto_exposure_max * ((12.5 / 100.0) / exposure_sensitivity), // Convert from Sensitivity to Luminance
+ auto_exposure_speed,
+ auto_exposure_scale);
+ emit_changed();
+}
+
+void CameraAttributesPractical::_validate_property(PropertyInfo &p_property) const {
+ if ((!dof_blur_far_enabled && (p_property.name == "dof_blur_far_distance" || p_property.name == "dof_blur_far_transition")) ||
+ (!dof_blur_near_enabled && (p_property.name == "dof_blur_near_distance" || p_property.name == "dof_blur_near_transition"))) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+}
+
+void CameraAttributesPractical::_bind_methods() {
+ // DOF blur
+
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraAttributesPractical::set_dof_blur_far_enabled);
+ ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraAttributesPractical::is_dof_blur_far_enabled);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "distance"), &CameraAttributesPractical::set_dof_blur_far_distance);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraAttributesPractical::get_dof_blur_far_distance);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "distance"), &CameraAttributesPractical::set_dof_blur_far_transition);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraAttributesPractical::get_dof_blur_far_transition);
+
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraAttributesPractical::set_dof_blur_near_enabled);
+ ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraAttributesPractical::is_dof_blur_near_enabled);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "distance"), &CameraAttributesPractical::set_dof_blur_near_distance);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraAttributesPractical::get_dof_blur_near_distance);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "distance"), &CameraAttributesPractical::set_dof_blur_near_transition);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraAttributesPractical::get_dof_blur_near_transition);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "amount"), &CameraAttributesPractical::set_dof_blur_amount);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraAttributesPractical::get_dof_blur_amount);
+
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_max_sensitivity", "max_sensitivity"), &CameraAttributesPractical::set_auto_exposure_max_sensitivity);
+ ClassDB::bind_method(D_METHOD("get_auto_exposure_max_sensitivity"), &CameraAttributesPractical::get_auto_exposure_max_sensitivity);
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_min_sensitivity", "min_sensitivity"), &CameraAttributesPractical::set_auto_exposure_min_sensitivity);
+ ClassDB::bind_method(D_METHOD("get_auto_exposure_min_sensitivity"), &CameraAttributesPractical::get_auto_exposure_min_sensitivity);
+
+ ADD_GROUP("DOF Blur", "dof_blur_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
+
+ ADD_GROUP("Auto Exposure", "auto_exposure_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_sensitivity", PROPERTY_HINT_RANGE, "0,1600,0.01,or_greater,suffic:ISO"), "set_auto_exposure_min_sensitivity", "get_auto_exposure_min_sensitivity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_sensitivity", PROPERTY_HINT_RANGE, "0,64000,0.1,or_greater,suffic:ISO"), "set_auto_exposure_max_sensitivity", "get_auto_exposure_max_sensitivity");
+}
+
+CameraAttributesPractical::CameraAttributesPractical() {
+ _update_dof_blur();
+ _update_exposure();
+ set_auto_exposure_min_sensitivity(0.0);
+ set_auto_exposure_max_sensitivity(800.0);
+ notify_property_list_changed();
+}
+
+CameraAttributesPractical::~CameraAttributesPractical() {
+}
+
+//////////////////////////////////////////////////////
+/* CameraAttributesPhysical */
+
+void CameraAttributesPhysical::set_aperture(float p_aperture) {
+ exposure_aperture = p_aperture;
+ _update_exposure();
+ _update_frustum();
+}
+
+float CameraAttributesPhysical::get_aperture() const {
+ return exposure_aperture;
+}
+
+void CameraAttributesPhysical::set_shutter_speed(float p_shutter_speed) {
+ exposure_shutter_speed = p_shutter_speed;
+ _update_exposure();
+}
+
+float CameraAttributesPhysical::get_shutter_speed() const {
+ return exposure_shutter_speed;
+}
+
+void CameraAttributesPhysical::set_focal_length(float p_focal_length) {
+ frustum_focal_length = p_focal_length;
+ _update_frustum();
+ emit_changed();
+}
+
+float CameraAttributesPhysical::get_focal_length() const {
+ return frustum_focal_length;
+}
+
+void CameraAttributesPhysical::set_focus_distance(float p_focus_distance) {
+ frustum_focus_distance = p_focus_distance;
+ _update_frustum();
+}
+
+float CameraAttributesPhysical::get_focus_distance() const {
+ return frustum_focus_distance;
+}
+
+void CameraAttributesPhysical::set_near(real_t p_near) {
+ frustum_near = p_near;
+ _update_frustum();
+ emit_changed();
+}
+
+real_t CameraAttributesPhysical::get_near() const {
+ return frustum_near;
+}
+
+void CameraAttributesPhysical::set_far(real_t p_far) {
+ frustum_far = p_far;
+ _update_frustum();
+ emit_changed();
+}
+
+real_t CameraAttributesPhysical::get_far() const {
+ return frustum_far;
+}
+
+real_t CameraAttributesPhysical::get_fov() const {
+ return frustum_fov;
+}
+
+void CameraAttributesPhysical::_update_frustum() {
+ //https://en.wikipedia.org/wiki/Circle_of_confusion#Circle_of_confusion_diameter_limit_based_on_d/1500
+ Vector2i sensor_size = Vector2i(36, 24); // Matches high-end DSLR, could be made variable if there is demand.
+ float CoC = sensor_size.length() / 1500.0;
+
+ frustum_fov = Math::rad_to_deg(2 * atan(sensor_size.height / (2 * frustum_focal_length)));
+
+ // Based on https://en.wikipedia.org/wiki/Depth_of_field.
+ float u = MAX(frustum_focus_distance * 1000.0, frustum_focal_length + 1.0); // Focus distance expressed in mm and clamped to at least 1 mm away from lens.
+ float hyperfocal_length = frustum_focal_length + ((frustum_focal_length * frustum_focal_length) / (exposure_aperture * CoC));
+
+ // This computes the start and end of the depth of field. Anything between these two points has a Circle of Confusino so small
+ // that it is not picked up by the camera sensors.
+ // To be properly physically-based, we would run the DoF shader at all depths. To be efficient, we are only running it where the CoC
+ // will be visible, this introduces some value shifts in the near field that we have to compensate for below.
+ float near = ((hyperfocal_length * u) / (hyperfocal_length + (u - frustum_focal_length))) / 1000.0; // In meters.
+ float far = ((hyperfocal_length * u) / (hyperfocal_length - (u - frustum_focal_length))) / 1000.0; // In meters.
+ float scale = (frustum_focal_length / (u - frustum_focal_length)) * (frustum_focal_length / exposure_aperture);
+
+ bool use_far = (far < frustum_far) && (far > 0.0);
+ bool use_near = near > frustum_near;
+ RS::get_singleton()->camera_attributes_set_dof_blur(
+ get_rid(),
+ use_far,
+ u / 1000.0, // Focus distance clampd to focal length expressed in meters.
+ -1.0, // Negative to tell Bokeh effect to use physically-based scaling.
+ use_near,
+ u / 1000.0,
+ -1.0,
+ scale / 5.0); // Arbitrary scaling to get close to how much blur there should be.
+}
+
+float CameraAttributesPhysical::calculate_exposure_normalization() const {
+ const float e = (exposure_aperture * exposure_aperture) * exposure_shutter_speed * (100.0 / exposure_sensitivity);
+ return 1.0 / (e * 1.2);
+}
+
+void CameraAttributesPhysical::set_auto_exposure_min_exposure_value(float p_min) {
+ auto_exposure_min = p_min;
+ _update_auto_exposure();
+}
+
+float CameraAttributesPhysical::get_auto_exposure_min_exposure_value() const {
+ return auto_exposure_min;
+}
+
+void CameraAttributesPhysical::set_auto_exposure_max_exposure_value(float p_max) {
+ auto_exposure_max = p_max;
+ _update_auto_exposure();
+}
+
+float CameraAttributesPhysical::get_auto_exposure_max_exposure_value() const {
+ return auto_exposure_max;
+}
+
+void CameraAttributesPhysical::_update_auto_exposure() {
+ RS::get_singleton()->camera_attributes_set_auto_exposure(
+ get_rid(),
+ auto_exposure_enabled,
+ pow(2.0, auto_exposure_min) * (12.5 / exposure_sensitivity), // Convert from EV100 to Luminance
+ pow(2.0, auto_exposure_max) * (12.5 / exposure_sensitivity), // Convert from EV100 to Luminance
+ auto_exposure_speed,
+ auto_exposure_scale);
+ emit_changed();
+}
+
+void CameraAttributesPhysical::_validate_property(PropertyInfo &property) const {
+ if (!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units") && (property.name == "exposure_aperture" || property.name == "exposure_shutter_speed")) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+ return;
+ }
+}
+
+void CameraAttributesPhysical::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_aperture", "aperture"), &CameraAttributesPhysical::set_aperture);
+ ClassDB::bind_method(D_METHOD("get_aperture"), &CameraAttributesPhysical::get_aperture);
+ ClassDB::bind_method(D_METHOD("set_shutter_speed", "shutter_speed"), &CameraAttributesPhysical::set_shutter_speed);
+ ClassDB::bind_method(D_METHOD("get_shutter_speed"), &CameraAttributesPhysical::get_shutter_speed);
+
+ ClassDB::bind_method(D_METHOD("set_focal_length", "focal_length"), &CameraAttributesPhysical::set_focal_length);
+ ClassDB::bind_method(D_METHOD("get_focal_length"), &CameraAttributesPhysical::get_focal_length);
+ ClassDB::bind_method(D_METHOD("set_focus_distance", "focus_distance"), &CameraAttributesPhysical::set_focus_distance);
+ ClassDB::bind_method(D_METHOD("get_focus_distance"), &CameraAttributesPhysical::get_focus_distance);
+ ClassDB::bind_method(D_METHOD("set_near", "near"), &CameraAttributesPhysical::set_near);
+ ClassDB::bind_method(D_METHOD("get_near"), &CameraAttributesPhysical::get_near);
+ ClassDB::bind_method(D_METHOD("set_far", "far"), &CameraAttributesPhysical::set_far);
+ ClassDB::bind_method(D_METHOD("get_far"), &CameraAttributesPhysical::get_far);
+ ClassDB::bind_method(D_METHOD("get_fov"), &CameraAttributesPhysical::get_fov);
+
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_max_exposure_value", "exposure_value_max"), &CameraAttributesPhysical::set_auto_exposure_max_exposure_value);
+ ClassDB::bind_method(D_METHOD("get_auto_exposure_max_exposure_value"), &CameraAttributesPhysical::get_auto_exposure_max_exposure_value);
+ ClassDB::bind_method(D_METHOD("set_auto_exposure_min_exposure_value", "exposure_value_min"), &CameraAttributesPhysical::set_auto_exposure_min_exposure_value);
+ ClassDB::bind_method(D_METHOD("get_auto_exposure_min_exposure_value"), &CameraAttributesPhysical::get_auto_exposure_min_exposure_value);
+
+ ADD_GROUP("Frustum", "frustum_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_focus_distance", PROPERTY_HINT_RANGE, "0.01,4000.0,0.01,suffix:m"), "set_focus_distance", "get_focus_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_focal_length", PROPERTY_HINT_RANGE, "1.0,800.0,0.01,exp,suffix:mm"), "set_focal_length", "get_focal_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far");
+
+ ADD_GROUP("Exposure", "exposure");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_aperture", PROPERTY_HINT_RANGE, "0.5,64.0,0.01,exp,suffix:f-stop"), "set_aperture", "get_aperture");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_shutter_speed", PROPERTY_HINT_RANGE, "0.1,8000.0,0.001,suffix:1/s"), "set_shutter_speed", "get_shutter_speed");
+
+ ADD_GROUP("Auto Exposure", "auto_exposure_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_min_exposure_value", "get_auto_exposure_min_exposure_value");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_exposure_value", PROPERTY_HINT_RANGE, "-16.0,16.0,0.01,or_greater,suffix:EV100"), "set_auto_exposure_max_exposure_value", "get_auto_exposure_max_exposure_value");
+};
+
+CameraAttributesPhysical::CameraAttributesPhysical() {
+ _update_exposure();
+ _update_frustum();
+ set_auto_exposure_min_exposure_value(-8);
+ set_auto_exposure_max_exposure_value(10); // Use a wide range by default to feel more like a real camera.
+ notify_property_list_changed();
+}
+
+CameraAttributesPhysical::~CameraAttributesPhysical() {
+}
diff --git a/scene/resources/camera_attributes.h b/scene/resources/camera_attributes.h
new file mode 100644
index 0000000000..c4c783af29
--- /dev/null
+++ b/scene/resources/camera_attributes.h
@@ -0,0 +1,183 @@
+/*************************************************************************/
+/* camera_attributes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CAMERA_ATTRIBUTES_H
+#define CAMERA_ATTRIBUTES_H
+
+#include "core/io/resource.h"
+#include "core/templates/rid.h"
+
+class CameraAttributes : public Resource {
+ GDCLASS(CameraAttributes, Resource);
+
+private:
+ RID camera_attributes;
+
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
+
+ float exposure_multiplier = 1.0;
+ float exposure_sensitivity = 100.0; // In ISO.
+ void _update_exposure();
+
+ bool auto_exposure_enabled = false;
+ float auto_exposure_min = 0.01;
+ float auto_exposure_max = 64.0;
+ float auto_exposure_speed = 0.5;
+ float auto_exposure_scale = 0.4;
+ virtual void _update_auto_exposure(){};
+
+public:
+ virtual RID get_rid() const override;
+ virtual float calculate_exposure_normalization() const { return 1.0; }
+
+ void set_exposure_multiplier(float p_multiplier);
+ float get_exposure_multiplier() const;
+ void set_exposure_sensitivity(float p_sensitivity);
+ float get_exposure_sensitivity() const;
+
+ void set_auto_exposure_enabled(bool p_enabled);
+ bool is_auto_exposure_enabled() const;
+ void set_auto_exposure_speed(float p_auto_exposure_speed);
+ float get_auto_exposure_speed() const;
+ void set_auto_exposure_scale(float p_auto_exposure_scale);
+ float get_auto_exposure_scale() const;
+
+ CameraAttributes();
+ ~CameraAttributes();
+};
+
+class CameraAttributesPractical : public CameraAttributes {
+ GDCLASS(CameraAttributesPractical, CameraAttributes);
+
+private:
+ // DOF blur
+ bool dof_blur_far_enabled = false;
+ float dof_blur_far_distance = 10.0;
+ float dof_blur_far_transition = 5.0;
+
+ bool dof_blur_near_enabled = false;
+ float dof_blur_near_distance = 2.0;
+ float dof_blur_near_transition = 1.0;
+
+ float dof_blur_amount = 0.1;
+ void _update_dof_blur();
+
+ virtual void _update_auto_exposure() override;
+
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
+
+public:
+ // DOF blur
+ void set_dof_blur_far_enabled(bool p_enabled);
+ bool is_dof_blur_far_enabled() const;
+ void set_dof_blur_far_distance(float p_distance);
+ float get_dof_blur_far_distance() const;
+ void set_dof_blur_far_transition(float p_distance);
+ float get_dof_blur_far_transition() const;
+
+ void set_dof_blur_near_enabled(bool p_enabled);
+ bool is_dof_blur_near_enabled() const;
+ void set_dof_blur_near_distance(float p_distance);
+ float get_dof_blur_near_distance() const;
+ void set_dof_blur_near_transition(float p_distance);
+ float get_dof_blur_near_transition() const;
+ void set_dof_blur_amount(float p_amount);
+ float get_dof_blur_amount() const;
+
+ void set_auto_exposure_min_sensitivity(float p_min);
+ float get_auto_exposure_min_sensitivity() const;
+ void set_auto_exposure_max_sensitivity(float p_max);
+ float get_auto_exposure_max_sensitivity() const;
+
+ virtual float calculate_exposure_normalization() const override;
+
+ CameraAttributesPractical();
+ ~CameraAttributesPractical();
+};
+
+class CameraAttributesPhysical : public CameraAttributes {
+ GDCLASS(CameraAttributesPhysical, CameraAttributes);
+
+private:
+ // Exposure
+ float exposure_aperture = 16.0; // In f-stops;
+ float exposure_shutter_speed = 100.0; // In 1 / seconds;
+
+ // Camera properties.
+ float frustum_focal_length = 35.0; // In millimeters.
+ float frustum_focus_distance = 10.0; // In Meters.
+ real_t frustum_near = 0.05;
+ real_t frustum_far = 4000.0;
+ real_t frustum_fov = 75.0;
+ void _update_frustum();
+
+ virtual void _update_auto_exposure() override;
+
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
+
+public:
+ void set_aperture(float p_aperture);
+ float get_aperture() const;
+
+ void set_shutter_speed(float p_shutter_speed);
+ float get_shutter_speed() const;
+
+ void set_focal_length(float p_focal_length);
+ float get_focal_length() const;
+
+ void set_focus_distance(float p_focus_distance);
+ float get_focus_distance() const;
+
+ void set_near(real_t p_near);
+ real_t get_near() const;
+
+ void set_far(real_t p_far);
+ real_t get_far() const;
+
+ real_t get_fov() const;
+
+ void set_auto_exposure_min_exposure_value(float p_min);
+ float get_auto_exposure_min_exposure_value() const;
+ void set_auto_exposure_max_exposure_value(float p_max);
+ float get_auto_exposure_max_exposure_value() const;
+
+ virtual float calculate_exposure_normalization() const override;
+
+ CameraAttributesPhysical();
+ ~CameraAttributesPhysical();
+};
+
+#endif // CAMERA_ATTRIBUTES_H
diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp
deleted file mode 100644
index 0b11366591..0000000000
--- a/scene/resources/camera_effects.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*************************************************************************/
-/* camera_effects.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "camera_effects.h"
-
-#include "servers/rendering_server.h"
-
-RID CameraEffects::get_rid() const {
- return camera_effects;
-}
-
-// DOF blur
-
-void CameraEffects::set_dof_blur_far_enabled(bool p_enabled) {
- dof_blur_far_enabled = p_enabled;
- _update_dof_blur();
- notify_property_list_changed();
-}
-
-bool CameraEffects::is_dof_blur_far_enabled() const {
- return dof_blur_far_enabled;
-}
-
-void CameraEffects::set_dof_blur_far_distance(float p_distance) {
- dof_blur_far_distance = p_distance;
- _update_dof_blur();
-}
-
-float CameraEffects::get_dof_blur_far_distance() const {
- return dof_blur_far_distance;
-}
-
-void CameraEffects::set_dof_blur_far_transition(float p_distance) {
- dof_blur_far_transition = p_distance;
- _update_dof_blur();
-}
-
-float CameraEffects::get_dof_blur_far_transition() const {
- return dof_blur_far_transition;
-}
-
-void CameraEffects::set_dof_blur_near_enabled(bool p_enabled) {
- dof_blur_near_enabled = p_enabled;
- _update_dof_blur();
- notify_property_list_changed();
-}
-
-bool CameraEffects::is_dof_blur_near_enabled() const {
- return dof_blur_near_enabled;
-}
-
-void CameraEffects::set_dof_blur_near_distance(float p_distance) {
- dof_blur_near_distance = p_distance;
- _update_dof_blur();
-}
-
-float CameraEffects::get_dof_blur_near_distance() const {
- return dof_blur_near_distance;
-}
-
-void CameraEffects::set_dof_blur_near_transition(float p_distance) {
- dof_blur_near_transition = p_distance;
- _update_dof_blur();
-}
-
-float CameraEffects::get_dof_blur_near_transition() const {
- return dof_blur_near_transition;
-}
-
-void CameraEffects::set_dof_blur_amount(float p_amount) {
- dof_blur_amount = p_amount;
- _update_dof_blur();
-}
-
-float CameraEffects::get_dof_blur_amount() const {
- return dof_blur_amount;
-}
-
-void CameraEffects::_update_dof_blur() {
- RS::get_singleton()->camera_effects_set_dof_blur(
- camera_effects,
- dof_blur_far_enabled,
- dof_blur_far_distance,
- dof_blur_far_transition,
- dof_blur_near_enabled,
- dof_blur_near_distance,
- dof_blur_near_transition,
- dof_blur_amount);
-}
-
-// Custom exposure
-
-void CameraEffects::set_override_exposure_enabled(bool p_enabled) {
- override_exposure_enabled = p_enabled;
- _update_override_exposure();
- notify_property_list_changed();
-}
-
-bool CameraEffects::is_override_exposure_enabled() const {
- return override_exposure_enabled;
-}
-
-void CameraEffects::set_override_exposure(float p_exposure) {
- override_exposure = p_exposure;
- _update_override_exposure();
-}
-
-float CameraEffects::get_override_exposure() const {
- return override_exposure;
-}
-
-void CameraEffects::_update_override_exposure() {
- RS::get_singleton()->camera_effects_set_custom_exposure(
- camera_effects,
- override_exposure_enabled,
- override_exposure);
-}
-
-// Private methods, constructor and destructor
-
-void CameraEffects::_validate_property(PropertyInfo &p_property) const {
- if ((!dof_blur_far_enabled && (p_property.name == "dof_blur_far_distance" || p_property.name == "dof_blur_far_transition")) ||
- (!dof_blur_near_enabled && (p_property.name == "dof_blur_near_distance" || p_property.name == "dof_blur_near_transition")) ||
- (!override_exposure_enabled && p_property.name == "override_exposure")) {
- p_property.usage = PROPERTY_USAGE_NO_EDITOR;
- }
-}
-
-void CameraEffects::_bind_methods() {
- // DOF blur
-
- ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraEffects::set_dof_blur_far_enabled);
- ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraEffects::is_dof_blur_far_enabled);
- ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "distance"), &CameraEffects::set_dof_blur_far_distance);
- ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraEffects::get_dof_blur_far_distance);
- ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "distance"), &CameraEffects::set_dof_blur_far_transition);
- ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraEffects::get_dof_blur_far_transition);
-
- ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraEffects::set_dof_blur_near_enabled);
- ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraEffects::is_dof_blur_near_enabled);
- ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "distance"), &CameraEffects::set_dof_blur_near_distance);
- ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraEffects::get_dof_blur_near_distance);
- ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "distance"), &CameraEffects::set_dof_blur_near_transition);
- ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraEffects::get_dof_blur_near_transition);
-
- ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "amount"), &CameraEffects::set_dof_blur_amount);
- ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraEffects::get_dof_blur_amount);
-
- ADD_GROUP("DOF Blur", "dof_blur_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
-
- // Override exposure
-
- ClassDB::bind_method(D_METHOD("set_override_exposure_enabled", "enabled"), &CameraEffects::set_override_exposure_enabled);
- ClassDB::bind_method(D_METHOD("is_override_exposure_enabled"), &CameraEffects::is_override_exposure_enabled);
- ClassDB::bind_method(D_METHOD("set_override_exposure", "exposure"), &CameraEffects::set_override_exposure);
- ClassDB::bind_method(D_METHOD("get_override_exposure"), &CameraEffects::get_override_exposure);
-
- ADD_GROUP("Override Exposure", "override_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_exposure_enabled"), "set_override_exposure_enabled", "is_override_exposure_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "override_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_override_exposure", "get_override_exposure");
-}
-
-CameraEffects::CameraEffects() {
- camera_effects = RS::get_singleton()->camera_effects_create();
-
- _update_dof_blur();
- _update_override_exposure();
-}
-
-CameraEffects::~CameraEffects() {
- RS::get_singleton()->free(camera_effects);
-}
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index ee53578517..0ea5264935 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -313,7 +313,7 @@ void Curve::set_max_value(real_t p_max) {
emit_signal(SNAME(SIGNAL_RANGE_CHANGED));
}
-real_t Curve::interpolate(real_t p_offset) const {
+real_t Curve::sample(real_t p_offset) const {
if (_points.size() == 0) {
return 0;
}
@@ -333,10 +333,10 @@ real_t Curve::interpolate(real_t p_offset) const {
return _points[0].position.y;
}
- return interpolate_local_nocheck(i, local);
+ return sample_local_nocheck(i, local);
}
-real_t Curve::interpolate_local_nocheck(int p_index, real_t p_local_offset) const {
+real_t Curve::sample_local_nocheck(int p_index, real_t p_local_offset) const {
const Point a = _points[p_index];
const Point b = _points[p_index + 1];
@@ -440,7 +440,7 @@ void Curve::bake() {
for (int i = 1; i < _bake_resolution - 1; ++i) {
real_t x = i / static_cast<real_t>(_bake_resolution);
- real_t y = interpolate(x);
+ real_t y = sample(x);
_baked_cache.write[i] = y;
}
@@ -459,7 +459,7 @@ void Curve::set_bake_resolution(int p_resolution) {
_baked_cache_dirty = true;
}
-real_t Curve::interpolate_baked(real_t p_offset) const {
+real_t Curve::sample_baked(real_t p_offset) const {
if (_baked_cache_dirty) {
// Last-second bake if not done already
const_cast<Curve *>(this)->bake();
@@ -486,7 +486,7 @@ real_t Curve::interpolate_baked(real_t p_offset) const {
fi = 0;
}
- // Interpolate
+ // Sample
if (i + 1 < _baked_cache.size()) {
real_t t = fi - i;
return Math::lerp(_baked_cache[i], _baked_cache[i + 1], t);
@@ -595,8 +595,8 @@ void Curve::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_position", "index"), &Curve::get_point_position);
ClassDB::bind_method(D_METHOD("set_point_value", "index", "y"), &Curve::set_point_value);
ClassDB::bind_method(D_METHOD("set_point_offset", "index", "offset"), &Curve::set_point_offset);
- ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Curve::interpolate);
- ClassDB::bind_method(D_METHOD("interpolate_baked", "offset"), &Curve::interpolate_baked);
+ ClassDB::bind_method(D_METHOD("sample", "offset"), &Curve::sample);
+ ClassDB::bind_method(D_METHOD("sample_baked", "offset"), &Curve::sample_baked);
ClassDB::bind_method(D_METHOD("get_point_left_tangent", "index"), &Curve::get_point_left_tangent);
ClassDB::bind_method(D_METHOD("get_point_right_tangent", "index"), &Curve::get_point_right_tangent);
ClassDB::bind_method(D_METHOD("get_point_left_mode", "index"), &Curve::get_point_left_mode);
@@ -720,7 +720,7 @@ void Curve2D::clear_points() {
}
}
-Vector2 Curve2D::interpolate(int p_index, const real_t p_offset) const {
+Vector2 Curve2D::sample(int p_index, const real_t p_offset) const {
int pc = points.size();
ERR_FAIL_COND_V(pc == 0, Vector2());
@@ -738,14 +738,14 @@ Vector2 Curve2D::interpolate(int p_index, const real_t p_offset) const {
return p0.bezier_interpolate(p1, p2, p3, p_offset);
}
-Vector2 Curve2D::interpolatef(real_t p_findex) const {
+Vector2 Curve2D::samplef(real_t p_findex) const {
if (p_findex < 0) {
p_findex = 0;
} else if (p_findex >= points.size()) {
p_findex = points.size();
}
- return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0));
+ return sample((int)p_findex, Math::fmod(p_findex, (real_t)1.0));
}
void Curve2D::mark_dirty() {
@@ -883,7 +883,7 @@ real_t Curve2D::get_baked_length() const {
return baked_max_ofs;
}
-Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const {
+Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
if (baked_cache_dirty) {
_bake();
}
@@ -923,7 +923,7 @@ Vector2 Curve2D::interpolate_baked(real_t p_offset, bool p_cubic) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector2(), "failed to find baked segment");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector2(), "Couldn't find baked segment.");
real_t frac = (p_offset - offset_begin) / idx_interval;
@@ -1176,14 +1176,14 @@ void Curve2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_out", "idx"), &Curve2D::get_point_out);
ClassDB::bind_method(D_METHOD("remove_point", "idx"), &Curve2D::remove_point);
ClassDB::bind_method(D_METHOD("clear_points"), &Curve2D::clear_points);
- ClassDB::bind_method(D_METHOD("interpolate", "idx", "t"), &Curve2D::interpolate);
- ClassDB::bind_method(D_METHOD("interpolatef", "fofs"), &Curve2D::interpolatef);
+ ClassDB::bind_method(D_METHOD("sample", "idx", "t"), &Curve2D::sample);
+ ClassDB::bind_method(D_METHOD("samplef", "fofs"), &Curve2D::samplef);
//ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve2D::bake,DEFVAL(10));
ClassDB::bind_method(D_METHOD("set_bake_interval", "distance"), &Curve2D::set_bake_interval);
ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve2D::get_bake_interval);
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
- ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve2D::interpolate_baked, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve2D::sample_baked, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve2D::get_closest_point);
ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve2D::get_closest_offset);
@@ -1309,7 +1309,7 @@ void Curve3D::clear_points() {
}
}
-Vector3 Curve3D::interpolate(int p_index, real_t p_offset) const {
+Vector3 Curve3D::sample(int p_index, real_t p_offset) const {
int pc = points.size();
ERR_FAIL_COND_V(pc == 0, Vector3());
@@ -1327,14 +1327,14 @@ Vector3 Curve3D::interpolate(int p_index, real_t p_offset) const {
return p0.bezier_interpolate(p1, p2, p3, p_offset);
}
-Vector3 Curve3D::interpolatef(real_t p_findex) const {
+Vector3 Curve3D::samplef(real_t p_findex) const {
if (p_findex < 0) {
p_findex = 0;
} else if (p_findex >= points.size()) {
p_findex = points.size();
}
- return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0));
+ return sample((int)p_findex, Math::fmod(p_findex, (real_t)1.0));
}
void Curve3D::mark_dirty() {
@@ -1536,7 +1536,7 @@ real_t Curve3D::get_baked_length() const {
return baked_max_ofs;
}
-Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const {
+Vector3 Curve3D::sample_baked(real_t p_offset, bool p_cubic) const {
if (baked_cache_dirty) {
_bake();
}
@@ -1576,7 +1576,7 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "failed to find baked segment");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(), "Couldn't find baked segment.");
real_t frac = (p_offset - offset_begin) / idx_interval;
@@ -1589,7 +1589,7 @@ Vector3 Curve3D::interpolate_baked(real_t p_offset, bool p_cubic) const {
}
}
-real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const {
+real_t Curve3D::sample_baked_tilt(real_t p_offset) const {
if (baked_cache_dirty) {
_bake();
}
@@ -1629,14 +1629,14 @@ real_t Curve3D::interpolate_baked_tilt(real_t p_offset) const {
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "failed to find baked segment");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, 0, "Couldn't find baked segment.");
real_t frac = (p_offset - offset_begin) / idx_interval;
return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
}
-Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
+Vector3 Curve3D::sample_baked_up_vector(real_t p_offset, bool p_apply_tilt) const {
if (baked_cache_dirty) {
_bake();
}
@@ -1671,7 +1671,7 @@ Vector3 Curve3D::interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt)
real_t offset_end = baked_dist_cache[idx + 1];
real_t idx_interval = offset_end - offset_begin;
- ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "failed to find baked segment");
+ ERR_FAIL_COND_V_MSG(p_offset < offset_begin || p_offset > offset_end, Vector3(0, 1, 0), "Couldn't find baked segment.");
real_t frac = (p_offset - offset_begin) / idx_interval;
@@ -1983,8 +1983,8 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_out", "idx"), &Curve3D::get_point_out);
ClassDB::bind_method(D_METHOD("remove_point", "idx"), &Curve3D::remove_point);
ClassDB::bind_method(D_METHOD("clear_points"), &Curve3D::clear_points);
- ClassDB::bind_method(D_METHOD("interpolate", "idx", "t"), &Curve3D::interpolate);
- ClassDB::bind_method(D_METHOD("interpolatef", "fofs"), &Curve3D::interpolatef);
+ ClassDB::bind_method(D_METHOD("sample", "idx", "t"), &Curve3D::sample);
+ ClassDB::bind_method(D_METHOD("samplef", "fofs"), &Curve3D::samplef);
//ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve3D::bake,DEFVAL(10));
ClassDB::bind_method(D_METHOD("set_bake_interval", "distance"), &Curve3D::set_bake_interval);
ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve3D::get_bake_interval);
@@ -1992,8 +1992,8 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_up_vector_enabled"), &Curve3D::is_up_vector_enabled);
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve3D::get_baked_length);
- ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("interpolate_baked_up_vector", "offset", "apply_tilt"), &Curve3D::interpolate_baked_up_vector, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked", "offset", "cubic"), &Curve3D::sample_baked, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("sample_baked_up_vector", "offset", "apply_tilt"), &Curve3D::sample_baked_up_vector, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
ClassDB::bind_method(D_METHOD("get_baked_up_vectors"), &Curve3D::get_baked_up_vectors);
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 08807b1b6e..88b6dda096 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -100,8 +100,8 @@ public:
real_t get_max_value() const { return _max_value; }
void set_max_value(real_t p_max);
- real_t interpolate(real_t p_offset) const;
- real_t interpolate_local_nocheck(int p_index, real_t p_local_offset) const;
+ real_t sample(real_t p_offset) const;
+ real_t sample_local_nocheck(int p_index, real_t p_local_offset) const;
void clean_dupes();
@@ -123,7 +123,7 @@ public:
void bake();
int get_bake_resolution() const { return _bake_resolution; }
void set_bake_resolution(int p_resolution);
- real_t interpolate_baked(real_t p_offset) const;
+ real_t sample_baked(real_t p_offset) const;
void ensure_default_setup(real_t p_min, real_t p_max);
@@ -208,14 +208,14 @@ public:
void remove_point(int p_index);
void clear_points();
- Vector2 interpolate(int p_index, real_t p_offset) const;
- Vector2 interpolatef(real_t p_findex) const;
+ Vector2 sample(int p_index, real_t p_offset) const;
+ Vector2 samplef(real_t p_findex) const;
void set_bake_interval(real_t p_tolerance);
real_t get_bake_interval() const;
real_t get_baked_length() const;
- Vector2 interpolate_baked(real_t p_offset, bool p_cubic = false) const;
+ Vector2 sample_baked(real_t p_offset, bool p_cubic = false) const;
PackedVector2Array get_baked_points() const; //useful for going through
Vector2 get_closest_point(const Vector2 &p_to_point) const;
real_t get_closest_offset(const Vector2 &p_to_point) const;
@@ -285,8 +285,8 @@ public:
void remove_point(int p_index);
void clear_points();
- Vector3 interpolate(int p_index, real_t p_offset) const;
- Vector3 interpolatef(real_t p_findex) const;
+ Vector3 sample(int p_index, real_t p_offset) const;
+ Vector3 samplef(real_t p_findex) const;
void set_bake_interval(real_t p_tolerance);
real_t get_bake_interval() const;
@@ -294,9 +294,9 @@ public:
bool is_up_vector_enabled() const;
real_t get_baked_length() const;
- Vector3 interpolate_baked(real_t p_offset, bool p_cubic = false) const;
- real_t interpolate_baked_tilt(real_t p_offset) const;
- Vector3 interpolate_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const;
+ Vector3 sample_baked(real_t p_offset, bool p_cubic = false) const;
+ real_t sample_baked_tilt(real_t p_offset) const;
+ Vector3 sample_baked_up_vector(real_t p_offset, bool p_apply_tilt = false) const;
PackedVector3Array get_baked_points() const; //useful for going through
Vector<real_t> get_baked_tilts() const; //useful for going through
PackedVector3Array get_baked_up_vectors() const;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 73ad1ceff7..208e28f17a 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -609,11 +609,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// Dialogs
- theme->set_constant("margin", "Dialogs", 8 * scale);
- theme->set_constant("button_margin", "Dialogs", 32 * scale);
-
- // AcceptDialog
-
+ // AcceptDialog is currently the base dialog, so this defines styles for all extending nodes.
+ theme->set_constant("margin", "AcceptDialog", 8 * scale);
+ theme->set_constant("button_margin", "AcceptDialog", 32 * scale);
theme->set_stylebox("panel", "AcceptDialog", make_flat_stylebox(style_popup_color, 0, 0, 0, 0));
// File Dialog
@@ -998,9 +996,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// Containers
+ theme->set_icon("h_grabber", "SplitContainer", icons["hsplitter"]);
+ theme->set_icon("v_grabber", "SplitContainer", icons["vsplitter"]);
theme->set_icon("grabber", "VSplitContainer", icons["vsplitter"]);
theme->set_icon("grabber", "HSplitContainer", icons["hsplitter"]);
+ theme->set_constant("separation", "BoxContainer", 4 * scale);
theme->set_constant("separation", "HBoxContainer", 4 * scale);
theme->set_constant("separation", "VBoxContainer", 4 * scale);
theme->set_constant("margin_left", "MarginContainer", 0 * scale);
@@ -1009,10 +1010,14 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("margin_bottom", "MarginContainer", 0 * scale);
theme->set_constant("h_separation", "GridContainer", 4 * scale);
theme->set_constant("v_separation", "GridContainer", 4 * scale);
+ theme->set_constant("separation", "SplitContainer", 12 * scale);
theme->set_constant("separation", "HSplitContainer", 12 * scale);
theme->set_constant("separation", "VSplitContainer", 12 * scale);
+ theme->set_constant("autohide", "SplitContainer", 1 * scale);
theme->set_constant("autohide", "HSplitContainer", 1 * scale);
theme->set_constant("autohide", "VSplitContainer", 1 * scale);
+ theme->set_constant("h_separation", "FlowContainer", 4 * scale);
+ theme->set_constant("v_separation", "FlowContainer", 4 * scale);
theme->set_constant("h_separation", "HFlowContainer", 4 * scale);
theme->set_constant("v_separation", "HFlowContainer", 4 * scale);
theme->set_constant("h_separation", "VFlowContainer", 4 * scale);
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index f7a7818b3b..18df59a7aa 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -94,13 +94,30 @@ Color Environment::get_bg_color() const {
return bg_color;
}
-void Environment::set_bg_energy(float p_energy) {
- bg_energy = p_energy;
- RS::get_singleton()->environment_set_bg_energy(environment, p_energy);
+void Environment::set_bg_energy_multiplier(float p_multiplier) {
+ bg_energy_multiplier = p_multiplier;
+ _update_bg_energy();
}
-float Environment::get_bg_energy() const {
- return bg_energy;
+float Environment::get_bg_energy_multiplier() const {
+ return bg_energy_multiplier;
+}
+
+void Environment::set_bg_intensity(float p_exposure_value) {
+ bg_intensity = p_exposure_value;
+ _update_bg_energy();
+}
+
+float Environment::get_bg_intensity() const {
+ return bg_intensity;
+}
+
+void Environment::_update_bg_energy() {
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ RS::get_singleton()->environment_set_bg_energy(environment, bg_energy_multiplier, bg_intensity);
+ } else {
+ RS::get_singleton()->environment_set_bg_energy(environment, bg_energy_multiplier, 1.0);
+ }
}
void Environment::set_canvas_max_layer(int p_max_layer) {
@@ -214,63 +231,12 @@ float Environment::get_tonemap_white() const {
return tonemap_white;
}
-void Environment::set_tonemap_auto_exposure_enabled(bool p_enabled) {
- tonemap_auto_exposure_enabled = p_enabled;
- _update_tonemap();
- notify_property_list_changed();
-}
-
-bool Environment::is_tonemap_auto_exposure_enabled() const {
- return tonemap_auto_exposure_enabled;
-}
-
-void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) {
- tonemap_auto_exposure_min = p_auto_exposure_min;
- _update_tonemap();
-}
-
-float Environment::get_tonemap_auto_exposure_min() const {
- return tonemap_auto_exposure_min;
-}
-
-void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) {
- tonemap_auto_exposure_max = p_auto_exposure_max;
- _update_tonemap();
-}
-
-float Environment::get_tonemap_auto_exposure_max() const {
- return tonemap_auto_exposure_max;
-}
-
-void Environment::set_tonemap_auto_exposure_speed(float p_auto_exposure_speed) {
- tonemap_auto_exposure_speed = p_auto_exposure_speed;
- _update_tonemap();
-}
-
-float Environment::get_tonemap_auto_exposure_speed() const {
- return tonemap_auto_exposure_speed;
-}
-
-void Environment::set_tonemap_auto_exposure_grey(float p_auto_exposure_grey) {
- tonemap_auto_exposure_grey = p_auto_exposure_grey;
- _update_tonemap();
-}
-
-float Environment::get_tonemap_auto_exposure_grey() const {
- return tonemap_auto_exposure_grey;
-}
-
void Environment::_update_tonemap() {
RS::get_singleton()->environment_set_tonemap(
environment,
RS::EnvironmentToneMapper(tone_mapper),
tonemap_exposure,
- tonemap_white,
- tonemap_auto_exposure_enabled,
- tonemap_auto_exposure_min,
- tonemap_auto_exposure_max,
- tonemap_auto_exposure_speed,
- tonemap_auto_exposure_grey);
+ tonemap_white);
}
// SSR
@@ -852,6 +818,15 @@ float Environment::get_fog_aerial_perspective() const {
return fog_aerial_perspective;
}
+void Environment::set_fog_sky_affect(float p_sky_affect) {
+ fog_sky_affect = p_sky_affect;
+ _update_fog();
+}
+
+float Environment::get_fog_sky_affect() const {
+ return fog_sky_affect;
+}
+
void Environment::_update_fog() {
RS::get_singleton()->environment_set_fog(
environment,
@@ -862,13 +837,28 @@ void Environment::_update_fog() {
fog_density,
fog_height,
fog_height_density,
- fog_aerial_perspective);
+ fog_aerial_perspective,
+ fog_sky_affect);
}
// Volumetric Fog
void Environment::_update_volumetric_fog() {
- RS::get_singleton()->environment_set_volumetric_fog(environment, volumetric_fog_enabled, volumetric_fog_density, volumetric_fog_albedo, volumetric_fog_emission, volumetric_fog_emission_energy, volumetric_fog_anisotropy, volumetric_fog_length, volumetric_fog_detail_spread, volumetric_fog_gi_inject, volumetric_fog_temporal_reproject, volumetric_fog_temporal_reproject_amount, volumetric_fog_ambient_inject);
+ RS::get_singleton()->environment_set_volumetric_fog(
+ environment,
+ volumetric_fog_enabled,
+ volumetric_fog_density,
+ volumetric_fog_albedo,
+ volumetric_fog_emission,
+ volumetric_fog_emission_energy,
+ volumetric_fog_anisotropy,
+ volumetric_fog_length,
+ volumetric_fog_detail_spread,
+ volumetric_fog_gi_inject,
+ volumetric_fog_temporal_reproject,
+ volumetric_fog_temporal_reproject_amount,
+ volumetric_fog_ambient_inject,
+ volumetric_fog_sky_affect);
}
void Environment::set_volumetric_fog_enabled(bool p_enable) {
@@ -946,6 +936,15 @@ float Environment::get_volumetric_fog_ambient_inject() const {
return volumetric_fog_ambient_inject;
}
+void Environment::set_volumetric_fog_sky_affect(float p_sky_affect) {
+ volumetric_fog_sky_affect = p_sky_affect;
+ _update_volumetric_fog();
+}
+
+float Environment::get_volumetric_fog_sky_affect() const {
+ return volumetric_fog_sky_affect;
+}
+
void Environment::set_volumetric_fog_temporal_reprojection_enabled(bool p_enable) {
volumetric_fog_temporal_reproject = p_enable;
_update_volumetric_fog();
@@ -1080,10 +1079,13 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
}
}
+ if (p_property.name == "background_intensity" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
static const char *hide_prefixes[] = {
"fog_",
"volumetric_fog_",
- "auto_exposure_",
"ssr_",
"ssao_",
"ssil_",
@@ -1095,7 +1097,6 @@ void Environment::_validate_property(PropertyInfo &p_property) const {
};
static const char *high_end_prefixes[] = {
- "auto_exposure_",
"ssr_",
"ssao_",
nullptr
@@ -1162,8 +1163,10 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation);
ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color);
ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color);
- ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy);
- ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy);
+ ClassDB::bind_method(D_METHOD("set_bg_energy_multiplier", "energy"), &Environment::set_bg_energy_multiplier);
+ ClassDB::bind_method(D_METHOD("get_bg_energy_multiplier"), &Environment::get_bg_energy_multiplier);
+ ClassDB::bind_method(D_METHOD("set_bg_intensity", "energy"), &Environment::set_bg_intensity);
+ ClassDB::bind_method(D_METHOD("get_bg_intensity"), &Environment::get_bg_intensity);
ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer);
ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer);
ClassDB::bind_method(D_METHOD("set_camera_feed_id", "id"), &Environment::set_camera_feed_id);
@@ -1172,7 +1175,9 @@ void Environment::_bind_methods() {
ADD_GROUP("Background", "background_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy_multiplier", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy_multiplier", "get_bg_energy_multiplier");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_intensity", PROPERTY_HINT_RANGE, "0,100000,0.01,suffix:nt"), "set_bg_intensity", "get_bg_intensity");
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id");
@@ -1211,27 +1216,11 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tonemap_exposure"), &Environment::get_tonemap_exposure);
ClassDB::bind_method(D_METHOD("set_tonemap_white", "white"), &Environment::set_tonemap_white);
ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white);
- ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_enabled", "enabled"), &Environment::set_tonemap_auto_exposure_enabled);
- ClassDB::bind_method(D_METHOD("is_tonemap_auto_exposure_enabled"), &Environment::is_tonemap_auto_exposure_enabled);
- ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max", "exposure_max"), &Environment::set_tonemap_auto_exposure_max);
- ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"), &Environment::get_tonemap_auto_exposure_max);
- ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min", "exposure_min"), &Environment::set_tonemap_auto_exposure_min);
- ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"), &Environment::get_tonemap_auto_exposure_min);
- ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed", "exposure_speed"), &Environment::set_tonemap_auto_exposure_speed);
- ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"), &Environment::get_tonemap_auto_exposure_speed);
- ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey", "exposure_grey"), &Environment::set_tonemap_auto_exposure_grey);
- ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"), &Environment::get_tonemap_auto_exposure_grey);
ADD_GROUP("Tonemap", "tonemap_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES"), "set_tonemapper", "get_tonemapper");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white");
- ADD_GROUP("Auto Exposure", "auto_exposure_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure_enabled", "is_tonemap_auto_exposure_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed");
// SSR
@@ -1419,6 +1408,9 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fog_aerial_perspective", "aerial_perspective"), &Environment::set_fog_aerial_perspective);
ClassDB::bind_method(D_METHOD("get_fog_aerial_perspective"), &Environment::get_fog_aerial_perspective);
+ ClassDB::bind_method(D_METHOD("set_fog_sky_affect", "sky_affect"), &Environment::set_fog_sky_affect);
+ ClassDB::bind_method(D_METHOD("get_fog_sky_affect"), &Environment::get_fog_sky_affect);
+
ADD_GROUP("Fog", "fog_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_fog_light_color", "get_fog_light_color");
@@ -1427,6 +1419,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater"), "set_fog_density", "get_fog_density");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_aerial_perspective", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_aerial_perspective", "get_fog_aerial_perspective");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sky_affect", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_fog_sky_affect", "get_fog_sky_affect");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater,suffix:m"), "set_fog_height", "get_fog_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "-16,16,0.0001,or_lesser,or_greater"), "set_fog_height_density", "get_fog_height_density");
@@ -1450,6 +1443,8 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_volumetric_fog_gi_inject"), &Environment::get_volumetric_fog_gi_inject);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_ambient_inject", "enabled"), &Environment::set_volumetric_fog_ambient_inject);
ClassDB::bind_method(D_METHOD("get_volumetric_fog_ambient_inject"), &Environment::get_volumetric_fog_ambient_inject);
+ ClassDB::bind_method(D_METHOD("set_volumetric_fog_sky_affect", "sky_affect"), &Environment::set_volumetric_fog_sky_affect);
+ ClassDB::bind_method(D_METHOD("get_volumetric_fog_sky_affect"), &Environment::get_volumetric_fog_sky_affect);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_temporal_reprojection_enabled", "enabled"), &Environment::set_volumetric_fog_temporal_reprojection_enabled);
ClassDB::bind_method(D_METHOD("is_volumetric_fog_temporal_reprojection_enabled"), &Environment::is_volumetric_fog_temporal_reprojection_enabled);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_temporal_reprojection_amount", "temporal_reprojection_amount"), &Environment::set_volumetric_fog_temporal_reprojection_amount);
@@ -1466,6 +1461,7 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "positive_only"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_ambient_inject", PROPERTY_HINT_RANGE, "0.0,16,0.01,exp"), "set_volumetric_fog_ambient_inject", "get_volumetric_fog_ambient_inject");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_sky_affect", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_volumetric_fog_sky_affect", "get_volumetric_fog_sky_affect");
ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_temporal_reprojection_enabled"), "set_volumetric_fog_temporal_reprojection_enabled", "is_volumetric_fog_temporal_reprojection_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_temporal_reprojection_amount", PROPERTY_HINT_RANGE, "0.5,0.99,0.001"), "set_volumetric_fog_temporal_reprojection_amount", "get_volumetric_fog_temporal_reprojection_amount");
@@ -1549,6 +1545,7 @@ Environment::Environment() {
_update_fog();
_update_adjustment();
_update_volumetric_fog();
+ _update_bg_energy();
notify_property_list_changed();
}
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index d39cb1acd8..507a0cee39 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -92,9 +92,11 @@ private:
float bg_sky_custom_fov = 0.0;
Vector3 bg_sky_rotation;
Color bg_color;
- float bg_energy = 1.0;
int bg_canvas_max_layer = 0;
int bg_camera_feed_id = 1;
+ float bg_energy_multiplier = 1.0;
+ float bg_intensity = 30000.0; // Measured in nits or candela/m^2
+ void _update_bg_energy();
// Ambient light
Color ambient_color;
@@ -108,11 +110,6 @@ private:
ToneMapper tone_mapper = TONE_MAPPER_LINEAR;
float tonemap_exposure = 1.0;
float tonemap_white = 1.0;
- bool tonemap_auto_exposure_enabled = false;
- float tonemap_auto_exposure_min = 0.05;
- float tonemap_auto_exposure_max = 8.0;
- float tonemap_auto_exposure_speed = 0.5;
- float tonemap_auto_exposure_grey = 0.4;
void _update_tonemap();
// SSR
@@ -182,6 +179,7 @@ private:
float fog_height = 0.0;
float fog_height_density = 0.0; //can be negative to invert effect
float fog_aerial_perspective = 0.0;
+ float fog_sky_affect = 1.0;
void _update_fog();
@@ -196,6 +194,7 @@ private:
float volumetric_fog_detail_spread = 2.0;
float volumetric_fog_gi_inject = 1.0;
float volumetric_fog_ambient_inject = 0.0;
+ float volumetric_fog_sky_affect = 1.0;
bool volumetric_fog_temporal_reproject = true;
float volumetric_fog_temporal_reproject_amount = 0.9;
void _update_volumetric_fog();
@@ -231,8 +230,10 @@ public:
Vector3 get_sky_rotation() const;
void set_bg_color(const Color &p_color);
Color get_bg_color() const;
- void set_bg_energy(float p_energy);
- float get_bg_energy() const;
+ void set_bg_energy_multiplier(float p_energy);
+ float get_bg_energy_multiplier() const;
+ void set_bg_intensity(float p_energy);
+ float get_bg_intensity() const;
void set_canvas_max_layer(int p_max_layer);
int get_canvas_max_layer() const;
void set_camera_feed_id(int p_id);
@@ -257,16 +258,6 @@ public:
float get_tonemap_exposure() const;
void set_tonemap_white(float p_white);
float get_tonemap_white() const;
- void set_tonemap_auto_exposure_enabled(bool p_enabled);
- bool is_tonemap_auto_exposure_enabled() const;
- void set_tonemap_auto_exposure_min(float p_auto_exposure_min);
- float get_tonemap_auto_exposure_min() const;
- void set_tonemap_auto_exposure_max(float p_auto_exposure_max);
- float get_tonemap_auto_exposure_max() const;
- void set_tonemap_auto_exposure_speed(float p_auto_exposure_speed);
- float get_tonemap_auto_exposure_speed() const;
- void set_tonemap_auto_exposure_grey(float p_auto_exposure_grey);
- float get_tonemap_auto_exposure_grey() const;
// SSR
void set_ssr_enabled(bool p_enabled);
@@ -385,6 +376,8 @@ public:
float get_fog_height_density() const;
void set_fog_aerial_perspective(float p_aerial_perspective);
float get_fog_aerial_perspective() const;
+ void set_fog_sky_affect(float p_sky_affect);
+ float get_fog_sky_affect() const;
// Volumetric Fog
void set_volumetric_fog_enabled(bool p_enable);
@@ -407,6 +400,8 @@ public:
float get_volumetric_fog_gi_inject() const;
void set_volumetric_fog_ambient_inject(float p_ambient_inject);
float get_volumetric_fog_ambient_inject() const;
+ void set_volumetric_fog_sky_affect(float p_sky_affect);
+ float get_volumetric_fog_sky_affect() const;
void set_volumetric_fog_temporal_reprojection_enabled(bool p_enable);
bool is_volumetric_fog_temporal_reprojection_enabled() const;
void set_volumetric_fog_temporal_reprojection_amount(float p_amount);
diff --git a/scene/resources/gradient.cpp b/scene/resources/gradient.cpp
index a9c44dc6bf..f04eb75d86 100644
--- a/scene/resources/gradient.cpp
+++ b/scene/resources/gradient.cpp
@@ -56,7 +56,7 @@ void Gradient::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &Gradient::set_color);
ClassDB::bind_method(D_METHOD("get_color", "point"), &Gradient::get_color);
- ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Gradient::get_color_at_offset);
+ ClassDB::bind_method(D_METHOD("sample", "offset"), &Gradient::get_color_at_offset);
ClassDB::bind_method(D_METHOD("get_point_count"), &Gradient::get_points_count);
diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h
index e4bac15e4b..2b91331ab0 100644
--- a/scene/resources/gradient.h
+++ b/scene/resources/gradient.h
@@ -122,7 +122,7 @@ public:
}
}
- // Return interpolated value.
+ // Return sampled value.
if (points[middle].offset > p_offset) {
middle--;
}
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 32ddef1693..448ff74a53 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -31,6 +31,8 @@
#include "material.h"
#include "core/config/engine.h"
+#include "core/config/project_settings.h"
+#include "core/error/error_macros.h"
#include "core/version.h"
#include "scene/main/scene_tree.h"
#include "scene/scene_string_names.h"
@@ -157,15 +159,16 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) {
StringName pr = shader->remap_uniform(p_name);
if (!pr) {
String n = p_name;
- if (n.find("param/") == 0) { //backwards compatibility
- pr = n.substr(6, n.length());
- }
- if (n.find("shader_uniform/") == 0) { //backwards compatibility
+ if (n.find("shader_parameter/") == 0) { //backwards compatibility
+ pr = n.replace_first("shader_parameter/", "");
+ } else if (n.find("shader_uniform/") == 0) { //backwards compatibility
pr = n.replace_first("shader_uniform/", "");
+ } else if (n.find("param/") == 0) { //backwards compatibility
+ pr = n.substr(6, n.length());
}
}
if (pr) {
- set_shader_uniform(pr, p_value);
+ set_shader_parameter(pr, p_value);
return true;
}
}
@@ -178,11 +181,12 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const {
StringName pr = shader->remap_uniform(p_name);
if (!pr) {
String n = p_name;
- if (n.find("param/") == 0) { //backwards compatibility
- pr = n.substr(6, n.length());
- }
- if (n.find("shader_uniform/") == 0) { //backwards compatibility
+ if (n.find("shader_parameter/") == 0) { //backwards compatibility
+ pr = n.replace_first("shader_parameter/", "");
+ } else if (n.find("shader_uniform/") == 0) { //backwards compatibility
pr = n.replace_first("shader_uniform/", "");
+ } else if (n.find("param/") == 0) { //backwards compatibility
+ pr = n.substr(6, n.length());
}
}
@@ -301,7 +305,7 @@ bool ShaderMaterial::_property_can_revert(const StringName &p_name) const {
if (shader.is_valid()) {
StringName pr = shader->remap_uniform(p_name);
if (pr) {
- Variant default_value = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr);
+ Variant default_value = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), pr);
Variant current_value;
_get(p_name, current_value);
return default_value.get_type() != Variant::NIL && default_value != current_value;
@@ -314,7 +318,7 @@ bool ShaderMaterial::_property_get_revert(const StringName &p_name, Variant &r_p
if (shader.is_valid()) {
StringName pr = shader->remap_uniform(p_name);
if (pr) {
- r_property = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr);
+ r_property = RenderingServer::get_singleton()->shader_get_parameter_default(shader->get_rid(), pr);
return true;
}
}
@@ -349,7 +353,7 @@ Ref<Shader> ShaderMaterial::get_shader() const {
return shader;
}
-void ShaderMaterial::set_shader_uniform(const StringName &p_param, const Variant &p_value) {
+void ShaderMaterial::set_shader_parameter(const StringName &p_param, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
param_cache.erase(p_param);
RS::get_singleton()->material_set_param(_get_material(), p_param, Variant());
@@ -369,7 +373,7 @@ void ShaderMaterial::set_shader_uniform(const StringName &p_param, const Variant
}
}
-Variant ShaderMaterial::get_shader_uniform(const StringName &p_param) const {
+Variant ShaderMaterial::get_shader_parameter(const StringName &p_param) const {
if (param_cache.has(p_param)) {
return param_cache[p_param];
} else {
@@ -384,20 +388,20 @@ void ShaderMaterial::_shader_changed() {
void ShaderMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader);
ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader);
- ClassDB::bind_method(D_METHOD("set_shader_uniform", "param", "value"), &ShaderMaterial::set_shader_uniform);
- ClassDB::bind_method(D_METHOD("get_shader_uniform", "param"), &ShaderMaterial::get_shader_uniform);
+ ClassDB::bind_method(D_METHOD("set_shader_parameter", "param", "value"), &ShaderMaterial::set_shader_parameter);
+ ClassDB::bind_method(D_METHOD("get_shader_parameter", "param"), &ShaderMaterial::get_shader_parameter);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"), "set_shader", "get_shader");
}
void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
String f = p_function.operator String();
- if ((f == "get_shader_uniform" || f == "set_shader_uniform") && p_idx == 0) {
+ if ((f == "get_shader_parameter" || f == "set_shader_parameter") && p_idx == 0) {
if (shader.is_valid()) {
List<PropertyInfo> pl;
shader->get_shader_uniform_list(&pl);
for (const PropertyInfo &E : pl) {
- r_options->push_back(E.name.replace_first("shader_uniform/", "").quote());
+ r_options->push_back(E.name.replace_first("shader_parameter/", "").quote());
}
}
}
@@ -1504,13 +1508,27 @@ Color BaseMaterial3D::get_emission() const {
return emission;
}
-void BaseMaterial3D::set_emission_energy(float p_emission_energy) {
- emission_energy = p_emission_energy;
- RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy);
+void BaseMaterial3D::set_emission_energy_multiplier(float p_emission_energy_multiplier) {
+ emission_energy_multiplier = p_emission_energy_multiplier;
+ if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy_multiplier * emission_intensity);
+ } else {
+ RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy_multiplier);
+ }
+}
+
+float BaseMaterial3D::get_emission_energy_multiplier() const {
+ return emission_energy_multiplier;
+}
+
+void BaseMaterial3D::set_emission_intensity(float p_emission_intensity) {
+ ERR_FAIL_COND_EDMSG(!GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units"), "Cannot set material emission intensity when Physical Light Units disabled.");
+ emission_intensity = p_emission_intensity;
+ RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, emission_energy_multiplier * emission_intensity);
}
-float BaseMaterial3D::get_emission_energy() const {
- return emission_energy;
+float BaseMaterial3D::get_emission_intensity() const {
+ return emission_intensity;
}
void BaseMaterial3D::set_normal_scale(float p_normal_scale) {
@@ -1884,6 +1902,10 @@ void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const {
_validate_high_end("subsurf_scatter", p_property);
_validate_high_end("heightmap", p_property);
+ if (p_property.name == "emission_intensity" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+
if (p_property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) {
p_property.usage = PROPERTY_USAGE_NONE;
}
@@ -2463,8 +2485,11 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emission", "emission"), &BaseMaterial3D::set_emission);
ClassDB::bind_method(D_METHOD("get_emission"), &BaseMaterial3D::get_emission);
- ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &BaseMaterial3D::set_emission_energy);
- ClassDB::bind_method(D_METHOD("get_emission_energy"), &BaseMaterial3D::get_emission_energy);
+ ClassDB::bind_method(D_METHOD("set_emission_energy_multiplier", "emission_energy_multiplier"), &BaseMaterial3D::set_emission_energy_multiplier);
+ ClassDB::bind_method(D_METHOD("get_emission_energy_multiplier"), &BaseMaterial3D::get_emission_energy_multiplier);
+
+ ClassDB::bind_method(D_METHOD("set_emission_intensity", "emission_energy_multiplier"), &BaseMaterial3D::set_emission_intensity);
+ ClassDB::bind_method(D_METHOD("get_emission_intensity"), &BaseMaterial3D::get_emission_intensity);
ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &BaseMaterial3D::set_normal_scale);
ClassDB::bind_method(D_METHOD("get_normal_scale"), &BaseMaterial3D::get_normal_scale);
@@ -2681,7 +2706,9 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Emission", "emission_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy_multiplier", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy_multiplier", "get_emission_energy_multiplier");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_intensity", PROPERTY_HINT_RANGE, "0,100000.0,0.01,or_greater,suffix:nt"), "set_emission_intensity", "get_emission_intensity");
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION);
@@ -2943,7 +2970,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_roughness(1.0);
set_metallic(0.0);
set_emission(Color(0, 0, 0));
- set_emission_energy(1.0);
+ set_emission_energy_multiplier(1.0);
set_normal_scale(1);
set_rim(1.0);
set_rim_tint(0.5);
@@ -3096,6 +3123,8 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value)
{ "depth_flip_binormal", "heightmap_flip_binormal" },
{ "depth_texture", "heightmap_texture" },
+ { "emission_energy", "emission_energy_multiplier" },
+
{ nullptr, nullptr },
};
diff --git a/scene/resources/material.h b/scene/resources/material.h
index c6be1b8766..6c81293ee3 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -115,8 +115,8 @@ public:
void set_shader(const Ref<Shader> &p_shader);
Ref<Shader> get_shader() const;
- void set_shader_uniform(const StringName &p_param, const Variant &p_value);
- Variant get_shader_uniform(const StringName &p_param) const;
+ void set_shader_parameter(const StringName &p_param, const Variant &p_value);
+ Variant get_shader_parameter(const StringName &p_param) const;
virtual Shader::Mode get_shader_mode() const override;
@@ -467,7 +467,8 @@ private:
float metallic = 0.0f;
float roughness = 0.0f;
Color emission;
- float emission_energy = 0.0f;
+ float emission_energy_multiplier = 1.0f;
+ float emission_intensity = 1000.0f; // In nits, equivalent to indoor lighting.
float normal_scale = 0.0f;
float rim = 0.0f;
float rim_tint = 0.0f;
@@ -573,8 +574,11 @@ public:
void set_emission(const Color &p_emission);
Color get_emission() const;
- void set_emission_energy(float p_emission_energy);
- float get_emission_energy() const;
+ void set_emission_energy_multiplier(float p_emission_energy_multiplier);
+ float get_emission_energy_multiplier() const;
+
+ void set_emission_intensity(float p_emission_intensity);
+ float get_emission_intensity() const;
void set_normal_scale(float p_normal_scale);
float get_normal_scale() const;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index fc5cf2a028..727f7a4e09 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -1822,7 +1822,7 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
float r = radius;
if (curve.is_valid() && curve->get_point_count() > 0) {
- r *= curve->interpolate_baked(v);
+ r *= curve->sample_baked(v);
}
float x = sin(u * Math_TAU);
float z = cos(u * Math_TAU);
@@ -1863,7 +1863,7 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
// add top
float scale_pos = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
- scale_pos = curve->interpolate_baked(0);
+ scale_pos = curve->sample_baked(0);
}
if (scale_pos > CMP_EPSILON) {
@@ -1925,7 +1925,7 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
float scale_neg = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
- scale_neg = curve->interpolate_baked(1.0);
+ scale_neg = curve->sample_baked(1.0);
}
// add bottom
@@ -2138,7 +2138,7 @@ void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const {
float s = size;
if (curve.is_valid() && curve->get_point_count() > 0) {
- s *= curve->interpolate_baked(v);
+ s *= curve->sample_baked(v);
}
points.push_back(Vector3(-s * 0.5, y, 0));
diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp
index a64b262cb4..6ebf96db8e 100644
--- a/scene/resources/rectangle_shape_2d.cpp
+++ b/scene/resources/rectangle_shape_2d.cpp
@@ -41,7 +41,7 @@ void RectangleShape2D::_update_shape() {
bool RectangleShape2D::_set(const StringName &p_name, const Variant &p_value) {
if (p_name == "extents") { // Compatibility with Godot 3.x.
// Convert to `size`, twice as big.
- set_size((Vector2)p_value * 2);
+ set_size((Size2)p_value * 2);
return true;
}
return false;
@@ -57,13 +57,13 @@ bool RectangleShape2D::_get(const StringName &p_name, Variant &r_property) const
}
#endif // DISABLE_DEPRECATED
-void RectangleShape2D::set_size(const Vector2 &p_size) {
+void RectangleShape2D::set_size(const Size2 &p_size) {
ERR_FAIL_COND_MSG(p_size.x < 0 || p_size.y < 0, "RectangleShape2D size cannot be negative.");
size = p_size;
_update_shape();
}
-Vector2 RectangleShape2D::get_size() const {
+Size2 RectangleShape2D::get_size() const {
return size;
}
@@ -106,6 +106,6 @@ void RectangleShape2D::_bind_methods() {
RectangleShape2D::RectangleShape2D() :
Shape2D(PhysicsServer2D::get_singleton()->rectangle_shape_create()) {
- size = Vector2(20, 20);
+ size = Size2(20, 20);
_update_shape();
}
diff --git a/scene/resources/rectangle_shape_2d.h b/scene/resources/rectangle_shape_2d.h
index fa85aef428..9cc7b999be 100644
--- a/scene/resources/rectangle_shape_2d.h
+++ b/scene/resources/rectangle_shape_2d.h
@@ -36,7 +36,7 @@
class RectangleShape2D : public Shape2D {
GDCLASS(RectangleShape2D, Shape2D);
- Vector2 size;
+ Size2 size;
void _update_shape();
protected:
@@ -47,8 +47,8 @@ protected:
#endif // DISABLE_DEPRECATED
public:
- void set_size(const Vector2 &p_size);
- Vector2 get_size() const;
+ void set_size(const Size2 &p_size);
+ Size2 get_size() const;
virtual void draw(const RID &p_to_rid, const Color &p_color) override;
virtual Rect2 get_rect() const override;
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 48d06934e3..4d566178a5 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -107,7 +107,7 @@ void Shader::get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_gr
_update_shader();
List<PropertyInfo> local;
- RenderingServer::get_singleton()->shader_get_shader_uniform_list(shader, &local);
+ RenderingServer::get_singleton()->get_shader_parameter_list(shader, &local);
params_cache.clear();
params_cache_dirty = false;
@@ -138,35 +138,35 @@ RID Shader::get_rid() const {
return shader;
}
-void Shader::set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture, int p_index) {
+void Shader::set_default_texture_parameter(const StringName &p_name, const Ref<Texture2D> &p_texture, int p_index) {
if (p_texture.is_valid()) {
- if (!default_textures.has(p_param)) {
- default_textures[p_param] = HashMap<int, Ref<Texture2D>>();
+ if (!default_textures.has(p_name)) {
+ default_textures[p_name] = HashMap<int, Ref<Texture2D>>();
}
- default_textures[p_param][p_index] = p_texture;
- RS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid(), p_index);
+ default_textures[p_name][p_index] = p_texture;
+ RS::get_singleton()->shader_set_default_texture_parameter(shader, p_name, p_texture->get_rid(), p_index);
} else {
- if (default_textures.has(p_param) && default_textures[p_param].has(p_index)) {
- default_textures[p_param].erase(p_index);
+ if (default_textures.has(p_name) && default_textures[p_name].has(p_index)) {
+ default_textures[p_name].erase(p_index);
- if (default_textures[p_param].is_empty()) {
- default_textures.erase(p_param);
+ if (default_textures[p_name].is_empty()) {
+ default_textures.erase(p_name);
}
}
- RS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID(), p_index);
+ RS::get_singleton()->shader_set_default_texture_parameter(shader, p_name, RID(), p_index);
}
emit_changed();
}
-Ref<Texture2D> Shader::get_default_texture_param(const StringName &p_param, int p_index) const {
- if (default_textures.has(p_param) && default_textures[p_param].has(p_index)) {
- return default_textures[p_param][p_index];
+Ref<Texture2D> Shader::get_default_texture_parameter(const StringName &p_name, int p_index) const {
+ if (default_textures.has(p_name) && default_textures[p_name].has(p_index)) {
+ return default_textures[p_name][p_index];
}
return Ref<Texture2D>();
}
-void Shader::get_default_texture_param_list(List<StringName> *r_textures) const {
+void Shader::get_default_texture_parameter_list(List<StringName> *r_textures) const {
for (const KeyValue<StringName, HashMap<int, Ref<Texture2D>>> &E : default_textures) {
r_textures->push_back(E.key);
}
@@ -176,8 +176,8 @@ bool Shader::is_text_shader() const {
return true;
}
-bool Shader::has_uniform(const StringName &p_param) const {
- return params_cache.has("shader_uniform/" + p_param);
+bool Shader::has_parameter(const StringName &p_name) const {
+ return params_cache.has("shader_parameter/" + p_name);
}
void Shader::_update_shader() const {
@@ -189,10 +189,10 @@ void Shader::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_code", "code"), &Shader::set_code);
ClassDB::bind_method(D_METHOD("get_code"), &Shader::get_code);
- ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture", "index"), &Shader::set_default_texture_param, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_default_texture_param", "param", "index"), &Shader::get_default_texture_param, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("set_default_texture_parameter", "name", "texture", "index"), &Shader::set_default_texture_parameter, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_default_texture_parameter", "name", "index"), &Shader::get_default_texture_parameter, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("has_uniform", "name"), &Shader::has_uniform);
+ ClassDB::bind_method(D_METHOD("has_parameter", "name"), &Shader::has_parameter);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_code", "get_code");
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index abc953de5f..d267e6520e 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -79,11 +79,11 @@ public:
String get_code() const;
void get_shader_uniform_list(List<PropertyInfo> *p_params, bool p_get_groups = false) const;
- bool has_uniform(const StringName &p_param) const;
+ bool has_parameter(const StringName &p_name) const;
- void set_default_texture_param(const StringName &p_uniform, const Ref<Texture2D> &p_texture, int p_index = 0);
- Ref<Texture2D> get_default_texture_param(const StringName &p_uniform, int p_index = 0) const;
- void get_default_texture_param_list(List<StringName> *r_textures) const;
+ void set_default_texture_parameter(const StringName &p_name, const Ref<Texture2D> &p_texture, int p_index = 0);
+ Ref<Texture2D> get_default_texture_parameter(const StringName &p_name, int p_index = 0) const;
+ void get_default_texture_parameter_list(List<StringName> *r_textures) const;
virtual bool is_text_shader() const;
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 737c50e570..fc999d5fcb 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -30,6 +30,7 @@
#include "sky_material.h"
+#include "core/config/project_settings.h"
#include "core/version.h"
Mutex ProceduralSkyMaterial::shader_mutex;
@@ -62,13 +63,13 @@ float ProceduralSkyMaterial::get_sky_curve() const {
return sky_curve;
}
-void ProceduralSkyMaterial::set_sky_energy(float p_energy) {
- sky_energy = p_energy;
- RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy);
+void ProceduralSkyMaterial::set_sky_energy_multiplier(float p_multiplier) {
+ sky_energy_multiplier = p_multiplier;
+ RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy_multiplier);
}
-float ProceduralSkyMaterial::get_sky_energy() const {
- return sky_energy;
+float ProceduralSkyMaterial::get_sky_energy_multiplier() const {
+ return sky_energy_multiplier;
}
void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) {
@@ -117,13 +118,13 @@ float ProceduralSkyMaterial::get_ground_curve() const {
return ground_curve;
}
-void ProceduralSkyMaterial::set_ground_energy(float p_energy) {
- ground_energy = p_energy;
- RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy);
+void ProceduralSkyMaterial::set_ground_energy_multiplier(float p_multiplier) {
+ ground_energy_multiplier = p_multiplier;
+ RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy_multiplier);
}
-float ProceduralSkyMaterial::get_ground_energy() const {
- return ground_energy;
+float ProceduralSkyMaterial::get_ground_energy_multiplier() const {
+ return ground_energy_multiplier;
}
void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) {
@@ -171,6 +172,12 @@ RID ProceduralSkyMaterial::get_shader_rid() const {
return shader;
}
+void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const {
+ if ((p_property.name == "sky_luminance" || p_property.name == "ground_luminance") && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+}
+
void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color);
ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color);
@@ -181,8 +188,8 @@ void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve);
ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve);
- ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy);
- ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy);
+ ClassDB::bind_method(D_METHOD("set_sky_energy_multiplier", "multiplier"), &ProceduralSkyMaterial::set_sky_energy_multiplier);
+ ClassDB::bind_method(D_METHOD("get_sky_energy_multiplier"), &ProceduralSkyMaterial::get_sky_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_sky_cover", "sky_cover"), &ProceduralSkyMaterial::set_sky_cover);
ClassDB::bind_method(D_METHOD("get_sky_cover"), &ProceduralSkyMaterial::get_sky_cover);
@@ -199,8 +206,8 @@ void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve);
ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve);
- ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSkyMaterial::set_ground_energy);
- ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSkyMaterial::get_ground_energy);
+ ClassDB::bind_method(D_METHOD("set_ground_energy_multiplier", "energy"), &ProceduralSkyMaterial::set_ground_energy_multiplier);
+ ClassDB::bind_method(D_METHOD("get_ground_energy_multiplier"), &ProceduralSkyMaterial::get_ground_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max);
ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max);
@@ -215,7 +222,7 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_top_color", "get_sky_top_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy_multiplier", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy_multiplier", "get_sky_energy_multiplier");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_sky_cover", "get_sky_cover");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate"), "set_sky_cover_modulate", "get_sky_cover_modulate");
@@ -223,7 +230,7 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_horizon_color", "get_ground_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy_multiplier", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy_multiplier", "get_ground_energy_multiplier");
ADD_GROUP("Sun", "sun_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01,degrees"), "set_sun_angle_max", "get_sun_angle_max");
@@ -253,7 +260,7 @@ shader_type sky;
uniform vec4 sky_top_color : source_color = vec4(0.385, 0.454, 0.55, 1.0);
uniform vec4 sky_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0);
uniform float sky_curve : hint_range(0, 1) = 0.15;
-uniform float sky_energy = 1.0;
+uniform float sky_energy = 1.0; // In Lux.
uniform sampler2D sky_cover : source_color, hint_default_black;
uniform vec4 sky_cover_modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 ground_bottom_color : source_color = vec4(0.2, 0.169, 0.133, 1.0);
@@ -338,13 +345,13 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
set_sky_top_color(Color(0.385, 0.454, 0.55));
set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708));
set_sky_curve(0.15);
- set_sky_energy(1.0);
+ set_sky_energy_multiplier(1.0);
set_sky_cover_modulate(Color(1, 1, 1));
set_ground_bottom_color(Color(0.2, 0.169, 0.133));
set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708));
set_ground_curve(0.02);
- set_ground_energy(1.0);
+ set_ground_energy_multiplier(1.0);
set_sun_angle_max(30.0);
set_sun_curve(0.15);
@@ -528,13 +535,13 @@ Color PhysicalSkyMaterial::get_ground_color() const {
return ground_color;
}
-void PhysicalSkyMaterial::set_exposure(float p_exposure) {
- exposure = p_exposure;
- RS::get_singleton()->material_set_param(_get_material(), "exposure", exposure);
+void PhysicalSkyMaterial::set_energy_multiplier(float p_multiplier) {
+ energy_multiplier = p_multiplier;
+ RS::get_singleton()->material_set_param(_get_material(), "exposure", energy_multiplier);
}
-float PhysicalSkyMaterial::get_exposure() const {
- return exposure;
+float PhysicalSkyMaterial::get_energy_multiplier() const {
+ return energy_multiplier;
}
void PhysicalSkyMaterial::set_use_debanding(bool p_use_debanding) {
@@ -574,6 +581,12 @@ RID PhysicalSkyMaterial::get_shader_rid() const {
return shader;
}
+void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "exposure_value" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+}
+
Mutex PhysicalSkyMaterial::shader_mutex;
RID PhysicalSkyMaterial::shader;
@@ -602,8 +615,8 @@ void PhysicalSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color);
ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color);
- ClassDB::bind_method(D_METHOD("set_exposure", "exposure"), &PhysicalSkyMaterial::set_exposure);
- ClassDB::bind_method(D_METHOD("get_exposure"), &PhysicalSkyMaterial::get_exposure);
+ ClassDB::bind_method(D_METHOD("set_energy_multiplier", "multiplier"), &PhysicalSkyMaterial::set_energy_multiplier);
+ ClassDB::bind_method(D_METHOD("get_energy_multiplier"), &PhysicalSkyMaterial::get_energy_multiplier);
ClassDB::bind_method(D_METHOD("set_use_debanding", "use_debanding"), &PhysicalSkyMaterial::set_use_debanding);
ClassDB::bind_method(D_METHOD("get_use_debanding"), &PhysicalSkyMaterial::get_use_debanding);
@@ -623,7 +636,7 @@ void PhysicalSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_color", "get_ground_color");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy_multiplier", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_energy_multiplier", "get_energy_multiplier");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "get_use_debanding");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
}
@@ -654,16 +667,13 @@ uniform vec4 mie_color : source_color = vec4(0.69, 0.729, 0.812, 1.0);
uniform float turbidity : hint_range(0, 1000) = 10.0;
uniform float sun_disk_scale : hint_range(0, 360) = 1.0;
uniform vec4 ground_color : source_color = vec4(0.1, 0.07, 0.034, 1.0);
-uniform float exposure : hint_range(0, 128) = 0.1;
+uniform float exposure : hint_range(0, 128) = 1.0;
uniform bool use_debanding = true;
uniform sampler2D night_sky : source_color, hint_default_black;
const vec3 UP = vec3( 0.0, 1.0, 0.0 );
-// Sun constants
-const float SUN_ENERGY = 1000.0;
-
// Optical length at zenith for molecules.
const float rayleigh_zenith_size = 8.4e3;
const float mie_zenith_size = 1.25e3;
@@ -683,7 +693,7 @@ vec3 interleaved_gradient_noise(vec2 pos) {
void sky() {
if (LIGHT0_ENABLED) {
float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
- float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;
+ float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * LIGHT0_ENERGY;
float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);
// Rayleigh coefficients.
@@ -721,10 +731,10 @@ void sky() {
float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);
float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);
float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
- vec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;
+ vec3 L0 = (sun_energy * extinction) * sundisk * LIGHT0_COLOR;
L0 += texture(night_sky, SKY_COORDS).xyz * extinction;
- vec3 color = (Lin + L0) * 0.04;
+ vec3 color = Lin + L0;
COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
COLOR *= exposure;
if (use_debanding) {
@@ -732,7 +742,7 @@ void sky() {
}
} else {
// There is no sun, so display night_sky and nothing else.
- COLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;
+ COLOR = texture(night_sky, SKY_COORDS).xyz;
COLOR *= exposure;
}
}
@@ -751,7 +761,7 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() {
set_turbidity(10.0);
set_sun_disk_scale(1.0);
set_ground_color(Color(0.1, 0.07, 0.034));
- set_exposure(0.1);
+ set_energy_multiplier(1.0);
set_use_debanding(true);
}
diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h
index 61999af3c4..b517fd806b 100644
--- a/scene/resources/sky_material.h
+++ b/scene/resources/sky_material.h
@@ -41,14 +41,14 @@ private:
Color sky_top_color;
Color sky_horizon_color;
float sky_curve = 0.0f;
- float sky_energy = 0.0f;
+ float sky_energy_multiplier = 0.0f;
Ref<Texture2D> sky_cover;
Color sky_cover_modulate;
Color ground_bottom_color;
Color ground_horizon_color;
float ground_curve = 0.0f;
- float ground_energy = 0.0f;
+ float ground_energy_multiplier = 0.0f;
float sun_angle_max = 0.0f;
float sun_curve = 0.0f;
@@ -61,6 +61,7 @@ private:
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
public:
void set_sky_top_color(const Color &p_sky_top);
@@ -72,8 +73,8 @@ public:
void set_sky_curve(float p_curve);
float get_sky_curve() const;
- void set_sky_energy(float p_energy);
- float get_sky_energy() const;
+ void set_sky_energy_multiplier(float p_multiplier);
+ float get_sky_energy_multiplier() const;
void set_sky_cover(const Ref<Texture2D> &p_sky_cover);
Ref<Texture2D> get_sky_cover() const;
@@ -90,8 +91,8 @@ public:
void set_ground_curve(float p_curve);
float get_ground_curve() const;
- void set_ground_energy(float p_energy);
- float get_ground_energy() const;
+ void set_ground_energy_multiplier(float p_energy);
+ float get_ground_energy_multiplier() const;
void set_sun_angle_max(float p_angle);
float get_sun_angle_max() const;
@@ -138,6 +139,9 @@ public:
void set_filtering_enabled(bool p_enabled);
bool is_filtering_enabled() const;
+ void set_energy_multiplier(float p_multiplier);
+ float get_energy_multiplier() const;
+
virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override;
virtual RID get_rid() const override;
@@ -166,7 +170,7 @@ private:
float turbidity = 0.0f;
float sun_disk_scale = 0.0f;
Color ground_color;
- float exposure = 0.0f;
+ float energy_multiplier = 1.0f;
bool use_debanding = true;
Ref<Texture2D> night_sky;
static void _update_shader();
@@ -174,6 +178,7 @@ private:
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
public:
void set_rayleigh_coefficient(float p_rayleigh);
@@ -200,8 +205,11 @@ public:
void set_ground_color(Color p_ground_color);
Color get_ground_color() const;
- void set_exposure(float p_exposure);
- float get_exposure() const;
+ void set_energy_multiplier(float p_multiplier);
+ float get_energy_multiplier() const;
+
+ void set_exposure_value(float p_exposure);
+ float get_exposure_value() const;
void set_use_debanding(bool p_use_debanding);
bool get_use_debanding() const;
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index ff5210f1b3..4b151eed12 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -687,7 +687,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
const bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0);
// Only enable antialiasing if it is actually needed. This improve performances
// and maximizes sharpness for non-skewed StyleBoxes with sharp corners.
- const bool aa_on = (rounded_corners || !skew.is_equal_approx(Vector2())) && anti_aliased;
+ const bool aa_on = (rounded_corners || !skew.is_zero_approx()) && anti_aliased;
const bool blend_on = blend_border && draw_border;
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 43d3f329fa..7e9a2591e4 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -77,7 +77,7 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_break_flags", "flags"), &TextParagraph::set_break_flags);
ClassDB::bind_method(D_METHOD("get_break_flags"), &TextParagraph::get_break_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "break_flags", PROPERTY_HINT_FLAGS, "Mandatory,Word Bound,Grapheme Bound,Adaptive"), "set_break_flags", "get_break_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "break_flags", PROPERTY_HINT_FLAGS, "Mandatory,Word Bound,Grapheme Bound,Adaptive,Trim Spaces"), "set_break_flags", "get_break_flags");
ClassDB::bind_method(D_METHOD("set_justification_flags", "flags"), &TextParagraph::set_justification_flags);
ClassDB::bind_method(D_METHOD("get_justification_flags"), &TextParagraph::get_justification_flags);
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 25f5006c4f..028c131d0c 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -294,7 +294,7 @@ bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const {
x = CLAMP(x, 0, aw);
y = CLAMP(y, 0, ah);
- return alpha_cache->get_bit(Point2(x, y));
+ return alpha_cache->get_bit(x, y);
}
return true;
@@ -561,7 +561,7 @@ bool PortableCompressedTexture2D::is_pixel_opaque(int p_x, int p_y) const {
x = CLAMP(x, 0, aw);
y = CLAMP(y, 0, ah);
- return alpha_cache->get_bit(Point2(x, y));
+ return alpha_cache->get_bit(x, y);
}
return true;
@@ -1017,7 +1017,7 @@ bool CompressedTexture2D::is_pixel_opaque(int p_x, int p_y) const {
x = CLAMP(x, 0, aw);
y = CLAMP(y, 0, ah);
- return alpha_cache->get_bit(Point2(x, y));
+ return alpha_cache->get_bit(x, y);
}
return true;
@@ -1866,11 +1866,11 @@ void CurveTexture::_update() {
for (int i = 0; i < _width; ++i) {
float t = i / static_cast<float>(_width);
if (texture_mode == TEXTURE_MODE_RGB) {
- wd[i * 3 + 0] = curve.interpolate_baked(t);
+ wd[i * 3 + 0] = curve.sample_baked(t);
wd[i * 3 + 1] = wd[i * 3 + 0];
wd[i * 3 + 2] = wd[i * 3 + 0];
} else {
- wd[i] = curve.interpolate_baked(t);
+ wd[i] = curve.sample_baked(t);
}
}
@@ -2054,7 +2054,7 @@ void CurveXYZTexture::_update() {
Curve &curve_x = **_curve_x;
for (int i = 0; i < _width; ++i) {
float t = i / static_cast<float>(_width);
- wd[i * 3 + 0] = curve_x.interpolate_baked(t);
+ wd[i * 3 + 0] = curve_x.sample_baked(t);
}
} else {
@@ -2067,7 +2067,7 @@ void CurveXYZTexture::_update() {
Curve &curve_y = **_curve_y;
for (int i = 0; i < _width; ++i) {
float t = i / static_cast<float>(_width);
- wd[i * 3 + 1] = curve_y.interpolate_baked(t);
+ wd[i * 3 + 1] = curve_y.sample_baked(t);
}
} else {
@@ -2080,7 +2080,7 @@ void CurveXYZTexture::_update() {
Curve &curve_z = **_curve_z;
for (int i = 0; i < _width; ++i) {
float t = i / static_cast<float>(_width);
- wd[i * 3 + 2] = curve_z.interpolate_baked(t);
+ wd[i * 3 + 2] = curve_z.sample_baked(t);
}
} else {
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 552d856034..9138a82ba8 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -118,7 +118,7 @@ void TileMapPattern::remove_cell(const Vector2i &p_coords, bool p_update_size) {
pattern.erase(p_coords);
if (p_update_size) {
- size = Vector2i();
+ size = Size2i();
for (const KeyValue<Vector2i, TileMapCell> &E : pattern) {
size = size.max(E.key + Vector2i(1, 1));
}
@@ -157,11 +157,11 @@ TypedArray<Vector2i> TileMapPattern::get_used_cells() const {
return a;
}
-Vector2i TileMapPattern::get_size() const {
+Size2i TileMapPattern::get_size() const {
return size;
}
-void TileMapPattern::set_size(const Vector2i &p_size) {
+void TileMapPattern::set_size(const Size2i &p_size) {
for (const KeyValue<Vector2i, TileMapCell> &E : pattern) {
Vector2i coords = E.key;
if (p_size.x <= coords.x || p_size.y <= coords.y) {
@@ -178,7 +178,7 @@ bool TileMapPattern::is_empty() const {
};
void TileMapPattern::clear() {
- size = Vector2i();
+ size = Size2i();
pattern.clear();
emit_changed();
};
@@ -4716,14 +4716,19 @@ void TileSetScenesCollectionSource::set_scene_tile_id(int p_id, int p_new_id) {
void TileSetScenesCollectionSource::set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene) {
ERR_FAIL_COND(!scenes.has(p_id));
if (p_packed_scene.is_valid()) {
- // Make sure we have a root node. Supposed to be at 0 index because find_node_by_path() does not seem to work.
- ERR_FAIL_COND(!p_packed_scene->get_state().is_valid());
- ERR_FAIL_COND(p_packed_scene->get_state()->get_node_count() < 1);
-
// Check if it extends CanvasItem.
- String type = p_packed_scene->get_state()->get_node_type(0);
+ Ref<SceneState> scene_state = p_packed_scene->get_state();
+ String type;
+ while (scene_state.is_valid() && type.is_empty()) {
+ // Make sure we have a root node. Supposed to be at 0 index because find_node_by_path() does not seem to work.
+ ERR_FAIL_COND(scene_state->get_node_count() < 1);
+
+ type = scene_state->get_node_type(0);
+ scene_state = scene_state->get_base_scene_state();
+ }
+ ERR_FAIL_COND_MSG(type.is_empty(), vformat("Invalid PackedScene for TileSetScenesCollectionSource: %s. Could not get the type of the root node.", p_packed_scene->get_path()));
bool extends_correct_class = ClassDB::is_parent_class(type, "Control") || ClassDB::is_parent_class(type, "Node2D");
- ERR_FAIL_COND_MSG(!extends_correct_class, vformat("Invalid PackedScene for TileSetScenesCollectionSource: %s. Root node should extend Control or Node2D.", p_packed_scene->get_path()));
+ ERR_FAIL_COND_MSG(!extends_correct_class, vformat("Invalid PackedScene for TileSetScenesCollectionSource: %s. Root node should extend Control or Node2D. Found %s instead.", p_packed_scene->get_path(), type));
scenes[p_id].scene = p_packed_scene;
} else {
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 4c0823cdf2..e156679711 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -117,7 +117,7 @@ union TileMapCell {
class TileMapPattern : public Resource {
GDCLASS(TileMapPattern, Resource);
- Vector2i size;
+ Size2i size;
HashMap<Vector2i, TileMapCell> pattern;
void _set_tile_data(const Vector<int> &p_data);
@@ -140,8 +140,8 @@ public:
TypedArray<Vector2i> get_used_cells() const;
- Vector2i get_size() const;
- void set_size(const Vector2i &p_size);
+ Size2i get_size() const;
+ void set_size(const Size2i &p_size);
bool is_empty() const;
void clear();
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 90f1a1bff1..70a73186bc 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -723,10 +723,10 @@ void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, co
n.node = p_node;
n.position = p_position;
- Ref<VisualShaderNodeUniform> uniform = n.node;
- if (uniform.is_valid()) {
- String valid_name = validate_uniform_name(uniform->get_uniform_name(), uniform);
- uniform->set_uniform_name(valid_name);
+ Ref<VisualShaderNodeParameter> parameter = n.node;
+ if (parameter.is_valid()) {
+ String valid_name = validate_parameter_name(parameter->get_parameter_name(), parameter);
+ parameter->set_parameter_name(valid_name);
}
Ref<VisualShaderNodeInput> input = n.node;
@@ -1279,7 +1279,7 @@ String VisualShader::validate_port_name(const String &p_port_name, VisualShaderN
return name;
}
-String VisualShader::validate_uniform_name(const String &p_name, const Ref<VisualShaderNodeUniform> &p_uniform) const {
+String VisualShader::validate_parameter_name(const String &p_name, const Ref<VisualShaderNodeParameter> &p_parameter) const {
String name = p_name; //validate name first
while (name.length() && !is_ascii_char(name[0])) {
name = name.substr(1, name.length() - 1);
@@ -1299,7 +1299,7 @@ String VisualShader::validate_uniform_name(const String &p_name, const Ref<Visua
}
if (name.is_empty()) {
- name = p_uniform->get_caption();
+ name = p_parameter->get_caption();
}
int attempt = 1;
@@ -1308,11 +1308,11 @@ String VisualShader::validate_uniform_name(const String &p_name, const Ref<Visua
bool exists = false;
for (int i = 0; i < TYPE_MAX; i++) {
for (const KeyValue<int, Node> &E : graph[i].nodes) {
- Ref<VisualShaderNodeUniform> node = E.value.node;
- if (node == p_uniform) { //do not test on self
+ Ref<VisualShaderNodeParameter> node = E.value.node;
+ if (node == p_parameter) { //do not test on self
continue;
}
- if (node.is_valid() && node->get_uniform_name() == name) {
+ if (node.is_valid() && node->get_parameter_name() == name) {
exists = true;
break;
}
@@ -1620,8 +1620,8 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
bool skip_global = input.is_valid() && for_preview;
if (!skip_global) {
- Ref<VisualShaderNodeUniform> uniform = vsnode;
- if (!uniform.is_valid() || !uniform->is_global_code_generated()) {
+ Ref<VisualShaderNodeParameter> parameter = vsnode;
+ if (!parameter.is_valid() || !parameter->is_global_code_generated()) {
if (global_code) {
*global_code += vsnode->generate_global(get_mode(), type, node);
}
@@ -1680,8 +1680,8 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
VisualShaderNode *ptr = const_cast<VisualShaderNode *>(graph[type].nodes[from_node].node.ptr());
if (ptr->has_method("get_input_real_name")) {
inputs[i] = ptr->call("get_input_real_name");
- } else if (ptr->has_method("get_uniform_name")) {
- inputs[i] = ptr->call("get_uniform_name");
+ } else if (ptr->has_method("get_parameter_name")) {
+ inputs[i] = ptr->call("get_parameter_name");
} else {
inputs[i] = "";
}
@@ -2150,8 +2150,8 @@ void VisualShader::_update_shader() const {
static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
String global_expressions;
- HashSet<String> used_uniform_names;
- List<VisualShaderNodeUniform *> uniforms;
+ HashSet<String> used_parameter_names;
+ List<VisualShaderNodeParameter *> parameters;
HashMap<int, List<int>> emitters;
HashMap<int, List<int>> varying_setters;
@@ -2170,13 +2170,13 @@ void VisualShader::_update_shader() const {
expr += "\n";
global_expressions += expr;
}
- Ref<VisualShaderNodeUniformRef> uniform_ref = E.value.node;
- if (uniform_ref.is_valid()) {
- used_uniform_names.insert(uniform_ref->get_uniform_name());
+ Ref<VisualShaderNodeParameterRef> parameter_ref = E.value.node;
+ if (parameter_ref.is_valid()) {
+ used_parameter_names.insert(parameter_ref->get_parameter_name());
}
- Ref<VisualShaderNodeUniform> uniform = E.value.node;
- if (uniform.is_valid()) {
- uniforms.push_back(uniform.ptr());
+ Ref<VisualShaderNodeParameter> parameter = E.value.node;
+ if (parameter.is_valid()) {
+ parameters.push_back(parameter.ptr());
}
Ref<VisualShaderNodeVaryingSetter> varying_setter = E.value.node;
if (varying_setter.is_valid() && varying_setter->is_input_port_connected(0)) {
@@ -2195,13 +2195,13 @@ void VisualShader::_update_shader() const {
}
}
- for (int i = 0; i < uniforms.size(); i++) {
- VisualShaderNodeUniform *uniform = uniforms[i];
- if (used_uniform_names.has(uniform->get_uniform_name())) {
- global_code += uniform->generate_global(get_mode(), Type(i), -1);
- const_cast<VisualShaderNodeUniform *>(uniform)->set_global_code_generated(true);
+ for (int i = 0; i < parameters.size(); i++) {
+ VisualShaderNodeParameter *parameter = parameters[i];
+ if (used_parameter_names.has(parameter->get_parameter_name())) {
+ global_code += parameter->generate_global(get_mode(), Type(i), -1);
+ const_cast<VisualShaderNodeParameter *>(parameter)->set_global_code_generated(true);
} else {
- const_cast<VisualShaderNodeUniform *>(uniform)->set_global_code_generated(false);
+ const_cast<VisualShaderNodeParameter *>(parameter)->set_global_code_generated(false);
}
}
@@ -2520,7 +2520,7 @@ void VisualShader::_update_shader() const {
const_cast<VisualShader *>(this)->set_code(final_code);
for (int i = 0; i < default_tex_params.size(); i++) {
for (int j = 0; j < default_tex_params[i].params.size(); j++) {
- const_cast<VisualShader *>(this)->set_default_texture_param(default_tex_params[i].name, default_tex_params[i].params[j], j);
+ const_cast<VisualShader *>(this)->set_default_texture_parameter(default_tex_params[i].name, default_tex_params[i].params[j], j);
}
}
if (previous_code != final_code) {
@@ -3215,20 +3215,20 @@ void VisualShaderNodeInput::_bind_methods() {
VisualShaderNodeInput::VisualShaderNodeInput() {
}
-////////////// UniformRef
+////////////// ParameterRef
-RBMap<RID, List<VisualShaderNodeUniformRef::Uniform>> uniforms;
+RBMap<RID, List<VisualShaderNodeParameterRef::Parameter>> parameters;
-void VisualShaderNodeUniformRef::add_uniform(RID p_shader_rid, const String &p_name, UniformType p_type) {
- uniforms[p_shader_rid].push_back({ p_name, p_type });
+void VisualShaderNodeParameterRef::add_parameter(RID p_shader_rid, const String &p_name, ParameterType p_type) {
+ parameters[p_shader_rid].push_back({ p_name, p_type });
}
-void VisualShaderNodeUniformRef::clear_uniforms(RID p_shader_rid) {
- uniforms[p_shader_rid].clear();
+void VisualShaderNodeParameterRef::clear_parameters(RID p_shader_rid) {
+ parameters[p_shader_rid].clear();
}
-bool VisualShaderNodeUniformRef::has_uniform(RID p_shader_rid, const String &p_name) {
- for (const VisualShaderNodeUniformRef::Uniform &E : uniforms[p_shader_rid]) {
+bool VisualShaderNodeParameterRef::has_parameter(RID p_shader_rid, const String &p_name) {
+ for (const VisualShaderNodeParameterRef::Parameter &E : parameters[p_shader_rid]) {
if (E.name == p_name) {
return true;
}
@@ -3236,41 +3236,41 @@ bool VisualShaderNodeUniformRef::has_uniform(RID p_shader_rid, const String &p_n
return false;
}
-String VisualShaderNodeUniformRef::get_caption() const {
- return "UniformRef";
+String VisualShaderNodeParameterRef::get_caption() const {
+ return "ParameterRef";
}
-int VisualShaderNodeUniformRef::get_input_port_count() const {
+int VisualShaderNodeParameterRef::get_input_port_count() const {
return 0;
}
-VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_input_port_type(int p_port) const {
+VisualShaderNodeParameterRef::PortType VisualShaderNodeParameterRef::get_input_port_type(int p_port) const {
return PortType::PORT_TYPE_SCALAR;
}
-String VisualShaderNodeUniformRef::get_input_port_name(int p_port) const {
+String VisualShaderNodeParameterRef::get_input_port_name(int p_port) const {
return "";
}
-int VisualShaderNodeUniformRef::get_output_port_count() const {
- switch (uniform_type) {
- case UniformType::UNIFORM_TYPE_FLOAT:
+int VisualShaderNodeParameterRef::get_output_port_count() const {
+ switch (param_type) {
+ case PARAMETER_TYPE_FLOAT:
return 1;
- case UniformType::UNIFORM_TYPE_INT:
+ case PARAMETER_TYPE_INT:
return 1;
- case UniformType::UNIFORM_TYPE_BOOLEAN:
+ case PARAMETER_TYPE_BOOLEAN:
return 1;
- case UniformType::UNIFORM_TYPE_VECTOR2:
+ case PARAMETER_TYPE_VECTOR2:
return 1;
- case UniformType::UNIFORM_TYPE_VECTOR3:
+ case PARAMETER_TYPE_VECTOR3:
return 1;
- case UniformType::UNIFORM_TYPE_VECTOR4:
+ case PARAMETER_TYPE_VECTOR4:
return 1;
- case UniformType::UNIFORM_TYPE_TRANSFORM:
+ case PARAMETER_TYPE_TRANSFORM:
return 1;
- case UniformType::UNIFORM_TYPE_COLOR:
+ case PARAMETER_TYPE_COLOR:
return 2;
- case UniformType::UNIFORM_TYPE_SAMPLER:
+ case UNIFORM_TYPE_SAMPLER:
return 1;
default:
break;
@@ -3278,30 +3278,30 @@ int VisualShaderNodeUniformRef::get_output_port_count() const {
return 1;
}
-VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port_type(int p_port) const {
- switch (uniform_type) {
- case UniformType::UNIFORM_TYPE_FLOAT:
+VisualShaderNodeParameterRef::PortType VisualShaderNodeParameterRef::get_output_port_type(int p_port) const {
+ switch (param_type) {
+ case PARAMETER_TYPE_FLOAT:
return PortType::PORT_TYPE_SCALAR;
- case UniformType::UNIFORM_TYPE_INT:
+ case PARAMETER_TYPE_INT:
return PortType::PORT_TYPE_SCALAR_INT;
- case UniformType::UNIFORM_TYPE_BOOLEAN:
+ case PARAMETER_TYPE_BOOLEAN:
return PortType::PORT_TYPE_BOOLEAN;
- case UniformType::UNIFORM_TYPE_VECTOR2:
+ case PARAMETER_TYPE_VECTOR2:
return PortType::PORT_TYPE_VECTOR_2D;
- case UniformType::UNIFORM_TYPE_VECTOR3:
+ case PARAMETER_TYPE_VECTOR3:
return PortType::PORT_TYPE_VECTOR_3D;
- case UniformType::UNIFORM_TYPE_VECTOR4:
+ case PARAMETER_TYPE_VECTOR4:
return PortType::PORT_TYPE_VECTOR_4D;
- case UniformType::UNIFORM_TYPE_TRANSFORM:
+ case PARAMETER_TYPE_TRANSFORM:
return PortType::PORT_TYPE_TRANSFORM;
- case UniformType::UNIFORM_TYPE_COLOR:
+ case PARAMETER_TYPE_COLOR:
if (p_port == 0) {
return PortType::PORT_TYPE_VECTOR_3D;
} else if (p_port == 1) {
return PORT_TYPE_SCALAR;
}
break;
- case UniformType::UNIFORM_TYPE_SAMPLER:
+ case UNIFORM_TYPE_SAMPLER:
return PortType::PORT_TYPE_SAMPLER;
default:
break;
@@ -3309,30 +3309,30 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const {
- switch (uniform_type) {
- case UniformType::UNIFORM_TYPE_FLOAT:
+String VisualShaderNodeParameterRef::get_output_port_name(int p_port) const {
+ switch (param_type) {
+ case PARAMETER_TYPE_FLOAT:
return "";
- case UniformType::UNIFORM_TYPE_INT:
+ case PARAMETER_TYPE_INT:
return "";
- case UniformType::UNIFORM_TYPE_BOOLEAN:
+ case PARAMETER_TYPE_BOOLEAN:
return "";
- case UniformType::UNIFORM_TYPE_VECTOR2:
+ case PARAMETER_TYPE_VECTOR2:
return "";
- case UniformType::UNIFORM_TYPE_VECTOR3:
+ case PARAMETER_TYPE_VECTOR3:
return "";
- case UniformType::UNIFORM_TYPE_VECTOR4:
+ case PARAMETER_TYPE_VECTOR4:
return "";
- case UniformType::UNIFORM_TYPE_TRANSFORM:
+ case PARAMETER_TYPE_TRANSFORM:
return "";
- case UniformType::UNIFORM_TYPE_COLOR:
+ case PARAMETER_TYPE_COLOR:
if (p_port == 0) {
return "rgb";
} else if (p_port == 1) {
return "alpha";
}
break;
- case UniformType::UNIFORM_TYPE_SAMPLER:
+ case UNIFORM_TYPE_SAMPLER:
return "";
break;
default:
@@ -3341,85 +3341,85 @@ String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const {
return "";
}
-void VisualShaderNodeUniformRef::set_shader_rid(const RID &p_shader_rid) {
+void VisualShaderNodeParameterRef::set_shader_rid(const RID &p_shader_rid) {
shader_rid = p_shader_rid;
}
-void VisualShaderNodeUniformRef::set_uniform_name(const String &p_name) {
- uniform_name = p_name;
+void VisualShaderNodeParameterRef::set_parameter_name(const String &p_name) {
+ parameter_name = p_name;
if (shader_rid.is_valid()) {
- update_uniform_type();
+ update_parameter_type();
}
emit_changed();
}
-void VisualShaderNodeUniformRef::update_uniform_type() {
- if (uniform_name != "[None]") {
- uniform_type = get_uniform_type_by_name(uniform_name);
+void VisualShaderNodeParameterRef::update_parameter_type() {
+ if (parameter_name != "[None]") {
+ param_type = get_parameter_type_by_name(parameter_name);
} else {
- uniform_type = UniformType::UNIFORM_TYPE_FLOAT;
+ param_type = PARAMETER_TYPE_FLOAT;
}
}
-String VisualShaderNodeUniformRef::get_uniform_name() const {
- return uniform_name;
+String VisualShaderNodeParameterRef::get_parameter_name() const {
+ return parameter_name;
}
-int VisualShaderNodeUniformRef::get_uniforms_count() const {
+int VisualShaderNodeParameterRef::get_parameters_count() const {
ERR_FAIL_COND_V(!shader_rid.is_valid(), 0);
- return uniforms[shader_rid].size();
+ return parameters[shader_rid].size();
}
-String VisualShaderNodeUniformRef::get_uniform_name_by_index(int p_idx) const {
+String VisualShaderNodeParameterRef::get_parameter_name_by_index(int p_idx) const {
ERR_FAIL_COND_V(!shader_rid.is_valid(), String());
- if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) {
- return uniforms[shader_rid][p_idx].name;
+ if (p_idx >= 0 && p_idx < parameters[shader_rid].size()) {
+ return parameters[shader_rid][p_idx].name;
}
return "";
}
-VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_name(const String &p_name) const {
- ERR_FAIL_COND_V(!shader_rid.is_valid(), UNIFORM_TYPE_FLOAT);
+VisualShaderNodeParameterRef::ParameterType VisualShaderNodeParameterRef::get_parameter_type_by_name(const String &p_name) const {
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), PARAMETER_TYPE_FLOAT);
- for (int i = 0; i < uniforms[shader_rid].size(); i++) {
- if (uniforms[shader_rid][i].name == p_name) {
- return uniforms[shader_rid][i].type;
+ for (int i = 0; i < parameters[shader_rid].size(); i++) {
+ if (parameters[shader_rid][i].name == p_name) {
+ return parameters[shader_rid][i].type;
}
}
- return UniformType::UNIFORM_TYPE_FLOAT;
+ return PARAMETER_TYPE_FLOAT;
}
-VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_index(int p_idx) const {
- ERR_FAIL_COND_V(!shader_rid.is_valid(), UNIFORM_TYPE_FLOAT);
+VisualShaderNodeParameterRef::ParameterType VisualShaderNodeParameterRef::get_parameter_type_by_index(int p_idx) const {
+ ERR_FAIL_COND_V(!shader_rid.is_valid(), PARAMETER_TYPE_FLOAT);
- if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) {
- return uniforms[shader_rid][p_idx].type;
+ if (p_idx >= 0 && p_idx < parameters[shader_rid].size()) {
+ return parameters[shader_rid][p_idx].type;
}
- return UniformType::UNIFORM_TYPE_FLOAT;
+ return PARAMETER_TYPE_FLOAT;
}
-VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_by_index(int p_idx) const {
+VisualShaderNodeParameterRef::PortType VisualShaderNodeParameterRef::get_port_type_by_index(int p_idx) const {
ERR_FAIL_COND_V(!shader_rid.is_valid(), PORT_TYPE_SCALAR);
- if (p_idx >= 0 && p_idx < uniforms[shader_rid].size()) {
- switch (uniforms[shader_rid][p_idx].type) {
- case UniformType::UNIFORM_TYPE_FLOAT:
+ if (p_idx >= 0 && p_idx < parameters[shader_rid].size()) {
+ switch (parameters[shader_rid][p_idx].type) {
+ case PARAMETER_TYPE_FLOAT:
return PORT_TYPE_SCALAR;
- case UniformType::UNIFORM_TYPE_INT:
+ case PARAMETER_TYPE_INT:
return PORT_TYPE_SCALAR_INT;
- case UniformType::UNIFORM_TYPE_SAMPLER:
+ case UNIFORM_TYPE_SAMPLER:
return PORT_TYPE_SAMPLER;
- case UniformType::UNIFORM_TYPE_VECTOR2:
+ case PARAMETER_TYPE_VECTOR2:
return PORT_TYPE_VECTOR_2D;
- case UniformType::UNIFORM_TYPE_VECTOR3:
+ case PARAMETER_TYPE_VECTOR3:
return PORT_TYPE_VECTOR_3D;
- case UniformType::UNIFORM_TYPE_VECTOR4:
+ case PARAMETER_TYPE_VECTOR4:
return PORT_TYPE_VECTOR_4D;
- case UniformType::UNIFORM_TYPE_TRANSFORM:
+ case PARAMETER_TYPE_TRANSFORM:
return PORT_TYPE_TRANSFORM;
- case UniformType::UNIFORM_TYPE_COLOR:
+ case PARAMETER_TYPE_COLOR:
return PORT_TYPE_VECTOR_3D;
default:
break;
@@ -3428,54 +3428,54 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_b
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeUniformRef::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- switch (uniform_type) {
- case UniformType::UNIFORM_TYPE_FLOAT:
- if (uniform_name == "[None]") {
+String VisualShaderNodeParameterRef::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ switch (param_type) {
+ case PARAMETER_TYPE_FLOAT:
+ if (parameter_name == "[None]") {
return " " + p_output_vars[0] + " = 0.0;\n";
}
break;
- case UniformType::UNIFORM_TYPE_COLOR: {
- String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n";
- code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n";
+ case PARAMETER_TYPE_COLOR: {
+ String code = " " + p_output_vars[0] + " = " + get_parameter_name() + ".rgb;\n";
+ code += " " + p_output_vars[1] + " = " + get_parameter_name() + ".a;\n";
return code;
} break;
- case UniformType::UNIFORM_TYPE_SAMPLER:
+ case UNIFORM_TYPE_SAMPLER:
return String();
default:
break;
}
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-void VisualShaderNodeUniformRef::_set_uniform_type(int p_uniform_type) {
- uniform_type = (UniformType)p_uniform_type;
+void VisualShaderNodeParameterRef::_set_parameter_type(int p_type) {
+ param_type = (ParameterType)p_type;
}
-int VisualShaderNodeUniformRef::_get_uniform_type() const {
- return (int)uniform_type;
+int VisualShaderNodeParameterRef::_get_parameter_type() const {
+ return (int)param_type;
}
-void VisualShaderNodeUniformRef::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_uniform_name", "name"), &VisualShaderNodeUniformRef::set_uniform_name);
- ClassDB::bind_method(D_METHOD("get_uniform_name"), &VisualShaderNodeUniformRef::get_uniform_name);
+void VisualShaderNodeParameterRef::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_parameter_name", "name"), &VisualShaderNodeParameterRef::set_parameter_name);
+ ClassDB::bind_method(D_METHOD("get_parameter_name"), &VisualShaderNodeParameterRef::get_parameter_name);
- ClassDB::bind_method(D_METHOD("_set_uniform_type", "type"), &VisualShaderNodeUniformRef::_set_uniform_type);
- ClassDB::bind_method(D_METHOD("_get_uniform_type"), &VisualShaderNodeUniformRef::_get_uniform_type);
+ ClassDB::bind_method(D_METHOD("_set_parameter_type", "type"), &VisualShaderNodeParameterRef::_set_parameter_type);
+ ClassDB::bind_method(D_METHOD("_get_parameter_type"), &VisualShaderNodeParameterRef::_get_parameter_type);
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "uniform_name", PROPERTY_HINT_ENUM, ""), "set_uniform_name", "get_uniform_name");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "uniform_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_uniform_type", "_get_uniform_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "parameter_name", PROPERTY_HINT_ENUM, ""), "set_parameter_name", "get_parameter_name");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "param_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_parameter_type", "_get_parameter_type");
}
-Vector<StringName> VisualShaderNodeUniformRef::get_editable_properties() const {
+Vector<StringName> VisualShaderNodeParameterRef::get_editable_properties() const {
Vector<StringName> props;
- props.push_back("uniform_name");
- props.push_back("uniform_type");
+ props.push_back("parameter_name");
+ props.push_back("param_type");
return props;
}
-VisualShaderNodeUniformRef::VisualShaderNodeUniformRef() {
+VisualShaderNodeParameterRef::VisualShaderNodeParameterRef() {
}
////////////////////////////////////////////
@@ -3687,17 +3687,17 @@ VisualShaderNodeOutput::VisualShaderNodeOutput() {
///////////////////////////
-void VisualShaderNodeUniform::set_uniform_name(const String &p_name) {
- uniform_name = p_name;
+void VisualShaderNodeParameter::set_parameter_name(const String &p_name) {
+ parameter_name = p_name;
emit_signal(SNAME("name_changed"));
emit_changed();
}
-String VisualShaderNodeUniform::get_uniform_name() const {
- return uniform_name;
+String VisualShaderNodeParameter::get_parameter_name() const {
+ return parameter_name;
}
-void VisualShaderNodeUniform::set_qualifier(VisualShaderNodeUniform::Qualifier p_qual) {
+void VisualShaderNodeParameter::set_qualifier(VisualShaderNodeParameter::Qualifier p_qual) {
ERR_FAIL_INDEX(int(p_qual), int(QUAL_MAX));
if (qualifier == p_qual) {
return;
@@ -3706,26 +3706,26 @@ void VisualShaderNodeUniform::set_qualifier(VisualShaderNodeUniform::Qualifier p
emit_changed();
}
-VisualShaderNodeUniform::Qualifier VisualShaderNodeUniform::get_qualifier() const {
+VisualShaderNodeParameter::Qualifier VisualShaderNodeParameter::get_qualifier() const {
return qualifier;
}
-void VisualShaderNodeUniform::set_global_code_generated(bool p_enabled) {
+void VisualShaderNodeParameter::set_global_code_generated(bool p_enabled) {
global_code_generated = p_enabled;
}
-bool VisualShaderNodeUniform::is_global_code_generated() const {
+bool VisualShaderNodeParameter::is_global_code_generated() const {
return global_code_generated;
}
-void VisualShaderNodeUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_uniform_name", "name"), &VisualShaderNodeUniform::set_uniform_name);
- ClassDB::bind_method(D_METHOD("get_uniform_name"), &VisualShaderNodeUniform::get_uniform_name);
+void VisualShaderNodeParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_parameter_name", "name"), &VisualShaderNodeParameter::set_parameter_name);
+ ClassDB::bind_method(D_METHOD("get_parameter_name"), &VisualShaderNodeParameter::get_parameter_name);
- ClassDB::bind_method(D_METHOD("set_qualifier", "qualifier"), &VisualShaderNodeUniform::set_qualifier);
- ClassDB::bind_method(D_METHOD("get_qualifier"), &VisualShaderNodeUniform::get_qualifier);
+ ClassDB::bind_method(D_METHOD("set_qualifier", "qualifier"), &VisualShaderNodeParameter::set_qualifier);
+ ClassDB::bind_method(D_METHOD("get_qualifier"), &VisualShaderNodeParameter::get_qualifier);
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "uniform_name"), "set_uniform_name", "get_uniform_name");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "parameter_name"), "set_parameter_name", "get_parameter_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "qualifier", PROPERTY_HINT_ENUM, "None,Global,Instance"), "set_qualifier", "get_qualifier");
BIND_ENUM_CONSTANT(QUAL_NONE);
@@ -3734,7 +3734,7 @@ void VisualShaderNodeUniform::_bind_methods() {
BIND_ENUM_CONSTANT(QUAL_MAX);
}
-String VisualShaderNodeUniform::_get_qual_str() const {
+String VisualShaderNodeParameter::_get_qual_str() const {
if (is_qualifier_supported(qualifier)) {
switch (qualifier) {
case QUAL_NONE:
@@ -3750,11 +3750,11 @@ String VisualShaderNodeUniform::_get_qual_str() const {
return String();
}
-String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
+String VisualShaderNodeParameter::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
List<String> keyword_list;
ShaderLanguage::get_keyword_list(&keyword_list);
- if (keyword_list.find(uniform_name)) {
- return RTR("Shader keywords cannot be used as uniform names.\nChoose another name.");
+ if (keyword_list.find(parameter_name)) {
+ return RTR("Shader keywords cannot be used as parameter names.\nChoose another name.");
}
if (!is_qualifier_supported(qualifier)) {
String qualifier_str;
@@ -3770,66 +3770,66 @@ String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::T
default:
break;
}
- return vformat(RTR("This uniform type does not support the '%s' qualifier."), qualifier_str);
+ return vformat(RTR("This parameter type does not support the '%s' qualifier."), qualifier_str);
} else if (qualifier == Qualifier::QUAL_GLOBAL) {
- RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(uniform_name);
+ RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(parameter_name);
if (gvt == RS::GLOBAL_VAR_TYPE_MAX) {
- return vformat(RTR("Global uniform '%s' does not exist.\nCreate it in the Project Settings."), uniform_name);
+ return vformat(RTR("Global parameter '%s' does not exist.\nCreate it in the Project Settings."), parameter_name);
}
bool incompatible_type = false;
switch (gvt) {
case RS::GLOBAL_VAR_TYPE_FLOAT: {
- if (!Object::cast_to<VisualShaderNodeFloatUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeFloatParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_INT: {
- if (!Object::cast_to<VisualShaderNodeIntUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeIntParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_BOOL: {
- if (!Object::cast_to<VisualShaderNodeBooleanUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeBooleanParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_COLOR: {
- if (!Object::cast_to<VisualShaderNodeColorUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeColorParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_VEC3: {
- if (!Object::cast_to<VisualShaderNodeVec3Uniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeVec3Parameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- if (!Object::cast_to<VisualShaderNodeVec4Uniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeVec4Parameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- if (!Object::cast_to<VisualShaderNodeTransformUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeTransformParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
- if (!Object::cast_to<VisualShaderNodeTextureUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeTextureParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
- if (!Object::cast_to<VisualShaderNodeTexture3DUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeTexture3DParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
- if (!Object::cast_to<VisualShaderNodeTexture2DArrayUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeTexture2DArrayParameter>(this)) {
incompatible_type = true;
}
} break;
case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
- if (!Object::cast_to<VisualShaderNodeCubemapUniform>(this)) {
+ if (!Object::cast_to<VisualShaderNodeCubemapParameter>(this)) {
incompatible_type = true;
}
} break;
@@ -3837,29 +3837,29 @@ String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::T
break;
}
if (incompatible_type) {
- return vformat(RTR("Global uniform '%s' has an incompatible type for this kind of node.\nChange it in the Project Settings."), uniform_name);
+ return vformat(RTR("Global parameter '%s' has an incompatible type for this kind of node.\nChange it in the Project Settings."), parameter_name);
}
}
return String();
}
-Vector<StringName> VisualShaderNodeUniform::get_editable_properties() const {
+Vector<StringName> VisualShaderNodeParameter::get_editable_properties() const {
Vector<StringName> props;
props.push_back("qualifier");
return props;
}
-VisualShaderNodeUniform::VisualShaderNodeUniform() {
+VisualShaderNodeParameter::VisualShaderNodeParameter() {
}
////////////// ResizeableBase
-void VisualShaderNodeResizableBase::set_size(const Vector2 &p_size) {
+void VisualShaderNodeResizableBase::set_size(const Size2 &p_size) {
size = p_size;
}
-Vector2 VisualShaderNodeResizableBase::get_size() const {
+Size2 VisualShaderNodeResizableBase::get_size() const {
return size;
}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 09a3917a16..88e92f15cf 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -36,7 +36,7 @@
#include "scene/gui/control.h"
#include "scene/resources/shader.h"
-class VisualShaderNodeUniform;
+class VisualShaderNodeParameter;
class VisualShaderNode;
class VisualShader : public Shader {
@@ -229,7 +229,7 @@ public: // internal methods
String generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &r_default_tex_params) const;
String validate_port_name(const String &p_port_name, VisualShaderNode *p_node, int p_port_id, bool p_output) const;
- String validate_uniform_name(const String &p_name, const Ref<VisualShaderNodeUniform> &p_uniform) const;
+ String validate_parameter_name(const String &p_name, const Ref<VisualShaderNodeParameter> &p_parameter) const;
VisualShader();
};
@@ -499,8 +499,8 @@ public:
VisualShaderNodeOutput();
};
-class VisualShaderNodeUniform : public VisualShaderNode {
- GDCLASS(VisualShaderNodeUniform, VisualShaderNode);
+class VisualShaderNodeParameter : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParameter, VisualShaderNode);
public:
enum Qualifier {
@@ -511,7 +511,7 @@ public:
};
private:
- String uniform_name = "";
+ String parameter_name = "";
Qualifier qualifier = QUAL_NONE;
bool global_code_generated = false;
@@ -520,8 +520,8 @@ protected:
String _get_qual_str() const;
public:
- void set_uniform_name(const String &p_name);
- String get_uniform_name() const;
+ void set_parameter_name(const String &p_name);
+ String get_parameter_name() const;
void set_qualifier(Qualifier p_qual);
Qualifier get_qualifier() const;
@@ -535,44 +535,44 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
- VisualShaderNodeUniform();
+ VisualShaderNodeParameter();
};
-VARIANT_ENUM_CAST(VisualShaderNodeUniform::Qualifier)
+VARIANT_ENUM_CAST(VisualShaderNodeParameter::Qualifier)
-class VisualShaderNodeUniformRef : public VisualShaderNode {
- GDCLASS(VisualShaderNodeUniformRef, VisualShaderNode);
+class VisualShaderNodeParameterRef : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeParameterRef, VisualShaderNode);
public:
- enum UniformType {
- UNIFORM_TYPE_FLOAT,
- UNIFORM_TYPE_INT,
- UNIFORM_TYPE_BOOLEAN,
- UNIFORM_TYPE_VECTOR2,
- UNIFORM_TYPE_VECTOR3,
- UNIFORM_TYPE_VECTOR4,
- UNIFORM_TYPE_TRANSFORM,
- UNIFORM_TYPE_COLOR,
+ enum ParameterType {
+ PARAMETER_TYPE_FLOAT,
+ PARAMETER_TYPE_INT,
+ PARAMETER_TYPE_BOOLEAN,
+ PARAMETER_TYPE_VECTOR2,
+ PARAMETER_TYPE_VECTOR3,
+ PARAMETER_TYPE_VECTOR4,
+ PARAMETER_TYPE_TRANSFORM,
+ PARAMETER_TYPE_COLOR,
UNIFORM_TYPE_SAMPLER,
};
- struct Uniform {
+ struct Parameter {
String name;
- UniformType type;
+ ParameterType type;
};
private:
RID shader_rid;
- String uniform_name = "[None]";
- UniformType uniform_type = UniformType::UNIFORM_TYPE_FLOAT;
+ String parameter_name = "[None]";
+ ParameterType param_type = ParameterType::PARAMETER_TYPE_FLOAT;
protected:
static void _bind_methods();
public:
- static void add_uniform(RID p_shader_rid, const String &p_name, UniformType p_type);
- static void clear_uniforms(RID p_shader_rid);
- static bool has_uniform(RID p_shader_rid, const String &p_name);
+ static void add_parameter(RID p_shader_rid, const String &p_name, ParameterType p_type);
+ static void clear_parameters(RID p_shader_rid);
+ static bool has_parameter(RID p_shader_rid, const String &p_name);
public:
virtual String get_caption() const override;
@@ -587,40 +587,40 @@ public:
void set_shader_rid(const RID &p_shader);
- void set_uniform_name(const String &p_name);
- String get_uniform_name() const;
+ void set_parameter_name(const String &p_name);
+ String get_parameter_name() const;
- void update_uniform_type();
+ void update_parameter_type();
- void _set_uniform_type(int p_uniform_type);
- int _get_uniform_type() const;
+ void _set_parameter_type(int p_parameter_type);
+ int _get_parameter_type() const;
- int get_uniforms_count() const;
- String get_uniform_name_by_index(int p_idx) const;
- UniformType get_uniform_type_by_name(const String &p_name) const;
- UniformType get_uniform_type_by_index(int p_idx) const;
+ int get_parameters_count() const;
+ String get_parameter_name_by_index(int p_idx) const;
+ ParameterType get_parameter_type_by_name(const String &p_name) const;
+ ParameterType get_parameter_type_by_index(int p_idx) const;
PortType get_port_type_by_index(int p_idx) const;
virtual Vector<StringName> get_editable_properties() const override;
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;
- VisualShaderNodeUniformRef();
+ VisualShaderNodeParameterRef();
};
class VisualShaderNodeResizableBase : public VisualShaderNode {
GDCLASS(VisualShaderNodeResizableBase, VisualShaderNode);
protected:
- Vector2 size = Size2(0, 0);
+ Size2 size = Size2(0, 0);
bool allow_v_resize = true;
protected:
static void _bind_methods();
public:
- void set_size(const Vector2 &p_size);
- Vector2 get_size() const;
+ void set_size(const Size2 &p_size);
+ Size2 get_size() const;
bool is_allow_v_resize() const;
void set_allow_v_resize(bool p_enabled);
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 3b2b58516d..72e55ac47d 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -4712,44 +4712,44 @@ VisualShaderNodeTransformDecompose::VisualShaderNodeTransformDecompose() {
set_input_port_default_value(0, Transform3D());
}
-////////////// Float Uniform
+////////////// Float Parameter
-String VisualShaderNodeFloatUniform::get_caption() const {
- return "FloatUniform";
+String VisualShaderNodeFloatParameter::get_caption() const {
+ return "FloatParameter";
}
-int VisualShaderNodeFloatUniform::get_input_port_count() const {
+int VisualShaderNodeFloatParameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeFloatUniform::PortType VisualShaderNodeFloatUniform::get_input_port_type(int p_port) const {
+VisualShaderNodeFloatParameter::PortType VisualShaderNodeFloatParameter::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeFloatUniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeFloatParameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeFloatUniform::get_output_port_count() const {
+int VisualShaderNodeFloatParameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeFloatUniform::PortType VisualShaderNodeFloatUniform::get_output_port_type(int p_port) const {
+VisualShaderNodeFloatParameter::PortType VisualShaderNodeFloatParameter::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeFloatUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeFloatParameter::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
-String VisualShaderNodeFloatUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+String VisualShaderNodeFloatParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = "";
if (hint == HINT_RANGE) {
- code += _get_qual_str() + "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ")";
+ code += _get_qual_str() + "uniform float " + get_parameter_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ")";
} else if (hint == HINT_RANGE_STEP) {
- code += _get_qual_str() + "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ")";
+ code += _get_qual_str() + "uniform float " + get_parameter_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ")";
} else {
- code += _get_qual_str() + "uniform float " + get_uniform_name();
+ code += _get_qual_str() + "uniform float " + get_parameter_name();
}
if (default_value_enabled) {
code += " = " + rtos(default_value);
@@ -4758,19 +4758,19 @@ String VisualShaderNodeFloatUniform::generate_global(Shader::Mode p_mode, Visual
return code;
}
-String VisualShaderNodeFloatUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeFloatParameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-bool VisualShaderNodeFloatUniform::is_show_prop_names() const {
+bool VisualShaderNodeFloatParameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeFloatUniform::is_use_prop_slots() const {
+bool VisualShaderNodeFloatParameter::is_use_prop_slots() const {
return true;
}
-void VisualShaderNodeFloatUniform::set_hint(Hint p_hint) {
+void VisualShaderNodeFloatParameter::set_hint(Hint p_hint) {
ERR_FAIL_INDEX(int(p_hint), int(HINT_MAX));
if (hint == p_hint) {
return;
@@ -4779,11 +4779,11 @@ void VisualShaderNodeFloatUniform::set_hint(Hint p_hint) {
emit_changed();
}
-VisualShaderNodeFloatUniform::Hint VisualShaderNodeFloatUniform::get_hint() const {
+VisualShaderNodeFloatParameter::Hint VisualShaderNodeFloatParameter::get_hint() const {
return hint;
}
-void VisualShaderNodeFloatUniform::set_min(float p_value) {
+void VisualShaderNodeFloatParameter::set_min(float p_value) {
if (Math::is_equal_approx(hint_range_min, p_value)) {
return;
}
@@ -4791,11 +4791,11 @@ void VisualShaderNodeFloatUniform::set_min(float p_value) {
emit_changed();
}
-float VisualShaderNodeFloatUniform::get_min() const {
+float VisualShaderNodeFloatParameter::get_min() const {
return hint_range_min;
}
-void VisualShaderNodeFloatUniform::set_max(float p_value) {
+void VisualShaderNodeFloatParameter::set_max(float p_value) {
if (Math::is_equal_approx(hint_range_max, p_value)) {
return;
}
@@ -4803,11 +4803,11 @@ void VisualShaderNodeFloatUniform::set_max(float p_value) {
emit_changed();
}
-float VisualShaderNodeFloatUniform::get_max() const {
+float VisualShaderNodeFloatParameter::get_max() const {
return hint_range_max;
}
-void VisualShaderNodeFloatUniform::set_step(float p_value) {
+void VisualShaderNodeFloatParameter::set_step(float p_value) {
if (Math::is_equal_approx(hint_range_step, p_value)) {
return;
}
@@ -4815,11 +4815,11 @@ void VisualShaderNodeFloatUniform::set_step(float p_value) {
emit_changed();
}
-float VisualShaderNodeFloatUniform::get_step() const {
+float VisualShaderNodeFloatParameter::get_step() const {
return hint_range_step;
}
-void VisualShaderNodeFloatUniform::set_default_value_enabled(bool p_enabled) {
+void VisualShaderNodeFloatParameter::set_default_value_enabled(bool p_enabled) {
if (default_value_enabled == p_enabled) {
return;
}
@@ -4827,11 +4827,11 @@ void VisualShaderNodeFloatUniform::set_default_value_enabled(bool p_enabled) {
emit_changed();
}
-bool VisualShaderNodeFloatUniform::is_default_value_enabled() const {
+bool VisualShaderNodeFloatParameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeFloatUniform::set_default_value(float p_value) {
+void VisualShaderNodeFloatParameter::set_default_value(float p_value) {
if (Math::is_equal_approx(default_value, p_value)) {
return;
}
@@ -4839,28 +4839,28 @@ void VisualShaderNodeFloatUniform::set_default_value(float p_value) {
emit_changed();
}
-float VisualShaderNodeFloatUniform::get_default_value() const {
+float VisualShaderNodeFloatParameter::get_default_value() const {
return default_value;
}
-void VisualShaderNodeFloatUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeFloatUniform::set_hint);
- ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeFloatUniform::get_hint);
+void VisualShaderNodeFloatParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeFloatParameter::set_hint);
+ ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeFloatParameter::get_hint);
- ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeFloatUniform::set_min);
- ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeFloatUniform::get_min);
+ ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeFloatParameter::set_min);
+ ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeFloatParameter::get_min);
- ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeFloatUniform::set_max);
- ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeFloatUniform::get_max);
+ ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeFloatParameter::set_max);
+ ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeFloatParameter::get_max);
- ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeFloatUniform::set_step);
- ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeFloatUniform::get_step);
+ ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeFloatParameter::set_step);
+ ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeFloatParameter::get_step);
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeFloatUniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeFloatUniform::is_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeFloatParameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeFloatParameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeFloatUniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeFloatUniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeFloatParameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeFloatParameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min"), "set_min", "get_min");
@@ -4875,16 +4875,16 @@ void VisualShaderNodeFloatUniform::_bind_methods() {
BIND_ENUM_CONSTANT(HINT_MAX);
}
-bool VisualShaderNodeFloatUniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeFloatParameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // all qualifiers are supported
}
-bool VisualShaderNodeFloatUniform::is_convertible_to_constant() const {
+bool VisualShaderNodeFloatParameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeFloatParameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("hint");
if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) {
props.push_back("min");
@@ -4900,47 +4900,47 @@ Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const
return props;
}
-VisualShaderNodeFloatUniform::VisualShaderNodeFloatUniform() {
+VisualShaderNodeFloatParameter::VisualShaderNodeFloatParameter() {
}
-////////////// Integer Uniform
+////////////// Integer Parametet
-String VisualShaderNodeIntUniform::get_caption() const {
- return "IntUniform";
+String VisualShaderNodeIntParameter::get_caption() const {
+ return "IntParameter";
}
-int VisualShaderNodeIntUniform::get_input_port_count() const {
+int VisualShaderNodeIntParameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeIntUniform::PortType VisualShaderNodeIntUniform::get_input_port_type(int p_port) const {
+VisualShaderNodeIntParameter::PortType VisualShaderNodeIntParameter::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR_INT;
}
-String VisualShaderNodeIntUniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeIntParameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeIntUniform::get_output_port_count() const {
+int VisualShaderNodeIntParameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeIntUniform::PortType VisualShaderNodeIntUniform::get_output_port_type(int p_port) const {
+VisualShaderNodeIntParameter::PortType VisualShaderNodeIntParameter::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR_INT;
}
-String VisualShaderNodeIntUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeIntParameter::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
-String VisualShaderNodeIntUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+String VisualShaderNodeIntParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = "";
if (hint == HINT_RANGE) {
- code += _get_qual_str() + "uniform int " + get_uniform_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ")";
+ code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ")";
} else if (hint == HINT_RANGE_STEP) {
- code += _get_qual_str() + "uniform int " + get_uniform_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ", " + itos(hint_range_step) + ")";
+ code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ", " + itos(hint_range_step) + ")";
} else {
- code += _get_qual_str() + "uniform int " + get_uniform_name();
+ code += _get_qual_str() + "uniform int " + get_parameter_name();
}
if (default_value_enabled) {
code += " = " + itos(default_value);
@@ -4949,19 +4949,19 @@ String VisualShaderNodeIntUniform::generate_global(Shader::Mode p_mode, VisualSh
return code;
}
-String VisualShaderNodeIntUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeIntParameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-bool VisualShaderNodeIntUniform::is_show_prop_names() const {
+bool VisualShaderNodeIntParameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeIntUniform::is_use_prop_slots() const {
+bool VisualShaderNodeIntParameter::is_use_prop_slots() const {
return true;
}
-void VisualShaderNodeIntUniform::set_hint(Hint p_hint) {
+void VisualShaderNodeIntParameter::set_hint(Hint p_hint) {
ERR_FAIL_INDEX(int(p_hint), int(HINT_MAX));
if (hint == p_hint) {
return;
@@ -4970,11 +4970,11 @@ void VisualShaderNodeIntUniform::set_hint(Hint p_hint) {
emit_changed();
}
-VisualShaderNodeIntUniform::Hint VisualShaderNodeIntUniform::get_hint() const {
+VisualShaderNodeIntParameter::Hint VisualShaderNodeIntParameter::get_hint() const {
return hint;
}
-void VisualShaderNodeIntUniform::set_min(int p_value) {
+void VisualShaderNodeIntParameter::set_min(int p_value) {
if (hint_range_min == p_value) {
return;
}
@@ -4982,11 +4982,11 @@ void VisualShaderNodeIntUniform::set_min(int p_value) {
emit_changed();
}
-int VisualShaderNodeIntUniform::get_min() const {
+int VisualShaderNodeIntParameter::get_min() const {
return hint_range_min;
}
-void VisualShaderNodeIntUniform::set_max(int p_value) {
+void VisualShaderNodeIntParameter::set_max(int p_value) {
if (hint_range_max == p_value) {
return;
}
@@ -4994,11 +4994,11 @@ void VisualShaderNodeIntUniform::set_max(int p_value) {
emit_changed();
}
-int VisualShaderNodeIntUniform::get_max() const {
+int VisualShaderNodeIntParameter::get_max() const {
return hint_range_max;
}
-void VisualShaderNodeIntUniform::set_step(int p_value) {
+void VisualShaderNodeIntParameter::set_step(int p_value) {
if (hint_range_step == p_value) {
return;
}
@@ -5006,11 +5006,11 @@ void VisualShaderNodeIntUniform::set_step(int p_value) {
emit_changed();
}
-int VisualShaderNodeIntUniform::get_step() const {
+int VisualShaderNodeIntParameter::get_step() const {
return hint_range_step;
}
-void VisualShaderNodeIntUniform::set_default_value_enabled(bool p_default_value_enabled) {
+void VisualShaderNodeIntParameter::set_default_value_enabled(bool p_default_value_enabled) {
if (default_value_enabled == p_default_value_enabled) {
return;
}
@@ -5018,11 +5018,11 @@ void VisualShaderNodeIntUniform::set_default_value_enabled(bool p_default_value_
emit_changed();
}
-bool VisualShaderNodeIntUniform::is_default_value_enabled() const {
+bool VisualShaderNodeIntParameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeIntUniform::set_default_value(int p_default_value) {
+void VisualShaderNodeIntParameter::set_default_value(int p_default_value) {
if (default_value == p_default_value) {
return;
}
@@ -5030,28 +5030,28 @@ void VisualShaderNodeIntUniform::set_default_value(int p_default_value) {
emit_changed();
}
-int VisualShaderNodeIntUniform::get_default_value() const {
+int VisualShaderNodeIntParameter::get_default_value() const {
return default_value;
}
-void VisualShaderNodeIntUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeIntUniform::set_hint);
- ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeIntUniform::get_hint);
+void VisualShaderNodeIntParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeIntParameter::set_hint);
+ ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeIntParameter::get_hint);
- ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeIntUniform::set_min);
- ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeIntUniform::get_min);
+ ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeIntParameter::set_min);
+ ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeIntParameter::get_min);
- ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeIntUniform::set_max);
- ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeIntUniform::get_max);
+ ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeIntParameter::set_max);
+ ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeIntParameter::get_max);
- ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeIntUniform::set_step);
- ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeIntUniform::get_step);
+ ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeIntParameter::set_step);
+ ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeIntParameter::get_step);
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeIntUniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntUniform::is_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeIntParameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntParameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntUniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntUniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntParameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntParameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step"), "set_hint", "get_hint");
ADD_PROPERTY(PropertyInfo(Variant::INT, "min"), "set_min", "get_min");
@@ -5066,16 +5066,16 @@ void VisualShaderNodeIntUniform::_bind_methods() {
BIND_ENUM_CONSTANT(HINT_MAX);
}
-bool VisualShaderNodeIntUniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeIntParameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // all qualifiers are supported
}
-bool VisualShaderNodeIntUniform::is_convertible_to_constant() const {
+bool VisualShaderNodeIntParameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeIntParameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("hint");
if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) {
props.push_back("min");
@@ -5091,40 +5091,40 @@ Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const {
return props;
}
-VisualShaderNodeIntUniform::VisualShaderNodeIntUniform() {
+VisualShaderNodeIntParameter::VisualShaderNodeIntParameter() {
}
-////////////// Boolean Uniform
+////////////// Boolean Parameter
-String VisualShaderNodeBooleanUniform::get_caption() const {
- return "BooleanUniform";
+String VisualShaderNodeBooleanParameter::get_caption() const {
+ return "BooleanParameter";
}
-int VisualShaderNodeBooleanUniform::get_input_port_count() const {
+int VisualShaderNodeBooleanParameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeBooleanUniform::PortType VisualShaderNodeBooleanUniform::get_input_port_type(int p_port) const {
+VisualShaderNodeBooleanParameter::PortType VisualShaderNodeBooleanParameter::get_input_port_type(int p_port) const {
return PORT_TYPE_BOOLEAN;
}
-String VisualShaderNodeBooleanUniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeBooleanParameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeBooleanUniform::get_output_port_count() const {
+int VisualShaderNodeBooleanParameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeBooleanUniform::PortType VisualShaderNodeBooleanUniform::get_output_port_type(int p_port) const {
+VisualShaderNodeBooleanParameter::PortType VisualShaderNodeBooleanParameter::get_output_port_type(int p_port) const {
return PORT_TYPE_BOOLEAN;
}
-String VisualShaderNodeBooleanUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeBooleanParameter::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
-void VisualShaderNodeBooleanUniform::set_default_value_enabled(bool p_default_value_enabled) {
+void VisualShaderNodeBooleanParameter::set_default_value_enabled(bool p_default_value_enabled) {
if (default_value_enabled == p_default_value_enabled) {
return;
}
@@ -5132,11 +5132,11 @@ void VisualShaderNodeBooleanUniform::set_default_value_enabled(bool p_default_va
emit_changed();
}
-bool VisualShaderNodeBooleanUniform::is_default_value_enabled() const {
+bool VisualShaderNodeBooleanParameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeBooleanUniform::set_default_value(bool p_default_value) {
+void VisualShaderNodeBooleanParameter::set_default_value(bool p_default_value) {
if (default_value == p_default_value) {
return;
}
@@ -5144,12 +5144,12 @@ void VisualShaderNodeBooleanUniform::set_default_value(bool p_default_value) {
emit_changed();
}
-bool VisualShaderNodeBooleanUniform::get_default_value() const {
+bool VisualShaderNodeBooleanParameter::get_default_value() const {
return default_value;
}
-String VisualShaderNodeBooleanUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform bool " + get_uniform_name();
+String VisualShaderNodeBooleanParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform bool " + get_parameter_name();
if (default_value_enabled) {
if (default_value) {
code += " = true";
@@ -5161,39 +5161,39 @@ String VisualShaderNodeBooleanUniform::generate_global(Shader::Mode p_mode, Visu
return code;
}
-String VisualShaderNodeBooleanUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeBooleanParameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-bool VisualShaderNodeBooleanUniform::is_show_prop_names() const {
+bool VisualShaderNodeBooleanParameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeBooleanUniform::is_use_prop_slots() const {
+bool VisualShaderNodeBooleanParameter::is_use_prop_slots() const {
return true;
}
-void VisualShaderNodeBooleanUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeBooleanUniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeBooleanUniform::is_default_value_enabled);
+void VisualShaderNodeBooleanParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeBooleanParameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeBooleanParameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeBooleanUniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeBooleanUniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeBooleanParameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeBooleanParameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value"), "set_default_value", "get_default_value");
}
-bool VisualShaderNodeBooleanUniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeBooleanParameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // all qualifiers are supported
}
-bool VisualShaderNodeBooleanUniform::is_convertible_to_constant() const {
+bool VisualShaderNodeBooleanParameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeBooleanParameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
@@ -5201,47 +5201,47 @@ Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() con
return props;
}
-VisualShaderNodeBooleanUniform::VisualShaderNodeBooleanUniform() {
+VisualShaderNodeBooleanParameter::VisualShaderNodeBooleanParameter() {
}
-////////////// Color Uniform
+////////////// Color Parameter
-String VisualShaderNodeColorUniform::get_caption() const {
- return "ColorUniform";
+String VisualShaderNodeColorParameter::get_caption() const {
+ return "ColorParameter";
}
-int VisualShaderNodeColorUniform::get_input_port_count() const {
+int VisualShaderNodeColorParameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeColorUniform::PortType VisualShaderNodeColorUniform::get_input_port_type(int p_port) const {
+VisualShaderNodeColorParameter::PortType VisualShaderNodeColorParameter::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeColorUniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeColorParameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeColorUniform::get_output_port_count() const {
+int VisualShaderNodeColorParameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeColorUniform::PortType VisualShaderNodeColorUniform::get_output_port_type(int p_port) const {
+VisualShaderNodeColorParameter::PortType VisualShaderNodeColorParameter::get_output_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR_4D : PORT_TYPE_SCALAR;
}
-String VisualShaderNodeColorUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeColorParameter::get_output_port_name(int p_port) const {
return "color";
}
-bool VisualShaderNodeColorUniform::is_output_port_expandable(int p_port) const {
+bool VisualShaderNodeColorParameter::is_output_port_expandable(int p_port) const {
if (p_port == 0) {
return true;
}
return false;
}
-void VisualShaderNodeColorUniform::set_default_value_enabled(bool p_enabled) {
+void VisualShaderNodeColorParameter::set_default_value_enabled(bool p_enabled) {
if (default_value_enabled == p_enabled) {
return;
}
@@ -5249,11 +5249,11 @@ void VisualShaderNodeColorUniform::set_default_value_enabled(bool p_enabled) {
emit_changed();
}
-bool VisualShaderNodeColorUniform::is_default_value_enabled() const {
+bool VisualShaderNodeColorParameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeColorUniform::set_default_value(const Color &p_value) {
+void VisualShaderNodeColorParameter::set_default_value(const Color &p_value) {
if (default_value.is_equal_approx(p_value)) {
return;
}
@@ -5261,12 +5261,12 @@ void VisualShaderNodeColorUniform::set_default_value(const Color &p_value) {
emit_changed();
}
-Color VisualShaderNodeColorUniform::get_default_value() const {
+Color VisualShaderNodeColorParameter::get_default_value() const {
return default_value;
}
-String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform vec4 " + get_uniform_name() + " : source_color";
+String VisualShaderNodeColorParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform vec4 " + get_parameter_name() + " : source_color";
if (default_value_enabled) {
code += vformat(" = vec4(%.6f, %.6f, %.6f, %.6f)", default_value.r, default_value.g, default_value.b, default_value.a);
}
@@ -5274,35 +5274,35 @@ String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, Visual
return code;
}
-String VisualShaderNodeColorUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeColorParameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-bool VisualShaderNodeColorUniform::is_show_prop_names() const {
+bool VisualShaderNodeColorParameter::is_show_prop_names() const {
return true;
}
-void VisualShaderNodeColorUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeColorUniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeColorUniform::is_default_value_enabled);
+void VisualShaderNodeColorParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeColorParameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeColorParameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeColorUniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeColorUniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeColorParameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeColorParameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_value"), "set_default_value", "get_default_value");
}
-bool VisualShaderNodeColorUniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeColorParameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // all qualifiers are supported
}
-bool VisualShaderNodeColorUniform::is_convertible_to_constant() const {
+bool VisualShaderNodeColorParameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeColorParameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
@@ -5310,59 +5310,59 @@ Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const
return props;
}
-VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() {
+VisualShaderNodeColorParameter::VisualShaderNodeColorParameter() {
}
-////////////// Vector2 Uniform
+////////////// Vector2 Parameter
-String VisualShaderNodeVec2Uniform::get_caption() const {
- return "Vector2Uniform";
+String VisualShaderNodeVec2Parameter::get_caption() const {
+ return "Vector2Parameter";
}
-int VisualShaderNodeVec2Uniform::get_input_port_count() const {
+int VisualShaderNodeVec2Parameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeVec2Uniform::PortType VisualShaderNodeVec2Uniform::get_input_port_type(int p_port) const {
+VisualShaderNodeVec2Parameter::PortType VisualShaderNodeVec2Parameter::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR_2D;
}
-String VisualShaderNodeVec2Uniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeVec2Parameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeVec2Uniform::get_output_port_count() const {
+int VisualShaderNodeVec2Parameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVec2Uniform::PortType VisualShaderNodeVec2Uniform::get_output_port_type(int p_port) const {
+VisualShaderNodeVec2Parameter::PortType VisualShaderNodeVec2Parameter::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR_2D;
}
-String VisualShaderNodeVec2Uniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeVec2Parameter::get_output_port_name(int p_port) const {
return String();
}
-void VisualShaderNodeVec2Uniform::set_default_value_enabled(bool p_enabled) {
+void VisualShaderNodeVec2Parameter::set_default_value_enabled(bool p_enabled) {
default_value_enabled = p_enabled;
emit_changed();
}
-bool VisualShaderNodeVec2Uniform::is_default_value_enabled() const {
+bool VisualShaderNodeVec2Parameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeVec2Uniform::set_default_value(const Vector2 &p_value) {
+void VisualShaderNodeVec2Parameter::set_default_value(const Vector2 &p_value) {
default_value = p_value;
emit_changed();
}
-Vector2 VisualShaderNodeVec2Uniform::get_default_value() const {
+Vector2 VisualShaderNodeVec2Parameter::get_default_value() const {
return default_value;
}
-String VisualShaderNodeVec2Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform vec2 " + get_uniform_name();
+String VisualShaderNodeVec2Parameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform vec2 " + get_parameter_name();
if (default_value_enabled) {
code += vformat(" = vec2(%.6f, %.6f)", default_value.x, default_value.y);
}
@@ -5370,39 +5370,39 @@ String VisualShaderNodeVec2Uniform::generate_global(Shader::Mode p_mode, VisualS
return code;
}
-String VisualShaderNodeVec2Uniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeVec2Parameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-void VisualShaderNodeVec2Uniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec2Uniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec2Uniform::is_default_value_enabled);
+void VisualShaderNodeVec2Parameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec2Parameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec2Parameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec2Uniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec2Uniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec2Parameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec2Parameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "default_value"), "set_default_value", "get_default_value");
}
-bool VisualShaderNodeVec2Uniform::is_show_prop_names() const {
+bool VisualShaderNodeVec2Parameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeVec2Uniform::is_use_prop_slots() const {
+bool VisualShaderNodeVec2Parameter::is_use_prop_slots() const {
return true;
}
-bool VisualShaderNodeVec2Uniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeVec2Parameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // all qualifiers are supported
}
-bool VisualShaderNodeVec2Uniform::is_convertible_to_constant() const {
+bool VisualShaderNodeVec2Parameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeVec2Uniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeVec2Parameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
@@ -5410,59 +5410,59 @@ Vector<StringName> VisualShaderNodeVec2Uniform::get_editable_properties() const
return props;
}
-VisualShaderNodeVec2Uniform::VisualShaderNodeVec2Uniform() {
+VisualShaderNodeVec2Parameter::VisualShaderNodeVec2Parameter() {
}
-////////////// Vector3 Uniform
+////////////// Vector3 Parameter
-String VisualShaderNodeVec3Uniform::get_caption() const {
- return "Vector3Uniform";
+String VisualShaderNodeVec3Parameter::get_caption() const {
+ return "Vector3Parameter";
}
-int VisualShaderNodeVec3Uniform::get_input_port_count() const {
+int VisualShaderNodeVec3Parameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeVec3Uniform::PortType VisualShaderNodeVec3Uniform::get_input_port_type(int p_port) const {
+VisualShaderNodeVec3Parameter::PortType VisualShaderNodeVec3Parameter::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR_3D;
}
-String VisualShaderNodeVec3Uniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeVec3Parameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeVec3Uniform::get_output_port_count() const {
+int VisualShaderNodeVec3Parameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVec3Uniform::PortType VisualShaderNodeVec3Uniform::get_output_port_type(int p_port) const {
+VisualShaderNodeVec3Parameter::PortType VisualShaderNodeVec3Parameter::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR_3D;
}
-String VisualShaderNodeVec3Uniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeVec3Parameter::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
-void VisualShaderNodeVec3Uniform::set_default_value_enabled(bool p_enabled) {
+void VisualShaderNodeVec3Parameter::set_default_value_enabled(bool p_enabled) {
default_value_enabled = p_enabled;
emit_changed();
}
-bool VisualShaderNodeVec3Uniform::is_default_value_enabled() const {
+bool VisualShaderNodeVec3Parameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeVec3Uniform::set_default_value(const Vector3 &p_value) {
+void VisualShaderNodeVec3Parameter::set_default_value(const Vector3 &p_value) {
default_value = p_value;
emit_changed();
}
-Vector3 VisualShaderNodeVec3Uniform::get_default_value() const {
+Vector3 VisualShaderNodeVec3Parameter::get_default_value() const {
return default_value;
}
-String VisualShaderNodeVec3Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform vec3 " + get_uniform_name();
+String VisualShaderNodeVec3Parameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform vec3 " + get_parameter_name();
if (default_value_enabled) {
code += vformat(" = vec3(%.6f, %.6f, %.6f)", default_value.x, default_value.y, default_value.z);
}
@@ -5470,39 +5470,39 @@ String VisualShaderNodeVec3Uniform::generate_global(Shader::Mode p_mode, VisualS
return code;
}
-String VisualShaderNodeVec3Uniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeVec3Parameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-void VisualShaderNodeVec3Uniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec3Uniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec3Uniform::is_default_value_enabled);
+void VisualShaderNodeVec3Parameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec3Parameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec3Parameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec3Uniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec3Uniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec3Parameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec3Parameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "default_value"), "set_default_value", "get_default_value");
}
-bool VisualShaderNodeVec3Uniform::is_show_prop_names() const {
+bool VisualShaderNodeVec3Parameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeVec3Uniform::is_use_prop_slots() const {
+bool VisualShaderNodeVec3Parameter::is_use_prop_slots() const {
return true;
}
-bool VisualShaderNodeVec3Uniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeVec3Parameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // all qualifiers are supported
}
-bool VisualShaderNodeVec3Uniform::is_convertible_to_constant() const {
+bool VisualShaderNodeVec3Parameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeVec3Parameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
@@ -5510,59 +5510,59 @@ Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const
return props;
}
-VisualShaderNodeVec3Uniform::VisualShaderNodeVec3Uniform() {
+VisualShaderNodeVec3Parameter::VisualShaderNodeVec3Parameter() {
}
-////////////// Vector4 Uniform
+////////////// Vector4 Parameter
-String VisualShaderNodeVec4Uniform::get_caption() const {
- return "Vector4Uniform";
+String VisualShaderNodeVec4Parameter::get_caption() const {
+ return "Vector4Parameter";
}
-int VisualShaderNodeVec4Uniform::get_input_port_count() const {
+int VisualShaderNodeVec4Parameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeVec4Uniform::PortType VisualShaderNodeVec4Uniform::get_input_port_type(int p_port) const {
+VisualShaderNodeVec4Parameter::PortType VisualShaderNodeVec4Parameter::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR_4D;
}
-String VisualShaderNodeVec4Uniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeVec4Parameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeVec4Uniform::get_output_port_count() const {
+int VisualShaderNodeVec4Parameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVec4Uniform::PortType VisualShaderNodeVec4Uniform::get_output_port_type(int p_port) const {
+VisualShaderNodeVec4Parameter::PortType VisualShaderNodeVec4Parameter::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR_4D;
}
-String VisualShaderNodeVec4Uniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeVec4Parameter::get_output_port_name(int p_port) const {
return ""; // No output port means the editor will be used as port.
}
-void VisualShaderNodeVec4Uniform::set_default_value_enabled(bool p_enabled) {
+void VisualShaderNodeVec4Parameter::set_default_value_enabled(bool p_enabled) {
default_value_enabled = p_enabled;
emit_changed();
}
-bool VisualShaderNodeVec4Uniform::is_default_value_enabled() const {
+bool VisualShaderNodeVec4Parameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeVec4Uniform::set_default_value(const Quaternion &p_value) {
+void VisualShaderNodeVec4Parameter::set_default_value(const Vector4 &p_value) {
default_value = p_value;
emit_changed();
}
-Quaternion VisualShaderNodeVec4Uniform::get_default_value() const {
+Vector4 VisualShaderNodeVec4Parameter::get_default_value() const {
return default_value;
}
-String VisualShaderNodeVec4Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform vec4 " + get_uniform_name();
+String VisualShaderNodeVec4Parameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform vec4 " + get_parameter_name();
if (default_value_enabled) {
code += vformat(" = vec4(%.6f, %.6f, %.6f, %.6f)", default_value.x, default_value.y, default_value.z, default_value.w);
}
@@ -5570,39 +5570,39 @@ String VisualShaderNodeVec4Uniform::generate_global(Shader::Mode p_mode, VisualS
return code;
}
-String VisualShaderNodeVec4Uniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeVec4Parameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-void VisualShaderNodeVec4Uniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec4Uniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec4Uniform::is_default_value_enabled);
+void VisualShaderNodeVec4Parameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec4Parameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec4Parameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec4Uniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec4Uniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec4Parameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec4Parameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "default_value"), "set_default_value", "get_default_value");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR4, "default_value"), "set_default_value", "get_default_value");
}
-bool VisualShaderNodeVec4Uniform::is_show_prop_names() const {
+bool VisualShaderNodeVec4Parameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeVec4Uniform::is_use_prop_slots() const {
+bool VisualShaderNodeVec4Parameter::is_use_prop_slots() const {
return true;
}
-bool VisualShaderNodeVec4Uniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeVec4Parameter::is_qualifier_supported(Qualifier p_qual) const {
return true; // All qualifiers are supported.
}
-bool VisualShaderNodeVec4Uniform::is_convertible_to_constant() const {
+bool VisualShaderNodeVec4Parameter::is_convertible_to_constant() const {
return true; // Conversion is allowed.
}
-Vector<StringName> VisualShaderNodeVec4Uniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeVec4Parameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
@@ -5610,59 +5610,59 @@ Vector<StringName> VisualShaderNodeVec4Uniform::get_editable_properties() const
return props;
}
-VisualShaderNodeVec4Uniform::VisualShaderNodeVec4Uniform() {
+VisualShaderNodeVec4Parameter::VisualShaderNodeVec4Parameter() {
}
-////////////// Transform Uniform
+////////////// Transform Parameter
-String VisualShaderNodeTransformUniform::get_caption() const {
- return "TransformUniform";
+String VisualShaderNodeTransformParameter::get_caption() const {
+ return "TransformParameter";
}
-int VisualShaderNodeTransformUniform::get_input_port_count() const {
+int VisualShaderNodeTransformParameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeTransformUniform::PortType VisualShaderNodeTransformUniform::get_input_port_type(int p_port) const {
+VisualShaderNodeTransformParameter::PortType VisualShaderNodeTransformParameter::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR_3D;
}
-String VisualShaderNodeTransformUniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeTransformParameter::get_input_port_name(int p_port) const {
return String();
}
-int VisualShaderNodeTransformUniform::get_output_port_count() const {
+int VisualShaderNodeTransformParameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeTransformUniform::PortType VisualShaderNodeTransformUniform::get_output_port_type(int p_port) const {
+VisualShaderNodeTransformParameter::PortType VisualShaderNodeTransformParameter::get_output_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
-String VisualShaderNodeTransformUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeTransformParameter::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
-void VisualShaderNodeTransformUniform::set_default_value_enabled(bool p_enabled) {
+void VisualShaderNodeTransformParameter::set_default_value_enabled(bool p_enabled) {
default_value_enabled = p_enabled;
emit_changed();
}
-bool VisualShaderNodeTransformUniform::is_default_value_enabled() const {
+bool VisualShaderNodeTransformParameter::is_default_value_enabled() const {
return default_value_enabled;
}
-void VisualShaderNodeTransformUniform::set_default_value(const Transform3D &p_value) {
+void VisualShaderNodeTransformParameter::set_default_value(const Transform3D &p_value) {
default_value = p_value;
emit_changed();
}
-Transform3D VisualShaderNodeTransformUniform::get_default_value() const {
+Transform3D VisualShaderNodeTransformParameter::get_default_value() const {
return default_value;
}
-String VisualShaderNodeTransformUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform mat4 " + get_uniform_name();
+String VisualShaderNodeTransformParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform mat4 " + get_parameter_name();
if (default_value_enabled) {
Vector3 row0 = default_value.basis.rows[0];
Vector3 row1 = default_value.basis.rows[1];
@@ -5674,42 +5674,42 @@ String VisualShaderNodeTransformUniform::generate_global(Shader::Mode p_mode, Vi
return code;
}
-String VisualShaderNodeTransformUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+String VisualShaderNodeTransformParameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
}
-void VisualShaderNodeTransformUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeTransformUniform::set_default_value_enabled);
- ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeTransformUniform::is_default_value_enabled);
+void VisualShaderNodeTransformParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeTransformParameter::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeTransformParameter::is_default_value_enabled);
- ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeTransformUniform::set_default_value);
- ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeTransformUniform::get_default_value);
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeTransformParameter::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeTransformParameter::get_default_value);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "default_value"), "set_default_value", "get_default_value");
}
-bool VisualShaderNodeTransformUniform::is_show_prop_names() const {
+bool VisualShaderNodeTransformParameter::is_show_prop_names() const {
return true;
}
-bool VisualShaderNodeTransformUniform::is_use_prop_slots() const {
+bool VisualShaderNodeTransformParameter::is_use_prop_slots() const {
return true;
}
-bool VisualShaderNodeTransformUniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeTransformParameter::is_qualifier_supported(Qualifier p_qual) const {
if (p_qual == Qualifier::QUAL_INSTANCE) {
return false;
}
return true;
}
-bool VisualShaderNodeTransformUniform::is_convertible_to_constant() const {
+bool VisualShaderNodeTransformParameter::is_convertible_to_constant() const {
return true; // conversion is allowed
}
-Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeTransformParameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("default_value_enabled");
if (default_value_enabled) {
props.push_back("default_value");
@@ -5717,12 +5717,12 @@ Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() c
return props;
}
-VisualShaderNodeTransformUniform::VisualShaderNodeTransformUniform() {
+VisualShaderNodeTransformParameter::VisualShaderNodeTransformParameter() {
}
//////////////
-String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_type, VisualShaderNodeTextureUniform::ColorDefault p_color_default, VisualShaderNodeTextureUniform::TextureFilter p_texture_filter, VisualShaderNodeTextureUniform::TextureRepeat p_texture_repeat) {
+String get_sampler_hint(VisualShaderNodeTextureParameter::TextureType p_texture_type, VisualShaderNodeTextureParameter::ColorDefault p_color_default, VisualShaderNodeTextureParameter::TextureFilter p_texture_filter, VisualShaderNodeTextureParameter::TextureRepeat p_texture_repeat) {
String code;
bool has_colon = false;
@@ -5731,25 +5731,25 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty
String type_code;
switch (p_texture_type) {
- case VisualShaderNodeTextureUniform::TYPE_DATA:
- if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) {
+ case VisualShaderNodeTextureParameter::TYPE_DATA:
+ if (p_color_default == VisualShaderNodeTextureParameter::COLOR_DEFAULT_BLACK) {
type_code = "hint_default_black";
- } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) {
+ } else if (p_color_default == VisualShaderNodeTextureParameter::COLOR_DEFAULT_TRANSPARENT) {
type_code = "hint_default_transparent";
}
break;
- case VisualShaderNodeTextureUniform::TYPE_COLOR:
+ case VisualShaderNodeTextureParameter::TYPE_COLOR:
type_code = "source_color";
- if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_BLACK) {
+ if (p_color_default == VisualShaderNodeTextureParameter::COLOR_DEFAULT_BLACK) {
type_code += ", hint_default_black";
- } else if (p_color_default == VisualShaderNodeTextureUniform::COLOR_DEFAULT_TRANSPARENT) {
+ } else if (p_color_default == VisualShaderNodeTextureParameter::COLOR_DEFAULT_TRANSPARENT) {
type_code += ", hint_default_transparent";
}
break;
- case VisualShaderNodeTextureUniform::TYPE_NORMAL_MAP:
+ case VisualShaderNodeTextureParameter::TYPE_NORMAL_MAP:
type_code = "hint_normal";
break;
- case VisualShaderNodeTextureUniform::TYPE_ANISOTROPY:
+ case VisualShaderNodeTextureParameter::TYPE_ANISOTROPY:
type_code = "hint_anisotropy";
break;
default:
@@ -5767,22 +5767,22 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty
String filter_code;
switch (p_texture_filter) {
- case VisualShaderNodeTextureUniform::FILTER_NEAREST:
+ case VisualShaderNodeTextureParameter::FILTER_NEAREST:
filter_code = "filter_nearest";
break;
- case VisualShaderNodeTextureUniform::FILTER_LINEAR:
+ case VisualShaderNodeTextureParameter::FILTER_LINEAR:
filter_code = "filter_linear";
break;
- case VisualShaderNodeTextureUniform::FILTER_NEAREST_MIPMAP:
+ case VisualShaderNodeTextureParameter::FILTER_NEAREST_MIPMAP:
filter_code = "filter_nearest_mipmap";
break;
- case VisualShaderNodeTextureUniform::FILTER_LINEAR_MIPMAP:
+ case VisualShaderNodeTextureParameter::FILTER_LINEAR_MIPMAP:
filter_code = "filter_linear_mipmap";
break;
- case VisualShaderNodeTextureUniform::FILTER_NEAREST_MIPMAP_ANISOTROPIC:
+ case VisualShaderNodeTextureParameter::FILTER_NEAREST_MIPMAP_ANISOTROPIC:
filter_code = "filter_nearest_mipmap_anisotropic";
break;
- case VisualShaderNodeTextureUniform::FILTER_LINEAR_MIPMAP_ANISOTROPIC:
+ case VisualShaderNodeTextureParameter::FILTER_LINEAR_MIPMAP_ANISOTROPIC:
filter_code = "filter_linear_mipmap_anisotropic";
break;
default:
@@ -5805,10 +5805,10 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty
String repeat_code;
switch (p_texture_repeat) {
- case VisualShaderNodeTextureUniform::REPEAT_ENABLED:
+ case VisualShaderNodeTextureParameter::REPEAT_ENABLED:
repeat_code = "repeat_enable";
break;
- case VisualShaderNodeTextureUniform::REPEAT_DISABLED:
+ case VisualShaderNodeTextureParameter::REPEAT_DISABLED:
repeat_code = "repeat_disable";
break;
default:
@@ -5828,29 +5828,25 @@ String get_sampler_hint(VisualShaderNodeTextureUniform::TextureType p_texture_ty
return code;
}
-////////////// Texture Uniform
+////////////// Texture Parameter
-String VisualShaderNodeTextureUniform::get_caption() const {
- return "TextureUniform";
-}
-
-int VisualShaderNodeTextureUniform::get_input_port_count() const {
+int VisualShaderNodeTextureParameter::get_input_port_count() const {
return 0;
}
-VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_input_port_type(int p_port) const {
+VisualShaderNodeTextureParameter::PortType VisualShaderNodeTextureParameter::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const {
+String VisualShaderNodeTextureParameter::get_input_port_name(int p_port) const {
return "";
}
-int VisualShaderNodeTextureUniform::get_output_port_count() const {
+int VisualShaderNodeTextureParameter::get_output_port_count() const {
return 1;
}
-VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_output_port_type(int p_port) const {
+VisualShaderNodeTextureParameter::PortType VisualShaderNodeTextureParameter::get_output_port_type(int p_port) const {
switch (p_port) {
case 0:
return PORT_TYPE_SAMPLER;
@@ -5859,27 +5855,11 @@ VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_out
}
}
-String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const {
- switch (p_port) {
- case 0:
- return "sampler2D";
- default:
- return "";
- }
-}
-
-String VisualShaderNodeTextureUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform sampler2D " + get_uniform_name();
- code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
- code += ";\n";
- return code;
-}
-
-String VisualShaderNodeTextureUniform::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 VisualShaderNodeTextureParameter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
return "";
}
-void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_texture_type) {
+void VisualShaderNodeTextureParameter::set_texture_type(TextureType p_texture_type) {
ERR_FAIL_INDEX(int(p_texture_type), int(TYPE_MAX));
if (texture_type == p_texture_type) {
return;
@@ -5888,11 +5868,11 @@ void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_texture_type
emit_changed();
}
-VisualShaderNodeTextureUniform::TextureType VisualShaderNodeTextureUniform::get_texture_type() const {
+VisualShaderNodeTextureParameter::TextureType VisualShaderNodeTextureParameter::get_texture_type() const {
return texture_type;
}
-void VisualShaderNodeTextureUniform::set_color_default(ColorDefault p_color_default) {
+void VisualShaderNodeTextureParameter::set_color_default(ColorDefault p_color_default) {
ERR_FAIL_INDEX(int(p_color_default), int(COLOR_DEFAULT_MAX));
if (color_default == p_color_default) {
return;
@@ -5901,11 +5881,11 @@ void VisualShaderNodeTextureUniform::set_color_default(ColorDefault p_color_defa
emit_changed();
}
-VisualShaderNodeTextureUniform::ColorDefault VisualShaderNodeTextureUniform::get_color_default() const {
+VisualShaderNodeTextureParameter::ColorDefault VisualShaderNodeTextureParameter::get_color_default() const {
return color_default;
}
-void VisualShaderNodeTextureUniform::set_texture_filter(TextureFilter p_filter) {
+void VisualShaderNodeTextureParameter::set_texture_filter(TextureFilter p_filter) {
ERR_FAIL_INDEX(int(p_filter), int(FILTER_MAX));
if (texture_filter == p_filter) {
return;
@@ -5914,11 +5894,11 @@ void VisualShaderNodeTextureUniform::set_texture_filter(TextureFilter p_filter)
emit_changed();
}
-VisualShaderNodeTextureUniform::TextureFilter VisualShaderNodeTextureUniform::get_texture_filter() const {
+VisualShaderNodeTextureParameter::TextureFilter VisualShaderNodeTextureParameter::get_texture_filter() const {
return texture_filter;
}
-void VisualShaderNodeTextureUniform::set_texture_repeat(TextureRepeat p_repeat) {
+void VisualShaderNodeTextureParameter::set_texture_repeat(TextureRepeat p_repeat) {
ERR_FAIL_INDEX(int(p_repeat), int(REPEAT_MAX));
if (texture_repeat == p_repeat) {
return;
@@ -5927,12 +5907,12 @@ void VisualShaderNodeTextureUniform::set_texture_repeat(TextureRepeat p_repeat)
emit_changed();
}
-VisualShaderNodeTextureUniform::TextureRepeat VisualShaderNodeTextureUniform::get_texture_repeat() const {
+VisualShaderNodeTextureParameter::TextureRepeat VisualShaderNodeTextureParameter::get_texture_repeat() const {
return texture_repeat;
}
-Vector<StringName> VisualShaderNodeTextureUniform::get_editable_properties() const {
- Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+Vector<StringName> VisualShaderNodeTextureParameter::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeParameter::get_editable_properties();
props.push_back("texture_type");
if (texture_type == TYPE_DATA || texture_type == TYPE_COLOR) {
props.push_back("color_default");
@@ -5942,11 +5922,11 @@ Vector<StringName> VisualShaderNodeTextureUniform::get_editable_properties() con
return props;
}
-bool VisualShaderNodeTextureUniform::is_show_prop_names() const {
+bool VisualShaderNodeTextureParameter::is_show_prop_names() const {
return true;
}
-HashMap<StringName, String> VisualShaderNodeTextureUniform::get_editable_properties_names() const {
+HashMap<StringName, String> VisualShaderNodeTextureParameter::get_editable_properties_names() const {
HashMap<StringName, String> names;
names.insert("texture_type", RTR("Type"));
names.insert("color_default", RTR("Default Color"));
@@ -5955,18 +5935,18 @@ HashMap<StringName, String> VisualShaderNodeTextureUniform::get_editable_propert
return names;
}
-void VisualShaderNodeTextureUniform::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_texture_type", "type"), &VisualShaderNodeTextureUniform::set_texture_type);
- ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTextureUniform::get_texture_type);
+void VisualShaderNodeTextureParameter::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_texture_type", "type"), &VisualShaderNodeTextureParameter::set_texture_type);
+ ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTextureParameter::get_texture_type);
- ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureUniform::set_color_default);
- ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureUniform::get_color_default);
+ ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureParameter::set_color_default);
+ ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureParameter::get_color_default);
- ClassDB::bind_method(D_METHOD("set_texture_filter", "filter"), &VisualShaderNodeTextureUniform::set_texture_filter);
- ClassDB::bind_method(D_METHOD("get_texture_filter"), &VisualShaderNodeTextureUniform::get_texture_filter);
+ ClassDB::bind_method(D_METHOD("set_texture_filter", "filter"), &VisualShaderNodeTextureParameter::set_texture_filter);
+ ClassDB::bind_method(D_METHOD("get_texture_filter"), &VisualShaderNodeTextureParameter::get_texture_filter);
- ClassDB::bind_method(D_METHOD("set_texture_repeat", "type"), &VisualShaderNodeTextureUniform::set_texture_repeat);
- ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureUniform::get_texture_repeat);
+ ClassDB::bind_method(D_METHOD("set_texture_repeat", "type"), &VisualShaderNodeTextureParameter::set_texture_repeat);
+ ClassDB::bind_method(D_METHOD("get_texture_repeat"), &VisualShaderNodeTextureParameter::get_texture_repeat);
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White,Black,Transparent"), "set_color_default", "get_color_default");
@@ -5999,7 +5979,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() {
BIND_ENUM_CONSTANT(REPEAT_MAX);
}
-bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const {
+bool VisualShaderNodeTextureParameter::is_qualifier_supported(Qualifier p_qual) const {
switch (p_qual) {
case Qualifier::QUAL_NONE:
return true;
@@ -6013,31 +5993,56 @@ bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) co
return false;
}
-bool VisualShaderNodeTextureUniform::is_convertible_to_constant() const {
+bool VisualShaderNodeTextureParameter::is_convertible_to_constant() const {
return false; // conversion is not allowed
}
-VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() {
+VisualShaderNodeTextureParameter::VisualShaderNodeTextureParameter() {
+}
+
+////////////// Texture2D Parameter
+
+String VisualShaderNodeTexture2DParameter::get_caption() const {
+ return "Texture2DParameter";
+}
+
+String VisualShaderNodeTexture2DParameter::get_output_port_name(int p_port) const {
+ switch (p_port) {
+ case 0:
+ return "sampler2D";
+ default:
+ return "";
+ }
+}
+
+String VisualShaderNodeTexture2DParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name();
+ code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
+ code += ";\n";
+ return code;
+}
+
+VisualShaderNodeTexture2DParameter::VisualShaderNodeTexture2DParameter() {
}
-////////////// Texture Uniform (Triplanar)
+////////////// Texture Parameter (Triplanar)
-String VisualShaderNodeTextureUniformTriplanar::get_caption() const {
+String VisualShaderNodeTextureParameterTriplanar::get_caption() const {
return "TextureUniformTriplanar";
}
-int VisualShaderNodeTextureUniformTriplanar::get_input_port_count() const {
+int VisualShaderNodeTextureParameterTriplanar::get_input_port_count() const {
return 2;
}
-VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const {
+VisualShaderNodeTextureParameterTriplanar::PortType VisualShaderNodeTextureParameterTriplanar::get_input_port_type(int p_port) const {
if (p_port == 0 || p_port == 1) {
return PORT_TYPE_VECTOR_3D;
}
return PORT_TYPE_SCALAR;
}
-String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port) const {
+String VisualShaderNodeTextureParameterTriplanar::get_input_port_name(int p_port) const {
if (p_port == 0) {
return "weights";
} else if (p_port == 1) {
@@ -6046,11 +6051,11 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port)
return "";
}
-int VisualShaderNodeTextureUniformTriplanar::get_output_port_count() const {
+int VisualShaderNodeTextureParameterTriplanar::get_output_port_count() const {
return 2;
}
-VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniformTriplanar::get_output_port_type(int p_port) const {
+VisualShaderNodeTextureParameterTriplanar::PortType VisualShaderNodeTextureParameterTriplanar::get_output_port_type(int p_port) const {
switch (p_port) {
case 0:
return PORT_TYPE_VECTOR_4D;
@@ -6061,7 +6066,7 @@ VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniform
}
}
-String VisualShaderNodeTextureUniformTriplanar::get_output_port_name(int p_port) const {
+String VisualShaderNodeTextureParameterTriplanar::get_output_port_name(int p_port) const {
switch (p_port) {
case 0:
return "color";
@@ -6072,7 +6077,7 @@ String VisualShaderNodeTextureUniformTriplanar::get_output_port_name(int p_port)
}
}
-String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
+String VisualShaderNodeTextureParameterTriplanar::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
String code;
code += "// " + get_caption() + "\n";
@@ -6094,7 +6099,7 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader:
return code;
}
-String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
if (p_type == VisualShader::TYPE_VERTEX) {
@@ -6110,8 +6115,8 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader:
return code;
}
-String VisualShaderNodeTextureUniformTriplanar::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 id = get_uniform_name();
+String VisualShaderNodeTextureParameterTriplanar::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 id = get_parameter_name();
String code;
if (p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) {
@@ -6127,7 +6132,7 @@ String VisualShaderNodeTextureUniformTriplanar::generate_code(Shader::Mode p_mod
return code;
}
-bool VisualShaderNodeTextureUniformTriplanar::is_input_port_default(int p_port, Shader::Mode p_mode) const {
+bool VisualShaderNodeTextureParameterTriplanar::is_input_port_default(int p_port, Shader::Mode p_mode) const {
if (p_port == 0) {
return true;
} else if (p_port == 1) {
@@ -6136,79 +6141,67 @@ bool VisualShaderNodeTextureUniformTriplanar::is_input_port_default(int p_port,
return false;
}
-VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() {
+VisualShaderNodeTextureParameterTriplanar::VisualShaderNodeTextureParameterTriplanar() {
}
-////////////// Texture2DArray Uniform
+////////////// Texture2DArray Parameter
-String VisualShaderNodeTexture2DArrayUniform::get_caption() const {
- return "Texture2DArrayUniform";
+String VisualShaderNodeTexture2DArrayParameter::get_caption() const {
+ return "Texture2DArrayParameter";
}
-String VisualShaderNodeTexture2DArrayUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeTexture2DArrayParameter::get_output_port_name(int p_port) const {
return "sampler2DArray";
}
-String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform sampler2DArray " + get_uniform_name();
+String VisualShaderNodeTexture2DArrayParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform sampler2DArray " + get_parameter_name();
code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
code += ";\n";
return code;
}
-String VisualShaderNodeTexture2DArrayUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return String();
-}
-
-VisualShaderNodeTexture2DArrayUniform::VisualShaderNodeTexture2DArrayUniform() {
+VisualShaderNodeTexture2DArrayParameter::VisualShaderNodeTexture2DArrayParameter() {
}
-////////////// Texture3D Uniform
+////////////// Texture3D Parameter
-String VisualShaderNodeTexture3DUniform::get_caption() const {
- return "Texture3DUniform";
+String VisualShaderNodeTexture3DParameter::get_caption() const {
+ return "Texture3DParameter";
}
-String VisualShaderNodeTexture3DUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeTexture3DParameter::get_output_port_name(int p_port) const {
return "sampler3D";
}
-String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform sampler3D " + get_uniform_name();
+String VisualShaderNodeTexture3DParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform sampler3D " + get_parameter_name();
code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
code += ";\n";
return code;
}
-String VisualShaderNodeTexture3DUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return String();
-}
-
-VisualShaderNodeTexture3DUniform::VisualShaderNodeTexture3DUniform() {
+VisualShaderNodeTexture3DParameter::VisualShaderNodeTexture3DParameter() {
}
-////////////// Cubemap Uniform
+////////////// Cubemap Parameter
-String VisualShaderNodeCubemapUniform::get_caption() const {
- return "CubemapUniform";
+String VisualShaderNodeCubemapParameter::get_caption() const {
+ return "CubemapParameter";
}
-String VisualShaderNodeCubemapUniform::get_output_port_name(int p_port) const {
+String VisualShaderNodeCubemapParameter::get_output_port_name(int p_port) const {
return "samplerCube";
}
-String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
- String code = _get_qual_str() + "uniform samplerCube " + get_uniform_name();
+String VisualShaderNodeCubemapParameter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform samplerCube " + get_parameter_name();
code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat);
code += ";\n";
return code;
}
-String VisualShaderNodeCubemapUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- return String();
-}
-
-VisualShaderNodeCubemapUniform::VisualShaderNodeCubemapUniform() {
+VisualShaderNodeCubemapParameter::VisualShaderNodeCubemapParameter() {
}
////////////// If
@@ -7247,7 +7240,11 @@ String VisualShaderNodeProximityFade::generate_code(Shader::Mode p_mode, VisualS
String proximity_fade_distance = vformat("%s", p_input_vars[0]);
code += " float __depth_tex = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;\n";
- code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, __depth_tex, 1.0);\n";
+ if (!RenderingServer::get_singleton()->is_low_end()) {
+ code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, __depth_tex, 1.0);\n";
+ } else {
+ code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(vec3(SCREEN_UV, __depth_tex) * 2.0 - 1.0, 1.0);\n";
+ }
code += " __depth_world_pos.xyz /= __depth_world_pos.z;\n";
code += vformat(" %s = clamp(1.0 - smoothstep(__depth_world_pos.z + %s, __depth_world_pos.z, VERTEX.z), 0.0, 1.0);\n", p_output_vars[0], p_input_vars[0]);
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index c603a10eae..ecba412fcb 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -1762,11 +1762,11 @@ public:
};
///////////////////////////////////////
-/// UNIFORMS
+/// PARAMETERS
///////////////////////////////////////
-class VisualShaderNodeFloatUniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeFloatUniform, VisualShaderNodeUniform);
+class VisualShaderNodeFloatParameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeFloatParameter, VisualShaderNodeParameter);
public:
enum Hint {
@@ -1827,13 +1827,13 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeFloatUniform();
+ VisualShaderNodeFloatParameter();
};
-VARIANT_ENUM_CAST(VisualShaderNodeFloatUniform::Hint)
+VARIANT_ENUM_CAST(VisualShaderNodeFloatParameter::Hint)
-class VisualShaderNodeIntUniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeIntUniform, VisualShaderNodeUniform);
+class VisualShaderNodeIntParameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeIntParameter, VisualShaderNodeParameter);
public:
enum Hint {
@@ -1894,15 +1894,15 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeIntUniform();
+ VisualShaderNodeIntParameter();
};
-VARIANT_ENUM_CAST(VisualShaderNodeIntUniform::Hint)
+VARIANT_ENUM_CAST(VisualShaderNodeIntParameter::Hint)
///////////////////////////////////////
-class VisualShaderNodeBooleanUniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeBooleanUniform, VisualShaderNodeUniform);
+class VisualShaderNodeBooleanParameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeBooleanParameter, VisualShaderNodeParameter);
private:
bool default_value_enabled = false;
@@ -1939,13 +1939,13 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeBooleanUniform();
+ VisualShaderNodeBooleanParameter();
};
///////////////////////////////////////
-class VisualShaderNodeColorUniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeColorUniform, VisualShaderNodeUniform);
+class VisualShaderNodeColorParameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeColorParameter, VisualShaderNodeParameter);
private:
bool default_value_enabled = false;
@@ -1983,13 +1983,13 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeColorUniform();
+ VisualShaderNodeColorParameter();
};
///////////////////////////////////////
-class VisualShaderNodeVec2Uniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeVec2Uniform, VisualShaderNodeUniform);
+class VisualShaderNodeVec2Parameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeVec2Parameter, VisualShaderNodeParameter);
private:
bool default_value_enabled = false;
@@ -2026,13 +2026,13 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeVec2Uniform();
+ VisualShaderNodeVec2Parameter();
};
///////////////////////////////////////
-class VisualShaderNodeVec3Uniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeVec3Uniform, VisualShaderNodeUniform);
+class VisualShaderNodeVec3Parameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeVec3Parameter, VisualShaderNodeParameter);
private:
bool default_value_enabled = false;
@@ -2069,17 +2069,17 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeVec3Uniform();
+ VisualShaderNodeVec3Parameter();
};
///////////////////////////////////////
-class VisualShaderNodeVec4Uniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeVec4Uniform, VisualShaderNodeUniform);
+class VisualShaderNodeVec4Parameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeVec4Parameter, VisualShaderNodeParameter);
private:
bool default_value_enabled = false;
- Quaternion default_value;
+ Vector4 default_value;
protected:
static void _bind_methods();
@@ -2104,21 +2104,21 @@ public:
void set_default_value_enabled(bool p_enabled);
bool is_default_value_enabled() const;
- void set_default_value(const Quaternion &p_value);
- Quaternion get_default_value() const;
+ void set_default_value(const Vector4 &p_value);
+ Vector4 get_default_value() const;
bool is_qualifier_supported(Qualifier p_qual) const override;
bool is_convertible_to_constant() const override;
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeVec4Uniform();
+ VisualShaderNodeVec4Parameter();
};
///////////////////////////////////////
-class VisualShaderNodeTransformUniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeTransformUniform, VisualShaderNodeUniform);
+class VisualShaderNodeTransformParameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeTransformParameter, VisualShaderNodeParameter);
private:
bool default_value_enabled = false;
@@ -2155,13 +2155,13 @@ public:
virtual Vector<StringName> get_editable_properties() const override;
- VisualShaderNodeTransformUniform();
+ VisualShaderNodeTransformParameter();
};
///////////////////////////////////////
-class VisualShaderNodeTextureUniform : public VisualShaderNodeUniform {
- GDCLASS(VisualShaderNodeTextureUniform, VisualShaderNodeUniform);
+class VisualShaderNodeTextureParameter : public VisualShaderNodeParameter {
+ GDCLASS(VisualShaderNodeTextureParameter, VisualShaderNodeParameter);
public:
enum TextureType {
@@ -2207,17 +2207,13 @@ protected:
static void _bind_methods();
public:
- virtual String get_caption() const override;
-
virtual int get_input_port_count() const override;
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
- virtual String get_output_port_name(int p_port) const override;
- virtual 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;
virtual HashMap<StringName, String> get_editable_properties_names() const override;
@@ -2240,18 +2236,32 @@ public:
bool is_qualifier_supported(Qualifier p_qual) const override;
bool is_convertible_to_constant() const override;
- VisualShaderNodeTextureUniform();
+ VisualShaderNodeTextureParameter();
};
-VARIANT_ENUM_CAST(VisualShaderNodeTextureUniform::TextureType)
-VARIANT_ENUM_CAST(VisualShaderNodeTextureUniform::ColorDefault)
-VARIANT_ENUM_CAST(VisualShaderNodeTextureUniform::TextureFilter)
-VARIANT_ENUM_CAST(VisualShaderNodeTextureUniform::TextureRepeat)
+VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureType)
+VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::ColorDefault)
+VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureFilter)
+VARIANT_ENUM_CAST(VisualShaderNodeTextureParameter::TextureRepeat)
+
+///////////////////////////////////////
+
+class VisualShaderNodeTexture2DParameter : public VisualShaderNodeTextureParameter {
+ GDCLASS(VisualShaderNodeTexture2DParameter, VisualShaderNodeTextureParameter);
+
+public:
+ virtual String get_caption() const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+
+ VisualShaderNodeTexture2DParameter();
+};
///////////////////////////////////////
-class VisualShaderNodeTextureUniformTriplanar : public VisualShaderNodeTextureUniform {
- GDCLASS(VisualShaderNodeTextureUniformTriplanar, VisualShaderNodeTextureUniform);
+class VisualShaderNodeTextureParameterTriplanar : public VisualShaderNodeTextureParameter {
+ GDCLASS(VisualShaderNodeTextureParameterTriplanar, VisualShaderNodeTextureParameter);
public:
virtual String get_caption() const override;
@@ -2270,52 +2280,49 @@ public:
virtual String generate_global_per_func(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;
- VisualShaderNodeTextureUniformTriplanar();
+ VisualShaderNodeTextureParameterTriplanar();
};
///////////////////////////////////////
-class VisualShaderNodeTexture2DArrayUniform : public VisualShaderNodeTextureUniform {
- GDCLASS(VisualShaderNodeTexture2DArrayUniform, VisualShaderNodeTextureUniform);
+class VisualShaderNodeTexture2DArrayParameter : public VisualShaderNodeTextureParameter {
+ GDCLASS(VisualShaderNodeTexture2DArrayParameter, VisualShaderNodeTextureParameter);
public:
virtual String get_caption() const override;
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
- VisualShaderNodeTexture2DArrayUniform();
+ VisualShaderNodeTexture2DArrayParameter();
};
///////////////////////////////////////
-class VisualShaderNodeTexture3DUniform : public VisualShaderNodeTextureUniform {
- GDCLASS(VisualShaderNodeTexture3DUniform, VisualShaderNodeTextureUniform);
+class VisualShaderNodeTexture3DParameter : public VisualShaderNodeTextureParameter {
+ GDCLASS(VisualShaderNodeTexture3DParameter, VisualShaderNodeTextureParameter);
public:
virtual String get_caption() const override;
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
- VisualShaderNodeTexture3DUniform();
+ VisualShaderNodeTexture3DParameter();
};
///////////////////////////////////////
-class VisualShaderNodeCubemapUniform : public VisualShaderNodeTextureUniform {
- GDCLASS(VisualShaderNodeCubemapUniform, VisualShaderNodeTextureUniform);
+class VisualShaderNodeCubemapParameter : public VisualShaderNodeTextureParameter {
+ GDCLASS(VisualShaderNodeCubemapParameter, VisualShaderNodeTextureParameter);
public:
virtual String get_caption() const override;
virtual String get_output_port_name(int p_port) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
- virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
- VisualShaderNodeCubemapUniform();
+ VisualShaderNodeCubemapParameter();
};
///////////////////////////////////////
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 4dfbe5f079..75deb1e60b 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -85,6 +85,7 @@ World2D::World2D() {
NavigationServer2D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 1));
NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 1));
+ NavigationServer2D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_DEF("navigation/2d/default_link_connection_radius", 4));
}
World2D::~World2D() {
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index fb6dcd3d57..ae8c9a182f 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -33,6 +33,8 @@
#include "core/config/project_settings.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/visible_on_screen_notifier_3d.h"
+#include "scene/resources/camera_attributes.h"
+#include "scene/resources/environment.h"
#include "scene/scene_string_names.h"
#include "servers/navigation_server_3d.h"
@@ -98,17 +100,17 @@ Ref<Environment> World3D::get_fallback_environment() const {
return fallback_environment;
}
-void World3D::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
- camera_effects = p_camera_effects;
- if (camera_effects.is_valid()) {
- RS::get_singleton()->scenario_set_camera_effects(scenario, camera_effects->get_rid());
+void World3D::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
+ camera_attributes = p_camera_attributes;
+ if (camera_attributes.is_valid()) {
+ RS::get_singleton()->scenario_set_camera_attributes(scenario, camera_attributes->get_rid());
} else {
- RS::get_singleton()->scenario_set_camera_effects(scenario, RID());
+ RS::get_singleton()->scenario_set_camera_attributes(scenario, RID());
}
}
-Ref<CameraEffects> World3D::get_camera_effects() const {
- return camera_effects;
+Ref<CameraAttributes> World3D::get_camera_attributes() const {
+ return camera_attributes;
}
PhysicsDirectSpaceState3D *World3D::get_direct_space_state() {
@@ -123,12 +125,12 @@ void World3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment);
ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World3D::set_fallback_environment);
ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World3D::get_fallback_environment);
- ClassDB::bind_method(D_METHOD("set_camera_effects", "effects"), &World3D::set_camera_effects);
- ClassDB::bind_method(D_METHOD("get_camera_effects"), &World3D::get_camera_effects);
+ ClassDB::bind_method(D_METHOD("set_camera_attributes", "attributes"), &World3D::set_camera_attributes);
+ ClassDB::bind_method(D_METHOD("get_camera_attributes"), &World3D::get_camera_attributes);
ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World3D::get_direct_space_state);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_space");
ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_navigation_map");
ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_scenario");
@@ -151,6 +153,7 @@ World3D::World3D() {
NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.25));
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 0.25));
+ NavigationServer3D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_DEF("navigation/3d/default_link_connection_radius", 1.0));
}
World3D::~World3D() {
diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h
index 08bc050349..411b9aab37 100644
--- a/scene/resources/world_3d.h
+++ b/scene/resources/world_3d.h
@@ -32,11 +32,11 @@
#define WORLD_3D_H
#include "core/io/resource.h"
-#include "scene/resources/camera_effects.h"
#include "scene/resources/environment.h"
#include "servers/physics_server_3d.h"
#include "servers/rendering_server.h"
+class CameraAttributes;
class Camera3D;
class VisibleOnScreenNotifier3D;
struct SpatialIndexer;
@@ -51,7 +51,7 @@ private:
Ref<Environment> environment;
Ref<Environment> fallback_environment;
- Ref<CameraEffects> camera_effects;
+ Ref<CameraAttributes> camera_attributes;
HashSet<Camera3D *> cameras;
@@ -74,8 +74,8 @@ public:
void set_fallback_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_fallback_environment() const;
- void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
- Ref<CameraEffects> get_camera_effects() const;
+ void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes);
+ Ref<CameraAttributes> get_camera_attributes() const;
_FORCE_INLINE_ const HashSet<Camera3D *> &get_cameras() const { return cameras; }