summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/math/geometry_3d.cpp6
-rw-r--r--doc/classes/Tree.xml7
-rw-r--r--drivers/alsa/asound-so_wrap.c48
-rw-r--r--drivers/alsa/asound-so_wrap.h20
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp433
-rw-r--r--editor/plugins/node_3d_editor_plugin.h59
-rw-r--r--main/main.cpp21
-rw-r--r--main/main.h2
-rw-r--r--modules/mono/editor/bindings_generator.cpp3
-rw-r--r--platform/server/detect.py1
-rw-r--r--scene/3d/world_environment.cpp86
-rw-r--r--scene/3d/world_environment.h3
-rw-r--r--scene/gui/button.cpp5
-rw-r--r--scene/gui/tree.cpp1
-rw-r--r--scene/main/scene_tree.cpp16
-rw-r--r--scene/main/scene_tree.h1
16 files changed, 614 insertions, 98 deletions
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index a4a7463bfd..6628b760e0 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -775,6 +775,8 @@ Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) {
}
Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
const double sides_step = Math_TAU / p_sides;
@@ -796,6 +798,8 @@ Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height
}
Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
Vector3 axis;
@@ -827,6 +831,8 @@ Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p
}
Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) {
+ ERR_FAIL_INDEX_V(p_axis, 3, Vector<Plane>());
+
Vector<Plane> planes;
Vector3 axis;
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index f1e799898d..8502707096 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -57,6 +57,13 @@
The new item will be the [code]idx[/code]th child of parent, or it will be the last child if there are not enough siblings.
</description>
</method>
+ <method name="edit_selected">
+ <return type="bool">
+ </return>
+ <description>
+ Edits the selected tree item as if it was clicked. The item must be set editable with [method TreeItem.set_editable]. Returns [code]true[/code] if the item could be edited. Fails if no item is selected.
+ </description>
+ </method>
<method name="ensure_cursor_is_visible">
<return type="void">
</return>
diff --git a/drivers/alsa/asound-so_wrap.c b/drivers/alsa/asound-so_wrap.c
index 0c759b75ca..65624bcb70 100644
--- a/drivers/alsa/asound-so_wrap.c
+++ b/drivers/alsa/asound-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:12
-// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/alsa/asoundlib.h --sys-include <alsa/asoundlib.h> --soname libasound.so.2 --init-name asound --output-header asound-so_wrap.h --output-implementation asound-so_wrap.c
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-22 19:22:12
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/alsa/asoundlib.h --sys-include <alsa/asoundlib.h> --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header asound-so_wrap.h --output-implementation asound-so_wrap.c
//
#include <stdint.h>
@@ -319,8 +319,6 @@
#define snd_pcm_sw_params_get_boundary snd_pcm_sw_params_get_boundary_dylibloader_orig_asound
#define snd_pcm_sw_params_set_tstamp_mode snd_pcm_sw_params_set_tstamp_mode_dylibloader_orig_asound
#define snd_pcm_sw_params_get_tstamp_mode snd_pcm_sw_params_get_tstamp_mode_dylibloader_orig_asound
-#define snd_pcm_sw_params_set_tstamp_type snd_pcm_sw_params_set_tstamp_type_dylibloader_orig_asound
-#define snd_pcm_sw_params_get_tstamp_type snd_pcm_sw_params_get_tstamp_type_dylibloader_orig_asound
#define snd_pcm_sw_params_set_avail_min snd_pcm_sw_params_set_avail_min_dylibloader_orig_asound
#define snd_pcm_sw_params_get_avail_min snd_pcm_sw_params_get_avail_min_dylibloader_orig_asound
#define snd_pcm_sw_params_set_period_event snd_pcm_sw_params_set_period_event_dylibloader_orig_asound
@@ -374,8 +372,6 @@
#define snd_pcm_status_get_htstamp snd_pcm_status_get_htstamp_dylibloader_orig_asound
#define snd_pcm_status_get_audio_htstamp snd_pcm_status_get_audio_htstamp_dylibloader_orig_asound
#define snd_pcm_status_get_driver_htstamp snd_pcm_status_get_driver_htstamp_dylibloader_orig_asound
-#define snd_pcm_status_get_audio_htstamp_report snd_pcm_status_get_audio_htstamp_report_dylibloader_orig_asound
-#define snd_pcm_status_set_audio_htstamp_config snd_pcm_status_set_audio_htstamp_config_dylibloader_orig_asound
#define snd_pcm_status_get_delay snd_pcm_status_get_delay_dylibloader_orig_asound
#define snd_pcm_status_get_avail snd_pcm_status_get_avail_dylibloader_orig_asound
#define snd_pcm_status_get_avail_max snd_pcm_status_get_avail_max_dylibloader_orig_asound
@@ -1603,8 +1599,6 @@
#undef snd_pcm_sw_params_get_boundary
#undef snd_pcm_sw_params_set_tstamp_mode
#undef snd_pcm_sw_params_get_tstamp_mode
-#undef snd_pcm_sw_params_set_tstamp_type
-#undef snd_pcm_sw_params_get_tstamp_type
#undef snd_pcm_sw_params_set_avail_min
#undef snd_pcm_sw_params_get_avail_min
#undef snd_pcm_sw_params_set_period_event
@@ -1658,8 +1652,6 @@
#undef snd_pcm_status_get_htstamp
#undef snd_pcm_status_get_audio_htstamp
#undef snd_pcm_status_get_driver_htstamp
-#undef snd_pcm_status_get_audio_htstamp_report
-#undef snd_pcm_status_set_audio_htstamp_config
#undef snd_pcm_status_get_delay
#undef snd_pcm_status_get_avail
#undef snd_pcm_status_get_avail_max
@@ -2888,8 +2880,6 @@ void (*snd_pcm_sw_params_copy_dylibloader_wrapper_asound)( snd_pcm_sw_params_t*,
int (*snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
int (*snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_tstamp_t);
int (*snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_tstamp_t*);
-int (*snd_pcm_sw_params_set_tstamp_type_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_tstamp_type_t);
-int (*snd_pcm_sw_params_get_tstamp_type_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_tstamp_type_t*);
int (*snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
int (*snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
int (*snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, int);
@@ -2943,8 +2933,6 @@ void (*snd_pcm_status_get_tstamp_dylibloader_wrapper_asound)(const snd_pcm_statu
void (*snd_pcm_status_get_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
void (*snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
void (*snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
-void (*snd_pcm_status_get_audio_htstamp_report_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_pcm_audio_tstamp_report_t*);
-void (*snd_pcm_status_set_audio_htstamp_config_dylibloader_wrapper_asound)( snd_pcm_status_t*, snd_pcm_audio_tstamp_config_t*);
snd_pcm_sframes_t (*snd_pcm_status_get_delay_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
snd_pcm_uframes_t (*snd_pcm_status_get_avail_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
snd_pcm_uframes_t (*snd_pcm_status_get_avail_max_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
@@ -6380,22 +6368,6 @@ int initialize_asound(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
-// snd_pcm_sw_params_set_tstamp_type
- *(void **) (&snd_pcm_sw_params_set_tstamp_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_tstamp_type");
- if (verbose) {
- error = dlerror();
- if (error != NULL) {
- fprintf(stderr, "%s\n", error);
- }
- }
-// snd_pcm_sw_params_get_tstamp_type
- *(void **) (&snd_pcm_sw_params_get_tstamp_type_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_get_tstamp_type");
- if (verbose) {
- error = dlerror();
- if (error != NULL) {
- fprintf(stderr, "%s\n", error);
- }
- }
// snd_pcm_sw_params_set_avail_min
*(void **) (&snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_sw_params_set_avail_min");
if (verbose) {
@@ -6820,22 +6792,6 @@ int initialize_asound(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
-// snd_pcm_status_get_audio_htstamp_report
- *(void **) (&snd_pcm_status_get_audio_htstamp_report_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_audio_htstamp_report");
- if (verbose) {
- error = dlerror();
- if (error != NULL) {
- fprintf(stderr, "%s\n", error);
- }
- }
-// snd_pcm_status_set_audio_htstamp_config
- *(void **) (&snd_pcm_status_set_audio_htstamp_config_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_set_audio_htstamp_config");
- if (verbose) {
- error = dlerror();
- if (error != NULL) {
- fprintf(stderr, "%s\n", error);
- }
- }
// snd_pcm_status_get_delay
*(void **) (&snd_pcm_status_get_delay_dylibloader_wrapper_asound) = dlsym(handle, "snd_pcm_status_get_delay");
if (verbose) {
diff --git a/drivers/alsa/asound-so_wrap.h b/drivers/alsa/asound-so_wrap.h
index c9b8ae8aec..5332d74152 100644
--- a/drivers/alsa/asound-so_wrap.h
+++ b/drivers/alsa/asound-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_ASOUND
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-20 00:08:12
-// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/alsa/asoundlib.h --sys-include <alsa/asoundlib.h> --soname libasound.so.2 --init-name asound --output-header asound-so_wrap.h --output-implementation asound-so_wrap.c
+// generated by /home/hp/Projects/godot/pulse/generate-wrapper.py 0.3 on 2021-02-22 19:22:12
+// flags: /home/hp/Projects/godot/pulse/generate-wrapper.py --include /usr/include/alsa/asoundlib.h --sys-include <alsa/asoundlib.h> --soname libasound.so.2 --init-name asound --omit-prefix snd_pcm_sw_params_set_tstamp_type --omit-prefix snd_pcm_status_get_audio_htstamp_report --omit-prefix snd_pcm_sw_params_get_tstamp_type --omit-prefix snd_pcm_status_set_audio_htstamp_config --output-header asound-so_wrap.h --output-implementation asound-so_wrap.c
//
#include <stdint.h>
@@ -321,8 +321,6 @@
#define snd_pcm_sw_params_get_boundary snd_pcm_sw_params_get_boundary_dylibloader_orig_asound
#define snd_pcm_sw_params_set_tstamp_mode snd_pcm_sw_params_set_tstamp_mode_dylibloader_orig_asound
#define snd_pcm_sw_params_get_tstamp_mode snd_pcm_sw_params_get_tstamp_mode_dylibloader_orig_asound
-#define snd_pcm_sw_params_set_tstamp_type snd_pcm_sw_params_set_tstamp_type_dylibloader_orig_asound
-#define snd_pcm_sw_params_get_tstamp_type snd_pcm_sw_params_get_tstamp_type_dylibloader_orig_asound
#define snd_pcm_sw_params_set_avail_min snd_pcm_sw_params_set_avail_min_dylibloader_orig_asound
#define snd_pcm_sw_params_get_avail_min snd_pcm_sw_params_get_avail_min_dylibloader_orig_asound
#define snd_pcm_sw_params_set_period_event snd_pcm_sw_params_set_period_event_dylibloader_orig_asound
@@ -376,8 +374,6 @@
#define snd_pcm_status_get_htstamp snd_pcm_status_get_htstamp_dylibloader_orig_asound
#define snd_pcm_status_get_audio_htstamp snd_pcm_status_get_audio_htstamp_dylibloader_orig_asound
#define snd_pcm_status_get_driver_htstamp snd_pcm_status_get_driver_htstamp_dylibloader_orig_asound
-#define snd_pcm_status_get_audio_htstamp_report snd_pcm_status_get_audio_htstamp_report_dylibloader_orig_asound
-#define snd_pcm_status_set_audio_htstamp_config snd_pcm_status_set_audio_htstamp_config_dylibloader_orig_asound
#define snd_pcm_status_get_delay snd_pcm_status_get_delay_dylibloader_orig_asound
#define snd_pcm_status_get_avail snd_pcm_status_get_avail_dylibloader_orig_asound
#define snd_pcm_status_get_avail_max snd_pcm_status_get_avail_max_dylibloader_orig_asound
@@ -1605,8 +1601,6 @@
#undef snd_pcm_sw_params_get_boundary
#undef snd_pcm_sw_params_set_tstamp_mode
#undef snd_pcm_sw_params_get_tstamp_mode
-#undef snd_pcm_sw_params_set_tstamp_type
-#undef snd_pcm_sw_params_get_tstamp_type
#undef snd_pcm_sw_params_set_avail_min
#undef snd_pcm_sw_params_get_avail_min
#undef snd_pcm_sw_params_set_period_event
@@ -1660,8 +1654,6 @@
#undef snd_pcm_status_get_htstamp
#undef snd_pcm_status_get_audio_htstamp
#undef snd_pcm_status_get_driver_htstamp
-#undef snd_pcm_status_get_audio_htstamp_report
-#undef snd_pcm_status_set_audio_htstamp_config
#undef snd_pcm_status_get_delay
#undef snd_pcm_status_get_avail
#undef snd_pcm_status_get_avail_max
@@ -2891,8 +2883,6 @@ extern "C" {
#define snd_pcm_sw_params_get_boundary snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound
#define snd_pcm_sw_params_set_tstamp_mode snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound
#define snd_pcm_sw_params_get_tstamp_mode snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound
-#define snd_pcm_sw_params_set_tstamp_type snd_pcm_sw_params_set_tstamp_type_dylibloader_wrapper_asound
-#define snd_pcm_sw_params_get_tstamp_type snd_pcm_sw_params_get_tstamp_type_dylibloader_wrapper_asound
#define snd_pcm_sw_params_set_avail_min snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound
#define snd_pcm_sw_params_get_avail_min snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound
#define snd_pcm_sw_params_set_period_event snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound
@@ -2946,8 +2936,6 @@ extern "C" {
#define snd_pcm_status_get_htstamp snd_pcm_status_get_htstamp_dylibloader_wrapper_asound
#define snd_pcm_status_get_audio_htstamp snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound
#define snd_pcm_status_get_driver_htstamp snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound
-#define snd_pcm_status_get_audio_htstamp_report snd_pcm_status_get_audio_htstamp_report_dylibloader_wrapper_asound
-#define snd_pcm_status_set_audio_htstamp_config snd_pcm_status_set_audio_htstamp_config_dylibloader_wrapper_asound
#define snd_pcm_status_get_delay snd_pcm_status_get_delay_dylibloader_wrapper_asound
#define snd_pcm_status_get_avail snd_pcm_status_get_avail_dylibloader_wrapper_asound
#define snd_pcm_status_get_avail_max snd_pcm_status_get_avail_max_dylibloader_wrapper_asound
@@ -4174,8 +4162,6 @@ extern void (*snd_pcm_sw_params_copy_dylibloader_wrapper_asound)( snd_pcm_sw_par
extern int (*snd_pcm_sw_params_get_boundary_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
extern int (*snd_pcm_sw_params_set_tstamp_mode_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_tstamp_t);
extern int (*snd_pcm_sw_params_get_tstamp_mode_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_tstamp_t*);
-extern int (*snd_pcm_sw_params_set_tstamp_type_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_tstamp_type_t);
-extern int (*snd_pcm_sw_params_get_tstamp_type_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_tstamp_type_t*);
extern int (*snd_pcm_sw_params_set_avail_min_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
extern int (*snd_pcm_sw_params_get_avail_min_dylibloader_wrapper_asound)(const snd_pcm_sw_params_t*, snd_pcm_uframes_t*);
extern int (*snd_pcm_sw_params_set_period_event_dylibloader_wrapper_asound)( snd_pcm_t*, snd_pcm_sw_params_t*, int);
@@ -4229,8 +4215,6 @@ extern void (*snd_pcm_status_get_tstamp_dylibloader_wrapper_asound)(const snd_pc
extern void (*snd_pcm_status_get_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
extern void (*snd_pcm_status_get_audio_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
extern void (*snd_pcm_status_get_driver_htstamp_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_htimestamp_t*);
-extern void (*snd_pcm_status_get_audio_htstamp_report_dylibloader_wrapper_asound)(const snd_pcm_status_t*, snd_pcm_audio_tstamp_report_t*);
-extern void (*snd_pcm_status_set_audio_htstamp_config_dylibloader_wrapper_asound)( snd_pcm_status_t*, snd_pcm_audio_tstamp_config_t*);
extern snd_pcm_sframes_t (*snd_pcm_status_get_delay_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
extern snd_pcm_uframes_t (*snd_pcm_status_get_avail_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
extern snd_pcm_uframes_t (*snd_pcm_status_get_avail_max_dylibloader_wrapper_asound)(const snd_pcm_status_t*);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 713837df44..1d3835add9 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -48,6 +48,7 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/gui/center_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/packed_scene.h"
#include "scene/resources/surface_tool.h"
@@ -4711,6 +4712,28 @@ Dictionary Node3DEditor::get_state() const {
}
d["gizmos_status"] = gizmos_status;
+ {
+ Dictionary pd;
+
+ pd["sun_rotation"] = sun_rotation;
+
+ pd["environ_sky_color"] = environ_sky_color->get_pick_color();
+ pd["environ_ground_color"] = environ_ground_color->get_pick_color();
+ pd["environ_energy"] = environ_energy->get_value();
+ pd["environ_glow_enabled"] = environ_glow_button->is_pressed();
+ pd["environ_tonemap_enabled"] = environ_tonemap_button->is_pressed();
+ pd["environ_ao_enabled"] = environ_ao_button->is_pressed();
+ pd["environ_gi_enabled"] = environ_gi_button->is_pressed();
+ pd["sun_max_distance"] = sun_max_distance->get_value();
+
+ pd["sun_color"] = sun_color->get_pick_color();
+ pd["sun_energy"] = sun_energy->get_value();
+
+ pd["sun_disabled"] = sun_button->is_pressed();
+ pd["environ_disabled"] = environ_button->is_pressed();
+
+ d["preview_sun_env"] = pd;
+ }
return d;
}
@@ -4820,6 +4843,38 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
}
_update_gizmos_menu();
}
+
+ if (d.has("preview_sun_env")) {
+ sun_environ_updating = true;
+ Dictionary pd = d["preview_sun_env"];
+ sun_rotation = pd["sun_rotation"];
+
+ environ_sky_color->set_pick_color(pd["environ_sky_color"]);
+ environ_ground_color->set_pick_color(pd["environ_ground_color"]);
+ environ_energy->set_value(pd["environ_energy"]);
+ environ_glow_button->set_pressed(pd["environ_glow_enabled"]);
+ environ_tonemap_button->set_pressed(pd["environ_tonemap_enabled"]);
+ environ_ao_button->set_pressed(pd["environ_ao_enabled"]);
+ environ_gi_button->set_pressed(pd["environ_gi_enabled"]);
+ sun_max_distance->set_value(pd["sun_max_distance"]);
+
+ sun_color->set_pick_color(pd["sun_color"]);
+ sun_energy->set_value(pd["sun_energy"]);
+
+ sun_button->set_pressed(pd["sun_disabled"]);
+ environ_button->set_pressed(pd["environ_disabled"]);
+
+ sun_environ_updating = false;
+
+ _preview_settings_changed();
+ _update_preview_environment();
+ } else {
+ _load_default_preview_settings();
+ sun_button->set_pressed(false);
+ environ_button->set_pressed(false);
+ _preview_settings_changed();
+ _update_preview_environment();
+ }
}
void Node3DEditor::edit(Node3D *p_spatial) {
@@ -6106,6 +6161,51 @@ void Node3DEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
}
+void Node3DEditor::_sun_environ_settings_pressed() {
+ Vector2 pos = sun_environ_settings->get_screen_position() + sun_environ_settings->get_size();
+ sun_environ_popup->set_position(pos - Vector2(sun_environ_popup->get_contents_minimum_size().width / 2, 0));
+ sun_environ_popup->popup();
+}
+
+void Node3DEditor::_add_sun_to_scene() {
+ sun_environ_popup->hide();
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
+ return;
+ }
+ ERR_FAIL_COND(!base);
+ Node *new_sun = preview_sun->duplicate();
+
+ undo_redo->create_action("Add Preview Sun to Scene");
+ undo_redo->add_do_method(base, "add_child", new_sun);
+ undo_redo->add_do_method(new_sun, "set_owner", base);
+ undo_redo->add_undo_method(base, "remove_child", new_sun);
+ undo_redo->add_do_reference(new_sun);
+ undo_redo->commit_action();
+}
+void Node3DEditor::_add_environment_to_scene() {
+ sun_environ_popup->hide();
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("A root node is needed for this operation"));
+ return;
+ }
+ ERR_FAIL_COND(!base);
+
+ WorldEnvironment *new_env = memnew(WorldEnvironment);
+ new_env->set_environment(preview_environment->get_environment()->duplicate(true));
+
+ undo_redo->create_action("Add Preview Environment to Scene");
+ undo_redo->add_do_method(base, "add_child", new_env);
+ undo_redo->add_do_method(new_env, "set_owner", base);
+ undo_redo->add_undo_method(base, "remove_child", new_env);
+ undo_redo->add_do_reference(new_env);
+ undo_redo->commit_action();
+}
+
void Node3DEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons"));
@@ -6134,17 +6234,29 @@ void Node3DEditor::_notification(int p_what) {
_refresh_menu_icons();
get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed));
+ get_tree()->connect("node_added", callable_mp(this, &Node3DEditor::_node_added));
EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
+
+ sun_button->set_icon(get_theme_icon("DirectionalLight3D", "EditorIcons"));
+ environ_button->set_icon(get_theme_icon("WorldEnvironment", "EditorIcons"));
+ sun_environ_settings->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons"));
+
+ _update_preview_environment();
+ sun_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+ environ_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+
} else if (p_what == NOTIFICATION_ENTER_TREE) {
_register_all_gizmos();
_update_gizmos_menu();
_init_indicators();
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
_update_gizmos_menu_theme();
+ sun_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
+ environ_title->add_theme_font_override("font", get_theme_font("title_font", "Window"));
} else if (p_what == NOTIFICATION_EXIT_TREE) {
_finish_indicators();
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
@@ -6281,7 +6393,37 @@ void Node3DEditor::_toggle_maximize_view(Object *p_viewport) {
}
}
+void Node3DEditor::_node_added(Node *p_node) {
+ if (EditorNode::get_singleton()->get_scene_root()->is_a_parent_of(p_node)) {
+ if (Object::cast_to<WorldEnvironment>(p_node)) {
+ world_env_count++;
+ if (world_env_count == 1) {
+ _update_preview_environment();
+ }
+ } else if (Object::cast_to<DirectionalLight3D>(p_node)) {
+ directional_light_count++;
+ if (directional_light_count == 1) {
+ _update_preview_environment();
+ }
+ }
+ }
+}
+
void Node3DEditor::_node_removed(Node *p_node) {
+ if (EditorNode::get_singleton()->get_scene_root()->is_a_parent_of(p_node)) {
+ if (Object::cast_to<WorldEnvironment>(p_node)) {
+ world_env_count--;
+ if (world_env_count == 0) {
+ _update_preview_environment();
+ }
+ } else if (Object::cast_to<DirectionalLight3D>(p_node)) {
+ directional_light_count--;
+ if (directional_light_count == 0) {
+ _update_preview_environment();
+ }
+ }
+ }
+
if (p_node == selected) {
selected = nullptr;
}
@@ -6351,6 +6493,128 @@ void Node3DEditor::clear() {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true);
}
+void Node3DEditor::_sun_direction_draw() {
+ sun_direction->draw_rect(Rect2(Vector2(), sun_direction->get_size()), Color(1, 1, 1, 1));
+ sun_direction_material->set_shader_param("sun_direction", -preview_sun->get_transform().basis.get_axis(Vector3::AXIS_Z));
+ float nrg = sun_energy->get_value();
+ sun_direction_material->set_shader_param("sun_color", Vector3(sun_color->get_pick_color().r * nrg, sun_color->get_pick_color().g * nrg, sun_color->get_pick_color().b * nrg));
+}
+
+void Node3DEditor::_preview_settings_changed() {
+ if (sun_environ_updating) {
+ return;
+ }
+
+ { // preview sun
+ Transform t;
+ t.basis = sun_rotation;
+ preview_sun->set_transform(t);
+ sun_direction->update();
+ preview_sun->set_param(Light3D::PARAM_ENERGY, sun_energy->get_value());
+ preview_sun->set_param(Light3D::PARAM_SHADOW_MAX_DISTANCE, sun_max_distance->get_value());
+ preview_sun->set_color(sun_color->get_pick_color());
+ }
+
+ { //preview env
+ sky_material->set_sky_energy(environ_energy->get_value());
+ Color hz_color = environ_sky_color->get_pick_color().lerp(environ_ground_color->get_pick_color(), 0.5).lerp(Color(1, 1, 1), 0.5);
+ sky_material->set_sky_top_color(environ_sky_color->get_pick_color());
+ sky_material->set_sky_horizon_color(hz_color);
+ sky_material->set_ground_bottom_color(environ_ground_color->get_pick_color());
+ sky_material->set_ground_horizon_color(hz_color);
+
+ environment->set_ssao_enabled(environ_ao_button->is_pressed());
+ environment->set_glow_enabled(environ_glow_button->is_pressed());
+ environment->set_sdfgi_enabled(environ_gi_button->is_pressed());
+ environment->set_tonemapper(environ_tonemap_button->is_pressed() ? Environment::TONE_MAPPER_FILMIC : Environment::TONE_MAPPER_LINEAR);
+ }
+}
+void Node3DEditor::_load_default_preview_settings() {
+ sun_environ_updating = true;
+
+ sun_rotation = Basis(Vector3(0, 1, 0), Math_PI * 3.0 / 4) * Basis(Vector3(1, 0, 0), -Math_PI / 4);
+
+ sun_direction->update();
+ environ_sky_color->set_pick_color(Color::hex(0x91b2ceff));
+ environ_ground_color->set_pick_color(Color::hex(0x1f1f21ff));
+ environ_energy->set_value(1.0);
+ environ_glow_button->set_pressed(true);
+ environ_tonemap_button->set_pressed(true);
+ environ_ao_button->set_pressed(false);
+ environ_gi_button->set_pressed(false);
+ sun_max_distance->set_value(250);
+
+ sun_color->set_pick_color(Color(1, 1, 1));
+ sun_energy->set_value(1.0);
+
+ sun_environ_updating = false;
+}
+
+void Node3DEditor::_update_preview_environment() {
+ bool disable_light = directional_light_count > 0 || sun_button->is_pressed();
+
+ sun_button->set_disabled(directional_light_count > 0);
+
+ if (disable_light) {
+ if (preview_sun->get_parent()) {
+ preview_sun->get_parent()->remove_child(preview_sun);
+ sun_state->show();
+ sun_vb->hide();
+ }
+
+ if (directional_light_count > 0) {
+ sun_state->set_text(TTR("Scene contains\nDirectionalLight3D.\nPreview Disabled."));
+ } else {
+ sun_state->set_text(TTR("Preview Disabled."));
+ }
+
+ } else {
+ if (!preview_sun->get_parent()) {
+ add_child(preview_sun);
+ sun_state->hide();
+ sun_vb->show();
+ }
+ }
+
+ bool disable_env = world_env_count > 0 || environ_button->is_pressed();
+
+ environ_button->set_disabled(world_env_count > 0);
+
+ if (disable_env) {
+ if (preview_environment->get_parent()) {
+ preview_environment->get_parent()->remove_child(preview_environment);
+ environ_state->show();
+ environ_vb->hide();
+ }
+ if (world_env_count > 0) {
+ environ_state->set_text(TTR("Scene contains\nWorldEnvironment.\nPreview Disabled."));
+ } else {
+ environ_state->set_text(TTR("Preview Disabled."));
+ }
+
+ } else {
+ if (!preview_environment->get_parent()) {
+ add_child(preview_environment);
+ environ_state->hide();
+ environ_vb->show();
+ }
+ }
+}
+
+void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) {
+ Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ float x = -mm->get_relative().y * 0.02 * EDSCALE;
+ float y = mm->get_relative().x * 0.02 * EDSCALE;
+
+ Basis rot = Basis(Vector3(0, 1, 0), y) * Basis(Vector3(1, 0, 0), x);
+
+ sun_rotation = rot * sun_rotation;
+ sun_rotation.orthonormalize();
+ _preview_settings_changed();
+ }
+}
+
Node3DEditor::Node3DEditor(EditorNode *p_editor) {
gizmo.visible = true;
gizmo.scale = 1.0;
@@ -6488,6 +6752,32 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
_update_camera_override_button(false);
hbc_menu->add_child(memnew(VSeparator));
+ sun_button = memnew(Button);
+ sun_button->set_tooltip(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled."));
+ sun_button->set_toggle_mode(true);
+ sun_button->set_flat(true);
+ sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED);
+ sun_button->set_disabled(true);
+
+ hbc_menu->add_child(sun_button);
+
+ environ_button = memnew(Button);
+ environ_button->set_tooltip(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled."));
+ environ_button->set_toggle_mode(true);
+ environ_button->set_flat(true);
+ environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), varray(), CONNECT_DEFERRED);
+ environ_button->set_disabled(true);
+
+ hbc_menu->add_child(environ_button);
+
+ sun_environ_settings = memnew(Button);
+ sun_environ_settings->set_tooltip(TTR("Edit Sun and Environment settings."));
+ sun_environ_settings->set_flat(true);
+ sun_environ_settings->connect("pressed", callable_mp(this, &Node3DEditor::_sun_environ_settings_pressed));
+
+ hbc_menu->add_child(sun_environ_settings);
+
+ hbc_menu->add_child(memnew(VSeparator));
// Drag and drop support;
preview_node = memnew(Node3D);
@@ -6717,6 +7007,149 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
EDITOR_DEF("editors/3d/navigation/show_viewport_rotation_gizmo", true);
over_gizmo_handle = -1;
+ {
+ //sun popup
+
+ sun_environ_popup = memnew(PopupPanel);
+ add_child(sun_environ_popup);
+
+ HBoxContainer *sun_environ_hb = memnew(HBoxContainer);
+
+ sun_environ_popup->add_child(sun_environ_hb);
+
+ sun_vb = memnew(VBoxContainer);
+ sun_environ_hb->add_child(sun_vb);
+ sun_vb->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
+ sun_vb->hide();
+
+ sun_title = memnew(Label);
+ sun_vb->add_child(sun_title);
+ sun_title->set_text(TTR("Preview Sun"));
+ sun_title->set_align(Label::ALIGN_CENTER);
+
+ sun_state = memnew(Label);
+ sun_environ_hb->add_child(sun_state);
+ sun_state->show();
+
+ CenterContainer *sun_direction_center = memnew(CenterContainer);
+ sun_direction = memnew(Control);
+ sun_direction->set_custom_minimum_size(Size2i(128, 128) * EDSCALE);
+ sun_direction_center->add_child(sun_direction);
+ sun_vb->add_margin_child(TTR("Sun Direction"), sun_direction_center);
+ sun_direction->connect("gui_input", callable_mp(this, &Node3DEditor::_sun_direction_input));
+ sun_direction->connect("draw", callable_mp(this, &Node3DEditor::_sun_direction_draw));
+ sun_direction->set_default_cursor_shape(CURSOR_MOVE);
+
+ String sun_dir_shader_code = "shader_type canvas_item; uniform vec3 sun_direction; uniform vec3 sun_color; void fragment() { vec3 n; n.xy = UV * 2.0 - 1.0; n.z = sqrt(max(0.0, 1.0 - dot(n.xy, n.xy))); COLOR.rgb = dot(n,sun_direction) * sun_color; COLOR.a = 1.0 - smoothstep(0.99,1.0,length(n.xy)); }";
+ sun_direction_shader.instance();
+ sun_direction_shader->set_code(sun_dir_shader_code);
+ sun_direction_material.instance();
+ sun_direction_material->set_shader(sun_direction_shader);
+ sun_direction_material->set_shader_param("sun_direction", Vector3(0, 0, 1));
+ sun_direction_material->set_shader_param("sun_color", Vector3(1, 1, 1));
+ sun_direction->set_material(sun_direction_material);
+
+ sun_color = memnew(ColorPickerButton);
+ sun_color->set_edit_alpha(false);
+ sun_vb->add_margin_child(TTR("Sun Color"), sun_color);
+ sun_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+
+ sun_energy = memnew(EditorSpinSlider);
+ sun_vb->add_margin_child(TTR("Sun Energy"), sun_energy);
+ sun_energy->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ sun_energy->set_max(64.0);
+
+ sun_max_distance = memnew(EditorSpinSlider);
+ sun_vb->add_margin_child(TTR("Shadow Max Distance"), sun_max_distance);
+ sun_max_distance->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ sun_max_distance->set_min(1);
+ sun_max_distance->set_max(4096);
+
+ sun_add_to_scene = memnew(Button);
+ sun_add_to_scene->set_text(TTR("Add Sun to Scene"));
+ sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene));
+ sun_vb->add_spacer();
+ sun_vb->add_child(sun_add_to_scene);
+
+ VSeparator *sc = memnew(VSeparator);
+ sc->set_custom_minimum_size(Size2(50 * EDSCALE, 0));
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
+ sun_environ_hb->add_child(sc);
+
+ environ_vb = memnew(VBoxContainer);
+ sun_environ_hb->add_child(environ_vb);
+ environ_vb->hide();
+
+ environ_vb->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
+
+ environ_state = memnew(Label);
+ sun_environ_hb->add_child(environ_state);
+ environ_state->show();
+
+ environ_title = memnew(Label);
+ environ_vb->add_child(environ_title);
+ environ_title->set_text(TTR("Preview Environment"));
+ environ_title->set_align(Label::ALIGN_CENTER);
+
+ environ_sky_color = memnew(ColorPickerButton);
+ environ_sky_color->set_edit_alpha(false);
+ environ_sky_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_vb->add_margin_child(TTR("Sky Color"), environ_sky_color);
+ environ_ground_color = memnew(ColorPickerButton);
+ environ_ground_color->connect("color_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_ground_color->set_edit_alpha(false);
+ environ_vb->add_margin_child(TTR("Ground Color"), environ_ground_color);
+ environ_energy = memnew(EditorSpinSlider);
+ environ_energy->connect("value_changed", callable_mp(this, &Node3DEditor::_preview_settings_changed).unbind(1));
+ environ_energy->set_max(8.0);
+ environ_vb->add_margin_child(TTR("Sky Energy"), environ_energy);
+ HBoxContainer *fx_vb = memnew(HBoxContainer);
+ fx_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ environ_ao_button = memnew(Button);
+ environ_ao_button->set_text(TTR("AO"));
+ environ_ao_button->set_toggle_mode(true);
+ environ_ao_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_ao_button);
+ environ_glow_button = memnew(Button);
+ environ_glow_button->set_text(TTR("Glow"));
+ environ_glow_button->set_toggle_mode(true);
+ environ_glow_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_glow_button);
+ environ_tonemap_button = memnew(Button);
+ environ_tonemap_button->set_text(TTR("Tonemap"));
+ environ_tonemap_button->set_toggle_mode(true);
+ environ_tonemap_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_tonemap_button);
+ environ_gi_button = memnew(Button);
+ environ_gi_button->set_text(TTR("GI"));
+ environ_gi_button->set_toggle_mode(true);
+ environ_gi_button->connect("pressed", callable_mp(this, &Node3DEditor::_preview_settings_changed), varray(), CONNECT_DEFERRED);
+ fx_vb->add_child(environ_gi_button);
+ environ_vb->add_margin_child(TTR("Post Process"), fx_vb);
+
+ environ_add_to_scene = memnew(Button);
+ environ_add_to_scene->set_text(TTR("Add Environment to Scene"));
+ environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene));
+ environ_vb->add_spacer();
+ environ_vb->add_child(environ_add_to_scene);
+
+ preview_sun = memnew(DirectionalLight3D);
+ preview_sun->set_shadow(true);
+ preview_sun->set_shadow_mode(DirectionalLight3D::SHADOW_PARALLEL_4_SPLITS);
+ preview_environment = memnew(WorldEnvironment);
+ environment.instance();
+ preview_environment->set_environment(environment);
+ Ref<Sky> sky;
+ sky.instance();
+ sky_material.instance();
+ sky->set_material(sky_material);
+ environment->set_sky(sky);
+ environment->set_background(Environment::BG_SKY);
+
+ _load_default_preview_settings();
+ _preview_settings_changed();
+ }
}
Node3DEditor::~Node3DEditor() {
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index bf478f850e..cf4aa33257 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -37,7 +37,10 @@
#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/3d/world_environment.h"
#include "scene/gui/panel_container.h"
+#include "scene/resources/environment.h"
+#include "scene/resources/sky_material.h"
class Camera3D;
class Node3DEditor;
@@ -732,6 +735,7 @@ private:
static Node3DEditor *singleton;
+ void _node_added(Node *p_node);
void _node_removed(Node *p_node);
Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_priority;
Vector<Ref<EditorNode3DGizmoPlugin>> gizmo_plugins_by_name;
@@ -744,6 +748,61 @@ private:
void _refresh_menu_icons();
+ // Preview Sun and Environment
+
+ uint32_t world_env_count = 0;
+ uint32_t directional_light_count = 0;
+
+ Button *sun_button;
+ Label *sun_state;
+ Label *sun_title;
+ VBoxContainer *sun_vb;
+ Popup *sun_environ_popup;
+ Control *sun_direction;
+ ColorPickerButton *sun_color;
+ EditorSpinSlider *sun_energy;
+ EditorSpinSlider *sun_max_distance;
+ Button *sun_add_to_scene;
+
+ void _sun_direction_draw();
+ void _sun_direction_input(const Ref<InputEvent> &p_event);
+
+ Basis sun_rotation;
+
+ Ref<Shader> sun_direction_shader;
+ Ref<ShaderMaterial> sun_direction_material;
+
+ Button *environ_button;
+ Label *environ_state;
+ Label *environ_title;
+ VBoxContainer *environ_vb;
+ ColorPickerButton *environ_sky_color;
+ ColorPickerButton *environ_ground_color;
+ EditorSpinSlider *environ_energy;
+ Button *environ_ao_button;
+ Button *environ_glow_button;
+ Button *environ_tonemap_button;
+ Button *environ_gi_button;
+ Button *environ_add_to_scene;
+
+ Button *sun_environ_settings;
+
+ DirectionalLight3D *preview_sun;
+ WorldEnvironment *preview_environment;
+ Ref<Environment> environment;
+ Ref<ProceduralSkyMaterial> sky_material;
+
+ bool sun_environ_updating = false;
+
+ void _load_default_preview_settings();
+ void _update_preview_environment();
+
+ void _preview_settings_changed();
+ void _sun_environ_settings_pressed();
+
+ void _add_sun_to_scene();
+ void _add_environment_to_scene();
+
protected:
void _notification(int p_what);
//void _gui_input(InputEvent p_event);
diff --git a/main/main.cpp b/main/main.cpp
index 41f97b2e3b..71dd3cf1ad 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -395,6 +395,8 @@ Error Main::test_setup() {
GLOBAL_DEF("debug/settings/crash_handler/message",
String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
+ translation_server = memnew(TranslationServer);
+
// From `Main::setup2()`.
preregister_module_types();
preregister_server_types();
@@ -402,6 +404,16 @@ Error Main::test_setup() {
register_core_singletons();
register_server_types();
+
+ translation_server->setup(); //register translations, load them, etc.
+ if (locale != "") {
+ translation_server->set_locale(locale);
+ }
+ translation_server->load_translations();
+ ResourceLoader::load_translation_remaps(); //load remaps for resources
+
+ ResourceLoader::load_path_remaps();
+
register_scene_types();
#ifdef TOOLS_ENABLED
@@ -441,6 +453,9 @@ void Main::test_cleanup() {
OS::get_singleton()->finalize();
+ if (translation_server) {
+ memdelete(translation_server);
+ }
if (globals) {
memdelete(globals);
}
@@ -2561,8 +2576,10 @@ void Main::force_redraw() {
* so that the engine closes cleanly without leaking memory or crashing.
* The order matters as some of those steps are linked with each other.
*/
-void Main::cleanup() {
- ERR_FAIL_COND(!_start_success);
+void Main::cleanup(bool p_force) {
+ if (!p_force) {
+ ERR_FAIL_COND(!_start_success);
+ }
EngineDebugger::deinitialize();
diff --git a/main/main.h b/main/main.h
index 9e606c188d..f4fff6b97e 100644
--- a/main/main.h
+++ b/main/main.h
@@ -59,7 +59,7 @@ public:
static bool is_iterating();
- static void cleanup();
+ static void cleanup(bool p_force = false);
};
// Test main override is for the testing behaviour.
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 167e9d75a1..a569dfc207 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -39,6 +39,7 @@
#include "core/os/file_access.h"
#include "core/os/os.h"
#include "core/string/ucaps.h"
+#include "main/main.h"
#include "../glue/cs_glue_version.gen.h"
#include "../godotsharp_defs.h"
@@ -3649,6 +3650,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
if (!bindings_generator.initialized) {
ERR_PRINT("Failed to initialize the bindings generator");
+ Main::cleanup(true);
::exit(0);
}
@@ -3675,6 +3677,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
}
// Exit once done
+ Main::cleanup(true);
::exit(0);
}
}
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 1c3fa990fe..5be7e81e7a 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -93,6 +93,7 @@ def configure(env):
env["CC"] = "clang"
env["CXX"] = "clang++"
env.extra_suffix = ".llvm" + env.extra_suffix
+ env.Append(LIBS=["atomic"])
if env["use_coverage"]:
env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index cf1c319acc..214ffd6bd5 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -35,51 +35,69 @@
void WorldEnvironment::_notification(int p_what) {
if (p_what == Node3D::NOTIFICATION_ENTER_WORLD || p_what == Node3D::NOTIFICATION_ENTER_TREE) {
if (environment.is_valid()) {
- if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
- WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_environment(environment);
add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_environment();
}
if (camera_effects.is_valid()) {
- if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) {
- WARN_PRINT("World already has a camera effects (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_camera_effects(camera_effects);
add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_camera_effects();
}
} else if (p_what == Node3D::NOTIFICATION_EXIT_WORLD || p_what == Node3D::NOTIFICATION_EXIT_TREE) {
- if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
- get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
+ if (environment.is_valid()) {
remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
+ _update_current_environment();
}
- if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
- get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ 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();
}
}
}
-void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
- if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
+void WorldEnvironment::_update_current_environment() {
+ WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())));
+
+ if (first) {
+ get_viewport()->find_world_3d()->set_environment(first->environment);
+ } else {
get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
+ }
+ get_tree()->call_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warning");
+}
+
+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())));
+ if (first) {
+ get_viewport()->find_world_3d()->set_camera_effects(first->camera_effects);
+ } else {
+ get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
+ }
+
+ get_tree()->call_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warning");
+}
+
+void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) {
+ if (environment == p_environment) {
+ return;
+ }
+ if (is_inside_tree() && environment.is_valid()) {
remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
- //clean up
}
environment = p_environment;
+
if (is_inside_tree() && environment.is_valid()) {
- if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
- WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_environment(environment);
add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
- update_configuration_warning();
+ if (is_inside_tree()) {
+ _update_current_environment();
+ } else {
+ update_configuration_warning();
+ }
}
Ref<Environment> WorldEnvironment::get_environment() const {
@@ -87,22 +105,24 @@ Ref<Environment> WorldEnvironment::get_environment() const {
}
void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) {
+ if (camera_effects == p_camera_effects) {
+ return;
+ }
+
if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) {
- get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>());
remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
- //clean up
}
camera_effects = p_camera_effects;
if (is_inside_tree() && camera_effects.is_valid()) {
- if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) {
- WARN_PRINT("World already has an camera_effects (Another WorldEnvironment?), overriding.");
- }
- get_viewport()->find_world_3d()->set_camera_effects(camera_effects);
add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
}
- update_configuration_warning();
+ if (is_inside_tree()) {
+ _update_current_camera_effects();
+ } else {
+ update_configuration_warning();
+ }
}
Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
@@ -123,14 +143,18 @@ String WorldEnvironment::get_configuration_warning() const {
return warning;
}
- List<Node *> nodes;
- get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), &nodes);
+ if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() != environment) {
+ if (!warning.is_empty()) {
+ warning += "\n\n";
+ }
+ warning += TTR("Only the first Environment has an effect in a scene (or set of instantiated scenes).");
+ }
- if (nodes.size() > 1) {
+ if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() != camera_effects) {
if (!warning.is_empty()) {
warning += "\n\n";
}
- warning += TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes).");
+ warning += TTR("Only the first CameraEffects has an effect in a scene (or set of instantiated scenes).");
}
return warning;
diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h
index 3dfba20bf0..e3f28d6d6b 100644
--- a/scene/3d/world_environment.h
+++ b/scene/3d/world_environment.h
@@ -41,6 +41,9 @@ class WorldEnvironment : public Node {
Ref<Environment> environment;
Ref<CameraEffects> camera_effects;
+ void _update_current_environment();
+ void _update_current_camera_effects();
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 37bb17b47d..b0bcde8865 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -56,6 +56,11 @@ Size2 Button::get_minimum_size() const {
}
}
+ Ref<Font> font = get_theme_font("font");
+ float font_height = font->get_height(get_theme_font_size("font_size"));
+
+ minsize.height = MAX(font_height, minsize.height);
+
return get_theme_stylebox("normal")->get_minimum_size() + minsize;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index ad06739da9..17fe001b5d 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -4187,6 +4187,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited"), &Tree::get_edited);
ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column);
+ ClassDB::bind_method(D_METHOD("edit_selected"), &Tree::edit_selected);
ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect);
ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::_get_item_rect, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 9f32c65f7b..b10e23ac07 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -956,6 +956,21 @@ bool SceneTree::has_group(const StringName &p_identifier) const {
return group_map.has(p_identifier);
}
+Node *SceneTree::get_first_node_in_group(const StringName &p_group) {
+ Map<StringName, Group>::Element *E = group_map.find(p_group);
+ if (!E) {
+ return nullptr; //no group
+ }
+
+ _update_group_order(E->get()); //update order just in case
+
+ if (E->get().nodes.size() == 0) {
+ return nullptr;
+ }
+
+ return E->get().nodes[0];
+}
+
void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E) {
@@ -1216,6 +1231,7 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group);
ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group);
+ ClassDB::bind_method(D_METHOD("get_first_node_in_group", "group"), &SceneTree::get_first_node_in_group);
ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene);
ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene);
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index f39780831f..c2280c747b 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -302,6 +302,7 @@ public:
void queue_delete(Object *p_object);
void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list);
+ Node *get_first_node_in_group(const StringName &p_group);
bool has_group(const StringName &p_identifier) const;
//void change_scene(const String& p_path);