From 8f5b4cd7fe206d096fca914ea5891aefe12ced3a Mon Sep 17 00:00:00 2001 From: hakro Date: Thu, 28 Nov 2024 22:13:29 +0100 Subject: [PATCH 01/71] Style skeleton button on import screen --- editor/icons/SkeletonPreview.svg | 1 + editor/import/3d/scene_import_settings.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 editor/icons/SkeletonPreview.svg diff --git a/editor/icons/SkeletonPreview.svg b/editor/icons/SkeletonPreview.svg new file mode 100644 index 00000000000..2c4384ab042 --- /dev/null +++ b/editor/icons/SkeletonPreview.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index 945c1811d77..99cee832251 100644 --- a/editor/import/3d/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -1329,7 +1329,7 @@ void SceneImportSettingsDialog::_notification(int p_what) { light_2_switch->set_button_icon(theme_cache.light_2_icon); light_rotate_switch->set_button_icon(theme_cache.rotate_icon); - animation_toggle_skeleton_visibility->set_button_icon(get_editor_theme_icon(SNAME("Skeleton3D"))); + animation_toggle_skeleton_visibility->set_button_icon(get_editor_theme_icon(SNAME("SkeletonPreview"))); } break; case NOTIFICATION_PROCESS: { @@ -1725,7 +1725,7 @@ SceneImportSettingsDialog::SceneImportSettingsDialog() { animation_toggle_skeleton_visibility = memnew(Button); animation_hbox->add_child(animation_toggle_skeleton_visibility); animation_toggle_skeleton_visibility->set_toggle_mode(true); - animation_toggle_skeleton_visibility->set_flat(true); + animation_toggle_skeleton_visibility->set_theme_type_variation("FlatButton"); animation_toggle_skeleton_visibility->set_focus_mode(Control::FOCUS_NONE); animation_toggle_skeleton_visibility->set_tooltip_text(TTR("Toggle Animation Skeleton Visibility")); From f2475326a42bbdf20dab614db9ac32bc105c8a84 Mon Sep 17 00:00:00 2001 From: Bernat Arlandis Date: Thu, 23 Jan 2025 10:02:17 +0100 Subject: [PATCH 02/71] Fix playing of video Theora files --- modules/theora/video_stream_theora.cpp | 248 +++++++------------------ modules/theora/video_stream_theora.h | 44 ++--- scene/gui/video_stream_player.cpp | 1 + servers/audio/audio_rb_resampler.h | 2 +- 4 files changed, 81 insertions(+), 214 deletions(-) diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 8c7d639a6b9..a2a74be7cda 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -39,31 +39,9 @@ int VideoStreamPlaybackTheora::buffer_data() { char *buffer = ogg_sync_buffer(&oy, 4096); -#ifdef THEORA_USE_THREAD_STREAMING - - int read; - - do { - thread_sem->post(); - read = MIN(ring_buffer.data_left(), 4096); - if (read) { - ring_buffer.read((uint8_t *)buffer, read); - ogg_sync_wrote(&oy, read); - } else { - OS::get_singleton()->delay_usec(100); - } - - } while (read == 0); - - return read; - -#else - uint64_t bytes = file->get_buffer((uint8_t *)buffer, 4096); ogg_sync_wrote(&oy, bytes); return (bytes); - -#endif } int VideoStreamPlaybackTheora::queue_page(ogg_page *page) { @@ -82,10 +60,7 @@ int VideoStreamPlaybackTheora::queue_page(ogg_page *page) { return 0; } -void VideoStreamPlaybackTheora::video_write() { - th_ycbcr_buffer yuv; - th_decode_ycbcr_out(td, yuv); - +void VideoStreamPlaybackTheora::video_write(th_ycbcr_buffer yuv) { int pitch = 4; frame_data.resize(size.x * size.y * pitch); { @@ -106,10 +81,11 @@ void VideoStreamPlaybackTheora::video_write() { } Ref img = memnew(Image(size.x, size.y, false, Image::FORMAT_RGBA8, frame_data)); //zero copy image creation + if (region.size.x != size.x || region.size.y != size.y) { + img = img->get_region(region); + } texture->update(img); //zero copy send to rendering server - - frames_pending = 1; } void VideoStreamPlaybackTheora::clear() { @@ -136,20 +112,15 @@ void VideoStreamPlaybackTheora::clear() { } ogg_sync_clear(&oy); -#ifdef THEORA_USE_THREAD_STREAMING - thread_exit = true; - thread_sem->post(); //just in case - thread.wait_to_finish(); - ring_buffer.clear(); -#endif - theora_p = 0; vorbis_p = 0; - videobuf_ready = 0; - frames_pending = 0; - videobuf_time = 0; + next_frame_time = 0; + current_frame_time = 0; theora_eos = false; vorbis_eos = false; + video_ready = false; + video_done = false; + audio_done = false; file.unref(); playing = false; @@ -164,17 +135,6 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { file = FileAccess::open(p_file, FileAccess::READ); ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_file + "'."); -#ifdef THEORA_USE_THREAD_STREAMING - thread_exit = false; - thread_eof = false; - //pre-fill buffer - int to_read = ring_buffer.space_left(); - uint64_t read = file->get_buffer(read_buffer.ptr(), to_read); - ring_buffer.write(read_buffer.ptr(), read); - - thread.start(_streaming_thread, this); -#endif - ogg_sync_init(&oy); /* init supporting Vorbis structures needed in header parsing */ @@ -327,16 +287,17 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { th_decode_ctl(td, TH_DECCTL_SET_PPLEVEL, &pp_level, sizeof(pp_level)); pp_inc = 0; - int w; - int h; - w = ((ti.pic_x + ti.frame_width + 1) & ~1) - (ti.pic_x & ~1); - h = ((ti.pic_y + ti.frame_height + 1) & ~1) - (ti.pic_y & ~1); - size.x = w; - size.y = h; + size.x = ti.frame_width; + size.y = ti.frame_height; + region.position.x = ti.pic_x; + region.position.y = ti.pic_y; + region.size.x = ti.pic_width; + region.size.y = ti.pic_height; - Ref img = Image::create_empty(w, h, false, Image::FORMAT_RGBA8); + Ref img = Image::create_empty(region.size.x, region.size.y, false, Image::FORMAT_RGBA8); texture->set_image(img); + frame_duration = (double)ti.fps_denominator / ti.fps_numerator; } else { /* tear down the partial theora setup */ th_info_clear(&ti); @@ -358,7 +319,8 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { playing = false; buffering = true; time = 0; - audio_frames_wrote = 0; + video_done = !theora_p; + audio_done = !vorbis_p; } double VideoStreamPlaybackTheora::get_time() const { @@ -378,68 +340,41 @@ void VideoStreamPlaybackTheora::update(double p_delta) { } if (!playing || paused) { - //printf("not playing\n"); return; } -#ifdef THEORA_USE_THREAD_STREAMING - thread_sem->post(); -#endif - time += p_delta; - if (videobuf_time > get_time()) { - return; //no new frames need to be produced - } - - bool frame_done = false; - bool audio_done = !vorbis_p; - - while (!frame_done || (!audio_done && !vorbis_eos)) { - //a frame needs to be produced + double comp_time = get_time(); + bool audio_ready = false; + // Read data until we fill the audio buffer and get a new video frame. + while ((!audio_ready && !audio_done) || (!video_ready && !video_done)) { ogg_packet op; - bool no_theora = false; - bool buffer_full = false; - while (vorbis_p && !audio_done && !buffer_full) { - int ret; + while (!audio_ready && !audio_done) { float **pcm; - - /* if there's pending, decoded audio, grab it */ - ret = vorbis_synthesis_pcmout(&vd, &pcm); + int ret = vorbis_synthesis_pcmout(&vd, &pcm); if (ret > 0) { const int AUXBUF_LEN = 4096; int to_read = ret; float aux_buffer[AUXBUF_LEN]; - while (to_read) { int m = MIN(AUXBUF_LEN / vi.channels, to_read); - int count = 0; - for (int j = 0; j < m; j++) { for (int i = 0; i < vi.channels; i++) { aux_buffer[count++] = pcm[i][j]; } } - - if (mix_callback) { - int mixed = mix_callback(mix_udata, aux_buffer, m); - to_read -= mixed; - if (mixed != m) { //could mix no more - buffer_full = true; - break; - } - } else { - to_read -= m; //just pretend we sent the audio + int mixed = mix_callback(mix_udata, aux_buffer, m); + to_read -= mixed; + if (mixed != m) { //could mix no more + audio_ready = true; + break; } } - vorbis_synthesis_read(&vd, ret - to_read); - - audio_frames_wrote += ret - to_read; - } else { /* no pending audio; is there a pending packet to decode? */ if (ogg_stream_packetout(&vo, &op) > 0) { @@ -447,19 +382,13 @@ void VideoStreamPlaybackTheora::update(double p_delta) { vorbis_synthesis_blockin(&vd, &vb); } } else { /* we need more data; break out to suck in another page */ + audio_done = vorbis_eos; break; } } - - audio_done = videobuf_time < (audio_frames_wrote / float(vi.rate)); - - if (buffer_full) { - break; - } } - while (theora_p && !frame_done) { - /* theora is one in, one out... */ + while (!video_ready && !video_done) { if (ogg_stream_packetout(&to, &op) > 0) { /*HACK: This should be set after a seek or a gap, but we might not have a granulepos for the first packet (we only have them for the last @@ -472,62 +401,37 @@ void VideoStreamPlaybackTheora::update(double p_delta) { sizeof(op.granulepos)); } ogg_int64_t videobuf_granulepos; - if (th_decode_packetin(td, &op, &videobuf_granulepos) == 0) { - videobuf_time = th_granule_time(td, videobuf_granulepos); - - //printf("frame time %f, play time %f, ready %i\n", (float)videobuf_time, get_time(), videobuf_ready); - - /* is it already too old to be useful? This is only actually - useful cosmetically after a SIGSTOP. Note that we have to - decode the frame even if we don't show it (for now) due to - keyframing. Soon enough libtheora will be able to deal - with non-keyframe seeks. */ - - if (videobuf_time >= get_time()) { - frame_done = true; + int ret = th_decode_packetin(td, &op, &videobuf_granulepos); + if (ret == 0 || ret == TH_DUPFRAME) { + next_frame_time = th_granule_time(td, videobuf_granulepos); + if (next_frame_time > comp_time) { + dup_frame = (ret == TH_DUPFRAME); + video_ready = true; } else { /*If we are too slow, reduce the pp level.*/ pp_inc = pp_level > 0 ? -1 : 0; } } - - } else { - no_theora = true; + } else { /* we need more data; break out to suck in another page */ + video_done = theora_eos; break; } } -#ifdef THEORA_USE_THREAD_STREAMING - if (file.is_valid() && thread_eof && no_theora && theora_eos && ring_buffer.data_left() == 0) { -#else - if (file.is_valid() && /*!videobuf_ready && */ no_theora && theora_eos) { -#endif - //printf("video done, stopping\n"); - stop(); - return; - } - - if (!frame_done || !audio_done) { - //what's the point of waiting for audio to grab a page? - - buffer_data(); - while (ogg_sync_pageout(&oy, &og) > 0) { - queue_page(&og); + if (!video_ready || !audio_ready) { + int ret = buffer_data(); + if (ret > 0) { + while (ogg_sync_pageout(&oy, &og) > 0) { + queue_page(&og); + } + } else { + vorbis_eos = true; + theora_eos = true; + break; } } - /* If playback has begun, top audio buffer off immediately. */ - //if(stateflag) audio_write_nonblocking(); - - /* are we at or past time for this video frame? */ - if (videobuf_ready && videobuf_time <= get_time()) { - //video_write(); - //videobuf_ready=0; - } else { - //printf("frame at %f not ready (time %f), ready %i\n", (float)videobuf_time, get_time(), videobuf_ready); - } - - double tdiff = videobuf_time - get_time(); + double tdiff = next_frame_time - comp_time; /*If we have lots of extra time, increase the post-processing level.*/ if (tdiff > ti.fps_denominator * 0.25 / ti.fps_numerator) { pp_inc = pp_level < pp_level_max ? 1 : 0; @@ -536,7 +440,22 @@ void VideoStreamPlaybackTheora::update(double p_delta) { } } - video_write(); + if (!video_ready && video_done && audio_done) { + stop(); + return; + } + + // Wait for the last frame to end before rendering the next one. + if (video_ready && comp_time >= current_frame_time) { + if (!dup_frame) { + th_ycbcr_buffer yuv; + th_decode_ycbcr_out(td, yuv); + video_write(yuv); + } + dup_frame = false; + video_ready = false; + current_frame_time = next_frame_time; + } } void VideoStreamPlaybackTheora::play() { @@ -596,44 +515,11 @@ int VideoStreamPlaybackTheora::get_mix_rate() const { return vi.rate; } -#ifdef THEORA_USE_THREAD_STREAMING - -void VideoStreamPlaybackTheora::_streaming_thread(void *ud) { - VideoStreamPlaybackTheora *vs = static_cast(ud); - - while (!vs->thread_exit) { - //just fill back the buffer - if (!vs->thread_eof) { - int to_read = vs->ring_buffer.space_left(); - if (to_read > 0) { - uint64_t read = vs->file->get_buffer(vs->read_buffer.ptr(), to_read); - vs->ring_buffer.write(vs->read_buffer.ptr(), read); - vs->thread_eof = vs->file->eof_reached(); - } - } - - vs->thread_sem->wait(); - } -} - -#endif - VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { texture.instantiate(); - -#ifdef THEORA_USE_THREAD_STREAMING - int rb_power = nearest_shift(RB_SIZE_KB * 1024); - ring_buffer.resize(rb_power); - read_buffer.resize(RB_SIZE_KB * 1024); - thread_sem = Semaphore::create(); - -#endif } VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() { -#ifdef THEORA_USE_THREAD_STREAMING - memdelete(thread_sem); -#endif clear(); } diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index 5e6630f1e2f..45b6746d40b 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -41,27 +41,20 @@ class ImageTexture; -//#define THEORA_USE_THREAD_STREAMING - class VideoStreamPlaybackTheora : public VideoStreamPlayback { GDCLASS(VideoStreamPlaybackTheora, VideoStreamPlayback); - enum { - MAX_FRAMES = 4, - }; - - //Image frames[MAX_FRAMES]; Image::Format format = Image::Format::FORMAT_L8; Vector frame_data; int frames_pending = 0; Ref file; String file_name; - int audio_frames_wrote = 0; Point2i size; + Rect2i region; int buffer_data(); int queue_page(ogg_page *page); - void video_write(); + void video_write(th_ycbcr_buffer yuv); double get_time() const; bool theora_eos = false; @@ -79,43 +72,30 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback { vorbis_block vb; vorbis_comment vc; th_pixel_fmt px_fmt; - double videobuf_time = 0; - int pp_inc = 0; + double frame_duration; int theora_p = 0; int vorbis_p = 0; int pp_level_max = 0; int pp_level = 0; - int videobuf_ready = 0; + int pp_inc = 0; bool playing = false; bool buffering = false; + bool paused = false; + + bool dup_frame = false; + bool video_ready = false; + bool video_done = false; + bool audio_done = false; - double last_update_time = 0; double time = 0; + double next_frame_time = 0; + double current_frame_time = 0; double delay_compensation = 0; Ref texture; - bool paused = false; - -#ifdef THEORA_USE_THREAD_STREAMING - - enum { - RB_SIZE_KB = 1024 - }; - - RingBuffer ring_buffer; - Vector read_buffer; - bool thread_eof = false; - Semaphore *thread_sem = nullptr; - Thread thread; - SafeFlag thread_exit; - - static void _streaming_thread(void *ud); - -#endif - int audio_track = 0; protected: diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 1a4bace9a50..fa965179a4d 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -158,6 +158,7 @@ void VideoStreamPlayer::_notification(int p_notification) { playback->update(delta); // playback->is_playing() returns false in the last video frame if (!playback->is_playing()) { + resampler.flush(); if (loop) { play(); return; diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h index 18ed1bb738e..d7e373178fa 100644 --- a/servers/audio/audio_rb_resampler.h +++ b/servers/audio/audio_rb_resampler.h @@ -86,7 +86,7 @@ public: } else if (w < r) { space = r - w - 1; } else { - space = (rb_len - r) + w - 1; + space = rb_len - w + r - 1; } return space; From a9e06b8f64a8c946ebddd05d15cd9c713874fc9d Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Mon, 27 Jan 2025 18:30:42 -0500 Subject: [PATCH 03/71] Fix Modal Dialog with Embedded Game --- editor/plugins/embedded_process.cpp | 91 +++++++++++++++------ editor/plugins/embedded_process.h | 3 +- platform/windows/display_server_windows.cpp | 3 +- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/editor/plugins/embedded_process.cpp b/editor/plugins/embedded_process.cpp index 1638c437125..a348607a6e9 100644 --- a/editor/plugins/embedded_process.cpp +++ b/editor/plugins/embedded_process.cpp @@ -67,20 +67,10 @@ void EmbeddedProcess::_notification(int p_what) { } break; case NOTIFICATION_APPLICATION_FOCUS_IN: { application_has_focus = true; - if (embedded_process_was_focused) { - embedded_process_was_focused = false; - // Refocus the embedded process if it was focused when the application lost focus, - // but do not refocus if the embedded process is currently focused (indicating it just lost focus) - // or if the current window is a different popup or secondary window. - if (embedding_completed && current_process_id != focused_process_id && window && window->has_focus()) { - grab_focus(); - queue_update_embedded_process(); - } - } + last_application_focus_time = OS::get_singleton()->get_ticks_msec(); } break; case NOTIFICATION_APPLICATION_FOCUS_OUT: { application_has_focus = false; - embedded_process_was_focused = embedding_completed && current_process_id == focused_process_id; } break; } } @@ -286,14 +276,27 @@ void EmbeddedProcess::_check_mouse_over() { // This method checks if the mouse is over the embedded process while the current application is focused. // The goal is to give focus to the embedded process as soon as the mouse hovers over it, // allowing the user to interact with it immediately without needing to click first. - if (!is_visible_in_tree() || !embedding_completed || !application_has_focus || !window || !window->has_focus() || Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT) || Input::get_singleton()->is_mouse_button_pressed(MouseButton::RIGHT)) { + if (!embedding_completed || !application_has_focus || !window || has_focus() || !is_visible_in_tree() || !window->has_focus() || Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT) || Input::get_singleton()->is_mouse_button_pressed(MouseButton::RIGHT)) { return; } - bool focused = has_focus(); + // Before checking whether the mouse is truly inside the embedded process, ensure + // the editor has enough time to re-render. When a breakpoint is hit in the script editor, + // `_check_mouse_over` may be triggered before the editor hides the game workspace. + // This prevents the embedded process from regaining focus immediately after the editor has taken it. + if (OS::get_singleton()->get_ticks_msec() - last_application_focus_time < 500) { + return; + } + + // Input::is_mouse_button_pressed is not sufficient to detect the mouse button state + // while the floating game window is being resized. + BitField mouse_button_mask = DisplayServer::get_singleton()->mouse_get_button_state(); + if (!mouse_button_mask.is_empty()) { + return; + } // Not stealing focus from a textfield. - if (!focused && get_viewport()->gui_get_focus_owner() && get_viewport()->gui_get_focus_owner()->is_text_field()) { + if (get_viewport()->gui_get_focus_owner() && get_viewport()->gui_get_focus_owner()->is_text_field()) { return; } @@ -309,14 +312,17 @@ void EmbeddedProcess::_check_mouse_over() { return; } - // When we already have the focus and the user moves the mouse over the embedded process, - // we just need to refocus the process. - if (focused) { - queue_update_embedded_process(); - } else { - grab_focus(); - queue_redraw(); + // When there's a modal window, we don't want to grab the focus to prevent + // the game window to go in front of the modal window. + if (_get_current_modal_window()) { + return; } + + // Force "regrabbing" the game window focus. + last_updated_embedded_process_focused = false; + + grab_focus(); + queue_redraw(); } void EmbeddedProcess::_check_focused_process_id() { @@ -325,17 +331,48 @@ void EmbeddedProcess::_check_focused_process_id() { focused_process_id = process_id; if (focused_process_id == current_process_id) { // The embedded process got the focus. - emit_signal(SNAME("embedded_process_focused")); - if (has_focus()) { - // Redraw to updated the focus style. - queue_redraw(); - } else { - grab_focus(); + + // Refocus the current model when focusing the embedded process. + Window *modal_window = _get_current_modal_window(); + if (!modal_window) { + emit_signal(SNAME("embedded_process_focused")); + if (has_focus()) { + // Redraw to updated the focus style. + queue_redraw(); + } else { + grab_focus(); + } } } else if (has_focus()) { release_focus(); } } + + // Ensure that the opened modal dialog is refocused when the focused process is the embedded process. + if (!application_has_focus && focused_process_id == current_process_id) { + Window *modal_window = _get_current_modal_window(); + if (modal_window) { + if (modal_window->get_mode() == Window::MODE_MINIMIZED) { + modal_window->set_mode(Window::MODE_WINDOWED); + } + callable_mp(modal_window, &Window::grab_focus).call_deferred(); + } + } +} + +Window *EmbeddedProcess::_get_current_modal_window() { + Vector wl = DisplayServer::get_singleton()->get_window_list(); + for (const DisplayServer::WindowID &window_id : wl) { + Window *w = Window::get_from_id(window_id); + if (!w) { + continue; + } + + if (w->is_exclusive()) { + return w; + } + } + return nullptr; } void EmbeddedProcess::_bind_methods() { diff --git a/editor/plugins/embedded_process.h b/editor/plugins/embedded_process.h index 3e800923a75..6f56f255e61 100644 --- a/editor/plugins/embedded_process.h +++ b/editor/plugins/embedded_process.h @@ -37,7 +37,7 @@ class EmbeddedProcess : public Control { GDCLASS(EmbeddedProcess, Control); bool application_has_focus = true; - bool embedded_process_was_focused = false; + uint64_t last_application_focus_time = 0; OS::ProcessID focused_process_id = 0; OS::ProcessID current_process_id = 0; bool embedding_grab_focus = false; @@ -68,6 +68,7 @@ class EmbeddedProcess : public Control { void _check_focused_process_id(); bool _is_embedded_process_updatable(); Rect2i _get_global_embedded_window_rect(); + Window *_get_current_modal_window(); protected: static void _bind_methods(); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index d0ddac4b7f9..1a407bdd4b2 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -2986,7 +2986,8 @@ Error DisplayServerWindows::embed_process(WindowID p_window, OS::ProcessID p_pid // (e.g., a screen to the left of the main screen). const Rect2i adjusted_rect = Rect2i(p_rect.position + _get_screens_origin(), p_rect.size); - SetWindowPos(ep->window_handle, nullptr, adjusted_rect.position.x, adjusted_rect.position.y, adjusted_rect.size.x, adjusted_rect.size.y, SWP_NOZORDER | SWP_NOACTIVATE | SWP_ASYNCWINDOWPOS); + // Use HWND_BOTTOM to prevent reordering of the embedded window over another popup. + SetWindowPos(ep->window_handle, HWND_BOTTOM, adjusted_rect.position.x, adjusted_rect.position.y, adjusted_rect.size.x, adjusted_rect.size.y, SWP_NOZORDER | SWP_NOACTIVATE | SWP_ASYNCWINDOWPOS); if (ep->is_visible != p_visible) { if (p_visible) { From 7444839299cd7679f74a15e6f811530e7e0df11a Mon Sep 17 00:00:00 2001 From: clayjohn Date: Thu, 30 Jan 2025 12:21:47 -0800 Subject: [PATCH 04/71] Reduce mobile pipeline compilations by tracking more feature usage globally and only compile what is needed --- scene/main/scene_tree.cpp | 8 ++-- .../render_forward_clustered.cpp | 1 + .../forward_mobile/render_forward_mobile.cpp | 38 ++++++++++++++++--- .../forward_mobile/render_forward_mobile.h | 5 +++ .../scene_shader_forward_mobile.h | 3 +- servers/rendering_server.cpp | 9 ++++- 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index abb6f8ec907..5b8eb4f5d80 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1883,16 +1883,16 @@ SceneTree::SceneTree() { root->set_as_audio_listener_2d(true); current_scene = nullptr; - const int msaa_mode_2d = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_2d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0); + const int msaa_mode_2d = GLOBAL_GET("rendering/anti_aliasing/quality/msaa_2d"); root->set_msaa_2d(Viewport::MSAA(msaa_mode_2d)); - const int msaa_mode_3d = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0); + const int msaa_mode_3d = GLOBAL_GET("rendering/anti_aliasing/quality/msaa_3d"); root->set_msaa_3d(Viewport::MSAA(msaa_mode_3d)); const bool transparent_background = GLOBAL_DEF("rendering/viewport/transparent_background", false); root->set_transparent_background(transparent_background); - const bool use_hdr_2d = GLOBAL_DEF_BASIC("rendering/viewport/hdr_2d", false); + const bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d"); root->set_use_hdr_2d(use_hdr_2d); const int ssaa_mode = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), 0); @@ -1936,7 +1936,7 @@ SceneTree::SceneTree() { int shadowmap_size = GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/atlas_size", PROPERTY_HINT_RANGE, "256,16384"), 4096); 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); + bool shadowmap_16_bits = GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/atlas_16_bits"); int atlas_q0 = GLOBAL_DEF(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"), 2); int atlas_q1 = GLOBAL_DEF(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"), 2); int atlas_q2 = GLOBAL_DEF(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"), 3); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index c14bba6ed80..7acaeb506b3 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -4940,6 +4940,7 @@ RenderForwardClustered::RenderForwardClustered() { } _update_shader_quality_settings(); + _update_global_pipeline_data_requirements_from_project(); resolve_effects = memnew(RendererRD::Resolve()); taa = memnew(RendererRD::TAA); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 1d438e591eb..9289c21a383 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -761,6 +761,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _update_vrs(rb); + if (rb->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) { + global_pipeline_data_required.use_vrs = true; + } + RENDER_TIMESTAMP("Setup 3D Scene"); /* TODO @@ -793,6 +797,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color bool merge_transparent_pass = true; // If true: we can do our transparent pass in the same pass as our opaque pass. bool using_subpass_post_process = true; // If true: we can do our post processing in a subpass RendererRD::MaterialStorage::Samplers samplers; + bool hdr_render_target = false; RS::ViewportMSAA msaa = rb->get_msaa_3d(); bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED; @@ -892,11 +897,20 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (using_subpass_post_process) { // We can do all in one go. framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_RENDER_AND_POST_PASS); + global_pipeline_data_required.use_subpass_post_pass = true; } else { // We separate things out. framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_RENDER_PASS); + global_pipeline_data_required.use_separate_post_pass = true; } samplers = rb->get_samplers(); + + hdr_render_target = RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target()); + if (hdr_render_target) { + global_pipeline_data_required.use_hdr_render_target = true; + } else { + global_pipeline_data_required.use_ldr_render_target = true; + } } else { ERR_FAIL(); //bug? } @@ -1107,7 +1121,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color WARN_PRINT_ONCE("Canvas background is not supported in multiview!"); } else { RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target()); - bool convert_to_linear = !RendererRD::TextureStorage::get_singleton()->render_target_is_using_hdr(rb->get_render_target()); + bool convert_to_linear = !hdr_render_target; copy_effects->copy_to_drawlist(draw_list, fb_format, texture, convert_to_linear); } @@ -2893,6 +2907,7 @@ static RD::FramebufferFormatID _get_color_framebuffer_format_for_pipeline(RD::Da attachment.samples = RD::TEXTURE_SAMPLES_1; attachment.format = RenderSceneBuffersRD::get_vrs_format(); attachment.usage_flags = RenderSceneBuffersRD::get_vrs_usage_bits(); + attachments.push_back(attachment); } if (multisampling) { @@ -3006,11 +3021,18 @@ void RenderForwardMobile::_mesh_compile_pipelines_for_surface(const SurfacePipel const bool multiview_enabled = p_global.use_multiview && scene_shader.is_multiview_enabled(); const RD::DataFormat buffers_color_format = _render_buffers_get_color_format(); const bool buffers_can_be_storage = _render_buffers_can_be_storage(); - const uint32_t vrs_iterations = is_vrs_supported() ? 2 : 1; + const uint32_t vrs_iterations = p_global.use_vrs ? 2 : 1; + + const uint32_t post_pass_start = p_global.use_separate_post_pass ? 0 : 1; + const uint32_t post_pass_iterations = p_global.use_subpass_post_pass ? 2 : (post_pass_start + 1); + + const uint32_t hdr_start = p_global.use_ldr_render_target ? 0 : 1; + const uint32_t hdr_target_iterations = p_global.use_hdr_render_target ? 2 : 1; + for (uint32_t use_vrs = 0; use_vrs < vrs_iterations; use_vrs++) { - for (uint32_t use_post_pass = 0; use_post_pass < 2; use_post_pass++) { - const uint32_t hdr_iterations = use_post_pass ? 2 : 1; - for (uint32_t use_hdr = 0; use_hdr < hdr_iterations; use_hdr++) { + for (uint32_t use_post_pass = post_pass_start; use_post_pass < post_pass_iterations; use_post_pass++) { + const uint32_t hdr_iterations = use_post_pass ? hdr_target_iterations : (hdr_start + 1); + for (uint32_t use_hdr = hdr_start; use_hdr < hdr_iterations; use_hdr++) { pipeline_key.version = SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS; pipeline_key.framebuffer_format_id = _get_color_framebuffer_format_for_pipeline(buffers_color_format, buffers_can_be_storage, RD::TextureSamples(p_global.texture_samples), RD::TextureSamples(p_global.target_samples), use_vrs, use_post_pass, use_hdr, 1); _mesh_compile_pipeline_for_surface(p_surface.shader, p_surface.mesh_surface, p_surface.instanced, p_source, pipeline_key, r_pipeline_pairs); @@ -3237,6 +3259,12 @@ RenderForwardMobile::RenderForwardMobile() { scene_shader.init(defines); _update_shader_quality_settings(); + _update_global_pipeline_data_requirements_from_project(); + + // Only update these from the project setting at init time. + const bool root_hdr_render_target = GLOBAL_GET("rendering/viewport/hdr_2d"); + global_pipeline_data_required.use_hdr_render_target = root_hdr_render_target; + global_pipeline_data_required.use_ldr_render_target = !root_hdr_render_target; } RenderForwardMobile::~RenderForwardMobile() { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 4d2513f012f..6e4d33520ef 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -587,6 +587,11 @@ public: uint32_t use_32_bit_shadows : 1; uint32_t use_shadow_cubemaps : 1; uint32_t use_shadow_dual_paraboloid : 1; + uint32_t use_vrs : 1; + uint32_t use_subpass_post_pass : 1; + uint32_t use_separate_post_pass : 1; + uint32_t use_hdr_render_target : 1; + uint32_t use_ldr_render_target : 1; }; }; }; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index ed1f55d2f67..c2b75eb450b 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -172,8 +172,9 @@ public: h = hash_murmur3_one_32(cull_mode, h); h = hash_murmur3_one_32(primitive_type, h); h = hash_murmur3_one_32(shader_specialization.packed_0, h); - h = hash_murmur3_one_float(shader_specialization.packed_1, h); + h = hash_murmur3_one_32(shader_specialization.packed_1, h); h = hash_murmur3_one_32(shader_specialization.packed_2, h); + h = hash_murmur3_one_float(shader_specialization.packed_3, h); h = hash_murmur3_one_32(version, h); h = hash_murmur3_one_32(render_pass, h); h = hash_murmur3_one_32(wireframe, h); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 36229dc1dfd..0b3c9182495 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -3608,6 +3608,7 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"), 2); GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile", 0); + GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/atlas_16_bits", true); GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/shadow_atlas/size", PROPERTY_HINT_RANGE, "128,16384"), 2048); GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/2d/batching/item_buffer_size", PROPERTY_HINT_RANGE, "128,1048576,1"), 16384); @@ -3664,6 +3665,12 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/environment/ssil/fadeout_from", PROPERTY_HINT_RANGE, "0.0,512,0.1,or_greater"), 50.0); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/environment/ssil/fadeout_to", PROPERTY_HINT_RANGE, "64,65536,0.1,or_greater"), 300.0); + // Move the project setting definitions here so they are available when we init the rendering internals. + GLOBAL_DEF_BASIC("rendering/viewport/hdr_2d", false); + + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_2d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/msaa_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Average),4× (Slow),8× (Slowest)")), 0); + GLOBAL_DEF("rendering/anti_aliasing/screen_space_roughness_limiter/enabled", true); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"), 0.25); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"), 0.18); @@ -3686,8 +3693,8 @@ void RenderingServer::init() { } GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/scaling_3d/scale", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), 1.0); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/scaling_3d/fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), 0.2f); - GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/textures/default_filters/texture_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.001"), 0.0f); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/textures/default_filters/texture_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.001"), 0.0f); GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"), DECAL_FILTER_LINEAR_MIPMAPS); GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"), LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS); From d481669c500a96fc74d366c433fbf6ec4d71a53e Mon Sep 17 00:00:00 2001 From: "J. F. Dowsley" Date: Thu, 6 Feb 2025 12:25:50 -0300 Subject: [PATCH 05/71] Ignore --test flag when it is an user-provided argument --- main/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main/main.cpp b/main/main.cpp index e8086db9d3c..f6f68d61ea9 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -889,6 +889,11 @@ void Main::test_cleanup() { int Main::test_entrypoint(int argc, char *argv[], bool &tests_need_run) { for (int x = 0; x < argc; x++) { + // Early return to ignore a possible user-provided "--test" argument. + if ((strlen(argv[x]) == 2) && ((strncmp(argv[x], "--", 2) == 0) || (strncmp(argv[x], "++", 2) == 0))) { + tests_need_run = false; + return EXIT_SUCCESS; + } if ((strncmp(argv[x], "--test", 6) == 0) && (strlen(argv[x]) == 6)) { tests_need_run = true; #ifdef TESTS_ENABLED From 75bb2c57acfa2b817a12a45b45f12f7deacc78f1 Mon Sep 17 00:00:00 2001 From: tetrapod <145553014+tetrapod00@users.noreply.github.com> Date: Fri, 7 Feb 2025 15:36:25 -0800 Subject: [PATCH 06/71] Add parentheses to method links in online class reference --- doc/tools/make_rst.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index 744325f1435..0b4896d25e3 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -2238,6 +2238,8 @@ def format_text_block( repl_text = target_name if target_class_name != state.current_class: repl_text = f"{target_class_name}.{target_name}" + if tag_state.name == "method": + repl_text = f"{repl_text}()" tag_text = f":ref:`{repl_text}`" escape_pre = True escape_post = True From 3084ed4bffc41600727dc509569ac2c619fb20af Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sat, 8 Feb 2025 08:11:35 +1100 Subject: [PATCH 07/71] editor: Fix AtlasTexture editor previews for compressed textures --- editor/plugins/editor_preview_plugins.cpp | 7 +++++++ editor/plugins/texture_editor_plugin.cpp | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 0f7af27d072..5b003f53e9b 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -100,6 +100,13 @@ Ref EditorTexturePreviewPlugin::generate(const Ref &p_from, return Ref(); } + if (atlas->is_compressed()) { + atlas = atlas->duplicate(); + if (atlas->decompress() != OK) { + return Ref(); + } + } + if (!tex_atlas->get_region().has_area()) { return Ref(); } diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index 561146be425..fcda832c911 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -132,8 +132,21 @@ static Image::Format get_texture_2d_format(const Ref &p_texture) { static int get_texture_mipmaps_count(const Ref &p_texture) { ERR_FAIL_COND_V(p_texture.is_null(), -1); + // We are having to download the image only to get its mipmaps count. It would be nice if we didn't have to. - Ref image = p_texture->get_image(); + Ref image; + Ref at = p_texture; + if (at.is_valid()) { + // The AtlasTexture tries to obtain the region from the atlas as an image, + // which will fail if it is a compressed format. + Ref atlas = at->get_atlas(); + if (atlas.is_valid()) { + image = atlas->get_image(); + } + } else { + image = p_texture->get_image(); + } + if (image.is_valid()) { return image->get_mipmap_count(); } From 65b7e1c73cde7dc0ac70c8eebc878832828e331e Mon Sep 17 00:00:00 2001 From: kit Date: Fri, 7 Feb 2025 14:34:04 -0500 Subject: [PATCH 08/71] Fix TextEdit cusor shape when mouse is held --- scene/gui/code_edit.cpp | 4 ++++ scene/gui/text_edit.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 98cdd549acc..6a7e69b3165 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -660,6 +660,10 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_POINTING_HAND; } + if (is_dragging_cursor()) { + return TextEdit::get_cursor_shape(p_pos); + } + if ((code_completion_active && code_completion_rect.has_point(p_pos)) || (!is_editable() && (!is_selecting_enabled() || get_line_count() == 0))) { return CURSOR_ARROW; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index a153e025c4e..3c7a4fd105a 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1674,6 +1674,7 @@ void TextEdit::_notification(int p_what) { selection_drag_attempt = false; drag_action = false; drag_caret_force_displayed = false; + dragging_selection = false; } break; case NOTIFICATION_MOUSE_EXIT_SELF: { @@ -3112,6 +3113,14 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { + if (dragging_selection) { + return get_default_cursor_shape(); + } + + if (dragging_minimap) { + return CURSOR_ARROW; + } + Vector2i current_hovered_gutter = _get_hovered_gutter(p_pos); if (current_hovered_gutter != Vector2i(-1, -1)) { if (gutters[current_hovered_gutter.x].clickable || is_line_gutter_clickable(current_hovered_gutter.y, current_hovered_gutter.x)) { From 5bfc4a5b06d1b897f112483e725d99e84da08441 Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Mon, 10 Feb 2025 02:32:31 +0100 Subject: [PATCH 09/71] Fix tree selecting hidden items --- scene/gui/tree.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 329c6f3da31..c329284ecb6 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2841,7 +2841,9 @@ void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_c TreeItem *c = p_current->first_child; while (c) { - select_single_item(p_selected, c, p_col, p_prev, r_in_range, p_current->is_collapsed() || p_force_deselect); + if (c->is_visible()) { + select_single_item(p_selected, c, p_col, p_prev, r_in_range, p_current->is_collapsed() || p_force_deselect); + } c = c->next; } } From 030d63eed9e18c34cccef59dd0e9614ca6ee5e00 Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Fri, 22 Nov 2024 08:45:56 +0100 Subject: [PATCH 10/71] Add tooltip text to Polygon3DEditor buttons --- editor/plugins/polygon_3d_editor_plugin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editor/plugins/polygon_3d_editor_plugin.cpp b/editor/plugins/polygon_3d_editor_plugin.cpp index 16cbbc7bdba..9d7567f2528 100644 --- a/editor/plugins/polygon_3d_editor_plugin.cpp +++ b/editor/plugins/polygon_3d_editor_plugin.cpp @@ -535,12 +535,14 @@ Polygon3DEditor::Polygon3DEditor() { button_create = memnew(Button); button_create->set_theme_type_variation(SceneStringName(FlatButton)); + button_create->set_tooltip_text(TTRC("Create Polygon")); add_child(button_create); button_create->connect(SceneStringName(pressed), callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_CREATE)); button_create->set_toggle_mode(true); button_edit = memnew(Button); button_edit->set_theme_type_variation(SceneStringName(FlatButton)); + button_edit->set_tooltip_text(TTRC("Edit Polygon")); add_child(button_edit); button_edit->connect(SceneStringName(pressed), callable_mp(this, &Polygon3DEditor::_menu_option).bind(MODE_EDIT)); button_edit->set_toggle_mode(true); From cedcc2444e196f7440cc3fb8eff86ce138ff6605 Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Sun, 9 Feb 2025 14:22:24 +0100 Subject: [PATCH 11/71] Add changeable freelook speed in Game Window --- editor/plugins/game_view_plugin.cpp | 1 + scene/debugger/scene_debugger.cpp | 18 +++++++++++++++++- scene/debugger/scene_debugger.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index a6d73cf9e15..5a76ccabf75 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -64,6 +64,7 @@ void GameViewDebugger::_session_started(Ref p_session) { settings["editors/panning/warped_mouse_panning"] = EDITOR_GET("editors/panning/warped_mouse_panning"); settings["editors/panning/2d_editor_pan_speed"] = EDITOR_GET("editors/panning/2d_editor_pan_speed"); settings["canvas_item_editor/pan_view"] = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("canvas_item_editor/pan_view")); + settings["editors/3d/freelook/freelook_base_speed"] = EDITOR_GET("editors/3d/freelook/freelook_base_speed"); setup_data.append(settings); p_session->send_message("scene:runtime_node_select_setup", setup_data); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 64087cdaf29..c620c5fd5c8 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -1261,6 +1261,8 @@ void RuntimeNodeSelect::_setup(const Dictionary &p_settings) { #ifndef _3D_DISABLED cursor = Cursor(); + freelook_speed = p_settings.get("editors/3d/freelook/freelook_base_speed", FREELOOK_BASE_SPEED); + /// 3D Selection Box Generation // Copied from the Node3DEditor implementation. @@ -1443,7 +1445,7 @@ void RuntimeNodeSelect::_process_frame() { direction -= up; } - real_t speed = FREELOOK_BASE_SPEED; + real_t speed = freelook_speed; if (input->is_physical_key_pressed(Key::SHIFT)) { speed *= 3.0; } @@ -1959,6 +1961,8 @@ bool RuntimeNodeSelect::_handle_3d_input(const Ref &p_event) { case MouseButton::WHEEL_UP: { if (!camera_freelook) { _cursor_scale_distance(1.0 / zoom_factor); + } else { + _scale_freelook_speed(zoom_factor); } return true; @@ -1966,6 +1970,8 @@ bool RuntimeNodeSelect::_handle_3d_input(const Ref &p_event) { case MouseButton::WHEEL_DOWN: { if (!camera_freelook) { _cursor_scale_distance(zoom_factor); + } else { + _scale_freelook_speed(1.0 / zoom_factor); } return true; @@ -2064,6 +2070,16 @@ void RuntimeNodeSelect::_cursor_scale_distance(real_t p_scale) { SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform()); } +void RuntimeNodeSelect::_scale_freelook_speed(real_t p_scale) { + real_t min_speed = MAX(CAMERA_ZNEAR * 4, VIEW_3D_MIN_ZOOM); + real_t max_speed = MIN(CAMERA_ZFAR / 4, VIEW_3D_MAX_ZOOM); + if (unlikely(min_speed > max_speed)) { + freelook_speed = (min_speed + max_speed) / 2; + } else { + freelook_speed = CLAMP(freelook_speed * p_scale, min_speed, max_speed); + } +} + void RuntimeNodeSelect::_cursor_look(Ref p_event) { Window *root = SceneTree::get_singleton()->get_root(); const Vector2 relative = Input::get_singleton()->warp_mouse_motion(p_event, Rect2(Vector2(), root->get_size())); diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 4542d7fc908..5a56ea9d99b 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -255,6 +255,7 @@ private: bool camera_first_override = true; bool camera_freelook = false; + real_t freelook_speed = FREELOOK_BASE_SPEED; Vector2 previous_mouse_position; @@ -309,6 +310,7 @@ private: bool _handle_3d_input(const Ref &p_event); void _set_camera_freelook_enabled(bool p_enabled); void _cursor_scale_distance(real_t p_scale); + void _scale_freelook_speed(real_t p_scale); void _cursor_look(Ref p_event); void _cursor_pan(Ref p_event); void _cursor_orbit(Ref p_event); From af900a5825dae39daff8d319b6ecaf12508d5966 Mon Sep 17 00:00:00 2001 From: "Matias N. Goldberg" Date: Tue, 14 Jan 2025 20:07:25 -0300 Subject: [PATCH 12/71] Change how device address is requested to avoid future API breakage PR #100062 introduced BUFFER_USAGE_DEVICE_ADDRESS_BIT. However it did so by adding a boolean to uniform_buffer_create(), called "bool p_enable_device_address". This makes maintaining backwards compatibility harder because I am working on another feature that would require introducing yet another bit flag. This would save us the need to add fallback routines when the feature I am working on makes it to Godot 4.5. Even if my feature doesn't make it to 4.5 either, this PR makes the routine more future-proof. This PR also moves STORAGE_BUFFER_USAGE_DEVICE_ADDRESS into BUFFER_CREATION_DEVICE_ADDRESS_BIT, since it's an option available to both storage and uniforms. This PR also moves the boolean use_as_storage into BUFFER_CREATION_AS_STORAGE. --- doc/classes/RenderingDevice.xml | 27 ++++++++++------ .../4.3-stable.expected | 7 ++-- .../renderer_rd/effects/debug_effects.cpp | 2 +- .../renderer_rd/storage_rd/mesh_storage.cpp | 9 +++--- servers/rendering/rendering_device.compat.inc | 23 +++++++------ servers/rendering/rendering_device.cpp | 32 ++++++++++--------- servers/rendering/rendering_device.h | 30 ++++++++++------- 7 files changed, 78 insertions(+), 52 deletions(-) diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 6ec7918d3b2..8db0272c75b 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -703,11 +703,10 @@ - + Creates a new index buffer. It can be accessed with the RID that is returned. Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method. - Optionally, set [param enable_device_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it. @@ -847,6 +846,7 @@ + Creates a [url=https://vkguide.dev/docs/chapter-4/storage_buffers/]storage buffer[/url] with the specified [param data] and [param usage]. It can be accessed with the RID that is returned. Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method. @@ -1073,11 +1073,10 @@ - + Creates a new uniform buffer. It can be accessed with the RID that is returned. Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method. - Optionally, set [param enable_device_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it. @@ -1111,12 +1110,10 @@ - - + It can be accessed with the RID that is returned. Once finished with your RID, you will want to free the RID using the RenderingDevice's [method free_rid] method. - Optionally, set [param enable_device_address] if you wish to use [method buffer_get_device_address] functionality and the GPU supports it. @@ -2068,8 +2065,20 @@ - - Allows usage of [method buffer_get_device_address] on supported GPUs. + + Optionally, set this flag if you wish to use [method buffer_get_device_address] functionality. You must first check the GPU supports it: + [codeblocks] + [gdscript] + rd = RenderingServer.get_rendering_device() + + if rd.has_feature(RenderingDevice.SUPPORTS_BUFFER_DEVICE_ADDRESS): + storage_buffer = rd.storage_buffer_create(bytes.size(), bytes, RenderingDevice.STORAGE_BUFFER_USAGE_SHADER_DEVICE_ADDRESS): + storage_buffer_address = rd.buffer_get_device_address(storage_buffer) + [/gdscript] + [/codeblocks] + + + Set this flag so that it is created as storage. This is useful if Compute Shaders need access (for reading or writing) to the buffer, e.g. skeletal animations are processed in Compute Shaders which need access to vertex buffers, to be later consumed by vertex shaders as part of the regular rasterization pipeline. Sampler uniform. diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected index 7b5889f464b..1cb33a64fbf 100644 --- a/misc/extension_api_validation/4.3-stable.expected +++ b/misc/extension_api_validation/4.3-stable.expected @@ -294,13 +294,16 @@ Validate extension JSON: Error: Field 'classes/RichTextLabel/methods/set_table_c Added optional "shrink" argument. Compatibility method registered. -GH-100062 +GH-101561 -------- Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/index_buffer_create/arguments': size changed value in new API, from 4 to 5. Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/uniform_buffer_create/arguments': size changed value in new API, from 2 to 3. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/storage_buffer_create/arguments': size changed value in new API, from 3 to 4. Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/vertex_buffer_create/arguments': size changed value in new API, from 3 to 4. +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/vertex_buffer_create/arguments/2': default_value changed value in new API, from "false" to "0". +Validate extension JSON: Error: Field 'classes/RenderingDevice/methods/vertex_buffer_create/arguments/2': type changed value in new API, from "bool" to "bitfield::RenderingDevice.BufferCreationBits". -Optional argument added. Compatibility methods registered. +Optional argument (creation flags) added. Compatibility methods registered. GH-101531 diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp index d7c08be8874..4cde9e9cac1 100644 --- a/servers/rendering/renderer_rd/effects/debug_effects.cpp +++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp @@ -66,7 +66,7 @@ DebugEffects::DebugEffects() { void DebugEffects::_create_frustum_arrays() { if (frustum.vertex_buffer.is_null()) { // Create vertex buffer, but don't put data in it yet - frustum.vertex_buffer = RD::get_singleton()->vertex_buffer_create(8 * sizeof(float) * 3, Vector(), false); + frustum.vertex_buffer = RD::get_singleton()->vertex_buffer_create(8 * sizeof(float) * 3, Vector()); Vector attributes; Vector buffers; diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 84f4b452996..cb3d827e77d 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -370,7 +370,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) s->format = new_surface.format; s->primitive = new_surface.primitive; - bool use_as_storage = (new_surface.skin_data.size() || mesh->blend_shape_count > 0); + const bool use_as_storage = (new_surface.skin_data.size() || mesh->blend_shape_count > 0); + const BitField as_storage_flag = use_as_storage ? RD::BUFFER_CREATION_AS_STORAGE_BIT : 0; if (new_surface.vertex_data.size()) { // If we have an uncompressed surface that contains normals, but not tangents, we need to differentiate the array @@ -384,10 +385,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) Vector new_vertex_data; new_vertex_data.resize_zeroed(new_surface.vertex_data.size() + sizeof(uint16_t) * 2); memcpy(new_vertex_data.ptrw(), new_surface.vertex_data.ptr(), new_surface.vertex_data.size()); - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_vertex_data.size(), new_vertex_data, use_as_storage); + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_vertex_data.size(), new_vertex_data, as_storage_flag); s->vertex_buffer_size = new_vertex_data.size(); } else { - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.vertex_data.size(), new_surface.vertex_data, use_as_storage); + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.vertex_data.size(), new_surface.vertex_data, as_storage_flag); s->vertex_buffer_size = new_surface.vertex_data.size(); } } @@ -396,7 +397,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.attribute_data.size(), new_surface.attribute_data); } if (new_surface.skin_data.size()) { - s->skin_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.skin_data.size(), new_surface.skin_data, use_as_storage); + s->skin_buffer = RD::get_singleton()->vertex_buffer_create(new_surface.skin_data.size(), new_surface.skin_data, as_storage_flag); s->skin_buffer_size = new_surface.skin_data.size(); } diff --git a/servers/rendering/rendering_device.compat.inc b/servers/rendering/rendering_device.compat.inc index c5a1e4ff30f..4ca4a2d5a62 100644 --- a/servers/rendering/rendering_device.compat.inc +++ b/servers/rendering/rendering_device.compat.inc @@ -143,16 +143,20 @@ RenderingDevice::FramebufferFormatID RenderingDevice::_screen_get_framebuffer_fo return screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID); } -RID RenderingDevice::_uniform_buffer_create_bind_compat_100062(uint32_t p_size_bytes, const Vector &p_data) { - return uniform_buffer_create(p_size_bytes, p_data, false); +RID RenderingDevice::_uniform_buffer_create_bind_compat_101561(uint32_t p_size_bytes, const Vector &p_data) { + return uniform_buffer_create(p_size_bytes, p_data, 0); } -RID RenderingDevice::_vertex_buffer_create_bind_compat_100062(uint32_t p_size_bytes, const Vector &p_data, bool p_use_as_storage) { - return vertex_buffer_create(p_size_bytes, p_data, p_use_as_storage, false); +RID RenderingDevice::_storage_buffer_create_bind_compat_101561(uint32_t p_size, const Vector &p_data, BitField p_usage) { + return storage_buffer_create(p_size, p_data, p_usage, 0); } -RID RenderingDevice::_index_buffer_create_bind_compat_100062(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data, bool p_use_restart_indices) { - return index_buffer_create(p_size_indices, p_format, p_data, p_use_restart_indices, false); +RID RenderingDevice::_vertex_buffer_create_bind_compat_101561(uint32_t p_size_bytes, const Vector &p_data, bool p_use_as_storage) { + return vertex_buffer_create(p_size_bytes, p_data, p_use_as_storage ? RD::BUFFER_CREATION_AS_STORAGE_BIT : 0); +} + +RID RenderingDevice::_index_buffer_create_bind_compat_101561(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data, bool p_use_restart_indices) { + return index_buffer_create(p_size_indices, p_format, p_data, p_use_restart_indices, 0); } void RenderingDevice::_bind_compatibility_methods() { @@ -179,9 +183,10 @@ void RenderingDevice::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "breadcrumb"), &RenderingDevice::_draw_list_begin_bind_compat_98670, DEFVAL(Vector()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(0)); - ClassDB::bind_compatibility_method(D_METHOD("uniform_buffer_create"), &RenderingDevice::_uniform_buffer_create_bind_compat_100062, DEFVAL(Vector())); - ClassDB::bind_compatibility_method(D_METHOD("vertex_buffer_create"), &RenderingDevice::_vertex_buffer_create_bind_compat_100062, DEFVAL(Vector()), DEFVAL(false)); - ClassDB::bind_compatibility_method(D_METHOD("index_buffer_create"), &RenderingDevice::_index_buffer_create_bind_compat_100062, DEFVAL(Vector()), DEFVAL(false)); + ClassDB::bind_compatibility_method(D_METHOD("uniform_buffer_create", "size_bytes", "data"), &RenderingDevice::_uniform_buffer_create_bind_compat_101561, DEFVAL(Vector())); + ClassDB::bind_compatibility_method(D_METHOD("storage_buffer_create", "size_bytes", "data", "usage"), &RenderingDevice::_storage_buffer_create_bind_compat_101561, DEFVAL(Vector()), DEFVAL(0)); + ClassDB::bind_compatibility_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::_vertex_buffer_create_bind_compat_101561, DEFVAL(Vector()), DEFVAL(false)); + ClassDB::bind_compatibility_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices"), &RenderingDevice::_index_buffer_create_bind_compat_101561, DEFVAL(Vector()), DEFVAL(false)); } #endif diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 9716a42c97b..bfbfd1919c4 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -796,7 +796,7 @@ uint64_t RenderingDevice::buffer_get_device_address(RID p_buffer) { return driver->buffer_get_device_address(buffer->driver_id); } -RID RenderingDevice::storage_buffer_create(uint32_t p_size_bytes, const Vector &p_data, BitField p_usage) { +RID RenderingDevice::storage_buffer_create(uint32_t p_size_bytes, const Vector &p_data, BitField p_usage, BitField p_creation_bits) { ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID()); Buffer buffer; @@ -805,7 +805,7 @@ RID RenderingDevice::storage_buffer_create(uint32_t p_size_bytes, const Vector &p_data, bool p_use_as_storage, bool p_enable_device_address) { +RID RenderingDevice::vertex_buffer_create(uint32_t p_size_bytes, const Vector &p_data, BitField p_creation_bits) { ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID()); Buffer buffer; buffer.size = p_size_bytes; buffer.usage = RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_VERTEX_BIT; - if (p_use_as_storage) { + if (p_creation_bits.has_flag(BUFFER_CREATION_AS_STORAGE_BIT)) { buffer.usage.set_flag(RDD::BUFFER_USAGE_STORAGE_BIT); } - if (p_enable_device_address) { + if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) { buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT); } buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); ERR_FAIL_COND_V(!buffer.driver_id, RID()); // Vertex buffers are assumed to be immutable unless they don't have initial data or they've been marked for storage explicitly. - if (p_data.is_empty() || p_use_as_storage) { + if (p_data.is_empty() || p_creation_bits.has_flag(BUFFER_CREATION_AS_STORAGE_BIT)) { buffer.draw_tracker = RDG::resource_tracker_create(); buffer.draw_tracker->buffer_driver_id = buffer.driver_id; } @@ -3120,7 +3120,7 @@ RID RenderingDevice::vertex_array_create(uint32_t p_vertex_count, VertexFormatID return id; } -RID RenderingDevice::index_buffer_create(uint32_t p_index_count, IndexBufferFormat p_format, const Vector &p_data, bool p_use_restart_indices, bool p_enable_device_address) { +RID RenderingDevice::index_buffer_create(uint32_t p_index_count, IndexBufferFormat p_format, const Vector &p_data, bool p_use_restart_indices, BitField p_creation_bits) { ERR_FAIL_COND_V(p_index_count == 0, RID()); IndexBuffer index_buffer; @@ -3159,7 +3159,7 @@ RID RenderingDevice::index_buffer_create(uint32_t p_index_count, IndexBufferForm #endif index_buffer.size = size_bytes; index_buffer.usage = (RDD::BUFFER_USAGE_TRANSFER_FROM_BIT | RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_INDEX_BIT); - if (p_enable_device_address) { + if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) { index_buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT); } index_buffer.driver_id = driver->buffer_create(index_buffer.size, index_buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); @@ -3370,13 +3370,13 @@ uint64_t RenderingDevice::shader_get_vertex_input_attribute_mask(RID p_shader) { /**** UNIFORMS ****/ /******************/ -RID RenderingDevice::uniform_buffer_create(uint32_t p_size_bytes, const Vector &p_data, bool p_enable_device_address) { +RID RenderingDevice::uniform_buffer_create(uint32_t p_size_bytes, const Vector &p_data, BitField p_creation_bits) { ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID()); Buffer buffer; buffer.size = p_size_bytes; buffer.usage = (RDD::BUFFER_USAGE_TRANSFER_TO_BIT | RDD::BUFFER_USAGE_UNIFORM_BIT); - if (p_enable_device_address) { + if (p_creation_bits.has_flag(BUFFER_CREATION_DEVICE_ADDRESS_BIT)) { buffer.usage.set_flag(RDD::BUFFER_USAGE_DEVICE_ADDRESS_BIT); } buffer.driver_id = driver->buffer_create(buffer.size, buffer.usage, RDD::MEMORY_ALLOCATION_TYPE_GPU); @@ -7294,11 +7294,11 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create); ClassDB::bind_method(D_METHOD("sampler_is_format_supported_for_filter", "format", "sampler_filter"), &RenderingDevice::sampler_is_format_supported_for_filter); - ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage", "enable_device_address"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector()), DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "creation_bits"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create); ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers", "offsets"), &RenderingDevice::_vertex_array_create, DEFVAL(Vector())); - ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices", "enable_device_address"), &RenderingDevice::index_buffer_create, DEFVAL(Vector()), DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices", "creation_bits"), &RenderingDevice::index_buffer_create, DEFVAL(Vector()), DEFVAL(false), DEFVAL(0)); ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create); ClassDB::bind_method(D_METHOD("shader_compile_spirv_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_spirv_from_source, DEFVAL(true)); @@ -7309,8 +7309,8 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("shader_get_vertex_input_attribute_mask", "shader"), &RenderingDevice::shader_get_vertex_input_attribute_mask); - ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data", "enable_device_address"), &RenderingDevice::uniform_buffer_create, DEFVAL(Vector()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("storage_buffer_create", "size_bytes", "data", "usage"), &RenderingDevice::storage_buffer_create, DEFVAL(Vector()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data", "creation_bits"), &RenderingDevice::uniform_buffer_create, DEFVAL(Vector()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("storage_buffer_create", "size_bytes", "data", "usage", "creation_bits"), &RenderingDevice::storage_buffer_create, DEFVAL(Vector()), DEFVAL(0), DEFVAL(0)); ClassDB::bind_method(D_METHOD("texture_buffer_create", "size_bytes", "format", "data"), &RenderingDevice::texture_buffer_create, DEFVAL(Vector())); ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create); @@ -7753,7 +7753,9 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32); BIND_BITFIELD_FLAG(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); - BIND_BITFIELD_FLAG(STORAGE_BUFFER_USAGE_DEVICE_ADDRESS); + + BIND_BITFIELD_FLAG(BUFFER_CREATION_DEVICE_ADDRESS_BIT); + BIND_BITFIELD_FLAG(BUFFER_CREATION_AS_STORAGE_BIT); BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type) BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 10723392a1e..6d480258e12 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -754,13 +754,22 @@ private: RID_Owner index_array_owner; public: - RID vertex_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector(), bool p_use_as_storage = false, bool p_enable_device_address = false); + enum BufferCreationBits { + BUFFER_CREATION_DEVICE_ADDRESS_BIT = (1 << 0), + BUFFER_CREATION_AS_STORAGE_BIT = (1 << 1), + }; + + enum StorageBufferUsage { + STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = (1 << 0), + }; + + RID vertex_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector(), BitField p_creation_bits = 0); // This ID is warranted to be unique for the same formats, does not need to be freed VertexFormatID vertex_format_create(const Vector &p_vertex_descriptions); RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector &p_src_buffers, const Vector &p_offsets = Vector()); - RID index_buffer_create(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data = Vector(), bool p_use_restart_indices = false, bool p_enable_device_address = false); + RID index_buffer_create(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data = Vector(), bool p_use_restart_indices = false, BitField p_creation_bits = 0); RID index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count); /****************/ @@ -895,9 +904,10 @@ private: DrawListID _draw_list_begin_bind_compat_98670(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, uint32_t p_breadcrumb); - RID _uniform_buffer_create_bind_compat_100062(uint32_t p_size_bytes, const Vector &p_data); - RID _vertex_buffer_create_bind_compat_100062(uint32_t p_size_bytes, const Vector &p_data, bool p_use_as_storage); - RID _index_buffer_create_bind_compat_100062(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data, bool p_use_restart_indices); + RID _uniform_buffer_create_bind_compat_101561(uint32_t p_size_bytes, const Vector &p_data); + RID _vertex_buffer_create_bind_compat_101561(uint32_t p_size_bytes, const Vector &p_data, bool p_use_as_storage); + RID _index_buffer_create_bind_compat_101561(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data, bool p_use_restart_indices); + RID _storage_buffer_create_bind_compat_101561(uint32_t p_size, const Vector &p_data, BitField p_usage); #endif public: @@ -930,17 +940,12 @@ public: /******************/ String get_perf_report() const; - enum StorageBufferUsage { - STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = (1 << 0), - STORAGE_BUFFER_USAGE_DEVICE_ADDRESS = (1 << 1), - }; - /*****************/ /**** BUFFERS ****/ /*****************/ - RID uniform_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector(), bool p_enable_device_address = false); - RID storage_buffer_create(uint32_t p_size, const Vector &p_data = Vector(), BitField p_usage = 0); + RID uniform_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector(), BitField p_creation_bits = 0); + RID storage_buffer_create(uint32_t p_size, const Vector &p_data = Vector(), BitField p_usage = 0, BitField p_creation_bits = 0); RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector &p_data = Vector()); @@ -1684,6 +1689,7 @@ VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor) VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency) VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat) VARIANT_BITFIELD_CAST(RenderingDevice::StorageBufferUsage) +VARIANT_BITFIELD_CAST(RenderingDevice::BufferCreationBits) VARIANT_ENUM_CAST(RenderingDevice::UniformType) VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive) VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode) From 38d0e82a35c628b08a7450d673556fe54a015742 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 12 Feb 2025 00:51:22 +0100 Subject: [PATCH 13/71] Store _custom_type_script meta as String --- editor/editor_data.cpp | 25 +++++++++++++++---------- editor/editor_node.cpp | 2 +- editor/scene_tree_dock.cpp | 6 +++--- scene/property_utils.cpp | 28 +++++++++++++++++++++++++++- scene/property_utils.h | 3 +++ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 8135a9b9664..aec082791ef 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -39,6 +39,7 @@ #include "editor/multi_node_edit.h" #include "editor/plugins/editor_context_menu_plugin.h" #include "editor/plugins/editor_plugin.h" +#include "scene/property_utils.h" #include "scene/resources/packed_scene.h" void EditorSelectionHistory::cleanup_history() { @@ -536,15 +537,18 @@ Variant EditorData::instantiate_custom_type(const String &p_type, const String & if (get_custom_types()[p_inherits][i].name == p_type) { Ref