diff options
351 files changed, 20376 insertions, 16733 deletions
diff --git a/.travis.yml b/.travis.yml index eeeedef063..8b58e12563 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ matrix: - name: Linux editor (debug, GCC 9, with Mono) stage: build - env: PLATFORM=x11 TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc-9 MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" EXTRA_ARGS="module_mono_enabled=yes mono_glue=no warnings=extra werror=yes" + env: PLATFORM=linuxbsd TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-mono-gcc-9 MATRIX_EVAL="CC=gcc-9 && CXX=g++-9" EXTRA_ARGS="module_mono_enabled=yes mono_glue=no warnings=extra werror=yes" os: linux compiler: gcc-9 addons: @@ -47,7 +47,7 @@ matrix: - name: Linux export template (release, Clang 7) stage: build - env: PLATFORM=x11 TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes" + env: PLATFORM=linuxbsd TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-clang EXTRA_ARGS="warnings=extra werror=yes" os: linux compiler: clang addons: @@ -67,17 +67,17 @@ matrix: # packages: # - openjdk-8-jdk -# - name: macOS editor (debug, Clang) -# stage: build -# env: PLATFORM=osx TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-clang EXTRA_ARGS="warnings=extra werror=yes" -# os: osx -# osx_image: xcode11.3 -# compiler: clang -# addons: -# homebrew: -# packages: -# - scons -# update: true + - name: macOS editor (debug, Clang) + stage: build + env: PLATFORM=osx TOOLS=yes TARGET=debug CACHE_NAME=${PLATFORM}-tools-clang EXTRA_ARGS="warnings=extra werror=yes" + os: osx + osx_image: xcode11.3 + compiler: clang + addons: + homebrew: + packages: + - scons + update: true # TODO: iOS MoltenVK support @@ -109,7 +109,7 @@ matrix: - name: Linux export template (release_debug, GCC 7, without 3D support) stage: build - env: PLATFORM=x11 TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-7 EXTRA_ARGS="disable_3d=yes" + env: PLATFORM=linuxbsd TOOLS=no TARGET=release_debug CACHE_NAME=${PLATFORM}-gcc-7 EXTRA_ARGS="disable_3d=yes" os: linux compiler: gcc addons: @@ -117,15 +117,15 @@ matrix: packages: - *linux_deps - - name: Javascript export template (release, emscripten latest) - stage: build - env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes" - os: linux - compiler: clang - addons: - apt: - packages: - - *linux_deps +# - name: Javascript export template (release, emscripten latest) +# stage: build +# env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes" +# os: linux +# compiler: clang +# addons: +# apt: +# packages: +# - *linux_deps before_install: - eval "${MATRIX_EVAL}" @@ -165,7 +165,7 @@ script: scons -j2 CC=$CC CXX=$CXX platform=$PLATFORM tools=$TOOLS target=$TARGET $OPTIONS $EXTRA_ARGS && if [ "$TEST_PROJECT" = "yes" ]; then git clone --depth 1 "https://github.com/godotengine/godot-tests.git"; - sed -i "s:custom_template/release=\"\":custom_template/release=\"$(readlink -e bin/godot_server.x11.opt.tools.64)\":" godot-tests/tests/project_export/export_presets.cfg; - godot-tests/tests/project_export/test_project.sh "bin/godot_server.x11.opt.tools.64"; + sed -i "s:custom_template/release=\"\":custom_template/release=\"$(readlink -e bin/godot_server.linuxbsd.opt.tools.64)\":" godot-tests/tests/project_export/export_presets.cfg; + godot-tests/tests/project_export/test_project.sh "bin/godot_server.linuxbsd.opt.tools.64"; fi fi diff --git a/SConstruct b/SConstruct index 84400e800d..ed4b3c6242 100644 --- a/SConstruct +++ b/SConstruct @@ -236,7 +236,7 @@ elif env_base['p'] != "": else: # Missing `platform` argument, try to detect platform automatically if sys.platform.startswith('linux'): - selected_platform = 'x11' + selected_platform = 'linuxbsd' elif sys.platform == 'darwin': selected_platform = 'osx' elif sys.platform == 'win32': diff --git a/core/SCsub b/core/SCsub index b4974196bd..ca003ce931 100644 --- a/core/SCsub +++ b/core/SCsub @@ -166,6 +166,7 @@ SConscript('math/SCsub') SConscript('crypto/SCsub') SConscript('io/SCsub') SConscript('debugger/SCsub') +SConscript('input/SCsub') SConscript('bind/SCsub') diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 62d83b2e04..0236523200 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -194,82 +194,6 @@ _ResourceSaver::_ResourceSaver() { singleton = this; } -/////////////////OS - -void _OS::global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta) { - - OS::get_singleton()->global_menu_add_item(p_menu, p_label, p_signal, p_meta); -} - -void _OS::global_menu_add_separator(const String &p_menu) { - - OS::get_singleton()->global_menu_add_separator(p_menu); -} - -void _OS::global_menu_remove_item(const String &p_menu, int p_idx) { - - OS::get_singleton()->global_menu_remove_item(p_menu, p_idx); -} - -void _OS::global_menu_clear(const String &p_menu) { - - OS::get_singleton()->global_menu_clear(p_menu); -} - -Point2 _OS::get_mouse_position() const { - - return OS::get_singleton()->get_mouse_position(); -} - -void _OS::set_window_title(const String &p_title) { - - OS::get_singleton()->set_window_title(p_title); -} - -int _OS::get_mouse_button_state() const { - - return OS::get_singleton()->get_mouse_button_state(); -} - -String _OS::get_unique_id() const { - return OS::get_singleton()->get_unique_id(); -} - -bool _OS::has_touchscreen_ui_hint() const { - - return OS::get_singleton()->has_touchscreen_ui_hint(); -} - -void _OS::set_clipboard(const String &p_text) { - - OS::get_singleton()->set_clipboard(p_text); -} - -String _OS::get_clipboard() const { - - return OS::get_singleton()->get_clipboard(); -} - -int _OS::get_video_driver_count() const { - return OS::get_singleton()->get_video_driver_count(); -} - -String _OS::get_video_driver_name(VideoDriver p_driver) const { - return OS::get_singleton()->get_video_driver_name((int)p_driver); -} - -_OS::VideoDriver _OS::get_current_video_driver() const { - return (VideoDriver)OS::get_singleton()->get_current_video_driver(); -} - -int _OS::get_audio_driver_count() const { - return OS::get_singleton()->get_audio_driver_count(); -} - -String _OS::get_audio_driver_name(int p_driver) const { - return OS::get_singleton()->get_audio_driver_name(p_driver); -} - PackedStringArray _OS::get_connected_midi_inputs() { return OS::get_singleton()->get_connected_midi_inputs(); } @@ -282,198 +206,11 @@ void _OS::close_midi_inputs() { OS::get_singleton()->close_midi_inputs(); } -void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) { - - OS::VideoMode vm; - vm.width = p_size.width; - vm.height = p_size.height; - vm.fullscreen = p_fullscreen; - vm.resizable = p_resizeable; - OS::get_singleton()->set_video_mode(vm, p_screen); -} - -Size2 _OS::get_video_mode(int p_screen) const { - - OS::VideoMode vm; - vm = OS::get_singleton()->get_video_mode(p_screen); - return Size2(vm.width, vm.height); -} - -bool _OS::is_video_mode_fullscreen(int p_screen) const { - - OS::VideoMode vm; - vm = OS::get_singleton()->get_video_mode(p_screen); - return vm.fullscreen; -} - -int _OS::get_screen_count() const { - return OS::get_singleton()->get_screen_count(); -} - -int _OS::get_current_screen() const { - return OS::get_singleton()->get_current_screen(); -} - -void _OS::set_current_screen(int p_screen) { - OS::get_singleton()->set_current_screen(p_screen); -} - -Point2 _OS::get_screen_position(int p_screen) const { - return OS::get_singleton()->get_screen_position(p_screen); -} - -Size2 _OS::get_screen_size(int p_screen) const { - return OS::get_singleton()->get_screen_size(p_screen); -} - -int _OS::get_screen_dpi(int p_screen) const { - - return OS::get_singleton()->get_screen_dpi(p_screen); -} - -Point2 _OS::get_window_position() const { - return OS::get_singleton()->get_window_position(); -} - -void _OS::set_window_position(const Point2 &p_position) { - OS::get_singleton()->set_window_position(p_position); -} - -Size2 _OS::get_max_window_size() const { - return OS::get_singleton()->get_max_window_size(); -} - -Size2 _OS::get_min_window_size() const { - return OS::get_singleton()->get_min_window_size(); -} - -Size2 _OS::get_window_size() const { - return OS::get_singleton()->get_window_size(); -} - -Size2 _OS::get_real_window_size() const { - return OS::get_singleton()->get_real_window_size(); -} - -void _OS::set_max_window_size(const Size2 &p_size) { - OS::get_singleton()->set_max_window_size(p_size); -} - -void _OS::set_min_window_size(const Size2 &p_size) { - OS::get_singleton()->set_min_window_size(p_size); -} - -void _OS::set_window_size(const Size2 &p_size) { - OS::get_singleton()->set_window_size(p_size); -} - -Rect2 _OS::get_window_safe_area() const { - return OS::get_singleton()->get_window_safe_area(); -} - -void _OS::set_window_fullscreen(bool p_enabled) { - OS::get_singleton()->set_window_fullscreen(p_enabled); -} - -bool _OS::is_window_fullscreen() const { - return OS::get_singleton()->is_window_fullscreen(); -} - -void _OS::set_window_resizable(bool p_enabled) { - OS::get_singleton()->set_window_resizable(p_enabled); -} - -bool _OS::is_window_resizable() const { - return OS::get_singleton()->is_window_resizable(); -} - -void _OS::set_window_minimized(bool p_enabled) { - OS::get_singleton()->set_window_minimized(p_enabled); -} - -bool _OS::is_window_minimized() const { - return OS::get_singleton()->is_window_minimized(); -} - -void _OS::set_window_maximized(bool p_enabled) { - OS::get_singleton()->set_window_maximized(p_enabled); -} - -bool _OS::is_window_maximized() const { - return OS::get_singleton()->is_window_maximized(); -} - -void _OS::set_window_always_on_top(bool p_enabled) { - OS::get_singleton()->set_window_always_on_top(p_enabled); -} - -bool _OS::is_window_always_on_top() const { - return OS::get_singleton()->is_window_always_on_top(); -} - -bool _OS::is_window_focused() const { - return OS::get_singleton()->is_window_focused(); -} - -void _OS::set_borderless_window(bool p_borderless) { - OS::get_singleton()->set_borderless_window(p_borderless); -} - -bool _OS::get_window_per_pixel_transparency_enabled() const { - return OS::get_singleton()->get_window_per_pixel_transparency_enabled(); -} - -void _OS::set_window_per_pixel_transparency_enabled(bool p_enabled) { - OS::get_singleton()->set_window_per_pixel_transparency_enabled(p_enabled); -} - -bool _OS::get_borderless_window() const { - return OS::get_singleton()->get_borderless_window(); -} - -void _OS::set_ime_active(const bool p_active) { - - OS::get_singleton()->set_ime_active(p_active); -} - -void _OS::set_ime_position(const Point2 &p_pos) { - - OS::get_singleton()->set_ime_position(p_pos); -} - -Point2 _OS::get_ime_selection() const { - return OS::get_singleton()->get_ime_selection(); -} - -String _OS::get_ime_text() const { - return OS::get_singleton()->get_ime_text(); -} - void _OS::set_use_file_access_save_and_swap(bool p_enable) { FileAccess::set_backup_save(p_enable); } -bool _OS::is_video_mode_resizable(int p_screen) const { - - OS::VideoMode vm; - vm = OS::get_singleton()->get_video_mode(p_screen); - return vm.resizable; -} - -Array _OS::get_fullscreen_mode_list(int p_screen) const { - - List<OS::VideoMode> vmlist; - OS::get_singleton()->get_fullscreen_mode_list(&vmlist, p_screen); - Array vmarr; - for (List<OS::VideoMode>::Element *E = vmlist.front(); E; E = E->next()) { - - vmarr.push_back(Size2(E->get().width, E->get().height)); - } - - return vmarr; -} - void _OS::set_low_processor_usage_mode(bool p_enabled) { OS::get_singleton()->set_low_processor_usage_mode(p_enabled); @@ -562,52 +299,16 @@ String _OS::get_locale() const { return OS::get_singleton()->get_locale(); } -String _OS::get_latin_keyboard_variant() const { - switch (OS::get_singleton()->get_latin_keyboard_variant()) { - case OS::LATIN_KEYBOARD_QWERTY: return "QWERTY"; - case OS::LATIN_KEYBOARD_QWERTZ: return "QWERTZ"; - case OS::LATIN_KEYBOARD_AZERTY: return "AZERTY"; - case OS::LATIN_KEYBOARD_QZERTY: return "QZERTY"; - case OS::LATIN_KEYBOARD_DVORAK: return "DVORAK"; - case OS::LATIN_KEYBOARD_NEO: return "NEO"; - case OS::LATIN_KEYBOARD_COLEMAK: return "COLEMAK"; - default: return "ERROR"; - } -} - String _OS::get_model_name() const { return OS::get_singleton()->get_model_name(); } -bool _OS::is_ok_left_and_cancel_right() const { - - return OS::get_singleton()->get_swap_ok_cancel(); -} - Error _OS::set_thread_name(const String &p_name) { return Thread::set_name(p_name); }; -void _OS::set_use_vsync(bool p_enable) { - OS::get_singleton()->set_use_vsync(p_enable); -} - -bool _OS::is_vsync_enabled() const { - - return OS::get_singleton()->is_vsync_enabled(); -} - -void _OS::set_vsync_via_compositor(bool p_enable) { - OS::get_singleton()->set_vsync_via_compositor(p_enable); -} - -bool _OS::is_vsync_via_compositor_enabled() const { - - return OS::get_singleton()->is_vsync_via_compositor_enabled(); -} - bool _OS::has_feature(const String &p_feature) const { return OS::get_singleton()->has_feature(p_feature); @@ -667,16 +368,6 @@ uint64_t _OS::get_static_memory_peak_usage() const { return OS::get_singleton()->get_static_memory_peak_usage(); } -void _OS::set_native_icon(const String &p_filename) { - - OS::get_singleton()->set_native_icon(p_filename); -} - -void _OS::set_icon(const Ref<Image> &p_icon) { - - OS::get_singleton()->set_icon(p_icon); -} - int _OS::get_exit_code() const { return OS::get_singleton()->get_exit_code(); @@ -924,11 +615,6 @@ bool _OS::can_use_threads() const { return OS::get_singleton()->can_use_threads(); } -bool _OS::can_draw() const { - - return OS::get_singleton()->can_draw(); -} - bool _OS::is_userfs_persistent() const { return OS::get_singleton()->is_userfs_persistent(); @@ -1025,22 +711,6 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) { } }; -bool _OS::has_virtual_keyboard() const { - return OS::get_singleton()->has_virtual_keyboard(); -} - -void _OS::show_virtual_keyboard(const String &p_existing_text) { - OS::get_singleton()->show_virtual_keyboard(p_existing_text, Rect2()); -} - -void _OS::hide_virtual_keyboard() { - OS::get_singleton()->hide_virtual_keyboard(); -} - -int _OS::get_virtual_keyboard_height() { - return OS::get_singleton()->get_virtual_keyboard_height(); -} - void _OS::print_all_resources(const String &p_to_file) { OS::get_singleton()->print_all_resources(p_to_file); @@ -1061,45 +731,6 @@ String _OS::get_user_data_dir() const { return OS::get_singleton()->get_user_data_dir(); }; -Error _OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { - - return OS::get_singleton()->native_video_play(p_path, p_volume, p_audio_track, p_subtitle_track); -}; - -bool _OS::native_video_is_playing() { - - return OS::get_singleton()->native_video_is_playing(); -}; - -void _OS::native_video_pause() { - - OS::get_singleton()->native_video_pause(); -}; - -void _OS::native_video_unpause() { - OS::get_singleton()->native_video_unpause(); -}; - -void _OS::native_video_stop() { - - OS::get_singleton()->native_video_stop(); -}; - -void _OS::request_attention() { - - OS::get_singleton()->request_attention(); -} - -void _OS::center_window() { - - OS::get_singleton()->center_window(); -} - -void _OS::move_window_to_foreground() { - - OS::get_singleton()->move_window_to_foreground(); -} - bool _OS::is_debug_build() const { #ifdef DEBUG_ENABLED @@ -1109,26 +740,6 @@ bool _OS::is_debug_build() const { #endif } -void _OS::set_screen_orientation(ScreenOrientation p_orientation) { - - OS::get_singleton()->set_screen_orientation(OS::ScreenOrientation(p_orientation)); -} - -_OS::ScreenOrientation _OS::get_screen_orientation() const { - - return ScreenOrientation(OS::get_singleton()->get_screen_orientation()); -} - -void _OS::set_keep_screen_on(bool p_enabled) { - - OS::get_singleton()->set_keep_screen_on(p_enabled); -} - -bool _OS::is_keep_screen_on() const { - - return OS::get_singleton()->is_keep_screen_on(); -} - String _OS::get_system_dir(SystemDir p_dir) const { return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir)); @@ -1149,11 +760,6 @@ int _OS::find_keycode_from_string(const String &p_code) const { return find_keycode(p_code); } -void _OS::alert(const String &p_alert, const String &p_title) { - - OS::get_singleton()->alert(p_alert, p_title); -} - bool _OS::request_permission(const String &p_name) { return OS::get_singleton()->request_permission(p_name); @@ -1169,90 +775,17 @@ Vector<String> _OS::get_granted_permissions() const { return OS::get_singleton()->get_granted_permissions(); } +String _OS::get_unique_id() const { + return OS::get_singleton()->get_unique_id(); +} _OS *_OS::singleton = NULL; void _OS::_bind_methods() { - //ClassDB::bind_method(D_METHOD("get_mouse_position"),&_OS::get_mouse_position); - //ClassDB::bind_method(D_METHOD("is_mouse_grab_enabled"),&_OS::is_mouse_grab_enabled); - - ClassDB::bind_method(D_METHOD("set_clipboard", "clipboard"), &_OS::set_clipboard); - ClassDB::bind_method(D_METHOD("get_clipboard"), &_OS::get_clipboard); - - //will not delete for now, just unexpose - //ClassDB::bind_method(D_METHOD("set_video_mode","size","fullscreen","resizable","screen"),&_OS::set_video_mode,DEFVAL(0)); - //ClassDB::bind_method(D_METHOD("get_video_mode_size","screen"),&_OS::get_video_mode,DEFVAL(0)); - //ClassDB::bind_method(D_METHOD("is_video_mode_fullscreen","screen"),&_OS::is_video_mode_fullscreen,DEFVAL(0)); - //ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0)); - //ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0)); - - ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu", "label", "id", "meta"), &_OS::global_menu_add_item); - ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu"), &_OS::global_menu_add_separator); - ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu", "idx"), &_OS::global_menu_remove_item); - ClassDB::bind_method(D_METHOD("global_menu_clear", "menu"), &_OS::global_menu_clear); - - ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count); - ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name); - ClassDB::bind_method(D_METHOD("get_current_video_driver"), &_OS::get_current_video_driver); - - ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count); - ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name); ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs); ClassDB::bind_method(D_METHOD("open_midi_inputs"), &_OS::open_midi_inputs); ClassDB::bind_method(D_METHOD("close_midi_inputs"), &_OS::close_midi_inputs); - ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count); - ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen); - ClassDB::bind_method(D_METHOD("set_current_screen", "screen"), &_OS::set_current_screen); - ClassDB::bind_method(D_METHOD("get_screen_position", "screen"), &_OS::get_screen_position, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_screen_size", "screen"), &_OS::get_screen_size, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_screen_dpi", "screen"), &_OS::get_screen_dpi, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_window_position"), &_OS::get_window_position); - ClassDB::bind_method(D_METHOD("set_window_position", "position"), &_OS::set_window_position); - ClassDB::bind_method(D_METHOD("get_window_size"), &_OS::get_window_size); - ClassDB::bind_method(D_METHOD("get_max_window_size"), &_OS::get_max_window_size); - ClassDB::bind_method(D_METHOD("get_min_window_size"), &_OS::get_min_window_size); - ClassDB::bind_method(D_METHOD("set_max_window_size", "size"), &_OS::set_max_window_size); - ClassDB::bind_method(D_METHOD("set_min_window_size", "size"), &_OS::set_min_window_size); - ClassDB::bind_method(D_METHOD("set_window_size", "size"), &_OS::set_window_size); - ClassDB::bind_method(D_METHOD("get_window_safe_area"), &_OS::get_window_safe_area); - ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen); - ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen); - ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable); - ClassDB::bind_method(D_METHOD("is_window_resizable"), &_OS::is_window_resizable); - ClassDB::bind_method(D_METHOD("set_window_minimized", "enabled"), &_OS::set_window_minimized); - ClassDB::bind_method(D_METHOD("is_window_minimized"), &_OS::is_window_minimized); - ClassDB::bind_method(D_METHOD("set_window_maximized", "enabled"), &_OS::set_window_maximized); - ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized); - ClassDB::bind_method(D_METHOD("set_window_always_on_top", "enabled"), &_OS::set_window_always_on_top); - ClassDB::bind_method(D_METHOD("is_window_always_on_top"), &_OS::is_window_always_on_top); - ClassDB::bind_method(D_METHOD("is_window_focused"), &_OS::is_window_focused); - ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention); - ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size); - ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window); - ClassDB::bind_method(D_METHOD("move_window_to_foreground"), &_OS::move_window_to_foreground); - - ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window); - ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window); - - ClassDB::bind_method(D_METHOD("get_window_per_pixel_transparency_enabled"), &_OS::get_window_per_pixel_transparency_enabled); - ClassDB::bind_method(D_METHOD("set_window_per_pixel_transparency_enabled", "enabled"), &_OS::set_window_per_pixel_transparency_enabled); - - ClassDB::bind_method(D_METHOD("set_ime_active", "active"), &_OS::set_ime_active); - ClassDB::bind_method(D_METHOD("set_ime_position", "position"), &_OS::set_ime_position); - ClassDB::bind_method(D_METHOD("get_ime_selection"), &_OS::get_ime_selection); - ClassDB::bind_method(D_METHOD("get_ime_text"), &_OS::get_ime_text); - - ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation); - ClassDB::bind_method(D_METHOD("get_screen_orientation"), &_OS::get_screen_orientation); - - ClassDB::bind_method(D_METHOD("set_keep_screen_on", "enabled"), &_OS::set_keep_screen_on); - ClassDB::bind_method(D_METHOD("is_keep_screen_on"), &_OS::is_keep_screen_on); - - ClassDB::bind_method(D_METHOD("has_touchscreen_ui_hint"), &_OS::has_touchscreen_ui_hint); - - ClassDB::bind_method(D_METHOD("set_window_title", "title"), &_OS::set_window_title); - ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &_OS::set_low_processor_usage_mode); ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &_OS::is_in_low_processor_usage_mode); @@ -1283,9 +816,6 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_system_time_secs"), &_OS::get_system_time_secs); ClassDB::bind_method(D_METHOD("get_system_time_msecs"), &_OS::get_system_time_msecs); - ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &_OS::set_native_icon); - ClassDB::bind_method(D_METHOD("set_icon", "icon"), &_OS::set_icon); - ClassDB::bind_method(D_METHOD("get_exit_code"), &_OS::get_exit_code); ClassDB::bind_method(D_METHOD("set_exit_code", "code"), &_OS::set_exit_code); @@ -1295,10 +825,8 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_ticks_usec"), &_OS::get_ticks_usec); ClassDB::bind_method(D_METHOD("get_splash_tick_msec"), &_OS::get_splash_tick_msec); ClassDB::bind_method(D_METHOD("get_locale"), &_OS::get_locale); - ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &_OS::get_latin_keyboard_variant); ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name); - ClassDB::bind_method(D_METHOD("can_draw"), &_OS::can_draw); ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &_OS::is_userfs_persistent); ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &_OS::is_stdout_verbose); @@ -1310,10 +838,6 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &_OS::dump_memory_to_file); ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &_OS::dump_resources_to_file); - ClassDB::bind_method(D_METHOD("has_virtual_keyboard"), &_OS::has_virtual_keyboard); - ClassDB::bind_method(D_METHOD("show_virtual_keyboard", "existing_text"), &_OS::show_virtual_keyboard, DEFVAL("")); - ClassDB::bind_method(D_METHOD("hide_virtual_keyboard"), &_OS::hide_virtual_keyboard); - ClassDB::bind_method(D_METHOD("get_virtual_keyboard_height"), &_OS::get_virtual_keyboard_height); ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &_OS::print_resources_in_use, DEFVAL(false)); ClassDB::bind_method(D_METHOD("print_all_resources", "tofile"), &_OS::print_all_resources, DEFVAL("")); @@ -1324,81 +848,32 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_system_dir", "dir"), &_OS::get_system_dir); ClassDB::bind_method(D_METHOD("get_unique_id"), &_OS::get_unique_id); - ClassDB::bind_method(D_METHOD("is_ok_left_and_cancel_right"), &_OS::is_ok_left_and_cancel_right); - ClassDB::bind_method(D_METHOD("print_all_textures_by_size"), &_OS::print_all_textures_by_size); ClassDB::bind_method(D_METHOD("print_resources_by_type", "types"), &_OS::print_resources_by_type); - ClassDB::bind_method(D_METHOD("native_video_play", "path", "volume", "audio_track", "subtitle_track"), &_OS::native_video_play); - ClassDB::bind_method(D_METHOD("native_video_is_playing"), &_OS::native_video_is_playing); - ClassDB::bind_method(D_METHOD("native_video_stop"), &_OS::native_video_stop); - ClassDB::bind_method(D_METHOD("native_video_pause"), &_OS::native_video_pause); - ClassDB::bind_method(D_METHOD("native_video_unpause"), &_OS::native_video_unpause); - ClassDB::bind_method(D_METHOD("get_keycode_string", "code"), &_OS::get_keycode_string); ClassDB::bind_method(D_METHOD("is_keycode_unicode", "code"), &_OS::is_keycode_unicode); ClassDB::bind_method(D_METHOD("find_keycode_from_string", "string"), &_OS::find_keycode_from_string); ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap", "enabled"), &_OS::set_use_file_access_save_and_swap); - ClassDB::bind_method(D_METHOD("alert", "text", "title"), &_OS::alert, DEFVAL("Alert!")); - ClassDB::bind_method(D_METHOD("set_thread_name", "name"), &_OS::set_thread_name); - ClassDB::bind_method(D_METHOD("set_use_vsync", "enable"), &_OS::set_use_vsync); - ClassDB::bind_method(D_METHOD("is_vsync_enabled"), &_OS::is_vsync_enabled); - - ClassDB::bind_method(D_METHOD("set_vsync_via_compositor", "enable"), &_OS::set_vsync_via_compositor); - ClassDB::bind_method(D_METHOD("is_vsync_via_compositor_enabled"), &_OS::is_vsync_via_compositor_enabled); - ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature); ClassDB::bind_method(D_METHOD("request_permission", "name"), &_OS::request_permission); ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions); ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "clipboard"), "set_clipboard", "get_clipboard"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen"); ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_enabled"), "set_use_vsync", "is_vsync_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vsync_via_compositor"), "set_vsync_via_compositor", "is_vsync_via_compositor_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_screen_on"), "set_keep_screen_on", "is_keep_screen_on"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "min_window_size"), "set_min_window_size", "get_min_window_size"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "max_window_size"), "set_max_window_size", "get_max_window_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor"), "set_screen_orientation", "get_screen_orientation"); - ADD_GROUP("Window", "window_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_resizable"), "set_window_resizable", "is_window_resizable"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_position"), "set_window_position", "get_window_position"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "window_size"), "set_window_size", "get_window_size"); // Those default values need to be specified for the docs generator, // to avoid using values from the documentation writer's own OS instance. - ADD_PROPERTY_DEFAULT("clipboard", ""); - ADD_PROPERTY_DEFAULT("current_screen", 0); ADD_PROPERTY_DEFAULT("exit_code", 0); - ADD_PROPERTY_DEFAULT("vsync_enabled", true); - ADD_PROPERTY_DEFAULT("vsync_via_compositor", false); ADD_PROPERTY_DEFAULT("low_processor_usage_mode", false); ADD_PROPERTY_DEFAULT("low_processor_usage_mode_sleep_usec", 6900); - ADD_PROPERTY_DEFAULT("keep_screen_on", true); - ADD_PROPERTY_DEFAULT("min_window_size", Vector2()); - ADD_PROPERTY_DEFAULT("max_window_size", Vector2()); - ADD_PROPERTY_DEFAULT("screen_orientation", 0); - ADD_PROPERTY_DEFAULT("window_borderless", false); - ADD_PROPERTY_DEFAULT("window_per_pixel_transparency_enabled", false); - ADD_PROPERTY_DEFAULT("window_fullscreen", false); - ADD_PROPERTY_DEFAULT("window_maximized", false); - ADD_PROPERTY_DEFAULT("window_minimized", false); - ADD_PROPERTY_DEFAULT("window_resizable", true); - ADD_PROPERTY_DEFAULT("window_position", Vector2()); - ADD_PROPERTY_DEFAULT("window_size", Vector2()); BIND_ENUM_CONSTANT(VIDEO_DRIVER_GLES2); BIND_ENUM_CONSTANT(VIDEO_DRIVER_VULKAN); @@ -1424,14 +899,6 @@ void _OS::_bind_methods() { BIND_ENUM_CONSTANT(MONTH_NOVEMBER); BIND_ENUM_CONSTANT(MONTH_DECEMBER); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_LANDSCAPE); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_PORTRAIT); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_REVERSE_LANDSCAPE); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_REVERSE_PORTRAIT); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR_LANDSCAPE); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR_PORTRAIT); - BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR); - BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP); BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM); BIND_ENUM_CONSTANT(SYSTEM_DIR_DOCUMENTS); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 3a5bd28ce8..510d87844d 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -145,83 +145,10 @@ public: MONTH_DECEMBER }; - void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta); - void global_menu_add_separator(const String &p_menu); - void global_menu_remove_item(const String &p_menu, int p_idx); - void global_menu_clear(const String &p_menu); - - Point2 get_mouse_position() const; - void set_window_title(const String &p_title); - int get_mouse_button_state() const; - - void set_clipboard(const String &p_text); - String get_clipboard() const; - - void set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen = 0); - Size2 get_video_mode(int p_screen = 0) const; - bool is_video_mode_fullscreen(int p_screen = 0) const; - bool is_video_mode_resizable(int p_screen = 0) const; - Array get_fullscreen_mode_list(int p_screen = 0) const; - - virtual int get_video_driver_count() const; - virtual String get_video_driver_name(VideoDriver p_driver) const; - virtual VideoDriver get_current_video_driver() const; - - virtual int get_audio_driver_count() const; - virtual String get_audio_driver_name(int p_driver) const; - virtual PackedStringArray get_connected_midi_inputs(); virtual void open_midi_inputs(); virtual void close_midi_inputs(); - virtual int get_screen_count() const; - virtual int get_current_screen() const; - virtual void set_current_screen(int p_screen); - virtual Point2 get_screen_position(int p_screen = -1) const; - virtual Size2 get_screen_size(int p_screen = -1) const; - virtual int get_screen_dpi(int p_screen = -1) const; - virtual Point2 get_window_position() const; - virtual void set_window_position(const Point2 &p_position); - virtual Size2 get_max_window_size() const; - virtual Size2 get_min_window_size() const; - virtual Size2 get_window_size() const; - virtual Size2 get_real_window_size() const; - virtual Rect2 get_window_safe_area() const; - virtual void set_max_window_size(const Size2 &p_size); - virtual void set_min_window_size(const Size2 &p_size); - virtual void set_window_size(const Size2 &p_size); - virtual void set_window_fullscreen(bool p_enabled); - virtual bool is_window_fullscreen() const; - virtual void set_window_resizable(bool p_enabled); - virtual bool is_window_resizable() const; - virtual void set_window_minimized(bool p_enabled); - virtual bool is_window_minimized() const; - virtual void set_window_maximized(bool p_enabled); - virtual bool is_window_maximized() const; - virtual void set_window_always_on_top(bool p_enabled); - virtual bool is_window_always_on_top() const; - virtual bool is_window_focused() const; - virtual void request_attention(); - virtual void center_window(); - virtual void move_window_to_foreground(); - - virtual void set_borderless_window(bool p_borderless); - virtual bool get_borderless_window() const; - - virtual bool get_window_per_pixel_transparency_enabled() const; - virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); - - virtual void set_ime_active(const bool p_active); - virtual void set_ime_position(const Point2 &p_pos); - virtual Point2 get_ime_selection() const; - virtual String get_ime_text() const; - - Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); - bool native_video_is_playing(); - void native_video_pause(); - void native_video_unpause(); - void native_video_stop(); - void set_low_processor_usage_mode(bool p_enabled); bool is_in_low_processor_usage_mode() const; @@ -243,25 +170,17 @@ public: Vector<String> get_cmdline_args(); String get_locale() const; - String get_latin_keyboard_variant() const; String get_model_name() const; void dump_memory_to_file(const String &p_file); void dump_resources_to_file(const String &p_file); - bool has_virtual_keyboard() const; - void show_virtual_keyboard(const String &p_existing_text = ""); - void hide_virtual_keyboard(); - int get_virtual_keyboard_height(); - void print_resources_in_use(bool p_short = false); void print_all_resources(const String &p_to_file); void print_all_textures_by_size(); void print_resources_by_type(const Vector<String> &p_types); - bool has_touchscreen_ui_hint() const; - bool is_debug_build() const; String get_unique_id() const; @@ -272,9 +191,6 @@ public: void set_use_file_access_save_and_swap(bool p_enable); - void set_native_icon(const String &p_filename); - void set_icon(const Ref<Image> &p_icon); - int get_exit_code() const; void set_exit_code(int p_code); Dictionary get_date(bool utc) const; @@ -298,8 +214,6 @@ public: bool can_use_threads() const; - bool can_draw() const; - bool is_userfs_persistent() const; bool is_stdout_verbose() const; @@ -317,39 +231,12 @@ public: SYSTEM_DIR_RINGTONES, }; - enum ScreenOrientation { - - SCREEN_ORIENTATION_LANDSCAPE, - SCREEN_ORIENTATION_PORTRAIT, - SCREEN_ORIENTATION_REVERSE_LANDSCAPE, - SCREEN_ORIENTATION_REVERSE_PORTRAIT, - SCREEN_ORIENTATION_SENSOR_LANDSCAPE, - SCREEN_ORIENTATION_SENSOR_PORTRAIT, - SCREEN_ORIENTATION_SENSOR, - }; - String get_system_dir(SystemDir p_dir) const; String get_user_data_dir() const; - void alert(const String &p_alert, const String &p_title = "ALERT!"); - - void set_screen_orientation(ScreenOrientation p_orientation); - ScreenOrientation get_screen_orientation() const; - - void set_keep_screen_on(bool p_enabled); - bool is_keep_screen_on() const; - - bool is_ok_left_and_cancel_right() const; - Error set_thread_name(const String &p_name); - void set_use_vsync(bool p_enable); - bool is_vsync_enabled() const; - - void set_vsync_via_compositor(bool p_enable); - bool is_vsync_via_compositor_enabled() const; - bool has_feature(const String &p_feature) const; bool request_permission(const String &p_name); @@ -365,7 +252,6 @@ VARIANT_ENUM_CAST(_OS::VideoDriver); VARIANT_ENUM_CAST(_OS::Weekday); VARIANT_ENUM_CAST(_OS::Month); VARIANT_ENUM_CAST(_OS::SystemDir); -VARIANT_ENUM_CAST(_OS::ScreenOrientation); class _Geometry : public Object { diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 5f7ffb115c..b9db8ab1b0 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -33,11 +33,12 @@ #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/os.h" #include "core/project_settings.h" #include "core/script_language.h" #include "scene/main/node.h" +#include "servers/display_server.h" template <typename T> void RemoteDebugger::_bind_profiler(const String &p_name, T *p_prof) { @@ -658,9 +659,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { servers_profiler->skip_profile_frame = true; // Avoid frame time spike in debug. - Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode(); - if (mouse_mode != Input::MOUSE_MODE_VISIBLE) - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + InputFilter::MouseMode mouse_mode = InputFilter::get_singleton()->get_mouse_mode(); + if (mouse_mode != InputFilter::MOUSE_MODE_VISIBLE) + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); uint64_t loop_begin_usec = 0; uint64_t loop_time_sec = 0; @@ -694,7 +695,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else if (command == "continue") { script_debugger->set_depth(-1); script_debugger->set_lines_left(-1); - OS::get_singleton()->move_window_to_foreground(); + DisplayServer::get_singleton()->window_move_to_foreground(); break; } else if (command == "break") { @@ -778,8 +779,8 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { send_message("debug_exit", Array()); - if (mouse_mode != Input::MOUSE_MODE_VISIBLE) - Input::get_singleton()->set_mouse_mode(mouse_mode); + if (mouse_mode != InputFilter::MOUSE_MODE_VISIBLE) + InputFilter::get_singleton()->set_mouse_mode(mouse_mode); } void RemoteDebugger::poll_events(bool p_is_idle) { diff --git a/core/global_constants.cpp b/core/global_constants.cpp index 0945240c1f..8706a38453 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -30,8 +30,8 @@ #include "global_constants.h" +#include "core/input/input_event.h" #include "core/object.h" -#include "core/os/input_event.h" #include "core/os/keyboard.h" #include "core/variant.h" diff --git a/core/input/SCsub b/core/input/SCsub new file mode 100644 index 0000000000..f1660932e5 --- /dev/null +++ b/core/input/SCsub @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +Import('env') + +from platform_methods import run_in_subprocess +import input_builders + + +# Order matters here. Higher index controller database files write on top of lower index database files. +controller_databases = ["#core/input/gamecontrollerdb_204.txt", "#core/input/gamecontrollerdb_205.txt", "#core/input/gamecontrollerdb.txt", "#core/input/godotcontrollerdb.txt"] + +env.Depends("#core/input/default_controller_mappings.gen.cpp", controller_databases) +env.CommandNoCache("#core/input/default_controller_mappings.gen.cpp", controller_databases, run_in_subprocess(input_builders.make_default_controller_mappings)) + +env.add_source_files(env.core_sources, "*.cpp") + +# Don't warn about duplicate entry here, we need it registered manually for first build, +# even if later builds will pick it up twice due to above *.cpp globbing. +env.add_source_files(env.core_sources, "#core/input/default_controller_mappings.gen.cpp", warn_duplicates=False) + diff --git a/main/default_controller_mappings.h b/core/input/default_controller_mappings.h index 9e2a69acec..9e2a69acec 100644 --- a/main/default_controller_mappings.h +++ b/core/input/default_controller_mappings.h diff --git a/main/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 90d309c1c8..90d309c1c8 100644 --- a/main/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt diff --git a/main/gamecontrollerdb_204.txt b/core/input/gamecontrollerdb_204.txt index 7fbe925b25..7fbe925b25 100644 --- a/main/gamecontrollerdb_204.txt +++ b/core/input/gamecontrollerdb_204.txt diff --git a/main/gamecontrollerdb_205.txt b/core/input/gamecontrollerdb_205.txt index 55c45eb148..55c45eb148 100644 --- a/main/gamecontrollerdb_205.txt +++ b/core/input/gamecontrollerdb_205.txt diff --git a/main/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt index 472b01947b..472b01947b 100644 --- a/main/godotcontrollerdb.txt +++ b/core/input/godotcontrollerdb.txt diff --git a/core/input/input_builders.py b/core/input/input_builders.py new file mode 100644 index 0000000000..ca142c0c80 --- /dev/null +++ b/core/input/input_builders.py @@ -0,0 +1,73 @@ +"""Functions used to generate source files during build time + +All such functions are invoked in a subprocess on Windows to prevent build flakiness. +""" + +from platform_methods import subprocess_main +from collections import OrderedDict + + +def make_default_controller_mappings(target, source, env): + dst = target[0] + g = open(dst, "w") + + g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") + g.write("#include \"core/typedefs.h\"\n") + g.write("#include \"core/input/default_controller_mappings.h\"\n") + + # ensure mappings have a consistent order + platform_mappings = OrderedDict() + for src_path in source: + with open(src_path, "r") as f: + # read mapping file and skip header + mapping_file_lines = f.readlines()[2:] + + current_platform = None + for line in mapping_file_lines: + if not line: + continue + line = line.strip() + if len(line) == 0: + continue + if line[0] == "#": + current_platform = line[1:].strip() + if current_platform not in platform_mappings: + platform_mappings[current_platform] = {} + elif current_platform: + line_parts = line.split(",") + guid = line_parts[0] + if guid in platform_mappings[current_platform]: + g.write("// WARNING - DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(src_path, current_platform, platform_mappings[current_platform][guid])) + valid_mapping = True + for input_map in line_parts[2:]: + if "+" in input_map or "-" in input_map or "~" in input_map: + g.write("// WARNING - DISCARDED UNSUPPORTED MAPPING TYPE FROM DATABASE {}: {} {}\n".format(src_path, current_platform, line)) + valid_mapping = False + break + if valid_mapping: + platform_mappings[current_platform][guid] = line + + platform_variables = { + "Linux": "#if X11_ENABLED", + "Windows": "#ifdef WINDOWS_ENABLED", + "Mac OS X": "#ifdef OSX_ENABLED", + "Android": "#if defined(__ANDROID__)", + "iOS": "#ifdef IPHONE_ENABLED", + "Javascript": "#ifdef JAVASCRIPT_ENABLED", + "UWP": "#ifdef UWP_ENABLED", + } + + g.write("const char* DefaultControllerMappings::mappings[] = {\n") + for platform, mappings in platform_mappings.items(): + variable = platform_variables[platform] + g.write("{}\n".format(variable)) + for mapping in mappings.values(): + g.write("\t\"{}\",\n".format(mapping)) + g.write("#endif\n") + + g.write("\tNULL\n};\n") + g.close() + + +if __name__ == '__main__': + subprocess_main(globals()) diff --git a/core/os/input_event.cpp b/core/input/input_event.cpp index 204a36bf56..088d185b8d 100644 --- a/core/os/input_event.cpp +++ b/core/input/input_event.cpp @@ -30,7 +30,7 @@ #include "input_event.h" -#include "core/input_map.h" +#include "core/input/input_map.h" #include "core/os/keyboard.h" const int InputEvent::DEVICE_ID_TOUCH_MOUSE = -1; @@ -136,6 +136,25 @@ InputEvent::InputEvent() { device = 0; } +//////////////// + +void InputEventFromWindow::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_window_id", "id"), &InputEventFromWindow::set_window_id); + ClassDB::bind_method(D_METHOD("get_window_id"), &InputEventFromWindow::get_window_id); + ADD_PROPERTY(PropertyInfo(Variant::INT, "window_id"), "set_window_id", "get_window_id"); +} + +void InputEventFromWindow::set_window_id(int64_t p_id) { + window_id = p_id; +} +int64_t InputEventFromWindow::get_window_id() const { + return window_id; +} + +InputEventFromWindow::InputEventFromWindow() { + window_id = 0; +} ////////////////// @@ -499,7 +518,7 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co mb.instance(); mb->set_device(get_device()); - + mb->set_window_id(get_window_id()); mb->set_modifiers_from_event(this); mb->set_position(l); @@ -650,6 +669,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co mm.instance(); mm->set_device(get_device()); + mm->set_window_id(get_window_id()); mm->set_modifiers_from_event(this); @@ -697,6 +717,10 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { if (motion.is_null()) return false; + if (get_window_id() != motion->get_window_id()) { + return false; + } + if (is_pressed() != motion->is_pressed()) { return false; } @@ -948,6 +972,7 @@ Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, co Ref<InputEventScreenTouch> st; st.instance(); st->set_device(get_device()); + st->set_window_id(get_window_id()); st->set_index(index); st->set_position(p_xform.xform(pos + p_local_ofs)); st->set_pressed(pressed); @@ -1028,6 +1053,7 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con sd.instance(); sd->set_device(get_device()); + sd->set_window_id(get_window_id()); sd->set_index(index); sd->set_position(p_xform.xform(pos + p_local_ofs)); @@ -1186,6 +1212,8 @@ Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, ev.instance(); ev->set_device(get_device()); + ev->set_window_id(get_window_id()); + ev->set_modifiers_from_event(this); ev->set_position(p_xform.xform(get_position() + p_local_ofs)); @@ -1228,6 +1256,8 @@ Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, con ev.instance(); ev->set_device(get_device()); + ev->set_window_id(get_window_id()); + ev->set_modifiers_from_event(this); ev->set_position(p_xform.xform(get_position() + p_local_ofs)); diff --git a/core/os/input_event.h b/core/input/input_event.h index 21549d811f..2fdcdd0319 100644 --- a/core/os/input_event.h +++ b/core/input/input_event.h @@ -205,8 +205,24 @@ public: InputEvent(); }; -class InputEventWithModifiers : public InputEvent { - GDCLASS(InputEventWithModifiers, InputEvent); +class InputEventFromWindow : public InputEvent { + + GDCLASS(InputEventFromWindow, InputEvent); + + int64_t window_id; + +protected: + static void _bind_methods(); + +public: + void set_window_id(int64_t p_id); + int64_t get_window_id() const; + + InputEventFromWindow(); +}; + +class InputEventWithModifiers : public InputEventFromWindow { + GDCLASS(InputEventWithModifiers, InputEventFromWindow); bool shift; bool alt; @@ -440,8 +456,8 @@ public: InputEventJoypadButton(); }; -class InputEventScreenTouch : public InputEvent { - GDCLASS(InputEventScreenTouch, InputEvent); +class InputEventScreenTouch : public InputEventFromWindow { + GDCLASS(InputEventScreenTouch, InputEventFromWindow); int index; Vector2 pos; bool pressed; @@ -465,9 +481,9 @@ public: InputEventScreenTouch(); }; -class InputEventScreenDrag : public InputEvent { +class InputEventScreenDrag : public InputEventFromWindow { - GDCLASS(InputEventScreenDrag, InputEvent); + GDCLASS(InputEventScreenDrag, InputEventFromWindow); int index; Vector2 pos; Vector2 relative; diff --git a/main/input_default.cpp b/core/input/input_filter.cpp index aa9e772a38..088f7effd6 100644 --- a/main/input_default.cpp +++ b/core/input/input_filter.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* input_default.cpp */ +/* input_filter.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,134 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "input_default.h" +#include "input_filter.h" -#include "core/input_map.h" +#include "core/input/default_controller_mappings.h" +#include "core/input/input_map.h" #include "core/os/os.h" -#include "main/default_controller_mappings.h" -#include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "core/project_settings.h" + +#ifdef TOOLS_ENABLED +#include "editor/editor_settings.h" +#endif + +InputFilter *InputFilter::singleton = NULL; + +void (*InputFilter::set_mouse_mode_func)(InputFilter::MouseMode) = nullptr; +InputFilter::MouseMode (*InputFilter::get_mouse_mode_func)() = nullptr; +void (*InputFilter::warp_mouse_func)(const Vector2 &p_to_pos) = nullptr; +InputFilter::CursorShape (*InputFilter::get_current_cursor_shape_func)() = nullptr; +void (*InputFilter::set_custom_mouse_cursor_func)(const RES &, InputFilter::CursorShape, const Vector2 &) = nullptr; + +InputFilter *InputFilter::get_singleton() { + + return singleton; +} + +void InputFilter::set_mouse_mode(MouseMode p_mode) { + ERR_FAIL_INDEX((int)p_mode, 4); + set_mouse_mode_func(p_mode); +} + +InputFilter::MouseMode InputFilter::get_mouse_mode() const { + + return get_mouse_mode_func(); +} + +void InputFilter::_bind_methods() { + + ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &InputFilter::is_key_pressed); + ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &InputFilter::is_mouse_button_pressed); + ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &InputFilter::is_joy_button_pressed); + ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &InputFilter::is_action_pressed); + ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &InputFilter::is_action_just_pressed); + ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &InputFilter::is_action_just_released); + ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &InputFilter::get_action_strength); + ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &InputFilter::add_joy_mapping, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &InputFilter::remove_joy_mapping); + ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &InputFilter::joy_connection_changed); + ClassDB::bind_method(D_METHOD("is_joy_known", "device"), &InputFilter::is_joy_known); + ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &InputFilter::get_joy_axis); + ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &InputFilter::get_joy_name); + ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &InputFilter::get_joy_guid); + ClassDB::bind_method(D_METHOD("get_connected_joypads"), &InputFilter::get_connected_joypads); + ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &InputFilter::get_joy_vibration_strength); + ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &InputFilter::get_joy_vibration_duration); + ClassDB::bind_method(D_METHOD("get_joy_button_string", "button_index"), &InputFilter::get_joy_button_string); + ClassDB::bind_method(D_METHOD("get_joy_button_index_from_string", "button"), &InputFilter::get_joy_button_index_from_string); + ClassDB::bind_method(D_METHOD("get_joy_axis_string", "axis_index"), &InputFilter::get_joy_axis_string); + ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &InputFilter::get_joy_axis_index_from_string); + ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &InputFilter::start_joy_vibration, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &InputFilter::stop_joy_vibration); + ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &InputFilter::vibrate_handheld, DEFVAL(500)); + ClassDB::bind_method(D_METHOD("get_gravity"), &InputFilter::get_gravity); + ClassDB::bind_method(D_METHOD("get_accelerometer"), &InputFilter::get_accelerometer); + ClassDB::bind_method(D_METHOD("get_magnetometer"), &InputFilter::get_magnetometer); + ClassDB::bind_method(D_METHOD("get_gyroscope"), &InputFilter::get_gyroscope); + ClassDB::bind_method(D_METHOD("get_last_mouse_speed"), &InputFilter::get_last_mouse_speed); + ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &InputFilter::get_mouse_button_mask); + ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &InputFilter::set_mouse_mode); + ClassDB::bind_method(D_METHOD("get_mouse_mode"), &InputFilter::get_mouse_mode); + ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &InputFilter::warp_mouse_position); + ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &InputFilter::action_press, DEFVAL(1.f)); + ClassDB::bind_method(D_METHOD("action_release", "action"), &InputFilter::action_release); + ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &InputFilter::set_default_cursor_shape, DEFVAL(CURSOR_ARROW)); + ClassDB::bind_method(D_METHOD("get_current_cursor_shape"), &InputFilter::get_current_cursor_shape); + ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &InputFilter::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); + ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &InputFilter::parse_input_event); + ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &InputFilter::set_use_accumulated_input); + + BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); + BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); + BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); + BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); + + BIND_ENUM_CONSTANT(CURSOR_ARROW); + BIND_ENUM_CONSTANT(CURSOR_IBEAM); + BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND); + BIND_ENUM_CONSTANT(CURSOR_CROSS); + BIND_ENUM_CONSTANT(CURSOR_WAIT); + BIND_ENUM_CONSTANT(CURSOR_BUSY); + BIND_ENUM_CONSTANT(CURSOR_DRAG); + BIND_ENUM_CONSTANT(CURSOR_CAN_DROP); + BIND_ENUM_CONSTANT(CURSOR_FORBIDDEN); + BIND_ENUM_CONSTANT(CURSOR_VSIZE); + BIND_ENUM_CONSTANT(CURSOR_HSIZE); + BIND_ENUM_CONSTANT(CURSOR_BDIAGSIZE); + BIND_ENUM_CONSTANT(CURSOR_FDIAGSIZE); + BIND_ENUM_CONSTANT(CURSOR_MOVE); + BIND_ENUM_CONSTANT(CURSOR_VSPLIT); + BIND_ENUM_CONSTANT(CURSOR_HSPLIT); + BIND_ENUM_CONSTANT(CURSOR_HELP); + + ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "device"), PropertyInfo(Variant::BOOL, "connected"))); +} + +void InputFilter::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { +#ifdef TOOLS_ENABLED + + const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; + + String pf = p_function; + if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) { + + List<PropertyInfo> pinfo; + ProjectSettings::get_singleton()->get_property_list(&pinfo); + + for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { + const PropertyInfo &pi = E->get(); + + if (!pi.name.begins_with("input/")) + continue; -void InputDefault::SpeedTrack::update(const Vector2 &p_delta_p) { + String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); + r_options->push_back(quote_style + name + quote_style); + } + } +#endif +} + +void InputFilter::SpeedTrack::update(const Vector2 &p_delta_p) { uint64_t tick = OS::get_singleton()->get_ticks_usec(); uint32_t tdiff = tick - last_tick; @@ -60,26 +179,26 @@ void InputDefault::SpeedTrack::update(const Vector2 &p_delta_p) { } } -void InputDefault::SpeedTrack::reset() { +void InputFilter::SpeedTrack::reset() { last_tick = OS::get_singleton()->get_ticks_usec(); speed = Vector2(); accum_t = 0; } -InputDefault::SpeedTrack::SpeedTrack() { +InputFilter::SpeedTrack::SpeedTrack() { min_ref_frame = 0.1; max_ref_frame = 0.3; reset(); } -bool InputDefault::is_key_pressed(int p_keycode) const { +bool InputFilter::is_key_pressed(int p_keycode) const { _THREAD_SAFE_METHOD_ return keys_pressed.has(p_keycode); } -bool InputDefault::is_mouse_button_pressed(int p_button) const { +bool InputFilter::is_mouse_button_pressed(int p_button) const { _THREAD_SAFE_METHOD_ return (mouse_button_mask & (1 << (p_button - 1))) != 0; @@ -90,18 +209,18 @@ static int _combine_device(int p_value, int p_device) { return p_value | (p_device << 20); } -bool InputDefault::is_joy_button_pressed(int p_device, int p_button) const { +bool InputFilter::is_joy_button_pressed(int p_device, int p_button) const { _THREAD_SAFE_METHOD_ return joy_buttons_pressed.has(_combine_device(p_button, p_device)); } -bool InputDefault::is_action_pressed(const StringName &p_action) const { +bool InputFilter::is_action_pressed(const StringName &p_action) const { return action_state.has(p_action) && action_state[p_action].pressed; } -bool InputDefault::is_action_just_pressed(const StringName &p_action) const { +bool InputFilter::is_action_just_pressed(const StringName &p_action) const { const Map<StringName, Action>::Element *E = action_state.find(p_action); if (!E) @@ -114,7 +233,7 @@ bool InputDefault::is_action_just_pressed(const StringName &p_action) const { } } -bool InputDefault::is_action_just_released(const StringName &p_action) const { +bool InputFilter::is_action_just_released(const StringName &p_action) const { const Map<StringName, Action>::Element *E = action_state.find(p_action); if (!E) @@ -127,7 +246,7 @@ bool InputDefault::is_action_just_released(const StringName &p_action) const { } } -float InputDefault::get_action_strength(const StringName &p_action) const { +float InputFilter::get_action_strength(const StringName &p_action) const { const Map<StringName, Action>::Element *E = action_state.find(p_action); if (!E) return 0.0f; @@ -135,7 +254,7 @@ float InputDefault::get_action_strength(const StringName &p_action) const { return E->get().strength; } -float InputDefault::get_joy_axis(int p_device, int p_axis) const { +float InputFilter::get_joy_axis(int p_device, int p_axis) const { _THREAD_SAFE_METHOD_ int c = _combine_device(p_axis, p_device); @@ -146,13 +265,13 @@ float InputDefault::get_joy_axis(int p_device, int p_axis) const { } } -String InputDefault::get_joy_name(int p_idx) { +String InputFilter::get_joy_name(int p_idx) { _THREAD_SAFE_METHOD_ return joy_names[p_idx].name; }; -Vector2 InputDefault::get_joy_vibration_strength(int p_device) { +Vector2 InputFilter::get_joy_vibration_strength(int p_device) { if (joy_vibration.has(p_device)) { return Vector2(joy_vibration[p_device].weak_magnitude, joy_vibration[p_device].strong_magnitude); } else { @@ -160,7 +279,7 @@ Vector2 InputDefault::get_joy_vibration_strength(int p_device) { } } -uint64_t InputDefault::get_joy_vibration_timestamp(int p_device) { +uint64_t InputFilter::get_joy_vibration_timestamp(int p_device) { if (joy_vibration.has(p_device)) { return joy_vibration[p_device].timestamp; } else { @@ -168,7 +287,7 @@ uint64_t InputDefault::get_joy_vibration_timestamp(int p_device) { } } -float InputDefault::get_joy_vibration_duration(int p_device) { +float InputFilter::get_joy_vibration_duration(int p_device) { if (joy_vibration.has(p_device)) { return joy_vibration[p_device].duration; } else { @@ -188,7 +307,7 @@ static String _hex_str(uint8_t p_byte) { return ret; }; -void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) { +void InputFilter::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) { _THREAD_SAFE_METHOD_ Joypad js; @@ -230,36 +349,36 @@ void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_ emit_signal("joy_connection_changed", p_idx, p_connected); }; -Vector3 InputDefault::get_gravity() const { +Vector3 InputFilter::get_gravity() const { _THREAD_SAFE_METHOD_ return gravity; } -Vector3 InputDefault::get_accelerometer() const { +Vector3 InputFilter::get_accelerometer() const { _THREAD_SAFE_METHOD_ return accelerometer; } -Vector3 InputDefault::get_magnetometer() const { +Vector3 InputFilter::get_magnetometer() const { _THREAD_SAFE_METHOD_ return magnetometer; } -Vector3 InputDefault::get_gyroscope() const { +Vector3 InputFilter::get_gyroscope() const { _THREAD_SAFE_METHOD_ return gyroscope; } -void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) { +void InputFilter::parse_input_event(const Ref<InputEvent> &p_event) { _parse_input_event_impl(p_event, false); } -void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) { +void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) { // Notes on mouse-touch emulation: // - Emulated mouse events are parsed, that is, re-routed to this method, so they make the same effects @@ -293,12 +412,12 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool set_mouse_position(pos); } - if (main_loop && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == 1) { + if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mb->get_button_index() == 1) { Ref<InputEventScreenTouch> touch_event; touch_event.instance(); touch_event->set_pressed(mb->is_pressed()); touch_event->set_position(mb->get_position()); - main_loop->input_event(touch_event); + event_dispatch_function(touch_event); } } @@ -311,7 +430,7 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool set_mouse_position(pos); } - if (main_loop && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask() & 1) { + if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && mm->get_button_mask() & 1) { Ref<InputEventScreenDrag> drag_event; drag_event.instance(); @@ -319,7 +438,7 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool drag_event->set_relative(mm->get_relative()); drag_event->set_speed(mm->get_speed()); - main_loop->input_event(drag_event); + event_dispatch_function(drag_event); } } @@ -417,8 +536,8 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool if (ge.is_valid()) { - if (main_loop) { - main_loop->input_event(ge); + if (event_dispatch_function) { + event_dispatch_function(ge); } } @@ -438,18 +557,18 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool } } - if (main_loop) - main_loop->input_event(p_event); + if (event_dispatch_function) + event_dispatch_function(p_event); } -void InputDefault::set_joy_axis(int p_device, int p_axis, float p_value) { +void InputFilter::set_joy_axis(int p_device, int p_axis, float p_value) { _THREAD_SAFE_METHOD_ int c = _combine_device(p_axis, p_device); _joy_axis[c] = p_value; } -void InputDefault::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) { +void InputFilter::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) { _THREAD_SAFE_METHOD_ if (p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { return; @@ -462,7 +581,7 @@ void InputDefault::start_joy_vibration(int p_device, float p_weak_magnitude, flo joy_vibration[p_device] = vibration; } -void InputDefault::stop_joy_vibration(int p_device) { +void InputFilter::stop_joy_vibration(int p_device) { _THREAD_SAFE_METHOD_ VibrationInfo vibration; vibration.weak_magnitude = 0; @@ -472,68 +591,63 @@ void InputDefault::stop_joy_vibration(int p_device) { joy_vibration[p_device] = vibration; } -void InputDefault::vibrate_handheld(int p_duration_ms) { +void InputFilter::vibrate_handheld(int p_duration_ms) { OS::get_singleton()->vibrate_handheld(p_duration_ms); } -void InputDefault::set_gravity(const Vector3 &p_gravity) { +void InputFilter::set_gravity(const Vector3 &p_gravity) { _THREAD_SAFE_METHOD_ gravity = p_gravity; } -void InputDefault::set_accelerometer(const Vector3 &p_accel) { +void InputFilter::set_accelerometer(const Vector3 &p_accel) { _THREAD_SAFE_METHOD_ accelerometer = p_accel; } -void InputDefault::set_magnetometer(const Vector3 &p_magnetometer) { +void InputFilter::set_magnetometer(const Vector3 &p_magnetometer) { _THREAD_SAFE_METHOD_ magnetometer = p_magnetometer; } -void InputDefault::set_gyroscope(const Vector3 &p_gyroscope) { +void InputFilter::set_gyroscope(const Vector3 &p_gyroscope) { _THREAD_SAFE_METHOD_ gyroscope = p_gyroscope; } -void InputDefault::set_main_loop(MainLoop *p_main_loop) { - main_loop = p_main_loop; -} - -void InputDefault::set_mouse_position(const Point2 &p_posf) { +void InputFilter::set_mouse_position(const Point2 &p_posf) { mouse_speed_track.update(p_posf - mouse_pos); mouse_pos = p_posf; } -Point2 InputDefault::get_mouse_position() const { +Point2 InputFilter::get_mouse_position() const { return mouse_pos; } -Point2 InputDefault::get_last_mouse_speed() const { +Point2 InputFilter::get_last_mouse_speed() const { return mouse_speed_track.speed; } -int InputDefault::get_mouse_button_mask() const { +int InputFilter::get_mouse_button_mask() const { return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state(); } -void InputDefault::warp_mouse_position(const Vector2 &p_to) { - - OS::get_singleton()->warp_mouse_position(p_to); +void InputFilter::warp_mouse_position(const Vector2 &p_to) { + warp_mouse_func(p_to); } -Point2i InputDefault::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { +Point2i InputFilter::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { // The relative distance reported for the next event after a warp is in the boundaries of the // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod() @@ -553,16 +667,16 @@ Point2i InputDefault::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_moti const Point2i pos_local = p_motion->get_global_position() - p_rect.position; const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); if (pos_warped != pos_local) { - OS::get_singleton()->warp_mouse_position(pos_warped + p_rect.position); + warp_mouse_position(pos_warped + p_rect.position); } return rel_warped; } -void InputDefault::iteration(float p_step) { +void InputFilter::iteration(float p_step) { } -void InputDefault::action_press(const StringName &p_action, float p_strength) { +void InputFilter::action_press(const StringName &p_action, float p_strength) { Action action; @@ -574,7 +688,7 @@ void InputDefault::action_press(const StringName &p_action, float p_strength) { action_state[p_action] = action; } -void InputDefault::action_release(const StringName &p_action) { +void InputFilter::action_release(const StringName &p_action) { Action action; @@ -586,19 +700,19 @@ void InputDefault::action_release(const StringName &p_action) { action_state[p_action] = action; } -void InputDefault::set_emulate_touch_from_mouse(bool p_emulate) { +void InputFilter::set_emulate_touch_from_mouse(bool p_emulate) { emulate_touch_from_mouse = p_emulate; } -bool InputDefault::is_emulating_touch_from_mouse() const { +bool InputFilter::is_emulating_touch_from_mouse() const { return emulate_touch_from_mouse; } // Calling this whenever the game window is focused helps unstucking the "touch mouse" // if the OS or its abstraction class hasn't properly reported that touch pointers raised -void InputDefault::ensure_touch_mouse_raised() { +void InputFilter::ensure_touch_mouse_raised() { if (mouse_from_touch_index != -1) { mouse_from_touch_index = -1; @@ -617,22 +731,22 @@ void InputDefault::ensure_touch_mouse_raised() { } } -void InputDefault::set_emulate_mouse_from_touch(bool p_emulate) { +void InputFilter::set_emulate_mouse_from_touch(bool p_emulate) { emulate_mouse_from_touch = p_emulate; } -bool InputDefault::is_emulating_mouse_from_touch() const { +bool InputFilter::is_emulating_mouse_from_touch() const { return emulate_mouse_from_touch; } -Input::CursorShape InputDefault::get_default_cursor_shape() const { +InputFilter::CursorShape InputFilter::get_default_cursor_shape() const { return default_shape; } -void InputDefault::set_default_cursor_shape(CursorShape p_shape) { +void InputFilter::set_default_cursor_shape(CursorShape p_shape) { if (default_shape == p_shape) return; @@ -647,19 +761,19 @@ void InputDefault::set_default_cursor_shape(CursorShape p_shape) { parse_input_event(mm); } -Input::CursorShape InputDefault::get_current_cursor_shape() const { +InputFilter::CursorShape InputFilter::get_current_cursor_shape() const { - return (Input::CursorShape)OS::get_singleton()->get_cursor_shape(); + return get_current_cursor_shape_func(); } -void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +void InputFilter::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { if (Engine::get_singleton()->is_editor_hint()) return; - OS::get_singleton()->set_custom_mouse_cursor(p_cursor, (OS::CursorShape)p_shape, p_hotspot); + set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot); } -void InputDefault::accumulate_input_event(const Ref<InputEvent> &p_event) { +void InputFilter::accumulate_input_event(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!use_accumulated_input) { @@ -672,7 +786,7 @@ void InputDefault::accumulate_input_event(const Ref<InputEvent> &p_event) { accumulated_events.push_back(p_event); } -void InputDefault::flush_accumulated_events() { +void InputFilter::flush_accumulated_events() { while (accumulated_events.front()) { parse_input_event(accumulated_events.front()->get()); @@ -680,12 +794,12 @@ void InputDefault::flush_accumulated_events() { } } -void InputDefault::set_use_accumulated_input(bool p_enable) { +void InputFilter::set_use_accumulated_input(bool p_enable) { use_accumulated_input = p_enable; } -void InputDefault::release_pressed_events() { +void InputFilter::release_pressed_events() { flush_accumulated_events(); // this is needed to release actions strengths @@ -693,61 +807,17 @@ void InputDefault::release_pressed_events() { joy_buttons_pressed.clear(); _joy_axis.clear(); - for (Map<StringName, InputDefault::Action>::Element *E = action_state.front(); E; E = E->next()) { + for (Map<StringName, InputFilter::Action>::Element *E = action_state.front(); E; E = E->next()) { if (E->get().pressed) action_release(E->key()); } } -InputDefault::InputDefault() { - - use_accumulated_input = true; - mouse_button_mask = 0; - emulate_touch_from_mouse = false; - emulate_mouse_from_touch = false; - mouse_from_touch_index = -1; - main_loop = NULL; - default_shape = CURSOR_ARROW; - - hat_map_default[HAT_UP].type = TYPE_BUTTON; - hat_map_default[HAT_UP].index = JOY_DPAD_UP; - hat_map_default[HAT_UP].value = 0; - - hat_map_default[HAT_RIGHT].type = TYPE_BUTTON; - hat_map_default[HAT_RIGHT].index = JOY_DPAD_RIGHT; - hat_map_default[HAT_RIGHT].value = 0; - - hat_map_default[HAT_DOWN].type = TYPE_BUTTON; - hat_map_default[HAT_DOWN].index = JOY_DPAD_DOWN; - hat_map_default[HAT_DOWN].value = 0; - - hat_map_default[HAT_LEFT].type = TYPE_BUTTON; - hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT; - hat_map_default[HAT_LEFT].value = 0; - - fallback_mapping = -1; - - // Parse default mappings. - { - int i = 0; - while (DefaultControllerMappings::mappings[i]) { - parse_mapping(DefaultControllerMappings::mappings[i++]); - } - } - - // If defined, parse SDL_GAMECONTROLLERCONFIG for possible new mappings/overrides. - String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG"); - if (env_mapping != "") { - Vector<String> entries = env_mapping.split("\n"); - for (int i = 0; i < entries.size(); i++) { - if (entries[i] == "") - continue; - parse_mapping(entries[i]); - } - } +void InputFilter::set_event_dispatch_function(EventDispatchFunc p_function) { + event_dispatch_function = p_function; } -void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) { +void InputFilter::joy_button(int p_device, int p_button, bool p_pressed) { _THREAD_SAFE_METHOD_; Joypad &joy = joy_names[p_device]; @@ -786,7 +856,7 @@ void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) { // no event? } -void InputDefault::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { +void InputFilter::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { _THREAD_SAFE_METHOD_; @@ -901,7 +971,7 @@ void InputDefault::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { //printf("invalid mapping\n"); } -void InputDefault::joy_hat(int p_device, int p_val) { +void InputFilter::joy_hat(int p_device, int p_val) { _THREAD_SAFE_METHOD_; const Joypad &joy = joy_names[p_device]; @@ -933,7 +1003,7 @@ void InputDefault::joy_hat(int p_device, int p_val) { joy_names[p_device].hat_current = p_val; } -void InputDefault::_button_event(int p_device, int p_index, bool p_pressed) { +void InputFilter::_button_event(int p_device, int p_index, bool p_pressed) { Ref<InputEventJoypadButton> ievent; ievent.instance(); @@ -944,7 +1014,7 @@ void InputDefault::_button_event(int p_device, int p_index, bool p_pressed) { parse_input_event(ievent); } -void InputDefault::_axis_event(int p_device, int p_axis, float p_value) { +void InputFilter::_axis_event(int p_device, int p_axis, float p_value) { Ref<InputEventJoypadMotion> ievent; ievent.instance(); @@ -955,7 +1025,7 @@ void InputDefault::_axis_event(int p_device, int p_axis, float p_value) { parse_input_event(ievent); }; -InputDefault::JoyEvent InputDefault::_find_to_event(String p_to) { +InputFilter::JoyEvent InputFilter::_find_to_event(String p_to) { // string names of the SDL buttons in the same order as input_event.h godot buttons static const char *buttons[] = { "a", "b", "x", "y", "leftshoulder", "rightshoulder", "lefttrigger", "righttrigger", "leftstick", "rightstick", "back", "start", "dpup", "dpdown", "dpleft", "dpright", "guide", NULL }; @@ -993,7 +1063,7 @@ InputDefault::JoyEvent InputDefault::_find_to_event(String p_to) { return ret; }; -void InputDefault::parse_mapping(String p_mapping) { +void InputFilter::parse_mapping(String p_mapping) { _THREAD_SAFE_METHOD_; JoyDeviceMapping mapping; @@ -1058,7 +1128,7 @@ void InputDefault::parse_mapping(String p_mapping) { //printf("added mapping with uuid %ls\n", mapping.uid.c_str()); }; -void InputDefault::add_joy_mapping(String p_mapping, bool p_update_existing) { +void InputFilter::add_joy_mapping(String p_mapping, bool p_update_existing) { parse_mapping(p_mapping); if (p_update_existing) { Vector<String> entry = p_mapping.split(","); @@ -1071,7 +1141,7 @@ void InputDefault::add_joy_mapping(String p_mapping, bool p_update_existing) { } } -void InputDefault::remove_joy_mapping(String p_guid) { +void InputFilter::remove_joy_mapping(String p_guid) { for (int i = map_db.size() - 1; i >= 0; i--) { if (p_guid == map_db[i].uid) { map_db.remove(i); @@ -1084,7 +1154,7 @@ void InputDefault::remove_joy_mapping(String p_guid) { } } -void InputDefault::set_fallback_mapping(String p_guid) { +void InputFilter::set_fallback_mapping(String p_guid) { for (int i = 0; i < map_db.size(); i++) { if (map_db[i].uid == p_guid) { @@ -1094,28 +1164,18 @@ void InputDefault::set_fallback_mapping(String p_guid) { } } -//Defaults to simple implementation for platforms with a fixed gamepad layout, like consoles. -bool InputDefault::is_joy_known(int p_device) { - - return OS::get_singleton()->is_joy_known(p_device); -} - -String InputDefault::get_joy_guid(int p_device) const { - return OS::get_singleton()->get_joy_guid(p_device); -} - //platforms that use the remapping system can override and call to these ones -bool InputDefault::is_joy_mapped(int p_device) { +bool InputFilter::is_joy_known(int p_device) { int mapping = joy_names[p_device].mapping; return mapping != -1 ? (mapping != fallback_mapping) : false; } -String InputDefault::get_joy_guid_remapped(int p_device) const { +String InputFilter::get_joy_guid(int p_device) const { ERR_FAIL_COND_V(!joy_names.has(p_device), ""); return joy_names[p_device].uid; } -Array InputDefault::get_connected_joypads() { +Array InputFilter::get_connected_joypads() { Array ret; Map<int, Joypad>::Element *elem = joy_names.front(); while (elem) { @@ -1159,12 +1219,12 @@ static const char *_axes[JOY_AXIS_MAX] = { "" }; -String InputDefault::get_joy_button_string(int p_button) { +String InputFilter::get_joy_button_string(int p_button) { ERR_FAIL_INDEX_V(p_button, JOY_BUTTON_MAX, ""); return _buttons[p_button]; } -int InputDefault::get_joy_button_index_from_string(String p_button) { +int InputFilter::get_joy_button_index_from_string(String p_button) { for (int i = 0; i < JOY_BUTTON_MAX; i++) { if (p_button == _buttons[i]) { return i; @@ -1173,7 +1233,7 @@ int InputDefault::get_joy_button_index_from_string(String p_button) { ERR_FAIL_V(-1); } -int InputDefault::get_unused_joy_id() { +int InputFilter::get_unused_joy_id() { for (int i = 0; i < JOYPADS_MAX; i++) { if (!joy_names.has(i) || !joy_names[i].connected) { return i; @@ -1182,12 +1242,12 @@ int InputDefault::get_unused_joy_id() { return -1; } -String InputDefault::get_joy_axis_string(int p_axis) { +String InputFilter::get_joy_axis_string(int p_axis) { ERR_FAIL_INDEX_V(p_axis, JOY_AXIS_MAX, ""); return _axes[p_axis]; } -int InputDefault::get_joy_axis_index_from_string(String p_axis) { +int InputFilter::get_joy_axis_index_from_string(String p_axis) { for (int i = 0; i < JOY_AXIS_MAX; i++) { if (p_axis == _axes[i]) { return i; @@ -1195,3 +1255,55 @@ int InputDefault::get_joy_axis_index_from_string(String p_axis) { } ERR_FAIL_V(-1); } + +InputFilter::InputFilter() { + + singleton = this; + use_accumulated_input = true; + mouse_button_mask = 0; + mouse_window = 0; + emulate_touch_from_mouse = false; + emulate_mouse_from_touch = false; + mouse_from_touch_index = -1; + event_dispatch_function = nullptr; + default_shape = CURSOR_ARROW; + + hat_map_default[HAT_UP].type = TYPE_BUTTON; + hat_map_default[HAT_UP].index = JOY_DPAD_UP; + hat_map_default[HAT_UP].value = 0; + + hat_map_default[HAT_RIGHT].type = TYPE_BUTTON; + hat_map_default[HAT_RIGHT].index = JOY_DPAD_RIGHT; + hat_map_default[HAT_RIGHT].value = 0; + + hat_map_default[HAT_DOWN].type = TYPE_BUTTON; + hat_map_default[HAT_DOWN].index = JOY_DPAD_DOWN; + hat_map_default[HAT_DOWN].value = 0; + + hat_map_default[HAT_LEFT].type = TYPE_BUTTON; + hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT; + hat_map_default[HAT_LEFT].value = 0; + + fallback_mapping = -1; + + // Parse default mappings. + { + int i = 0; + while (DefaultControllerMappings::mappings[i]) { + parse_mapping(DefaultControllerMappings::mappings[i++]); + } + } + + // If defined, parse SDL_GAMECONTROLLERCONFIG for possible new mappings/overrides. + String env_mapping = OS::get_singleton()->get_environment("SDL_GAMECONTROLLERCONFIG"); + if (env_mapping != "") { + Vector<String> entries = env_mapping.split("\n"); + for (int i = 0; i < entries.size(); i++) { + if (entries[i] == "") + continue; + parse_mapping(entries[i]); + } + } +} + +////////////////////////////////////////////////////////// diff --git a/main/input_default.h b/core/input/input_filter.h index 0ec31d417b..908a005228 100644 --- a/main/input_default.h +++ b/core/input/input_filter.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* input_default.h */ +/* input_filter.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,78 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef INPUT_DEFAULT_H -#define INPUT_DEFAULT_H +#ifndef INPUT_H +#define INPUT_H -#include "core/os/input.h" +#include "core/input/input_event.h" +#include "core/object.h" +#include "core/os/thread_safe.h" -class InputDefault : public Input { +class InputFilter : public Object { - GDCLASS(InputDefault, Input); + GDCLASS(InputFilter, Object); _THREAD_SAFE_CLASS_ + static InputFilter *singleton; + +public: + enum MouseMode { + MOUSE_MODE_VISIBLE, + MOUSE_MODE_HIDDEN, + MOUSE_MODE_CAPTURED, + MOUSE_MODE_CONFINED + }; + +#undef CursorShape + enum CursorShape { + CURSOR_ARROW, + CURSOR_IBEAM, + CURSOR_POINTING_HAND, + CURSOR_CROSS, + CURSOR_WAIT, + CURSOR_BUSY, + CURSOR_DRAG, + CURSOR_CAN_DROP, + CURSOR_FORBIDDEN, + CURSOR_VSIZE, + CURSOR_HSIZE, + CURSOR_BDIAGSIZE, + CURSOR_FDIAGSIZE, + CURSOR_MOVE, + CURSOR_VSPLIT, + CURSOR_HSPLIT, + CURSOR_HELP, + CURSOR_MAX + }; + + enum HatMask { + HAT_MASK_CENTER = 0, + HAT_MASK_UP = 1, + HAT_MASK_RIGHT = 2, + HAT_MASK_DOWN = 4, + HAT_MASK_LEFT = 8, + }; + + enum HatDir { + HAT_UP, + HAT_RIGHT, + HAT_DOWN, + HAT_LEFT, + HAT_MAX, + }; + + enum { + JOYPADS_MAX = 16, + }; + + struct JoyAxis { + int min; + float value; + }; + + typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event); + +private: int mouse_button_mask; Set<int> keys_pressed; @@ -49,7 +111,7 @@ class InputDefault : public Input { Vector3 magnetometer; Vector3 gyroscope; Vector2 mouse_pos; - MainLoop *main_loop; + int64_t mouse_window; struct Action { uint64_t physics_frame; @@ -123,33 +185,6 @@ class InputDefault : public Input { CursorShape default_shape; -public: - enum HatMask { - HAT_MASK_CENTER = 0, - HAT_MASK_UP = 1, - HAT_MASK_RIGHT = 2, - HAT_MASK_DOWN = 4, - HAT_MASK_LEFT = 8, - }; - - enum HatDir { - HAT_UP, - HAT_RIGHT, - HAT_DOWN, - HAT_LEFT, - HAT_MAX, - }; - - enum { - JOYPADS_MAX = 16, - }; - - struct JoyAxis { - int min; - float value; - }; - -private: enum JoyType { TYPE_BUTTON, TYPE_AXIS, @@ -185,38 +220,57 @@ private: List<Ref<InputEvent>> accumulated_events; bool use_accumulated_input; + friend class DisplayServer; + + static void (*set_mouse_mode_func)(MouseMode); + static MouseMode (*get_mouse_mode_func)(); + static void (*warp_mouse_func)(const Vector2 &p_to_pos); + + static CursorShape (*get_current_cursor_shape_func)(); + static void (*set_custom_mouse_cursor_func)(const RES &, CursorShape, const Vector2 &); + + EventDispatchFunc event_dispatch_function; + +protected: + static void _bind_methods(); public: - virtual bool is_key_pressed(int p_keycode) const; - virtual bool is_mouse_button_pressed(int p_button) const; - virtual bool is_joy_button_pressed(int p_device, int p_button) const; - virtual bool is_action_pressed(const StringName &p_action) const; - virtual bool is_action_just_pressed(const StringName &p_action) const; - virtual bool is_action_just_released(const StringName &p_action) const; - virtual float get_action_strength(const StringName &p_action) const; - - virtual float get_joy_axis(int p_device, int p_axis) const; + void set_mouse_mode(MouseMode p_mode); + MouseMode get_mouse_mode() const; + void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; + + static InputFilter *get_singleton(); + + bool is_key_pressed(int p_keycode) const; + bool is_mouse_button_pressed(int p_button) const; + bool is_joy_button_pressed(int p_device, int p_button) const; + bool is_action_pressed(const StringName &p_action) const; + bool is_action_just_pressed(const StringName &p_action) const; + bool is_action_just_released(const StringName &p_action) const; + float get_action_strength(const StringName &p_action) const; + + float get_joy_axis(int p_device, int p_axis) const; String get_joy_name(int p_idx); - virtual Array get_connected_joypads(); - virtual Vector2 get_joy_vibration_strength(int p_device); - virtual float get_joy_vibration_duration(int p_device); - virtual uint64_t get_joy_vibration_timestamp(int p_device); + Array get_connected_joypads(); + Vector2 get_joy_vibration_strength(int p_device); + float get_joy_vibration_duration(int p_device); + uint64_t get_joy_vibration_timestamp(int p_device); void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = ""); void parse_joypad_mapping(String p_mapping, bool p_update_existing); - virtual Vector3 get_gravity() const; - virtual Vector3 get_accelerometer() const; - virtual Vector3 get_magnetometer() const; - virtual Vector3 get_gyroscope() const; + Vector3 get_gravity() const; + Vector3 get_accelerometer() const; + Vector3 get_magnetometer() const; + Vector3 get_gyroscope() const; - virtual Point2 get_mouse_position() const; - virtual Point2 get_last_mouse_speed() const; - virtual int get_mouse_button_mask() const; + Point2 get_mouse_position() const; + Point2 get_last_mouse_speed() const; + int get_mouse_button_mask() const; - virtual void warp_mouse_position(const Vector2 &p_to); - virtual Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); + void warp_mouse_position(const Vector2 &p_to); + Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect); - virtual void parse_input_event(const Ref<InputEvent> &p_event); + void parse_input_event(const Ref<InputEvent> &p_event); void set_gravity(const Vector3 &p_gravity); void set_accelerometer(const Vector3 &p_accel); @@ -224,11 +278,10 @@ public: void set_gyroscope(const Vector3 &p_gyroscope); void set_joy_axis(int p_device, int p_axis, float p_value); - virtual void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0); - virtual void stop_joy_vibration(int p_device); - virtual void vibrate_handheld(int p_duration_ms = 500); + void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0); + void stop_joy_vibration(int p_device); + void vibrate_handheld(int p_duration_ms = 500); - void set_main_loop(MainLoop *p_main_loop); void set_mouse_position(const Point2 &p_posf); void action_press(const StringName &p_action, float p_strength = 1.f); @@ -237,44 +290,48 @@ public: void iteration(float p_step); void set_emulate_touch_from_mouse(bool p_emulate); - virtual bool is_emulating_touch_from_mouse() const; + bool is_emulating_touch_from_mouse() const; void ensure_touch_mouse_raised(); void set_emulate_mouse_from_touch(bool p_emulate); - virtual bool is_emulating_mouse_from_touch() const; + bool is_emulating_mouse_from_touch() const; - virtual CursorShape get_default_cursor_shape() const; - virtual void set_default_cursor_shape(CursorShape p_shape); - virtual CursorShape get_current_cursor_shape() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); + CursorShape get_default_cursor_shape() const; + void set_default_cursor_shape(CursorShape p_shape); + CursorShape get_current_cursor_shape() const; + void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = InputFilter::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); void parse_mapping(String p_mapping); void joy_button(int p_device, int p_button, bool p_pressed); void joy_axis(int p_device, int p_axis, const JoyAxis &p_value); void joy_hat(int p_device, int p_val); - virtual void add_joy_mapping(String p_mapping, bool p_update_existing = false); - virtual void remove_joy_mapping(String p_guid); - virtual bool is_joy_known(int p_device); - virtual String get_joy_guid(int p_device) const; + void add_joy_mapping(String p_mapping, bool p_update_existing = false); + void remove_joy_mapping(String p_guid); - virtual String get_joy_button_string(int p_button); - virtual String get_joy_axis_string(int p_axis); - virtual int get_joy_axis_index_from_string(String p_axis); - virtual int get_joy_button_index_from_string(String p_button); + String get_joy_button_string(int p_button); + String get_joy_axis_string(int p_axis); + int get_joy_axis_index_from_string(String p_axis); + int get_joy_button_index_from_string(String p_button); int get_unused_joy_id(); - bool is_joy_mapped(int p_device); - String get_joy_guid_remapped(int p_device) const; + bool is_joy_known(int p_device); + String get_joy_guid(int p_device) const; void set_fallback_mapping(String p_guid); - virtual void accumulate_input_event(const Ref<InputEvent> &p_event); - virtual void flush_accumulated_events(); - virtual void set_use_accumulated_input(bool p_enable); + void accumulate_input_event(const Ref<InputEvent> &p_event); + void flush_accumulated_events(); + void set_use_accumulated_input(bool p_enable); + + void release_pressed_events(); - virtual void release_pressed_events(); - InputDefault(); + void set_event_dispatch_function(EventDispatchFunc p_function); + + InputFilter(); }; -#endif // INPUT_DEFAULT_H +VARIANT_ENUM_CAST(InputFilter::MouseMode); +VARIANT_ENUM_CAST(InputFilter::CursorShape); + +#endif // INPUT_H diff --git a/core/input_map.cpp b/core/input/input_map.cpp index 8f18c082d6..8f18c082d6 100644 --- a/core/input_map.cpp +++ b/core/input/input_map.cpp diff --git a/core/input_map.h b/core/input/input_map.h index 6039d915c9..de6f57b0bf 100644 --- a/core/input_map.h +++ b/core/input/input_map.h @@ -31,8 +31,8 @@ #ifndef INPUT_MAP_H #define INPUT_MAP_H +#include "core/input/input_event.h" #include "core/object.h" -#include "core/os/input_event.h" class InputMap : public Object { diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h index d09242e2f1..7ae0a788bd 100644 --- a/core/method_ptrcall.h +++ b/core/method_ptrcall.h @@ -118,6 +118,9 @@ MAKE_PTRARG(String); MAKE_PTRARG(Vector2); MAKE_PTRARG(Rect2); MAKE_PTRARG_BY_REFERENCE(Vector3); +MAKE_PTRARG(Vector2i); +MAKE_PTRARG(Rect2i); +MAKE_PTRARG_BY_REFERENCE(Vector3i); MAKE_PTRARG(Transform2D); MAKE_PTRARG_BY_REFERENCE(Plane); MAKE_PTRARG(Quat); diff --git a/core/os/input.cpp b/core/os/input.cpp deleted file mode 100644 index 1768b851df..0000000000 --- a/core/os/input.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/*************************************************************************/ -/* input.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "input.h" - -#include "core/input_map.h" -#include "core/os/os.h" -#include "core/project_settings.h" - -#ifdef TOOLS_ENABLED -#include "editor/editor_settings.h" -#endif - -Input *Input::singleton = NULL; - -Input *Input::get_singleton() { - - return singleton; -} - -void Input::set_mouse_mode(MouseMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 4); - OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode); -} - -Input::MouseMode Input::get_mouse_mode() const { - - return (MouseMode)OS::get_singleton()->get_mouse_mode(); -} - -void Input::_bind_methods() { - - ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed); - ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed); - ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed); - ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_pressed); - ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed); - ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released); - ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength); - ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping); - ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed); - ClassDB::bind_method(D_METHOD("is_joy_known", "device"), &Input::is_joy_known); - ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis); - ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name); - ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &Input::get_joy_guid); - ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads); - ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength); - ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration); - ClassDB::bind_method(D_METHOD("get_joy_button_string", "button_index"), &Input::get_joy_button_string); - ClassDB::bind_method(D_METHOD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string); - ClassDB::bind_method(D_METHOD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string); - ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string); - ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); - ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &Input::vibrate_handheld, DEFVAL(500)); - ClassDB::bind_method(D_METHOD("get_gravity"), &Input::get_gravity); - ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer); - ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer); - ClassDB::bind_method(D_METHOD("get_gyroscope"), &Input::get_gyroscope); - //ClassDB::bind_method(D_METHOD("get_mouse_position"),&Input::get_mouse_position); - this is not the function you want - ClassDB::bind_method(D_METHOD("get_last_mouse_speed"), &Input::get_last_mouse_speed); - ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask); - ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode); - ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode); - ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position); - ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f)); - ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release); - ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW)); - ClassDB::bind_method(D_METHOD("get_current_cursor_shape"), &Input::get_current_cursor_shape); - ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); - ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); - ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input); - - BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); - BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); - BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); - BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); - - BIND_ENUM_CONSTANT(CURSOR_ARROW); - BIND_ENUM_CONSTANT(CURSOR_IBEAM); - BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND); - BIND_ENUM_CONSTANT(CURSOR_CROSS); - BIND_ENUM_CONSTANT(CURSOR_WAIT); - BIND_ENUM_CONSTANT(CURSOR_BUSY); - BIND_ENUM_CONSTANT(CURSOR_DRAG); - BIND_ENUM_CONSTANT(CURSOR_CAN_DROP); - BIND_ENUM_CONSTANT(CURSOR_FORBIDDEN); - BIND_ENUM_CONSTANT(CURSOR_VSIZE); - BIND_ENUM_CONSTANT(CURSOR_HSIZE); - BIND_ENUM_CONSTANT(CURSOR_BDIAGSIZE); - BIND_ENUM_CONSTANT(CURSOR_FDIAGSIZE); - BIND_ENUM_CONSTANT(CURSOR_MOVE); - BIND_ENUM_CONSTANT(CURSOR_VSPLIT); - BIND_ENUM_CONSTANT(CURSOR_HSPLIT); - BIND_ENUM_CONSTANT(CURSOR_HELP); - - ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "device"), PropertyInfo(Variant::BOOL, "connected"))); -} - -void Input::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { -#ifdef TOOLS_ENABLED - - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; - - String pf = p_function; - if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) { - - List<PropertyInfo> pinfo; - ProjectSettings::get_singleton()->get_property_list(&pinfo); - - for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - const PropertyInfo &pi = E->get(); - - if (!pi.name.begins_with("input/")) - continue; - - String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); - r_options->push_back(quote_style + name + quote_style); - } - } -#endif -} - -Input::Input() { - - singleton = this; -} - -////////////////////////////////////////////////////////// diff --git a/core/os/input.h b/core/os/input.h deleted file mode 100644 index 55e0511080..0000000000 --- a/core/os/input.h +++ /dev/null @@ -1,146 +0,0 @@ -/*************************************************************************/ -/* input.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef INPUT_H -#define INPUT_H - -#include "core/object.h" -#include "core/os/main_loop.h" -#include "core/os/thread_safe.h" - -class Input : public Object { - - GDCLASS(Input, Object); - - static Input *singleton; - -protected: - static void _bind_methods(); - -public: - enum MouseMode { - MOUSE_MODE_VISIBLE, - MOUSE_MODE_HIDDEN, - MOUSE_MODE_CAPTURED, - MOUSE_MODE_CONFINED - }; - -#undef CursorShape - enum CursorShape { - CURSOR_ARROW, - CURSOR_IBEAM, - CURSOR_POINTING_HAND, - CURSOR_CROSS, - CURSOR_WAIT, - CURSOR_BUSY, - CURSOR_DRAG, - CURSOR_CAN_DROP, - CURSOR_FORBIDDEN, - CURSOR_VSIZE, - CURSOR_HSIZE, - CURSOR_BDIAGSIZE, - CURSOR_FDIAGSIZE, - CURSOR_MOVE, - CURSOR_VSPLIT, - CURSOR_HSPLIT, - CURSOR_HELP, - CURSOR_MAX - }; - - void set_mouse_mode(MouseMode p_mode); - MouseMode get_mouse_mode() const; - - static Input *get_singleton(); - - virtual bool is_key_pressed(int p_keycode) const = 0; - virtual bool is_mouse_button_pressed(int p_button) const = 0; - virtual bool is_joy_button_pressed(int p_device, int p_button) const = 0; - virtual bool is_action_pressed(const StringName &p_action) const = 0; - virtual bool is_action_just_pressed(const StringName &p_action) const = 0; - virtual bool is_action_just_released(const StringName &p_action) const = 0; - virtual float get_action_strength(const StringName &p_action) const = 0; - - virtual float get_joy_axis(int p_device, int p_axis) const = 0; - virtual String get_joy_name(int p_idx) = 0; - virtual Array get_connected_joypads() = 0; - virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) = 0; - virtual void add_joy_mapping(String p_mapping, bool p_update_existing = false) = 0; - virtual void remove_joy_mapping(String p_guid) = 0; - virtual bool is_joy_known(int p_device) = 0; - virtual String get_joy_guid(int p_device) const = 0; - virtual Vector2 get_joy_vibration_strength(int p_device) = 0; - virtual float get_joy_vibration_duration(int p_device) = 0; - virtual uint64_t get_joy_vibration_timestamp(int p_device) = 0; - virtual void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration = 0) = 0; - virtual void stop_joy_vibration(int p_device) = 0; - virtual void vibrate_handheld(int p_duration_ms = 500) = 0; - - virtual Point2 get_mouse_position() const = 0; - virtual Point2 get_last_mouse_speed() const = 0; - virtual int get_mouse_button_mask() const = 0; - - virtual void warp_mouse_position(const Vector2 &p_to) = 0; - virtual Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) = 0; - - virtual Vector3 get_gravity() const = 0; - virtual Vector3 get_accelerometer() const = 0; - virtual Vector3 get_magnetometer() const = 0; - virtual Vector3 get_gyroscope() const = 0; - - virtual void action_press(const StringName &p_action, float p_strength = 1.f) = 0; - virtual void action_release(const StringName &p_action) = 0; - - void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; - - virtual bool is_emulating_touch_from_mouse() const = 0; - virtual bool is_emulating_mouse_from_touch() const = 0; - - virtual CursorShape get_default_cursor_shape() const = 0; - virtual void set_default_cursor_shape(CursorShape p_shape) = 0; - virtual CursorShape get_current_cursor_shape() const = 0; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) = 0; - - virtual String get_joy_button_string(int p_button) = 0; - virtual String get_joy_axis_string(int p_axis) = 0; - virtual int get_joy_button_index_from_string(String p_button) = 0; - virtual int get_joy_axis_index_from_string(String p_axis) = 0; - - virtual void parse_input_event(const Ref<InputEvent> &p_event) = 0; - virtual void accumulate_input_event(const Ref<InputEvent> &p_event) = 0; - virtual void flush_accumulated_events() = 0; - virtual void set_use_accumulated_input(bool p_enable) = 0; - - Input(); -}; - -VARIANT_ENUM_CAST(Input::MouseMode); -VARIANT_ENUM_CAST(Input::CursorShape); - -#endif // INPUT_H diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index ab43ce4af7..0d1a080682 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -34,30 +34,16 @@ void MainLoop::_bind_methods() { - ClassDB::bind_method(D_METHOD("input_event", "event"), &MainLoop::input_event); - ClassDB::bind_method(D_METHOD("input_text", "text"), &MainLoop::input_text); ClassDB::bind_method(D_METHOD("init"), &MainLoop::init); ClassDB::bind_method(D_METHOD("iteration", "delta"), &MainLoop::iteration); ClassDB::bind_method(D_METHOD("idle", "delta"), &MainLoop::idle); ClassDB::bind_method(D_METHOD("finish"), &MainLoop::finish); - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); - BIND_VMETHOD(MethodInfo("_input_text", PropertyInfo(Variant::STRING, "text"))); BIND_VMETHOD(MethodInfo("_initialize")); BIND_VMETHOD(MethodInfo(Variant::BOOL, "_iteration", PropertyInfo(Variant::FLOAT, "delta"))); BIND_VMETHOD(MethodInfo(Variant::BOOL, "_idle", PropertyInfo(Variant::FLOAT, "delta"))); - BIND_VMETHOD(MethodInfo("_drop_files", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "from_screen"))); BIND_VMETHOD(MethodInfo("_finalize")); - BIND_VMETHOD(MethodInfo("_global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta"))); - - BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER); - BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT); - BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); - BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); - BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST); - BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST); - BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST); BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING); BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED); BIND_CONSTANT(NOTIFICATION_WM_ABOUT); @@ -80,18 +66,6 @@ MainLoop::MainLoop() { MainLoop::~MainLoop() { } -void MainLoop::input_text(const String &p_text) { - - if (get_script_instance()) - get_script_instance()->call("_input_text", p_text); -} - -void MainLoop::input_event(const Ref<InputEvent> &p_event) { - - if (get_script_instance()) - get_script_instance()->call("_input_event", p_event); -} - void MainLoop::init() { if (init_script.is_valid()) @@ -115,18 +89,6 @@ bool MainLoop::idle(float p_time) { return false; } -void MainLoop::drop_files(const Vector<String> &p_files, int p_from_screen) { - - if (get_script_instance()) - get_script_instance()->call("_drop_files", p_files, p_from_screen); -} - -void MainLoop::global_menu_action(const Variant &p_id, const Variant &p_meta) { - - if (get_script_instance()) - get_script_instance()->call("_global_menu_action", p_id, p_meta); -} - void MainLoop::finish() { if (get_script_instance()) { diff --git a/core/os/main_loop.h b/core/os/main_loop.h index 3fdfb77af2..8f6c8c91b1 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -31,7 +31,7 @@ #ifndef MAIN_LOOP_H #define MAIN_LOOP_H -#include "core/os/input_event.h" +#include "core/input/input_event.h" #include "core/reference.h" #include "core/script_language.h" @@ -48,33 +48,20 @@ protected: public: enum { //make sure these are replicated in Node - NOTIFICATION_WM_MOUSE_ENTER = 1002, - NOTIFICATION_WM_MOUSE_EXIT = 1003, - NOTIFICATION_WM_FOCUS_IN = 1004, - NOTIFICATION_WM_FOCUS_OUT = 1005, - NOTIFICATION_WM_QUIT_REQUEST = 1006, - NOTIFICATION_WM_GO_BACK_REQUEST = 1007, - NOTIFICATION_WM_UNFOCUS_REQUEST = 1008, - NOTIFICATION_OS_MEMORY_WARNING = 1009, - NOTIFICATION_TRANSLATION_CHANGED = 1010, - NOTIFICATION_WM_ABOUT = 1011, - NOTIFICATION_CRASH = 1012, - NOTIFICATION_OS_IME_UPDATE = 1013, - NOTIFICATION_APP_RESUMED = 1014, - NOTIFICATION_APP_PAUSED = 1015, + NOTIFICATION_OS_MEMORY_WARNING = 2009, + NOTIFICATION_TRANSLATION_CHANGED = 2010, + NOTIFICATION_WM_ABOUT = 2011, + NOTIFICATION_CRASH = 2012, + NOTIFICATION_OS_IME_UPDATE = 2013, + NOTIFICATION_APP_RESUMED = 2014, + NOTIFICATION_APP_PAUSED = 2015, }; - virtual void input_event(const Ref<InputEvent> &p_event); - virtual void input_text(const String &p_text); - virtual void init(); virtual bool iteration(float p_time); virtual bool idle(float p_time); virtual void finish(); - virtual void drop_files(const Vector<String> &p_files, int p_from_screen = 0); - virtual void global_menu_action(const Variant &p_id, const Variant &p_meta); - void set_init_script(const Ref<Script> &p_init_script); MainLoop(); diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index 6ebec50ff0..c23ade3088 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -30,8 +30,8 @@ #include "midi_driver.h" +#include "core/input/input_filter.h" #include "core/os/os.h" -#include "main/input_default.h" uint8_t MIDIDriver::last_received_message = 0x00; MIDIDriver *MIDIDriver::singleton = NULL; @@ -117,7 +117,7 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ break; } - InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); + InputFilter *id = InputFilter::get_singleton(); id->parse_input_event(event); } diff --git a/core/os/os.cpp b/core/os/os.cpp index 9a65d537ac..66ab3bbd8c 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -30,9 +30,9 @@ #include "os.h" +#include "core/input/input_filter.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" -#include "core/os/input.h" #include "core/os/midi_driver.h" #include "core/project_settings.h" #include "core/version_generated.gen.h" @@ -139,14 +139,6 @@ void OS::printerr(const char *p_format, ...) { va_end(argp); }; -void OS::set_keep_screen_on(bool p_enabled) { - _keep_screen_on = p_enabled; -} - -bool OS::is_keep_screen_on() const { - return _keep_screen_on; -} - void OS::set_low_processor_usage_mode(bool p_enabled) { low_processor_usage_mode = p_enabled; @@ -167,15 +159,6 @@ int OS::get_low_processor_usage_mode_sleep_usec() const { return low_processor_usage_mode_sleep_usec; } -void OS::set_clipboard(const String &p_text) { - - _local_clipboard = p_text; -} -String OS::get_clipboard() const { - - return _local_clipboard; -} - String OS::get_executable_path() const { return _execpath; @@ -216,31 +199,6 @@ static void _OS_printres(Object *p_obj) { print_line(str); } -bool OS::has_virtual_keyboard() const { - - return false; -} - -void OS::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length) { -} - -void OS::hide_virtual_keyboard() { -} - -int OS::get_virtual_keyboard_height() const { - return 0; -} - -void OS::set_cursor_shape(CursorShape p_shape) { -} - -OS::CursorShape OS::get_cursor_shape() const { - return CURSOR_ARROW; -} - -void OS::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { -} - void OS::print_all_resources(String p_to_file) { ERR_FAIL_COND(p_to_file != "" && _OSPRF); @@ -372,45 +330,6 @@ Error OS::shell_open(String p_uri) { }; // implement these with the canvas? -Error OS::dialog_show(String p_title, String p_description, Vector<String> p_buttons, Object *p_obj, String p_callback) { - - while (true) { - - print("%ls\n--------\n%ls\n", p_title.c_str(), p_description.c_str()); - for (int i = 0; i < p_buttons.size(); i++) { - if (i > 0) print(", "); - print("%i=%ls", i + 1, p_buttons[i].c_str()); - }; - print("\n"); - String res = get_stdin_string().strip_edges(); - if (!res.is_numeric()) - continue; - int n = res.to_int(); - if (n < 0 || n >= p_buttons.size()) - continue; - if (p_obj && p_callback != "") - p_obj->call_deferred(p_callback, n); - break; - }; - return OK; -}; - -Error OS::dialog_input_text(String p_title, String p_description, String p_partial, Object *p_obj, String p_callback) { - - ERR_FAIL_COND_V(!p_obj, FAILED); - ERR_FAIL_COND_V(p_callback == "", FAILED); - print("%ls\n---------\n%ls\n[%ls]:\n", p_title.c_str(), p_description.c_str(), p_partial.c_str()); - - String res = get_stdin_string().strip_edges(); - bool success = true; - if (res == "") { - res = p_partial; - }; - - p_obj->call_deferred(p_callback, success, res); - - return OK; -}; uint64_t OS::get_static_memory_usage() const { @@ -427,12 +346,6 @@ Error OS::set_cwd(const String &p_cwd) { return ERR_CANT_OPEN; } -bool OS::has_touchscreen_ui_hint() const { - - //return false; - return Input::get_singleton() && Input::get_singleton()->is_emulating_touch_from_mouse(); -} - uint64_t OS::get_free_static_memory() const { return Memory::get_mem_available(); @@ -441,17 +354,7 @@ uint64_t OS::get_free_static_memory() const { void OS::yield() { } -void OS::set_screen_orientation(ScreenOrientation p_orientation) { - - _orientation = p_orientation; -} - -OS::ScreenOrientation OS::get_screen_orientation() const { - - return (OS::ScreenOrientation)_orientation; -} - -void OS::_ensure_user_data_dir() { +void OS::ensure_user_data_dir() { String dd = get_user_data_dir(); DirAccess *da = DirAccess::open(dd); @@ -467,12 +370,6 @@ void OS::_ensure_user_data_dir() { memdelete(da); } -void OS::set_native_icon(const String &p_filename) { -} - -void OS::set_icon(const Ref<Image> &p_icon) { -} - String OS::get_model_name() const { return "GenericDevice"; @@ -484,15 +381,6 @@ void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) { _cmdline = p_args; }; -void OS::release_rendering_thread() { -} - -void OS::make_rendering_thread() { -} - -void OS::swap_buffers() { -} - String OS::get_unique_id() const { ERR_FAIL_V(""); @@ -503,31 +391,6 @@ int OS::get_processor_count() const { return 1; } -Error OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { - - return FAILED; -}; - -bool OS::native_video_is_playing() const { - - return false; -}; - -void OS::native_video_pause(){ - -}; - -void OS::native_video_unpause(){ - -}; - -void OS::native_video_stop(){ - -}; - -void OS::set_mouse_mode(MouseMode p_mode) { -} - bool OS::can_use_threads() const { #ifdef NO_THREADS @@ -537,51 +400,6 @@ bool OS::can_use_threads() const { #endif } -OS::MouseMode OS::get_mouse_mode() const { - - return MOUSE_MODE_VISIBLE; -} - -OS::LatinKeyboardVariant OS::get_latin_keyboard_variant() const { - - return LATIN_KEYBOARD_QWERTY; -} - -bool OS::is_joy_known(int p_device) { - return true; -} - -String OS::get_joy_guid(int p_device) const { - return "Default Joypad"; -} - -void OS::set_context(int p_context) { -} - -OS::SwitchVSyncCallbackInThread OS::switch_vsync_function = NULL; - -void OS::set_use_vsync(bool p_enable) { - _use_vsync = p_enable; - if (switch_vsync_function) { //if a function was set, use function - switch_vsync_function(p_enable); - } else { //otherwise just call here - _set_use_vsync(p_enable); - } -} - -bool OS::is_vsync_enabled() const { - - return _use_vsync; -} - -void OS::set_vsync_via_compositor(bool p_enable) { - _vsync_via_compositor = p_enable; -} - -bool OS::is_vsync_via_compositor_enabled() const { - return _vsync_via_compositor; -} - void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) { has_server_feature_callback = p_callback; @@ -653,48 +471,6 @@ bool OS::has_feature(const String &p_feature) { return false; } -void OS::center_window() { - - if (is_window_fullscreen()) return; - - Point2 sp = get_screen_position(get_current_screen()); - Size2 scr = get_screen_size(get_current_screen()); - Size2 wnd = get_real_window_size(); - - int x = sp.width + (scr.width - wnd.width) / 2; - int y = sp.height + (scr.height - wnd.height) / 2; - - set_window_position(Vector2(x, y)); -} - -int OS::get_video_driver_count() const { - - return 2; -} - -const char *OS::get_video_driver_name(int p_driver) const { - - switch (p_driver) { - case VIDEO_DRIVER_GLES2: - return "GLES2"; - case VIDEO_DRIVER_VULKAN: - default: - return "Vulkan"; - } -} - -int OS::get_audio_driver_count() const { - - return AudioDriverManager::get_driver_count(); -} - -const char *OS::get_audio_driver_name(int p_driver) const { - - AudioDriver *driver = AudioDriverManager::get_driver(p_driver); - ERR_FAIL_COND_V_MSG(!driver, "", "Cannot get audio driver at index '" + itos(p_driver) + "'."); - return AudioDriverManager::get_driver(p_driver)->get_name(); -} - void OS::set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments) { restart_on_exit = p_restart; restart_commandline = p_restart_arguments; @@ -740,7 +516,6 @@ OS::OS() { _verbose_stdout = false; _no_window = false; _exit_code = 0; - _orientation = SCREEN_LANDSCAPE; _render_thread_mode = RENDER_THREAD_SAFE; diff --git a/core/os/os.h b/core/os/os.h index 3e2ee7affd..a31b1c1f4b 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -82,31 +82,6 @@ public: RENDER_THREAD_SAFE, RENDER_SEPARATE_THREAD }; - struct VideoMode { - - int width, height; - bool fullscreen; - bool resizable; - bool borderless_window; - bool maximized; - bool always_on_top; - bool use_vsync; - bool vsync_via_compositor; - bool layered; - float get_aspect() const { return (float)width / (float)height; } - VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false, bool p_vsync_via_compositor = false) { - width = p_width; - height = p_height; - fullscreen = p_fullscreen; - resizable = p_resizable; - borderless_window = p_borderless_window; - maximized = p_maximized; - always_on_top = p_always_on_top; - use_vsync = p_use_vsync; - vsync_via_compositor = p_vsync_via_compositor; - layered = false; - } - }; protected: friend class Main; @@ -117,8 +92,8 @@ protected: // functions used by main to initialize/deinitialize the OS void add_logger(Logger *p_logger); - virtual void initialize_core() = 0; - virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0; + virtual void initialize() = 0; + virtual void initialize_joypads() = 0; virtual void set_main_loop(MainLoop *p_main_loop) = 0; virtual void delete_main_loop() = 0; @@ -128,7 +103,6 @@ protected: virtual void set_cmdline(const char *p_execpath, const List<String> &p_args); - void _ensure_user_data_dir(); virtual bool _check_internal_feature_support(const String &p_feature) = 0; public: @@ -136,121 +110,20 @@ public: static OS *get_singleton(); - virtual void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta){}; - virtual void global_menu_add_separator(const String &p_menu){}; - virtual void global_menu_remove_item(const String &p_menu, int p_idx){}; - virtual void global_menu_clear(const String &p_menu){}; - void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR); void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; - virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0; virtual String get_stdin_string(bool p_block = true) = 0; - enum MouseMode { - MOUSE_MODE_VISIBLE, - MOUSE_MODE_HIDDEN, - MOUSE_MODE_CAPTURED, - MOUSE_MODE_CONFINED - }; - - virtual void set_mouse_mode(MouseMode p_mode); - virtual MouseMode get_mouse_mode() const; - - virtual void warp_mouse_position(const Point2 &p_to) {} - virtual Point2 get_mouse_position() const = 0; - virtual int get_mouse_button_state() const = 0; - virtual void set_window_title(const String &p_title) = 0; - - virtual void set_clipboard(const String &p_text); - virtual String get_clipboard() const; - - virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0) = 0; - virtual VideoMode get_video_mode(int p_screen = 0) const = 0; - virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const = 0; - - enum VideoDriver { - VIDEO_DRIVER_VULKAN, - VIDEO_DRIVER_GLES2, - VIDEO_DRIVER_MAX, - }; - - virtual int get_video_driver_count() const; - virtual const char *get_video_driver_name(int p_driver) const; - virtual int get_current_video_driver() const = 0; - - virtual int get_audio_driver_count() const; - virtual const char *get_audio_driver_name(int p_driver) const; - virtual PackedStringArray get_connected_midi_inputs(); virtual void open_midi_inputs(); virtual void close_midi_inputs(); - virtual int get_screen_count() const { return 1; } - virtual int get_current_screen() const { return 0; } - virtual void set_current_screen(int p_screen) {} - virtual Point2 get_screen_position(int p_screen = -1) const { return Point2(); } - virtual Size2 get_screen_size(int p_screen = -1) const { return get_window_size(); } - virtual int get_screen_dpi(int p_screen = -1) const { return 72; } - virtual Point2 get_window_position() const { return Vector2(); } - virtual void set_window_position(const Point2 &p_position) {} - virtual Size2 get_max_window_size() const { return Size2(); }; - virtual Size2 get_min_window_size() const { return Size2(); }; - virtual Size2 get_window_size() const = 0; - virtual Size2 get_real_window_size() const { return get_window_size(); } - virtual void set_min_window_size(const Size2 p_size) {} - virtual void set_max_window_size(const Size2 p_size) {} - virtual void set_window_size(const Size2 p_size) {} - virtual void set_window_fullscreen(bool p_enabled) {} - virtual bool is_window_fullscreen() const { return true; } - virtual void set_window_resizable(bool p_enabled) {} - virtual bool is_window_resizable() const { return false; } - virtual void set_window_minimized(bool p_enabled) {} - virtual bool is_window_minimized() const { return false; } - virtual void set_window_maximized(bool p_enabled) {} - virtual bool is_window_maximized() const { return true; } - virtual void set_window_always_on_top(bool p_enabled) {} - virtual bool is_window_always_on_top() const { return false; } - virtual bool is_window_focused() const { return true; } - virtual void set_console_visible(bool p_enabled) {} - virtual bool is_console_visible() const { return false; } - virtual void request_attention() {} - virtual void center_window(); - - // Returns window area free of hardware controls and other obstacles. - // The application should use this to determine where to place UI elements. - // - // Keep in mind the area returned is in window coordinates rather than - // viewport coordinates - you should perform the conversion on your own. - // - // The maximum size of the area is Rect2(0, 0, window_size.width, window_size.height). - virtual Rect2 get_window_safe_area() const { - Size2 window_size = get_window_size(); - return Rect2(0, 0, window_size.width, window_size.height); - } - - virtual void set_borderless_window(bool p_borderless) {} - virtual bool get_borderless_window() { return 0; } - - virtual bool get_window_per_pixel_transparency_enabled() const { return false; } - virtual void set_window_per_pixel_transparency_enabled(bool p_enabled) {} - - virtual uint8_t *get_layered_buffer_data() { return NULL; } - virtual Size2 get_layered_buffer_size() { return Size2(0, 0); } - virtual void swap_layered_buffer() {} - - virtual void set_ime_active(const bool p_active) {} - virtual void set_ime_position(const Point2 &p_pos) {} - virtual Point2 get_ime_selection() const { return Point2(); } - virtual String get_ime_text() const { return String(); } - virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) { return ERR_UNAVAILABLE; } virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; } virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; } - virtual void set_keep_screen_on(bool p_enabled); - virtual bool is_keep_screen_on() const; virtual void set_low_processor_usage_mode(bool p_enabled); virtual bool is_in_low_processor_usage_mode() const; virtual void set_low_processor_usage_mode_sleep_usec(int p_usec); @@ -273,6 +146,11 @@ public: virtual List<String> get_cmdline_args() const { return _cmdline; } virtual String get_model_name() const; + bool is_layered_allowed() const { return _allow_layered; } + bool is_hidpi_allowed() const { return _allow_hidpi; } + + void ensure_user_data_dir(); + virtual MainLoop *get_main_loop() const = 0; virtual void yield(); @@ -338,8 +216,6 @@ public: uint32_t get_ticks_msec() const; uint64_t get_splash_tick_msec() const; - virtual bool can_draw() const = 0; - virtual bool is_userfs_persistent() const { return true; } bool is_stdout_verbose() const; @@ -348,39 +224,6 @@ public: virtual bool is_disable_crash_handler() const { return false; } virtual void initialize_debugging() {} - enum CursorShape { - CURSOR_ARROW, - CURSOR_IBEAM, - CURSOR_POINTING_HAND, - CURSOR_CROSS, - CURSOR_WAIT, - CURSOR_BUSY, - CURSOR_DRAG, - CURSOR_CAN_DROP, - CURSOR_FORBIDDEN, - CURSOR_VSIZE, - CURSOR_HSIZE, - CURSOR_BDIAGSIZE, - CURSOR_FDIAGSIZE, - CURSOR_MOVE, - CURSOR_VSPLIT, - CURSOR_HSPLIT, - CURSOR_HELP, - CURSOR_MAX - }; - - virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1); - virtual void hide_virtual_keyboard(); - - // returns height of the currently shown virtual keyboard (0 if keyboard is hidden) - virtual int get_virtual_keyboard_height() const; - - virtual void set_cursor_shape(CursorShape p_shape); - virtual CursorShape get_cursor_shape() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); - - virtual bool get_swap_ok_cancel() { return false; } virtual void dump_memory_to_file(const char *p_file); virtual void dump_resources_to_file(const char *p_file); virtual void print_resources_in_use(bool p_short = false); @@ -423,34 +266,8 @@ public: virtual void set_no_window_mode(bool p_enable); virtual bool is_no_window_mode_enabled() const; - virtual bool has_touchscreen_ui_hint() const; - - enum ScreenOrientation { - - SCREEN_LANDSCAPE, - SCREEN_PORTRAIT, - SCREEN_REVERSE_LANDSCAPE, - SCREEN_REVERSE_PORTRAIT, - SCREEN_SENSOR_LANDSCAPE, - SCREEN_SENSOR_PORTRAIT, - SCREEN_SENSOR, - }; - - virtual void set_screen_orientation(ScreenOrientation p_orientation); - ScreenOrientation get_screen_orientation() const; - - virtual void enable_for_stealing_focus(ProcessID pid) {} - virtual void move_window_to_foreground() {} - virtual void debug_break(); - virtual void release_rendering_thread(); - virtual void make_rendering_thread(); - virtual void swap_buffers(); - - virtual void set_native_icon(const String &p_filename); - virtual void set_icon(const Ref<Image> &p_icon); - virtual int get_exit_code() const; virtual void set_exit_code(int p_code); @@ -458,62 +275,12 @@ public: virtual String get_unique_id() const; - virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); - virtual bool native_video_is_playing() const; - virtual void native_video_pause(); - virtual void native_video_unpause(); - virtual void native_video_stop(); - virtual bool can_use_threads() const; - virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, Object *p_obj, String p_callback); - virtual Error dialog_input_text(String p_title, String p_description, String p_partial, Object *p_obj, String p_callback); - - enum LatinKeyboardVariant { - LATIN_KEYBOARD_QWERTY, - LATIN_KEYBOARD_QWERTZ, - LATIN_KEYBOARD_AZERTY, - LATIN_KEYBOARD_QZERTY, - LATIN_KEYBOARD_DVORAK, - LATIN_KEYBOARD_NEO, - LATIN_KEYBOARD_COLEMAK, - }; - - virtual LatinKeyboardVariant get_latin_keyboard_variant() const; - - virtual bool is_joy_known(int p_device); - virtual String get_joy_guid(int p_device) const; - - enum EngineContext { - CONTEXT_EDITOR, - CONTEXT_PROJECTMAN, - CONTEXT_ENGINE, - }; - - virtual void set_context(int p_context); - - //amazing hack because OpenGL needs this to be set on a separate thread.. - //also core can't access servers, so a callback must be used - typedef void (*SwitchVSyncCallbackInThread)(bool); - - static SwitchVSyncCallbackInThread switch_vsync_function; - void set_use_vsync(bool p_enable); - bool is_vsync_enabled() const; - - //real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed - virtual void _set_use_vsync(bool p_enable) {} - - void set_vsync_via_compositor(bool p_enable); - bool is_vsync_via_compositor_enabled() const; - - virtual void force_process_input(){}; bool has_feature(const String &p_feature); void set_has_server_feature_callback(HasServerFeatureCallback p_callback); - bool is_layered_allowed() const { return _allow_layered; } - bool is_hidpi_allowed() const { return _allow_hidpi; } - void set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments); bool is_restart_on_exit_set() const; List<String> get_restart_on_exit_arguments() const; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index b0ba8ed194..7145d64629 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -38,7 +38,8 @@ #include "core/crypto/hashing_context.h" #include "core/engine.h" #include "core/func_ref.h" -#include "core/input_map.h" +#include "core/input/input_filter.h" +#include "core/input/input_map.h" #include "core/io/config_file.h" #include "core/io/dtls_server.h" #include "core/io/http_client.h" @@ -62,7 +63,6 @@ #include "core/math/geometry.h" #include "core/math/random_number_generator.h" #include "core/math/triangle_mesh.h" -#include "core/os/input.h" #include "core/os/main_loop.h" #include "core/packed_data_container.h" #include "core/path_remap.h" @@ -248,7 +248,7 @@ void register_core_singletons() { ClassDB::register_class<_ClassDB>(); ClassDB::register_class<_Marshalls>(); ClassDB::register_class<TranslationServer>(); - ClassDB::register_virtual_class<Input>(); + ClassDB::register_virtual_class<InputFilter>(); ClassDB::register_class<InputMap>(); ClassDB::register_class<_JSON>(); ClassDB::register_class<Expression>(); @@ -263,7 +263,7 @@ void register_core_singletons() { Engine::get_singleton()->add_singleton(Engine::Singleton("ClassDB", _classdb)); Engine::get_singleton()->add_singleton(Engine::Singleton("Marshalls", _Marshalls::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("TranslationServer", TranslationServer::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("Input", Input::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("Input", InputFilter::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("JSON", _JSON::get_singleton())); } diff --git a/core/type_info.h b/core/type_info.h index 7e4b192b27..816d0d9381 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -144,6 +144,9 @@ MAKE_TYPE_INFO(String, Variant::STRING) MAKE_TYPE_INFO(Vector2, Variant::VECTOR2) MAKE_TYPE_INFO(Rect2, Variant::RECT2) MAKE_TYPE_INFO(Vector3, Variant::VECTOR3) +MAKE_TYPE_INFO(Vector2i, Variant::VECTOR2I) +MAKE_TYPE_INFO(Rect2i, Variant::RECT2I) +MAKE_TYPE_INFO(Vector3i, Variant::VECTOR3I) MAKE_TYPE_INFO(Transform2D, Variant::TRANSFORM2D) MAKE_TYPE_INFO(Plane, Variant::PLANE) MAKE_TYPE_INFO(Quat, Variant::QUAT) diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index d2ee0b71c9..0a578faf78 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -30,8 +30,8 @@ #include "variant_parser.h" +#include "core/input/input_event.h" #include "core/io/resource_loader.h" -#include "core/os/input_event.h" #include "core/os/keyboard.h" #include "core/string_buffer.h" diff --git a/drivers/gl_context/SCsub b/drivers/gl_context/SCsub index b9f0ea2254..d6945ee2eb 100644 --- a/drivers/gl_context/SCsub +++ b/drivers/gl_context/SCsub @@ -2,7 +2,7 @@ Import('env') -if (env["platform"] in ["haiku", "osx", "windows", "x11"]): +if (env["platform"] in ["haiku", "osx", "windows", "linuxbsd"]): # Thirdparty source files thirdparty_dir = "#thirdparty/glad/" thirdparty_sources = [ diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 24927c4bb8..5e8948e9c4 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -124,7 +124,7 @@ void RasterizerCanvasGLES2::canvas_begin() { viewport_width = storage->frame.current_rt->width; viewport_height = storage->frame.current_rt->height; viewport_x = storage->frame.current_rt->x; - viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y; + viewport_y = DisplayServer::get_singleton()->window_get_size().height - viewport_height - storage->frame.current_rt->y; glScissor(viewport_x, viewport_y, viewport_width, viewport_height); glViewport(viewport_x, viewport_y, viewport_width, viewport_height); glEnable(GL_SCISSOR_TEST); @@ -168,7 +168,7 @@ void RasterizerCanvasGLES2::canvas_begin() { canvas_transform.translate(-(storage->frame.current_rt->width / 2.0f), -(storage->frame.current_rt->height / 2.0f), 0.0f); canvas_transform.scale(Vector3(2.0f / storage->frame.current_rt->width, csy * -2.0f / storage->frame.current_rt->height, 1.0f)); } else { - Vector2 ssize = OS::get_singleton()->get_window_size(); + Vector2 ssize = DisplayServer::get_singleton()->window_get_size(); canvas_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); canvas_transform.scale(Vector3(2.0f / ssize.width, -2.0f / ssize.height, 1.0f)); } @@ -194,8 +194,8 @@ void RasterizerCanvasGLES2::canvas_end() { if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { //reset viewport to full window size - int viewport_width = OS::get_singleton()->get_window_size().width; - int viewport_height = OS::get_singleton()->get_window_size().height; + int viewport_width = DisplayServer::get_singleton()->window_get_size().width; + int viewport_height = DisplayServer::get_singleton()->window_get_size().height; glViewport(0, 0, viewport_width, viewport_height); glScissor(0, 0, viewport_width, viewport_height); } @@ -1995,7 +1995,7 @@ void RasterizerCanvasGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float if (storage->frame.current_rt) { half_size = Vector2(storage->frame.current_rt->width, storage->frame.current_rt->height); } else { - half_size = OS::get_singleton()->get_window_size(); + half_size = DisplayServer::get_singleton()->window_get_size(); } half_size *= 0.5; Vector2 offset((p_rect.position.x - half_size.x) / half_size.x, (p_rect.position.y - half_size.y) / half_size.y); @@ -2029,7 +2029,7 @@ void RasterizerCanvasGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_image) { - Vector2 window_size = OS::get_singleton()->get_window_size(); + Vector2 window_size = DisplayServer::get_singleton()->window_get_size(); int window_h = window_size.height; int window_w = window_size.width; diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 02b956fd44..f14c5f9406 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -318,7 +318,7 @@ void RasterizerGLES2::set_current_render_target(RID p_render_target) { } else { storage->frame.current_rt = NULL; storage->frame.clear_request = false; - glViewport(0, 0, OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); + glViewport(0, 0, DisplayServer::get_singleton()->window_get_size().width, DisplayServer::get_singleton()->window_get_size().height); glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo); } } diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index c433886545..8872dde9fc 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -3261,7 +3261,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const viewport_x = storage->frame.current_rt->x; if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN]) { - viewport_y = OS::get_singleton()->get_window_size().height - viewport_height - storage->frame.current_rt->y; + viewport_y = DisplayServer::get_singleton()->window_get_size().height - viewport_height - storage->frame.current_rt->y; } else { viewport_y = storage->frame.current_rt->y; } diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub index 85a5ae8d26..de776b19b2 100644 --- a/drivers/vulkan/SCsub +++ b/drivers/vulkan/SCsub @@ -57,7 +57,7 @@ if env['builtin_vulkan']: 'FALLBACK_DATA_DIRS=\\"%s\\"' % '/usr/local/share:/usr/share', 'FALLBACK_CONFIG_DIRS=\\"%s\\"' % '/etc/xdg' ]) - elif env['platform'] == "x11": + elif env['platform'] == "linuxbsd": env_thirdparty.AppendUnique(CPPDEFINES=[ 'VK_USE_PLATFORM_XLIB_KHR', 'VULKAN_NON_CMAKE_BUILD', diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 76541c3cd5..8ebf5b0f04 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -5150,12 +5150,12 @@ bool RenderingDeviceVulkan::compute_pipeline_is_valid(RID p_pipeline) { /**** SCREEN ****/ /****************/ -int RenderingDeviceVulkan::screen_get_width(int p_screen) const { +int RenderingDeviceVulkan::screen_get_width(DisplayServer::WindowID p_screen) const { _THREAD_SAFE_METHOD_ return context->window_get_width(p_screen); } -int RenderingDeviceVulkan::screen_get_height(int p_screen) const { +int RenderingDeviceVulkan::screen_get_height(DisplayServer::WindowID p_screen) const { _THREAD_SAFE_METHOD_ return context->window_get_height(p_screen); @@ -5189,7 +5189,7 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::screen_get_framebuff /**** DRAW LIST ****/ /*******************/ -RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(int p_screen, const Color &p_clear_color) { +RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(DisplayServer::WindowID p_screen, const Color &p_clear_color) { _THREAD_SAFE_METHOD_ diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 4a224f0ceb..7f1697b2b5 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -1052,15 +1052,15 @@ public: /**** SCREEN ****/ /****************/ - virtual int screen_get_width(int p_screen = 0) const; - virtual int screen_get_height(int p_screen = 0) const; + virtual int screen_get_width(DisplayServer::WindowID p_screen = 0) const; + virtual int screen_get_height(DisplayServer::WindowID p_screen = 0) const; virtual FramebufferFormatID screen_get_framebuffer_format() const; /********************/ /**** DRAW LISTS ****/ /********************/ - virtual DrawListID draw_list_begin_for_screen(int p_screen = 0, const Color &p_clear_color = Color()); + virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()); virtual DrawListID draw_list_begin(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<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index c8ff342713..494c64ff55 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -696,7 +696,9 @@ Error VulkanContext::_create_semaphores() { return OK; } -int VulkanContext::_window_create(VkSurfaceKHR p_surface, int p_width, int p_height) { +Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height) { + + ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER); if (!queues_initialized) { // We use a single GPU, but we need a surface to initialize the @@ -710,39 +712,37 @@ int VulkanContext::_window_create(VkSurfaceKHR p_surface, int p_width, int p_hei window.width = p_width; window.height = p_height; Error err = _update_swap_chain(&window); - ERR_FAIL_COND_V(err != OK, -1); + ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); - int id = last_window_id; - windows[id] = window; - last_window_id++; - return id; + windows[p_window_id] = window; + return OK; } -void VulkanContext::window_resize(int p_window, int p_width, int p_height) { +void VulkanContext::window_resize(DisplayServer::WindowID p_window, int p_width, int p_height) { ERR_FAIL_COND(!windows.has(p_window)); windows[p_window].width = p_width; windows[p_window].height = p_height; _update_swap_chain(&windows[p_window]); } -int VulkanContext::window_get_width(int p_window) { +int VulkanContext::window_get_width(DisplayServer::WindowID p_window) { ERR_FAIL_COND_V(!windows.has(p_window), -1); return windows[p_window].width; } -int VulkanContext::window_get_height(int p_window) { +int VulkanContext::window_get_height(DisplayServer::WindowID p_window) { ERR_FAIL_COND_V(!windows.has(p_window), -1); return windows[p_window].height; } -VkRenderPass VulkanContext::window_get_render_pass(int p_window) { +VkRenderPass VulkanContext::window_get_render_pass(DisplayServer::WindowID p_window) { ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); Window *w = &windows[p_window]; //vulkan use of currentbuffer return w->render_pass; } -VkFramebuffer VulkanContext::window_get_framebuffer(int p_window) { +VkFramebuffer VulkanContext::window_get_framebuffer(DisplayServer::WindowID p_window) { ERR_FAIL_COND_V(!windows.has(p_window), VK_NULL_HANDLE); ERR_FAIL_COND_V(!buffers_prepared, VK_NULL_HANDLE); Window *w = &windows[p_window]; @@ -750,7 +750,7 @@ VkFramebuffer VulkanContext::window_get_framebuffer(int p_window) { return w->swapchain_image_resources[w->current_buffer].framebuffer; } -void VulkanContext::window_destroy(int p_window_id) { +void VulkanContext::window_destroy(DisplayServer::WindowID p_window_id) { ERR_FAIL_COND(!windows.has(p_window_id)); _clean_up_swap_chain(&windows[p_window_id]); vkDestroySurfaceKHR(inst, windows[p_window_id].surface, NULL); @@ -1497,7 +1497,6 @@ VulkanContext::VulkanContext() { buffers_prepared = false; swapchainImageCount = 0; - last_window_id = 0; } VulkanContext::~VulkanContext() { diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index 458cb6d793..2f10fbfdef 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -34,6 +34,7 @@ #include "core/error_list.h" #include "core/map.h" #include "core/ustring.h" +#include "servers/display_server.h" #include <vulkan/vulkan.h> class VulkanContext { @@ -106,8 +107,7 @@ class VulkanContext { } }; - Map<int, Window> windows; - int last_window_id; + Map<DisplayServer::WindowID, Window> windows; uint32_t swapchainImageCount; //commands @@ -173,7 +173,7 @@ protected: virtual const char *_get_platform_surface_extension() const = 0; // virtual VkResult _create_surface(VkSurfaceKHR *surface, VkInstance p_instance) = 0; - virtual int _window_create(VkSurfaceKHR p_surface, int p_width, int p_height); + virtual Error _window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height); VkInstance _get_instance() { return inst; @@ -187,12 +187,12 @@ public: int get_swapchain_image_count() const; uint32_t get_graphics_queue() const; - void window_resize(int p_window_id, int p_width, int p_height); - int window_get_width(int p_window = 0); - int window_get_height(int p_window = 0); - void window_destroy(int p_window_id); - VkFramebuffer window_get_framebuffer(int p_window = 0); - VkRenderPass window_get_render_pass(int p_window = 0); + void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height); + int window_get_width(DisplayServer::WindowID p_window = 0); + int window_get_height(DisplayServer::WindowID p_window = 0); + void window_destroy(DisplayServer::WindowID p_window_id); + VkFramebuffer window_get_framebuffer(DisplayServer::WindowID p_window = 0); + VkRenderPass window_get_render_pass(DisplayServer::WindowID p_window = 0); VkFormat get_screen_format() const; VkPhysicalDeviceLimits get_device_limits() const; diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 6dcc9dd8ae..f3e3025e81 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -215,20 +215,20 @@ void AnimationBezierTrackEdit::_draw_line_clipped(const Vector2 &p_from, const V void AnimationBezierTrackEdit::_notification(int p_what) { if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { - bezier_icon = get_icon("KeyBezierPoint", "EditorIcons"); - bezier_handle_icon = get_icon("KeyBezierHandle", "EditorIcons"); - selected_icon = get_icon("KeyBezierSelected", "EditorIcons"); + bezier_icon = get_theme_icon("KeyBezierPoint", "EditorIcons"); + bezier_handle_icon = get_theme_icon("KeyBezierHandle", "EditorIcons"); + selected_icon = get_theme_icon("KeyBezierSelected", "EditorIcons"); if (handle_mode_option->get_item_count() == 0) { - handle_mode_option->add_icon_item(get_icon("BezierHandlesFree", "EditorIcons"), TTR("Free"), HANDLE_MODE_FREE); - handle_mode_option->add_icon_item(get_icon("BezierHandlesBalanced", "EditorIcons"), TTR("Balanced"), HANDLE_MODE_BALANCED); - handle_mode_option->add_icon_item(get_icon("BezierHandlesMirror", "EditorIcons"), TTR("Mirror"), HANDLE_MODE_MIRROR); + handle_mode_option->add_icon_item(get_theme_icon("BezierHandlesFree", "EditorIcons"), TTR("Free"), HANDLE_MODE_FREE); + handle_mode_option->add_icon_item(get_theme_icon("BezierHandlesBalanced", "EditorIcons"), TTR("Balanced"), HANDLE_MODE_BALANCED); + handle_mode_option->add_icon_item(get_theme_icon("BezierHandlesMirror", "EditorIcons"), TTR("Mirror"), HANDLE_MODE_MIRROR); } } if (p_what == NOTIFICATION_RESIZED) { int right_limit = get_size().width - timeline->get_buttons_width(); - int hsep = get_constant("hseparation", "ItemList"); - int vsep = get_constant("vseparation", "ItemList"); + int hsep = get_theme_constant("hseparation", "ItemList"); + int vsep = get_theme_constant("vseparation", "ItemList"); handle_mode_option->set_position(Vector2(right_limit + hsep, get_size().height - handle_mode_option->get_combined_minimum_size().height - vsep)); handle_mode_option->set_size(Vector2(timeline->get_buttons_width() - hsep * 2, handle_mode_option->get_combined_minimum_size().height)); @@ -240,15 +240,15 @@ void AnimationBezierTrackEdit::_notification(int p_what) { int limit = timeline->get_name_limit(); if (has_focus()) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); accent.a *= 0.7; draw_rect(Rect2(Point2(), get_size()), accent, false); } - Ref<Font> font = get_font("font", "Label"); - Color color = get_color("font_color", "Label"); - int hsep = get_constant("hseparation", "ItemList"); - int vsep = get_constant("vseparation", "ItemList"); + Ref<Font> font = get_theme_font("font", "Label"); + Color color = get_theme_color("font_color", "Label"); + int hsep = get_theme_constant("hseparation", "ItemList"); + int vsep = get_theme_constant("vseparation", "ItemList"); Color linecolor = color; linecolor.a = 0.2; @@ -258,7 +258,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { draw_line(Point2(right_limit, 0), Point2(right_limit, get_size().height), linecolor); - Ref<Texture2D> close_icon = get_icon("Close", "EditorIcons"); + Ref<Texture2D> close_icon = get_theme_icon("Close", "EditorIcons"); close_icon_rect.position = Vector2(get_size().width - close_icon->get_width() - hsep, hsep); close_icon_rect.size = close_icon->get_size(); @@ -340,7 +340,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { subtracks[i] = rect; } else { - Color ac = get_color("accent_color", "Editor"); + Color ac = get_theme_color("accent_color", "Editor"); ac.a = 0.5; draw_rect(rect, ac); } @@ -349,7 +349,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { vofs += font->get_height() + vsep; } - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); { //guides float min_left_scale = font->get_height() + vsep; @@ -391,7 +391,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { { //draw OTHER curves float scale = timeline->get_zoom_scale(); - Ref<Texture2D> point = get_icon("KeyValue", "EditorIcons"); + Ref<Texture2D> point = get_theme_icon("KeyValue", "EditorIcons"); for (Map<int, Color>::Element *E = subtrack_colors.front(); E; E = E->next()) { _draw_track(E->key(), E->get()); @@ -410,7 +410,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { } //draw edited curve - const Color highlight = get_color("highlight_color", "Editor"); + const Color highlight = get_theme_color("highlight_color", "Editor"); _draw_track(track, highlight); } @@ -540,7 +540,7 @@ void AnimationBezierTrackEdit::_play_position_draw() { int px = (-timeline->get_value() + play_position_pos) * scale + timeline->get_name_limit(); if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); play_position->draw_line(Point2(px, 0), Point2(px, h), color); } } @@ -657,9 +657,9 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(bezier_icon, TTR("Insert Key Here"), MENU_KEY_INSERT); if (selection.size()) { menu->add_separator(); - menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE); + menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Duplicate Selected Key(s)"), MENU_KEY_DUPLICATE); menu->add_separator(); - menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE); + menu->add_icon_item(get_theme_icon("Remove", "EditorIcons"), TTR("Delete Selected Key(s)"), MENU_KEY_DELETE); } menu->set_as_minsize(); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index fb427afe24..182b406705 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -31,13 +31,13 @@ #include "animation_track_editor.h" #include "animation_track_editor_plugins.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "editor/animation_bezier_editor.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor_node.h" #include "editor_scale.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "servers/audio/audio_stream.h" class AnimationTrackKeyEdit : public Object { @@ -1442,11 +1442,11 @@ void AnimationTimelineEdit::_anim_loop_pressed() { int AnimationTimelineEdit::get_buttons_width() const { - Ref<Texture2D> interp_mode = get_icon("TrackContinuous", "EditorIcons"); - Ref<Texture2D> interp_type = get_icon("InterpRaw", "EditorIcons"); - Ref<Texture2D> loop_type = get_icon("InterpWrapClamp", "EditorIcons"); - Ref<Texture2D> remove_icon = get_icon("Remove", "EditorIcons"); - Ref<Texture2D> down_icon = get_icon("select_arrow", "Tree"); + Ref<Texture2D> interp_mode = get_theme_icon("TrackContinuous", "EditorIcons"); + Ref<Texture2D> interp_type = get_theme_icon("InterpRaw", "EditorIcons"); + Ref<Texture2D> loop_type = get_theme_icon("InterpWrapClamp", "EditorIcons"); + Ref<Texture2D> remove_icon = get_theme_icon("Remove", "EditorIcons"); + Ref<Texture2D> down_icon = get_theme_icon("select_arrow", "Tree"); int total_w = interp_mode->get_width() + interp_type->get_width() + loop_type->get_width() + remove_icon->get_width(); total_w += (down_icon->get_width() + 4 * EDSCALE) * 4; @@ -1456,7 +1456,7 @@ int AnimationTimelineEdit::get_buttons_width() const { int AnimationTimelineEdit::get_name_limit() const { - Ref<Texture2D> hsize_icon = get_icon("Hsize", "EditorIcons"); + Ref<Texture2D> hsize_icon = get_theme_icon("Hsize", "EditorIcons"); int limit = MAX(name_limit, add_track->get_minimum_size().width + hsize_icon->get_width()); @@ -1468,17 +1468,17 @@ int AnimationTimelineEdit::get_name_limit() const { void AnimationTimelineEdit::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - add_track->set_icon(get_icon("Add", "EditorIcons")); - loop->set_icon(get_icon("Loop", "EditorIcons")); - time_icon->set_texture(get_icon("Time", "EditorIcons")); + add_track->set_icon(get_theme_icon("Add", "EditorIcons")); + loop->set_icon(get_theme_icon("Loop", "EditorIcons")); + time_icon->set_texture(get_theme_icon("Time", "EditorIcons")); add_track->get_popup()->clear(); - add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), TTR("Property Track")); - add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), TTR("3D Transform Track")); - add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), TTR("Call Method Track")); - add_track->get_popup()->add_icon_item(get_icon("KeyBezier", "EditorIcons"), TTR("Bezier Curve Track")); - add_track->get_popup()->add_icon_item(get_icon("KeyAudio", "EditorIcons"), TTR("Audio Playback Track")); - add_track->get_popup()->add_icon_item(get_icon("KeyAnimation", "EditorIcons"), TTR("Animation Playback Track")); + add_track->get_popup()->add_icon_item(get_theme_icon("KeyValue", "EditorIcons"), TTR("Property Track")); + add_track->get_popup()->add_icon_item(get_theme_icon("KeyXform", "EditorIcons"), TTR("3D Transform Track")); + add_track->get_popup()->add_icon_item(get_theme_icon("KeyCall", "EditorIcons"), TTR("Call Method Track")); + add_track->get_popup()->add_icon_item(get_theme_icon("KeyBezier", "EditorIcons"), TTR("Bezier Curve Track")); + add_track->get_popup()->add_icon_item(get_theme_icon("KeyAudio", "EditorIcons"), TTR("Audio Playback Track")); + add_track->get_popup()->add_icon_item(get_theme_icon("KeyAnimation", "EditorIcons"), TTR("Animation Playback Track")); } if (p_what == NOTIFICATION_RESIZED) { @@ -1493,8 +1493,8 @@ void AnimationTimelineEdit::_notification(int p_what) { if (!animation.is_valid()) return; - Ref<Font> font = get_font("font", "Label"); - Color color = get_color("font_color", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); + Color color = get_theme_color("font_color", "Label"); int zoomw = key_range; float scale = get_zoom_scale(); @@ -1504,7 +1504,7 @@ void AnimationTimelineEdit::_notification(int p_what) { if (l <= 0) l = 0.001; //avoid crashor - Ref<Texture2D> hsize_icon = get_icon("Hsize", "EditorIcons"); + Ref<Texture2D> hsize_icon = get_theme_icon("Hsize", "EditorIcons"); hsize_rect = Rect2(get_name_limit() - hsize_icon->get_width() - 2 * EDSCALE, (get_size().height - hsize_icon->get_height()) / 2, hsize_icon->get_width(), hsize_icon->get_height()); draw_texture(hsize_icon, hsize_rect.position); @@ -1554,7 +1554,7 @@ void AnimationTimelineEdit::_notification(int p_what) { int end_px = (l - get_value()) * scale; int begin_px = -get_value() * scale; - Color notimecol = get_color("dark_color_2", "Editor"); + Color notimecol = get_theme_color("dark_color_2", "Editor"); Color timecolor = color; timecolor.a = 0.2; Color linecolor = color; @@ -1685,9 +1685,9 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation) { Size2 AnimationTimelineEdit::get_minimum_size() const { Size2 ms = add_track->get_minimum_size(); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); ms.height = MAX(ms.height, font->get_height()); - ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_icon("Hsize", "EditorIcons")->get_width() + 2; + ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_theme_icon("Hsize", "EditorIcons")->get_width() + 2; return ms; } @@ -1746,11 +1746,11 @@ void AnimationTimelineEdit::_play_position_draw() { int px = (-get_value() + play_position_pos) * scale + get_name_limit(); if (px >= get_name_limit() && px < (play_position->get_size().width - get_buttons_width())) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE)); play_position->draw_texture( - get_icon("TimelineIndicator", "EditorIcons"), - Point2(px - get_icon("TimelineIndicator", "EditorIcons")->get_width() * 0.5, 0), + get_theme_icon("TimelineIndicator", "EditorIcons"), + Point2(px - get_theme_icon("TimelineIndicator", "EditorIcons")->get_width() * 0.5, 0), color); } } @@ -1921,23 +1921,23 @@ void AnimationTrackEdit::_notification(int p_what) { int limit = timeline->get_name_limit(); if (has_focus()) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); accent.a *= 0.7; // Offside so the horizontal sides aren't cutoff. draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), accent, false); } - Ref<Font> font = get_font("font", "Label"); - Color color = get_color("font_color", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); + Color color = get_theme_color("font_color", "Label"); Ref<Texture2D> type_icons[6] = { - get_icon("KeyValue", "EditorIcons"), - get_icon("KeyXform", "EditorIcons"), - get_icon("KeyCall", "EditorIcons"), - get_icon("KeyBezier", "EditorIcons"), - get_icon("KeyAudio", "EditorIcons"), - get_icon("KeyAnimation", "EditorIcons") + get_theme_icon("KeyValue", "EditorIcons"), + get_theme_icon("KeyXform", "EditorIcons"), + get_theme_icon("KeyCall", "EditorIcons"), + get_theme_icon("KeyBezier", "EditorIcons"), + get_theme_icon("KeyAudio", "EditorIcons"), + get_theme_icon("KeyAnimation", "EditorIcons") }; - int hsep = get_constant("hseparation", "ItemList"); + int hsep = get_theme_constant("hseparation", "ItemList"); Color linecolor = color; linecolor.a = 0.2; @@ -1945,7 +1945,7 @@ void AnimationTrackEdit::_notification(int p_what) { { - Ref<Texture2D> check = animation->track_is_enabled(track) ? get_icon("checked", "CheckBox") : get_icon("unchecked", "CheckBox"); + Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon("checked", "CheckBox") : get_theme_icon("unchecked", "CheckBox"); int ofs = in_group ? check->get_width() : 0; //not the best reference for margin but.. @@ -1966,7 +1966,7 @@ void AnimationTrackEdit::_notification(int p_what) { String text; Color text_color = color; if (node && EditorNode::get_singleton()->get_editor_selection()->is_selected(node)) { - text_color = get_color("accent_color", "Editor"); + text_color = get_theme_color("accent_color", "Editor"); } if (in_group) { @@ -2045,25 +2045,25 @@ void AnimationTrackEdit::_notification(int p_what) { { Ref<Texture2D> wrap_icon[2] = { - get_icon("InterpWrapClamp", "EditorIcons"), - get_icon("InterpWrapLoop", "EditorIcons"), + get_theme_icon("InterpWrapClamp", "EditorIcons"), + get_theme_icon("InterpWrapLoop", "EditorIcons"), }; Ref<Texture2D> interp_icon[3] = { - get_icon("InterpRaw", "EditorIcons"), - get_icon("InterpLinear", "EditorIcons"), - get_icon("InterpCubic", "EditorIcons") + get_theme_icon("InterpRaw", "EditorIcons"), + get_theme_icon("InterpLinear", "EditorIcons"), + get_theme_icon("InterpCubic", "EditorIcons") }; Ref<Texture2D> cont_icon[4] = { - get_icon("TrackContinuous", "EditorIcons"), - get_icon("TrackDiscrete", "EditorIcons"), - get_icon("TrackTrigger", "EditorIcons"), - get_icon("TrackCapture", "EditorIcons") + get_theme_icon("TrackContinuous", "EditorIcons"), + get_theme_icon("TrackDiscrete", "EditorIcons"), + get_theme_icon("TrackTrigger", "EditorIcons"), + get_theme_icon("TrackCapture", "EditorIcons") }; int ofs = get_size().width - timeline->get_buttons_width(); - Ref<Texture2D> down_icon = get_icon("select_arrow", "Tree"); + Ref<Texture2D> down_icon = get_theme_icon("select_arrow", "Tree"); draw_line(Point2(ofs, 0), Point2(ofs, get_size().height), linecolor, Math::round(EDSCALE)); @@ -2100,7 +2100,7 @@ void AnimationTrackEdit::_notification(int p_what) { update_mode_rect.size.x += down_icon->get_width(); bezier_edit_rect = Rect2(); } else if (animation->track_get_type(track) == Animation::TYPE_BEZIER) { - Ref<Texture2D> bezier_icon = get_icon("EditBezier", "EditorIcons"); + Ref<Texture2D> bezier_icon = get_theme_icon("EditBezier", "EditorIcons"); update_mode_rect.size.x += down_icon->get_width(); bezier_edit_rect.position = update_mode_rect.position + (update_mode_rect.size - bezier_icon->get_size()) / 2; bezier_edit_rect.size = bezier_icon->get_size(); @@ -2185,7 +2185,7 @@ void AnimationTrackEdit::_notification(int p_what) { { //erase - Ref<Texture2D> icon = get_icon("Remove", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon("Remove", "EditorIcons"); remove_rect.position.x = ofs + ((get_size().width - ofs) - icon->get_width()) / 2; remove_rect.position.y = int(get_size().height - icon->get_height()) / 2; @@ -2202,7 +2202,7 @@ void AnimationTrackEdit::_notification(int p_what) { } if (dropping_at != 0) { - Color drop_color = get_color("accent_color", "Editor"); + Color drop_color = get_theme_color("accent_color", "Editor"); if (dropping_at < 0) { draw_line(Vector2(0, 0), Vector2(get_size().width, 0), drop_color, Math::round(EDSCALE)); } else { @@ -2249,7 +2249,7 @@ void AnimationTrackEdit::draw_key_link(int p_index, float p_pixels_sec, int p_x, if (current != next) return; - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); color.a = 0.5; int from_x = MAX(p_x, p_clip_left); @@ -2273,15 +2273,15 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool const Variant &v = animation->track_get_key_value(track, p_index); Variant::Type valid_type = Variant::NIL; if (!_is_value_key_valid(v, valid_type)) { - icon_to_draw = get_icon("KeyInvalid", "EditorIcons"); + icon_to_draw = get_theme_icon("KeyInvalid", "EditorIcons"); } } Vector2 ofs(p_x - icon_to_draw->get_width() / 2, int(get_size().height - icon_to_draw->get_height()) / 2); if (animation->track_get_type(track) == Animation::TYPE_METHOD) { - Ref<Font> font = get_font("font", "Label"); - Color color = get_color("font_color", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); + Color color = get_theme_color("font_color", "Label"); color.a = 0.5; Dictionary d = animation->track_get_key_value(track, p_index); @@ -2387,19 +2387,19 @@ void AnimationTrackEdit::set_animation_and_track(const Ref<Animation> &p_animati update(); Ref<Texture2D> type_icons[6] = { - get_icon("KeyValue", "EditorIcons"), - get_icon("KeyXform", "EditorIcons"), - get_icon("KeyCall", "EditorIcons"), - get_icon("KeyBezier", "EditorIcons"), - get_icon("KeyAudio", "EditorIcons"), - get_icon("KeyAnimation", "EditorIcons") + get_theme_icon("KeyValue", "EditorIcons"), + get_theme_icon("KeyXform", "EditorIcons"), + get_theme_icon("KeyCall", "EditorIcons"), + get_theme_icon("KeyBezier", "EditorIcons"), + get_theme_icon("KeyAudio", "EditorIcons"), + get_theme_icon("KeyAnimation", "EditorIcons") }; ERR_FAIL_INDEX(track, animation->get_track_count()); node_path = animation->track_get_path(p_track); type_icon = type_icons[animation->track_get_type(track)]; - selected_icon = get_icon("KeySelected", "EditorIcons"); + selected_icon = get_theme_icon("KeySelected", "EditorIcons"); } NodePath AnimationTrackEdit::get_path() const { @@ -2408,9 +2408,9 @@ NodePath AnimationTrackEdit::get_path() const { Size2 AnimationTrackEdit::get_minimum_size() const { - Ref<Texture2D> texture = get_icon("Object", "EditorIcons"); - Ref<Font> font = get_font("font", "Label"); - int separation = get_constant("vseparation", "ItemList"); + Ref<Texture2D> texture = get_theme_icon("Object", "EditorIcons"); + Ref<Font> font = get_theme_font("font", "Label"); + int separation = get_theme_constant("vseparation", "ItemList"); int max_h = MAX(texture->get_height(), font->get_height()); max_h = MAX(max_h, get_key_height()); @@ -2442,7 +2442,7 @@ void AnimationTrackEdit::_play_position_draw() { int px = (-timeline->get_value() + play_position_pos) * scale + timeline->get_name_limit(); if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE)); } } @@ -2471,6 +2471,7 @@ void AnimationTrackEdit::_path_entered(const String &p_text) { undo_redo->add_do_method(animation.ptr(), "track_set_path", track, p_text); undo_redo->add_undo_method(animation.ptr(), "track_set_path", track, animation->track_get_path(track)); undo_redo->commit_action(); + path_popup->hide(); } bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const { @@ -2689,14 +2690,14 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected)); } menu->clear(); - menu->add_icon_item(get_icon("TrackContinuous", "EditorIcons"), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS); - menu->add_icon_item(get_icon("TrackDiscrete", "EditorIcons"), TTR("Discrete"), MENU_CALL_MODE_DISCRETE); - menu->add_icon_item(get_icon("TrackTrigger", "EditorIcons"), TTR("Trigger"), MENU_CALL_MODE_TRIGGER); - menu->add_icon_item(get_icon("TrackCapture", "EditorIcons"), TTR("Capture"), MENU_CALL_MODE_CAPTURE); + menu->add_icon_item(get_theme_icon("TrackContinuous", "EditorIcons"), TTR("Continuous"), MENU_CALL_MODE_CONTINUOUS); + menu->add_icon_item(get_theme_icon("TrackDiscrete", "EditorIcons"), TTR("Discrete"), MENU_CALL_MODE_DISCRETE); + menu->add_icon_item(get_theme_icon("TrackTrigger", "EditorIcons"), TTR("Trigger"), MENU_CALL_MODE_TRIGGER); + menu->add_icon_item(get_theme_icon("TrackCapture", "EditorIcons"), TTR("Capture"), MENU_CALL_MODE_CAPTURE); menu->set_as_minsize(); - Vector2 popup_pos = get_global_position() + update_mode_rect.position + Vector2(0, update_mode_rect.size.height); - menu->set_global_position(popup_pos); + Vector2 popup_pos = get_screen_position() + update_mode_rect.position + Vector2(0, update_mode_rect.size.height); + menu->set_position(popup_pos); menu->popup(); accept_event(); } @@ -2708,13 +2709,13 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected)); } menu->clear(); - menu->add_icon_item(get_icon("InterpRaw", "EditorIcons"), TTR("Nearest"), MENU_INTERPOLATION_NEAREST); - menu->add_icon_item(get_icon("InterpLinear", "EditorIcons"), TTR("Linear"), MENU_INTERPOLATION_LINEAR); - menu->add_icon_item(get_icon("InterpCubic", "EditorIcons"), TTR("Cubic"), MENU_INTERPOLATION_CUBIC); + menu->add_icon_item(get_theme_icon("InterpRaw", "EditorIcons"), TTR("Nearest"), MENU_INTERPOLATION_NEAREST); + menu->add_icon_item(get_theme_icon("InterpLinear", "EditorIcons"), TTR("Linear"), MENU_INTERPOLATION_LINEAR); + menu->add_icon_item(get_theme_icon("InterpCubic", "EditorIcons"), TTR("Cubic"), MENU_INTERPOLATION_CUBIC); menu->set_as_minsize(); - Vector2 popup_pos = get_global_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height); - menu->set_global_position(popup_pos); + Vector2 popup_pos = get_screen_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height); + menu->set_position(popup_pos); menu->popup(); accept_event(); } @@ -2726,12 +2727,12 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { menu->connect("id_pressed", callable_mp(this, &AnimationTrackEdit::_menu_selected)); } menu->clear(); - menu->add_icon_item(get_icon("InterpWrapClamp", "EditorIcons"), TTR("Clamp Loop Interp"), MENU_LOOP_CLAMP); - menu->add_icon_item(get_icon("InterpWrapLoop", "EditorIcons"), TTR("Wrap Loop Interp"), MENU_LOOP_WRAP); + menu->add_icon_item(get_theme_icon("InterpWrapClamp", "EditorIcons"), TTR("Clamp Loop Interp"), MENU_LOOP_CLAMP); + menu->add_icon_item(get_theme_icon("InterpWrapLoop", "EditorIcons"), TTR("Wrap Loop Interp"), MENU_LOOP_WRAP); menu->set_as_minsize(); - Vector2 popup_pos = get_global_position() + loop_mode_rect.position + Vector2(0, loop_mode_rect.size.height); - menu->set_global_position(popup_pos); + Vector2 popup_pos = get_screen_position() + loop_mode_rect.position + Vector2(0, loop_mode_rect.size.height); + menu->set_position(popup_pos); menu->popup(); accept_event(); } @@ -2822,17 +2823,17 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { } menu->clear(); - menu->add_icon_item(get_icon("Key", "EditorIcons"), TTR("Insert Key"), MENU_KEY_INSERT); + menu->add_icon_item(get_theme_icon("Key", "EditorIcons"), TTR("Insert Key"), MENU_KEY_INSERT); if (editor->is_selection_active()) { menu->add_separator(); - menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate Key(s)"), MENU_KEY_DUPLICATE); + menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Duplicate Key(s)"), MENU_KEY_DUPLICATE); menu->add_separator(); - menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete Key(s)"), MENU_KEY_DELETE); + menu->add_icon_item(get_theme_icon("Remove", "EditorIcons"), TTR("Delete Key(s)"), MENU_KEY_DELETE); } menu->set_as_minsize(); - Vector2 popup_pos = get_global_transform().xform(get_local_mouse_position()); - menu->set_global_position(popup_pos); + Vector2 popup_pos = get_screen_transform().xform(get_local_mouse_position()); + menu->set_position(popup_pos); menu->popup(); insert_at_pos = offset + timeline->get_value(); @@ -2843,17 +2844,20 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && clicking_on_name) { if (!path) { + path_popup = memnew(Popup); + path_popup->set_wrap_controls(true); + add_child(path_popup); path = memnew(LineEdit); - add_child(path); - path->set_as_toplevel(true); + path_popup->add_child(path); + path->set_anchors_and_margins_preset(PRESET_WIDE); path->connect("text_entered", callable_mp(this, &AnimationTrackEdit::_path_entered)); } path->set_text(animation->track_get_path(track)); - Vector2 theme_ofs = path->get_stylebox("normal", "LineEdit")->get_offset(); - path->set_position(get_global_position() + path_rect.position - theme_ofs); - path->set_size(path_rect.size); - path->show_modal(); + Vector2 theme_ofs = path->get_theme_stylebox("normal", "LineEdit")->get_offset(); + path_popup->set_position(get_screen_position() + path_rect.position - theme_ofs); + path_popup->set_size(path_rect.size); + path_popup->popup(); path->grab_focus(); path->set_cursor_position(path->get_text().length()); clicking_on_name = false; @@ -3090,6 +3094,7 @@ AnimationTrackEdit::AnimationTrackEdit() { timeline = NULL; root = NULL; path = NULL; + path_popup = NULL; menu = NULL; clicking_on_name = false; dropping_at = 0; @@ -3158,18 +3163,18 @@ AnimationTrackEdit *AnimationTrackEditPlugin::create_animation_track_edit(Object void AnimationTrackEditGroup::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<Font> font = get_font("font", "Label"); - int separation = get_constant("hseparation", "ItemList"); - Color color = get_color("font_color", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); + int separation = get_theme_constant("hseparation", "ItemList"); + Color color = get_theme_color("font_color", "Label"); if (root && root->has_node(node)) { Node *n = root->get_node(node); if (n && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) { - color = get_color("accent_color", "Editor"); + color = get_theme_color("accent_color", "Editor"); } } - Color bgcol = get_color("dark_color_2", "Editor"); + Color bgcol = get_theme_color("dark_color_2", "Editor"); bgcol.a *= 0.6; draw_rect(Rect2(Point2(), get_size()), bgcol); Color linecolor = color; @@ -3187,7 +3192,7 @@ void AnimationTrackEditGroup::_notification(int p_what) { int px = (-timeline->get_value() + timeline->get_play_position()) * timeline->get_zoom_scale() + timeline->get_name_limit(); if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_line(Point2(px, 0), Point2(px, get_size().height), accent, Math::round(2 * EDSCALE)); } } @@ -3203,8 +3208,8 @@ void AnimationTrackEditGroup::set_type_and_name(const Ref<Texture2D> &p_type, co Size2 AnimationTrackEditGroup::get_minimum_size() const { - Ref<Font> font = get_font("font", "Label"); - int separation = get_constant("vseparation", "ItemList"); + Ref<Font> font = get_theme_font("font", "Label"); + int separation = get_theme_constant("vseparation", "ItemList"); return Vector2(0, MAX(font->get_height(), icon->get_height()) + separation); } @@ -3443,7 +3448,7 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) { if (insert_frame != Engine::get_singleton()->get_frames_drawn()) { //clear insert list for the frame if frame changed - if (insert_confirm->is_visible_in_tree()) + if (insert_confirm->is_visible()) return; //do nothing insert_data.clear(); insert_query = false; @@ -3496,7 +3501,7 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) { insert_confirm_bezier->set_visible(all_bezier); insert_confirm->get_ok()->set_text(TTR("Create")); - insert_confirm->popup_centered_minsize(); + insert_confirm->popup_centered(); insert_query = true; } else { call_deferred("_insert_delay"); @@ -4095,7 +4100,7 @@ bool AnimationTrackEditor::is_selection_active() const { } bool AnimationTrackEditor::is_snap_enabled() const { - return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL); + return snap->is_pressed() ^ InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); } void AnimationTrackEditor::_update_tracks() { @@ -4207,7 +4212,7 @@ void AnimationTrackEditor::_update_tracks() { if (!group_sort.has(base_path)) { AnimationTrackEditGroup *g = memnew(AnimationTrackEditGroup); - Ref<Texture2D> icon = get_icon("Node", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon("Node", "EditorIcons"); String name = base_path; String tooltip; if (root && root->has_node(base_path)) { @@ -4225,7 +4230,7 @@ void AnimationTrackEditor::_update_tracks() { g->set_timeline(timeline); groups.push_back(g); VBoxContainer *vb = memnew(VBoxContainer); - vb->add_constant_override("separation", 0); + vb->add_theme_constant_override("separation", 0); vb->add_child(g); track_vbox->add_child(vb); group_sort[base_path] = vb; @@ -4368,12 +4373,12 @@ MenuButton *AnimationTrackEditor::get_edit_menu() { void AnimationTrackEditor::_notification(int p_what) { if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { - zoom_icon->set_texture(get_icon("Zoom", "EditorIcons")); - snap->set_icon(get_icon("Snap", "EditorIcons")); - view_group->set_icon(get_icon(view_group->is_pressed() ? "AnimationTrackList" : "AnimationTrackGroup", "EditorIcons")); - selected_filter->set_icon(get_icon("AnimationFilter", "EditorIcons")); - imported_anim_warning->set_icon(get_icon("NodeWarning", "EditorIcons")); - main_panel->add_style_override("panel", get_stylebox("bg", "Tree")); + zoom_icon->set_texture(get_theme_icon("Zoom", "EditorIcons")); + snap->set_icon(get_theme_icon("Snap", "EditorIcons")); + view_group->set_icon(get_theme_icon(view_group->is_pressed() ? "AnimationTrackList" : "AnimationTrackGroup", "EditorIcons")); + selected_filter->set_icon(get_theme_icon("AnimationFilter", "EditorIcons")); + imported_anim_warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons")); + main_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); } if (p_what == NOTIFICATION_READY) { @@ -5050,8 +5055,8 @@ float AnimationTrackEditor::get_moving_selection_offset() const { void AnimationTrackEditor::_box_selection_draw() { const Rect2 selection_rect = Rect2(Point2(), box_selection->get_size()); - box_selection->draw_rect(selection_rect, get_color("box_selection_fill_color", "Editor")); - box_selection->draw_rect(selection_rect, get_color("box_selection_stroke_color", "Editor"), false, Math::round(EDSCALE)); + box_selection->draw_rect(selection_rect, get_theme_color("box_selection_fill_color", "Editor")); + box_selection->draw_rect(selection_rect, get_theme_color("box_selection_stroke_color", "Editor"), false, Math::round(EDSCALE)); } void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) { @@ -5266,10 +5271,10 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } String text; - Ref<Texture2D> icon = get_icon("Node", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon("Node", "EditorIcons"); if (node) { - if (has_icon(node->get_class(), "EditorIcons")) { - icon = get_icon(node->get_class(), "EditorIcons"); + if (has_theme_icon(node->get_class(), "EditorIcons")) { + icon = get_theme_icon(node->get_class(), "EditorIcons"); } text = node->get_name(); @@ -5309,7 +5314,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { it->set_metadata(0, md); } - track_copy_dialog->popup_centered_minsize(Size2(350, 500) * EDSCALE); + track_copy_dialog->popup_centered(Size2(350, 500) * EDSCALE); } break; case EDIT_COPY_TRACKS_CONFIRM: { @@ -5578,7 +5583,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } break; case EDIT_CLEAN_UP_ANIMATION: { - cleanup_dialog->popup_centered_minsize(Size2(300, 0) * EDSCALE); + cleanup_dialog->popup_centered(Size2(300, 0) * EDSCALE); } break; case EDIT_CLEAN_UP_ANIMATION_CONFIRM: { @@ -5652,7 +5657,7 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) { void AnimationTrackEditor::_view_group_toggle() { _update_tracks(); - view_group->set_icon(get_icon(view_group->is_pressed() ? "AnimationTrackList" : "AnimationTrackGroup", "EditorIcons")); + view_group->set_icon(get_theme_icon(view_group->is_pressed() ? "AnimationTrackList" : "AnimationTrackGroup", "EditorIcons")); } bool AnimationTrackEditor::is_grouping_tracks() { @@ -5763,7 +5768,7 @@ AnimationTrackEditor::AnimationTrackEditor() { timeline_scroll->add_child(timeline_vbox); timeline_vbox->set_v_size_flags(SIZE_EXPAND_FILL); timeline_vbox->set_h_size_flags(SIZE_EXPAND_FILL); - timeline_vbox->add_constant_override("separation", 0); + timeline_vbox->add_theme_constant_override("separation", 0); info_message = memnew(Label); info_message->set_text(TTR("Select an AnimationPlayer node to create and edit animations.")); @@ -5814,7 +5819,7 @@ AnimationTrackEditor::AnimationTrackEditor() { track_vbox->set_h_size_flags(SIZE_EXPAND_FILL); scroll->set_enable_h_scroll(false); scroll->set_enable_v_scroll(true); - track_vbox->add_constant_override("separation", 0); + track_vbox->add_theme_constant_override("separation", 0); HBoxContainer *bottom_hb = memnew(HBoxContainer); add_child(bottom_hb); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 8de56a153e..7f13716b67 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -140,6 +140,7 @@ class AnimationTrackEdit : public Control { }; AnimationTimelineEdit *timeline; UndoRedo *undo_redo; + Popup *path_popup; LineEdit *path; Node *root; Control *play_position; //separate control used to draw so updates for only position changed are much faster diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index fc47a69a2c..7effe114ca 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -42,12 +42,12 @@ /// BOOL /// int AnimationTrackEditBool::get_key_height() const { - Ref<Texture2D> checked = get_icon("checked", "CheckBox"); + Ref<Texture2D> checked = get_theme_icon("checked", "CheckBox"); return checked->get_height(); } Rect2 AnimationTrackEditBool::get_key_rect(int p_index, float p_pixels_sec) { - Ref<Texture2D> checked = get_icon("checked", "CheckBox"); + Ref<Texture2D> checked = get_theme_icon("checked", "CheckBox"); return Rect2(-checked->get_width() / 2, 0, checked->get_width(), get_size().height); } @@ -58,7 +58,7 @@ bool AnimationTrackEditBool::is_key_selectable_by_distance() const { void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) { bool checked = get_animation()->track_get_key_value(get_track(), p_index); - Ref<Texture2D> icon = get_icon(checked ? "checked" : "unchecked", "CheckBox"); + Ref<Texture2D> icon = get_theme_icon(checked ? "checked" : "unchecked", "CheckBox"); Vector2 ofs(p_x - icon->get_width() / 2, int(get_size().height - icon->get_height()) / 2); @@ -71,7 +71,7 @@ void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x, draw_texture(icon, ofs); if (p_selected) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); draw_rect_clipped(Rect2(ofs, icon->get_size()), color, false); } } @@ -80,12 +80,12 @@ void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x, int AnimationTrackEditColor::get_key_height() const { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return font->get_height() * 0.8; } Rect2 AnimationTrackEditColor::get_key_rect(int p_index, float p_pixels_sec) { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; return Rect2(-fh / 2, 0, fh, get_size().height); } @@ -97,7 +97,7 @@ bool AnimationTrackEditColor::is_key_selectable_by_distance() const { void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right) { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = (font->get_height() * 0.8); int x_from = p_x + fh / 2 - 1; @@ -146,7 +146,7 @@ void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x, Color color = get_animation()->track_get_key_value(get_track(), p_index); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; Rect2 rect(Vector2(p_x - fh / 2, int(get_size().height - fh) / 2), Size2(fh, fh)); @@ -158,7 +158,7 @@ void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x, draw_rect_clipped(rect, color); if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect_clipped(rect, accent, false); } } @@ -185,7 +185,7 @@ int AnimationTrackEditAudio::get_key_height() const { return AnimationTrackEdit::get_key_height(); } - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return int(font->get_height() * 1.5); } Rect2 AnimationTrackEditAudio::get_key_rect(int p_index, float p_pixels_sec) { @@ -218,7 +218,7 @@ Rect2 AnimationTrackEditAudio::get_key_rect(int p_index, float p_pixels_sec) { return Rect2(0, 0, len * p_pixels_sec, get_size().height); } else { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; return Rect2(0, 0, fh, get_size().height); } @@ -279,7 +279,7 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, if (to_x <= from_x) return; - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); float fh = int(font->get_height() * 1.5); Rect2 rect = Rect2(from_x, (get_size().height - fh) / 2, to_x - from_x, fh); draw_rect(rect, Color(0.25, 0.25, 0.25)); @@ -306,19 +306,19 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, VS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color); if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } else { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh)); - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); draw_rect(rect, color); if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } @@ -344,7 +344,7 @@ int AnimationTrackEditSpriteFrame::get_key_height() const { return AnimationTrackEdit::get_key_height(); } - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return int(font->get_height() * 2); } Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_sec) { @@ -413,7 +413,7 @@ Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_se size = size.floor(); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int height = int(font->get_height() * 2); int width = height * size.width / size.height; @@ -507,7 +507,7 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in region.size = texture->get_size(); } - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int height = int(font->get_height() * 2); int width = height * region.size.width / region.size.height; @@ -520,7 +520,7 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in if (rect.position.x > p_clip_right) return; - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); Color bg = accent; bg.a = 0.15; @@ -551,7 +551,7 @@ int AnimationTrackEditSubAnim::get_key_height() const { return AnimationTrackEdit::get_key_height(); } - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return int(font->get_height() * 1.5); } Rect2 AnimationTrackEditSubAnim::get_key_rect(int p_index, float p_pixels_sec) { @@ -580,7 +580,7 @@ Rect2 AnimationTrackEditSubAnim::get_key_rect(int p_index, float p_pixels_sec) { return Rect2(0, 0, len * p_pixels_sec, get_size().height); } else { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; return Rect2(0, 0, fh, get_size().height); } @@ -633,12 +633,12 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_ if (to_x <= from_x) return; - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 1.5; Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh); - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); Color bg = color; bg.r = 1 - color.r; bg.g = 1 - color.g; @@ -682,19 +682,19 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_ } if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } else { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh)); - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); draw_rect(rect, color); if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } @@ -709,13 +709,13 @@ void AnimationTrackEditSubAnim::set_node(Object *p_object) { int AnimationTrackEditVolumeDB::get_key_height() const { - Ref<Texture2D> volume_texture = get_icon("ColorTrackVu", "EditorIcons"); + Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons"); return volume_texture->get_height() * 1.2; } void AnimationTrackEditVolumeDB::draw_bg(int p_clip_left, int p_clip_right) { - Ref<Texture2D> volume_texture = get_icon("ColorTrackVu", "EditorIcons"); + Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons"); int tex_h = volume_texture->get_height(); int y_from = (get_size().height - tex_h) / 2; @@ -727,7 +727,7 @@ void AnimationTrackEditVolumeDB::draw_bg(int p_clip_left, int p_clip_right) { void AnimationTrackEditVolumeDB::draw_fg(int p_clip_left, int p_clip_right) { - Ref<Texture2D> volume_texture = get_icon("ColorTrackVu", "EditorIcons"); + Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons"); int tex_h = volume_texture->get_height(); int y_from = (get_size().height - tex_h) / 2; int db0 = y_from + (24 / 80.0) * tex_h; @@ -762,12 +762,12 @@ void AnimationTrackEditVolumeDB::draw_key_link(int p_index, float p_pixels_sec, to_x = p_clip_right; } - Ref<Texture2D> volume_texture = get_icon("ColorTrackVu", "EditorIcons"); + Ref<Texture2D> volume_texture = get_theme_icon("ColorTrackVu", "EditorIcons"); int tex_h = volume_texture->get_height(); int y_from = (get_size().height - tex_h) / 2; - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); color.a *= 0.7; draw_line(Point2(from_x, y_from + h * tex_h), Point2(to_x, y_from + h_n * tex_h), color, 2); @@ -790,7 +790,7 @@ void AnimationTrackEditTypeAudio::_preview_changed(ObjectID p_which) { int AnimationTrackEditTypeAudio::get_key_height() const { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return int(font->get_height() * 1.5); } Rect2 AnimationTrackEditTypeAudio::get_key_rect(int p_index, float p_pixels_sec) { @@ -854,7 +854,7 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int } } - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); float fh = int(font->get_height() * 1.5); float len = stream->get_length(); @@ -928,7 +928,7 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int VS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color); - Color cut_color = get_color("accent_color", "Editor"); + Color cut_color = get_theme_color("accent_color", "Editor"); cut_color.a = 0.7; if (start_ofs > 0 && pixel_begin > p_clip_left) { draw_rect(Rect2(pixel_begin, rect.position.y, 1, rect.size.y), cut_color); @@ -938,7 +938,7 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int } if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } @@ -1133,7 +1133,7 @@ int AnimationTrackEditTypeAnimation::get_key_height() const { return AnimationTrackEdit::get_key_height(); } - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return int(font->get_height() * 1.5); } Rect2 AnimationTrackEditTypeAnimation::get_key_rect(int p_index, float p_pixels_sec) { @@ -1162,7 +1162,7 @@ Rect2 AnimationTrackEditTypeAnimation::get_key_rect(int p_index, float p_pixels_ return Rect2(0, 0, len * p_pixels_sec, get_size().height); } else { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; return Rect2(0, 0, fh, get_size().height); } @@ -1215,12 +1215,12 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec, if (to_x <= from_x) return; - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 1.5; Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh); - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); Color bg = color; bg.r = 1 - color.r; bg.g = 1 - color.g; @@ -1264,19 +1264,19 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec, } if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } else { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); int fh = font->get_height() * 0.8; Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh)); - Color color = get_color("font_color", "Label"); + Color color = get_theme_color("font_color", "Label"); draw_rect(rect, color); if (p_selected) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); draw_rect(rect, accent, false); } } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index ddd702fc6c..26bc6dfaf2 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -30,7 +30,7 @@ #include "code_editor.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "core/string_builder.h" #include "editor/editor_scale.h" @@ -69,10 +69,10 @@ GotoLineDialog::GotoLineDialog() { set_title(TTR("Go to Line")); VBoxContainer *vbc = memnew(VBoxContainer); - vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE); add_child(vbc); Label *l = memnew(Label); @@ -91,25 +91,25 @@ void FindReplaceBar::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { - find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); - find_next->set_icon(get_icon("MoveDown", "EditorIcons")); - hide_button->set_normal_texture(get_icon("Close", "EditorIcons")); - hide_button->set_hover_texture(get_icon("Close", "EditorIcons")); - hide_button->set_pressed_texture(get_icon("Close", "EditorIcons")); + find_prev->set_icon(get_theme_icon("MoveUp", "EditorIcons")); + find_next->set_icon(get_theme_icon("MoveDown", "EditorIcons")); + hide_button->set_normal_texture(get_theme_icon("Close", "EditorIcons")); + hide_button->set_hover_texture(get_theme_icon("Close", "EditorIcons")); + hide_button->set_pressed_texture(get_theme_icon("Close", "EditorIcons")); hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size()); } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { set_process_unhandled_input(is_visible_in_tree()); } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); - find_next->set_icon(get_icon("MoveDown", "EditorIcons")); - hide_button->set_normal_texture(get_icon("Close", "EditorIcons")); - hide_button->set_hover_texture(get_icon("Close", "EditorIcons")); - hide_button->set_pressed_texture(get_icon("Close", "EditorIcons")); + find_prev->set_icon(get_theme_icon("MoveUp", "EditorIcons")); + find_next->set_icon(get_theme_icon("MoveDown", "EditorIcons")); + hide_button->set_normal_texture(get_theme_icon("Close", "EditorIcons")); + hide_button->set_hover_texture(get_theme_icon("Close", "EditorIcons")); + hide_button->set_pressed_texture(get_theme_icon("Close", "EditorIcons")); hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size()); } else if (p_what == NOTIFICATION_THEME_CHANGED) { - matches_label->add_color_override("font_color", results_count > 0 ? get_color("font_color", "Label") : get_color("error_color", "Editor")); + matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); } } @@ -277,7 +277,7 @@ void FindReplaceBar::_replace_all() { } text_edit->set_v_scroll(vsval); - matches_label->add_color_override("font_color", rc > 0 ? get_color("font_color", "Label") : get_color("error_color", "Editor")); + matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); matches_label->set_text(vformat(TTR("%d replaced."), rc)); text_edit->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed")); @@ -331,7 +331,7 @@ void FindReplaceBar::_update_matches_label() { } else { matches_label->show(); - matches_label->add_color_override("font_color", results_count > 0 ? get_color("font_color", "Label") : get_color("error_color", "Editor")); + matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); matches_label->set_text(vformat(results_count == 1 ? TTR("%d match.") : TTR("%d matches."), results_count)); } } @@ -505,7 +505,7 @@ void FindReplaceBar::_search_text_changed(const String &p_text) { void FindReplaceBar::_search_text_entered(const String &p_text) { - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { search_prev(); } else { search_next(); @@ -517,7 +517,7 @@ void FindReplaceBar::_replace_text_entered(const String &p_text) { if (selection_only->is_pressed() && text_edit->is_selection_active()) { _replace_all(); _hide_bar(); - } else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + } else if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { _replace(); search_prev(); } else { @@ -712,7 +712,7 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMagnifyGesture> magnify_gesture = p_event; if (magnify_gesture.is_valid()) { - Ref<DynamicFont> font = text_editor->get_font("font"); + Ref<DynamicFont> font = text_editor->get_theme_font("font"); if (font.is_valid()) { if (font->get_size() != (int)font_size) { @@ -760,7 +760,7 @@ void CodeTextEditor::_zoom_changed() { } void CodeTextEditor::_reset_zoom() { - Ref<DynamicFont> font = text_editor->get_font("font"); // Reset source font size to default. + Ref<DynamicFont> font = text_editor->get_theme_font("font"); // Reset source font size to default. if (font.is_valid()) { EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14); @@ -828,41 +828,41 @@ Ref<Texture2D> CodeTextEditor::_get_completion_icon(const ScriptCodeCompletionOp Ref<Texture2D> tex; switch (p_option.kind) { case ScriptCodeCompletionOption::KIND_CLASS: { - if (has_icon(p_option.display, "EditorIcons")) { - tex = get_icon(p_option.display, "EditorIcons"); + if (has_theme_icon(p_option.display, "EditorIcons")) { + tex = get_theme_icon(p_option.display, "EditorIcons"); } else { - tex = get_icon("Object", "EditorIcons"); + tex = get_theme_icon("Object", "EditorIcons"); } } break; case ScriptCodeCompletionOption::KIND_ENUM: - tex = get_icon("Enum", "EditorIcons"); + tex = get_theme_icon("Enum", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_FILE_PATH: - tex = get_icon("File", "EditorIcons"); + tex = get_theme_icon("File", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_NODE_PATH: - tex = get_icon("NodePath", "EditorIcons"); + tex = get_theme_icon("NodePath", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_VARIABLE: - tex = get_icon("Variant", "EditorIcons"); + tex = get_theme_icon("Variant", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_CONSTANT: - tex = get_icon("MemberConstant", "EditorIcons"); + tex = get_theme_icon("MemberConstant", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_MEMBER: - tex = get_icon("MemberProperty", "EditorIcons"); + tex = get_theme_icon("MemberProperty", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_SIGNAL: - tex = get_icon("MemberSignal", "EditorIcons"); + tex = get_theme_icon("MemberSignal", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_FUNCTION: - tex = get_icon("MemberMethod", "EditorIcons"); + tex = get_theme_icon("MemberMethod", "EditorIcons"); break; case ScriptCodeCompletionOption::KIND_PLAIN_TEXT: - tex = get_icon("CubeMesh", "EditorIcons"); + tex = get_theme_icon("CubeMesh", "EditorIcons"); break; default: - tex = get_icon("String", "EditorIcons"); + tex = get_theme_icon("String", "EditorIcons"); break; } return tex; @@ -877,7 +877,7 @@ void CodeTextEditor::_font_resize_timeout() { bool CodeTextEditor::_add_font_size(int p_delta) { - Ref<DynamicFont> font = text_editor->get_font("font"); + Ref<DynamicFont> font = text_editor->get_theme_font("font"); if (font.is_valid()) { int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE); @@ -1454,18 +1454,18 @@ void CodeTextEditor::goto_error() { void CodeTextEditor::_update_font() { - text_editor->add_font_override("font", get_font("source", "EditorFonts")); + text_editor->add_theme_font_override("font", get_theme_font("source", "EditorFonts")); - error->add_font_override("font", get_font("status_source", "EditorFonts")); - error->add_color_override("font_color", get_color("error_color", "Editor")); + error->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts")); + error->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - Ref<Font> status_bar_font = get_font("status_source", "EditorFonts"); - error->add_font_override("font", status_bar_font); + Ref<Font> status_bar_font = get_theme_font("status_source", "EditorFonts"); + error->add_theme_font_override("font", status_bar_font); int count = status_bar->get_child_count(); for (int i = 0; i < count; i++) { Control *n = Object::cast_to<Control>(status_bar->get_child(i)); if (n) - n->add_font_override("font", status_bar_font); + n->add_theme_font_override("font", status_bar_font); } } @@ -1516,7 +1516,7 @@ void CodeTextEditor::_set_show_warnings_panel(bool p_show) { } void CodeTextEditor::_toggle_scripts_pressed() { - toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_icon("Back", "EditorIcons") : get_icon("Forward", "EditorIcons")); + toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons")); } void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { @@ -1540,8 +1540,8 @@ void CodeTextEditor::_notification(int p_what) { _update_font(); } break; case NOTIFICATION_ENTER_TREE: { - warning_button->set_icon(get_icon("NodeWarning", "EditorIcons")); - add_constant_override("separation", 4 * EDSCALE); + warning_button->set_icon(get_theme_icon("NodeWarning", "EditorIcons")); + add_theme_constant_override("separation", 4 * EDSCALE); } break; case NOTIFICATION_VISIBILITY_CHANGED: { if (toggle_scripts_button->is_visible()) { @@ -1650,7 +1650,7 @@ void CodeTextEditor::show_toggle_scripts_button() { } void CodeTextEditor::update_toggle_scripts_button() { - toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_icon("Back", "EditorIcons") : get_icon("Forward", "EditorIcons")); + toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons")); toggle_scripts_button->set_tooltip(TTR("Toggle Scripts Panel") + " (" + ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text() + ")"); } @@ -1729,8 +1729,8 @@ CodeTextEditor::CodeTextEditor() { warning_count_label->set_default_cursor_shape(CURSOR_POINTING_HAND); warning_count_label->set_mouse_filter(MOUSE_FILTER_STOP); warning_count_label->set_tooltip(TTR("Warnings")); - warning_count_label->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor")); - warning_count_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + warning_count_label->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor")); + warning_count_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts")); warning_count_label->connect("gui_input", callable_mp(this, &CodeTextEditor::_warning_label_gui_input)); is_warnings_panel_opened = false; @@ -1740,7 +1740,7 @@ CodeTextEditor::CodeTextEditor() { line_and_col_txt = memnew(Label); status_bar->add_child(line_and_col_txt); line_and_col_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); - line_and_col_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + line_and_col_txt->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts")); line_and_col_txt->set_tooltip(TTR("Line and column numbers.")); line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 60a15984ee..7f03fd30f0 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -115,7 +115,7 @@ void ConnectDialog::ok_pressed() { if (dst_method->get_text() == "") { error->set_text(TTR("Method in target node must be specified.")); - error->popup_centered_minsize(); + error->popup_centered(); return; } Node *target = tree->get_selected(); @@ -125,7 +125,7 @@ void ConnectDialog::ok_pressed() { if (target->get_script().is_null()) { if (!target->has_method(dst_method->get_text())) { error->set_text(TTR("Target method not found. Specify a valid method or attach a script to the target node.")); - error->popup_centered_minsize(); + error->popup_centered(); return; } } @@ -341,7 +341,7 @@ void ConnectDialog::init(ConnectionData c, bool bEdit) { void ConnectDialog::popup_dialog(const String &p_for_signal) { from_signal->set_text(p_for_signal); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); + error_label->add_theme_color_override("font_color", error_label->get_theme_color("error_color", "Editor")); if (!advanced->is_pressed()) error_label->set_visible(!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root())); @@ -351,14 +351,14 @@ void ConnectDialog::popup_dialog(const String &p_for_signal) { void ConnectDialog::_advanced_pressed() { if (advanced->is_pressed()) { - set_custom_minimum_size(Size2(900, 500) * EDSCALE); + set_min_size(Size2(900, 500) * EDSCALE); connect_to_label->set_text(TTR("Connect to Node:")); tree->set_connect_to_script_mode(false); vbc_right->show(); error_label->hide(); } else { - set_custom_minimum_size(Size2(600, 500) * EDSCALE); + set_min_size(Size2(600, 500) * EDSCALE); set_size(Size2()); connect_to_label->set_text(TTR("Connect to Script:")); tree->set_connect_to_script_mode(true); @@ -369,23 +369,23 @@ void ConnectDialog::_advanced_pressed() { _update_ok_enabled(); - set_position((get_viewport_rect().size - get_custom_minimum_size()) / 2); + popup_centered(); } ConnectDialog::ConnectDialog() { - set_custom_minimum_size(Size2(600, 500) * EDSCALE); + set_min_size(Size2(600, 500) * EDSCALE); VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); HBoxContainer *main_hb = memnew(HBoxContainer); vbc->add_child(main_hb); - main_hb->set_v_size_flags(SIZE_EXPAND_FILL); + main_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL); VBoxContainer *vbc_left = memnew(VBoxContainer); main_hb->add_child(vbc_left); - vbc_left->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL); from_signal = memnew(LineEdit); from_signal->set_editable(false); @@ -407,13 +407,13 @@ ConnectDialog::ConnectDialog() { vbc_right = memnew(VBoxContainer); main_hb->add_child(vbc_right); - vbc_right->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_right->set_h_size_flags(Control::SIZE_EXPAND_FILL); vbc_right->hide(); HBoxContainer *add_bind_hb = memnew(HBoxContainer); type_list = memnew(OptionButton); - type_list->set_h_size_flags(SIZE_EXPAND_FILL); + type_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_bind_hb->add_child(type_list); type_list->add_item("bool", Variant::BOOL); type_list->add_item("int", Variant::INT); @@ -451,7 +451,7 @@ ConnectDialog::ConnectDialog() { vbc_left->add_margin_child(TTR("Receiver Method:"), dstm_hb); dst_method = memnew(LineEdit); - dst_method->set_h_size_flags(SIZE_EXPAND_FILL); + dst_method->set_h_size_flags(Control::SIZE_EXPAND_FILL); dst_method->connect("text_entered", callable_mp(this, &ConnectDialog::_text_entered)); dstm_hb->add_child(dst_method); @@ -477,8 +477,6 @@ ConnectDialog::ConnectDialog() { oneshot->set_tooltip(TTR("Disconnects the signal after its first emission.")); vbc_right->add_child(oneshot); - set_as_toplevel(true); - cdbinds = memnew(ConnectDialogBinds); error = memnew(AcceptDialog); @@ -499,7 +497,7 @@ ConnectDialog::~ConnectDialog() { Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const { EditorHelpBit *help_bit = memnew(EditorHelpBit); - help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel")); + help_bit->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel")); help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); String text = TTR("Signal:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]"; @@ -909,21 +907,21 @@ void ConnectionsDock::update_tree() { else name = scr->get_class(); - if (has_icon(scr->get_class(), "EditorIcons")) { - icon = get_icon(scr->get_class(), "EditorIcons"); + if (has_theme_icon(scr->get_class(), "EditorIcons")) { + icon = get_theme_icon(scr->get_class(), "EditorIcons"); } } } else { ClassDB::get_signal_list(base, &node_signals2, true); - if (has_icon(base, "EditorIcons")) { - icon = get_icon(base, "EditorIcons"); + if (has_theme_icon(base, "EditorIcons")) { + icon = get_theme_icon(base, "EditorIcons"); } name = base; } if (!icon.is_valid()) { - icon = get_icon("Object", "EditorIcons"); + icon = get_theme_icon("Object", "EditorIcons"); } TreeItem *pitem = NULL; @@ -934,7 +932,7 @@ void ConnectionsDock::update_tree() { pitem->set_icon(0, icon); pitem->set_selectable(0, false); pitem->set_editable(0, false); - pitem->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + pitem->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor")); node_signals2.sort(); } @@ -970,7 +968,7 @@ void ConnectionsDock::update_tree() { sinfo["name"] = signal_name; sinfo["args"] = argnames; item->set_metadata(0, sinfo); - item->set_icon(0, get_icon("Signal", "EditorIcons")); + item->set_icon(0, get_theme_icon("Signal", "EditorIcons")); // Set tooltip with the signal's documentation. { @@ -1045,7 +1043,7 @@ void ConnectionsDock::update_tree() { item2->set_text(0, path); Connection cd = c; item2->set_metadata(0, cd); - item2->set_icon(0, get_icon("Slot", "EditorIcons")); + item2->set_icon(0, get_theme_icon("Slot", "EditorIcons")); } } @@ -1072,7 +1070,7 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) { tree->set_select_mode(Tree::SELECT_ROW); tree->set_hide_root(true); vbc->add_child(tree); - tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->set_allow_rmb_select(true); connect_button = memnew(Button); @@ -1083,11 +1081,9 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) { connect_button->connect("pressed", callable_mp(this, &ConnectionsDock::_connect_pressed)); connect_dialog = memnew(ConnectDialog); - connect_dialog->set_as_toplevel(true); add_child(connect_dialog); disconnect_all_dialog = memnew(ConfirmationDialog); - disconnect_all_dialog->set_as_toplevel(true); add_child(disconnect_all_dialog); disconnect_all_dialog->connect("confirmed", callable_mp(this, &ConnectionsDock::_disconnect_all)); disconnect_all_dialog->set_text(TTR("Are you sure you want to remove all connections from this signal?")); @@ -1110,7 +1106,7 @@ ConnectionsDock::ConnectionsDock(EditorNode *p_editor) { tree->connect("item_activated", callable_mp(this, &ConnectionsDock::_tree_item_activated)); tree->connect("item_rmb_selected", callable_mp(this, &ConnectionsDock::_rmb_pressed)); - add_constant_override("separation", 3 * EDSCALE); + add_theme_constant_override("separation", 3 * EDSCALE); } ConnectionsDock::~ConnectionsDock() { diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index b220e82f6c..6210b580ba 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -193,7 +193,7 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p item->set_text(0, p_type + " (" + ScriptServer::get_global_class_path(p_type).get_file() + ")"); } if (!can_instance) { - item->set_custom_color(0, get_color("disabled_font_color", "Editor")); + item->set_custom_color(0, search_options->get_theme_color("disabled_font_color", "Editor")); item->set_selectable(0, false); } else if (!(*to_select && (*to_select)->get_text(0) == search_box->get_text())) { String search_term = search_box->get_text().to_lower(); @@ -310,8 +310,8 @@ void CreateDialog::_update_search() { EditorData &ed = EditorNode::get_editor_data(); root->set_text(0, base_type); - if (has_icon(base_type, "EditorIcons")) { - root->set_icon(0, get_icon(base_type, "EditorIcons")); + if (search_options->has_theme_icon(base_type, "EditorIcons")) { + root->set_icon(0, search_options->get_theme_icon(base_type, "EditorIcons")); } TreeItem *to_select = search_box->get_text() == base_type ? root : NULL; @@ -460,23 +460,22 @@ void CreateDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { connect("confirmed", callable_mp(this, &CreateDialog::_confirmed)); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); - favorite->set_icon(get_icon("Favorites", "EditorIcons")); + favorite->set_icon(search_options->get_theme_icon("Favorites", "EditorIcons")); } break; case NOTIFICATION_EXIT_TREE: { disconnect("confirmed", callable_mp(this, &CreateDialog::_confirmed)); } break; case NOTIFICATION_VISIBILITY_CHANGED: { - if (is_visible_in_tree()) { + if (is_visible()) { search_box->call_deferred("grab_focus"); // still not visible search_box->select_all(); + } else { + EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "create_new_node", Rect2(get_position(), get_size())); + search_loaded_scripts.clear(); } } break; - case NOTIFICATION_POPUP_HIDE: { - EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "create_new_node", get_rect()); - search_loaded_scripts.clear(); - } break; } } @@ -562,7 +561,7 @@ void CreateDialog::_item_selected() { } void CreateDialog::_hide_requested() { - _closed(); // From WindowDialog. + _cancel_pressed(); // From AcceptDialog. } void CreateDialog::_favorite_toggled() { @@ -662,7 +661,7 @@ Variant CreateDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { ToolButton *tb = memnew(ToolButton); tb->set_icon(ti->get_icon(0)); tb->set_text(ti->get_text(0)); - set_drag_preview(tb); + favorites->set_drag_preview(tb); return d; } @@ -743,8 +742,6 @@ CreateDialog::CreateDialog() { is_replace_mode = false; - set_resizable(true); - HSplitContainer *hsc = memnew(HSplitContainer); add_child(hsc); @@ -754,7 +751,7 @@ CreateDialog::CreateDialog() { VBoxContainer *fav_vb = memnew(VBoxContainer); vsc->add_child(fav_vb); fav_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); - fav_vb->set_v_size_flags(SIZE_EXPAND_FILL); + fav_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); favorites = memnew(Tree); fav_vb->add_margin_child(TTR("Favorites:"), favorites, true); @@ -763,13 +760,16 @@ CreateDialog::CreateDialog() { favorites->set_allow_reselect(true); favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected)); favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated)); - favorites->set_drag_forwarding(this); - favorites->add_constant_override("draw_guides", 1); +#ifndef _MSC_VER +#warning cant forward drag data to a non control, must be fixed +#endif + //favorites->set_drag_forwarding(this); + favorites->add_theme_constant_override("draw_guides", 1); VBoxContainer *rec_vb = memnew(VBoxContainer); vsc->add_child(rec_vb); rec_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); - rec_vb->set_v_size_flags(SIZE_EXPAND_FILL); + rec_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); recent = memnew(Tree); rec_vb->add_margin_child(TTR("Recent:"), recent, true); @@ -778,15 +778,15 @@ CreateDialog::CreateDialog() { recent->set_allow_reselect(true); recent->connect("cell_selected", callable_mp(this, &CreateDialog::_history_selected)); recent->connect("item_activated", callable_mp(this, &CreateDialog::_history_activated)); - recent->add_constant_override("draw_guides", 1); + recent->add_theme_constant_override("draw_guides", 1); VBoxContainer *vbc = memnew(VBoxContainer); hsc->add_child(vbc); vbc->set_custom_minimum_size(Size2(300, 0) * EDSCALE); - vbc->set_h_size_flags(SIZE_EXPAND_FILL); + vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); HBoxContainer *search_hb = memnew(HBoxContainer); search_box = memnew(LineEdit); - search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); search_hb->add_child(search_box); favorite = memnew(Button); favorite->set_flat(true); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index f4a8102b79..5c9b977247 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -53,8 +53,8 @@ EditorDebuggerNode::EditorDebuggerNode() { if (!singleton) singleton = this; - add_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT)); - add_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT)); + add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT)); + add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT)); tabs = memnew(TabContainer); tabs->set_tab_align(TabContainer::ALIGN_LEFT); @@ -64,7 +64,7 @@ EditorDebuggerNode::EditorDebuggerNode() { Ref<StyleBoxEmpty> empty; empty.instance(); - tabs->add_style_override("panel", empty); + tabs->add_theme_style_override("panel", empty); auto_switch_remote_scene_tree = EDITOR_DEF("debugger/auto_switch_to_remote_scene_tree", false); _add_debugger(); @@ -110,7 +110,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { if (tabs->get_tab_count() > 1) { node->clear_style(); tabs->set_tabs_visible(true); - tabs->add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles")); + tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles")); } return node; @@ -223,10 +223,10 @@ void EditorDebuggerNode::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { if (tabs->get_tab_count() > 1) { - add_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT)); - add_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT)); + add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT)); + add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT)); - tabs->add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles")); + tabs->add_theme_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles")); } } break; default: @@ -262,9 +262,9 @@ void EditorDebuggerNode::_notification(int p_what) { } else { debugger_button->set_text(TTR("Debugger") + " (" + itos(error_count + warning_count) + ")"); if (error_count == 0) { - debugger_button->set_icon(get_icon("Warning", "EditorIcons")); + debugger_button->set_icon(get_theme_icon("Warning", "EditorIcons")); } else { - debugger_button->set_icon(get_icon("Error", "EditorIcons")); + debugger_button->set_icon(get_theme_icon("Error", "EditorIcons")); } } last_error_count = error_count; @@ -371,7 +371,6 @@ void EditorDebuggerNode::set_script_debug_button(MenuButton *p_button) { script_menu->set_text(TTR("Debug")); script_menu->set_switch_on_hover(true); PopupMenu *p = script_menu->get_popup(); - p->set_hide_on_window_lose_focus(true); p->add_shortcut(ED_GET_SHORTCUT("debugger/step_into"), DEBUG_STEP); p->add_shortcut(ED_GET_SHORTCUT("debugger/step_over"), DEBUG_NEXT); p->add_separator(); diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index 019a5d0fc3..427b929ccb 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -33,6 +33,7 @@ #include "editor/editor_node.h" #include "scene/debugger/scene_debugger.h" #include "scene/resources/packed_scene.h" +#include "servers/display_server.h" EditorDebuggerTree::EditorDebuggerTree() { set_v_size_flags(SIZE_EXPAND_FILL); @@ -106,9 +107,9 @@ void EditorDebuggerTree::_scene_tree_rmb_selected(const Vector2 &p_position) { item->select(0); item_menu->clear(); - item_menu->add_icon_item(get_icon("CreateNewSceneFrom", "EditorIcons"), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE); - item_menu->add_icon_item(get_icon("CopyNodePath", "EditorIcons"), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH); - item_menu->set_global_position(get_global_mouse_position()); + item_menu->add_icon_item(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE); + item_menu->add_icon_item(get_theme_icon("CopyNodePath", "EditorIcons"), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH); + item_menu->set_position(get_screen_transform().xform(get_local_mouse_position())); item_menu->popup(); } @@ -229,7 +230,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) { case ITEM_MENU_SAVE_REMOTE_NODE: { file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); List<String> extensions; Ref<PackedScene> sd = memnew(PackedScene); @@ -257,7 +258,7 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) { text = text.substr(slash + 1); } } - OS::get_singleton()->set_clipboard(text); + DisplayServer::get_singleton()->clipboard_set(text); } break; } } diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp index 21ef66d1aa..b8c795d9ca 100644 --- a/editor/debugger/editor_network_profiler.cpp +++ b/editor/debugger/editor_network_profiler.cpp @@ -41,14 +41,14 @@ void EditorNetworkProfiler::_bind_methods() { void EditorNetworkProfiler::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - activate->set_icon(get_icon("Play", "EditorIcons")); - clear_button->set_icon(get_icon("Clear", "EditorIcons")); - incoming_bandwidth_text->set_right_icon(get_icon("ArrowDown", "EditorIcons")); - outgoing_bandwidth_text->set_right_icon(get_icon("ArrowUp", "EditorIcons")); + activate->set_icon(get_theme_icon("Play", "EditorIcons")); + clear_button->set_icon(get_theme_icon("Clear", "EditorIcons")); + incoming_bandwidth_text->set_right_icon(get_theme_icon("ArrowDown", "EditorIcons")); + outgoing_bandwidth_text->set_right_icon(get_theme_icon("ArrowUp", "EditorIcons")); // This needs to be done here to set the faded color when the profiler is first opened - incoming_bandwidth_text->add_color_override("font_color_uneditable", get_color("font_color", "Editor") * Color(1, 1, 1, 0.5)); - outgoing_bandwidth_text->add_color_override("font_color_uneditable", get_color("font_color", "Editor") * Color(1, 1, 1, 0.5)); + incoming_bandwidth_text->add_theme_color_override("font_color_uneditable", get_theme_color("font_color", "Editor") * Color(1, 1, 1, 0.5)); + outgoing_bandwidth_text->add_theme_color_override("font_color_uneditable", get_theme_color("font_color", "Editor") * Color(1, 1, 1, 0.5)); } } @@ -77,10 +77,10 @@ void EditorNetworkProfiler::_update_frame() { void EditorNetworkProfiler::_activate_pressed() { if (activate->is_pressed()) { - activate->set_icon(get_icon("Stop", "EditorIcons")); + activate->set_icon(get_theme_icon("Stop", "EditorIcons")); activate->set_text(TTR("Stop")); } else { - activate->set_icon(get_icon("Play", "EditorIcons")); + activate->set_icon(get_theme_icon("Play", "EditorIcons")); activate->set_text(TTR("Start")); } emit_signal("enable_profiling", activate->is_pressed()); @@ -118,12 +118,12 @@ void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) { outgoing_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_outgoing))); // Make labels more prominent when the bandwidth is greater than 0 to attract user attention - incoming_bandwidth_text->add_color_override( + incoming_bandwidth_text->add_theme_color_override( "font_color_uneditable", - get_color("font_color", "Editor") * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5)); - outgoing_bandwidth_text->add_color_override( + get_theme_color("font_color", "Editor") * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5)); + outgoing_bandwidth_text->add_theme_color_override( "font_color_uneditable", - get_color("font_color", "Editor") * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5)); + get_theme_color("font_color", "Editor") * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5)); } bool EditorNetworkProfiler::is_profiling() { @@ -133,7 +133,7 @@ bool EditorNetworkProfiler::is_profiling() { EditorNetworkProfiler::EditorNetworkProfiler() { HBoxContainer *hb = memnew(HBoxContainer); - hb->add_constant_override("separation", 8 * EDSCALE); + hb->add_theme_constant_override("separation", 8 * EDSCALE); add_child(hb); activate = memnew(Button); diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index ca4979563d..1577e24ac0 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -132,11 +132,11 @@ String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_ca Color EditorProfiler::_get_color_from_signature(const StringName &p_signature) const { - Color bc = get_color("error_color", "Editor"); + Color bc = get_theme_color("error_color", "Editor"); double rot = ABS(double(p_signature.hash()) / double(0x7FFFFFFF)); Color c; c.set_hsv(rot, bc.get_s(), bc.get_v()); - return c.linear_interpolate(get_color("base_color", "Editor"), 0.07); + return c.linear_interpolate(get_theme_color("base_color", "Editor"), 0.07); } void EditorProfiler::_item_edited() { @@ -176,7 +176,7 @@ void EditorProfiler::_update_plot() { } uint8_t *wr = graph_image.ptrw(); - const Color background_color = get_color("dark_color_2", "Editor"); + const Color background_color = get_theme_color("dark_color_2", "Editor"); // Clear the previous frame and set the background color. for (int i = 0; i < desired_len; i += 4) { @@ -420,10 +420,10 @@ void EditorProfiler::_update_frame() { void EditorProfiler::_activate_pressed() { if (activate->is_pressed()) { - activate->set_icon(get_icon("Stop", "EditorIcons")); + activate->set_icon(get_theme_icon("Stop", "EditorIcons")); activate->set_text(TTR("Stop")); } else { - activate->set_icon(get_icon("Play", "EditorIcons")); + activate->set_icon(get_theme_icon("Play", "EditorIcons")); activate->set_text(TTR("Start")); } emit_signal("enable_profiling", activate->is_pressed()); @@ -438,8 +438,8 @@ void EditorProfiler::_clear_pressed() { void EditorProfiler::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - activate->set_icon(get_icon("Play", "EditorIcons")); - clear_button->set_icon(get_icon("Clear", "EditorIcons")); + activate->set_icon(get_theme_icon("Play", "EditorIcons")); + clear_button->set_icon(get_theme_icon("Clear", "EditorIcons")); } } @@ -712,7 +712,7 @@ EditorProfiler::EditorProfiler() { hb->add_child(cursor_metric_edit); cursor_metric_edit->connect("value_changed", callable_mp(this, &EditorProfiler::_cursor_metric_changed)); - hb->add_constant_override("separation", 8 * EDSCALE); + hb->add_theme_constant_override("separation", 8 * EDSCALE); h_split = memnew(HSplitContainer); add_child(h_split); diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 48425062d1..d2edba5970 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -128,11 +128,11 @@ String EditorVisualProfiler::_get_time_as_text(float p_time) { Color EditorVisualProfiler::_get_color_from_signature(const StringName &p_signature) const { - Color bc = get_color("error_color", "Editor"); + Color bc = get_theme_color("error_color", "Editor"); double rot = ABS(double(p_signature.hash()) / double(0x7FFFFFFF)); Color c; c.set_hsv(rot, bc.get_s(), bc.get_v()); - return c.linear_interpolate(get_color("base_color", "Editor"), 0.07); + return c.linear_interpolate(get_theme_color("base_color", "Editor"), 0.07); } void EditorVisualProfiler::_item_selected() { @@ -327,7 +327,7 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) { int cursor_metric = _get_cursor_index(); - Ref<Texture> track_icon = get_icon("TrackColor", "EditorIcons"); + Ref<Texture> track_icon = get_theme_icon("TrackColor", "EditorIcons"); ERR_FAIL_INDEX(cursor_metric, frame_metrics.size()); @@ -418,11 +418,11 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) { void EditorVisualProfiler::_activate_pressed() { if (activate->is_pressed()) { - activate->set_icon(get_icon("Stop", "EditorIcons")); + activate->set_icon(get_theme_icon("Stop", "EditorIcons")); activate->set_text(TTR("Stop")); _clear_pressed(); //always clear on start } else { - activate->set_icon(get_icon("Play", "EditorIcons")); + activate->set_icon(get_theme_icon("Play", "EditorIcons")); activate->set_text(TTR("Start")); } emit_signal("enable_profiling", activate->is_pressed()); @@ -437,8 +437,8 @@ void EditorVisualProfiler::_clear_pressed() { void EditorVisualProfiler::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - activate->set_icon(get_icon("Play", "EditorIcons")); - clear_button->set_icon(get_icon("Clear", "EditorIcons")); + activate->set_icon(get_theme_icon("Play", "EditorIcons")); + clear_button->set_icon(get_theme_icon("Clear", "EditorIcons")); } } @@ -446,7 +446,7 @@ void EditorVisualProfiler::_graph_tex_draw() { if (last_metric < 0) return; - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); if (seeking) { int max_frames = frame_metrics.size(); @@ -777,7 +777,7 @@ EditorVisualProfiler::EditorVisualProfiler() { hb->add_child(cursor_metric_edit); cursor_metric_edit->connect("value_changed", callable_mp(this, &EditorVisualProfiler::_cursor_metric_changed)); - hb->add_constant_override("separation", 8 * EDSCALE); + hb->add_theme_constant_override("separation", 8 * EDSCALE); h_split = memnew(HSplitContainer); add_child(h_split); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index dcb1611f71..7526111eef 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -58,6 +58,7 @@ #include "scene/gui/texture_button.h" #include "scene/gui/tree.h" #include "scene/resources/packed_scene.h" +#include "servers/display_server.h" using CameraOverride = EditorDebuggerNode::CameraOverride; @@ -73,15 +74,15 @@ void ScriptEditorDebugger::_put_msg(String p_message, Array p_data) { void ScriptEditorDebugger::debug_copy() { String msg = reason->get_text(); if (msg == "") return; - OS::get_singleton()->set_clipboard(msg); + DisplayServer::get_singleton()->clipboard_set(msg); } void ScriptEditorDebugger::debug_skip_breakpoints() { skip_breakpoints_value = !skip_breakpoints_value; if (skip_breakpoints_value) - skip_breakpoints->set_icon(get_icon("DebugSkipBreakpointsOn", "EditorIcons")); + skip_breakpoints->set_icon(get_theme_icon("DebugSkipBreakpointsOn", "EditorIcons")); else - skip_breakpoints->set_icon(get_icon("DebugSkipBreakpointsOff", "EditorIcons")); + skip_breakpoints->set_icon(get_theme_icon("DebugSkipBreakpointsOff", "EditorIcons")); Array msg; msg.push_back(skip_breakpoints_value); @@ -116,7 +117,7 @@ void ScriptEditorDebugger::debug_continue() { // Allow focus stealing only if we actually run this client for security. if (remote_pid && EditorNode::get_singleton()->has_child_process(remote_pid)) - OS::get_singleton()->enable_for_stealing_focus(remote_pid); + DisplayServer::get_singleton()->enable_for_stealing_focus(remote_pid); _clear_execution(); _put_msg("continue", Array()); @@ -129,15 +130,15 @@ void ScriptEditorDebugger::update_tabs() { } else { errors_tab->set_name(TTR("Errors") + " (" + itos(error_count + warning_count) + ")"); if (error_count == 0) { - tabs->set_tab_icon(errors_tab->get_index(), get_icon("Warning", "EditorIcons")); + tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon("Warning", "EditorIcons")); } else { - tabs->set_tab_icon(errors_tab->get_index(), get_icon("Error", "EditorIcons")); + tabs->set_tab_icon(errors_tab->get_index(), get_theme_icon("Error", "EditorIcons")); } } } void ScriptEditorDebugger::clear_style() { - tabs->add_style_override("panel", NULL); + tabs->add_theme_style_override("panel", NULL); } void ScriptEditorDebugger::save_node(ObjectID p_id, const String &p_file) { @@ -253,7 +254,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da _update_buttons_state(); _set_reason_text(error, MESSAGE_ERROR); emit_signal("breaked", true, can_continue); - OS::get_singleton()->move_window_to_foreground(); + DisplayServer::get_singleton()->window_move_to_foreground(); if (error != "") { tabs->set_current_tab(0); } @@ -310,8 +311,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da it->set_text(3, String::humanize_size(bytes)); total += bytes; - if (has_icon(type, "EditorIcons")) - it->set_icon(0, get_icon(type, "EditorIcons")); + if (has_theme_icon(type, "EditorIcons")) + it->set_icon(0, get_theme_icon(type, "EditorIcons")); } vmem_total->set_tooltip(TTR("Bytes:") + " " + itos(total)); @@ -442,7 +443,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da TreeItem *error = error_tree->create_item(r); error->set_collapsed(true); - error->set_icon(0, get_icon(oe.warning ? "Warning" : "Error", "EditorIcons")); + error->set_icon(0, get_theme_icon(oe.warning ? "Warning" : "Error", "EditorIcons")); error->set_text(0, time); error->set_text_align(0, TreeItem::ALIGN_LEFT); @@ -660,13 +661,13 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType p_type) { switch (p_type) { case MESSAGE_ERROR: - reason->add_color_override("font_color", get_color("error_color", "Editor")); + reason->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); break; case MESSAGE_WARNING: - reason->add_color_override("font_color", get_color("warning_color", "Editor")); + reason->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); break; default: - reason->add_color_override("font_color", get_color("success_color", "Editor")); + reason->add_theme_color_override("font_color", get_theme_color("success_color", "Editor")); } reason->set_text(p_reason); reason->set_tooltip(p_reason.word_wrap(80)); @@ -693,8 +694,8 @@ void ScriptEditorDebugger::_performance_draw() { info_message->hide(); - Ref<StyleBox> graph_sb = get_stylebox("normal", "TextEdit"); - Ref<Font> graph_font = get_font("font", "TextEdit"); + Ref<StyleBox> graph_sb = get_theme_stylebox("normal", "TextEdit"); + Ref<Font> graph_font = get_theme_font("font", "TextEdit"); int cols = Math::ceil(Math::sqrt((float)which.size())); int rows = Math::ceil((float)which.size() / cols); @@ -714,7 +715,7 @@ void ScriptEditorDebugger::_performance_draw() { r.position += graph_sb->get_offset(); r.size -= graph_sb->get_minimum_size(); int pi = which[i]; - Color c = get_color("accent_color", "Editor"); + Color c = get_theme_color("accent_color", "Editor"); float h = (float)which[i] / (float)(perf_items.size()); // Use a darker color on light backgrounds for better visibility float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55; @@ -753,20 +754,20 @@ void ScriptEditorDebugger::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - skip_breakpoints->set_icon(get_icon("DebugSkipBreakpointsOff", "EditorIcons")); - copy->set_icon(get_icon("ActionCopy", "EditorIcons")); + skip_breakpoints->set_icon(get_theme_icon("DebugSkipBreakpointsOff", "EditorIcons")); + copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); - step->set_icon(get_icon("DebugStep", "EditorIcons")); - next->set_icon(get_icon("DebugNext", "EditorIcons")); - dobreak->set_icon(get_icon("Pause", "EditorIcons")); - docontinue->set_icon(get_icon("DebugContinue", "EditorIcons")); + step->set_icon(get_theme_icon("DebugStep", "EditorIcons")); + next->set_icon(get_theme_icon("DebugNext", "EditorIcons")); + dobreak->set_icon(get_theme_icon("Pause", "EditorIcons")); + docontinue->set_icon(get_theme_icon("DebugContinue", "EditorIcons")); le_set->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_live_edit_set)); le_clear->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_live_edit_clear)); error_tree->connect("item_selected", callable_mp(this, &ScriptEditorDebugger::_error_selected)); error_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_error_activated)); - vmem_refresh->set_icon(get_icon("Reload", "EditorIcons")); + vmem_refresh->set_icon(get_theme_icon("Reload", "EditorIcons")); - reason->add_color_override("font_color", get_color("error_color", "Editor")); + reason->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); } break; case NOTIFICATION_PROCESS: { @@ -829,16 +830,16 @@ void ScriptEditorDebugger::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - if (tabs->has_stylebox_override("panel")) { - tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles")); + if (tabs->has_theme_stylebox_override("panel")) { + tabs->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles")); } - copy->set_icon(get_icon("ActionCopy", "EditorIcons")); - step->set_icon(get_icon("DebugStep", "EditorIcons")); - next->set_icon(get_icon("DebugNext", "EditorIcons")); - dobreak->set_icon(get_icon("Pause", "EditorIcons")); - docontinue->set_icon(get_icon("DebugContinue", "EditorIcons")); - vmem_refresh->set_icon(get_icon("Reload", "EditorIcons")); + copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); + step->set_icon(get_theme_icon("DebugStep", "EditorIcons")); + next->set_icon(get_theme_icon("DebugNext", "EditorIcons")); + dobreak->set_icon(get_theme_icon("Pause", "EditorIcons")); + docontinue->set_icon(get_theme_icon("DebugContinue", "EditorIcons")); + vmem_refresh->set_icon(get_theme_icon("Reload", "EditorIcons")); } break; } } @@ -978,7 +979,7 @@ void ScriptEditorDebugger::_stack_dump_frame_selected() { void ScriptEditorDebugger::_export_csv() { - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_dialog->popup_centered_ratio(); } @@ -1388,7 +1389,7 @@ void ScriptEditorDebugger::_error_tree_item_rmb_selected(const Vector2 &p_pos) { item_menu->set_size(Size2(1, 1)); if (error_tree->is_anything_selected()) { - item_menu->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Error"), 0); + item_menu->add_icon_item(get_theme_icon("ActionCopy", "EditorIcons"), TTR("Copy Error"), 0); } if (item_menu->get_item_count() > 0) { @@ -1404,9 +1405,9 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { String type; - if (ti->get_icon(0) == get_icon("Warning", "EditorIcons")) { + if (ti->get_icon(0) == get_theme_icon("Warning", "EditorIcons")) { type = "W "; - } else if (ti->get_icon(0) == get_icon("Error", "EditorIcons")) { + } else if (ti->get_icon(0) == get_theme_icon("Error", "EditorIcons")) { type = "E "; } @@ -1420,7 +1421,7 @@ void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { ci = ci->get_next(); } - OS::get_singleton()->set_clipboard(text); + DisplayServer::get_singleton()->clipboard_set(text); } void ScriptEditorDebugger::_tab_changed(int p_tab) { @@ -1461,7 +1462,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { tabs = memnew(TabContainer); tabs->set_tab_align(TabContainer::ALIGN_LEFT); - tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles")); + tabs->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("DebuggerPanel", "EditorStyles")); tabs->connect("tab_changed", callable_mp(this, &ScriptEditorDebugger::_tab_changed)); add_child(tabs); diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index 5a0accd45c..8ba706d4b3 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -174,7 +174,7 @@ void DependencyEditor::_update_list() { TreeItem *root = tree->create_item(); - Ref<Texture2D> folder = get_icon("folder", "FileDialog"); + Ref<Texture2D> folder = tree->get_theme_icon("folder", "FileDialog"); bool broken = false; @@ -256,7 +256,7 @@ DependencyEditor::DependencyEditor() { vb->add_child(hbc); MarginContainer *mc = memnew(MarginContainer); - mc->set_v_size_flags(SIZE_EXPAND_FILL); + mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); mc->add_child(tree); vb->add_child(mc); @@ -264,7 +264,7 @@ DependencyEditor::DependencyEditor() { set_title(TTR("Dependency Editor")); search = memnew(EditorFileDialog); search->connect("file_selected", callable_mp(this, &DependencyEditor::_searched)); - search->set_mode(EditorFileDialog::MODE_OPEN_FILE); + search->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); search->set_title(TTR("Search Replacement Resource:")); add_child(search); } @@ -422,17 +422,17 @@ void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<Removed if (!tree_items.has(rd.dependency_folder)) { TreeItem *folder_item = owners->create_item(owners->get_root()); folder_item->set_text(0, rd.dependency_folder); - folder_item->set_icon(0, get_icon("Folder", "EditorIcons")); + folder_item->set_icon(0, owners->get_theme_icon("Folder", "EditorIcons")); tree_items[rd.dependency_folder] = folder_item; } TreeItem *dependency_item = owners->create_item(tree_items[rd.dependency_folder]); dependency_item->set_text(0, rd.dependency); - dependency_item->set_icon(0, get_icon("Warning", "EditorIcons")); + dependency_item->set_icon(0, owners->get_theme_icon("Warning", "EditorIcons")); tree_items[rd.dependency] = dependency_item; } else { TreeItem *dependency_item = owners->create_item(owners->get_root()); dependency_item->set_text(0, rd.dependency); - dependency_item->set_icon(0, get_icon("Warning", "EditorIcons")); + dependency_item->set_icon(0, owners->get_theme_icon("Warning", "EditorIcons")); tree_items[rd.dependency] = dependency_item; } } @@ -580,7 +580,7 @@ DependencyRemoveDialog::DependencyRemoveDialog() { owners = memnew(Tree); owners->set_hide_root(true); vb->add_child(owners); - owners->set_v_size_flags(SIZE_EXPAND_FILL); + owners->set_v_size_flags(Control::SIZE_EXPAND_FILL); } ////////////// @@ -636,9 +636,9 @@ DependencyErrorDialog::DependencyErrorDialog() { files = memnew(Tree); files->set_hide_root(true); vb->add_margin_child(TTR("Load failed due to missing dependencies:"), files, true); - files->set_v_size_flags(SIZE_EXPAND_FILL); + files->set_v_size_flags(Control::SIZE_EXPAND_FILL); - set_custom_minimum_size(Size2(500, 220) * EDSCALE); + set_min_size(Size2(500, 220) * EDSCALE); get_ok()->set_text(TTR("Open Anyway")); get_cancel()->set_text(TTR("Close")); @@ -662,7 +662,7 @@ void OrphanResourcesDialog::ok_pressed() { return; delete_confirm->set_text(vformat(TTR("Permanently delete %d item(s)? (No undo!)"), paths.size())); - delete_confirm->popup_centered_clamped(delete_confirm->get_minimum_size()); + delete_confirm->popup_centered(); } bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMap<String, int> &refs, TreeItem *p_parent) { @@ -678,7 +678,7 @@ bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMa if (p_parent) { dir_item = files->create_item(p_parent); dir_item->set_text(0, efsd->get_subdir(i)->get_name()); - dir_item->set_icon(0, get_icon("folder", "FileDialog")); + dir_item->set_icon(0, files->get_theme_icon("folder", "FileDialog")); } bool children = _fill_owners(efsd->get_subdir(i), refs, dir_item); @@ -717,7 +717,7 @@ bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd, HashMa int ds = efsd->get_file_deps(i).size(); ti->set_text(1, itos(ds)); if (ds) { - ti->add_button(1, get_icon("GuiVisibilityVisible", "EditorIcons"), -1, false, TTR("Show Dependencies")); + ti->add_button(1, files->get_theme_icon("GuiVisibilityVisible", "EditorIcons"), -1, false, TTR("Show Dependencies")); } ti->set_metadata(0, path); has_children = true; diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index a223cee360..33ee95c2d8 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -37,20 +37,23 @@ #include "core/version.h" #include "core/version_hash.gen.h" +void EditorAbout::_theme_changed() { + + Control *base = EditorNode::get_singleton()->get_gui_base(); + Ref<Font> font = base->get_theme_font("source", "EditorFonts"); + _tpl_text->add_theme_font_override("normal_font", font); + _tpl_text->add_theme_constant_override("line_separation", 6 * EDSCALE); + _license_text->add_theme_font_override("normal_font", font); + _license_text->add_theme_constant_override("line_separation", 6 * EDSCALE); + _logo->set_texture(base->get_theme_icon("Logo", "EditorIcons")); +} + void EditorAbout::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - - Control *base = EditorNode::get_singleton()->get_gui_base(); - Ref<Font> font = base->get_font("source", "EditorFonts"); - _tpl_text->add_font_override("normal_font", font); - _tpl_text->add_constant_override("line_separation", 6 * EDSCALE); - _license_text->add_font_override("normal_font", font); - _license_text->add_constant_override("line_separation", 6 * EDSCALE); - _logo->set_texture(base->get_icon("Logo", "EditorIcons")); + case NOTIFICATION_ENTER_TREE: { + _theme_changed(); } break; } } @@ -95,7 +98,7 @@ ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<St il->set_same_column_width(true); il->set_auto_height(true); il->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); - il->add_constant_override("hseparation", 16 * EDSCALE); + il->add_theme_constant_override("hseparation", 16 * EDSCALE); while (*names_ptr) { il->add_item(String::utf8(*names_ptr++), NULL, false); } @@ -115,13 +118,13 @@ EditorAbout::EditorAbout() { set_title(TTR("Thanks from the Godot community!")); set_hide_on_ok(true); - set_resizable(true); VBoxContainer *vbc = memnew(VBoxContainer); + vbc->connect("theme_changed", callable_mp(this, &EditorAbout::_theme_changed)); HBoxContainer *hbc = memnew(HBoxContainer); hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->set_alignment(BoxContainer::ALIGN_CENTER); - hbc->add_constant_override("separation", 30 * EDSCALE); + hbc->add_theme_constant_override("separation", 30 * EDSCALE); add_child(vbc); vbc->add_child(hbc); diff --git a/editor/editor_about.h b/editor/editor_about.h index 51438ee953..83e9e9f490 100644 --- a/editor/editor_about.h +++ b/editor/editor_about.h @@ -57,6 +57,8 @@ private: RichTextLabel *_tpl_text; TextureRect *_logo; + void _theme_changed(); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index e26d44025f..d61fe8f08a 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -112,17 +112,17 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { Map<String, Ref<Texture2D>> extension_guess; { - extension_guess["png"] = get_icon("ImageTexture", "EditorIcons"); - extension_guess["jpg"] = get_icon("ImageTexture", "EditorIcons"); - extension_guess["atlastex"] = get_icon("AtlasTexture", "EditorIcons"); - extension_guess["scn"] = get_icon("PackedScene", "EditorIcons"); - extension_guess["tscn"] = get_icon("PackedScene", "EditorIcons"); - extension_guess["shader"] = get_icon("Shader", "EditorIcons"); - extension_guess["gd"] = get_icon("GDScript", "EditorIcons"); - extension_guess["vs"] = get_icon("VisualScript", "EditorIcons"); + extension_guess["png"] = tree->get_theme_icon("ImageTexture", "EditorIcons"); + extension_guess["jpg"] = tree->get_theme_icon("ImageTexture", "EditorIcons"); + extension_guess["atlastex"] = tree->get_theme_icon("AtlasTexture", "EditorIcons"); + extension_guess["scn"] = tree->get_theme_icon("PackedScene", "EditorIcons"); + extension_guess["tscn"] = tree->get_theme_icon("PackedScene", "EditorIcons"); + extension_guess["shader"] = tree->get_theme_icon("Shader", "EditorIcons"); + extension_guess["gd"] = tree->get_theme_icon("GDScript", "EditorIcons"); + extension_guess["vs"] = tree->get_theme_icon("VisualScript", "EditorIcons"); } - Ref<Texture2D> generic_extension = get_icon("Object", "EditorIcons"); + Ref<Texture2D> generic_extension = tree->get_theme_icon("Object", "EditorIcons"); unzClose(pkg); @@ -131,7 +131,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { TreeItem *root = tree->create_item(); root->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); root->set_checked(0, true); - root->set_icon(0, get_icon("folder", "FileDialog")); + root->set_icon(0, tree->get_theme_icon("folder", "FileDialog")); root->set_text(0, "res://"); root->set_editable(0, true); Map<String, TreeItem *> dir_map; @@ -180,7 +180,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { if (isdir) { dir_map[path] = ti; ti->set_text(0, path.get_file() + "/"); - ti->set_icon(0, get_icon("folder", "FileDialog")); + ti->set_icon(0, tree->get_theme_icon("folder", "FileDialog")); ti->set_metadata(0, String()); } else { String file = path.get_file(); @@ -194,7 +194,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { String res_path = "res://" + path; if (FileAccess::exists(res_path)) { - ti->set_custom_color(0, get_color("error_color", "Editor")); + ti->set_custom_color(0, tree->get_theme_color("error_color", "Editor")); ti->set_tooltip(0, vformat(TTR("%s (Already Exists)"), res_path)); ti->set_checked(0, false); } else { diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index d77216697e..55bdd2070b 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -30,8 +30,8 @@ #include "editor_audio_buses.h" +#include "core/input/input_filter.h" #include "core/io/resource_saver.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "editor_node.h" #include "editor_scale.h" @@ -69,27 +69,27 @@ void EditorAudioBus::_notification(int p_what) { case NOTIFICATION_READY: { for (int i = 0; i < CHANNELS_MAX; i++) { - channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons")); - channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons")); - channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons")); - channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons")); + channel[i].vu_l->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons")); + channel[i].vu_l->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons")); + channel[i].vu_r->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons")); + channel[i].vu_r->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons")); channel[i].prev_active = true; } - disabled_vu = get_icon("BusVuFrozen", "EditorIcons"); + disabled_vu = get_theme_icon("BusVuFrozen", "EditorIcons"); Color solo_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.89, 0.22) : Color(1.0, 0.92, 0.44); Color mute_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.16, 0.16) : Color(1.0, 0.44, 0.44); Color bypass_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(0.13, 0.8, 1.0) : Color(0.44, 0.87, 1.0); - solo->set_icon(get_icon("AudioBusSolo", "EditorIcons")); - solo->add_color_override("icon_color_pressed", solo_color); - mute->set_icon(get_icon("AudioBusMute", "EditorIcons")); - mute->add_color_override("icon_color_pressed", mute_color); - bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons")); - bypass->add_color_override("icon_color_pressed", bypass_color); + solo->set_icon(get_theme_icon("AudioBusSolo", "EditorIcons")); + solo->add_theme_color_override("icon_color_pressed", solo_color); + mute->set_icon(get_theme_icon("AudioBusMute", "EditorIcons")); + mute->add_theme_color_override("icon_color_pressed", mute_color); + bypass->set_icon(get_theme_icon("AudioBusBypass", "EditorIcons")); + bypass->add_theme_color_override("icon_color_pressed", bypass_color); - bus_options->set_icon(get_icon("GuiTabMenu", "EditorIcons")); + bus_options->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); update_bus(); set_process(true); @@ -97,15 +97,15 @@ void EditorAudioBus::_notification(int p_what) { case NOTIFICATION_DRAW: { if (is_master) { - draw_style_box(get_stylebox("disabled", "Button"), Rect2(Vector2(), get_size())); + draw_style_box(get_theme_stylebox("disabled", "Button"), Rect2(Vector2(), get_size())); } else if (has_focus()) { - draw_style_box(get_stylebox("focus", "Button"), Rect2(Vector2(), get_size())); + draw_style_box(get_theme_stylebox("focus", "Button"), Rect2(Vector2(), get_size())); } else { - draw_style_box(get_stylebox("panel", "TabContainer"), Rect2(Vector2(), get_size())); + draw_style_box(get_theme_stylebox("panel", "TabContainer"), Rect2(Vector2(), get_size())); } if (get_index() != 0 && hovering_drop) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); accent.a *= 0.7; draw_rect(Rect2(Point2(), get_size()), accent, false); } @@ -168,20 +168,20 @@ void EditorAudioBus::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < CHANNELS_MAX; i++) { - channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons")); - channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons")); - channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons")); - channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons")); + channel[i].vu_l->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons")); + channel[i].vu_l->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons")); + channel[i].vu_r->set_under_texture(get_theme_icon("BusVuEmpty", "EditorIcons")); + channel[i].vu_r->set_progress_texture(get_theme_icon("BusVuFull", "EditorIcons")); channel[i].prev_active = true; } - disabled_vu = get_icon("BusVuFrozen", "EditorIcons"); + disabled_vu = get_theme_icon("BusVuFrozen", "EditorIcons"); - solo->set_icon(get_icon("AudioBusSolo", "EditorIcons")); - mute->set_icon(get_icon("AudioBusMute", "EditorIcons")); - bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons")); + solo->set_icon(get_theme_icon("AudioBusSolo", "EditorIcons")); + mute->set_icon(get_theme_icon("AudioBusMute", "EditorIcons")); + bypass->set_icon(get_theme_icon("AudioBusBypass", "EditorIcons")); - bus_options->set_icon(get_icon("GuiTabMenu", "EditorIcons")); + bus_options->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); } break; case NOTIFICATION_MOUSE_EXIT: case NOTIFICATION_DRAG_END: { @@ -325,7 +325,7 @@ void EditorAudioBus::_volume_changed(float p_normalized) { const float p_db = this->_normalized_volume_to_scaled_db(p_normalized); - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) { // Snap the value when holding Ctrl for easier editing. // To do so, it needs to be converted back to normalized volume (as the slider uses that unit). slider->set_value(_scaled_db_to_normalized_volume(Math::round(p_db))); @@ -386,7 +386,7 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) { void EditorAudioBus::_show_value(float slider_value) { float db; - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) { // Display the correct (snapped) value when holding Ctrl db = Math::round(_normalized_volume_to_scaled_db(slider_value)); } else { @@ -586,7 +586,7 @@ Variant EditorAudioBus::get_drag_data(const Point2 &p_point) { Panel *p = memnew(Panel); c->add_child(p); p->set_modulate(Color(1, 1, 1, 0.7)); - p->add_style_override("panel", get_stylebox("focus", "Button")); + p->add_theme_style_override("panel", get_theme_stylebox("focus", "Button")); p->set_size(get_size()); p->set_position(-p_point); set_drag_preview(c); @@ -819,10 +819,10 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { Ref<StyleBoxEmpty> sbempty = memnew(StyleBoxEmpty); for (int i = 0; i < hbc->get_child_count(); i++) { Control *child = Object::cast_to<Control>(hbc->get_child(i)); - child->add_style_override("normal", sbempty); - child->add_style_override("hover", sbempty); - child->add_style_override("focus", sbempty); - child->add_style_override("pressed", sbempty); + child->add_theme_style_override("normal", sbempty); + child->add_theme_style_override("hover", sbempty); + child->add_theme_style_override("focus", sbempty); + child->add_theme_style_override("pressed", sbempty); } HSeparator *separator = memnew(HSeparator); @@ -854,7 +854,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { audio_value_preview_box->set_as_toplevel(true); Ref<StyleBoxFlat> panel_style = memnew(StyleBoxFlat); panel_style->set_bg_color(Color(0.0f, 0.0f, 0.0f, 0.8f)); - audio_value_preview_box->add_style_override("panel", panel_style); + audio_value_preview_box->add_theme_style_override("panel", panel_style); audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS); audio_value_preview_box->hide(); @@ -953,10 +953,10 @@ void EditorAudioBusDrop::_notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { - draw_style_box(get_stylebox("normal", "Button"), Rect2(Vector2(), get_size())); + draw_style_box(get_theme_stylebox("normal", "Button"), Rect2(Vector2(), get_size())); if (hovering_drop) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); accent.a *= 0.7; draw_rect(Rect2(Point2(), get_size()), accent, false); } @@ -1035,7 +1035,7 @@ void EditorAudioBuses::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - bus_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + bus_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); } break; case NOTIFICATION_READY: { @@ -1204,7 +1204,7 @@ void EditorAudioBuses::_select_layout() { void EditorAudioBuses::_save_as_layout() { - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_title(TTR("Save Audio Bus Layout As...")); file_dialog->set_current_path(edited_path); file_dialog->popup_centered_ratio(); @@ -1213,7 +1213,7 @@ void EditorAudioBuses::_save_as_layout() { void EditorAudioBuses::_new_layout() { - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_title(TTR("Location for New Layout...")); file_dialog->set_current_path(edited_path); file_dialog->popup_centered_ratio(); @@ -1222,7 +1222,7 @@ void EditorAudioBuses::_new_layout() { void EditorAudioBuses::_load_layout() { - file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file_dialog->set_title(TTR("Open Audio Bus Layout")); file_dialog->set_current_path(edited_path); file_dialog->popup_centered_ratio(); @@ -1249,7 +1249,7 @@ void EditorAudioBuses::_load_default_layout() { void EditorAudioBuses::_file_dialog_callback(const String &p_string) { - if (file_dialog->get_mode() == EditorFileDialog::MODE_OPEN_FILE) { + if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_OPEN_FILE) { Ref<AudioBusLayout> state = ResourceLoader::load(p_string, "", true); if (state.is_null()) { EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout.")); @@ -1263,7 +1263,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) { EditorNode::get_singleton()->get_undo_redo()->clear_history(); call_deferred("_select_layout"); - } else if (file_dialog->get_mode() == EditorFileDialog::MODE_SAVE_FILE) { + } else if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { if (new_layout) { Ref<AudioBusLayout> empty_state; @@ -1423,7 +1423,7 @@ void EditorAudioMeterNotches::add_notch(float p_normalized_offset, float p_db_va Size2 EditorAudioMeterNotches::get_minimum_size() const { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); float font_height = font->get_height(); float width = 0; @@ -1460,7 +1460,7 @@ void EditorAudioMeterNotches::_notification(int p_what) { void EditorAudioMeterNotches::_draw_audio_notches() { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); float font_height = font->get_height(); for (int i = 0; i < notches.size(); i++) { diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 83a1e2fca2..a6a383ba58 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -35,7 +35,7 @@ #include "editor_node.h" #include "editor_scale.h" #include "project_settings_editor.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" #define PREVIEW_LIST_MAX_SIZE 10 @@ -452,10 +452,10 @@ void EditorAutoloadSettings::update_autoload() { item->set_editable(2, true); item->set_text(2, TTR("Enable")); item->set_checked(2, info.is_singleton); - item->add_button(3, get_icon("Load", "EditorIcons"), BUTTON_OPEN); - item->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP); - item->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN); - item->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_DELETE); + item->add_button(3, get_theme_icon("Load", "EditorIcons"), BUTTON_OPEN); + item->add_button(3, get_theme_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP); + item->add_button(3, get_theme_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN); + item->add_button(3, get_theme_icon("Remove", "EditorIcons"), BUTTON_DELETE); item->set_selectable(3, false); } @@ -825,7 +825,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() { autoload_add_path = memnew(EditorLineEditFileChooser); autoload_add_path->set_h_size_flags(SIZE_EXPAND_FILL); - autoload_add_path->get_file_dialog()->set_mode(EditorFileDialog::MODE_OPEN_FILE); + autoload_add_path->get_file_dialog()->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); autoload_add_path->get_file_dialog()->connect("file_selected", callable_mp(this, &EditorAutoloadSettings::_autoload_file_callback)); autoload_add_path->get_line_edit()->connect("text_changed", callable_mp(this, &EditorAutoloadSettings::_autoload_path_text_changed)); diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp index 20fe349ef6..cb87656382 100644 --- a/editor/editor_dir_dialog.cpp +++ b/editor/editor_dir_dialog.cpp @@ -35,6 +35,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_settings.h" #include "editor_scale.h" +#include "servers/display_server.h" void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p_dir, const String &p_select_path) { @@ -43,7 +44,7 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p String path = p_dir->get_path(); p_item->set_metadata(0, p_dir->get_path()); - p_item->set_icon(0, get_icon("Folder", "EditorIcons")); + p_item->set_icon(0, tree->get_theme_icon("Folder", "EditorIcons")); if (!p_item->get_parent()) { p_item->set_text(0, "res://"); @@ -68,7 +69,7 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p void EditorDirDialog::reload(const String &p_path) { - if (!is_visible_in_tree()) { + if (!is_visible()) { must_reload = true; return; } @@ -102,7 +103,7 @@ void EditorDirDialog::_notification(int p_what) { } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (must_reload && is_visible_in_tree()) { + if (must_reload && is_visible()) { reload(); } } @@ -141,11 +142,11 @@ void EditorDirDialog::_make_dir() { TreeItem *ti = tree->get_selected(); if (!ti) { mkdirerr->set_text(TTR("Please select a base directory first.")); - mkdirerr->popup_centered_minsize(); + mkdirerr->popup_centered(); return; } - makedialog->popup_centered_minsize(Size2(250, 80)); + makedialog->popup_centered(Size2(250, 80)); makedirname->grab_focus(); } @@ -162,7 +163,7 @@ void EditorDirDialog::_make_dir_confirm() { Error err = d->make_dir(makedirname->get_text()); if (err != OK) { - mkdirerr->popup_centered_minsize(Size2(250, 80) * EDSCALE); + mkdirerr->popup_centered(Size2(250, 80) * EDSCALE); } else { opened_paths.insert(dir); //reload(dir.plus_file(makedirname->get_text())); @@ -188,7 +189,7 @@ EditorDirDialog::EditorDirDialog() { tree->connect("item_activated", callable_mp(this, &EditorDirDialog::_item_activated)); - makedir = add_button(TTR("Create Folder"), OS::get_singleton()->get_swap_ok_cancel(), "makedir"); + makedir = add_button(TTR("Create Folder"), DisplayServer::get_singleton()->get_swap_ok_cancel(), "makedir"); makedir->connect("pressed", callable_mp(this, &EditorDirDialog::_make_dir)); makedialog = memnew(ConfirmationDialog); diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 4b0bbdcec2..6e13ec7967 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -420,7 +420,7 @@ void EditorFeatureProfileManager::_profile_action(int p_action) { } break; case PROFILE_NEW: { - new_profile_dialog->popup_centered_minsize(); + new_profile_dialog->popup_centered(); new_profile_name->clear(); new_profile_name->grab_focus(); } break; @@ -430,7 +430,7 @@ void EditorFeatureProfileManager::_profile_action(int p_action) { ERR_FAIL_COND(selected == String()); erase_profile_dialog->set_text(vformat(TTR("Erase profile '%s'? (no undo)"), selected)); - erase_profile_dialog->popup_centered_minsize(); + erase_profile_dialog->popup_centered(); } break; } } @@ -485,7 +485,7 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S bool disabled_editor = edited->is_class_editor_disabled(p_class); bool disabled_properties = edited->has_class_properties_disabled(p_class); if (disabled) { - class_item->set_custom_color(0, get_color("disabled_font_color", "Editor")); + class_item->set_custom_color(0, class_list->get_theme_color("disabled_font_color", "Editor")); } else if (disabled_editor && disabled_properties) { text += " " + TTR("(Editor Disabled, Properties Disabled)"); } else if (disabled_properties) { @@ -805,7 +805,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { current_profile_name = memnew(LineEdit); name_hbc->add_child(current_profile_name); current_profile_name->set_editable(false); - current_profile_name->set_h_size_flags(SIZE_EXPAND_FILL); + current_profile_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); profile_actions[PROFILE_CLEAR] = memnew(Button(TTR("Unset"))); name_hbc->add_child(profile_actions[PROFILE_CLEAR]); profile_actions[PROFILE_CLEAR]->set_disabled(true); @@ -815,7 +815,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { HBoxContainer *profiles_hbc = memnew(HBoxContainer); profile_list = memnew(OptionButton); - profile_list->set_h_size_flags(SIZE_EXPAND_FILL); + profile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); profiles_hbc->add_child(profile_list); profile_list->connect("item_selected", callable_mp(this, &EditorFeatureProfileManager::_profile_selected)); @@ -849,12 +849,12 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { main_vbc->add_margin_child(TTR("Available Profiles:"), profiles_hbc); h_split = memnew(HSplitContainer); - h_split->set_v_size_flags(SIZE_EXPAND_FILL); + h_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); main_vbc->add_child(h_split); VBoxContainer *class_list_vbc = memnew(VBoxContainer); h_split->add_child(class_list_vbc); - class_list_vbc->set_h_size_flags(SIZE_EXPAND_FILL); + class_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); class_list = memnew(Tree); class_list_vbc->add_margin_child(TTR("Enabled Classes:"), class_list, true); @@ -865,7 +865,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { VBoxContainer *property_list_vbc = memnew(VBoxContainer); h_split->add_child(property_list_vbc); - property_list_vbc->set_h_size_flags(SIZE_EXPAND_FILL); + property_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); property_list = memnew(Tree); property_list_vbc->add_margin_child(TTR("Class Options"), property_list, true); @@ -891,7 +891,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { import_profiles = memnew(EditorFileDialog); add_child(import_profiles); - import_profiles->set_mode(EditorFileDialog::MODE_OPEN_FILES); + import_profiles->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); import_profiles->add_filter("*.profile; " + TTR("Godot Feature Profile")); import_profiles->connect("files_selected", callable_mp(this, &EditorFeatureProfileManager::_import_profiles)); import_profiles->set_title(TTR("Import Profile(s)")); @@ -899,7 +899,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { export_profile = memnew(EditorFileDialog); add_child(export_profile); - export_profile->set_mode(EditorFileDialog::MODE_SAVE_FILE); + export_profile->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); export_profile->add_filter("*.profile; " + TTR("Godot Feature Profile")); export_profile->connect("file_selected", callable_mp(this, &EditorFeatureProfileManager::_export_profile)); export_profile->set_title(TTR("Export Profile")); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 250fa6b3e0..fca59946ae 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -42,6 +42,7 @@ #include "scene/gui/center_container.h" #include "scene/gui/label.h" #include "scene/gui/margin_container.h" +#include "servers/display_server.h" EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func = NULL; EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func = NULL; @@ -58,17 +59,17 @@ void EditorFileDialog::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { // update icons - mode_thumbnails->set_icon(get_icon("FileThumbnail", "EditorIcons")); - mode_list->set_icon(get_icon("FileList", "EditorIcons")); - dir_prev->set_icon(get_icon("Back", "EditorIcons")); - dir_next->set_icon(get_icon("Forward", "EditorIcons")); - dir_up->set_icon(get_icon("ArrowUp", "EditorIcons")); - refresh->set_icon(get_icon("Reload", "EditorIcons")); - favorite->set_icon(get_icon("Favorites", "EditorIcons")); - show_hidden->set_icon(get_icon("GuiVisibilityVisible", "EditorIcons")); - - fav_up->set_icon(get_icon("MoveUp", "EditorIcons")); - fav_down->set_icon(get_icon("MoveDown", "EditorIcons")); + mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons")); + mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons")); + dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons")); + dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons")); + dir_up->set_icon(item_list->get_theme_icon("ArrowUp", "EditorIcons")); + refresh->set_icon(item_list->get_theme_icon("Reload", "EditorIcons")); + favorite->set_icon(item_list->get_theme_icon("Favorites", "EditorIcons")); + show_hidden->set_icon(item_list->get_theme_icon("GuiVisibilityVisible", "EditorIcons")); + + fav_up->set_icon(item_list->get_theme_icon("MoveUp", "EditorIcons")); + fav_down->set_icon(item_list->get_theme_icon("MoveDown", "EditorIcons")); } else if (p_what == NOTIFICATION_PROCESS) { @@ -78,14 +79,11 @@ void EditorFileDialog::_notification(int p_what) { preview_wheel_index++; if (preview_wheel_index >= 8) preview_wheel_index = 0; - Ref<Texture2D> frame = get_icon("Progress" + itos(preview_wheel_index + 1), "EditorIcons"); + Ref<Texture2D> frame = item_list->get_theme_icon("Progress" + itos(preview_wheel_index + 1), "EditorIcons"); preview->set_texture(frame); preview_wheel_timeout = 0.1; } } - } else if (p_what == NOTIFICATION_POPUP_HIDE) { - - set_process_unhandled_input(false); } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { @@ -95,18 +93,23 @@ void EditorFileDialog::_notification(int p_what) { set_display_mode((DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int()); // update icons - mode_thumbnails->set_icon(get_icon("FileThumbnail", "EditorIcons")); - mode_list->set_icon(get_icon("FileList", "EditorIcons")); - dir_prev->set_icon(get_icon("Back", "EditorIcons")); - dir_next->set_icon(get_icon("Forward", "EditorIcons")); - dir_up->set_icon(get_icon("ArrowUp", "EditorIcons")); - refresh->set_icon(get_icon("Reload", "EditorIcons")); - favorite->set_icon(get_icon("Favorites", "EditorIcons")); - - fav_up->set_icon(get_icon("MoveUp", "EditorIcons")); - fav_down->set_icon(get_icon("MoveDown", "EditorIcons")); + mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons")); + mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons")); + dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons")); + dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons")); + dir_up->set_icon(item_list->get_theme_icon("ArrowUp", "EditorIcons")); + refresh->set_icon(item_list->get_theme_icon("Reload", "EditorIcons")); + favorite->set_icon(item_list->get_theme_icon("Favorites", "EditorIcons")); + + fav_up->set_icon(item_list->get_theme_icon("MoveUp", "EditorIcons")); + fav_down->set_icon(item_list->get_theme_icon("MoveDown", "EditorIcons")); // DO NOT CALL UPDATE FILE LIST HERE, ALL HUNDREDS OF HIDDEN DIALOGS WILL RESPOND, CALL INVALIDATE INSTEAD invalidate(); + } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + + if (!is_visible()) { + set_process_unhandled_input(false); + } } } @@ -114,7 +117,7 @@ void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid() && is_window_modal_on_top()) { + if (k.is_valid()) { if (k->is_pressed()) { @@ -176,7 +179,7 @@ void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { } if (handled) { - accept_event(); + set_input_as_handled(); } } } @@ -208,15 +211,15 @@ void EditorFileDialog::update_dir() { get_ok()->set_disabled(_is_open_should_be_disabled()); switch (mode) { - case MODE_OPEN_FILE: - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(TTR("Open")); break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_text(TTR("Select Current Folder")); break; - case MODE_OPEN_ANY: - case MODE_SAVE_FILE: + case FILE_MODE_OPEN_ANY: + case FILE_MODE_SAVE_FILE: // FIXME: Implement, or refactor to avoid duplication with set_mode break; } @@ -251,23 +254,23 @@ void EditorFileDialog::_post_popup() { update_file_list(); invalidated = false; } - if (mode == MODE_SAVE_FILE) + if (mode == FILE_MODE_SAVE_FILE) file->grab_focus(); else item_list->grab_focus(); - if (mode == MODE_OPEN_DIR) { + if (mode == FILE_MODE_OPEN_DIR) { file_box->set_visible(false); } else { file_box->set_visible(true); } - if (is_visible_in_tree() && get_current_file() != "") + if (is_visible() && get_current_file() != "") _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); - if (is_visible_in_tree()) { - Ref<Texture2D> folder = get_icon("folder", "FileDialog"); - const Color folder_color = get_color("folder_icon_modulate", "FileDialog"); + if (is_visible()) { + Ref<Texture2D> folder = item_list->get_theme_icon("folder", "FileDialog"); + const Color folder_color = item_list->get_theme_color("folder_icon_modulate", "FileDialog"); recent->clear(); bool res = access == ACCESS_RESOURCES; @@ -346,7 +349,7 @@ void EditorFileDialog::_request_single_thumbnail(const String &p_path) { void EditorFileDialog::_action_pressed() { - if (mode == MODE_OPEN_FILES) { + if (mode == FILE_MODE_OPEN_FILES) { String fbase = dir_access->get_current_dir(); @@ -367,11 +370,11 @@ void EditorFileDialog::_action_pressed() { String f = dir_access->get_current_dir().plus_file(file->get_text()); - if ((mode == MODE_OPEN_ANY || mode == MODE_OPEN_FILE) && dir_access->file_exists(f)) { + if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) { _save_to_recent(); hide(); emit_signal("file_selected", f); - } else if (mode == MODE_OPEN_ANY || mode == MODE_OPEN_DIR) { + } else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) { String path = dir_access->get_current_dir(); @@ -393,7 +396,7 @@ void EditorFileDialog::_action_pressed() { emit_signal("dir_selected", path); } - if (mode == MODE_SAVE_FILE) { + if (mode == FILE_MODE_SAVE_FILE) { bool valid = false; @@ -446,7 +449,7 @@ void EditorFileDialog::_action_pressed() { if (!valid) { - exterr->popup_centered_minsize(Size2(250, 80) * EDSCALE); + exterr->popup_centered(Size2(250, 80) * EDSCALE); return; } @@ -481,7 +484,7 @@ void EditorFileDialog::_item_selected(int p_item) { file->set_text(d["name"]); _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); - } else if (mode == MODE_OPEN_DIR) { + } else if (mode == FILE_MODE_OPEN_DIR) { get_ok()->set_text(TTR("Select This Folder")); } @@ -512,19 +515,19 @@ void EditorFileDialog::_items_clear_selection() { // If nothing is selected, then block Open button. switch (mode) { - case MODE_OPEN_FILE: - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(TTR("Open")); get_ok()->set_disabled(!item_list->is_anything_selected()); break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_disabled(false); get_ok()->set_text(TTR("Select Current Folder")); break; - case MODE_OPEN_ANY: - case MODE_SAVE_FILE: + case FILE_MODE_OPEN_ANY: + case FILE_MODE_SAVE_FILE: // FIXME: Implement, or refactor to avoid duplication with set_mode break; } @@ -586,16 +589,16 @@ void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p } if (single_item_selected) { - item_menu->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), ITEM_MENU_COPY_PATH); + item_menu->add_icon_item(item_list->get_theme_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), ITEM_MENU_COPY_PATH); } if (allow_delete) { - item_menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE); + item_menu->add_icon_item(item_list->get_theme_icon("Remove", "EditorIcons"), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE); } if (single_item_selected) { item_menu->add_separator(); Dictionary item_meta = item_list->get_item_metadata(p_item); String item_text = item_meta["dir"] ? TTR("Open in File Manager") : TTR("Show in File Manager"); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), item_text, ITEM_MENU_SHOW_IN_EXPLORER); + item_menu->add_icon_item(item_list->get_theme_icon("Filesystem", "EditorIcons"), item_text, ITEM_MENU_SHOW_IN_EXPLORER); } if (item_menu->get_item_count() > 0) { @@ -615,11 +618,11 @@ void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) { item_menu->set_size(Size2(1, 1)); if (can_create_dir) { - item_menu->add_icon_item(get_icon("folder", "FileDialog"), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KEY_MASK_CMD | KEY_N); + item_menu->add_icon_item(item_list->get_theme_icon("folder", "FileDialog"), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KEY_MASK_CMD | KEY_N); } - item_menu->add_icon_item(get_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5); + item_menu->add_icon_item(item_list->get_theme_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5); item_menu->add_separator(); - item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); + item_menu->add_icon_item(item_list->get_theme_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); item_menu->set_position(item_list->get_global_position() + p_pos); item_menu->popup(); @@ -631,7 +634,7 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) { case ITEM_MENU_COPY_PATH: { Dictionary item_meta = item_list->get_item_metadata(item_list->get_current()); - OS::get_singleton()->set_clipboard(item_meta["path"]); + DisplayServer::get_singleton()->clipboard_set(item_meta["path"]); } break; case ITEM_MENU_DELETE: { @@ -667,18 +670,18 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) { bool EditorFileDialog::_is_open_should_be_disabled() { - if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE) + if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_SAVE_FILE) return false; Vector<int> items = item_list->get_selected_items(); if (items.size() == 0) - return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. + return mode != FILE_MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. for (int i = 0; i < items.size(); i++) { Dictionary d = item_list->get_item_metadata(items.get(i)); - if (((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || (mode == MODE_OPEN_DIR && !d["dir"])) + if (((mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES) && d["dir"]) || (mode == FILE_MODE_OPEN_DIR && !d["dir"])) return true; } @@ -724,11 +727,11 @@ void EditorFileDialog::update_file_list() { item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size)); if (thumbnail_size < 64) { - folder_thumbnail = get_icon("FolderMediumThumb", "EditorIcons"); - file_thumbnail = get_icon("FileMediumThumb", "EditorIcons"); + folder_thumbnail = item_list->get_theme_icon("FolderMediumThumb", "EditorIcons"); + file_thumbnail = item_list->get_theme_icon("FileMediumThumb", "EditorIcons"); } else { - folder_thumbnail = get_icon("FolderBigThumb", "EditorIcons"); - file_thumbnail = get_icon("FileBigThumb", "EditorIcons"); + folder_thumbnail = item_list->get_theme_icon("FolderBigThumb", "EditorIcons"); + file_thumbnail = item_list->get_theme_icon("FileBigThumb", "EditorIcons"); } preview_vb->hide(); @@ -748,8 +751,8 @@ void EditorFileDialog::update_file_list() { dir_access->list_dir_begin(); - Ref<Texture2D> folder = get_icon("folder", "FileDialog"); - const Color folder_color = get_color("folder_icon_modulate", "FileDialog"); + Ref<Texture2D> folder = item_list->get_theme_icon("folder", "FileDialog"); + const Color folder_color = item_list->get_theme_color("folder_icon_modulate", "FileDialog"); List<String> files; List<String> dirs; @@ -978,7 +981,7 @@ void EditorFileDialog::set_current_file(const String &p_file) { file->grab_focus(); } - if (is_visible_in_tree()) + if (is_visible()) _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); } void EditorFileDialog::set_current_path(const String &p_path) { @@ -998,39 +1001,39 @@ void EditorFileDialog::set_current_path(const String &p_path) { } } -void EditorFileDialog::set_mode(Mode p_mode) { +void EditorFileDialog::set_file_mode(FileMode p_mode) { mode = p_mode; switch (mode) { - case MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILE: get_ok()->set_text(TTR("Open")); set_title(TTR("Open a File")); can_create_dir = false; break; - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(TTR("Open")); set_title(TTR("Open File(s)")); can_create_dir = false; break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_text(TTR("Open")); set_title(TTR("Open a Directory")); can_create_dir = true; break; - case MODE_OPEN_ANY: + case FILE_MODE_OPEN_ANY: get_ok()->set_text(TTR("Open")); set_title(TTR("Open a File or Directory")); can_create_dir = true; break; - case MODE_SAVE_FILE: + case FILE_MODE_SAVE_FILE: get_ok()->set_text(TTR("Save")); set_title(TTR("Save a File")); can_create_dir = true; break; } - if (mode == MODE_OPEN_FILES) { + if (mode == FILE_MODE_OPEN_FILES) { item_list->set_select_mode(ItemList::SELECT_MULTI); } else { item_list->set_select_mode(ItemList::SELECT_SINGLE); @@ -1043,7 +1046,7 @@ void EditorFileDialog::set_mode(Mode p_mode) { } } -EditorFileDialog::Mode EditorFileDialog::get_mode() const { +EditorFileDialog::FileMode EditorFileDialog::get_file_mode() const { return mode; } @@ -1077,7 +1080,7 @@ void EditorFileDialog::set_access(Access p_access) { void EditorFileDialog::invalidate() { - if (is_visible_in_tree()) { + if (is_visible()) { update_file_list(); _update_favorites(); invalidated = false; @@ -1102,14 +1105,14 @@ void EditorFileDialog::_make_dir_confirm() { _push_history(); EditorFileSystem::get_singleton()->scan_changes(); //we created a dir, so rescan changes } else { - mkdirerr->popup_centered_minsize(Size2(250, 50) * EDSCALE); + mkdirerr->popup_centered(Size2(250, 50) * EDSCALE); } makedirname->set_text(""); // reset label } void EditorFileDialog::_make_dir() { - makedialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + makedialog->popup_centered(Size2(250, 80) * EDSCALE); makedirname->grab_focus(); } @@ -1224,8 +1227,8 @@ void EditorFileDialog::_update_favorites() { bool res = access == ACCESS_RESOURCES; String current = get_current_dir(); - Ref<Texture2D> folder_icon = get_icon("Folder", "EditorIcons"); - const Color folder_color = get_color("folder_icon_modulate", "FileDialog"); + Ref<Texture2D> folder_icon = item_list->get_theme_icon("Folder", "EditorIcons"); + const Color folder_color = item_list->get_theme_color("folder_icon_modulate", "FileDialog"); favorites->clear(); favorite->set_pressed(false); @@ -1383,8 +1386,8 @@ void EditorFileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_dir", "dir"), &EditorFileDialog::set_current_dir); ClassDB::bind_method(D_METHOD("set_current_file", "file"), &EditorFileDialog::set_current_file); ClassDB::bind_method(D_METHOD("set_current_path", "path"), &EditorFileDialog::set_current_path); - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &EditorFileDialog::set_mode); - ClassDB::bind_method(D_METHOD("get_mode"), &EditorFileDialog::get_mode); + ClassDB::bind_method(D_METHOD("set_file_mode", "mode"), &EditorFileDialog::set_file_mode); + ClassDB::bind_method(D_METHOD("get_file_mode"), &EditorFileDialog::get_file_mode); ClassDB::bind_method(D_METHOD("get_vbox"), &EditorFileDialog::get_vbox); ClassDB::bind_method(D_METHOD("set_access", "access"), &EditorFileDialog::set_access); ClassDB::bind_method(D_METHOD("get_access"), &EditorFileDialog::get_access); @@ -1408,18 +1411,18 @@ void EditorFileDialog::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"), "set_display_mode", "get_display_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_mode", "get_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_file_mode", "get_file_mode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR), "set_current_dir", "get_current_dir"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*"), "set_current_file", "get_current_file"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path"), "set_current_path", "get_current_path"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_overwrite_warning"), "set_disable_overwrite_warning", "is_overwrite_warning_disabled"); - BIND_ENUM_CONSTANT(MODE_OPEN_FILE); - BIND_ENUM_CONSTANT(MODE_OPEN_FILES); - BIND_ENUM_CONSTANT(MODE_OPEN_DIR); - BIND_ENUM_CONSTANT(MODE_OPEN_ANY); - BIND_ENUM_CONSTANT(MODE_SAVE_FILE); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILE); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILES); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_DIR); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_ANY); + BIND_ENUM_CONSTANT(FILE_MODE_SAVE_FILE); BIND_ENUM_CONSTANT(ACCESS_RESOURCES); BIND_ENUM_CONSTANT(ACCESS_USERDATA); @@ -1483,8 +1486,6 @@ bool EditorFileDialog::is_overwrite_warning_disabled() const { EditorFileDialog::EditorFileDialog() { - set_resizable(true); - show_hidden_files = default_show_hidden_files; display_mode = default_display_mode; local_history_pos = 0; @@ -1492,7 +1493,7 @@ EditorFileDialog::EditorFileDialog() { VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); - mode = MODE_SAVE_FILE; + mode = FILE_MODE_SAVE_FILE; set_title(TTR("Save a File")); ED_SHORTCUT("file_dialog/go_back", TTR("Go Back"), KEY_MASK_ALT | KEY_LEFT); @@ -1532,7 +1533,7 @@ EditorFileDialog::EditorFileDialog() { dir = memnew(LineEdit); pathhb->add_child(dir); - dir->set_h_size_flags(SIZE_EXPAND_FILL); + dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); refresh = memnew(ToolButton); refresh->set_tooltip(TTR("Refresh files.")); @@ -1588,7 +1589,7 @@ EditorFileDialog::EditorFileDialog() { vbc->add_child(pathhb); vbc->add_child(list_hb); - list_hb->set_v_size_flags(SIZE_EXPAND_FILL); + list_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL); VSplitContainer *vsc = memnew(VSplitContainer); list_hb->add_child(vsc); @@ -1596,7 +1597,7 @@ EditorFileDialog::EditorFileDialog() { VBoxContainer *fav_vb = memnew(VBoxContainer); vsc->add_child(fav_vb); fav_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); - fav_vb->set_v_size_flags(SIZE_EXPAND_FILL); + fav_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); HBoxContainer *fav_hb = memnew(HBoxContainer); fav_vb->add_child(fav_hb); fav_hb->add_child(memnew(Label(TTR("Favorites:")))); @@ -1610,13 +1611,13 @@ EditorFileDialog::EditorFileDialog() { favorites = memnew(ItemList); fav_vb->add_child(favorites); - favorites->set_v_size_flags(SIZE_EXPAND_FILL); + favorites->set_v_size_flags(Control::SIZE_EXPAND_FILL); favorites->connect("item_selected", callable_mp(this, &EditorFileDialog::_favorite_selected)); VBoxContainer *rec_vb = memnew(VBoxContainer); vsc->add_child(rec_vb); rec_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE); - rec_vb->set_v_size_flags(SIZE_EXPAND_FILL); + rec_vb->set_v_size_flags(Control::SIZE_EXPAND_FILL); recent = memnew(ItemList); recent->set_allow_reselect(true); rec_vb->add_margin_child(TTR("Recent:"), recent, true); @@ -1627,18 +1628,18 @@ EditorFileDialog::EditorFileDialog() { item_vb->set_custom_minimum_size(Size2(320, 0) * EDSCALE); HBoxContainer *preview_hb = memnew(HBoxContainer); - preview_hb->set_v_size_flags(SIZE_EXPAND_FILL); + preview_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL); item_vb->add_child(preview_hb); VBoxContainer *list_vb = memnew(VBoxContainer); - list_vb->set_h_size_flags(SIZE_EXPAND_FILL); + list_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); list_vb->add_child(memnew(Label(TTR("Directories & Files:")))); preview_hb->add_child(list_vb); // Item (files and folders) list with context menu. item_list = memnew(ItemList); - item_list->set_v_size_flags(SIZE_EXPAND_FILL); + item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); item_list->connect("item_rmb_selected", callable_mp(this, &EditorFileDialog::_item_list_item_rmb_selected)); item_list->connect("rmb_clicked", callable_mp(this, &EditorFileDialog::_item_list_rmb_clicked)); item_list->set_allow_rmb_select(true); @@ -1662,14 +1663,14 @@ EditorFileDialog::EditorFileDialog() { file_box->add_child(memnew(Label(TTR("File:")))); file = memnew(LineEdit); file->set_stretch_ratio(4); - file->set_h_size_flags(SIZE_EXPAND_FILL); + file->set_h_size_flags(Control::SIZE_EXPAND_FILL); file_box->add_child(file); filter = memnew(OptionButton); filter->set_stretch_ratio(3); - filter->set_h_size_flags(SIZE_EXPAND_FILL); + filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); filter->set_clip_text(true); // Too many extensions overflow it. file_box->add_child(filter); - file_box->set_h_size_flags(SIZE_EXPAND_FILL); + file_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); item_vb->add_child(file_box); dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); @@ -1686,7 +1687,7 @@ EditorFileDialog::EditorFileDialog() { filter->connect("item_selected", callable_mp(this, &EditorFileDialog::_filter_selected)); confirm_save = memnew(ConfirmationDialog); - confirm_save->set_as_toplevel(true); + //confirm_save->set_as_toplevel(true); add_child(confirm_save); confirm_save->connect("confirmed", callable_mp(this, &EditorFileDialog::_save_confirm_pressed)); @@ -1736,7 +1737,7 @@ EditorFileDialog::~EditorFileDialog() { void EditorLineEditFileChooser::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) - button->set_icon(get_icon("Folder", "EditorIcons")); + button->set_icon(get_theme_icon("Folder", "EditorIcons")); } void EditorLineEditFileChooser::_bind_methods() { @@ -1761,7 +1762,7 @@ EditorLineEditFileChooser::EditorLineEditFileChooser() { line_edit = memnew(LineEdit); add_child(line_edit); - line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); button = memnew(Button); add_child(button); button->connect("pressed", callable_mp(this, &EditorLineEditFileChooser::_browse)); diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index 998ac33761..ed23f14ebe 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -60,12 +60,12 @@ public: ACCESS_FILESYSTEM }; - enum Mode { - MODE_OPEN_FILE, - MODE_OPEN_FILES, - MODE_OPEN_DIR, - MODE_OPEN_ANY, - MODE_SAVE_FILE + enum FileMode { + FILE_MODE_OPEN_FILE, + FILE_MODE_OPEN_FILES, + FILE_MODE_OPEN_DIR, + FILE_MODE_OPEN_ANY, + FILE_MODE_SAVE_FILE }; typedef Ref<Texture2D> (*GetIconFunc)(const String &); @@ -92,7 +92,7 @@ private: Access access; //Button *action; VBoxContainer *vbox; - Mode mode; + FileMode mode; bool can_create_dir; LineEdit *dir; @@ -221,8 +221,8 @@ public: void set_display_mode(DisplayMode p_mode); DisplayMode get_display_mode() const; - void set_mode(Mode p_mode); - Mode get_mode() const; + void set_file_mode(FileMode p_mode); + FileMode get_file_mode() const; VBoxContainer *get_vbox(); LineEdit *get_line_edit() { return file; } @@ -267,7 +267,7 @@ public: EditorLineEditFileChooser(); }; -VARIANT_ENUM_CAST(EditorFileDialog::Mode); +VARIANT_ENUM_CAST(EditorFileDialog::FileMode); VARIANT_ENUM_CAST(EditorFileDialog::Access); VARIANT_ENUM_CAST(EditorFileDialog::DisplayMode); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 874f984844..9d8c46cc2d 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -30,7 +30,7 @@ #include "editor_help.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "doc_data_compressed.gen.h" #include "editor/plugins/script_editor_plugin.h" @@ -46,17 +46,17 @@ DocData *EditorHelp::doc = NULL; void EditorHelp::_init_colors() { - title_color = get_color("accent_color", "Editor"); - text_color = get_color("default_color", "RichTextLabel"); - headline_color = get_color("headline_color", "EditorHelp"); + title_color = get_theme_color("accent_color", "Editor"); + text_color = get_theme_color("default_color", "RichTextLabel"); + headline_color = get_theme_color("headline_color", "EditorHelp"); base_type_color = title_color.linear_interpolate(text_color, 0.5); comment_color = text_color * Color(1, 1, 1, 0.6); symbol_color = comment_color; value_color = text_color * Color(1, 1, 1, 0.6); qualifier_color = text_color * Color(1, 1, 1, 0.8); - type_color = get_color("accent_color", "Editor").linear_interpolate(text_color, 0.5); - class_desc->add_color_override("selection_color", get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); - class_desc->add_constant_override("line_separation", Math::round(5 * EDSCALE)); + type_color = get_theme_color("accent_color", "Editor").linear_interpolate(text_color, 0.5); + class_desc->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); + class_desc->add_theme_constant_override("line_separation", Math::round(5 * EDSCALE)); } void EditorHelp::_unhandled_key_input(const Ref<InputEvent> &p_ev) { @@ -173,14 +173,14 @@ void EditorHelp::_class_desc_input(const Ref<InputEvent> &p_input) { void EditorHelp::_class_desc_resized() { // Add extra horizontal margins for better readability. // The margins increase as the width of the editor help container increases. - Ref<Font> doc_code_font = get_font("doc_source", "EditorFonts"); + Ref<Font> doc_code_font = get_theme_font("doc_source", "EditorFonts"); real_t char_width = doc_code_font->get_char_size('x').width; const int display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5; - Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_stylebox("normal", "RichTextLabel")->duplicate(); + Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "RichTextLabel")->duplicate(); class_desc_stylebox->set_default_margin(MARGIN_LEFT, display_margin); class_desc_stylebox->set_default_margin(MARGIN_RIGHT, display_margin); - class_desc->add_style_override("normal", class_desc_stylebox); + class_desc->add_theme_style_override("normal", class_desc_stylebox); } void EditorHelp::_add_type(const String &p_type, const String &p_enum) { @@ -197,8 +197,8 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) { t = p_enum.get_slice(".", 0); } } - const Color text_color = get_color("default_color", "RichTextLabel"); - const Color type_color = get_color("accent_color", "Editor").linear_interpolate(text_color, 0.5); + const Color text_color = get_theme_color("default_color", "RichTextLabel"); + const Color type_color = get_theme_color("accent_color", "Editor").linear_interpolate(text_color, 0.5); class_desc->push_color(type_color); if (can_ref) { if (p_enum.empty()) { @@ -346,10 +346,10 @@ void EditorHelp::_update_doc() { DocData::ClassDoc cd = doc->class_list[edited_class]; //make a copy, so we can sort without worrying - Ref<Font> doc_font = get_font("doc", "EditorFonts"); - Ref<Font> doc_bold_font = get_font("doc_bold", "EditorFonts"); - Ref<Font> doc_title_font = get_font("doc_title", "EditorFonts"); - Ref<Font> doc_code_font = get_font("doc_source", "EditorFonts"); + Ref<Font> doc_font = get_theme_font("doc", "EditorFonts"); + Ref<Font> doc_bold_font = get_theme_font("doc_bold", "EditorFonts"); + Ref<Font> doc_title_font = get_theme_font("doc_title", "EditorFonts"); + Ref<Font> doc_code_font = get_theme_font("doc_source", "EditorFonts"); String link_color_text = title_color.to_html(false); // Class name @@ -1072,7 +1072,7 @@ void EditorHelp::_update_doc() { if (cd.properties[i].description.strip_edges() != String()) { _add_text(DTR(cd.properties[i].description)); } else { - class_desc->add_image(get_icon("Error", "EditorIcons")); + class_desc->add_image(get_theme_icon("Error", "EditorIcons")); class_desc->add_text(" "); class_desc->push_color(comment_color); class_desc->append_bbcode(TTR("There is currently no description for this property. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text)); @@ -1125,7 +1125,7 @@ void EditorHelp::_update_doc() { if (methods_filtered[i].description.strip_edges() != String()) { _add_text(DTR(methods_filtered[i].description)); } else { - class_desc->add_image(get_icon("Error", "EditorIcons")); + class_desc->add_image(get_theme_icon("Error", "EditorIcons")); class_desc->add_text(" "); class_desc->push_color(comment_color); class_desc->append_bbcode(TTR("There is currently no description for this method. Please help us by [color=$color][url=$url]contributing one[/url][/color]!").replace("$url", CONTRIBUTE_URL).replace("$color", link_color_text)); @@ -1209,12 +1209,12 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { DocData *doc = EditorHelp::get_doc_data(); String base_path; - Ref<Font> doc_font = p_rt->get_font("doc", "EditorFonts"); - Ref<Font> doc_bold_font = p_rt->get_font("doc_bold", "EditorFonts"); - Ref<Font> doc_code_font = p_rt->get_font("doc_source", "EditorFonts"); + Ref<Font> doc_font = p_rt->get_theme_font("doc", "EditorFonts"); + Ref<Font> doc_bold_font = p_rt->get_theme_font("doc_bold", "EditorFonts"); + Ref<Font> doc_code_font = p_rt->get_theme_font("doc_source", "EditorFonts"); - Color font_color_hl = p_rt->get_color("headline_color", "EditorHelp"); - Color accent_color = p_rt->get_color("accent_color", "Editor"); + Color font_color_hl = p_rt->get_theme_color("headline_color", "EditorHelp"); + Color accent_color = p_rt->get_theme_color("accent_color", "Editor"); Color link_color = accent_color.linear_interpolate(font_color_hl, 0.8); Color code_color = accent_color.linear_interpolate(font_color_hl, 0.6); @@ -1545,7 +1545,7 @@ EditorHelp::EditorHelp() { class_desc = memnew(RichTextLabel); add_child(class_desc); class_desc->set_v_size_flags(SIZE_EXPAND_FILL); - class_desc->add_color_override("selection_color", get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); + class_desc->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); class_desc->connect("meta_clicked", callable_mp(this, &EditorHelp::_class_desc_select)); class_desc->connect("gui_input", callable_mp(this, &EditorHelp::_class_desc_input)); @@ -1610,9 +1610,14 @@ void EditorHelpBit::_bind_methods() { void EditorHelpBit::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_READY: { + rich_text->clear(); + _add_text_to_rt(text, rich_text); + + } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - rich_text->add_color_override("selection_color", get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); + rich_text->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); } break; default: break; } @@ -1620,8 +1625,9 @@ void EditorHelpBit::_notification(int p_what) { void EditorHelpBit::set_text(const String &p_text) { + text = p_text; rich_text->clear(); - _add_text_to_rt(p_text, rich_text); + _add_text_to_rt(text, rich_text); } EditorHelpBit::EditorHelpBit() { @@ -1629,7 +1635,7 @@ EditorHelpBit::EditorHelpBit() { rich_text = memnew(RichTextLabel); add_child(rich_text); rich_text->connect("meta_clicked", callable_mp(this, &EditorHelpBit::_meta_clicked)); - rich_text->add_color_override("selection_color", get_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); + rich_text->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4)); rich_text->set_override_selected_font_color(false); set_custom_minimum_size(Size2(0, 70 * EDSCALE)); } @@ -1693,13 +1699,13 @@ void FindBar::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - find_prev->set_icon(get_icon("MoveUp", "EditorIcons")); - find_next->set_icon(get_icon("MoveDown", "EditorIcons")); - hide_button->set_normal_texture(get_icon("Close", "EditorIcons")); - hide_button->set_hover_texture(get_icon("Close", "EditorIcons")); - hide_button->set_pressed_texture(get_icon("Close", "EditorIcons")); + find_prev->set_icon(get_theme_icon("MoveUp", "EditorIcons")); + find_next->set_icon(get_theme_icon("MoveDown", "EditorIcons")); + hide_button->set_normal_texture(get_theme_icon("Close", "EditorIcons")); + hide_button->set_hover_texture(get_theme_icon("Close", "EditorIcons")); + hide_button->set_pressed_texture(get_theme_icon("Close", "EditorIcons")); hide_button->set_custom_minimum_size(hide_button->get_normal_texture()->get_size()); - matches_label->add_color_override("font_color", results_count > 0 ? get_color("font_color", "Label") : get_color("error_color", "Editor")); + matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -1780,7 +1786,7 @@ void FindBar::_update_matches_label() { } else { matches_label->show(); - matches_label->add_color_override("font_color", results_count > 0 ? get_color("font_color", "Label") : get_color("error_color", "Editor")); + matches_label->add_theme_color_override("font_color", results_count > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); matches_label->set_text(vformat(results_count == 1 ? TTR("%d match.") : TTR("%d matches."), results_count)); } } @@ -1828,7 +1834,7 @@ void FindBar::_search_text_changed(const String &p_text) { void FindBar::_search_text_entered(const String &p_text) { - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { search_prev(); } else { search_next(); diff --git a/editor/editor_help.h b/editor/editor_help.h index 0d3ecf9bd0..d9c7194003 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -200,6 +200,8 @@ class EditorHelpBit : public PanelContainer { void _go_to_help(String p_what); void _meta_clicked(String p_select); + String text; + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index f7ce2dd4fc..6fba5b1b4c 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -37,13 +37,13 @@ void EditorHelpSearch::_update_icons() { - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_right_icon(results_tree->get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); - search_box->add_icon_override("right_icon", get_icon("Search", "EditorIcons")); - case_sensitive_button->set_icon(get_icon("MatchCase", "EditorIcons")); - hierarchy_button->set_icon(get_icon("ClassList", "EditorIcons")); + search_box->add_theme_icon_override("right_icon", results_tree->get_theme_icon("Search", "EditorIcons")); + case_sensitive_button->set_icon(results_tree->get_theme_icon("MatchCase", "EditorIcons")); + hierarchy_button->set_icon(results_tree->get_theme_icon("ClassList", "EditorIcons")); - if (is_visible_in_tree()) + if (is_visible()) _update_results(); } @@ -57,7 +57,7 @@ void EditorHelpSearch::_update_results() { if (hierarchy_button->is_pressed()) search_flags |= SEARCH_SHOW_HIERARCHY; - search = Ref<Runner>(memnew(Runner(this, results_tree, term, search_flags))); + search = Ref<Runner>(memnew(Runner(results_tree, results_tree, term, search_flags))); set_process(true); } @@ -105,6 +105,13 @@ void EditorHelpSearch::_confirmed() { void EditorHelpSearch::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + results_tree->call_deferred("clear"); // Wait for the Tree's mouse event propagation. + get_ok()->set_disabled(true); + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "search_help", Rect2(get_position(), get_size())); + } + } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { _update_icons(); @@ -114,12 +121,7 @@ void EditorHelpSearch::_notification(int p_what) { connect("confirmed", callable_mp(this, &EditorHelpSearch::_confirmed)); _update_icons(); } break; - case NOTIFICATION_POPUP_HIDE: { - results_tree->call_deferred("clear"); // Wait for the Tree's mouse event propagation. - get_ok()->set_disabled(true); - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "search_help", get_rect()); - } break; case NOTIFICATION_PROCESS: { // Update background search. @@ -184,7 +186,7 @@ EditorHelpSearch::EditorHelpSearch() { old_search = false; set_hide_on_ok(false); - set_resizable(true); + set_title(TTR("Search Help")); get_ok()->set_disabled(true); @@ -200,7 +202,7 @@ EditorHelpSearch::EditorHelpSearch() { search_box = memnew(LineEdit); search_box->set_custom_minimum_size(Size2(200, 0) * EDSCALE); - search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); search_box->connect("gui_input", callable_mp(this, &EditorHelpSearch::_search_box_gui_input)); search_box->connect("text_changed", callable_mp(this, &EditorHelpSearch::_search_box_text_changed)); register_text_enter(search_box); @@ -210,7 +212,7 @@ EditorHelpSearch::EditorHelpSearch() { case_sensitive_button->set_tooltip(TTR("Case Sensitive")); case_sensitive_button->connect("pressed", callable_mp(this, &EditorHelpSearch::_update_results)); case_sensitive_button->set_toggle_mode(true); - case_sensitive_button->set_focus_mode(FOCUS_NONE); + case_sensitive_button->set_focus_mode(Control::FOCUS_NONE); hbox->add_child(case_sensitive_button); hierarchy_button = memnew(ToolButton); @@ -218,7 +220,7 @@ EditorHelpSearch::EditorHelpSearch() { hierarchy_button->connect("pressed", callable_mp(this, &EditorHelpSearch::_update_results)); hierarchy_button->set_toggle_mode(true); hierarchy_button->set_pressed(true); - hierarchy_button->set_focus_mode(FOCUS_NONE); + hierarchy_button->set_focus_mode(Control::FOCUS_NONE); hbox->add_child(hierarchy_button); filter_combo = memnew(OptionButton); @@ -237,7 +239,7 @@ EditorHelpSearch::EditorHelpSearch() { // Create the results tree. results_tree = memnew(Tree); - results_tree->set_v_size_flags(SIZE_EXPAND_FILL); + results_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); results_tree->set_columns(2); results_tree->set_column_title(0, TTR("Name")); results_tree->set_column_title(1, TTR("Member Type")); @@ -479,10 +481,10 @@ TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_ TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray) { Ref<Texture2D> icon = empty_icon; - if (ui_service->has_icon(p_doc->name, "EditorIcons")) - icon = ui_service->get_icon(p_doc->name, "EditorIcons"); + if (ui_service->has_theme_icon(p_doc->name, "EditorIcons")) + icon = ui_service->get_theme_icon(p_doc->name, "EditorIcons"); else if (ClassDB::class_exists(p_doc->name) && ClassDB::is_parent_class(p_doc->name, "Object")) - icon = ui_service->get_icon("Object", "EditorIcons"); + icon = ui_service->get_theme_icon("Object", "EditorIcons"); String tooltip = p_doc->brief_description.strip_edges(); TreeItem *item = results_tree->create_item(p_parent); @@ -557,10 +559,10 @@ TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, cons Ref<Texture2D> icon; String text; if (search_flags & SEARCH_SHOW_HIERARCHY) { - icon = ui_service->get_icon(p_icon, "EditorIcons"); + icon = ui_service->get_theme_icon(p_icon, "EditorIcons"); text = p_name; } else { - icon = ui_service->get_icon(p_icon, "EditorIcons"); + icon = ui_service->get_theme_icon(p_icon, "EditorIcons"); /*// In flat mode, show the class icon. if (ui_service->has_icon(p_class_name, "EditorIcons")) icon = ui_service->get_icon(p_class_name, "EditorIcons"); @@ -598,6 +600,6 @@ EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, results_tree(p_results_tree), term((p_search_flags & SEARCH_CASE_SENSITIVE) == 0 ? p_term.strip_edges().to_lower() : p_term.strip_edges()), search_flags(p_search_flags), - empty_icon(ui_service->get_icon("ArrowRight", "EditorIcons")), - disabled_color(ui_service->get_color("disabled_font_color", "Editor")) { + empty_icon(ui_service->get_theme_icon("ArrowRight", "EditorIcons")), + disabled_color(ui_service->get_theme_color("disabled_font_color", "Editor")) { } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index be3ee397e8..ba02f8e99f 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -41,7 +41,7 @@ Size2 EditorProperty::get_minimum_size() const { Size2 ms; - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); ms.height = font->get_height(); for (int i = 0; i < get_child_count(); i++) { @@ -62,17 +62,17 @@ Size2 EditorProperty::get_minimum_size() const { } if (keying) { - Ref<Texture2D> key = get_icon("Key", "EditorIcons"); - ms.width += key->get_width() + get_constant("hseparator", "Tree"); + Ref<Texture2D> key = get_theme_icon("Key", "EditorIcons"); + ms.width += key->get_width() + get_theme_constant("hseparator", "Tree"); } if (checkable) { - Ref<Texture2D> check = get_icon("checked", "CheckBox"); - ms.width += check->get_width() + get_constant("hseparation", "CheckBox") + get_constant("hseparator", "Tree"); + Ref<Texture2D> check = get_theme_icon("checked", "CheckBox"); + ms.width += check->get_width() + get_theme_constant("hseparation", "CheckBox") + get_theme_constant("hseparator", "Tree"); } if (bottom_editor != NULL && bottom_editor->is_visible()) { - ms.height += get_constant("vseparation", "Tree"); + ms.height += get_theme_constant("vseparation", "Tree"); Size2 bems = bottom_editor->get_combined_minimum_size(); //bems.width += get_constant("item_margin", "Tree"); ms.height += bems.height; @@ -103,7 +103,7 @@ void EditorProperty::_notification(int p_what) { { int child_room = size.width * (1.0 - split_ratio); - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); int height = font->get_height(); bool no_children = true; @@ -136,19 +136,19 @@ void EditorProperty::_notification(int p_what) { int m = 0; //get_constant("item_margin", "Tree"); - bottom_rect = Rect2(m, rect.size.height + get_constant("vseparation", "Tree"), size.width - m, bottom_editor->get_combined_minimum_size().height); + bottom_rect = Rect2(m, rect.size.height + get_theme_constant("vseparation", "Tree"), size.width - m, bottom_editor->get_combined_minimum_size().height); } if (keying) { Ref<Texture2D> key; if (use_keying_next()) { - key = get_icon("KeyNext", "EditorIcons"); + key = get_theme_icon("KeyNext", "EditorIcons"); } else { - key = get_icon("Key", "EditorIcons"); + key = get_theme_icon("Key", "EditorIcons"); } - rect.size.x -= key->get_width() + get_constant("hseparator", "Tree"); + rect.size.x -= key->get_width() + get_theme_constant("hseparator", "Tree"); if (no_children) { text_size -= key->get_width() + 4 * EDSCALE; @@ -180,8 +180,8 @@ void EditorProperty::_notification(int p_what) { } if (p_what == NOTIFICATION_DRAW) { - Ref<Font> font = get_font("font", "Tree"); - Color dark_color = get_color("dark_color_2", "Editor"); + Ref<Font> font = get_theme_font("font", "Tree"); + Color dark_color = get_theme_color("dark_color_2", "Editor"); Size2 size = get_size(); if (bottom_editor) { @@ -191,7 +191,7 @@ void EditorProperty::_notification(int p_what) { } if (selected) { - Ref<StyleBox> sb = get_stylebox("selected", "Tree"); + Ref<StyleBox> sb = get_theme_stylebox("selected", "Tree"); draw_style_box(sb, Rect2(Vector2(), size)); } @@ -204,9 +204,9 @@ void EditorProperty::_notification(int p_what) { Color color; if (draw_red) { - color = get_color("error_color", "Editor"); + color = get_theme_color("error_color", "Editor"); } else { - color = get_color("property_color", "Editor"); + color = get_theme_color("property_color", "Editor"); } if (label.find(".") != -1) { color.a = 0.5; //this should be un-hacked honestly, as it's used for editor overrides @@ -218,9 +218,9 @@ void EditorProperty::_notification(int p_what) { if (checkable) { Ref<Texture2D> checkbox; if (checked) - checkbox = get_icon("GuiChecked", "EditorIcons"); + checkbox = get_theme_icon("GuiChecked", "EditorIcons"); else - checkbox = get_icon("GuiUnchecked", "EditorIcons"); + checkbox = get_theme_icon("GuiUnchecked", "EditorIcons"); Color color2(1, 1, 1); if (check_hover) { @@ -230,16 +230,16 @@ void EditorProperty::_notification(int p_what) { } check_rect = Rect2(ofs, ((size.height - checkbox->get_height()) / 2), checkbox->get_width(), checkbox->get_height()); draw_texture(checkbox, check_rect.position, color2); - ofs += get_constant("hseparator", "Tree") + checkbox->get_width() + get_constant("hseparation", "CheckBox"); + ofs += get_theme_constant("hseparator", "Tree") + checkbox->get_width() + get_theme_constant("hseparation", "CheckBox"); text_limit -= ofs; } else { check_rect = Rect2(); } if (can_revert) { - Ref<Texture2D> reload_icon = get_icon("ReloadSmall", "EditorIcons"); - text_limit -= reload_icon->get_width() + get_constant("hseparator", "Tree") * 2; - revert_rect = Rect2(text_limit + get_constant("hseparator", "Tree"), (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height()); + Ref<Texture2D> reload_icon = get_theme_icon("ReloadSmall", "EditorIcons"); + text_limit -= reload_icon->get_width() + get_theme_constant("hseparator", "Tree") * 2; + revert_rect = Rect2(text_limit + get_theme_constant("hseparator", "Tree"), (size.height - reload_icon->get_height()) / 2, reload_icon->get_width(), reload_icon->get_height()); Color color2(1, 1, 1); if (revert_hover) { @@ -260,12 +260,12 @@ void EditorProperty::_notification(int p_what) { Ref<Texture2D> key; if (use_keying_next()) { - key = get_icon("KeyNext", "EditorIcons"); + key = get_theme_icon("KeyNext", "EditorIcons"); } else { - key = get_icon("Key", "EditorIcons"); + key = get_theme_icon("Key", "EditorIcons"); } - ofs = size.width - key->get_width() - get_constant("hseparator", "Tree"); + ofs = size.width - key->get_width() - get_theme_constant("hseparator", "Tree"); Color color2(1, 1, 1); if (keying_hover) { @@ -776,13 +776,14 @@ Control *EditorProperty::make_custom_tooltip(const String &p_text) const { tooltip_text = p_text; EditorHelpBit *help_bit = memnew(EditorHelpBit); - help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel")); + //help_bit->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel")); help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); + String text; PackedStringArray slices = p_text.split("::", false); if (!slices.empty()) { String property_name = slices[0].strip_edges(); - String text = TTR("Property:") + " [u][b]" + property_name + "[/b][/u]"; + text = TTR("Property:") + " [u][b]" + property_name + "[/b][/u]"; if (slices.size() > 1) { String property_doc = slices[1].strip_edges(); @@ -790,7 +791,7 @@ Control *EditorProperty::make_custom_tooltip(const String &p_text) const { text += "\n" + property_doc; } } - help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene + help_bit->set_text(text); } return help_bit; @@ -987,9 +988,9 @@ void EditorInspectorCategory::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { draw_rect(Rect2(Vector2(), get_size()), bg_color); - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); - int hs = get_constant("hseparation", "Tree"); + int hs = get_theme_constant("hseparation", "Tree"); int w = font->get_string_size(label).width; if (icon.is_valid()) { @@ -1003,7 +1004,7 @@ void EditorInspectorCategory::_notification(int p_what) { ofs += hs + icon->get_width(); } - Color color = get_color("font_color", "Tree"); + Color color = get_theme_color("font_color", "Tree"); draw_string(font, Point2(ofs, font->get_ascent() + (get_size().height - font->get_height()) / 2).floor(), label, color, get_size().width); } } @@ -1012,7 +1013,7 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons tooltip_text = p_text; EditorHelpBit *help_bit = memnew(EditorHelpBit); - help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel")); + help_bit->add_theme_style_override("panel", get_theme_stylebox("panel", "TooltipPanel")); help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE); PackedStringArray slices = p_text.split("::", false); @@ -1026,7 +1027,7 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons text += "\n" + property_doc; } } - help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene + help_bit->set_text(text); //hack so it uses proper theme once inside scene } return help_bit; @@ -1034,7 +1035,7 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons Size2 EditorInspectorCategory::get_minimum_size() const { - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); Size2 ms; ms.width = 1; @@ -1042,7 +1043,7 @@ Size2 EditorInspectorCategory::get_minimum_size() const { if (icon.is_valid()) { ms.height = MAX(icon->get_height(), ms.height); } - ms.height += get_constant("vseparation", "Tree"); + ms.height += get_theme_constant("vseparation", "Tree"); return ms; } @@ -1074,14 +1075,14 @@ void EditorInspectorSection::_notification(int p_what) { if (p_what == NOTIFICATION_SORT_CHILDREN) { - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); Ref<Texture2D> arrow; if (foldable) { if (object->editor_is_section_unfolded(section)) { - arrow = get_icon("arrow", "Tree"); + arrow = get_theme_icon("arrow", "Tree"); } else { - arrow = get_icon("arrow_collapsed", "Tree"); + arrow = get_theme_icon("arrow_collapsed", "Tree"); } } @@ -1092,8 +1093,8 @@ void EditorInspectorSection::_notification(int p_what) { offset.y = MAX(offset.y, arrow->get_height()); } - offset.y += get_constant("vseparation", "Tree"); - offset.x += get_constant("inspector_margin", "Editor"); + offset.y += get_theme_constant("vseparation", "Tree"); + offset.x += get_theme_constant("inspector_margin", "Editor"); Rect2 rect(offset, size - offset); @@ -1120,24 +1121,24 @@ void EditorInspectorSection::_notification(int p_what) { if (foldable) { if (object->editor_is_section_unfolded(section)) { - arrow = get_icon("arrow", "Tree"); + arrow = get_theme_icon("arrow", "Tree"); } else { - arrow = get_icon("arrow_collapsed", "Tree"); + arrow = get_theme_icon("arrow_collapsed", "Tree"); } } - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); int h = font->get_height(); if (arrow.is_valid()) { h = MAX(h, arrow->get_height()); } - h += get_constant("vseparation", "Tree"); + h += get_theme_constant("vseparation", "Tree"); draw_rect(Rect2(Vector2(), Vector2(get_size().width, h)), bg_color); const int arrow_margin = 3; - Color color = get_color("font_color", "Tree"); + Color color = get_theme_color("font_color", "Tree"); draw_string(font, Point2(Math::round((16 + arrow_margin) * EDSCALE), font->get_ascent() + (h - font->get_height()) / 2).floor(), label, color, get_size().width); if (arrow.is_valid()) { @@ -1163,9 +1164,9 @@ Size2 EditorInspectorSection::get_minimum_size() const { ms.height = MAX(ms.height, minsize.height); } - Ref<Font> font = get_font("font", "Tree"); - ms.height += font->get_height() + get_constant("vseparation", "Tree"); - ms.width += get_constant("inspector_margin", "Editor"); + Ref<Font> font = get_theme_font("font", "Tree"); + ms.height += font->get_height() + get_theme_constant("vseparation", "Tree"); + ms.width += get_theme_constant("inspector_margin", "Editor"); return ms; } @@ -1201,7 +1202,7 @@ void EditorInspectorSection::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - Ref<Font> font = get_font("font", "Tree"); + Ref<Font> font = get_theme_font("font", "Tree"); if (mb->get_position().y > font->get_height()) { //clicked outside return; } @@ -1488,7 +1489,7 @@ void EditorInspector::update_tree() { item_path[""] = main_vbox; - Color sscolor = get_color("prop_subsection", "Editor"); + Color sscolor = get_theme_color("prop_subsection", "Editor"); for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) { Ref<EditorInspectorPlugin> ped = E->get(); @@ -1540,7 +1541,7 @@ void EditorInspector::update_tree() { category->icon = EditorNode::get_singleton()->get_class_icon(type, "Object"); category->label = type; - category->bg_color = get_color("prop_category", "Editor"); + category->bg_color = get_theme_color("prop_category", "Editor"); if (use_doc_hints) { StringName type2 = p.name; if (!class_descr_cache.has(type2)) { @@ -1978,9 +1979,9 @@ void EditorInspector::set_sub_inspector(bool p_enable) { return; if (sub_inspector) { - add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); + add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg", "Editor")); } else { - add_style_override("bg", get_stylebox("bg", "Tree")); + add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); } } @@ -2203,9 +2204,9 @@ void EditorInspector::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { if (sub_inspector) { - add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); + add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg", "Editor")); } else { - add_style_override("bg", get_stylebox("bg", "Tree")); + add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); get_tree()->connect("node_removed", callable_mp(this, &EditorInspector::_node_removed)); } } @@ -2266,9 +2267,9 @@ void EditorInspector::_notification(int p_what) { if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { if (sub_inspector) { - add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); + add_theme_style_override("bg", get_theme_stylebox("sub_inspector_bg", "Editor")); } else if (is_inside_tree()) { - add_style_override("bg", get_stylebox("bg", "Tree")); + add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); } update_tree(); @@ -2331,7 +2332,7 @@ EditorInspector::EditorInspector() { undo_redo = NULL; main_vbox = memnew(VBoxContainer); main_vbox->set_h_size_flags(SIZE_EXPAND_FILL); - main_vbox->add_constant_override("separation", 0); + main_vbox->add_theme_constant_override("separation", 0); add_child(main_vbox); set_enable_h_scroll(false); set_enable_v_scroll(true); diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp index 776fbd9314..dbd043c494 100644 --- a/editor/editor_layouts_dialog.cpp +++ b/editor/editor_layouts_dialog.cpp @@ -52,12 +52,12 @@ void EditorLayoutsDialog::_line_gui_input(const Ref<InputEvent> &p_event) { if (get_hide_on_ok()) hide(); ok_pressed(); - accept_event(); + set_input_as_handled(); } break; case KEY_ESCAPE: { hide(); - accept_event(); + set_input_as_handled(); } break; } } @@ -110,15 +110,15 @@ EditorLayoutsDialog::EditorLayoutsDialog() { makevb = memnew(VBoxContainer); add_child(makevb); - makevb->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5); - makevb->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -5); + makevb->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5); + makevb->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5); layout_names = memnew(ItemList); makevb->add_child(layout_names); layout_names->set_visible(true); layout_names->set_margin(MARGIN_TOP, 5); - layout_names->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5); - layout_names->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -5); + layout_names->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5); + layout_names->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5); layout_names->set_v_size_flags(Control::SIZE_EXPAND_FILL); layout_names->set_select_mode(ItemList::SELECT_MULTI); layout_names->set_allow_rmb_select(true); @@ -126,8 +126,8 @@ EditorLayoutsDialog::EditorLayoutsDialog() { name = memnew(LineEdit); makevb->add_child(name); name->set_margin(MARGIN_TOP, 5); - name->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5); - name->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -5); + name->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5); + name->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5); name->connect("gui_input", callable_mp(this, &EditorLayoutsDialog::_line_gui_input)); name->connect("focus_entered", callable_mp(layout_names, &ItemList::unselect_all)); } diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 0e50a5e95c..91e53edeac 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -62,12 +62,12 @@ void EditorLog::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { //button->set_icon(get_icon("Console","EditorIcons")); - log->add_font_override("normal_font", get_font("output_source", "EditorFonts")); + log->add_theme_font_override("normal_font", get_theme_font("output_source", "EditorFonts")); } else if (p_what == NOTIFICATION_THEME_CHANGED) { - Ref<DynamicFont> df_output_code = get_font("output_source", "EditorFonts"); + Ref<DynamicFont> df_output_code = get_theme_font("output_source", "EditorFonts"); if (df_output_code.is_valid()) { if (log != NULL) { - log->add_font_override("normal_font", get_font("output_source", "EditorFonts")); + log->add_theme_font_override("normal_font", get_theme_font("output_source", "EditorFonts")); } } } @@ -101,22 +101,22 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) { case MSG_TYPE_STD: { } break; case MSG_TYPE_ERROR: { - log->push_color(get_color("error_color", "Editor")); - Ref<Texture2D> icon = get_icon("Error", "EditorIcons"); + log->push_color(get_theme_color("error_color", "Editor")); + Ref<Texture2D> icon = get_theme_icon("Error", "EditorIcons"); log->add_image(icon); log->add_text(" "); tool_button->set_icon(icon); } break; case MSG_TYPE_WARNING: { - log->push_color(get_color("warning_color", "Editor")); - Ref<Texture2D> icon = get_icon("Warning", "EditorIcons"); + log->push_color(get_theme_color("warning_color", "Editor")); + Ref<Texture2D> icon = get_theme_icon("Warning", "EditorIcons"); log->add_image(icon); log->add_text(" "); tool_button->set_icon(icon); } break; case MSG_TYPE_EDITOR: { // Distinguish editor messages from messages printed by the project - log->push_color(get_color("font_color", "Editor") * Color(1, 1, 1, 0.6)); + log->push_color(get_theme_color("font_color", "Editor") * Color(1, 1, 1, 0.6)); } break; } @@ -181,7 +181,7 @@ EditorLog::EditorLog() { current = Thread::get_caller_id(); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); + add_theme_constant_override("separation", get_theme_constant("separation", "VBoxContainer")); EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk, this); } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f40762586e..86d4b76ee2 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -32,6 +32,7 @@ #include "core/bind/core_bind.h" #include "core/class_db.h" +#include "core/input/input_filter.h" #include "core/io/config_file.h" #include "core/io/image_loader.h" #include "core/io/resource_loader.h" @@ -39,7 +40,6 @@ #include "core/io/stream_peer_ssl.h" #include "core/message_queue.h" #include "core/os/file_access.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/path_remap.h" @@ -47,7 +47,6 @@ #include "core/project_settings.h" #include "core/translation.h" #include "core/version.h" -#include "main/input_default.h" #include "main/main.h" #include "scene/gui/center_container.h" #include "scene/gui/control.h" @@ -170,7 +169,8 @@ #include "editor/register_exporters.h" #include "editor/run_settings_dialog.h" #include "editor/settings_config_dialog.h" - +#include "scene/main/window.h" +#include "servers/display_server.h" #include <stdio.h> #include <stdlib.h> @@ -180,10 +180,12 @@ void EditorNode::_update_scene_tabs() { bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button"); - OS::get_singleton()->global_menu_clear("_dock"); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { + DisplayServer::get_singleton()->global_menu_clear("_dock"); + } scene_tabs->clear_tabs(); - Ref<Texture2D> script_icon = gui_base->get_icon("Script", "EditorIcons"); + Ref<Texture2D> script_icon = gui_base->get_theme_icon("Script", "EditorIcons"); for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { Node *type_node = editor_data.get_edited_scene_root(i); @@ -196,15 +198,19 @@ void EditorNode::_update_scene_tabs() { bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon); - OS::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), GLOBAL_SCENE, i); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { + DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), i); + } if (show_rb && editor_data.get_scene_root_script(i).is_valid()) { scene_tabs->set_tab_right_button(i, script_icon); } } - OS::get_singleton()->global_menu_add_separator("_dock"); - OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant()); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { + DisplayServer::get_singleton()->global_menu_add_separator("_dock"); + DisplayServer::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), callable_mp(this, &EditorNode::_global_menu_new_window)); + } scene_tabs->set_current_tab(editor_data.get_edited_scene()); @@ -253,16 +259,13 @@ void EditorNode::_update_title() { if (unsaved_cache) title += " (*)"; - OS::get_singleton()->set_window_title(title); + DisplayServer::get_singleton()->window_set_title(title); } void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) { - if (Node::get_viewport()->get_modal_stack_top()) - return; //ignore because of modal window - Ref<InputEventKey> k = p_event; - if (k.is_valid() && k->is_pressed() && !k->is_echo() && !gui_base->get_viewport()->gui_has_modal_stack()) { + if (k.is_valid() && k->is_pressed() && !k->is_echo()) { EditorPlugin *old_editor = editor_plugin_screen; @@ -297,7 +300,7 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) { } if (old_editor != editor_plugin_screen) { - get_tree()->set_input_as_handled(); + get_tree()->get_root()->set_input_as_handled(); } } } @@ -335,13 +338,13 @@ void EditorNode::_notification(int p_what) { // update the icon itself only when the spinner is visible if (EditorSettings::get_singleton()->get("interface/editor/show_update_spinner")) { - update_spinner->set_icon(gui_base->get_icon("Progress" + itos(update_spinner_step + 1), "EditorIcons")); + update_spinner->set_icon(gui_base->get_theme_icon("Progress" + itos(update_spinner_step + 1), "EditorIcons")); } } editor_selection->update(); - scene_root->set_size_override(true, Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"))); + //scene_root->set_size_override(true, Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"))); { //TODO should only happen on settings changed int current_filter = GLOBAL_GET("rendering/canvas_textures/default_texture_filter"); @@ -374,8 +377,7 @@ void EditorNode::_notification(int p_what) { get_tree()->get_root()->set_as_audio_listener(false); get_tree()->get_root()->set_as_audio_listener_2d(false); get_tree()->set_auto_accept_quit(false); - get_tree()->connect("files_dropped", callable_mp(this, &EditorNode::_dropped_files)); - get_tree()->connect("global_menu_action", callable_mp(this, &EditorNode::_global_menu_action)); + get_tree()->get_root()->connect("files_dropped", callable_mp(this, &EditorNode::_dropped_files)); /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; @@ -417,7 +419,7 @@ void EditorNode::_notification(int p_what) { /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_FOCUS_IN: { // Restore the original FPS cap after focusing back on the editor OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec"))); @@ -425,18 +427,18 @@ void EditorNode::_notification(int p_what) { EditorFileSystem::get_singleton()->scan_changes(); } break; - case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_FOCUS_OUT: { // Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec"))); } break; - case MainLoop::NOTIFICATION_WM_ABOUT: { + case NOTIFICATION_WM_ABOUT: { show_about(); } break; - case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { + case NOTIFICATION_WM_CLOSE_REQUEST: { _menu_option_confirm(FILE_QUIT, false); } break; @@ -448,17 +450,17 @@ void EditorNode::_notification(int p_what) { theme_base->set_theme(theme); gui_base->set_theme(theme); - gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); - scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles")); - bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); - scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles")); - scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles")); + gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox("Background", "EditorStyles")); + scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox("Content", "EditorStyles")); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer")); + scene_tabs->add_theme_style_override("tab_fg", gui_base->get_theme_stylebox("SceneTabFG", "EditorStyles")); + scene_tabs->add_theme_style_override("tab_bg", gui_base->get_theme_stylebox("SceneTabBG", "EditorStyles")); - file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); - project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); - debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); - settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); - help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); + file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); + project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); + debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); + settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); + help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); if (EDITOR_GET("interface/scene_tabs/resize_if_many_tabs")) { scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE); @@ -471,7 +473,7 @@ void EditorNode::_notification(int p_what) { // debugger area if (EditorDebuggerNode::get_singleton()->is_visible()) - bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")); // update_icons for (int i = 0; i < singleton->main_editor_buttons.size(); i++) { @@ -482,36 +484,36 @@ void EditorNode::_notification(int p_what) { if (icon.is_valid()) { tb->set_icon(icon); - } else if (singleton->gui_base->has_icon(p_editor->get_name(), "EditorIcons")) { - tb->set_icon(singleton->gui_base->get_icon(p_editor->get_name(), "EditorIcons")); + } else if (singleton->gui_base->has_theme_icon(p_editor->get_name(), "EditorIcons")) { + tb->set_icon(singleton->gui_base->get_theme_icon(p_editor->get_name(), "EditorIcons")); } } _build_icon_type_cache(); - play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons")); - play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons")); - play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); - pause_button->set_icon(gui_base->get_icon("Pause", "EditorIcons")); - stop_button->set_icon(gui_base->get_icon("Stop", "EditorIcons")); + play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons")); + play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons")); + play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons")); + pause_button->set_icon(gui_base->get_theme_icon("Pause", "EditorIcons")); + stop_button->set_icon(gui_base->get_theme_icon("Stop", "EditorIcons")); - prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons")); - distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons")); - scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons")); + prev_scene->set_icon(gui_base->get_theme_icon("PrevScene", "EditorIcons")); + distraction_free->set_icon(gui_base->get_theme_icon("DistractionFree", "EditorIcons")); + scene_tab_add->set_icon(gui_base->get_theme_icon("Add", "EditorIcons")); - bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); + bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons")); // clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons")); dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons")); PopupMenu *p = help_menu->get_popup(); - p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_icon("HelpSearch", "EditorIcons")); - p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_icon("Instance", "EditorIcons")); - p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_icon("Instance", "EditorIcons")); - p->set_item_icon(p->get_item_index(HELP_ISSUES), gui_base->get_icon("Instance", "EditorIcons")); - p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_icon("Instance", "EditorIcons")); - p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_theme_icon("HelpSearch", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_theme_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_theme_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_ISSUES), gui_base->get_theme_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon("Instance", "EditorIcons")); + p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_theme_icon("Godot", "EditorIcons")); _update_update_spinner(); } break; @@ -822,7 +824,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String } } - file->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); saving_resource = p_resource; current_option = RESOURCE_SAVE_AS; @@ -1466,7 +1468,7 @@ void EditorNode::_dialog_action(String p_file) { int scene_idx = (current_option == FILE_SAVE_SCENE || current_option == FILE_SAVE_AS_SCENE) ? -1 : tab_closing; - if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) { + if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { bool same_open_scene = false; for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { if (editor_data.get_scene_path(i) == p_file && i != scene_idx) @@ -1490,7 +1492,7 @@ void EditorNode::_dialog_action(String p_file) { } break; case FILE_SAVE_AND_RUN: { - if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) { + if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { _save_default_environment(); _save_scene_with_preview(p_file); @@ -1620,7 +1622,7 @@ void EditorNode::_dialog_action(String p_file) { } break; default: { //save scene? - if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) { + if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { _save_scene_with_preview(p_file); } @@ -1970,11 +1972,11 @@ void EditorNode::_run(bool p_current, const String &p_custom) { } play_button->set_pressed(false); - play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons")); + play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons")); play_scene_button->set_pressed(false); - play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons")); + play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons")); play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); + play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons")); String main_scene; String run_filename; @@ -2057,14 +2059,14 @@ void EditorNode::_run(bool p_current, const String &p_custom) { emit_signal("play_pressed"); if (p_current) { play_scene_button->set_pressed(true); - play_scene_button->set_icon(gui_base->get_icon("Reload", "EditorIcons")); + play_scene_button->set_icon(gui_base->get_theme_icon("Reload", "EditorIcons")); } else if (p_custom != "") { run_custom_filename = p_custom; play_custom_scene_button->set_pressed(true); - play_custom_scene_button->set_icon(gui_base->get_icon("Reload", "EditorIcons")); + play_custom_scene_button->set_icon(gui_base->get_theme_icon("Reload", "EditorIcons")); } else { play_button->set_pressed(true); - play_button->set_icon(gui_base->get_icon("Reload", "EditorIcons")); + play_button->set_icon(gui_base->get_theme_icon("Reload", "EditorIcons")); } stop_button->set_disabled(false); @@ -2085,7 +2087,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case FILE_NEW_INHERITED_SCENE: case FILE_OPEN_SCENE: { - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); List<String> extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions); file->clear_filters(); @@ -2158,7 +2160,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { String scene_filename = editor_data.get_edited_scene_root(tab_closing)->get_filename(); save_confirmation->get_ok()->set_text(TTR("Save & Close")); save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene")); - save_confirmation->popup_centered_minsize(); + save_confirmation->popup_centered(); break; } } else if (p_option == FILE_CLOSE) { @@ -2212,7 +2214,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { break; } - file->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); List<String> extensions; Ref<PackedScene> sd = memnew(PackedScene); @@ -2254,7 +2256,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { confirmation->get_cancel()->set_text(TTR("No")); confirmation->get_ok()->set_text(TTR("Yes")); confirmation->set_text(TTR("This scene has never been saved. Save before running?")); - confirmation->popup_centered_minsize(); + confirmation->popup_centered(); break; } @@ -2326,7 +2328,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { confirmation->get_ok()->set_text(TTR("Open")); confirmation->set_text(TTR("Current scene not saved. Open anyway?")); - confirmation->popup_centered_minsize(); + confirmation->popup_centered(); break; } @@ -2341,7 +2343,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case EDIT_UNDO: { - if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { + if (InputFilter::get_singleton()->get_mouse_button_mask() & 0x7) { log->add_message("Can't undo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR); } else { String action = editor_data.get_undo_redo().get_current_action_name(); @@ -2355,7 +2357,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case EDIT_REDO: { - if (Input::get_singleton()->get_mouse_button_mask() & 0x7) { + if (InputFilter::get_singleton()->get_mouse_button_mask() & 0x7) { log->add_message("Can't redo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR); } else { if (!editor_data.get_undo_redo().redo()) { @@ -2384,7 +2386,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (unsaved_cache && !p_confirmed) { confirmation->get_ok()->set_text(TTR("Revert")); confirmation->set_text(TTR("This action cannot be undone. Revert anyway?")); - confirmation->popup_centered_minsize(); + confirmation->popup_centered(); break; } @@ -2424,11 +2426,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { editor_run.stop(); run_custom_filename.clear(); play_button->set_pressed(false); - play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons")); + play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons")); play_scene_button->set_pressed(false); - play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons")); + play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons")); play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); + play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons")); stop_button->set_disabled(true); if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) { @@ -2487,11 +2489,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { export_template_manager->install_android_template(); } else { if (DirAccess::exists("res://android/build")) { - remove_android_build_template->popup_centered_minsize(); + remove_android_build_template->popup_centered(); } else if (export_template_manager->can_install_android_template()) { - install_android_build_template->popup_centered_minsize(); + install_android_build_template->popup_centered(); } else { - custom_build_manage_templates->popup_centered_minsize(); + custom_build_manage_templates->popup_centered(); } } } break; @@ -2513,7 +2515,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { confirmation->get_ok()->set_text(p_option == FILE_QUIT ? TTR("Quit") : TTR("Yes")); confirmation->set_text(p_option == FILE_QUIT ? TTR("Exit the editor?") : TTR("Open Project Manager?")); - confirmation->popup_centered_minsize(); + confirmation->popup_centered(); } else { _discard_changes(); break; @@ -2534,11 +2536,11 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { save_confirmation->get_ok()->set_text(TTR("Save & Quit")); save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes the following scene(s) before opening Project Manager?")) + unsaved_scenes); - save_confirmation->popup_centered_minsize(); + save_confirmation->popup_centered(); } } - OS::get_singleton()->request_attention(); + DisplayServer::get_singleton()->window_request_attention(); break; } @@ -2586,13 +2588,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case SETTINGS_TOGGLE_FULLSCREEN: { - OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen()); + DisplayServer::get_singleton()->window_set_mode(DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_FULLSCREEN ? DisplayServer::WINDOW_MODE_WINDOWED : DisplayServer::WINDOW_MODE_FULLSCREEN); } break; case SETTINGS_TOGGLE_CONSOLE: { - bool was_visible = OS::get_singleton()->is_console_visible(); - OS::get_singleton()->set_console_visible(!was_visible); + bool was_visible = DisplayServer::get_singleton()->is_console_visible(); + DisplayServer::get_singleton()->console_set_visible(!was_visible); EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", was_visible); } break; case EDITOR_SCREENSHOT: { @@ -2601,7 +2603,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case SETTINGS_PICK_MAIN_SCENE: { - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); List<String> extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions); file->clear_filters(); @@ -2634,7 +2636,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { OS::get_singleton()->shell_open("https://godotengine.org/community"); } break; case HELP_ABOUT: { - about->popup_centered_minsize(Size2(780, 500) * EDSCALE); + about->popup_centered(Size2(780, 500) * EDSCALE); } break; case SET_VIDEO_DRIVER_SAVE_AND_RESTART: { @@ -2663,10 +2665,10 @@ void EditorNode::_screenshot(bool p_use_utc) { void EditorNode::_save_screenshot(NodePath p_path) { - Viewport *viewport = EditorInterface::get_singleton()->get_editor_viewport()->get_viewport(); - viewport->set_clear_mode(Viewport::CLEAR_MODE_ONLY_NEXT_FRAME); + SubViewport *viewport = Object::cast_to<SubViewport>(EditorInterface::get_singleton()->get_editor_viewport()->get_viewport()); + viewport->set_clear_mode(SubViewport::CLEAR_MODE_ONLY_NEXT_FRAME); Ref<Image> img = viewport->get_texture()->get_data(); - viewport->set_clear_mode(Viewport::CLEAR_MODE_ALWAYS); + viewport->set_clear_mode(SubViewport::CLEAR_MODE_ALWAYS); Error error = img->save_png(p_path); ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); } @@ -2884,8 +2886,8 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed if (icon.is_valid()) { tb->set_icon(icon); - } else if (singleton->gui_base->has_icon(p_editor->get_name(), "EditorIcons")) { - tb->set_icon(singleton->gui_base->get_icon(p_editor->get_name(), "EditorIcons")); + } else if (singleton->gui_base->has_theme_icon(p_editor->get_name(), "EditorIcons")) { + tb->set_icon(singleton->gui_base->get_theme_icon(p_editor->get_name(), "EditorIcons")); } tb->set_name(p_editor->get_name()); @@ -3269,7 +3271,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (!p_force_open_imported && FileAccess::exists(p_scene + ".import")) { open_imported->set_text(vformat(TTR("Scene '%s' was automatically imported, so it can't be modified.\nTo make changes to it, a new inherited scene can be created."), p_scene.get_file())); - open_imported->popup_centered_minsize(); + open_imported->popup_centered(); new_inherited_button->grab_focus(); open_import_request = p_scene; return OK; @@ -3553,7 +3555,7 @@ void EditorNode::add_io_error(const String &p_error) { void EditorNode::_load_error_notify(void *p_ud, const String &p_text) { EditorNode *en = (EditorNode *)p_ud; - en->load_errors->add_image(en->gui_base->get_icon("Error", "EditorIcons")); + en->load_errors->add_image(en->gui_base->get_theme_icon("Error", "EditorIcons")); en->load_errors->add_text(p_text + "\n"); en->load_error_dialog->popup_centered_ratio(0.5); } @@ -3746,11 +3748,11 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String if (p_object->has_meta("_editor_icon")) return p_object->get_meta("_editor_icon"); - if (gui_base->has_icon(p_object->get_class(), "EditorIcons")) - return gui_base->get_icon(p_object->get_class(), "EditorIcons"); + if (gui_base->has_theme_icon(p_object->get_class(), "EditorIcons")) + return gui_base->get_theme_icon(p_object->get_class(), "EditorIcons"); if (p_fallback.length()) - return gui_base->get_icon(p_fallback, "EditorIcons"); + return gui_base->get_theme_icon(p_fallback, "EditorIcons"); return NULL; } @@ -3758,8 +3760,8 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const { ERR_FAIL_COND_V_MSG(p_class.empty(), NULL, "Class name cannot be empty."); - if (gui_base->has_icon(p_class, "EditorIcons")) { - return gui_base->get_icon(p_class, "EditorIcons"); + if (gui_base->has_theme_icon(p_class, "EditorIcons")) { + return gui_base->get_theme_icon(p_class, "EditorIcons"); } if (ScriptServer::is_global_class(p_class)) { @@ -3782,7 +3784,7 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } if (icon.is_null()) { - icon = gui_base->get_icon(ScriptServer::get_global_class_base(p_class), "EditorIcons"); + icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(p_class), "EditorIcons"); } return icon; @@ -3800,8 +3802,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } } - if (p_fallback.length() && gui_base->has_icon(p_fallback, "EditorIcons")) - return gui_base->get_icon(p_fallback, "EditorIcons"); + if (p_fallback.length() && gui_base->has_theme_icon(p_fallback, "EditorIcons")) + return gui_base->get_theme_icon(p_fallback, "EditorIcons"); return NULL; } @@ -3922,7 +3924,7 @@ void EditorNode::show_accept(const String &p_text, const String &p_title) { current_option = -1; accept->get_ok()->set_text(p_title); accept->set_text(p_text); - accept->popup_centered_minsize(); + accept->popup_centered(); } void EditorNode::show_warning(const String &p_text, const String &p_title) { @@ -3930,7 +3932,7 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) { if (warning->is_inside_tree()) { warning->set_text(p_text); warning->set_title(p_title); - warning->popup_centered_minsize(); + warning->popup_centered(); } else { WARN_PRINT(p_title + " " + p_text); } @@ -3938,7 +3940,78 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) { void EditorNode::_copy_warning(const String &p_str) { - OS::get_singleton()->set_clipboard(warning->get_text()); + DisplayServer::get_singleton()->clipboard_set(warning->get_text()); +} + +void EditorNode::_dock_floating_close_request(Control *p_control) { + Window *window = (Window *)p_control->get_parent(); + int window_slot = window->get_meta("dock_slot"); + + window->remove_child(p_control); + dock_slot[window_slot]->add_child(p_control); + + window->queue_delete(); + + _update_dock_containers(); + + floating_docks.erase(p_control); +} + +void EditorNode::_dock_make_float() { + Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control(); + ERR_FAIL_COND(!dock); + + Size2 dock_size = dock->get_size(); //remember size + Point2 dock_screen_pos = dock->get_global_position() + get_tree()->get_root()->get_position(); + + print_line("dock pos: " + dock->get_global_position() + " window pos: " + get_tree()->get_root()->get_position()); + dock_slot[dock_popup_selected]->remove_child(dock); + + Window *window = memnew(Window); + window->set_title(dock->get_name()); + Panel *p = memnew(Panel); + p->set_mode(Panel::MODE_FOREGROUND); + p->set_anchors_and_margins_preset(Control::PRESET_WIDE); + window->add_child(p); + dock->set_anchors_and_margins_preset(Control::PRESET_WIDE); + window->add_child(dock); + window->set_wrap_controls(true); + window->set_size(dock_size); + window->set_position(dock_screen_pos); + window->set_transient(true); + window->connect("close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request), varray(dock)); + window->set_meta("dock_slot", dock_popup_selected); + gui_base->add_child(window); + + dock_select_popup->hide(); + + _update_dock_containers(); + + floating_docks.push_back(dock); +} + +void EditorNode::_update_dock_containers() { + + for (int i = 0; i < DOCK_SLOT_MAX; i++) { + if (dock_slot[i]->get_tab_count() == 0 && dock_slot[i]->is_visible()) { + dock_slot[i]->hide(); + } + if (dock_slot[i]->get_tab_count() > 0 && !dock_slot[i]->is_visible()) { + dock_slot[i]->show(); + } + } + for (int i = 0; i < vsplits.size(); i++) { + bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count(); + if (in_use) + vsplits[i]->show(); + else + vsplits[i]->hide(); + } + + if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) + right_hsplit->show(); + else + right_hsplit->hide(); } void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { @@ -3986,18 +4059,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { dock_slot[nrect]->show(); dock_select->update(); - for (int i = 0; i < vsplits.size(); i++) { - bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count(); - if (in_use) - vsplits[i]->show(); - else - vsplits[i]->hide(); - } - - if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) - right_hsplit->show(); - else - right_hsplit->hide(); + _update_dock_containers(); _edit_current(); _save_docks(); @@ -4051,7 +4113,7 @@ void EditorNode::_dock_select_draw() { Color used = Color(0.6, 0.6, 0.6, 0.8); Color used_selected = Color(0.8, 0.8, 0.8, 0.8); - Color tab_selected = theme_base->get_color("mono_color", "Editor"); + Color tab_selected = theme_base->get_theme_color("mono_color", "Editor"); Color unused = used; unused.a = 0.4; Color unusable = unused; @@ -4454,7 +4516,7 @@ bool EditorNode::ensure_main_scene(bool p_from_native) { current_option = -1; pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category.")); - pick_main_scene->popup_centered_minsize(); + pick_main_scene->popup_centered(); return false; } @@ -4462,7 +4524,7 @@ bool EditorNode::ensure_main_scene(bool p_from_native) { current_option = -1; pick_main_scene->set_text(vformat(TTR("Selected scene '%s' does not exist, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene)); - pick_main_scene->popup_centered_minsize(); + pick_main_scene->popup_centered(); return false; } @@ -4470,7 +4532,7 @@ bool EditorNode::ensure_main_scene(bool p_from_native) { current_option = -1; pick_main_scene->set_text(vformat(TTR("Selected scene '%s' is not a scene file, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene)); - pick_main_scene->popup_centered_minsize(); + pick_main_scene->popup_centered(); return false; } @@ -4590,7 +4652,7 @@ void EditorNode::_scene_tab_closed(int p_tab, int option) { if (unsaved) { save_confirmation->get_ok()->set_text(TTR("Save & Close")); save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene->get_filename() != "" ? scene->get_filename() : "unsaved scene")); - save_confirmation->popup_centered_minsize(); + save_confirmation->popup_centered(); } else { _discard_changes(); } @@ -4814,9 +4876,9 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { bottom_panel_items[i].control->set_visible(i == p_idx); } if (EditorDebuggerNode::get_singleton() == bottom_panel_items[p_idx].control) { // this is the debug panel which uses tabs, so the top section should be smaller - bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("BottomPanelDebuggerOverride", "EditorStyles")); } else { - bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer")); } center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); @@ -4826,7 +4888,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { bottom_panel_raise->show(); } else { - bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer")); bottom_panel_items[p_idx].button->set_pressed(false); bottom_panel_items[p_idx].control->set_visible(false); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); @@ -4919,7 +4981,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { { //todo make proper previews - Ref<ImageTexture> pic = gui_base->get_icon("FileBigThumb", "EditorIcons"); + Ref<ImageTexture> pic = gui_base->get_theme_icon("FileBigThumb", "EditorIcons"); Ref<Image> img = pic->get_data(); img = img->duplicate(); img->resize(48, 48); //meh @@ -4971,10 +5033,10 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control * if (p_paths[i].ends_with("/")) { label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file()); - icon->set_texture(gui_base->get_icon("Folder", "EditorIcons")); + icon->set_texture(gui_base->get_theme_icon("Folder", "EditorIcons")); } else { label->set_text(p_paths[i].get_file()); - icon->set_texture(gui_base->get_icon("File", "EditorIcons")); + icon->set_texture(gui_base->get_theme_icon("File", "EditorIcons")); } icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); icon->set_size(Size2(16, 16)); @@ -5042,21 +5104,19 @@ void EditorNode::remove_tool_menu_item(const String &p_name) { } } -void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta) { +void EditorNode::_global_menu_scene(const Variant &p_tag) { + int idx = (int)p_tag; + scene_tabs->set_current_tab(idx); +} - int id = (int)p_id; - if (id == GLOBAL_NEW_WINDOW) { - if (OS::get_singleton()->get_main_loop()) { - List<String> args; - args.push_back("-e"); - String exec = OS::get_singleton()->get_executable_path(); +void EditorNode::_global_menu_new_window(const Variant &p_tag) { + if (OS::get_singleton()->get_main_loop()) { + List<String> args; + args.push_back("-p"); + String exec = OS::get_singleton()->get_executable_path(); - OS::ProcessID pid = 0; - OS::get_singleton()->execute(exec, args, false, &pid); - } - } else if (id == GLOBAL_SCENE) { - int idx = (int)p_meta; - scene_tabs->set_current_tab(idx); + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); } } @@ -5277,9 +5337,9 @@ void EditorNode::_update_video_driver_color() { // TODO: Probably should de-hardcode this and add to editor settings. if (video_driver->get_text() == "GLES2") { - video_driver->add_color_override("font_color", Color::hex(0x5586a4ff)); + video_driver->add_theme_color_override("font_color", Color::hex(0x5586a4ff)); } else if (video_driver->get_text() == "Vulkan") { - video_driver->add_color_override("font_color", theme_base->get_color("vulkan_color", "Editor")); + video_driver->add_theme_color_override("font_color", theme_base->get_theme_color("vulkan_color", "Editor")); } } @@ -5287,14 +5347,14 @@ void EditorNode::_video_driver_selected(int p_which) { String driver = video_driver->get_item_metadata(p_which); - String current = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); + String current = ""; //OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); if (driver == current) { return; } video_driver_request = driver; - video_restart_dialog->popup_centered_minsize(); + video_restart_dialog->popup_centered(); video_driver->select(video_driver_current); _update_video_driver_color(); } @@ -5376,6 +5436,7 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes); ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history); + ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource); ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); @@ -5466,7 +5527,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p EditorNode::EditorNode() { - Input::get_singleton()->set_use_accumulated_input(true); + InputFilter::get_singleton()->set_use_accumulated_input(true); Resource::_get_local_scene_func = _resource_get_edited_scene; VisualServer::get_singleton()->set_debug_generate_wireframes(true); @@ -5482,15 +5543,22 @@ EditorNode::EditorNode() { ResourceLoader::clear_translation_remaps(); //no remaps using during editor ResourceLoader::clear_path_remaps(); - InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); + InputFilter *id = InputFilter::get_singleton(); if (id) { - if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) { + bool found_touchscreen = false; + for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) { + if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) { + found_touchscreen = true; + } + } + + if (!found_touchscreen && InputFilter::get_singleton()) { //only if no touchscreen ui hint, set emulation id->set_emulate_touch_from_mouse(false); //just disable just in case } - id->set_custom_mouse_cursor(RES()); + DisplayServer::get_singleton()->cursor_set_custom_image(RES()); } singleton = this; @@ -5519,8 +5587,12 @@ EditorNode::EditorNode() { switch (display_scale) { case 0: { // Try applying a suitable display scale automatically - const int screen = OS::get_singleton()->get_current_screen(); - editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); + const int screen = DisplayServer::get_singleton()->window_get_current_screen(); +#ifdef OSX_ENABLED + editor_set_scale(DisplayServer::get_singleton()->screen_get_scale(screen)); +#else + editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0); +#endif } break; case 1: { @@ -5554,7 +5626,7 @@ EditorNode::EditorNode() { } // Define a minimum window size to prevent UI elements from overlapping or being cut off - OS::get_singleton()->set_min_window_size(Size2(1024, 600) * EDSCALE); + DisplayServer::get_singleton()->window_set_min_size(Size2(1024, 600) * EDSCALE); ResourceLoader::set_abort_on_missing_resources(false); FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); @@ -5713,7 +5785,7 @@ EditorNode::EditorNode() { theme_base->set_theme(theme); gui_base->set_theme(theme); - gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); + gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox("Background", "EditorStyles")); resource_preview = memnew(EditorResourcePreview); add_child(resource_preview); @@ -5728,7 +5800,7 @@ EditorNode::EditorNode() { main_vbox = memnew(VBoxContainer); gui_base->add_child(main_vbox); main_vbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8); - main_vbox->add_constant_override("separation", 8 * EDSCALE); + main_vbox->add_theme_constant_override("separation", 8 * EDSCALE); menu_hb = memnew(HBoxContainer); main_vbox->add_child(menu_hb); @@ -5832,6 +5904,14 @@ EditorNode::EditorNode() { dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL); dock_vb->add_child(dock_select); + dock_float = memnew(Button); + dock_float->set_text("Make Floating"); + dock_float->set_focus_mode(Control::FOCUS_NONE); + dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER); + dock_float->connect("pressed", callable_mp(this, &EditorNode::_dock_make_float)); + + dock_vb->add_child(dock_float); + dock_select_popup->set_as_minsize(); dock_select_rect_over = -1; dock_popup_selected = -1; @@ -5861,7 +5941,7 @@ EditorNode::EditorNode() { VBoxContainer *srt = memnew(VBoxContainer); srt->set_v_size_flags(Control::SIZE_EXPAND_FILL); top_split->add_child(srt); - srt->add_constant_override("separation", 0); + srt->add_theme_constant_override("separation", 0); tab_preview_panel = memnew(Panel); tab_preview_panel->set_size(Size2(100, 100) * EDSCALE); @@ -5876,8 +5956,8 @@ EditorNode::EditorNode() { tab_preview_panel->add_child(tab_preview); scene_tabs = memnew(Tabs); - scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles")); - scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles")); + scene_tabs->add_theme_style_override("tab_fg", gui_base->get_theme_stylebox("SceneTabFG", "EditorStyles")); + scene_tabs->add_theme_style_override("tab_bg", gui_base->get_theme_stylebox("SceneTabBG", "EditorStyles")); scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); scene_tabs->set_tab_align(Tabs::ALIGN_LEFT); @@ -5899,7 +5979,6 @@ EditorNode::EditorNode() { scene_tabs_context_menu = memnew(PopupMenu); tabbar_container->add_child(scene_tabs_context_menu); scene_tabs_context_menu->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); - scene_tabs_context_menu->set_hide_on_window_lose_focus(true); srt->add_child(tabbar_container); tabbar_container->add_child(scene_tabs); @@ -5911,25 +5990,25 @@ EditorNode::EditorNode() { #endif distraction_free->set_tooltip(TTR("Toggle distraction-free mode.")); distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode)); - distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons")); + distraction_free->set_icon(gui_base->get_theme_icon("DistractionFree", "EditorIcons")); distraction_free->set_toggle_mode(true); scene_tab_add = memnew(ToolButton); tabbar_container->add_child(scene_tab_add); tabbar_container->add_child(distraction_free); scene_tab_add->set_tooltip(TTR("Add a new scene.")); - scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons")); - scene_tab_add->add_color_override("icon_color_normal", Color(0.6f, 0.6f, 0.6f, 0.8f)); + scene_tab_add->set_icon(gui_base->get_theme_icon("Add", "EditorIcons")); + scene_tab_add->add_theme_color_override("icon_color_normal", Color(0.6f, 0.6f, 0.6f, 0.8f)); scene_tab_add->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_NEW_SCENE)); scene_root_parent = memnew(PanelContainer); scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE); - scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles")); + scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox("Content", "EditorStyles")); scene_root_parent->set_draw_behind_parent(true); srt->add_child(scene_root_parent); scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL); - scene_root = memnew(Viewport); + scene_root = memnew(SubViewport); //scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true); @@ -5938,7 +6017,7 @@ EditorNode::EditorNode() { viewport = memnew(VBoxContainer); viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL); - viewport->add_constant_override("separation", 0); + viewport->add_theme_constant_override("separation", 0); scene_root_parent->add_child(viewport); HBoxContainer *left_menu_hb = memnew(HBoxContainer); @@ -5948,11 +6027,11 @@ EditorNode::EditorNode() { file_menu->set_flat(false); file_menu->set_switch_on_hover(true); file_menu->set_text(TTR("Scene")); - file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); + file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(file_menu); prev_scene = memnew(ToolButton); - prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons")); + prev_scene->set_icon(gui_base->get_theme_icon("PrevScene", "EditorIcons")); prev_scene->set_tooltip(TTR("Go to previously opened scene.")); prev_scene->set_disabled(true); prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(FILE_OPEN_PREV)); @@ -6004,7 +6083,7 @@ EditorNode::EditorNode() { file_menu->set_tooltip(TTR("Operations with scene files.")); p = file_menu->get_popup(); - p->set_hide_on_window_lose_focus(true); + p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE); p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE); p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE); @@ -6052,11 +6131,11 @@ EditorNode::EditorNode() { project_menu->set_switch_on_hover(true); project_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools.")); project_menu->set_text(TTR("Project")); - project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); + project_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(project_menu); p = project_menu->get_popup(); - p->set_hide_on_window_lose_focus(true); + p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings...")), RUN_SETTINGS); p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); @@ -6102,19 +6181,20 @@ EditorNode::EditorNode() { debug_menu->set_flat(false); debug_menu->set_switch_on_hover(true); debug_menu->set_text(TTR("Debug")); - debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); + debug_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(debug_menu); + menu_hb->add_spacer(); settings_menu = memnew(MenuButton); settings_menu->set_flat(false); settings_menu->set_switch_on_hover(true); settings_menu->set_text(TTR("Editor")); - settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); + settings_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(settings_menu); p = settings_menu->get_popup(); - p->set_hide_on_window_lose_focus(true); + p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES); p->add_separator(); @@ -6158,20 +6238,19 @@ EditorNode::EditorNode() { help_menu->set_flat(false); help_menu->set_switch_on_hover(true); help_menu->set_text(TTR("Help")); - help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles")); + help_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(help_menu); p = help_menu->get_popup(); - p->set_hide_on_window_lose_focus(true); p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); - p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_MASK_SHIFT | KEY_F1), HELP_SEARCH); + p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_MASK_SHIFT | KEY_F1), HELP_SEARCH); p->add_separator(); - p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS); - p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA); - p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/issue_tracker", TTR("Issue Tracker")), HELP_ISSUES); - p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY); + p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS); + p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA); + p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/issue_tracker", TTR("Issue Tracker")), HELP_ISSUES); + p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY); p->add_separator(); - p->add_icon_shortcut(gui_base->get_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About")), HELP_ABOUT); + p->add_icon_shortcut(gui_base->get_theme_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About")), HELP_ABOUT); HBoxContainer *play_hb = memnew(HBoxContainer); menu_hb->add_child(play_hb); @@ -6179,7 +6258,7 @@ EditorNode::EditorNode() { play_button = memnew(ToolButton); play_hb->add_child(play_button); play_button->set_toggle_mode(true); - play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons")); + play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons")); play_button->set_focus_mode(Control::FOCUS_NONE); play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY)); play_button->set_tooltip(TTR("Play the project.")); @@ -6191,7 +6270,7 @@ EditorNode::EditorNode() { pause_button = memnew(ToolButton); pause_button->set_toggle_mode(true); - pause_button->set_icon(gui_base->get_icon("Pause", "EditorIcons")); + pause_button->set_icon(gui_base->get_theme_icon("Pause", "EditorIcons")); pause_button->set_focus_mode(Control::FOCUS_NONE); pause_button->set_tooltip(TTR("Pause the scene execution for debugging.")); pause_button->set_disabled(true); @@ -6205,7 +6284,7 @@ EditorNode::EditorNode() { stop_button = memnew(ToolButton); play_hb->add_child(stop_button); stop_button->set_focus_mode(Control::FOCUS_NONE); - stop_button->set_icon(gui_base->get_icon("Stop", "EditorIcons")); + stop_button->set_icon(gui_base->get_theme_icon("Stop", "EditorIcons")); stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_STOP)); stop_button->set_tooltip(TTR("Stop the scene.")); stop_button->set_disabled(true); @@ -6223,7 +6302,7 @@ EditorNode::EditorNode() { play_hb->add_child(play_scene_button); play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); - play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons")); + play_scene_button->set_icon(gui_base->get_theme_icon("PlayScene", "EditorIcons")); play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_SCENE)); play_scene_button->set_tooltip(TTR("Play the edited scene.")); #ifdef OSX_ENABLED @@ -6236,7 +6315,7 @@ EditorNode::EditorNode() { play_hb->add_child(play_custom_scene_button); play_custom_scene_button->set_toggle_mode(true); play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE); - play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons")); + play_custom_scene_button->set_icon(gui_base->get_theme_icon("PlayCustom", "EditorIcons")); play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_CUSTOM_SCENE)); play_custom_scene_button->set_tooltip(TTR("Play custom scene")); #ifdef OSX_ENABLED @@ -6253,11 +6332,15 @@ EditorNode::EditorNode() { video_driver->set_flat(true); video_driver->set_focus_mode(Control::FOCUS_NONE); video_driver->connect("item_selected", callable_mp(this, &EditorNode::_video_driver_selected)); - video_driver->add_font_override("font", gui_base->get_font("bold", "EditorFonts")); + video_driver->add_theme_font_override("font", gui_base->get_theme_font("bold", "EditorFonts")); // TODO re-enable when GLES2 is ported video_driver->set_disabled(true); right_menu_hb->add_child(video_driver); +#ifndef _MSC_VER +#warning neeeds to be reimplemented +#endif +#if 0 String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string; String current_video_driver = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); video_driver_current = 0; @@ -6273,7 +6356,7 @@ EditorNode::EditorNode() { } _update_video_driver_color(); - +#endif video_restart_dialog = memnew(ConfirmationDialog); video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor.")); video_restart_dialog->get_ok()->set_text(TTR("Save & Restart")); @@ -6291,7 +6374,7 @@ EditorNode::EditorNode() { update_spinner = memnew(MenuButton); update_spinner->set_tooltip(TTR("Spins when the editor window redraws.")); right_menu_hb->add_child(update_spinner); - update_spinner->set_icon(gui_base->get_icon("Progress1", "EditorIcons")); + update_spinner->set_icon(gui_base->get_theme_icon("Progress1", "EditorIcons")); update_spinner->get_popup()->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); p = update_spinner->get_popup(); p->add_radio_check_item(TTR("Update Continuously"), SETTINGS_UPDATE_CONTINUOUSLY); @@ -6367,7 +6450,7 @@ EditorNode::EditorNode() { // Bottom panels bottom_panel = memnew(PanelContainer); - bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("panel", "TabContainer")); center_split->add_child(bottom_panel); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); @@ -6389,7 +6472,7 @@ EditorNode::EditorNode() { bottom_panel_hb->add_child(version_label); bottom_panel_raise = memnew(ToolButton); - bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons")); + bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons")); bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12)); @@ -6414,7 +6497,7 @@ EditorNode::EditorNode() { confirmation->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current)); save_confirmation = memnew(ConfirmationDialog); - save_confirmation->add_button(TTR("Don't Save"), OS::get_singleton()->get_swap_ok_cancel(), "discard"); + save_confirmation->add_button(TTR("Don't Save"), DisplayServer::get_singleton()->get_swap_ok_cancel(), "discard"); gui_base->add_child(save_confirmation); save_confirmation->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current)); save_confirmation->connect("custom_action", callable_mp(this, &EditorNode::_discard_changes)); @@ -6441,7 +6524,7 @@ EditorNode::EditorNode() { file_templates->set_title(TTR("Import Templates From ZIP File")); gui_base->add_child(file_templates); - file_templates->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_templates->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file_templates->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_templates->clear_filters(); file_templates->add_filter("*.tpz ; " + TTR("Template Package")); @@ -6452,7 +6535,7 @@ EditorNode::EditorNode() { file_export_lib = memnew(EditorFileDialog); file_export_lib->set_title(TTR("Export Library")); - file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_export_lib->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_export_lib->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action)); file_export_lib_merge = memnew(CheckBox); file_export_lib_merge->set_text(TTR("Merge With Existing")); @@ -6463,7 +6546,7 @@ EditorNode::EditorNode() { file_script = memnew(EditorFileDialog); file_script->set_title(TTR("Open & Run a Script")); file_script->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file_script->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_script->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); List<String> sexts; ResourceLoader::get_recognized_extensions_for_type("Script", &sexts); for (List<String>::Element *E = sexts.front(); E; E = E->next()) { @@ -6473,7 +6556,7 @@ EditorNode::EditorNode() { file_script->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action)); file_menu->get_popup()->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); - file_menu->connect("about_to_show", callable_mp(this, &EditorNode::_update_file_menu_opened)); + file_menu->connect("about_to_popup", callable_mp(this, &EditorNode::_update_file_menu_opened)); file_menu->get_popup()->connect("popup_hide", callable_mp(this, &EditorNode::_update_file_menu_closed)); settings_menu->get_popup()->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option)); @@ -6625,7 +6708,7 @@ EditorNode::EditorNode() { open_imported = memnew(ConfirmationDialog); open_imported->get_ok()->set_text(TTR("Open Anyway")); - new_inherited_button = open_imported->add_button(TTR("New Inherited"), !OS::get_singleton()->get_swap_ok_cancel(), "inherit"); + new_inherited_button = open_imported->add_button(TTR("New Inherited"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "inherit"); open_imported->connect("confirmed", callable_mp(this, &EditorNode::_open_imported)); open_imported->connect("custom_action", callable_mp(this, &EditorNode::_inherit_imported)); gui_base->add_child(open_imported); diff --git a/editor/editor_node.h b/editor/editor_node.h index bd285db224..21025f2a50 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -84,6 +84,8 @@ class Tabs; class TextureProgress; class ToolButton; class VSplitContainer; +class Window; +class SubViewport; class EditorNode : public Node { @@ -206,7 +208,7 @@ private: TOOL_MENU_BASE = 1000 }; - Viewport *scene_root; //root of the scene being edited + SubViewport *scene_root; //root of the scene being edited PanelContainer *scene_root_parent; Control *theme_base; @@ -348,11 +350,14 @@ private: Button *new_inherited_button; String open_import_request; + Vector<Control *> floating_docks; + TabContainer *dock_slot[DOCK_SLOT_MAX]; Rect2 dock_select_rect[DOCK_SLOT_MAX]; int dock_select_rect_over; PopupPanel *dock_select_popup; Control *dock_select; + Button *dock_float; ToolButton *dock_tab_move_left; ToolButton *dock_tab_move_right; int dock_popup_selected; @@ -493,7 +498,8 @@ private: void _add_to_recent_scenes(const String &p_scene); void _update_recent_scenes(); void _open_recent_scene(int p_idx); - void _global_menu_action(const Variant &p_id, const Variant &p_meta); + void _global_menu_scene(const Variant &p_tag); + void _global_menu_new_window(const Variant &p_tag); void _dropped_files(const Vector<String> &p_files, int p_screen); void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path); String _recent_scene; @@ -560,6 +566,8 @@ private: bool _find_scene_in_use(Node *p_node, const String &p_path) const; + void _update_dock_containers(); + void _dock_select_input(const Ref<InputEvent> &p_input); void _dock_move_left(); void _dock_move_right(); @@ -567,6 +575,8 @@ private: void _dock_pre_popup(int p_which); void _dock_split_dragged(int ofs); void _dock_popup_exit(); + void _dock_floating_close_request(Control *p_control); + void _dock_make_float(); void _scene_tab_changed(int p_tab); void _scene_tab_closed(int p_tab, int option = SCENE_TAB_CLOSE); void _scene_tab_hover(int p_tab); @@ -724,7 +734,7 @@ public: Node *get_edited_scene() { return editor_data.get_edited_scene_root(); } - Viewport *get_scene_root() { return scene_root; } //root of the scene being edited + SubViewport *get_scene_root() { return scene_root; } //root of the scene being edited void fix_dependencies(const String &p_for_file); void clear_scene() { _cleanup_scene(); } diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 305dc03568..804ad62bbb 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -149,6 +149,6 @@ EditorPath::EditorPath(EditorHistory *p_history) { history = p_history; set_clip_text(true); set_text_align(ALIGN_LEFT); - get_popup()->connect("about_to_show", callable_mp(this, &EditorPath::_about_to_show)); + get_popup()->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show)); get_popup()->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed)); } diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 33877f86c2..62a76786ae 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -40,7 +40,7 @@ void EditorPluginSettings::_notification(int p_what) { - if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_FOCUS_IN) { update_plugins(); } else if (p_what == Node::NOTIFICATION_READY) { plugin_config_dialog->connect_compat("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready"); @@ -142,7 +142,7 @@ void EditorPluginSettings::update_plugins() { bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(d2); item->set_checked(3, is_active); item->set_editable(3, true); - item->add_button(4, get_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin")); + item->add_button(4, get_theme_icon("Edit", "EditorIcons"), BUTTON_PLUGIN_EDIT, false, TTR("Edit Plugin")); } } } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 9a474ed4af..af83e808fc 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -35,7 +35,7 @@ #include "editor_node.h" #include "editor_properties_array_dict.h" #include "editor_scale.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" ///////////////////// NULL ///////////////////////// @@ -140,9 +140,9 @@ void EditorPropertyMultilineText::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { - Ref<Texture2D> df = get_icon("DistractionFree", "EditorIcons"); + Ref<Texture2D> df = get_theme_icon("DistractionFree", "EditorIcons"); open_big_text->set_icon(df); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); text->set_custom_minimum_size(Vector2(0, font->get_height() * 6)); } break; @@ -240,10 +240,10 @@ void EditorPropertyPath::_path_pressed() { } if (folder) { - dialog->set_mode(EditorFileDialog::MODE_OPEN_DIR); + dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); dialog->set_current_dir(full_path); } else { - dialog->set_mode(save_mode ? EditorFileDialog::MODE_SAVE_FILE : EditorFileDialog::MODE_OPEN_FILE); + dialog->set_file_mode(save_mode ? EditorFileDialog::FILE_MODE_SAVE_FILE : EditorFileDialog::FILE_MODE_OPEN_FILE); for (int i = 0; i < extensions.size(); i++) { String e = extensions[i].strip_edges(); if (e != String()) { @@ -278,7 +278,7 @@ void EditorPropertyPath::set_save_mode() { void EditorPropertyPath::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - path_edit->set_icon(get_icon("Folder", "EditorIcons")); + path_edit->set_icon(get_theme_icon("Folder", "EditorIcons")); } } @@ -604,7 +604,7 @@ public: Vector<String> tooltips; virtual Size2 get_minimum_size() const { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); return Vector2(0, font->get_height() * 2); } @@ -646,7 +646,7 @@ public: int h = bsize * 2 + 1; int vofs = (rect.size.height - h) / 2; - Color color = get_color("highlight_color", "Editor"); + Color color = get_theme_color("highlight_color", "Editor"); for (int i = 0; i < 2; i++) { Point2 ofs(4, vofs); @@ -749,10 +749,10 @@ void EditorPropertyLayers::_button_pressed() { layers->set_item_checked(idx, grid->value & (1 << i)); } - Rect2 gp = button->get_global_rect(); + Rect2 gp = button->get_screen_rect(); layers->set_as_minsize(); - Vector2 popup_pos = gp.position - Vector2(layers->get_combined_minimum_size().x, 0); - layers->set_global_position(popup_pos); + Vector2 popup_pos = gp.position - Vector2(layers->get_contents_minimum_size().x, 0); + layers->set_position(popup_pos); layers->popup(); } @@ -920,7 +920,7 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) { } if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { - preset->set_global_position(easing_draw->get_global_transform().xform(mb->get_position())); + preset->set_position(easing_draw->get_screen_transform().xform(mb->get_position())); preset->popup(); // Ensure the easing doesn't appear as being dragged @@ -976,13 +976,13 @@ void EditorPropertyEasing::_draw_easing() { float prev = 1.0; const float exp = get_edited_object()->get(get_edited_property()); - const Ref<Font> f = get_font("font", "Label"); - const Color font_color = get_color("font_color", "Label"); + const Ref<Font> f = get_theme_font("font", "Label"); + const Color font_color = get_theme_color("font_color", "Label"); Color line_color; if (dragging) { - line_color = get_color("accent_color", "Editor"); + line_color = get_theme_color("accent_color", "Editor"); } else { - line_color = get_color("font_color", "Label") * Color(1, 1, 1, 0.9); + line_color = get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.9); } Vector<Point2> lines; @@ -1058,15 +1058,15 @@ void EditorPropertyEasing::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { preset->clear(); - preset->add_icon_item(get_icon("CurveConstant", "EditorIcons"), "Zero", EASING_ZERO); - preset->add_icon_item(get_icon("CurveLinear", "EditorIcons"), "Linear", EASING_LINEAR); - preset->add_icon_item(get_icon("CurveIn", "EditorIcons"), "In", EASING_IN); - preset->add_icon_item(get_icon("CurveOut", "EditorIcons"), "Out", EASING_OUT); + preset->add_icon_item(get_theme_icon("CurveConstant", "EditorIcons"), "Zero", EASING_ZERO); + preset->add_icon_item(get_theme_icon("CurveLinear", "EditorIcons"), "Linear", EASING_LINEAR); + preset->add_icon_item(get_theme_icon("CurveIn", "EditorIcons"), "In", EASING_IN); + preset->add_icon_item(get_theme_icon("CurveOut", "EditorIcons"), "Out", EASING_OUT); if (full) { - preset->add_icon_item(get_icon("CurveInOut", "EditorIcons"), "In-Out", EASING_IN_OUT); - preset->add_icon_item(get_icon("CurveOutIn", "EditorIcons"), "Out-In", EASING_OUT_IN); + preset->add_icon_item(get_theme_icon("CurveInOut", "EditorIcons"), "In-Out", EASING_IN_OUT); + preset->add_icon_item(get_theme_icon("CurveOutIn", "EditorIcons"), "Out-In", EASING_OUT_IN); } - easing_draw->set_custom_minimum_size(Size2(0, get_font("font", "Label")->get_height() * 2)); + easing_draw->set_custom_minimum_size(Size2(0, get_theme_font("font", "Label")->get_height() * 2)); } break; } } @@ -1126,7 +1126,7 @@ void EditorPropertyVector2::update_property() { void EditorPropertyVector2::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 2; i++) { Color c = base; @@ -1208,7 +1208,7 @@ void EditorPropertyRect2::update_property() { } void EditorPropertyRect2::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 4; i++) { Color c = base; @@ -1288,7 +1288,7 @@ void EditorPropertyVector3::update_property() { } void EditorPropertyVector3::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 3; i++) { Color c = base; @@ -1368,7 +1368,7 @@ void EditorPropertyPlane::update_property() { } void EditorPropertyPlane::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 3; i++) { Color c = base; @@ -1450,7 +1450,7 @@ void EditorPropertyQuat::update_property() { } void EditorPropertyQuat::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 3; i++) { Color c = base; @@ -1537,7 +1537,7 @@ void EditorPropertyAABB::update_property() { } void EditorPropertyAABB::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 6; i++) { Color c = base; @@ -1611,7 +1611,7 @@ void EditorPropertyTransform2D::update_property() { } void EditorPropertyTransform2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 6; i++) { Color c = base; @@ -1690,7 +1690,7 @@ void EditorPropertyBasis::update_property() { } void EditorPropertyBasis::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 9; i++) { Color c = base; @@ -1775,7 +1775,7 @@ void EditorPropertyTransform::update_property() { } void EditorPropertyTransform::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Color base = get_color("accent_color", "Editor"); + Color base = get_theme_color("accent_color", "Editor"); for (int i = 0; i < 12; i++) { Color c = base; @@ -1983,7 +1983,7 @@ void EditorPropertyNodePath::setup(const NodePath &p_base_hint, Vector<StringNam void EditorPropertyNodePath::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Ref<Texture2D> t = get_icon("Clear", "EditorIcons"); + Ref<Texture2D> t = get_theme_icon("Clear", "EditorIcons"); clear->set_icon(t); } } @@ -2074,7 +2074,7 @@ void EditorPropertyResource::_menu_option(int p_which) { file->connect("file_selected", callable_mp(this, &EditorPropertyResource::_file_selected)); add_child(file); } - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); String type = base_type; List<String> extensions; @@ -2294,7 +2294,7 @@ void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<T } if (p_preview.is_valid()) { - preview->set_margin(MARGIN_LEFT, assign->get_icon()->get_width() + assign->get_stylebox("normal")->get_default_margin(MARGIN_LEFT) + get_constant("hseparation", "Button")); + preview->set_margin(MARGIN_LEFT, assign->get_icon()->get_width() + assign->get_theme_stylebox("normal")->get_default_margin(MARGIN_LEFT) + get_theme_constant("hseparation", "Button")); if (type == "GradientTexture") { preview->set_stretch_mode(TextureRect::STRETCH_SCALE); assign->set_custom_minimum_size(Size2(1, 1)); @@ -2318,8 +2318,8 @@ void EditorPropertyResource::_update_menu_items() { menu->clear(); if (get_edited_property() == "script" && base_type == "Script" && Object::cast_to<Node>(get_edited_object())) { - menu->add_icon_item(get_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); - menu->add_icon_item(get_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); + menu->add_icon_item(get_theme_icon("ScriptCreate", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); + menu->add_icon_item(get_theme_icon("ScriptExtend", "EditorIcons"), TTR("Extend Script"), OBJ_MENU_EXTEND_SCRIPT); menu->add_separator(); } else if (base_type != "") { int idx = 0; @@ -2381,7 +2381,7 @@ void EditorPropertyResource::_update_menu_items() { inheritors_array.push_back(t); if (!icon.is_valid()) - icon = get_icon(has_icon(t, "EditorIcons") ? t : "Object", "EditorIcons"); + icon = get_theme_icon(has_theme_icon(t, "EditorIcons") ? t : "Object", "EditorIcons"); int id = TYPE_BASE_ID + idx; menu->add_icon_item(icon, vformat(TTR("New %s"), t), id); @@ -2394,14 +2394,14 @@ void EditorPropertyResource::_update_menu_items() { menu->add_separator(); } - menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); + menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); if (!res.is_null()) { - menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); - menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); - menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); - menu->add_icon_item(get_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE); + menu->add_icon_item(get_theme_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); + menu->add_icon_item(get_theme_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); + menu->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); + menu->add_icon_item(get_theme_icon("Save", "EditorIcons"), TTR("Save"), OBJ_MENU_SAVE); RES r = res; if (r.is_valid() && r->get_path().is_resource_file()) { menu->add_separator(); @@ -2445,12 +2445,12 @@ void EditorPropertyResource::_update_menu_items() { for (int i = 0; i < conversions.size(); i++) { String what = conversions[i]->converts_to(); Ref<Texture2D> icon; - if (has_icon(what, "EditorIcons")) { + if (has_theme_icon(what, "EditorIcons")) { - icon = get_icon(what, "EditorIcons"); + icon = get_theme_icon(what, "EditorIcons"); } else { - icon = get_icon(what, "Resource"); + icon = get_theme_icon(what, "Resource"); } menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); @@ -2462,11 +2462,11 @@ void EditorPropertyResource::_update_menu() { _update_menu_items(); - Rect2 gt = edit->get_global_rect(); + Rect2 gt = edit->get_screen_rect(); menu->set_as_minsize(); - int ms = menu->get_combined_minimum_size().width; + int ms = menu->get_contents_minimum_size().width; Vector2 popup_pos = gt.position + gt.size - Vector2(ms, 0); - menu->set_global_position(popup_pos); + menu->set_position(popup_pos); menu->popup(); } @@ -2490,10 +2490,10 @@ void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) { if (mb.is_valid()) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { _update_menu_items(); - Vector2 pos = mb->get_global_position(); + Vector2 pos = get_screen_position() + mb->get_position(); //pos = assign->get_global_transform().xform(pos); menu->set_as_minsize(); - menu->set_global_position(pos); + menu->set_position(pos); menu->popup(); } } @@ -2663,7 +2663,7 @@ void EditorPropertyResource::setup(const String &p_base_type) { void EditorPropertyResource::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Ref<Texture2D> t = get_icon("select_arrow", "Tree"); + Ref<Texture2D> t = get_theme_icon("select_arrow", "Tree"); edit->set_icon(t); } @@ -2718,7 +2718,7 @@ void EditorPropertyResource::expand_all_folding() { void EditorPropertyResource::_button_draw() { if (dropping) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); assign->draw_rect(Rect2(Point2(), assign->get_size()), color, false); } } diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index c2a6aeb582..13eb2e19d6 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -184,9 +184,9 @@ void EditorPropertyArray::_change_type(Object *p_button, int p_index) { Button *button = Object::cast_to<Button>(p_button); changing_type_idx = p_index; - Rect2 rect = button->get_global_rect(); + Rect2 rect = button->get_screen_rect(); change_type->set_as_minsize(); - change_type->set_global_position(rect.position + rect.size - Vector2(change_type->get_combined_minimum_size().x, 0)); + change_type->set_position(rect.position + rect.size - Vector2(change_type->get_contents_minimum_size().x, 0)); change_type->popup(); } @@ -373,13 +373,13 @@ void EditorPropertyArray::update_property() { if (is_untyped_array) { Button *edit = memnew(Button); - edit->set_icon(get_icon("Edit", "EditorIcons")); + edit->set_icon(get_theme_icon("Edit", "EditorIcons")); hb->add_child(edit); edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_change_type), varray(edit, i + offset)); } else { Button *remove = memnew(Button); - remove->set_icon(get_icon("Remove", "EditorIcons")); + remove->set_icon(get_theme_icon("Remove", "EditorIcons")); remove->connect("pressed", callable_mp(this, &EditorPropertyArray::_remove_pressed), varray(i + offset)); hb->add_child(remove); } @@ -553,9 +553,9 @@ void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) { Button *button = Object::cast_to<Button>(p_button); - Rect2 rect = button->get_global_rect(); + Rect2 rect = button->get_screen_rect(); change_type->set_as_minsize(); - change_type->set_global_position(rect.position + rect.size - Vector2(change_type->get_combined_minimum_size().x, 0)); + change_type->set_position(rect.position + rect.size - Vector2(change_type->get_contents_minimum_size().x, 0)); change_type->popup(); changing_type_idx = p_index; } @@ -909,9 +909,9 @@ void EditorPropertyDictionary::update_property() { for (int j = 0; j < 4; j++) { flat->set_default_margin(Margin(j), 2 * EDSCALE); } - flat->set_bg_color(get_color("prop_subsection", "Editor")); + flat->set_bg_color(get_theme_color("prop_subsection", "Editor")); - pc->add_style_override("panel", flat); + pc->add_theme_style_override("panel", flat); add_vbox = memnew(VBoxContainer); pc->add_child(add_vbox); } @@ -944,7 +944,7 @@ void EditorPropertyDictionary::update_property() { hb->add_child(prop); prop->set_h_size_flags(SIZE_EXPAND_FILL); Button *edit = memnew(Button); - edit->set_icon(get_icon("Edit", "EditorIcons")); + edit->set_icon(get_theme_icon("Edit", "EditorIcons")); hb->add_child(edit); edit->connect("pressed", callable_mp(this, &EditorPropertyDictionary::_change_type), varray(edit, change_index)); diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 98bc544478..398850f2d6 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -168,7 +168,7 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref< } r_texture = generated; - int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retrieve the default icon size + int small_thumbnail_size = EditorNode::get_singleton()->get_theme_base()->get_theme_icon("Object", "EditorIcons")->get_width(); // Kind of a workaround to retrieve the default icon size small_thumbnail_size *= EDSCALE; if (preview_generators[i]->can_generate_small_preview()) { diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 9f0e1f2349..b4ddb7ebfa 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -32,6 +32,7 @@ #include "core/project_settings.h" #include "editor_settings.h" +#include "servers/display_server.h" EditorRun::Status EditorRun::get_status() const { @@ -70,19 +71,19 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L int screen = EditorSettings::get_singleton()->get("run/window_placement/screen"); if (screen == 0) { // Same as editor - screen = OS::get_singleton()->get_current_screen(); + screen = DisplayServer::get_singleton()->window_get_current_screen(); } else if (screen == 1) { // Previous monitor (wrap to the other end if needed) screen = Math::wrapi( - OS::get_singleton()->get_current_screen() - 1, + DisplayServer::get_singleton()->window_get_current_screen() - 1, 0, - OS::get_singleton()->get_screen_count()); + DisplayServer::get_singleton()->get_screen_count()); } else if (screen == 2) { // Next monitor (wrap to the other end if needed) screen = Math::wrapi( - OS::get_singleton()->get_current_screen() + 1, + DisplayServer::get_singleton()->window_get_current_screen() + 1, 0, - OS::get_singleton()->get_screen_count()); + DisplayServer::get_singleton()->get_screen_count()); } else { // Fixed monitor ID // There are 3 special options, so decrement the option ID by 3 to get the monitor ID @@ -94,8 +95,8 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L } Rect2 screen_rect; - screen_rect.position = OS::get_singleton()->get_screen_position(screen); - screen_rect.size = OS::get_singleton()->get_screen_size(screen); + screen_rect.position = DisplayServer::get_singleton()->screen_get_position(screen); + screen_rect.size = DisplayServer::get_singleton()->screen_get_size(screen); Size2 desired_size; desired_size.x = ProjectSettings::get_singleton()->get("display/window/size/width"); @@ -120,7 +121,9 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L case 1: { // centered int display_scale = 1; #ifdef OSX_ENABLED - if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000) { + display_scale = DisplayServer::get_singleton()->screen_get_scale(screen); +#else + if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000) { display_scale = 2; } #endif diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp index fe28efedeb..2c895a3e9d 100644 --- a/editor/editor_sectioned_inspector.cpp +++ b/editor/editor_sectioned_inspector.cpp @@ -257,7 +257,7 @@ void SectionedInspector::update_category_list() { for (int i = 0; i < sc; i++) { TreeItem *parent = section_map[metasection]; - parent->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + parent->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor")); if (i > 0) { metasection += "/" + sectionarr[i]; @@ -309,7 +309,7 @@ SectionedInspector::SectionedInspector() : filter(memnew(SectionedInspectorFilter)), inspector(memnew(EditorInspector)), search_box(NULL) { - add_constant_override("autohide", 1); // Fixes the dragger always showing up + add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up VBoxContainer *left_vb = memnew(VBoxContainer); left_vb->set_custom_minimum_size(Size2(190, 0) * EDSCALE); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index a32b736851..286ca7b184 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -49,7 +49,7 @@ #include "editor/editor_translations.gen.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" // PRIVATE METHODS @@ -599,7 +599,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("run/window_placement/rect", 1); hints["run/window_placement/rect"] = PropertyInfo(Variant::INT, "run/window_placement/rect", PROPERTY_HINT_ENUM, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen"); String screen_hints = "Same as Editor,Previous Monitor,Next Monitor"; - for (int i = 0; i < OS::get_singleton()->get_screen_count(); i++) { + for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) { screen_hints += ",Monitor " + itos(i + 1); } _initial_set("run/window_placement/rect_custom_position", Vector2()); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 0ede0a3b7a..2c115c66cb 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -29,8 +29,9 @@ /*************************************************************************/ #include "editor_spin_slider.h" + +#include "core/input/input_filter.h" #include "core/math/expression.h" -#include "core/os/input.h" #include "editor_node.h" #include "editor_scale.h" @@ -67,7 +68,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { grabbing_spinner_dist_cache = 0; pre_grab_value = get_value(); grabbing_spinner = false; - grabbing_spinner_mouse_pos = Input::get_singleton()->get_mouse_position(); + grabbing_spinner_mouse_pos = InputFilter::get_singleton()->get_mouse_position(); } } else { @@ -75,8 +76,8 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { if (grabbing_spinner) { - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); - Input::get_singleton()->warp_mouse_position(grabbing_spinner_mouse_pos); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); + InputFilter::get_singleton()->warp_mouse_position(grabbing_spinner_mouse_pos); update(); } else { _focus_entered(); @@ -105,7 +106,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { grabbing_spinner_dist_cache += diff_x; if (!grabbing_spinner && ABS(grabbing_spinner_dist_cache) > 4 * EDSCALE) { - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_CAPTURED); grabbing_spinner = true; } @@ -176,11 +177,11 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { void EditorSpinSlider::_notification(int p_what) { - if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT || - p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN || + if (p_what == NOTIFICATION_WM_FOCUS_OUT || + p_what == NOTIFICATION_WM_FOCUS_IN || p_what == NOTIFICATION_EXIT_TREE) { if (grabbing_spinner) { - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); grabbing_spinner = false; grabbing_spinner_attempt = false; } @@ -191,30 +192,30 @@ void EditorSpinSlider::_notification(int p_what) { // when it's edited. The LineEdit "focus" stylebox uses the "normal" stylebox's // default margins. Ref<StyleBoxFlat> stylebox = - EditorNode::get_singleton()->get_theme_base()->get_stylebox("normal", "LineEdit")->duplicate(); + EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "LineEdit")->duplicate(); // EditorSpinSliders with a label have more space on the left, so add an // higher margin to match the location where the text begins. // The margin values below were determined by empirical testing. stylebox->set_default_margin(MARGIN_LEFT, (get_label() != String() ? 23 : 16) * EDSCALE); - value_input->add_style_override("normal", stylebox); + value_input->add_theme_style_override("normal", stylebox); } if (p_what == NOTIFICATION_DRAW) { updown_offset = -1; - Ref<StyleBox> sb = get_stylebox("normal", "LineEdit"); + Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit"); if (!flat) { draw_style_box(sb, Rect2(Vector2(), get_size())); } - Ref<Font> font = get_font("font", "LineEdit"); + Ref<Font> font = get_theme_font("font", "LineEdit"); int sep_base = 4 * EDSCALE; int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better int string_width = font->get_string_size(label).width; int number_width = get_size().width - sb->get_minimum_size().width - string_width - sep; - Ref<Texture2D> updown = get_icon("updown", "SpinBox"); + Ref<Texture2D> updown = get_theme_icon("updown", "SpinBox"); if (get_step() == 1) { number_width -= updown->get_width(); @@ -224,7 +225,7 @@ void EditorSpinSlider::_notification(int p_what) { int vofs = (get_size().height - font->get_height()) / 2 + font->get_ascent(); - Color fc = get_color("font_color", "LineEdit"); + Color fc = get_theme_color("font_color", "LineEdit"); Color lc; if (use_custom_label_color) { lc = custom_label_color; @@ -233,12 +234,12 @@ void EditorSpinSlider::_notification(int p_what) { } if (flat && label != String()) { - Color label_bg_color = get_color("dark_color_3", "Editor"); + Color label_bg_color = get_theme_color("dark_color_3", "Editor"); draw_rect(Rect2(Vector2(), Vector2(sb->get_offset().x * 2 + string_width, get_size().height)), label_bg_color); } if (has_focus()) { - Ref<StyleBox> focus = get_stylebox("focus", "LineEdit"); + Ref<StyleBox> focus = get_theme_stylebox("focus", "LineEdit"); draw_style_box(focus, Rect2(Vector2(), get_size())); } @@ -247,7 +248,7 @@ void EditorSpinSlider::_notification(int p_what) { draw_string(font, Vector2(Math::round(sb->get_offset().x + string_width + sep), vofs), numstr, fc, number_width); if (get_step() == 1) { - Ref<Texture2D> updown2 = get_icon("updown", "SpinBox"); + Ref<Texture2D> updown2 = get_theme_icon("updown", "SpinBox"); int updown_vofs = (get_size().height - updown2->get_height()) / 2; updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown2->get_width(); Color c(1, 1, 1); @@ -272,7 +273,7 @@ void EditorSpinSlider::_notification(int p_what) { Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE); draw_rect(grabber_rect, c); - bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input->is_visible(); + bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner && !value_input_popup->is_visible(); if (grabber->is_visible() != display_grabber) { if (display_grabber) { grabber->show(); @@ -284,9 +285,9 @@ void EditorSpinSlider::_notification(int p_what) { if (display_grabber) { Ref<Texture2D> grabber_tex; if (mouse_over_grabber) { - grabber_tex = get_icon("grabber_highlight", "HSlider"); + grabber_tex = get_theme_icon("grabber_highlight", "HSlider"); } else { - grabber_tex = get_icon("grabber", "HSlider"); + grabber_tex = get_theme_icon("grabber", "HSlider"); } if (grabber->get_texture() != grabber_tex) { @@ -297,7 +298,7 @@ void EditorSpinSlider::_notification(int p_what) { grabber->set_position(get_global_position() + grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5); if (mousewheel_over_grabber) { - Input::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size); + InputFilter::get_singleton()->warp_mouse_position(grabber->get_position() + grabber_rect.size); } grabber_range = width; @@ -316,12 +317,7 @@ void EditorSpinSlider::_notification(int p_what) { update(); } if (p_what == NOTIFICATION_FOCUS_ENTER) { - /* Sorry, I don't like this, it makes navigating the different fields with arrows more difficult. - * Just press enter to edit. - * if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && !value_input_just_closed) { - _focus_entered(); - }*/ - if ((Input::get_singleton()->is_action_pressed("ui_focus_next") || Input::get_singleton()->is_action_pressed("ui_focus_prev")) && !value_input_just_closed) { + if ((InputFilter::get_singleton()->is_action_pressed("ui_focus_next") || InputFilter::get_singleton()->is_action_pressed("ui_focus_prev")) && !value_input_just_closed) { _focus_entered(); } value_input_just_closed = false; @@ -330,8 +326,8 @@ void EditorSpinSlider::_notification(int p_what) { Size2 EditorSpinSlider::get_minimum_size() const { - Ref<StyleBox> sb = get_stylebox("normal", "LineEdit"); - Ref<Font> font = get_font("font", "LineEdit"); + Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit"); + Ref<Font> font = get_theme_font("font", "LineEdit"); Size2 ms = sb->get_minimum_size(); ms.height += font->get_height(); @@ -375,7 +371,7 @@ void EditorSpinSlider::_evaluate_input_text() { //text_entered signal void EditorSpinSlider::_value_input_entered(const String &p_text) { value_input_just_closed = true; - value_input->hide(); + value_input_popup->hide(); } //modal_closed signal @@ -398,7 +394,7 @@ void EditorSpinSlider::_value_focus_exited() { // -> modal_close was not called // -> need to close/hide manually if (!value_input_just_closed) { //value_input_just_closed should do the same - value_input->hide(); + value_input_popup->hide(); //tab was pressed } else { //enter, click, esc @@ -441,11 +437,11 @@ void EditorSpinSlider::set_custom_label_color(bool p_use_custom_label_color, Col } void EditorSpinSlider::_focus_entered() { - Rect2 gr = get_global_rect(); + Rect2 gr = get_screen_rect(); value_input->set_text(get_text_value()); - value_input->set_position(gr.position); - value_input->set_size(gr.size); - value_input->call_deferred("show_modal"); + value_input_popup->set_position(gr.position); + value_input_popup->set_size(gr.size); + value_input_popup->call_deferred("popup"); value_input->call_deferred("grab_focus"); value_input->call_deferred("select_all"); value_input->set_focus_next(find_next_valid_focus()->get_path()); @@ -492,11 +488,13 @@ EditorSpinSlider::EditorSpinSlider() { mousewheel_over_grabber = false; grabbing_grabber = false; grabber_range = 1; + value_input_popup = memnew(Popup); + add_child(value_input_popup); value_input = memnew(LineEdit); - add_child(value_input); - value_input->set_as_toplevel(true); - value_input->hide(); - value_input->connect("modal_closed", callable_mp(this, &EditorSpinSlider::_value_input_closed)); + value_input_popup->add_child(value_input); + value_input_popup->set_wrap_controls(true); + value_input->set_anchors_and_margins_preset(PRESET_WIDE); + value_input_popup->connect("popup_hide", callable_mp(this, &EditorSpinSlider::_value_input_closed)); value_input->connect("text_entered", callable_mp(this, &EditorSpinSlider::_value_input_entered)); value_input->connect("focus_exited", callable_mp(this, &EditorSpinSlider::_value_focus_exited)); value_input_just_closed = false; diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h index 81a7b981cc..db74f5fb70 100644 --- a/editor/editor_spin_slider.h +++ b/editor/editor_spin_slider.h @@ -62,6 +62,7 @@ class EditorSpinSlider : public Range { Vector2 grabbing_spinner_mouse_pos; double pre_grab_value; + Popup *value_input_popup; LineEdit *value_input; bool value_input_just_closed; diff --git a/editor/editor_sub_scene.cpp b/editor/editor_sub_scene.cpp index 3ebd8f0475..cd5768551f 100644 --- a/editor/editor_sub_scene.cpp +++ b/editor/editor_sub_scene.cpp @@ -70,11 +70,11 @@ void EditorSubScene::_path_browse() { } void EditorSubScene::_notification(int p_what) { - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (is_visible() && scene == NULL) + if (is_visible() && scene == NULL) { _path_browse(); + } } } @@ -240,7 +240,7 @@ EditorSubScene::EditorSubScene() { path = memnew(LineEdit); path->connect("text_entered", callable_mp(this, &EditorSubScene::_path_changed)); hb->add_child(path); - path->set_h_size_flags(SIZE_EXPAND_FILL); + path->set_h_size_flags(Control::SIZE_EXPAND_FILL); Button *b = memnew(Button); b->set_text(TTR("Browse")); hb->add_child(b); @@ -248,7 +248,7 @@ EditorSubScene::EditorSubScene() { vb->add_margin_child(TTR("Scene Path:"), hb); tree = memnew(Tree); - tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); vb->add_margin_child(TTR("Import From Node:"), tree, true); tree->set_select_mode(Tree::SELECT_MULTI); tree->connect("multi_selected", callable_mp(this, &EditorSubScene::_item_multi_selected)); @@ -266,7 +266,7 @@ EditorSubScene::EditorSubScene() { file_dialog->add_filter("*." + E->get()); } - file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &EditorSubScene::_path_selected)); } diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 1263eb166b..ac902854b7 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -910,14 +910,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_window->set_border_color(tab_color); style_window->set_border_width(MARGIN_TOP, 24 * EDSCALE); style_window->set_expand_margin_size(MARGIN_TOP, 24 * EDSCALE); - theme->set_stylebox("panel", "WindowDialog", style_window); - theme->set_color("title_color", "WindowDialog", font_color); - theme->set_icon("close", "WindowDialog", theme->get_icon("GuiClose", "EditorIcons")); - theme->set_icon("close_highlight", "WindowDialog", theme->get_icon("GuiClose", "EditorIcons")); - theme->set_constant("close_h_ofs", "WindowDialog", 22 * EDSCALE); - theme->set_constant("close_v_ofs", "WindowDialog", 20 * EDSCALE); - theme->set_constant("title_height", "WindowDialog", 24 * EDSCALE); - theme->set_font("title_font", "WindowDialog", theme->get_font("title", "EditorFonts")); + + theme->set_stylebox("panel", "Window", style_default); + theme->set_stylebox("panel_window", "Window", style_window); + theme->set_color("title_color", "Window", font_color); + theme->set_icon("close", "Window", theme->get_icon("GuiClose", "EditorIcons")); + theme->set_icon("close_highlight", "Window", theme->get_icon("GuiClose", "EditorIcons")); + theme->set_constant("close_h_ofs", "Window", 22 * EDSCALE); + theme->set_constant("close_v_ofs", "Window", 20 * EDSCALE); + theme->set_constant("title_height", "Window", 24 * EDSCALE); + theme->set_constant("resize_margin", "Window", 4 * EDSCALE); + theme->set_font("title_font", "Window", theme->get_font("title", "EditorFonts")); // complex window, for now only Editor settings and Project settings Ref<StyleBoxFlat> style_complex_window = style_window->duplicate(); @@ -974,10 +977,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); theme->set_stylebox("normal", "RichTextLabel", style_tree_bg); + theme->set_stylebox("panel", "EditorHelpBit", make_flat_stylebox(dark_color_1, 6, 4, 6, 4)); + theme->set_color("headline_color", "EditorHelp", mono_color); // Panel theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4)); + theme->set_stylebox("panel_fg", "Panel", style_default); // Label theme->set_stylebox("normal", "Label", style_empty); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 9328a5e04d..61ec9c44c2 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -30,10 +30,10 @@ #include "export_template_manager.h" +#include "core/input/input_filter.h" #include "core/io/json.h" #include "core/io/zip_io.h" #include "core/os/dir_access.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/version.h" #include "editor_node.h" @@ -82,11 +82,11 @@ void ExportTemplateManager::_update_template_list() { String(VERSION_STATUS) != String("rc"); Label *current = memnew(Label); - current->set_h_size_flags(SIZE_EXPAND_FILL); + current->set_h_size_flags(Control::SIZE_EXPAND_FILL); current_hb->add_child(current); if (templates.has(current_version)) { - current->add_color_override("font_color", get_color("success_color", "Editor")); + current->add_theme_color_override("font_color", current->get_theme_color("success_color", "Editor")); // Only display a redownload button if it can be downloaded in the first place if (downloads_available) { @@ -103,7 +103,7 @@ void ExportTemplateManager::_update_template_list() { uninstall->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template), varray(current_version)); } else { - current->add_color_override("font_color", get_color("error_color", "Editor")); + current->add_theme_color_override("font_color", current->get_theme_color("error_color", "Editor")); Button *redownload = memnew(Button); redownload->set_text(TTR("Download")); @@ -121,13 +121,13 @@ void ExportTemplateManager::_update_template_list() { HBoxContainer *hbc = memnew(HBoxContainer); Label *version = memnew(Label); - version->set_modulate(get_color("disabled_font_color", "Editor")); + version->set_modulate(current->get_theme_color("disabled_font_color", "Editor")); String text = E->get(); if (text == current_version) { text += " " + TTR("(Current)"); } version->set_text(text); - version->set_h_size_flags(SIZE_EXPAND_FILL); + version->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(version); Button *uninstall = memnew(Button); @@ -145,7 +145,7 @@ void ExportTemplateManager::_download_template(const String &p_version) { while (template_list->get_child_count()) { memdelete(template_list->get_child(0)); } - template_downloader->popup_centered_minsize(); + template_downloader->popup_centered(); template_list_state->set_text(TTR("Retrieving mirrors, please wait...")); template_download_progress->set_max(100); template_download_progress->set_value(0); @@ -157,7 +157,7 @@ void ExportTemplateManager::_download_template(const String &p_version) { void ExportTemplateManager::_uninstall_template(const String &p_version) { remove_confirm->set_text(vformat(TTR("Remove template version '%s'?"), p_version)); - remove_confirm->popup_centered_minsize(); + remove_confirm->popup_centered(); to_remove = p_version; } @@ -342,7 +342,7 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ void ExportTemplateManager::popup_manager() { _update_template_list(); - popup_centered_minsize(Size2(400, 400) * EDSCALE); + popup_centered(Size2(400, 400) * EDSCALE); } void ExportTemplateManager::ok_pressed() { @@ -446,7 +446,7 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int void ExportTemplateManager::_begin_template_download(const String &p_url) { - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { OS::get_singleton()->shell_open(p_url); return; } @@ -483,6 +483,11 @@ void ExportTemplateManager::_window_template_downloader_closed() { void ExportTemplateManager::_notification(int p_what) { + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (!is_visible()) { + set_process(false); + } + } if (p_what == NOTIFICATION_PROCESS) { update_countdown -= get_process_delta_time(); @@ -536,12 +541,6 @@ void ExportTemplateManager::_notification(int p_what) { set_process(false); } } - - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (!is_visible_in_tree()) { - set_process(false); - } - } } bool ExportTemplateManager::can_install_android_template() { @@ -674,7 +673,7 @@ ExportTemplateManager::ExportTemplateManager() { installed_scroll->add_child(installed_vb); installed_scroll->set_enable_v_scroll(true); installed_scroll->set_enable_h_scroll(false); - installed_vb->set_h_size_flags(SIZE_EXPAND_FILL); + installed_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); get_cancel()->set_text(TTR("Close")); get_ok()->set_text(TTR("Install From File")); @@ -688,7 +687,7 @@ ExportTemplateManager::ExportTemplateManager() { template_open->set_title(TTR("Select Template File")); template_open->add_filter("*.tpz ; " + TTR("Godot Export Templates")); template_open->set_access(FileDialog::ACCESS_FILESYSTEM); - template_open->set_mode(FileDialog::MODE_OPEN_FILE); + template_open->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); template_open->connect("file_selected", callable_mp(this, &ExportTemplateManager::_install_from_file), varray(true)); add_child(template_open); @@ -708,7 +707,7 @@ ExportTemplateManager::ExportTemplateManager() { template_downloader->get_ok()->set_text(TTR("Close")); template_downloader->set_exclusive(true); add_child(template_downloader); - template_downloader->connect("popup_hide", callable_mp(this, &ExportTemplateManager::_window_template_downloader_closed)); + template_downloader->connect("cancelled", callable_mp(this, &ExportTemplateManager::_window_template_downloader_closed)); VBoxContainer *vbc = memnew(VBoxContainer); template_downloader->add_child(vbc); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 962d95736f..e1fcddda3a 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -42,16 +42,17 @@ #include "editor_scale.h" #include "editor_settings.h" #include "import_dock.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" +#include "servers/display_server.h" Ref<Texture2D> FileSystemDock::_get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx) { Ref<Texture2D> file_icon; if (!p_dir->get_file_import_is_valid(p_idx)) { - file_icon = get_icon("ImportFail", "EditorIcons"); + file_icon = get_theme_icon("ImportFail", "EditorIcons"); } else { String file_type = p_dir->get_file_type(p_idx); - file_icon = (has_icon(file_type, "EditorIcons")) ? get_icon(file_type, "EditorIcons") : get_icon("File", "EditorIcons"); + file_icon = (has_theme_icon(file_type, "EditorIcons")) ? get_theme_icon(file_type, "EditorIcons") : get_theme_icon("File", "EditorIcons"); } return file_icon; } @@ -66,8 +67,8 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory dname = "res://"; subdirectory_item->set_text(0, dname); - subdirectory_item->set_icon(0, get_icon("Folder", "EditorIcons")); - subdirectory_item->set_icon_modulate(0, get_color("folder_icon_modulate", "FileDialog")); + subdirectory_item->set_icon(0, get_theme_icon("Folder", "EditorIcons")); + subdirectory_item->set_icon_modulate(0, get_theme_color("folder_icon_modulate", "FileDialog")); subdirectory_item->set_selectable(0, true); String lpath = p_dir->get_path(); subdirectory_item->set_metadata(0, lpath); @@ -121,7 +122,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory file_item->set_as_cursor(0); } if (main_scene == file_metadata) { - file_item->set_custom_color(0, get_color("accent_color", "Editor")); + file_item->set_custom_color(0, get_theme_color("accent_color", "Editor")); } Array udata; udata.push_back(tree_update_id); @@ -187,7 +188,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo // Handles the favorites. TreeItem *favorites = tree->create_item(root); - favorites->set_icon(0, get_icon("Favorites", "EditorIcons")); + favorites->set_icon(0, get_theme_icon("Favorites", "EditorIcons")); favorites->set_text(0, TTR("Favorites:")); favorites->set_metadata(0, "Favorites"); favorites->set_collapsed(p_uncollapsed_paths.find("Favorites") < 0); @@ -198,8 +199,8 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo if (!fave.begins_with("res://")) continue; - Ref<Texture2D> folder_icon = get_icon("Folder", "EditorIcons"); - const Color folder_color = get_color("folder_icon_modulate", "FileDialog"); + Ref<Texture2D> folder_icon = get_theme_icon("Folder", "EditorIcons"); + const Color folder_color = get_theme_color("folder_icon_modulate", "FileDialog"); String text; Ref<Texture2D> icon; @@ -219,7 +220,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo if (dir) { icon = _get_tree_item_icon(dir, index); } else { - icon = get_icon("File", "EditorIcons"); + icon = get_theme_icon("File", "EditorIcons"); } color = Color(1, 1, 1); } @@ -306,20 +307,21 @@ void FileSystemDock::_notification(int p_what) { EditorResourcePreview::get_singleton()->connect("preview_invalidated", callable_mp(this, &FileSystemDock::_preview_invalidated)); String ei = "EditorIcons"; - button_reload->set_icon(get_icon("Reload", ei)); - button_toggle_display_mode->set_icon(get_icon("Panels2", ei)); + + button_reload->set_icon(get_theme_icon("Reload", ei)); + button_toggle_display_mode->set_icon(get_theme_icon("Panels2", ei)); button_file_list_display_mode->connect("pressed", callable_mp(this, &FileSystemDock::_toggle_file_display)); files->connect("item_activated", callable_mp(this, &FileSystemDock::_file_list_activate_file)); button_hist_next->connect("pressed", callable_mp(this, &FileSystemDock::_fw_history)); button_hist_prev->connect("pressed", callable_mp(this, &FileSystemDock::_bw_history)); - tree_search_box->set_right_icon(get_icon("Search", ei)); + tree_search_box->set_right_icon(get_theme_icon("Search", ei)); tree_search_box->set_clear_button_enabled(true); - file_list_search_box->set_right_icon(get_icon("Search", ei)); + file_list_search_box->set_right_icon(get_theme_icon("Search", ei)); file_list_search_box->set_clear_button_enabled(true); - button_hist_next->set_icon(get_icon("Forward", ei)); - button_hist_prev->set_icon(get_icon("Back", ei)); + button_hist_next->set_icon(get_theme_icon("Forward", ei)); + button_hist_prev->set_icon(get_theme_icon("Back", ei)); file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option)); tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option)); @@ -369,19 +371,19 @@ void FileSystemDock::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { // Update icons. String ei = "EditorIcons"; - button_reload->set_icon(get_icon("Reload", ei)); - button_toggle_display_mode->set_icon(get_icon("Panels2", ei)); - button_hist_next->set_icon(get_icon("Forward", ei)); - button_hist_prev->set_icon(get_icon("Back", ei)); + button_reload->set_icon(get_theme_icon("Reload", ei)); + button_toggle_display_mode->set_icon(get_theme_icon("Panels2", ei)); + button_hist_next->set_icon(get_theme_icon("Forward", ei)); + button_hist_prev->set_icon(get_theme_icon("Back", ei)); if (file_list_display_mode == FILE_LIST_DISPLAY_LIST) { - button_file_list_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); + button_file_list_display_mode->set_icon(get_theme_icon("FileThumbnail", "EditorIcons")); } else { - button_file_list_display_mode->set_icon(get_icon("FileList", "EditorIcons")); + button_file_list_display_mode->set_icon(get_theme_icon("FileList", "EditorIcons")); } - tree_search_box->set_right_icon(get_icon("Search", ei)); + tree_search_box->set_right_icon(get_theme_icon("Search", ei)); tree_search_box->set_clear_button_enabled(true); - file_list_search_box->set_right_icon(get_icon("Search", ei)); + file_list_search_box->set_right_icon(get_theme_icon("Search", ei)); file_list_search_box->set_clear_button_enabled(true); // Update always show folders. @@ -532,11 +534,11 @@ void FileSystemDock::_toggle_file_display() { void FileSystemDock::_set_file_display(bool p_active) { if (p_active) { file_list_display_mode = FILE_LIST_DISPLAY_LIST; - button_file_list_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); + button_file_list_display_mode->set_icon(get_theme_icon("FileThumbnail", "EditorIcons")); button_file_list_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); } else { file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; - button_file_list_display_mode->set_icon(get_icon("FileList", "EditorIcons")); + button_file_list_display_mode->set_icon(get_theme_icon("FileList", "EditorIcons")); button_file_list_display_mode->set_tooltip(TTR("View items as a list.")); } @@ -628,13 +630,13 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { files->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size)); if (thumbnail_size < 64) { - folder_thumbnail = get_icon("FolderMediumThumb", ei); - file_thumbnail = get_icon("FileMediumThumb", ei); - file_thumbnail_broken = get_icon("FileDeadMediumThumb", ei); + folder_thumbnail = get_theme_icon("FolderMediumThumb", ei); + file_thumbnail = get_theme_icon("FileMediumThumb", ei); + file_thumbnail_broken = get_theme_icon("FileDeadMediumThumb", ei); } else { - folder_thumbnail = get_icon("FolderBigThumb", ei); - file_thumbnail = get_icon("FileBigThumb", ei); - file_thumbnail_broken = get_icon("FileDeadBigThumb", ei); + folder_thumbnail = get_theme_icon("FolderBigThumb", ei); + file_thumbnail = get_theme_icon("FileBigThumb", ei); + file_thumbnail_broken = get_theme_icon("FileDeadBigThumb", ei); } } else { // No thumbnails. @@ -645,8 +647,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { files->set_fixed_icon_size(Size2()); } - Ref<Texture2D> folder_icon = (use_thumbnails) ? folder_thumbnail : get_icon("folder", "FileDialog"); - const Color folder_color = get_color("folder_icon_modulate", "FileDialog"); + Ref<Texture2D> folder_icon = (use_thumbnails) ? folder_thumbnail : get_theme_icon("folder", "FileDialog"); + const Color folder_color = get_theme_color("folder_icon_modulate", "FileDialog"); // Build the FileInfo list. List<FileInfo> filelist; @@ -766,10 +768,10 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { // Select the icons. if (!finfo->import_broken) { - type_icon = (has_icon(ftype, ei)) ? get_icon(ftype, ei) : get_icon(oi, ei); + type_icon = (has_theme_icon(ftype, ei)) ? get_theme_icon(ftype, ei) : get_theme_icon(oi, ei); big_icon = file_thumbnail; } else { - type_icon = get_icon("ImportFail", ei); + type_icon = get_theme_icon("ImportFail", ei); big_icon = file_thumbnail_broken; tooltip += "\n" + TTR("Status: Import of file failed. Please fix file and reimport manually."); } @@ -789,7 +791,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) { } if (fpath == main_scene) { - files->set_item_custom_fg_color(item_index, get_color("accent_color", "Editor")); + files->set_item_custom_fg_color(item_index, get_theme_color("accent_color", "Editor")); } // Generate the preview. @@ -1412,7 +1414,7 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove bool can_move = _check_existing(); if (!can_move) { // Ask to do something. - overwrite_dialog->popup_centered_minsize(); + overwrite_dialog->popup_centered(); return; } } @@ -1676,7 +1678,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected rename_dialog_text->set_text(name); rename_dialog_text->select(0, name.length()); } - rename_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + rename_dialog->popup_centered(Size2(250, 80) * EDSCALE); rename_dialog_text->grab_focus(); } } @@ -1720,7 +1722,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected duplicate_dialog_text->set_text(name); duplicate_dialog_text->select(0, name.length()); } - duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + duplicate_dialog->popup_centered(Size2(250, 80) * EDSCALE); duplicate_dialog_text->grab_focus(); } } break; @@ -1742,14 +1744,14 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected case FILE_NEW_FOLDER: { make_dir_dialog_text->set_text("new folder"); make_dir_dialog_text->select_all(); - make_dir_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + make_dir_dialog->popup_centered(Size2(250, 80) * EDSCALE); make_dir_dialog_text->grab_focus(); } break; case FILE_NEW_SCENE: { make_scene_dialog_text->set_text("new scene"); make_scene_dialog_text->select_all(); - make_scene_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE); + make_scene_dialog->popup_centered(Size2(250, 80) * EDSCALE); make_scene_dialog_text->grab_focus(); } break; @@ -1765,7 +1767,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected case FILE_COPY_PATH: { if (!p_selected.empty()) { String fpath = p_selected[0]; - OS::get_singleton()->set_clipboard(fpath); + DisplayServer::get_singleton()->clipboard_set(fpath); } } break; @@ -2178,28 +2180,28 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str if (all_files) { if (all_files_scenes) { if (filenames.size() == 1) { - p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open Scene"), FILE_OPEN); - p_popup->add_icon_item(get_icon("CreateNewSceneFrom", "EditorIcons"), TTR("New Inherited Scene"), FILE_INHERIT); + p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open Scene"), FILE_OPEN); + p_popup->add_icon_item(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), TTR("New Inherited Scene"), FILE_INHERIT); if (ProjectSettings::get_singleton()->get("application/run/main_scene") != filenames[0]) { - p_popup->add_icon_item(get_icon("PlayScene", "EditorIcons"), TTR("Set As Main Scene"), FILE_MAIN_SCENE); + p_popup->add_icon_item(get_theme_icon("PlayScene", "EditorIcons"), TTR("Set As Main Scene"), FILE_MAIN_SCENE); } } else { - p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open Scenes"), FILE_OPEN); + p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open Scenes"), FILE_OPEN); } - p_popup->add_icon_item(get_icon("Instance", "EditorIcons"), TTR("Instance"), FILE_INSTANCE); + p_popup->add_icon_item(get_theme_icon("Instance", "EditorIcons"), TTR("Instance"), FILE_INSTANCE); p_popup->add_separator(); } else if (filenames.size() == 1) { - p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN); + p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN); p_popup->add_separator(); } } if (p_paths.size() >= 1) { if (!all_favorites) { - p_popup->add_icon_item(get_icon("Favorites", "EditorIcons"), TTR("Add to Favorites"), FILE_ADD_FAVORITE); + p_popup->add_icon_item(get_theme_icon("Favorites", "EditorIcons"), TTR("Add to Favorites"), FILE_ADD_FAVORITE); } if (!all_not_favorites) { - p_popup->add_icon_item(get_icon("NonFavorite", "EditorIcons"), TTR("Remove from Favorites"), FILE_REMOVE_FAVORITE); + p_popup->add_icon_item(get_theme_icon("NonFavorite", "EditorIcons"), TTR("Remove from Favorites"), FILE_REMOVE_FAVORITE); } p_popup->add_separator(); } @@ -2212,36 +2214,36 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str } } else if (all_folders && foldernames.size() > 0) { - p_popup->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN); + p_popup->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open"), FILE_OPEN); p_popup->add_separator(); } if (p_paths.size() == 1) { - p_popup->add_icon_item(get_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), FILE_COPY_PATH); + p_popup->add_icon_item(get_theme_icon("ActionCopy", "EditorIcons"), TTR("Copy Path"), FILE_COPY_PATH); if (p_paths[0] != "res://") { - p_popup->add_icon_item(get_icon("Rename", "EditorIcons"), TTR("Rename..."), FILE_RENAME); - p_popup->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Duplicate..."), FILE_DUPLICATE); + p_popup->add_icon_item(get_theme_icon("Rename", "EditorIcons"), TTR("Rename..."), FILE_RENAME); + p_popup->add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), TTR("Duplicate..."), FILE_DUPLICATE); } } if (p_paths.size() > 1 || p_paths[0] != "res://") { - p_popup->add_icon_item(get_icon("MoveUp", "EditorIcons"), TTR("Move To..."), FILE_MOVE); - p_popup->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete"), FILE_REMOVE); + p_popup->add_icon_item(get_theme_icon("MoveUp", "EditorIcons"), TTR("Move To..."), FILE_MOVE); + p_popup->add_icon_item(get_theme_icon("Remove", "EditorIcons"), TTR("Delete"), FILE_REMOVE); } if (p_paths.size() == 1) { p_popup->add_separator(); if (p_display_path_dependent_options) { - p_popup->add_icon_item(get_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); - p_popup->add_icon_item(get_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); - p_popup->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); - p_popup->add_icon_item(get_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); + p_popup->add_icon_item(get_theme_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); + p_popup->add_icon_item(get_theme_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); + p_popup->add_icon_item(get_theme_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); + p_popup->add_icon_item(get_theme_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); p_popup->add_separator(); } String fpath = p_paths[0]; String item_text = fpath.ends_with("/") ? TTR("Open in File Manager") : TTR("Show in File Manager"); - p_popup->add_icon_item(get_icon("Filesystem", "EditorIcons"), item_text, FILE_SHOW_IN_EXPLORER); + p_popup->add_icon_item(get_theme_icon("Filesystem", "EditorIcons"), item_text, FILE_SHOW_IN_EXPLORER); } } @@ -2251,8 +2253,8 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { if (paths.size() == 1) { if (paths[0].ends_with("/")) { - tree_popup->add_icon_item(get_icon("GuiTreeArrowDown", "EditorIcons"), TTR("Expand All"), FOLDER_EXPAND_ALL); - tree_popup->add_icon_item(get_icon("GuiTreeArrowRight", "EditorIcons"), TTR("Collapse All"), FOLDER_COLLAPSE_ALL); + tree_popup->add_icon_item(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), TTR("Expand All"), FOLDER_EXPAND_ALL); + tree_popup->add_icon_item(get_theme_icon("GuiTreeArrowRight", "EditorIcons"), TTR("Collapse All"), FOLDER_COLLAPSE_ALL); tree_popup->add_separator(); } } @@ -2272,10 +2274,10 @@ void FileSystemDock::_tree_rmb_empty(const Vector2 &p_pos) { path = "res://"; tree_popup->clear(); tree_popup->set_size(Size2(1, 1)); - tree_popup->add_icon_item(get_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); - tree_popup->add_icon_item(get_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); - tree_popup->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); - tree_popup->add_icon_item(get_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); + tree_popup->add_icon_item(get_theme_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); + tree_popup->add_icon_item(get_theme_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); + tree_popup->add_icon_item(get_theme_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); + tree_popup->add_icon_item(get_theme_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); tree_popup->set_position(tree->get_global_position() + p_pos); tree_popup->popup(); } @@ -2315,12 +2317,12 @@ void FileSystemDock::_file_list_rmb_pressed(const Vector2 &p_pos) { file_list_popup->clear(); file_list_popup->set_size(Size2(1, 1)); - file_list_popup->add_icon_item(get_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); - file_list_popup->add_icon_item(get_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); - file_list_popup->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); - file_list_popup->add_icon_item(get_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); + file_list_popup->add_icon_item(get_theme_icon("Folder", "EditorIcons"), TTR("New Folder..."), FILE_NEW_FOLDER); + file_list_popup->add_icon_item(get_theme_icon("PackedScene", "EditorIcons"), TTR("New Scene..."), FILE_NEW_SCENE); + file_list_popup->add_icon_item(get_theme_icon("Script", "EditorIcons"), TTR("New Script..."), FILE_NEW_SCRIPT); + file_list_popup->add_icon_item(get_theme_icon("Object", "EditorIcons"), TTR("New Resource..."), FILE_NEW_RESOURCE); file_list_popup->add_separator(); - file_list_popup->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER); + file_list_popup->add_icon_item(get_theme_icon("Filesystem", "EditorIcons"), TTR("Open in File Manager"), FILE_SHOW_IN_EXPLORER); file_list_popup->set_position(files->get_global_position() + p_pos); file_list_popup->popup(); } @@ -2348,8 +2350,6 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { } void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { - if (get_viewport()->get_modal_stack_top()) - return; // Ignore because of modal window. Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { @@ -2366,8 +2366,6 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { } void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { - if (get_viewport()->get_modal_stack_top()) - return; // Ignore because of modal window. Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { @@ -2492,7 +2490,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { add_child(top_vbc); HBoxContainer *toolbar_hbc = memnew(HBoxContainer); - toolbar_hbc->add_constant_override("separation", 0); + toolbar_hbc->add_theme_constant_override("separation", 0); top_vbc->add_child(toolbar_hbc); button_hist_prev = memnew(ToolButton); @@ -2529,7 +2527,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { toolbar_hbc->add_child(button_toggle_display_mode); HBoxContainer *toolbar2_hbc = memnew(HBoxContainer); - toolbar2_hbc->add_constant_override("separation", 0); + toolbar2_hbc->add_theme_constant_override("separation", 0); top_vbc->add_child(toolbar2_hbc); tree_search_box = memnew(LineEdit); @@ -2539,11 +2537,11 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { toolbar2_hbc->add_child(tree_search_box); file_list_popup = memnew(PopupMenu); - file_list_popup->set_hide_on_window_lose_focus(true); + add_child(file_list_popup); tree_popup = memnew(PopupMenu); - tree_popup->set_hide_on_window_lose_focus(true); + add_child(tree_popup); split_box = memnew(VSplitContainer); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 5a7d4cede7..61afc9115f 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -299,14 +299,14 @@ const char *FindInFilesDialog::SIGNAL_REPLACE_REQUESTED = "replace_requested"; FindInFilesDialog::FindInFilesDialog() { - set_custom_minimum_size(Size2(500 * EDSCALE, 0)); + set_min_size(Size2(500 * EDSCALE, 0)); set_title(TTR("Find in Files")); VBoxContainer *vbc = memnew(VBoxContainer); - vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE); add_child(vbc); GridContainer *gc = memnew(GridContainer); @@ -318,7 +318,7 @@ FindInFilesDialog::FindInFilesDialog() { gc->add_child(find_label); _search_text_line_edit = memnew(LineEdit); - _search_text_line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + _search_text_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); _search_text_line_edit->connect("text_changed", callable_mp(this, &FindInFilesDialog::_on_search_text_modified)); _search_text_line_edit->connect("text_entered", callable_mp(this, &FindInFilesDialog::_on_search_text_entered)); gc->add_child(_search_text_line_edit); @@ -329,7 +329,7 @@ FindInFilesDialog::FindInFilesDialog() { gc->add_child(_replace_label); _replace_text_line_edit = memnew(LineEdit); - _replace_text_line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + _replace_text_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); _replace_text_line_edit->connect("text_entered", callable_mp(this, &FindInFilesDialog::_on_replace_text_entered)); _replace_text_line_edit->hide(); gc->add_child(_replace_text_line_edit); @@ -362,7 +362,7 @@ FindInFilesDialog::FindInFilesDialog() { hbc->add_child(prefix_label); _folder_line_edit = memnew(LineEdit); - _folder_line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + _folder_line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(_folder_line_edit); Button *folder_button = memnew(Button); @@ -371,7 +371,7 @@ FindInFilesDialog::FindInFilesDialog() { hbc->add_child(folder_button); _folder_dialog = memnew(FileDialog); - _folder_dialog->set_mode(FileDialog::MODE_OPEN_DIR); + _folder_dialog->set_file_mode(FileDialog::FILE_MODE_OPEN_DIR); _folder_dialog->connect("dir_selected", callable_mp(this, &FindInFilesDialog::_on_folder_selected)); add_child(_folder_dialog); @@ -464,6 +464,7 @@ Set<String> FindInFilesDialog::get_filter() const { void FindInFilesDialog::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (is_visible()) { // Doesn't work more than once if not deferred... _search_text_line_edit->call_deferred("grab_focus"); @@ -576,7 +577,7 @@ FindInFilesPanel::FindInFilesPanel() { hbc->add_child(find_label); _search_text_label = memnew(Label); - _search_text_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts")); + _search_text_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts")); hbc->add_child(_search_text_label); _progress_bar = memnew(ProgressBar); @@ -604,7 +605,7 @@ FindInFilesPanel::FindInFilesPanel() { } _results_display = memnew(Tree); - _results_display->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts")); + _results_display->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts")); _results_display->set_v_size_flags(SIZE_EXPAND_FILL); _results_display->connect("item_selected", callable_mp(this, &FindInFilesPanel::_on_result_selected)); _results_display->connect("item_edited", callable_mp(this, &FindInFilesPanel::_on_item_edited)); @@ -734,7 +735,7 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin item->set_text(text_index, item_text); item->set_custom_draw(text_index, this, "_draw_result_text"); - Ref<Font> font = _results_display->get_font("font"); + Ref<Font> font = _results_display->get_theme_font("font"); float raw_text_width = font->get_string_size(text).x; float item_text_width = font->get_string_size(item_text).x; @@ -780,11 +781,11 @@ void FindInFilesPanel::_on_item_edited() { TreeItem *item = _results_display->get_selected(); if (item->is_checked(0)) { - item->set_custom_color(1, _results_display->get_color("font_color")); + item->set_custom_color(1, _results_display->get_theme_color("font_color")); } else { // Grey out - Color color = _results_display->get_color("font_color"); + Color color = _results_display->get_theme_color("font_color"); color.a /= 2.0; item->set_custom_color(1, color); } diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 7002f750b7..41adb156b6 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -120,10 +120,11 @@ public: Set<String> get_filter() const; protected: - static void _bind_methods(); - void _notification(int p_what); + + void _visibility_changed(); void custom_action(const String &p_action); + static void _bind_methods(); private: void _on_folder_button_pressed(); diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index b4c9a01f2a..686ca869a6 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -94,7 +94,7 @@ void GroupDialog::_load_nodes(Node *p_current) { if (!_can_edit(p_current, selected_group)) { node->set_selectable(0, false); - node->set_custom_color(0, get_color("disabled_font_color", "Editor")); + node->set_custom_color(0, groups->get_theme_color("disabled_font_color", "Editor")); } } @@ -204,7 +204,7 @@ void GroupDialog::_add_group(String p_name) { TreeItem *new_group = groups->create_item(groups_root); new_group->set_text(0, name); - new_group->add_button(0, get_icon("Remove", "EditorIcons"), 0); + new_group->add_button(0, groups->get_theme_icon("Remove", "EditorIcons"), 0); new_group->set_editable(0, true); new_group->select(0); groups->ensure_cursor_is_visible(); @@ -361,12 +361,12 @@ void GroupDialog::_delete_group_item(const String &p_name) { void GroupDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - add_button->set_icon(get_icon("Forward", "EditorIcons")); - remove_button->set_icon(get_icon("Back", "EditorIcons")); + add_button->set_icon(groups->get_theme_icon("Forward", "EditorIcons")); + remove_button->set_icon(groups->get_theme_icon("Back", "EditorIcons")); - add_filter->set_right_icon(get_icon("Search", "EditorIcons")); + add_filter->set_right_icon(groups->get_theme_icon("Search", "EditorIcons")); add_filter->set_clear_button_enabled(true); - remove_filter->set_right_icon(get_icon("Search", "EditorIcons")); + remove_filter->set_right_icon(groups->get_theme_icon("Search", "EditorIcons")); remove_filter->set_clear_button_enabled(true); } break; } @@ -399,21 +399,21 @@ void GroupDialog::_bind_methods() { } GroupDialog::GroupDialog() { - set_custom_minimum_size(Size2(600, 400) * EDSCALE); + set_min_size(Size2(600, 400) * EDSCALE); scene_tree = SceneTree::get_singleton(); VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); - vbc->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + vbc->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); HBoxContainer *hbc = memnew(HBoxContainer); vbc->add_child(hbc); - hbc->set_v_size_flags(SIZE_EXPAND_FILL); + hbc->set_v_size_flags(Control::SIZE_EXPAND_FILL); VBoxContainer *vbc_left = memnew(VBoxContainer); hbc->add_child(vbc_left); - vbc_left->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_left->set_h_size_flags(Control::SIZE_EXPAND_FILL); Label *group_title = memnew(Label); group_title->set_text(TTR("Groups")); @@ -425,19 +425,19 @@ GroupDialog::GroupDialog() { groups->set_select_mode(Tree::SELECT_SINGLE); groups->set_allow_reselect(true); groups->set_allow_rmb_select(true); - groups->set_v_size_flags(SIZE_EXPAND_FILL); - groups->add_constant_override("draw_guides", 1); + groups->set_v_size_flags(Control::SIZE_EXPAND_FILL); + groups->add_theme_constant_override("draw_guides", 1); groups->connect("item_selected", callable_mp(this, &GroupDialog::_group_selected)); groups->connect("button_pressed", callable_mp(this, &GroupDialog::_delete_group_pressed)); groups->connect("item_edited", callable_mp(this, &GroupDialog::_group_renamed)); HBoxContainer *chbc = memnew(HBoxContainer); vbc_left->add_child(chbc); - chbc->set_h_size_flags(SIZE_EXPAND_FILL); + chbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_group_text = memnew(LineEdit); chbc->add_child(add_group_text); - add_group_text->set_h_size_flags(SIZE_EXPAND_FILL); + add_group_text->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_group_text->connect("text_entered", callable_mp(this, &GroupDialog::_add_group_pressed)); Button *add_group_button = memnew(Button); @@ -447,7 +447,7 @@ GroupDialog::GroupDialog() { VBoxContainer *vbc_add = memnew(VBoxContainer); hbc->add_child(vbc_add); - vbc_add->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_add->set_h_size_flags(Control::SIZE_EXPAND_FILL); Label *out_of_group_title = memnew(Label); out_of_group_title->set_text(TTR("Nodes Not in Group")); @@ -458,23 +458,23 @@ GroupDialog::GroupDialog() { nodes_to_add->set_hide_root(true); nodes_to_add->set_hide_folding(true); nodes_to_add->set_select_mode(Tree::SELECT_MULTI); - nodes_to_add->set_v_size_flags(SIZE_EXPAND_FILL); - nodes_to_add->add_constant_override("draw_guides", 1); + nodes_to_add->set_v_size_flags(Control::SIZE_EXPAND_FILL); + nodes_to_add->add_theme_constant_override("draw_guides", 1); HBoxContainer *add_filter_hbc = memnew(HBoxContainer); - add_filter_hbc->add_constant_override("separate", 0); + add_filter_hbc->add_theme_constant_override("separate", 0); vbc_add->add_child(add_filter_hbc); add_filter = memnew(LineEdit); - add_filter->set_h_size_flags(SIZE_EXPAND_FILL); + add_filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_filter->set_placeholder(TTR("Filter nodes")); add_filter_hbc->add_child(add_filter); add_filter->connect("text_changed", callable_mp(this, &GroupDialog::_add_filter_changed)); VBoxContainer *vbc_buttons = memnew(VBoxContainer); hbc->add_child(vbc_buttons); - vbc_buttons->set_h_size_flags(SIZE_SHRINK_CENTER); - vbc_buttons->set_v_size_flags(SIZE_SHRINK_CENTER); + vbc_buttons->set_h_size_flags(Control::SIZE_SHRINK_CENTER); + vbc_buttons->set_v_size_flags(Control::SIZE_SHRINK_CENTER); add_button = memnew(ToolButton); add_button->set_text(TTR("Add")); @@ -493,7 +493,7 @@ GroupDialog::GroupDialog() { VBoxContainer *vbc_remove = memnew(VBoxContainer); hbc->add_child(vbc_remove); - vbc_remove->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_remove->set_h_size_flags(Control::SIZE_EXPAND_FILL); Label *in_group_title = memnew(Label); in_group_title->set_text(TTR("Nodes in Group")); @@ -501,18 +501,18 @@ GroupDialog::GroupDialog() { nodes_to_remove = memnew(Tree); vbc_remove->add_child(nodes_to_remove); - nodes_to_remove->set_v_size_flags(SIZE_EXPAND_FILL); + nodes_to_remove->set_v_size_flags(Control::SIZE_EXPAND_FILL); nodes_to_remove->set_hide_root(true); nodes_to_remove->set_hide_folding(true); nodes_to_remove->set_select_mode(Tree::SELECT_MULTI); - nodes_to_remove->add_constant_override("draw_guides", 1); + nodes_to_remove->add_theme_constant_override("draw_guides", 1); HBoxContainer *remove_filter_hbc = memnew(HBoxContainer); - remove_filter_hbc->add_constant_override("separate", 0); + remove_filter_hbc->add_theme_constant_override("separate", 0); vbc_remove->add_child(remove_filter_hbc); remove_filter = memnew(LineEdit); - remove_filter->set_h_size_flags(SIZE_EXPAND_FILL); + remove_filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); remove_filter->set_placeholder(TTR("Filter nodes")); remove_filter_hbc->add_child(remove_filter); remove_filter->connect("text_changed", callable_mp(this, &GroupDialog::_remove_filter_changed)); @@ -524,11 +524,9 @@ GroupDialog::GroupDialog() { group_empty->set_autowrap(true); group_empty->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); nodes_to_remove->add_child(group_empty); - group_empty->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + group_empty->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); set_title(TTR("Group Editor")); - set_as_toplevel(true); - set_resizable(true); error = memnew(ConfirmationDialog); add_child(error); @@ -639,7 +637,7 @@ void GroupsEditor::update_tree() { TreeItem *item = tree->create_item(root); item->set_text(0, gi.name); if (can_be_deleted) { - item->add_button(0, get_icon("Remove", "EditorIcons"), 0); + item->add_button(0, get_theme_icon("Remove", "EditorIcons"), 0); } else { item->set_selectable(0, false); } @@ -669,7 +667,7 @@ GroupsEditor::GroupsEditor() { VBoxContainer *vbc = this; group_dialog = memnew(GroupDialog); - group_dialog->set_as_toplevel(true); + add_child(group_dialog); group_dialog->connect("group_edited", callable_mp(this, &GroupsEditor::update_tree)); @@ -682,7 +680,7 @@ GroupsEditor::GroupsEditor() { vbc->add_child(hbc); group_name = memnew(LineEdit); - group_name->set_h_size_flags(SIZE_EXPAND_FILL); + group_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(group_name); group_name->connect("text_entered", callable_mp(this, &GroupsEditor::_add_group)); @@ -693,11 +691,11 @@ GroupsEditor::GroupsEditor() { tree = memnew(Tree); tree->set_hide_root(true); - tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbc->add_child(tree); tree->connect("button_pressed", callable_mp(this, &GroupsEditor::_remove_group)); - tree->add_constant_override("draw_guides", 1); - add_constant_override("separation", 3 * EDSCALE); + tree->add_theme_constant_override("draw_guides", 1); + add_theme_constant_override("separation", 3 * EDSCALE); } GroupsEditor::~GroupsEditor() { diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 84c653bdea..40c7b3c75a 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -41,9 +41,9 @@ #include "scene/gui/tool_button.h" #include "scene/gui/tree.h" -class GroupDialog : public WindowDialog { +class GroupDialog : public AcceptDialog { - GDCLASS(GroupDialog, WindowDialog); + GDCLASS(GroupDialog, AcceptDialog); ConfirmationDialog *error; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index e2e68f0f41..23be42aaea 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -424,7 +424,7 @@ void ImportDock::_reimport_attempt() { if (need_restart) { label_warning->set_visible(used_in_resources); - reimport_confirm->popup_centered_minsize(); + reimport_confirm->popup_centered(); return; } @@ -492,13 +492,13 @@ void ImportDock::_notification(int p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - imported->add_style_override("normal", get_stylebox("normal", "LineEdit")); + imported->add_theme_style_override("normal", get_theme_stylebox("normal", "LineEdit")); } break; case NOTIFICATION_ENTER_TREE: { import_opts->edit(params); - label_warning->add_color_override("font_color", get_color("warning_color", "Editor")); + label_warning->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); } break; } } @@ -526,7 +526,7 @@ ImportDock::ImportDock() { set_name("Import"); imported = memnew(Label); - imported->add_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_stylebox("normal", "LineEdit")); + imported->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("normal", "LineEdit")); imported->set_clip_text(true); add_child(imported); HBoxContainer *hb = memnew(HBoxContainer); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 2729d9ecb5..916ebd27ab 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -140,7 +140,7 @@ void InspectorDock::_new_resource() { } void InspectorDock::_load_resource(const String &p_type) { - load_resource_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + load_resource_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); List<String> extensions; ResourceLoader::get_recognized_extensions_for_type(p_type, &extensions); @@ -214,7 +214,7 @@ void InspectorDock::_prepare_history() { history_menu->get_popup()->clear(); - Ref<Texture2D> base_icon = get_icon("Object", "EditorIcons"); + Ref<Texture2D> base_icon = get_theme_icon("Object", "EditorIcons"); Set<ObjectID> already; for (int i = editor_history->get_history_len() - 1; i >= history_to; i--) { @@ -317,7 +317,7 @@ void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Tran } void InspectorDock::_warning_pressed() { - warning_dialog->popup_centered_minsize(); + warning_dialog->popup_centered(); } Container *InspectorDock::get_addon_area() { @@ -328,15 +328,15 @@ void InspectorDock::_notification(int p_what) { switch (p_what) { case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { set_theme(editor->get_gui_base()->get_theme()); - resource_new_button->set_icon(get_icon("New", "EditorIcons")); - resource_load_button->set_icon(get_icon("Load", "EditorIcons")); - resource_save_button->set_icon(get_icon("Save", "EditorIcons")); - backward_button->set_icon(get_icon("Back", "EditorIcons")); - forward_button->set_icon(get_icon("Forward", "EditorIcons")); - history_menu->set_icon(get_icon("History", "EditorIcons")); - object_menu->set_icon(get_icon("Tools", "EditorIcons")); - warning->set_icon(get_icon("NodeWarning", "EditorIcons")); - warning->add_color_override("font_color", get_color("warning_color", "Editor")); + resource_new_button->set_icon(get_theme_icon("New", "EditorIcons")); + resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons")); + resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons")); + backward_button->set_icon(get_theme_icon("Back", "EditorIcons")); + forward_button->set_icon(get_theme_icon("Forward", "EditorIcons")); + history_menu->set_icon(get_theme_icon("History", "EditorIcons")); + object_menu->set_icon(get_theme_icon("Tools", "EditorIcons")); + warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons")); + warning->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); } break; } } @@ -435,7 +435,7 @@ void InspectorDock::update(Object *p_object) { p->add_separator(); p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique", TTR("Make Sub-Resources Unique")), OBJECT_UNIQUE_RESOURCES); p->add_separator(); - p->add_icon_shortcut(get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP); + p->add_icon_shortcut(get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("property_editor/open_help", TTR("Open in Help")), OBJECT_REQUEST_HELP); } List<MethodInfo> methods; @@ -496,21 +496,21 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { resource_new_button = memnew(ToolButton); resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it.")); - resource_new_button->set_icon(get_icon("New", "EditorIcons")); + resource_new_button->set_icon(get_theme_icon("New", "EditorIcons")); general_options_hb->add_child(resource_new_button); resource_new_button->connect("pressed", callable_mp(this, &InspectorDock::_new_resource)); resource_new_button->set_focus_mode(Control::FOCUS_NONE); resource_load_button = memnew(ToolButton); resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it.")); - resource_load_button->set_icon(get_icon("Load", "EditorIcons")); + resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons")); general_options_hb->add_child(resource_load_button); resource_load_button->connect("pressed", callable_mp(this, &InspectorDock::_open_resource_selector)); resource_load_button->set_focus_mode(Control::FOCUS_NONE); resource_save_button = memnew(MenuButton); resource_save_button->set_tooltip(TTR("Save the currently edited resource.")); - resource_save_button->set_icon(get_icon("Save", "EditorIcons")); + resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons")); general_options_hb->add_child(resource_save_button); resource_save_button->get_popup()->add_item(TTR("Save"), RESOURCE_SAVE); resource_save_button->get_popup()->add_item(TTR("Save As..."), RESOURCE_SAVE_AS); @@ -522,7 +522,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { backward_button = memnew(ToolButton); general_options_hb->add_child(backward_button); - backward_button->set_icon(get_icon("Back", "EditorIcons")); + backward_button->set_icon(get_theme_icon("Back", "EditorIcons")); backward_button->set_flat(true); backward_button->set_tooltip(TTR("Go to the previous edited object in history.")); backward_button->set_disabled(true); @@ -530,7 +530,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { forward_button = memnew(ToolButton); general_options_hb->add_child(forward_button); - forward_button->set_icon(get_icon("Forward", "EditorIcons")); + forward_button->set_icon(get_theme_icon("Forward", "EditorIcons")); forward_button->set_flat(true); forward_button->set_tooltip(TTR("Go to the next edited object in history.")); forward_button->set_disabled(true); @@ -538,9 +538,9 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { history_menu = memnew(MenuButton); history_menu->set_tooltip(TTR("History of recently edited objects.")); - history_menu->set_icon(get_icon("History", "EditorIcons")); + history_menu->set_icon(get_theme_icon("History", "EditorIcons")); general_options_hb->add_child(history_menu); - history_menu->connect("about_to_show", callable_mp(this, &InspectorDock::_prepare_history)); + history_menu->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_history)); history_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_select_history)); HBoxContainer *node_info_hb = memnew(HBoxContainer); @@ -551,7 +551,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { node_info_hb->add_child(editor_path); object_menu = memnew(MenuButton); - object_menu->set_icon(get_icon("Tools", "EditorIcons")); + object_menu->set_icon(get_theme_icon("Tools", "EditorIcons")); node_info_hb->add_child(object_menu); object_menu->set_tooltip(TTR("Object properties.")); object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option)); @@ -564,15 +564,15 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { search = memnew(LineEdit); search->set_h_size_flags(Control::SIZE_EXPAND_FILL); search->set_placeholder(TTR("Filter properties")); - search->set_right_icon(get_icon("Search", "EditorIcons")); + search->set_right_icon(get_theme_icon("Search", "EditorIcons")); search->set_clear_button_enabled(true); add_child(search); warning = memnew(Button); add_child(warning); warning->set_text(TTR("Changes may be lost!")); - warning->set_icon(get_icon("NodeWarning", "EditorIcons")); - warning->add_color_override("font_color", get_color("warning_color", "Editor")); + warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons")); + warning->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); warning->set_clip_text(true); warning->hide(); warning->connect("pressed", callable_mp(this, &InspectorDock::_warning_pressed)); diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index 3013406152..0c511e4819 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -55,8 +55,8 @@ void NodeDock::_bind_methods() { void NodeDock::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - connections_button->set_icon(get_icon("Signals", "EditorIcons")); - groups_button->set_icon(get_icon("Groups", "EditorIcons")); + connections_button->set_icon(get_theme_icon("Signals", "EditorIcons")); + groups_button->set_icon(get_theme_icon("Groups", "EditorIcons")); } } diff --git a/editor/pane_drag.cpp b/editor/pane_drag.cpp index b143f86ada..ce90fa94dc 100644 --- a/editor/pane_drag.cpp +++ b/editor/pane_drag.cpp @@ -45,7 +45,7 @@ void PaneDrag::_notification(int p_what) { case NOTIFICATION_DRAW: { - Ref<Texture2D> icon = mouse_over ? get_icon("PaneDragHover", "EditorIcons") : get_icon("PaneDrag", "EditorIcons"); + Ref<Texture2D> icon = mouse_over ? get_theme_icon("PaneDragHover", "EditorIcons") : get_theme_icon("PaneDrag", "EditorIcons"); if (!icon.is_null()) icon->draw(get_canvas_item(), Point2(0, 0)); @@ -62,7 +62,7 @@ void PaneDrag::_notification(int p_what) { } Size2 PaneDrag::get_minimum_size() const { - Ref<Texture2D> icon = get_icon("PaneDrag", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon("PaneDrag", "EditorIcons"); if (!icon.is_null()) return icon->get_size(); return Size2(); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 1e7c625abb..4317a5e80f 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -131,14 +131,15 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { void PluginConfigDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (is_visible()) { + name_edit->grab_focus(); + } + } break; case NOTIFICATION_READY: { connect("confirmed", callable_mp(this, &PluginConfigDialog::_on_confirmed)); get_cancel()->connect("pressed", callable_mp(this, &PluginConfigDialog::_on_cancelled)); } break; - - case NOTIFICATION_POST_POPUP: { - name_edit->grab_focus(); - } break; } } diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 8d5444db73..e3e9eae31a 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -204,9 +204,9 @@ void AbstractPolygon2DEditor::_notification(int p_what) { disable_polygon_editing(false, String()); - button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); - button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); - button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons")); + button_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); + button_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); + button_delete->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); button_edit->set_pressed(true); get_tree()->connect("node_removed", callable_mp(this, &AbstractPolygon2DEditor::_node_removed)); @@ -310,7 +310,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { create_resource->set_text(String("No polygon resource on this node.\nCreate and assign one?")); - create_resource->popup_centered_minsize(); + create_resource->popup_centered(); } return (mb.is_valid() && mb->get_button_index() == 1); } @@ -573,7 +573,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); // All polygon points are sharp, so use the sharp handle icon - const Ref<Texture2D> handle = get_icon("EditorPathSharpHandle", "EditorIcons"); + const Ref<Texture2D> handle = get_theme_icon("EditorPathSharpHandle", "EditorIcons"); const Vertex active_point = get_active_point(); const int n_polygons = _get_polygon_count(); @@ -651,7 +651,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl p_overlay->draw_texture(handle, point - handle->get_size() * 0.5, modulate); if (vertex == hover_point) { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); String num = String::num(vertex.vertex); Size2 num_size = font->get_string_size(num); p_overlay->draw_string(font, point - num_size * 0.5, num, Color(1.0, 1.0, 1.0, 0.5)); @@ -661,7 +661,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl if (edge_point.valid()) { - Ref<Texture2D> add_handle = get_icon("EditorHandleAdd", "EditorIcons"); + Ref<Texture2D> add_handle = get_theme_icon("EditorHandleAdd", "EditorIcons"); p_overlay->draw_texture(add_handle, edge_point.pos - add_handle->get_size() * 0.5); } } diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 7916ac71ea..86c43ea9ab 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -73,7 +73,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven ap->get_animation_list(&names); for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - animations_menu->add_icon_item(get_icon("Animation", "EditorIcons"), E->get()); + animations_menu->add_icon_item(get_theme_icon("Animation", "EditorIcons"), E->get()); animations_to_add.push_back(E->get()); } } @@ -97,7 +97,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven menu->add_separator(); menu->add_item(TTR("Load..."), MENU_LOAD_FILE); - menu->set_global_position(blend_space_draw->get_global_transform().xform(mb->get_position())); + menu->set_position(blend_space_draw->get_screen_transform().xform(mb->get_position())); menu->popup(); add_point_pos = (mb->get_position() / blend_space_draw->get_size()).x; @@ -197,18 +197,18 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven void AnimationNodeBlendSpace1DEditor::_blend_space_draw() { - Color linecolor = get_color("font_color", "Label"); + Color linecolor = get_theme_color("font_color", "Label"); Color linecolor_soft = linecolor; linecolor_soft.a *= 0.5; - Ref<Font> font = get_font("font", "Label"); - Ref<Texture2D> icon = get_icon("KeyValue", "EditorIcons"); - Ref<Texture2D> icon_selected = get_icon("KeySelected", "EditorIcons"); + Ref<Font> font = get_theme_font("font", "Label"); + Ref<Texture2D> icon = get_theme_icon("KeyValue", "EditorIcons"); + Ref<Texture2D> icon_selected = get_theme_icon("KeySelected", "EditorIcons"); Size2 s = blend_space_draw->get_size(); if (blend_space_draw->has_focus()) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); blend_space_draw->draw_rect(Rect2(Point2(), s), color, false); } @@ -280,7 +280,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() { { Color color; if (tool_blend->is_pressed()) { - color = get_color("accent_color", "Editor"); + color = get_theme_color("accent_color", "Editor"); } else { color = linecolor; color.a *= 0.5; @@ -532,15 +532,15 @@ void AnimationNodeBlendSpace1DEditor::_open_editor() { void AnimationNodeBlendSpace1DEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - error_panel->add_style_override("panel", get_stylebox("bg", "Tree")); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); - panel->add_style_override("panel", get_stylebox("bg", "Tree")); - tool_blend->set_icon(get_icon("EditPivot", "EditorIcons")); - tool_select->set_icon(get_icon("ToolSelect", "EditorIcons")); - tool_create->set_icon(get_icon("EditKey", "EditorIcons")); - tool_erase->set_icon(get_icon("Remove", "EditorIcons")); - snap->set_icon(get_icon("SnapGrid", "EditorIcons")); - open_editor->set_icon(get_icon("Edit", "EditorIcons")); + error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); + panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + tool_blend->set_icon(get_theme_icon("EditPivot", "EditorIcons")); + tool_select->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_create->set_icon(get_theme_icon("EditKey", "EditorIcons")); + tool_erase->set_icon(get_theme_icon("Remove", "EditorIcons")); + snap->set_icon(get_theme_icon("SnapGrid", "EditorIcons")); + open_editor->set_icon(get_theme_icon("Edit", "EditorIcons")); } if (p_what == NOTIFICATION_PROCESS) { @@ -735,7 +735,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { open_file = memnew(EditorFileDialog); add_child(open_file); open_file->set_title(TTR("Open Animation Node")); - open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_file_opened)); undo_redo = EditorNode::get_undo_redo(); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 663f2dde05..843beacfd6 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -30,9 +30,9 @@ #include "animation_blend_space_2d_editor.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" #include "core/math/delaunay.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_scale.h" @@ -40,7 +40,7 @@ #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" bool AnimationNodeBlendSpace2DEditor::can_edit(const Ref<AnimationNode> &p_node) { @@ -100,7 +100,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven List<StringName> names; ap->get_animation_list(&names); for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - animations_menu->add_icon_item(get_icon("Animation", "EditorIcons"), E->get()); + animations_menu->add_icon_item(get_theme_icon("Animation", "EditorIcons"), E->get()); animations_to_add.push_back(E->get()); } } @@ -124,7 +124,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven menu->add_separator(); menu->add_item(TTR("Load..."), MENU_LOAD_FILE); - menu->set_global_position(blend_space_draw->get_global_transform().xform(mb->get_position())); + menu->set_position(blend_space_draw->get_screen_transform().xform(mb->get_position())); menu->popup(); add_point_pos = (mb->get_position() / blend_space_draw->get_size()); add_point_pos.y = 1.0 - add_point_pos.y; @@ -406,17 +406,17 @@ void AnimationNodeBlendSpace2DEditor::_tool_switch(int p_tool) { void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { - Color linecolor = get_color("font_color", "Label"); + Color linecolor = get_theme_color("font_color", "Label"); Color linecolor_soft = linecolor; linecolor_soft.a *= 0.5; - Ref<Font> font = get_font("font", "Label"); - Ref<Texture2D> icon = get_icon("KeyValue", "EditorIcons"); - Ref<Texture2D> icon_selected = get_icon("KeySelected", "EditorIcons"); + Ref<Font> font = get_theme_font("font", "Label"); + Ref<Texture2D> icon = get_theme_icon("KeyValue", "EditorIcons"); + Ref<Texture2D> icon_selected = get_theme_icon("KeySelected", "EditorIcons"); Size2 s = blend_space_draw->get_size(); if (blend_space_draw->has_focus()) { - Color color = get_color("accent_color", "Editor"); + Color color = get_theme_color("accent_color", "Editor"); blend_space_draw->draw_rect(Rect2(Point2(), s), color, false); } blend_space_draw->draw_line(Point2(1, 0), Point2(1, s.height - 1), linecolor); @@ -502,7 +502,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { Color color; if (i == selected_triangle) { - color = get_color("accent_color", "Editor"); + color = get_theme_color("accent_color", "Editor"); color.a *= 0.5; } else { color = linecolor; @@ -563,7 +563,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { { Color color; if (tool_blend->is_pressed()) { - color = get_color("accent_color", "Editor"); + color = get_theme_color("accent_color", "Editor"); } else { color = linecolor; color.a *= 0.5; @@ -754,21 +754,21 @@ void AnimationNodeBlendSpace2DEditor::_edit_point_pos(double) { void AnimationNodeBlendSpace2DEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - error_panel->add_style_override("panel", get_stylebox("bg", "Tree")); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); - panel->add_style_override("panel", get_stylebox("bg", "Tree")); - tool_blend->set_icon(get_icon("EditPivot", "EditorIcons")); - tool_select->set_icon(get_icon("ToolSelect", "EditorIcons")); - tool_create->set_icon(get_icon("EditKey", "EditorIcons")); - tool_triangle->set_icon(get_icon("ToolTriangle", "EditorIcons")); - tool_erase->set_icon(get_icon("Remove", "EditorIcons")); - snap->set_icon(get_icon("SnapGrid", "EditorIcons")); - open_editor->set_icon(get_icon("Edit", "EditorIcons")); - auto_triangles->set_icon(get_icon("AutoTriangle", "EditorIcons")); + error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); + panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + tool_blend->set_icon(get_theme_icon("EditPivot", "EditorIcons")); + tool_select->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_create->set_icon(get_theme_icon("EditKey", "EditorIcons")); + tool_triangle->set_icon(get_theme_icon("ToolTriangle", "EditorIcons")); + tool_erase->set_icon(get_theme_icon("Remove", "EditorIcons")); + snap->set_icon(get_theme_icon("SnapGrid", "EditorIcons")); + open_editor->set_icon(get_theme_icon("Edit", "EditorIcons")); + auto_triangles->set_icon(get_theme_icon("AutoTriangle", "EditorIcons")); interpolation->clear(); - interpolation->add_icon_item(get_icon("TrackContinuous", "EditorIcons"), "", 0); - interpolation->add_icon_item(get_icon("TrackDiscrete", "EditorIcons"), "", 1); - interpolation->add_icon_item(get_icon("TrackCapture", "EditorIcons"), "", 2); + interpolation->add_icon_item(get_theme_icon("TrackContinuous", "EditorIcons"), "", 0); + interpolation->add_icon_item(get_theme_icon("TrackDiscrete", "EditorIcons"), "", 1); + interpolation->add_icon_item(get_theme_icon("TrackCapture", "EditorIcons"), "", 2); } if (p_what == NOTIFICATION_PROCESS) { @@ -1042,7 +1042,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { open_file = memnew(EditorFileDialog); add_child(open_file); open_file->set_title(TTR("Open Animation Node")); - open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_file_opened)); undo_redo = EditorNode::get_undo_redo(); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index e79909fae1..03b48f1c15 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -30,8 +30,8 @@ #include "animation_blend_tree_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_inspector.h" @@ -40,7 +40,7 @@ #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/gui/progress_bar.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void AnimationNodeBlendTreeEditor::add_custom_type(const String &p_name, const Ref<Script> &p_script) { @@ -145,7 +145,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { name->set_text(E->get()); name->set_expand_to_text_length(true); node->add_child(name); - node->set_slot(0, false, 0, Color(), true, 0, get_color("font_color", "Label")); + node->set_slot(0, false, 0, Color(), true, 0, get_theme_color("font_color", "Label")); name->connect("text_entered", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed), varray(agnode)); name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED); base = 1; @@ -157,7 +157,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { Label *in_name = memnew(Label); node->add_child(in_name); in_name->set_text(agnode->get_input_name(i)); - node->set_slot(base + i, true, 0, get_color("font_color", "Label"), false, 0, Color()); + node->set_slot(base + i, true, 0, get_theme_color("font_color", "Label"), false, 0, Color()); } List<PropertyInfo> pinfo; @@ -185,7 +185,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { node->add_child(memnew(HSeparator)); Button *open_in_editor = memnew(Button); open_in_editor->set_text(TTR("Open Editor")); - open_in_editor->set_icon(get_icon("Edit", "EditorIcons")); + open_in_editor->set_icon(get_theme_icon("Edit", "EditorIcons")); node->add_child(open_in_editor); open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor), varray(E->get()), CONNECT_DEFERRED); open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER); @@ -196,7 +196,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { node->add_child(memnew(HSeparator)); Button *edit_filters = memnew(Button); edit_filters->set_text(TTR("Edit Filters")); - edit_filters->set_icon(get_icon("AnimationFilter", "EditorIcons")); + edit_filters->set_icon(get_theme_icon("AnimationFilter", "EditorIcons")); node->add_child(edit_filters); edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters), varray(E->get()), CONNECT_DEFERRED); edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER); @@ -207,7 +207,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { MenuButton *mb = memnew(MenuButton); mb->set_text(anim->get_animation()); - mb->set_icon(get_icon("Animation", "EditorIcons")); + mb->set_icon(get_theme_icon("Animation", "EditorIcons")); Array options; node->add_child(memnew(HSeparator)); @@ -242,16 +242,16 @@ void AnimationNodeBlendTreeEditor::_update_graph() { } if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Ref<StyleBoxFlat> sb = node->get_stylebox("frame", "GraphNode"); + Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); Color c = sb->get_border_color(); Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); mono_color.a = 0.85; c = mono_color; - node->add_color_override("title_color", c); + node->add_theme_color_override("title_color", c); c.a = 0.7; - node->add_color_override("close_color", c); - node->add_color_override("resizer_color", c); + node->add_theme_color_override("close_color", c); + node->add_theme_color_override("resizer_color", c); } } @@ -643,7 +643,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano ti->set_text(0, F->get()); ti->set_selectable(0, false); ti->set_editable(0, false); - ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); } else { ti = parenthood[accum]; } @@ -654,7 +654,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); ti->set_checked(0, anode->is_path_filtered(path)); - ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, path); } else { @@ -705,7 +705,7 @@ void AnimationNodeBlendTreeEditor::_edit_filters(const String &p_which) { if (!_update_filters(anode)) return; - filter_dialog->popup_centered_minsize(Size2(500, 500) * EDSCALE); + filter_dialog->popup_centered(Size2(500, 500) * EDSCALE); } void AnimationNodeBlendTreeEditor::_removed_from_graph() { @@ -718,8 +718,8 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - error_panel->add_style_override("panel", get_stylebox("bg", "Tree")); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); + error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) _update_graph(); @@ -931,7 +931,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); add_node->get_popup()->connect("id_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_add_node)); - add_node->connect("about_to_show", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu)); + add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu)); add_options.push_back(AddOption("Animation", "AnimationNodeAnimation")); add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot")); @@ -975,7 +975,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { open_file = memnew(EditorFileDialog); add_child(open_file); open_file->set_title(TTR("Open Animation Node")); - open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); open_file->connect("file_selected", callable_mp(this, &AnimationNodeBlendTreeEditor::_file_opened)); undo_redo = EditorNode::get_undo_redo(); } diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index af12335a27..4b75f09cf5 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "animation_player_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/animation_track_editor.h" @@ -40,7 +40,7 @@ #include "editor/editor_settings.h" #include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning. #include "editor/plugins/spatial_editor_plugin.h" // For onion skinning. -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "servers/visual_server.h" void AnimationPlayerEditor::_node_removed(Node *p_node) { @@ -105,33 +105,33 @@ void AnimationPlayerEditor::_notification(int p_what) { get_tree()->connect("node_removed", callable_mp(this, &AnimationPlayerEditor::_node_removed)); - add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel")); + add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("panel", "Panel")); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel")); + add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("panel", "Panel")); } break; case NOTIFICATION_THEME_CHANGED: { - autoplay->set_icon(get_icon("AutoPlay", "EditorIcons")); + autoplay->set_icon(get_theme_icon("AutoPlay", "EditorIcons")); - play->set_icon(get_icon("PlayStart", "EditorIcons")); - play_from->set_icon(get_icon("Play", "EditorIcons")); - play_bw->set_icon(get_icon("PlayStartBackwards", "EditorIcons")); - play_bw_from->set_icon(get_icon("PlayBackwards", "EditorIcons")); + play->set_icon(get_theme_icon("PlayStart", "EditorIcons")); + play_from->set_icon(get_theme_icon("Play", "EditorIcons")); + play_bw->set_icon(get_theme_icon("PlayStartBackwards", "EditorIcons")); + play_bw_from->set_icon(get_theme_icon("PlayBackwards", "EditorIcons")); - autoplay_icon = get_icon("AutoPlay", "EditorIcons"); - stop->set_icon(get_icon("Stop", "EditorIcons")); + autoplay_icon = get_theme_icon("AutoPlay", "EditorIcons"); + stop->set_icon(get_theme_icon("Stop", "EditorIcons")); - onion_toggle->set_icon(get_icon("Onion", "EditorIcons")); - onion_skinning->set_icon(get_icon("GuiTabMenu", "EditorIcons")); + onion_toggle->set_icon(get_theme_icon("Onion", "EditorIcons")); + onion_skinning->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); - pin->set_icon(get_icon("Pin", "EditorIcons")); + pin->set_icon(get_theme_icon("Pin", "EditorIcons")); - tool_anim->add_style_override("normal", get_stylebox("normal", "Button")); - track_editor->get_edit_menu()->add_style_override("normal", get_stylebox("normal", "Button")); + tool_anim->add_theme_style_override("normal", get_theme_stylebox("normal", "Button")); + track_editor->get_edit_menu()->add_theme_style_override("normal", get_theme_stylebox("normal", "Button")); -#define ITEM_ICON(m_item, m_icon) tool_anim->get_popup()->set_item_icon(tool_anim->get_popup()->get_item_index(m_item), get_icon(m_icon, "EditorIcons")) +#define ITEM_ICON(m_item, m_icon) tool_anim->get_popup()->set_item_icon(tool_anim->get_popup()->get_item_index(m_item), get_theme_icon(m_icon, "EditorIcons")) ITEM_ICON(TOOL_NEW_ANIM, "New"); ITEM_ICON(TOOL_LOAD_ANIM, "Load"); @@ -349,7 +349,7 @@ void AnimationPlayerEditor::_animation_rename() { } void AnimationPlayerEditor::_animation_load() { ERR_FAIL_COND(!player); - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file->clear_filters(); List<String> extensions; @@ -392,7 +392,7 @@ void AnimationPlayerEditor::_animation_save(const Ref<Resource> &p_resource) { void AnimationPlayerEditor::_animation_save_as(const Ref<Resource> &p_resource) { - file->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); List<String> extensions; ResourceSaver::get_recognized_extensions(p_resource, &extensions); @@ -434,7 +434,7 @@ void AnimationPlayerEditor::_animation_remove() { return; delete_dialog->set_text(TTR("Delete Animation?")); - delete_dialog->popup_centered_minsize(); + delete_dialog->popup_centered(); } void AnimationPlayerEditor::_animation_remove_confirmed() { @@ -488,7 +488,7 @@ double AnimationPlayerEditor::_get_editor_step() const { ERR_FAIL_COND_V(!anim.is_valid(), 0.0); // Use more precise snapping when holding Shift - return Input::get_singleton()->is_key_pressed(KEY_SHIFT) ? anim->get_step() * 0.25 : anim->get_step(); + return InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT) ? anim->get_step() * 0.25 : anim->get_step(); } return 0.0; @@ -501,7 +501,7 @@ void AnimationPlayerEditor::_animation_name_edited() { String new_name = name->get_text(); if (new_name == "" || new_name.find(":") != -1 || new_name.find("/") != -1) { error_dialog->set_text(TTR("Invalid animation name!")); - error_dialog->popup_centered_minsize(); + error_dialog->popup_centered(); return; } @@ -512,7 +512,7 @@ void AnimationPlayerEditor::_animation_name_edited() { if (player->has_animation(new_name)) { error_dialog->set_text(TTR("Animation name already exists!")); - error_dialog->popup_centered_minsize(); + error_dialog->popup_centered(); return; } @@ -1058,7 +1058,7 @@ void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) { if (player == p_pl && is_visible_in_tree()) { _update_player(); - if (blend_editor.dialog->is_visible_in_tree()) + if (blend_editor.dialog->is_visible()) _animation_blend(); // Update. } } @@ -1152,7 +1152,7 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { if (!animation->get_item_count()) { error_dialog->set_text(TTR("No animation to copy!")); - error_dialog->popup_centered_minsize(); + error_dialog->popup_centered(); return; } @@ -1165,7 +1165,7 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { Ref<Animation> anim2 = EditorSettings::get_singleton()->get_resource_clipboard(); if (!anim2.is_valid()) { error_dialog->set_text(TTR("No animation resource on clipboard!")); - error_dialog->popup_centered_minsize(); + error_dialog->popup_centered(); return; } @@ -1195,7 +1195,7 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { if (!animation->get_item_count()) { error_dialog->set_text(TTR("No animation to edit!")); - error_dialog->popup_centered_minsize(); + error_dialog->popup_centered(); return; } @@ -1420,7 +1420,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { // Tweak the root viewport to ensure it's rendered before our target. RID root_vp = get_tree()->get_root()->get_viewport_rid(); - Rect2 root_vp_screen_rect = get_tree()->get_root()->get_attach_to_screen_rect(); + Rect2 root_vp_screen_rect = Rect2(Vector2(), get_tree()->get_root()->get_size()); VS::get_singleton()->viewport_attach_to_screen(root_vp, Rect2()); VS::get_singleton()->viewport_set_update_mode(root_vp, VS::VIEWPORT_UPDATE_ALWAYS); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index cae959e1f4..8ff8c92f4d 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -30,9 +30,9 @@ #include "animation_state_machine_editor.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" #include "core/math/delaunay.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_scale.h" @@ -40,7 +40,7 @@ #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" bool AnimationNodeStateMachineEditor::can_edit(const Ref<AnimationNode> &p_node) { @@ -97,7 +97,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv List<StringName> names; ap->get_animation_list(&names); for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - animations_menu->add_icon_item(get_icon("Animation", "EditorIcons"), E->get()); + animations_menu->add_icon_item(get_theme_icon("Animation", "EditorIcons"), E->get()); animations_to_add.push_back(E->get()); } } @@ -121,7 +121,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv menu->add_separator(); menu->add_item(TTR("Load..."), MENU_LOAD_FILE); - menu->set_global_position(state_machine_draw->get_global_transform().xform(mb->get_position())); + menu->set_position(state_machine_draw->get_screen_transform().xform(mb->get_position())); menu->popup(); add_node_pos = mb->get_position() / EDSCALE + state_machine->get_graph_offset(); } @@ -149,16 +149,16 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv if (node_rects[i].name.has_point(mb->get_position())) { //edit name - Ref<StyleBox> line_sb = get_stylebox("normal", "LineEdit"); + Ref<StyleBox> line_sb = get_theme_stylebox("normal", "LineEdit"); Rect2 edit_rect = node_rects[i].name; edit_rect.position -= line_sb->get_offset(); edit_rect.size += line_sb->get_minimum_size(); - name_edit->set_global_position(state_machine_draw->get_global_transform().xform(edit_rect.position)); - name_edit->set_size(edit_rect.size); + name_edit_popup->set_position(state_machine_draw->get_screen_transform().xform(edit_rect.position)); + name_edit_popup->set_size(edit_rect.size); name_edit->set_text(node_rects[i].node_name); - name_edit->show_modal(); + name_edit_popup->popup(); name_edit->grab_focus(); name_edit->select_all(); @@ -504,9 +504,9 @@ void AnimationNodeStateMachineEditor::_add_animation_type(int p_index) { void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, const Vector2 &p_to, AnimationNodeStateMachineTransition::SwitchMode p_mode, bool p_enabled, bool p_selected, bool p_travel, bool p_auto_advance) { - Color linecolor = get_color("font_color", "Label"); + Color linecolor = get_theme_color("font_color", "Label"); Color icon_color(1, 1, 1); - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); if (!p_enabled) { linecolor.a *= 0.2; @@ -515,12 +515,12 @@ void AnimationNodeStateMachineEditor::_connection_draw(const Vector2 &p_from, co } Ref<Texture2D> icons[6] = { - get_icon("TransitionImmediateBig", "EditorIcons"), - get_icon("TransitionSyncBig", "EditorIcons"), - get_icon("TransitionEndBig", "EditorIcons"), - get_icon("TransitionImmediateAutoBig", "EditorIcons"), - get_icon("TransitionSyncAutoBig", "EditorIcons"), - get_icon("TransitionEndAutoBig", "EditorIcons") + get_theme_icon("TransitionImmediateBig", "EditorIcons"), + get_theme_icon("TransitionSyncBig", "EditorIcons"), + get_theme_icon("TransitionEndBig", "EditorIcons"), + get_theme_icon("TransitionImmediateAutoBig", "EditorIcons"), + get_theme_icon("TransitionSyncAutoBig", "EditorIcons"), + get_theme_icon("TransitionEndAutoBig", "EditorIcons") }; if (p_selected) { @@ -573,18 +573,18 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { Ref<AnimationNodeStateMachinePlayback> playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + "playback"); - Ref<StyleBox> style = get_stylebox("state_machine_frame", "GraphNode"); - Ref<StyleBox> style_selected = get_stylebox("state_machine_selectedframe", "GraphNode"); + Ref<StyleBox> style = get_theme_stylebox("state_machine_frame", "GraphNode"); + Ref<StyleBox> style_selected = get_theme_stylebox("state_machine_selectedframe", "GraphNode"); - Ref<Font> font = get_font("title_font", "GraphNode"); - Color font_color = get_color("title_color", "GraphNode"); - Ref<Texture2D> play = get_icon("Play", "EditorIcons"); - Ref<Texture2D> auto_play = get_icon("AutoPlay", "EditorIcons"); - Ref<Texture2D> edit = get_icon("Edit", "EditorIcons"); - Color accent = get_color("accent_color", "Editor"); - Color linecolor = get_color("font_color", "Label"); + Ref<Font> font = get_theme_font("title_font", "GraphNode"); + Color font_color = get_theme_color("title_color", "GraphNode"); + Ref<Texture2D> play = get_theme_icon("Play", "EditorIcons"); + Ref<Texture2D> auto_play = get_theme_icon("AutoPlay", "EditorIcons"); + Ref<Texture2D> edit = get_theme_icon("Edit", "EditorIcons"); + Color accent = get_theme_color("accent_color", "Editor"); + Color linecolor = get_theme_color("font_color", "Label"); linecolor.a *= 0.3; - Ref<StyleBox> playing_overlay = get_stylebox("position", "GraphNode"); + Ref<StyleBox> playing_overlay = get_theme_stylebox("position", "GraphNode"); bool playing = false; StringName current; @@ -686,7 +686,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { _connection_draw(from, to, AnimationNodeStateMachineTransition::SwitchMode(transition_mode->get_selected()), true, false, false, false); } - Ref<Texture2D> tr_reference_icon = get_icon("TransitionImmediateBig", "EditorIcons"); + Ref<Texture2D> tr_reference_icon = get_theme_icon("TransitionImmediateBig", "EditorIcons"); float tr_bidi_offset = int(tr_reference_icon->get_height() * 0.8); //draw transition lines @@ -879,7 +879,7 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() { float pos = CLAMP(play_pos, 0, len); float c = pos / len; - Color fg = get_color("font_color", "Label"); + Color fg = get_theme_color("font_color", "Label"); Color bg = fg; bg.a *= 0.3; @@ -905,26 +905,26 @@ void AnimationNodeStateMachineEditor::_update_graph() { void AnimationNodeStateMachineEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - error_panel->add_style_override("panel", get_stylebox("bg", "Tree")); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); - panel->add_style_override("panel", get_stylebox("bg", "Tree")); + error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); + panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); - tool_select->set_icon(get_icon("ToolSelect", "EditorIcons")); - tool_create->set_icon(get_icon("ToolAddNode", "EditorIcons")); - tool_connect->set_icon(get_icon("ToolConnect", "EditorIcons")); + tool_select->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_create->set_icon(get_theme_icon("ToolAddNode", "EditorIcons")); + tool_connect->set_icon(get_theme_icon("ToolConnect", "EditorIcons")); transition_mode->clear(); - transition_mode->add_icon_item(get_icon("TransitionImmediate", "EditorIcons"), TTR("Immediate")); - transition_mode->add_icon_item(get_icon("TransitionSync", "EditorIcons"), TTR("Sync")); - transition_mode->add_icon_item(get_icon("TransitionEnd", "EditorIcons"), TTR("At End")); + transition_mode->add_icon_item(get_theme_icon("TransitionImmediate", "EditorIcons"), TTR("Immediate")); + transition_mode->add_icon_item(get_theme_icon("TransitionSync", "EditorIcons"), TTR("Sync")); + transition_mode->add_icon_item(get_theme_icon("TransitionEnd", "EditorIcons"), TTR("At End")); - tool_erase->set_icon(get_icon("Remove", "EditorIcons")); - tool_autoplay->set_icon(get_icon("AutoPlay", "EditorIcons")); - tool_end->set_icon(get_icon("AutoEnd", "EditorIcons")); + tool_erase->set_icon(get_theme_icon("Remove", "EditorIcons")); + tool_autoplay->set_icon(get_theme_icon("AutoPlay", "EditorIcons")); + tool_end->set_icon(get_theme_icon("AutoEnd", "EditorIcons")); play_mode->clear(); - play_mode->add_icon_item(get_icon("PlayTravel", "EditorIcons"), TTR("Travel")); - play_mode->add_icon_item(get_icon("Play", "EditorIcons"), TTR("Immediate")); + play_mode->add_icon_item(get_theme_icon("PlayTravel", "EditorIcons"), TTR("Travel")); + play_mode->add_icon_item(get_theme_icon("Play", "EditorIcons"), TTR("Immediate")); } if (p_what == NOTIFICATION_PROCESS) { @@ -1110,7 +1110,7 @@ void AnimationNodeStateMachineEditor::_name_edited(const String &p_text) { undo_redo->add_do_method(this, "_update_graph"); undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); - name_edit->hide(); + name_edit_popup->hide(); updating = false; state_machine_draw->update(); @@ -1357,17 +1357,19 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { animations_menu->set_name("animations"); animations_menu->connect("index_pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_add_animation_type)); + name_edit_popup = memnew(Popup); + add_child(name_edit_popup); name_edit = memnew(LineEdit); - state_machine_draw->add_child(name_edit); - name_edit->hide(); + name_edit_popup->add_child(name_edit); + name_edit->set_anchors_and_margins_preset(PRESET_WIDE); + name_edit_popup->add_child(name_edit); name_edit->connect("text_entered", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited)); name_edit->connect("focus_exited", callable_mp(this, &AnimationNodeStateMachineEditor::_name_edited_focus_out)); - name_edit->set_as_toplevel(true); open_file = memnew(EditorFileDialog); add_child(open_file); open_file->set_title(TTR("Open Animation Node")); - open_file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + open_file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); open_file->connect("file_selected", callable_mp(this, &AnimationNodeStateMachineEditor::_file_opened)); undo_redo = EditorNode::get_undo_redo(); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 132e66b28d..5c4fc87df5 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -50,6 +50,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { ToolButton *tool_select; ToolButton *tool_create; ToolButton *tool_connect; + Popup *name_edit_popup; LineEdit *name_edit; HBoxContainer *tool_erase_hb; diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index c9706a7f68..605696aa75 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -34,9 +34,9 @@ #include "animation_blend_space_2d_editor.h" #include "animation_blend_tree_editor_plugin.h" #include "animation_state_machine_editor.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" #include "core/math/delaunay.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/editor_scale.h" @@ -44,7 +44,7 @@ #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" void AnimationTreeEditor::edit(AnimationTree *p_tree) { diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 80b7e6ffc8..3b104e34b2 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -30,8 +30,8 @@ #include "asset_library_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/io/json.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/version.h" #include "editor/editor_node.h" @@ -62,10 +62,10 @@ void EditorAssetLibraryItem::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - icon->set_normal_texture(get_icon("ProjectIconLoading", "EditorIcons")); - category->add_color_override("font_color", Color(0.5, 0.5, 0.5)); - author->add_color_override("font_color", Color(0.5, 0.5, 0.5)); - price->add_color_override("font_color", Color(0.5, 0.5, 0.5)); + icon->set_normal_texture(get_theme_icon("ProjectIconLoading", "EditorIcons")); + category->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5)); + author->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5)); + price->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5)); } } @@ -99,11 +99,11 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() { border->set_default_margin(MARGIN_RIGHT, 5 * EDSCALE); border->set_default_margin(MARGIN_BOTTOM, 5 * EDSCALE); border->set_default_margin(MARGIN_TOP, 5 * EDSCALE); - add_style_override("panel", border); + add_theme_style_override("panel", border); HBoxContainer *hb = memnew(HBoxContainer); // Add some spacing to visually separate the icon from the asset details. - hb->add_constant_override("separation", 15 * EDSCALE); + hb->add_theme_constant_override("separation", 15 * EDSCALE); add_child(hb); icon = memnew(TextureButton); @@ -116,7 +116,7 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() { VBoxContainer *vb = memnew(VBoxContainer); hb->add_child(vb); - vb->set_h_size_flags(SIZE_EXPAND_FILL); + vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); title = memnew(LinkButton); title->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); @@ -137,7 +137,7 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() { vb->add_child(price); set_custom_minimum_size(Size2(250, 100) * EDSCALE); - set_h_size_flags(SIZE_EXPAND_FILL); + set_h_size_flags(Control::SIZE_EXPAND_FILL); } ////////////////////////////////////////////////////////////////////////////// @@ -156,7 +156,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const for (int i = 0; i < preview_images.size(); i++) { if (preview_images[i].id == p_index) { if (preview_images[i].is_video) { - Ref<Image> overlay = get_icon("PlayOverlay", "EditorIcons")->get_data(); + Ref<Image> overlay = previews->get_theme_icon("PlayOverlay", "EditorIcons")->get_data(); Ref<Image> thumbnail = p_image->get_data(); thumbnail = thumbnail->duplicate(); Point2 overlay_pos = Point2((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2); @@ -172,7 +172,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const preview_images[i].button->set_icon(tex); // Make it clearer that clicking it will open an external link - preview_images[i].button->set_default_cursor_shape(CURSOR_POINTING_HAND); + preview_images[i].button->set_default_cursor_shape(Control::CURSOR_POINTING_HAND); } else { preview_images[i].button->set_icon(p_image); } @@ -198,7 +198,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const void EditorAssetLibraryItemDescription::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - previews_bg->add_style_override("panel", get_stylebox("normal", "TextEdit")); + previews_bg->add_theme_style_override("panel", previews->get_theme_stylebox("normal", "TextEdit")); } break; } } @@ -219,7 +219,7 @@ void EditorAssetLibraryItemDescription::_preview_click(int p_id) { if (!preview_images[i].is_video) { if (preview_images[i].image.is_valid()) { preview->set_texture(preview_images[i].image); - minimum_size_changed(); + child_controls_changed(); } } else { _link_click(preview_images[i].video_link); @@ -256,12 +256,12 @@ void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video, cons preview.is_video = p_video; preview.button = memnew(Button); preview.button->set_flat(true); - preview.button->set_icon(get_icon("ThumbnailWait", "EditorIcons")); + preview.button->set_icon(previews->get_theme_icon("ThumbnailWait", "EditorIcons")); preview.button->set_toggle_mode(true); preview.button->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDescription::_preview_click), varray(p_id)); preview_hb->add_child(preview.button); if (!p_video) { - preview.image = get_icon("ThumbnailWait", "EditorIcons"); + preview.image = previews->get_theme_icon("ThumbnailWait", "EditorIcons"); } preview_images.push_back(preview); if (preview_images.size() == 1 && !p_video) { @@ -275,7 +275,7 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { add_child(hbox); VBoxContainer *desc_vbox = memnew(VBoxContainer); hbox->add_child(desc_vbox); - hbox->add_constant_override("separation", 15 * EDSCALE); + hbox->add_theme_constant_override("separation", 15 * EDSCALE); item = memnew(EditorAssetLibraryItem); @@ -284,14 +284,14 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { description = memnew(RichTextLabel); desc_vbox->add_child(description); - description->set_v_size_flags(SIZE_EXPAND_FILL); + description->set_v_size_flags(Control::SIZE_EXPAND_FILL); description->connect("meta_clicked", callable_mp(this, &EditorAssetLibraryItemDescription::_link_click)); - description->add_constant_override("line_separation", Math::round(5 * EDSCALE)); + description->add_theme_constant_override("line_separation", Math::round(5 * EDSCALE)); VBoxContainer *previews_vbox = memnew(VBoxContainer); hbox->add_child(previews_vbox); - previews_vbox->add_constant_override("separation", 15 * EDSCALE); - previews_vbox->set_v_size_flags(SIZE_EXPAND_FILL); + previews_vbox->add_theme_constant_override("separation", 15 * EDSCALE); + previews_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); preview = memnew(TextureRect); previews_vbox->add_child(preview); @@ -308,7 +308,7 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { previews->set_enable_v_scroll(false); previews->set_enable_h_scroll(true); preview_hb = memnew(HBoxContainer); - preview_hb->set_v_size_flags(SIZE_EXPAND_FILL); + preview_hb->set_v_size_flags(Control::SIZE_EXPAND_FILL); previews->add_child(preview_hb); get_ok()->set_text(TTR("Download")); @@ -375,7 +375,7 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int if (error_text != String()) { download_error->set_text(TTR("Asset Download Error:") + "\n" + error_text); - download_error->popup_centered_minsize(); + download_error->popup_centered(); return; } @@ -393,7 +393,7 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse icon->set_texture(p_preview); asset_id = p_asset_id; if (!p_preview.is_valid()) - icon->set_texture(get_icon("FileBrokenBigThumb", "EditorIcons")); + icon->set_texture(get_theme_icon("FileBrokenBigThumb", "EditorIcons")); host = p_download_url; sha256 = p_sha256_hash; _make_request(); @@ -406,8 +406,8 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { // FIXME: The editor crashes if 'NOTICATION_THEME_CHANGED' is used. case NOTIFICATION_ENTER_TREE: { - add_style_override("panel", get_stylebox("panel", "TabContainer")); - dismiss->set_normal_texture(get_icon("Close", "EditorIcons")); + add_theme_style_override("panel", get_theme_stylebox("panel", "TabContainer")); + dismiss->set_normal_texture(get_theme_icon("Close", "EditorIcons")); } break; case NOTIFICATION_PROCESS: { @@ -507,13 +507,13 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { VBoxContainer *vb = memnew(VBoxContainer); hb->add_child(vb); - vb->set_h_size_flags(SIZE_EXPAND_FILL); + vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); HBoxContainer *title_hb = memnew(HBoxContainer); vb->add_child(title_hb); title = memnew(Label); title_hb->add_child(title); - title->set_h_size_flags(SIZE_EXPAND_FILL); + title->set_h_size_flags(Control::SIZE_EXPAND_FILL); dismiss = memnew(TextureButton); dismiss->connect("pressed", callable_mp(this, &EditorAssetLibraryItemDownload::_close)); @@ -525,7 +525,7 @@ EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() { status = memnew(Label(TTR("Idle"))); vb->add_child(status); - status->add_color_override("font_color", Color(0.5, 0.5, 0.5)); + status->add_theme_color_override("font_color", Color(0.5, 0.5, 0.5)); progress = memnew(ProgressBar); vb->add_child(progress); @@ -571,8 +571,8 @@ void EditorAssetLibrary::_notification(int p_what) { case NOTIFICATION_READY: { - error_tr->set_texture(get_icon("Error", "EditorIcons")); - filter->set_right_icon(get_icon("Search", "EditorIcons")); + error_tr->set_texture(get_theme_icon("Error", "EditorIcons")); + filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); error_label->raise(); @@ -602,10 +602,10 @@ void EditorAssetLibrary::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - library_scroll_bg->add_style_override("panel", get_stylebox("bg", "Tree")); - downloads_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); - error_tr->set_texture(get_icon("Error", "EditorIcons")); - filter->set_right_icon(get_icon("Search", "EditorIcons")); + library_scroll_bg->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + downloads_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); + error_tr->set_texture(get_theme_icon("Error", "EditorIcons")); + filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); } break; } @@ -774,7 +774,7 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB } if (!image_set && final) { - obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("FileBrokenBigThumb", "EditorIcons")); + obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_theme_icon("FileBrokenBigThumb", "EditorIcons")); } } } @@ -819,7 +819,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons WARN_PRINT("Error getting image file from URL: " + image_queue[p_queue_id].image_url); Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target); if (obj) { - obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("FileBrokenBigThumb", "EditorIcons")); + obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_theme_icon("FileBrokenBigThumb", "EditorIcons")); } } @@ -976,7 +976,7 @@ HBoxContainer *EditorAssetLibrary::_make_pages(int p_page, int p_page_count, int to = p_page_count; hbc->add_spacer(); - hbc->add_constant_override("separation", 5 * EDSCALE); + hbc->add_theme_constant_override("separation", 5 * EDSCALE); Button *first = memnew(Button); first->set_text(TTR("First")); @@ -1191,8 +1191,8 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const asset_items = memnew(GridContainer); asset_items->set_columns(2); - asset_items->add_constant_override("hseparation", 10 * EDSCALE); - asset_items->add_constant_override("vseparation", 10 * EDSCALE); + asset_items->add_theme_constant_override("hseparation", 10 * EDSCALE); + asset_items->add_theme_constant_override("vseparation", 10 * EDSCALE); library_vb->add_child(asset_items); @@ -1260,7 +1260,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const description = memnew(EditorAssetLibraryItemDescription); add_child(description); - description->popup_centered_minsize(); + description->popup_centered(); description->connect("confirmed", callable_mp(this, &EditorAssetLibrary::_install_asset)); description->configure(r["title"], r["asset_id"], category_map[r["category_id"]], r["category_id"], r["author"], r["author_id"], r["cost"], r["version"], r["version_string"], r["description"], r["download_url"], r["browse_url"], r["download_hash"]); @@ -1353,11 +1353,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { HBoxContainer *search_hb = memnew(HBoxContainer); library_main->add_child(search_hb); - library_main->add_constant_override("separation", 10 * EDSCALE); + library_main->add_theme_constant_override("separation", 10 * EDSCALE); filter = memnew(LineEdit); search_hb->add_child(filter); - filter->set_h_size_flags(SIZE_EXPAND_FILL); + filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); filter->connect("text_entered", callable_mp(this, &EditorAssetLibrary::_search_text_entered)); search = memnew(Button(TTR("Search"))); search->connect("pressed", callable_mp(this, &EditorAssetLibrary::_search), make_binds(0)); @@ -1392,7 +1392,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { search_hb2->add_child(sort); - sort->set_h_size_flags(SIZE_EXPAND_FILL); + sort->set_h_size_flags(Control::SIZE_EXPAND_FILL); sort->connect("item_selected", callable_mp(this, &EditorAssetLibrary::_rerun_search)); search_hb2->add_child(memnew(VSeparator)); @@ -1401,7 +1401,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { categories = memnew(OptionButton); categories->add_item(TTR("All")); search_hb2->add_child(categories); - categories->set_h_size_flags(SIZE_EXPAND_FILL); + categories->set_h_size_flags(Control::SIZE_EXPAND_FILL); categories->connect("item_selected", callable_mp(this, &EditorAssetLibrary::_rerun_search)); search_hb2->add_child(memnew(VSeparator)); @@ -1417,7 +1417,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { repository->connect("item_selected", callable_mp(this, &EditorAssetLibrary::_repository_changed)); search_hb2->add_child(repository); - repository->set_h_size_flags(SIZE_EXPAND_FILL); + repository->set_h_size_flags(Control::SIZE_EXPAND_FILL); search_hb2->add_child(memnew(VSeparator)); @@ -1435,7 +1435,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { library_scroll_bg = memnew(PanelContainer); library_main->add_child(library_scroll_bg); - library_scroll_bg->set_v_size_flags(SIZE_EXPAND_FILL); + library_scroll_bg->set_v_size_flags(Control::SIZE_EXPAND_FILL); library_scroll = memnew(ScrollContainer); library_scroll->set_enable_v_scroll(true); @@ -1452,11 +1452,11 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { PanelContainer *library_vb_border = memnew(PanelContainer); library_scroll->add_child(library_vb_border); - library_vb_border->add_style_override("panel", border2); - library_vb_border->set_h_size_flags(SIZE_EXPAND_FILL); + library_vb_border->add_theme_style_override("panel", border2); + library_vb_border->set_h_size_flags(Control::SIZE_EXPAND_FILL); library_vb = memnew(VBoxContainer); - library_vb->set_h_size_flags(SIZE_EXPAND_FILL); + library_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); library_vb_border->add_child(library_vb); @@ -1474,8 +1474,8 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { asset_items = memnew(GridContainer); asset_items->set_columns(2); - asset_items->add_constant_override("hseparation", 10 * EDSCALE); - asset_items->add_constant_override("vseparation", 10 * EDSCALE); + asset_items->add_theme_constant_override("hseparation", 10 * EDSCALE); + asset_items->add_theme_constant_override("vseparation", 10 * EDSCALE); library_vb->add_child(asset_items); @@ -1489,12 +1489,12 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { last_queue_id = 0; - library_vb->add_constant_override("separation", 20 * EDSCALE); + library_vb->add_theme_constant_override("separation", 20 * EDSCALE); error_hb = memnew(HBoxContainer); library_main->add_child(error_hb); error_label = memnew(Label); - error_label->add_color_override("color", get_color("error_color", "Editor")); + error_label->add_theme_color_override("color", get_theme_color("error_color", "Editor")); error_hb->add_child(error_label); error_tr = memnew(TextureRect); error_tr->set_v_size_flags(Control::SIZE_SHRINK_CENTER); @@ -1516,7 +1516,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { asset_open->set_access(EditorFileDialog::ACCESS_FILESYSTEM); asset_open->add_filter("*.zip ; " + TTR("Assets ZIP File")); - asset_open->set_mode(EditorFileDialog::MODE_OPEN_FILE); + asset_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); add_child(asset_open); asset_open->connect("file_selected", callable_mp(this, &EditorAssetLibrary::_asset_file_selected)); diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 7a1722c73b..6cffda49d0 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -43,10 +43,10 @@ void AudioStreamEditor::_notification(int p_what) { } if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { - _play_button->set_icon(get_icon("MainPlay", "EditorIcons")); - _stop_button->set_icon(get_icon("Stop", "EditorIcons")); - _preview->set_frame_color(get_color("dark_color_2", "Editor")); - set_frame_color(get_color("dark_color_1", "Editor")); + _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons")); + _stop_button->set_icon(get_theme_icon("Stop", "EditorIcons")); + _preview->set_frame_color(get_theme_color("dark_color_2", "Editor")); + set_frame_color(get_theme_color("dark_color_1", "Editor")); _indicator->update(); _preview->update(); @@ -87,7 +87,7 @@ void AudioStreamEditor::_draw_preview() { } Vector<Color> color; - color.push_back(get_color("contrast_color_2", "Editor")); + color.push_back(get_theme_color("contrast_color_2", "Editor")); VS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color); } @@ -110,11 +110,11 @@ void AudioStreamEditor::_play() { if (_player->is_playing()) { _player->stop(); - _play_button->set_icon(get_icon("MainPlay", "EditorIcons")); + _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons")); set_process(false); } else { _player->play(_current); - _play_button->set_icon(get_icon("Pause", "EditorIcons")); + _play_button->set_icon(get_theme_icon("Pause", "EditorIcons")); set_process(true); } } @@ -122,7 +122,7 @@ void AudioStreamEditor::_play() { void AudioStreamEditor::_stop() { _player->stop(); - _play_button->set_icon(get_icon("MainPlay", "EditorIcons")); + _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons")); _current = 0; _indicator->update(); set_process(false); @@ -130,7 +130,7 @@ void AudioStreamEditor::_stop() { void AudioStreamEditor::_on_finished() { - _play_button->set_icon(get_icon("MainPlay", "EditorIcons")); + _play_button->set_icon(get_theme_icon("MainPlay", "EditorIcons")); if (_current == _player->get_stream()->get_length()) { _current = 0; _indicator->update(); @@ -146,7 +146,7 @@ void AudioStreamEditor::_draw_indicator() { Rect2 rect = _preview->get_rect(); float len = stream->get_length(); float ofs_x = _current / len * rect.size.width; - _indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), get_color("accent_color", "Editor"), 1); + _indicator->draw_line(Point2(ofs_x, 0), Point2(ofs_x, rect.size.height), get_theme_color("accent_color", "Editor"), 1); _current_label->set_text(String::num(_current, 2).pad_decimals(2) + " /"); } @@ -225,7 +225,7 @@ AudioStreamEditor::AudioStreamEditor() { _preview->add_child(_indicator); HBoxContainer *hbox = memnew(HBoxContainer); - hbox->add_constant_override("separation", 0); + hbox->add_theme_constant_override("separation", 0); vbox->add_child(hbox); _play_button = memnew(ToolButton); @@ -241,12 +241,12 @@ AudioStreamEditor::AudioStreamEditor() { _current_label = memnew(Label); _current_label->set_align(Label::ALIGN_RIGHT); _current_label->set_h_size_flags(SIZE_EXPAND_FILL); - _current_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + _current_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts")); _current_label->set_modulate(Color(1, 1, 1, 0.5)); hbox->add_child(_current_label); _duration_label = memnew(Label); - _duration_label->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); + _duration_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts")); hbox->add_child(_duration_label); } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 9f66672f4a..4cc0bd4780 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "canvas_item_editor_plugin.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "core/print_string.h" #include "core/project_settings.h" @@ -50,7 +50,7 @@ #include "scene/gui/nine_patch_rect.h" #include "scene/gui/viewport_container.h" #include "scene/main/canvas_layer.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" #define MIN_ZOOM 0.01 @@ -99,7 +99,7 @@ public: label = memnew(Label); label->set_text(TTR("Grid Offset:")); child_container->add_child(label); - label->set_h_size_flags(SIZE_EXPAND_FILL); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); grid_offset_x = memnew(SpinBox); grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE); @@ -107,7 +107,7 @@ public: grid_offset_x->set_allow_lesser(true); grid_offset_x->set_allow_greater(true); grid_offset_x->set_suffix("px"); - grid_offset_x->set_h_size_flags(SIZE_EXPAND_FILL); + grid_offset_x->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(grid_offset_x); grid_offset_y = memnew(SpinBox); @@ -116,20 +116,20 @@ public: grid_offset_y->set_allow_lesser(true); grid_offset_y->set_allow_greater(true); grid_offset_y->set_suffix("px"); - grid_offset_y->set_h_size_flags(SIZE_EXPAND_FILL); + grid_offset_y->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(grid_offset_y); label = memnew(Label); label->set_text(TTR("Grid Step:")); child_container->add_child(label); - label->set_h_size_flags(SIZE_EXPAND_FILL); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); grid_step_x = memnew(SpinBox); grid_step_x->set_min(0.01); grid_step_x->set_max(SPIN_BOX_GRID_RANGE); grid_step_x->set_allow_greater(true); grid_step_x->set_suffix("px"); - grid_step_x->set_h_size_flags(SIZE_EXPAND_FILL); + grid_step_x->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(grid_step_x); grid_step_y = memnew(SpinBox); @@ -137,7 +137,7 @@ public: grid_step_y->set_max(SPIN_BOX_GRID_RANGE); grid_step_y->set_allow_greater(true); grid_step_y->set_suffix("px"); - grid_step_y->set_h_size_flags(SIZE_EXPAND_FILL); + grid_step_y->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(grid_step_y); child_container = memnew(GridContainer); @@ -146,7 +146,7 @@ public: label = memnew(Label); label->set_text(TTR("Primary Line Every:")); - label->set_h_size_flags(SIZE_EXPAND_FILL); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(label); primary_grid_steps = memnew(SpinBox); @@ -155,7 +155,7 @@ public: primary_grid_steps->set_max(100); primary_grid_steps->set_allow_greater(true); primary_grid_steps->set_suffix(TTR("steps")); - primary_grid_steps->set_h_size_flags(SIZE_EXPAND_FILL); + primary_grid_steps->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(primary_grid_steps); container->add_child(memnew(HSeparator)); @@ -169,25 +169,25 @@ public: label = memnew(Label); label->set_text(TTR("Rotation Offset:")); child_container->add_child(label); - label->set_h_size_flags(SIZE_EXPAND_FILL); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); rotation_offset = memnew(SpinBox); rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE); rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE); rotation_offset->set_suffix("deg"); - rotation_offset->set_h_size_flags(SIZE_EXPAND_FILL); + rotation_offset->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(rotation_offset); label = memnew(Label); label->set_text(TTR("Rotation Step:")); child_container->add_child(label); - label->set_h_size_flags(SIZE_EXPAND_FILL); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); rotation_step = memnew(SpinBox); rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE); rotation_step->set_max(SPIN_BOX_ROTATION_RANGE); rotation_step->set_suffix("deg"); - rotation_step->set_h_size_flags(SIZE_EXPAND_FILL); + rotation_step->set_h_size_flags(Control::SIZE_EXPAND_FILL); child_container->add_child(rotation_step); container->add_child(memnew(HSeparator)); @@ -198,13 +198,13 @@ public: label = memnew(Label); label->set_text(TTR("Scale Step:")); child_container->add_child(label); - label->set_h_size_flags(SIZE_EXPAND_FILL); + label->set_h_size_flags(Control::SIZE_EXPAND_FILL); scale_step = memnew(SpinBox); scale_step->set_min(SPIN_BOX_SCALE_MIN); scale_step->set_max(SPIN_BOX_SCALE_MAX); scale_step->set_allow_greater(true); - scale_step->set_h_size_flags(SIZE_EXPAND_FILL); + scale_step->set_h_size_flags(Control::SIZE_EXPAND_FILL); scale_step->set_step(0.01f); child_container->add_child(scale_step); } @@ -334,7 +334,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig snap_target[0] = SNAP_TARGET_NONE; snap_target[1] = SNAP_TARGET_NONE; - bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool is_snap_active = smart_snap_active ^ InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); // Smart snap using the canvas position Vector2 output = p_target; @@ -462,7 +462,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig } float CanvasItemEditor::snap_angle(float p_target, float p_start) const { - if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) { + if (((smart_snap_active || snap_rotation) ^ InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) { if (snap_relative) { return Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset + (p_start - (int)(p_start / snap_rotation_step) * snap_rotation_step); } else { @@ -477,7 +477,7 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { Ref<InputEventKey> k = p_ev; - if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack()) + if (!is_visible_in_tree()) return; if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) { @@ -1284,7 +1284,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo // Pan the viewport Point2i relative; if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) { - relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect()); + relative = InputFilter::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect()); } else { relative = m->get_relative(); } @@ -1912,7 +1912,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform; bool uniform = m->get_shift(); - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool is_ctrl = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); Point2 drag_from_local = simple_xform.xform(drag_from); Point2 drag_to_local = simple_xform.xform(drag_to); @@ -2207,10 +2207,10 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && tool == TOOL_SELECT && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) { // Confirm canvas items move by arrow keys - if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) && - (!Input::get_singleton()->is_key_pressed(KEY_DOWN)) && - (!Input::get_singleton()->is_key_pressed(KEY_LEFT)) && - (!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) { + if ((!InputFilter::get_singleton()->is_key_pressed(KEY_UP)) && + (!InputFilter::get_singleton()->is_key_pressed(KEY_DOWN)) && + (!InputFilter::get_singleton()->is_key_pressed(KEY_LEFT)) && + (!InputFilter::get_singleton()->is_key_pressed(KEY_RIGHT))) { _commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true); drag_type = DRAG_NONE; } @@ -2284,7 +2284,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } selection_menu_additive_selection = b->get_shift(); - selection_menu->set_global_position(b->get_global_position()); + selection_menu->set_position(get_screen_transform().xform(b->get_position())); selection_menu->popup(); return true; } @@ -2588,9 +2588,9 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { } void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) { - Color color = get_color("font_color", "Editor"); + Color color = get_theme_color("font_color", "Editor"); color.a = 0.8; - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); Size2 text_size = font->get_string_size(p_string); switch (p_side) { case MARGIN_LEFT: @@ -2626,7 +2626,7 @@ void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_posi void CanvasItemEditor::_draw_focus() { // Draw the focus around the base viewport if (viewport->has_focus()) { - get_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size())); + get_theme_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size())); } } @@ -2657,18 +2657,18 @@ void CanvasItemEditor::_draw_guides() { } // Dragged guide - Color text_color = get_color("font_color", "Editor"); + Color text_color = get_theme_color("font_color", "Editor"); text_color.a = 0.5; if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) { String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); Size2 text_size = font->get_string_size(str); viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color); viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE)); } if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) { String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); Size2 text_size = font->get_string_size(str); viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, text_color); viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE)); @@ -2690,11 +2690,11 @@ void CanvasItemEditor::_draw_smart_snapping() { } void CanvasItemEditor::_draw_rulers() { - Color bg_color = get_color("dark_color_2", "Editor"); - Color graduation_color = get_color("font_color", "Editor").linear_interpolate(bg_color, 0.5); - Color font_color = get_color("font_color", "Editor"); + Color bg_color = get_theme_color("dark_color_2", "Editor"); + Color graduation_color = get_theme_color("font_color", "Editor").linear_interpolate(bg_color, 0.5); + Color font_color = get_theme_color("font_color", "Editor"); font_color.a = 0.8; - Ref<Font> font = get_font("rulers", "EditorFonts"); + Ref<Font> font = get_theme_font("rulers", "EditorFonts"); // The rule transform Transform2D ruler_transform = Transform2D(); @@ -2856,7 +2856,7 @@ void CanvasItemEditor::_draw_ruler_tool() { return; if (ruler_tool_active) { - Color ruler_primary_color = get_color("accent_color", "Editor"); + Color ruler_primary_color = get_theme_color("accent_color", "Editor"); Color ruler_secondary_color = ruler_primary_color; ruler_secondary_color.a = 0.5; @@ -2873,8 +2873,8 @@ void CanvasItemEditor::_draw_ruler_tool() { viewport->draw_line(corner, end, ruler_secondary_color, Math::round(EDSCALE)); } - Ref<Font> font = get_font("bold", "EditorFonts"); - Color font_color = get_color("font_color", "Editor"); + Ref<Font> font = get_theme_font("bold", "EditorFonts"); + Color font_color = get_theme_color("font_color", "Editor"); Color font_secondary_color = font_color; font_secondary_color.a = 0.5; float text_height = font->get_height(); @@ -2974,8 +2974,8 @@ void CanvasItemEditor::_draw_ruler_tool() { } else { if (grid_snap_active) { - Ref<Texture2D> position_icon = get_icon("EditorPosition", "EditorIcons"); - viewport->draw_texture(get_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2); + Ref<Texture2D> position_icon = get_theme_icon("EditorPosition", "EditorIcons"); + viewport->draw_texture(get_theme_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2); } } } @@ -3187,9 +3187,9 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) { } void CanvasItemEditor::_draw_selection() { - Ref<Texture2D> pivot_icon = get_icon("EditorPivot", "EditorIcons"); - Ref<Texture2D> position_icon = get_icon("EditorPosition", "EditorIcons"); - Ref<Texture2D> previous_position_icon = get_icon("EditorPositionPrevious", "EditorIcons"); + Ref<Texture2D> pivot_icon = get_theme_icon("EditorPivot", "EditorIcons"); + Ref<Texture2D> position_icon = get_theme_icon("EditorPosition", "EditorIcons"); + Ref<Texture2D> previous_position_icon = get_theme_icon("EditorPositionPrevious", "EditorIcons"); RID ci = viewport->get_canvas_item(); @@ -3297,8 +3297,8 @@ void CanvasItemEditor::_draw_selection() { } // Draw the move handles - bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); - bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); + bool is_ctrl = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); + bool is_alt = InputFilter::get_singleton()->is_key_pressed(KEY_ALT); if (tool == TOOL_MOVE && show_transformation_gizmos) { if (_is_node_movable(canvas_item)) { Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized(); @@ -3312,16 +3312,16 @@ void CanvasItemEditor::_draw_selection() { points.push_back(Vector2(move_factor.x * EDSCALE, -5 * EDSCALE)); points.push_back(Vector2((move_factor.x + 10) * EDSCALE, 0)); - viewport->draw_colored_polygon(points, get_color("axis_x_color", "Editor")); - viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_color("axis_x_color", "Editor"), Math::round(EDSCALE)); + viewport->draw_colored_polygon(points, get_theme_color("axis_x_color", "Editor")); + viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_theme_color("axis_x_color", "Editor"), Math::round(EDSCALE)); points.clear(); points.push_back(Vector2(5 * EDSCALE, move_factor.y * EDSCALE)); points.push_back(Vector2(-5 * EDSCALE, move_factor.y * EDSCALE)); points.push_back(Vector2(0, (move_factor.y + 10) * EDSCALE)); - viewport->draw_colored_polygon(points, get_color("axis_y_color", "Editor")); - viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE)); + viewport->draw_colored_polygon(points, get_theme_color("axis_y_color", "Editor")); + viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_theme_color("axis_y_color", "Editor"), Math::round(EDSCALE)); viewport->draw_set_transform_matrix(viewport->get_transform()); } @@ -3334,7 +3334,7 @@ void CanvasItemEditor::_draw_selection() { Transform2D simple_xform = viewport->get_transform() * unscaled_transform; Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); - bool uniform = Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool uniform = InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT); Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom; if (drag_type == DRAG_SCALE_X) { @@ -3351,12 +3351,12 @@ void CanvasItemEditor::_draw_selection() { viewport->draw_set_transform_matrix(simple_xform); Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - viewport->draw_rect(x_handle_rect, get_color("axis_x_color", "Editor")); - viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_color("axis_x_color", "Editor"), Math::round(EDSCALE)); + viewport->draw_rect(x_handle_rect, get_theme_color("axis_x_color", "Editor")); + viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_theme_color("axis_x_color", "Editor"), Math::round(EDSCALE)); Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - viewport->draw_rect(y_handle_rect, get_color("axis_y_color", "Editor")); - viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE)); + viewport->draw_rect(y_handle_rect, get_theme_color("axis_y_color", "Editor")); + viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_theme_color("axis_y_color", "Editor"), Math::round(EDSCALE)); viewport->draw_set_transform_matrix(viewport->get_transform()); } @@ -3371,11 +3371,11 @@ void CanvasItemEditor::_draw_selection() { viewport->draw_rect( Rect2(bsfrom, bsto - bsfrom), - get_color("box_selection_fill_color", "Editor")); + get_theme_color("box_selection_fill_color", "Editor")); viewport->draw_rect( Rect2(bsfrom, bsto - bsfrom), - get_color("box_selection_stroke_color", "Editor"), + get_theme_color("box_selection_stroke_color", "Editor"), false, Math::round(EDSCALE)); } @@ -3385,7 +3385,7 @@ void CanvasItemEditor::_draw_selection() { viewport->draw_line( transform.xform(drag_rotation_center), transform.xform(drag_to), - get_color("accent_color", "Editor") * Color(1, 1, 1, 0.6), + get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.6), Math::round(2 * EDSCALE)); } } @@ -3435,8 +3435,8 @@ void CanvasItemEditor::_draw_axis() { if (show_origin) { - _draw_straight_line(Point2(), Point2(1, 0), get_color("axis_x_color", "Editor") * Color(1, 1, 1, 0.75)); - _draw_straight_line(Point2(), Point2(0, 1), get_color("axis_y_color", "Editor") * Color(1, 1, 1, 0.75)); + _draw_straight_line(Point2(), Point2(1, 0), get_theme_color("axis_x_color", "Editor") * Color(1, 1, 1, 0.75)); + _draw_straight_line(Point2(), Point2(0, 1), get_theme_color("axis_y_color", "Editor") * Color(1, 1, 1, 0.75)); } if (show_viewport) { @@ -3547,7 +3547,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans Transform2D xform = transform * canvas_xform * parent_xform; // Draw the node's position - Ref<Texture2D> position_icon = get_icon("EditorPositionUnselected", "EditorIcons"); + Ref<Texture2D> position_icon = get_theme_icon("EditorPositionUnselected", "EditorIcons"); Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized(); Transform2D simple_xform = viewport->get_transform() * unscaled_transform; viewport->draw_set_transform_matrix(simple_xform); @@ -3564,7 +3564,7 @@ void CanvasItemEditor::_draw_hover() { Ref<Texture2D> node_icon = hovering_results[i].icon; String node_name = hovering_results[i].name; - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); Size2 node_name_size = font->get_string_size(node_name); Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3)); @@ -3615,13 +3615,13 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p if (canvas_item) { float offset = 0; - Ref<Texture2D> lock = get_icon("LockViewport", "EditorIcons"); + Ref<Texture2D> lock = get_theme_icon("LockViewport", "EditorIcons"); if (p_node->has_meta("_edit_lock_") && show_edit_locks) { lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); offset += lock->get_size().x; } - Ref<Texture2D> group = get_icon("GroupViewport", "EditorIcons"); + Ref<Texture2D> group = get_theme_icon("GroupViewport", "EditorIcons"); if (canvas_item->has_meta("_edit_group_") && show_edit_locks) { group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); //offset += group->get_size().x; @@ -3893,7 +3893,7 @@ void CanvasItemEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons")); + select_sb->set_texture(get_theme_icon("EditorRect2D", "EditorIcons")); for (int i = 0; i < 4; i++) { select_sb->set_margin_size(Margin(i), 4); select_sb->set_default_margin(Margin(i), 4); @@ -3906,7 +3906,7 @@ void CanvasItemEditor::_notification(int p_what) { } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons")); + select_sb->set_texture(get_theme_icon("EditorRect2D", "EditorIcons")); } if (p_what == NOTIFICATION_EXIT_TREE) { @@ -3915,85 +3915,85 @@ void CanvasItemEditor::_notification(int p_what) { } if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - select_button->set_icon(get_icon("ToolSelect", "EditorIcons")); - list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); - move_button->set_icon(get_icon("ToolMove", "EditorIcons")); - scale_button->set_icon(get_icon("ToolScale", "EditorIcons")); - rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons")); - smart_snap_button->set_icon(get_icon("Snap", "EditorIcons")); - grid_snap_button->set_icon(get_icon("SnapGrid", "EditorIcons")); - snap_config_menu->set_icon(get_icon("GuiTabMenu", "EditorIcons")); - skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); - override_camera_button->set_icon(get_icon("Camera2D", "EditorIcons")); - pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); - ruler_button->set_icon(get_icon("Ruler", "EditorIcons")); - pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); - select_handle = get_icon("EditorHandle", "EditorIcons"); - anchor_handle = get_icon("EditorControlAnchor", "EditorIcons"); - lock_button->set_icon(get_icon("Lock", "EditorIcons")); - unlock_button->set_icon(get_icon("Unlock", "EditorIcons")); - group_button->set_icon(get_icon("Group", "EditorIcons")); - ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons")); - key_loc_button->set_icon(get_icon("KeyPosition", "EditorIcons")); - key_rot_button->set_icon(get_icon("KeyRotation", "EditorIcons")); - key_scale_button->set_icon(get_icon("KeyScale", "EditorIcons")); - key_insert_button->set_icon(get_icon("Key", "EditorIcons")); - key_auto_insert_button->set_icon(get_icon("AutoKey", "EditorIcons")); - animation_menu->set_icon(get_icon("GuiTabMenu", "EditorIcons")); - - zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons")); - zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons")); - - presets_menu->set_icon(get_icon("ControlLayout", "EditorIcons")); + select_button->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + list_select_button->set_icon(get_theme_icon("ListSelect", "EditorIcons")); + move_button->set_icon(get_theme_icon("ToolMove", "EditorIcons")); + scale_button->set_icon(get_theme_icon("ToolScale", "EditorIcons")); + rotate_button->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); + smart_snap_button->set_icon(get_theme_icon("Snap", "EditorIcons")); + grid_snap_button->set_icon(get_theme_icon("SnapGrid", "EditorIcons")); + snap_config_menu->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); + skeleton_menu->set_icon(get_theme_icon("Bone", "EditorIcons")); + override_camera_button->set_icon(get_theme_icon("Camera2D", "EditorIcons")); + pan_button->set_icon(get_theme_icon("ToolPan", "EditorIcons")); + ruler_button->set_icon(get_theme_icon("Ruler", "EditorIcons")); + pivot_button->set_icon(get_theme_icon("EditPivot", "EditorIcons")); + select_handle = get_theme_icon("EditorHandle", "EditorIcons"); + anchor_handle = get_theme_icon("EditorControlAnchor", "EditorIcons"); + lock_button->set_icon(get_theme_icon("Lock", "EditorIcons")); + unlock_button->set_icon(get_theme_icon("Unlock", "EditorIcons")); + group_button->set_icon(get_theme_icon("Group", "EditorIcons")); + ungroup_button->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + key_loc_button->set_icon(get_theme_icon("KeyPosition", "EditorIcons")); + key_rot_button->set_icon(get_theme_icon("KeyRotation", "EditorIcons")); + key_scale_button->set_icon(get_theme_icon("KeyScale", "EditorIcons")); + key_insert_button->set_icon(get_theme_icon("Key", "EditorIcons")); + key_auto_insert_button->set_icon(get_theme_icon("AutoKey", "EditorIcons")); + animation_menu->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); + + zoom_minus->set_icon(get_theme_icon("ZoomLess", "EditorIcons")); + zoom_plus->set_icon(get_theme_icon("ZoomMore", "EditorIcons")); + + presets_menu->set_icon(get_theme_icon("ControlLayout", "EditorIcons")); PopupMenu *p = presets_menu->get_popup(); p->clear(); - p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_MARGINS_PRESET_TOP_LEFT); - p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT); + p->add_icon_item(get_theme_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_MARGINS_PRESET_TOP_LEFT); + p->add_icon_item(get_theme_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT); + p->add_icon_item(get_theme_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT); + p->add_icon_item(get_theme_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT); p->add_separator(); - p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT); - p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_MARGINS_PRESET_CENTER_TOP); - p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT); - p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM); - p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_MARGINS_PRESET_CENTER); + p->add_icon_item(get_theme_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT); + p->add_icon_item(get_theme_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_MARGINS_PRESET_CENTER_TOP); + p->add_icon_item(get_theme_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT); + p->add_icon_item(get_theme_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM); + p->add_icon_item(get_theme_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_MARGINS_PRESET_CENTER); p->add_separator(); - p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE); - p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_MARGINS_PRESET_TOP_WIDE); - p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE); - p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE); - p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE); - p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE); + p->add_icon_item(get_theme_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE); + p->add_icon_item(get_theme_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_MARGINS_PRESET_TOP_WIDE); + p->add_icon_item(get_theme_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE); + p->add_icon_item(get_theme_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE); + p->add_icon_item(get_theme_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE); + p->add_icon_item(get_theme_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE); p->add_separator(); - p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_MARGINS_PRESET_WIDE); - p->add_icon_item(get_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO); + p->add_icon_item(get_theme_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_MARGINS_PRESET_WIDE); + p->add_icon_item(get_theme_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO); p->add_separator(); p->add_submenu_item(TTR("Anchors only"), "Anchors"); - p->set_item_icon(21, get_icon("Anchor", "EditorIcons")); + p->set_item_icon(21, get_theme_icon("Anchor", "EditorIcons")); anchors_popup->clear(); - anchors_popup->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT); - anchors_popup->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT); - anchors_popup->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT); - anchors_popup->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT); anchors_popup->add_separator(); - anchors_popup->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT); - anchors_popup->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP); - anchors_popup->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT); - anchors_popup->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM); - anchors_popup->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_PRESET_CENTER); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_PRESET_CENTER); anchors_popup->add_separator(); - anchors_popup->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE); - anchors_popup->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE); - anchors_popup->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE); - anchors_popup->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE); - anchors_popup->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE); - anchors_popup->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE); anchors_popup->add_separator(); - anchors_popup->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_PRESET_WIDE); + anchors_popup->add_icon_item(get_theme_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_PRESET_WIDE); - anchor_mode_button->set_icon(get_icon("Anchor", "EditorIcons")); + anchor_mode_button->set_icon(get_theme_icon("Anchor", "EditorIcons")); } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { @@ -5420,18 +5420,18 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { bottom_split = memnew(VSplitContainer); add_child(bottom_split); - bottom_split->set_v_size_flags(SIZE_EXPAND_FILL); + bottom_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); palette_split = memnew(HSplitContainer); bottom_split->add_child(palette_split); - palette_split->set_v_size_flags(SIZE_EXPAND_FILL); + palette_split->set_v_size_flags(Control::SIZE_EXPAND_FILL); viewport_scrollable = memnew(Control); palette_split->add_child(viewport_scrollable); viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS); viewport_scrollable->set_clip_contents(true); - viewport_scrollable->set_v_size_flags(SIZE_EXPAND_FILL); - viewport_scrollable->set_h_size_flags(SIZE_EXPAND_FILL); + viewport_scrollable->set_v_size_flags(Control::SIZE_EXPAND_FILL); + viewport_scrollable->set_h_size_flags(Control::SIZE_EXPAND_FILL); viewport_scrollable->connect("draw", callable_mp(this, &CanvasItemEditor::_update_scrollbars)); ViewportContainer *scene_tree = memnew(ViewportContainer); @@ -5445,7 +5445,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { zoom_hb = memnew(HBoxContainer); // Bring the zoom percentage closer to the zoom buttons - zoom_hb->add_constant_override("separation", Math::round(-8 * EDSCALE)); + zoom_hb->add_theme_constant_override("separation", Math::round(-8 * EDSCALE)); controls_vb->add_child(zoom_hb); viewport = memnew(CanvasItemEditorViewport(p_editor, this)); @@ -5462,7 +5462,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { info_overlay->set_margin(MARGIN_LEFT, 10); info_overlay->set_margin(MARGIN_BOTTOM, -15); info_overlay->set_v_grow_direction(Control::GROW_DIRECTION_BEGIN); - info_overlay->add_constant_override("separation", 10); + info_overlay->add_theme_constant_override("separation", 10); viewport_scrollable->add_child(info_overlay); Theme *info_overlay_theme = memnew(Theme); @@ -5477,8 +5477,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { warning_child_of_container = memnew(Label); warning_child_of_container->hide(); warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent.")); - warning_child_of_container->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor")); - warning_child_of_container->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts")); + warning_child_of_container->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor")); + warning_child_of_container->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts")); add_control_to_info_overlay(warning_child_of_container); h_scroll = memnew(HScrollBar); @@ -5783,7 +5783,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { selection_menu = memnew(PopupMenu); add_child(selection_menu); - selection_menu->set_custom_minimum_size(Vector2(100, 0)); + selection_menu->set_min_size(Vector2(100, 0)); selection_menu->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_selection_result_pressed)); selection_menu->connect("popup_hide", callable_mp(this, &CanvasItemEditor::_selection_menu_hide)); @@ -6049,7 +6049,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { // Without root dropping multiple files is not allowed if (!target_node && selected_files.size() > 1) { accept->set_text(TTR("Cannot instantiate multiple nodes without root.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } @@ -6110,7 +6110,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { } files_str = files_str.substr(0, files_str.length() - 1); accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); - accept->popup_centered_minsize(); + accept->popup_centered(); } } @@ -6176,7 +6176,7 @@ void CanvasItemEditorViewport::_show_resource_type_selector() { check->set_pressed(check->get_text() == default_type); } selector->set_title(vformat(TTR("Add %s"), default_type)); - selector->popup_centered_minsize(); + selector->popup_centered(); } bool CanvasItemEditorViewport::_only_packed_scenes_selected() const { @@ -6191,8 +6191,8 @@ bool CanvasItemEditorViewport::_only_packed_scenes_selected() const { } void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) { - bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT); - bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); + bool is_shift = InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT); + bool is_alt = InputFilter::get_singleton()->is_key_pressed(KEY_ALT); selected_files.clear(); Dictionary d = p_data; @@ -6233,7 +6233,7 @@ void CanvasItemEditorViewport::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { connect("mouse_exited", callable_mp(this, &CanvasItemEditorViewport::_on_mouse_exit)); - label->add_color_override("font_color", get_color("warning_color", "Editor")); + label->add_theme_color_override("font_color", get_theme_color("warning_color", "Editor")); } break; case NOTIFICATION_EXIT_TREE: { disconnect("mouse_exited", callable_mp(this, &CanvasItemEditorViewport::_on_mouse_exit)); @@ -6271,12 +6271,12 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte editor->get_gui_base()->add_child(selector); selector->set_title(TTR("Change Default Type")); selector->connect("confirmed", callable_mp(this, &CanvasItemEditorViewport::_on_change_type_confirmed)); - selector->connect("popup_hide", callable_mp(this, &CanvasItemEditorViewport::_on_change_type_closed)); + selector->connect("cancelled", callable_mp(this, &CanvasItemEditorViewport::_on_change_type_closed)); VBoxContainer *vbc = memnew(VBoxContainer); selector->add_child(vbc); - vbc->set_h_size_flags(SIZE_EXPAND_FILL); - vbc->set_v_size_flags(SIZE_EXPAND_FILL); + vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); + vbc->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE); btn_group = memnew(VBoxContainer); @@ -6293,17 +6293,17 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte } label = memnew(Label); - label->add_color_override("font_color_shadow", Color(0, 0, 0, 1)); - label->add_constant_override("shadow_as_outline", 1 * EDSCALE); + label->add_theme_color_override("font_color_shadow", Color(0, 0, 0, 1)); + label->add_theme_constant_override("shadow_as_outline", 1 * EDSCALE); label->hide(); canvas_item_editor->get_controls_container()->add_child(label); label_desc = memnew(Label); label_desc->set_text(TTR("Drag & drop + Shift : Add node as sibling\nDrag & drop + Alt : Change node type")); - label_desc->add_color_override("font_color", Color(0.6f, 0.6f, 0.6f, 1)); - label_desc->add_color_override("font_color_shadow", Color(0.2f, 0.2f, 0.2f, 1)); - label_desc->add_constant_override("shadow_as_outline", 1 * EDSCALE); - label_desc->add_constant_override("line_spacing", 0); + label_desc->add_theme_color_override("font_color", Color(0.6f, 0.6f, 0.6f, 1)); + label_desc->add_theme_color_override("font_color_shadow", Color(0.2f, 0.2f, 0.2f, 1)); + label_desc->add_theme_constant_override("shadow_as_outline", 1 * EDSCALE); + label_desc->add_theme_constant_override("line_spacing", 0); label_desc->hide(); canvas_item_editor->get_controls_container()->add_child(label_desc); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 3c4cacf5c8..f109b06aa3 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -687,7 +687,7 @@ class CanvasItemEditorViewport : public Control { CanvasItemEditor *canvas_item_editor; Node2D *preview_node; AcceptDialog *accept; - WindowDialog *selector; + AcceptDialog *selector; Label *selector_label; Label *label; Label *label_desc; diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index 1562286073..93295e6ab5 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -31,8 +31,8 @@ #include "collision_polygon_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/os/file_access.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "editor/editor_settings.h" #include "scene/3d/camera.h" @@ -44,8 +44,8 @@ void Polygon3DEditor::_notification(int p_what) { case NOTIFICATION_READY: { - button_create->set_icon(get_icon("Edit", "EditorIcons")); - button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); + button_create->set_icon(get_theme_icon("Edit", "EditorIcons")); + button_edit->set_icon(get_theme_icon("MovePoint", "EditorIcons")); button_edit->set_pressed(true); get_tree()->connect("node_removed", callable_mp(this, &Polygon3DEditor::_node_removed)); @@ -342,7 +342,7 @@ bool Polygon3DEditor::forward_spatial_gui_input(Camera *p_camera, const Ref<Inpu Vector2 cpoint(spoint.x, spoint.y); - if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (snap_ignore && !InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) { snap_ignore = false; } @@ -556,7 +556,7 @@ Polygon3DEditor::Polygon3DEditor(EditorNode *p_editor) { handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); - Ref<Texture2D> handle = editor->get_gui_base()->get_icon("Editor3DHandle", "EditorIcons"); + Ref<Texture2D> handle = editor->get_gui_base()->get_theme_icon("Editor3DHandle", "EditorIcons"); handle_material->set_point_size(handle->get_width()); handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 01b4a61a85..709ff91fc0 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -435,7 +435,7 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref<Texture2D> h = get_icon("EditorHandle", "EditorIcons"); + Ref<Texture2D> h = get_theme_icon("EditorHandle", "EditorIcons"); Vector2 size = h->get_size() * 0.5; handles.clear(); diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp index 119528dfc8..25b8fb8bcb 100644 --- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp @@ -60,7 +60,7 @@ void CPUParticles2DEditorPlugin::make_visible(bool p_visible) { void CPUParticles2DEditorPlugin::_file_selected(const String &p_file) { source_emission_file = p_file; - emission_mask->popup_centered_minsize(); + emission_mask->popup_centered(); } void CPUParticles2DEditorPlugin::_menu_callback(int p_idx) { @@ -73,7 +73,7 @@ void CPUParticles2DEditorPlugin::_menu_callback(int p_idx) { } break; case MENU_CLEAR_EMISSION_MASK: { - emission_mask->popup_centered_minsize(); + emission_mask->popup_centered(); } break; case MENU_RESTART: { @@ -241,7 +241,7 @@ void CPUParticles2DEditorPlugin::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { menu->get_popup()->connect("id_pressed", callable_mp(this, &CPUParticles2DEditorPlugin::_menu_callback)); - menu->set_icon(menu->get_popup()->get_icon("Particles2D", "EditorIcons")); + menu->set_icon(epoints->get_theme_icon("Particles2D", "EditorIcons")); file->connect("file_selected", callable_mp(this, &CPUParticles2DEditorPlugin::_file_selected)); } } @@ -276,7 +276,7 @@ CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin(EditorNode *p_node) { for (List<String>::Element *E = ext.front(); E; E = E->next()) { file->add_filter("*." + E->get() + "; " + E->get().to_upper()); } - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); toolbar->add_child(file); epoints = memnew(SpinBox); diff --git a/editor/plugins/cpu_particles_editor_plugin.cpp b/editor/plugins/cpu_particles_editor_plugin.cpp index 2161041ee6..1388b9ca10 100644 --- a/editor/plugins/cpu_particles_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_editor_plugin.cpp @@ -43,7 +43,7 @@ void CPUParticlesEditor::_node_removed(Node *p_node) { void CPUParticlesEditor::_notification(int p_notification) { if (p_notification == NOTIFICATION_ENTER_TREE) { - options->set_icon(options->get_popup()->get_icon("CPUParticles", "EditorIcons")); + options->set_icon(get_theme_icon("CPUParticles", "EditorIcons")); } } diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 878787231d..0fd8ea4fb5 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -32,7 +32,7 @@ #include "canvas_item_editor_plugin.h" #include "core/core_string_names.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" @@ -210,7 +210,7 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { else tangent = 9999 * (dir.y >= 0 ? 1 : -1); - bool link = !Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool link = !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT); if (_selected_tangent == TANGENT_LEFT) { curve.set_point_left_tangent(_selected_point, tangent); @@ -511,7 +511,7 @@ void CurveEditor::set_hover_point_index(int index) { } void CurveEditor::update_view_transform() { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); const real_t margin = font->get_height() + 2 * EDSCALE; float min_y = 0; @@ -626,7 +626,7 @@ void CurveEditor::_draw() { // Background Vector2 view_size = get_rect().size; - draw_style_box(get_stylebox("bg", "Tree"), Rect2(Point2(), view_size)); + draw_style_box(get_theme_stylebox("bg", "Tree"), Rect2(Point2(), view_size)); // Grid @@ -635,8 +635,8 @@ void CurveEditor::_draw() { Vector2 min_edge = get_world_pos(Vector2(0, view_size.y)); Vector2 max_edge = get_world_pos(Vector2(view_size.x, 0)); - const Color grid_color0 = get_color("mono_color", "Editor") * Color(1, 1, 1, 0.15); - const Color grid_color1 = get_color("mono_color", "Editor") * Color(1, 1, 1, 0.07); + const Color grid_color0 = get_theme_color("mono_color", "Editor") * Color(1, 1, 1, 0.15); + const Color grid_color1 = get_theme_color("mono_color", "Editor") * Color(1, 1, 1, 0.07); draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0); draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0); draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0); @@ -656,9 +656,9 @@ void CurveEditor::_draw() { draw_set_transform_matrix(Transform2D()); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); float font_height = font->get_height(); - Color text_color = get_color("font_color", "Editor"); + Color text_color = get_theme_color("font_color", "Editor"); { // X axis @@ -686,7 +686,7 @@ void CurveEditor::_draw() { if (_selected_point >= 0) { - const Color tangent_color = get_color("accent_color", "Editor"); + const Color tangent_color = get_theme_color("accent_color", "Editor"); int i = _selected_point; Vector2 pos = curve.get_point_position(i); @@ -708,8 +708,8 @@ void CurveEditor::_draw() { draw_set_transform_matrix(_world_to_view); - const Color line_color = get_color("font_color", "Editor"); - const Color edge_line_color = get_color("highlight_color", "Editor"); + const Color line_color = get_theme_color("font_color", "Editor"); + const Color edge_line_color = get_theme_color("highlight_color", "Editor"); CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color); plot_curve_accurate(curve, 4.f / view_size.x, plot_func); @@ -718,8 +718,8 @@ void CurveEditor::_draw() { draw_set_transform_matrix(Transform2D()); - const Color point_color = get_color("font_color", "Editor"); - const Color selected_point_color = get_color("accent_color", "Editor"); + const Color point_color = get_theme_color("font_color", "Editor"); + const Color selected_point_color = get_theme_color("accent_color", "Editor"); for (int i = 0; i < curve.get_point_count(); ++i) { Vector2 pos = curve.get_point_position(i); diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index c4069ac2ab..566ff378c3 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -54,7 +54,6 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(EditorNode *p_editor, MenuButton *p_d // Main editor debug menu. debug_menu = p_debug_menu; PopupMenu *p = debug_menu->get_popup(); - p->set_hide_on_window_lose_focus(true); p->set_hide_on_checkable_item_selection(false); p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG); p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged.")); diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp index c077c23e8a..908a32fdb6 100644 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ b/editor/plugins/gi_probe_editor_plugin.cpp @@ -87,16 +87,16 @@ void GIProbeEditorPlugin::_notification(int p_what) { Color color; if (size_mb <= 16.0 + CMP_EPSILON) { // Fast. - color = bake_info->get_color("success_color", "Editor"); + color = bake_info->get_theme_color("success_color", "Editor"); } else if (size_mb <= 64.0 + CMP_EPSILON) { // Medium. - color = bake_info->get_color("warning_color", "Editor"); + color = bake_info->get_theme_color("warning_color", "Editor"); } else { // Slow. - color = bake_info->get_color("error_color", "Editor"); + color = bake_info->get_theme_color("error_color", "Editor"); } + bake_info->add_theme_color_override("font_color", color); - bake_info->add_color_override("font_color", color); bake_info->set_text(text); } } @@ -153,7 +153,7 @@ GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); bake_hb->hide(); bake = memnew(ToolButton); - bake->set_icon(editor->get_gui_base()->get_icon("Bake", "EditorIcons")); + bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake GI Probe")); bake->connect("pressed", callable_mp(this, &GIProbeEditorPlugin::_bake)); bake_hb->add_child(bake); @@ -165,7 +165,7 @@ GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake_hb); gi_probe = NULL; probe_file = memnew(EditorFileDialog); - probe_file->set_mode(EditorFileDialog::MODE_SAVE_FILE); + probe_file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); probe_file->add_filter("*.res"); probe_file->connect("file_selected", callable_mp(this, &GIProbeEditorPlugin::_giprobe_save_path_and_bake)); get_editor_interface()->get_base_control()->add_child(probe_file); diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index ba640883c7..9ae4d2ae9d 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -264,8 +264,8 @@ void ItemListEditor::_notification(int p_notification) { if (p_notification == NOTIFICATION_ENTER_TREE || p_notification == NOTIFICATION_THEME_CHANGED) { - add_button->set_icon(get_icon("Add", "EditorIcons")); - del_button->set_icon(get_icon("Remove", "EditorIcons")); + add_button->set_icon(get_theme_icon("Add", "EditorIcons")); + del_button->set_icon(get_theme_icon("Remove", "EditorIcons")); } else if (p_notification == NOTIFICATION_READY) { get_tree()->connect("node_removed", callable_mp(this, &ItemListEditor::_node_removed)); diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index d388296927..74588d4439 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -44,15 +44,15 @@ void MaterialEditor::_notification(int p_what) { if (first_enter) { //it's in propertyeditor so.. could be moved around - light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1", "EditorIcons")); - light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off", "EditorIcons")); - light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2", "EditorIcons")); - light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off", "EditorIcons")); + light_1_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight1", "EditorIcons")); + light_1_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight1Off", "EditorIcons")); + light_2_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight2", "EditorIcons")); + light_2_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight2Off", "EditorIcons")); - sphere_switch->set_normal_texture(get_icon("MaterialPreviewSphereOff", "EditorIcons")); - sphere_switch->set_pressed_texture(get_icon("MaterialPreviewSphere", "EditorIcons")); - box_switch->set_normal_texture(get_icon("MaterialPreviewCubeOff", "EditorIcons")); - box_switch->set_pressed_texture(get_icon("MaterialPreviewCube", "EditorIcons")); + sphere_switch->set_normal_texture(get_theme_icon("MaterialPreviewSphereOff", "EditorIcons")); + sphere_switch->set_pressed_texture(get_theme_icon("MaterialPreviewSphere", "EditorIcons")); + box_switch->set_normal_texture(get_theme_icon("MaterialPreviewCubeOff", "EditorIcons")); + box_switch->set_pressed_texture(get_theme_icon("MaterialPreviewCube", "EditorIcons")); first_enter = false; } @@ -60,7 +60,7 @@ void MaterialEditor::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<Texture2D> checkerboard = get_icon("Checkerboard", "EditorIcons"); + Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons"); Size2 size = get_size(); draw_texture_rect(checkerboard, Rect2(Point2(), size), true); @@ -114,7 +114,7 @@ MaterialEditor::MaterialEditor() { vc->set_stretch(true); add_child(vc); vc->set_anchors_and_margins_preset(PRESET_WIDE); - viewport = memnew(Viewport); + viewport = memnew(SubViewport); Ref<World> world; world.instance(); viewport->set_world(world); //use own world diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index 84e69425d0..895c3f80bd 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -48,7 +48,7 @@ class MaterialEditor : public Control { GDCLASS(MaterialEditor, Control); ViewportContainer *vc; - Viewport *viewport; + SubViewport *viewport; MeshInstance *sphere_instance; MeshInstance *box_instance; DirectionalLight *light1; diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 5a17f0d4f1..352997d6fa 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -57,10 +57,10 @@ void MeshEditor::_notification(int p_what) { if (first_enter) { //it's in propertyeditor so. could be moved around - light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1", "EditorIcons")); - light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off", "EditorIcons")); - light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2", "EditorIcons")); - light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off", "EditorIcons")); + light_1_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight1", "EditorIcons")); + light_1_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight1Off", "EditorIcons")); + light_2_switch->set_normal_texture(get_theme_icon("MaterialPreviewLight2", "EditorIcons")); + light_2_switch->set_pressed_texture(get_theme_icon("MaterialPreviewLight2Off", "EditorIcons")); first_enter = false; } } @@ -115,7 +115,7 @@ void MeshEditor::_bind_methods() { MeshEditor::MeshEditor() { - viewport = memnew(Viewport); + viewport = memnew(SubViewport); Ref<World> world; world.instance(); viewport->set_world(world); //use own world diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h index 87c4a1776b..6d39d49de1 100644 --- a/editor/plugins/mesh_editor_plugin.h +++ b/editor/plugins/mesh_editor_plugin.h @@ -46,7 +46,7 @@ class MeshEditor : public ViewportContainer { float rot_x; float rot_y; - Viewport *viewport; + SubViewport *viewport; MeshInstance *mesh_instance; Spatial *rotation; DirectionalLight *light1; diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 6025e7dd9d..3fdda36177 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -55,7 +55,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { Ref<Mesh> mesh = node->get_mesh(); if (mesh.is_null()) { err_dialog->set_text(TTR("Mesh is empty!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -71,7 +71,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { Ref<Shape> shape = mesh->create_trimesh_shape(); if (shape.is_null()) { err_dialog->set_text(TTR("Couldn't create a Trimesh collision shape.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -130,7 +130,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("This doesn't work on scene root!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -158,7 +158,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("Can't create a single convex collision shape for the scene root.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -166,7 +166,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (shape.is_null()) { err_dialog->set_text(TTR("Couldn't create a single convex collision shape.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -192,7 +192,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("Can't create multiple convex collision shapes for the scene root.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -200,7 +200,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { if (!shapes.size()) { err_dialog->set_text(TTR("Couldn't create any collision shapes.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -258,14 +258,14 @@ void MeshInstanceEditor::_menu_option(int p_option) { Ref<ArrayMesh> mesh2 = node->get_mesh(); if (!mesh2.is_valid()) { err_dialog->set_text(TTR("Contained Mesh is not of type ArrayMesh.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } Error err = mesh2->lightmap_unwrap(node->get_global_transform()); if (err != OK) { err_dialog->set_text(TTR("UV Unwrap failed, mesh may not be manifold?")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -274,7 +274,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { Ref<Mesh> mesh2 = node->get_mesh(); if (!mesh2.is_valid()) { err_dialog->set_text(TTR("No mesh to debug.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } _create_uv_lines(0); @@ -283,7 +283,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { Ref<Mesh> mesh2 = node->get_mesh(); if (!mesh2.is_valid()) { err_dialog->set_text(TTR("No mesh to debug.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } _create_uv_lines(1); @@ -330,7 +330,7 @@ void MeshInstanceEditor::_create_uv_lines(int p_layer) { Vector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2]; if (uv.size() == 0) { err_dialog->set_text(TTR("Model has no UV in this layer")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -374,7 +374,7 @@ void MeshInstanceEditor::_create_uv_lines(int p_layer) { } } - debug_uv_dialog->popup_centered_minsize(); + debug_uv_dialog->popup_centered(); } void MeshInstanceEditor::_debug_uv_draw() { @@ -393,17 +393,17 @@ void MeshInstanceEditor::_create_outline_mesh() { Ref<Mesh> mesh = node->get_mesh(); if (mesh.is_null()) { err_dialog->set_text(TTR("MeshInstance lacks a Mesh!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } if (mesh->get_surface_count() == 0) { err_dialog->set_text(TTR("Mesh has not surface to create outlines from!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } else if (mesh->get_surface_count() == 1 && mesh->surface_get_primitive_type(0) != Mesh::PRIMITIVE_TRIANGLES) { err_dialog->set_text(TTR("Mesh primitive type is not PRIMITIVE_TRIANGLES!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -411,7 +411,7 @@ void MeshInstanceEditor::_create_outline_mesh() { if (mesho.is_null()) { err_dialog->set_text(TTR("Could not create outline!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -444,7 +444,7 @@ MeshInstanceEditor::MeshInstanceEditor() { SpatialEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Mesh")); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshInstance", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshInstance", "EditorIcons")); options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a StaticBody and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection.")); diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index 4e63a498b8..32099c1364 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -36,7 +36,7 @@ #include "scene/3d/mesh_instance.h" #include "scene/3d/navigation_region.h" #include "scene/3d/physics_body.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" #include "spatial_editor_plugin.h" @@ -253,7 +253,7 @@ void MeshLibraryEditor::_bind_methods() { MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) { file = memnew(EditorFileDialog); - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); //not for now? List<String> extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions); @@ -270,7 +270,7 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) { SpatialEditor::get_singleton()->add_control_to_menu_panel(menu); menu->set_position(Point2(1, 1)); menu->set_text(TTR("Mesh Library")); - menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshLibrary", "EditorIcons")); + menu->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MeshLibrary", "EditorIcons")); menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); menu->get_popup()->add_item(TTR("Remove Selected Item"), MENU_OPTION_REMOVE_ITEM); menu->get_popup()->add_separator(); diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp index 27d400c035..dcae59bbe8 100644 --- a/editor/plugins/multimesh_editor_plugin.cpp +++ b/editor/plugins/multimesh_editor_plugin.cpp @@ -56,13 +56,13 @@ void MultiMeshEditor::_populate() { if (multimesh.is_null()) { err_dialog->set_text(TTR("No mesh source specified (and no MultiMesh set in node).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } if (multimesh->get_mesh().is_null()) { err_dialog->set_text(TTR("No mesh source specified (and MultiMesh contains no Mesh).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -74,7 +74,7 @@ void MultiMeshEditor::_populate() { if (!ms_node) { err_dialog->set_text(TTR("Mesh source is invalid (invalid path).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -83,7 +83,7 @@ void MultiMeshEditor::_populate() { if (!ms_instance) { err_dialog->set_text(TTR("Mesh source is invalid (not a MeshInstance).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -92,7 +92,7 @@ void MultiMeshEditor::_populate() { if (mesh.is_null()) { err_dialog->set_text(TTR("Mesh source is invalid (contains no Mesh resource).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } } @@ -100,7 +100,7 @@ void MultiMeshEditor::_populate() { if (surface_source->get_text() == "") { err_dialog->set_text(TTR("No surface source specified.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -109,7 +109,7 @@ void MultiMeshEditor::_populate() { if (!ss_node) { err_dialog->set_text(TTR("Surface source is invalid (invalid path).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -118,7 +118,7 @@ void MultiMeshEditor::_populate() { if (!ss_instance) { err_dialog->set_text(TTR("Surface source is invalid (no geometry).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -129,7 +129,7 @@ void MultiMeshEditor::_populate() { if (geometry.size() == 0) { err_dialog->set_text(TTR("Surface source is invalid (no faces).")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -287,7 +287,7 @@ MultiMeshEditor::MultiMeshEditor() { SpatialEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text("MultiMesh"); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MultiMeshInstance", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("MultiMeshInstance", "EditorIcons")); options->get_popup()->add_item(TTR("Populate Surface")); options->get_popup()->connect("id_pressed", callable_mp(this, &MultiMeshEditor::_menu_option)); diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp index 812144742f..744424a3fa 100644 --- a/editor/plugins/particles_2d_editor_plugin.cpp +++ b/editor/plugins/particles_2d_editor_plugin.cpp @@ -60,7 +60,7 @@ void Particles2DEditorPlugin::make_visible(bool p_visible) { void Particles2DEditorPlugin::_file_selected(const String &p_file) { source_emission_file = p_file; - emission_mask->popup_centered_minsize(); + emission_mask->popup_centered(); } void Particles2DEditorPlugin::_menu_callback(int p_idx) { @@ -72,7 +72,7 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { generate_seconds->set_value(1.0); else generate_seconds->set_value(trunc(gen_time) + 1.0); - generate_visibility_rect->popup_centered_minsize(); + generate_visibility_rect->popup_centered(); } break; case MENU_LOAD_EMISSION_MASK: { @@ -81,7 +81,7 @@ void Particles2DEditorPlugin::_menu_callback(int p_idx) { } break; case MENU_CLEAR_EMISSION_MASK: { - emission_mask->popup_centered_minsize(); + emission_mask->popup_centered(); } break; case MENU_OPTION_CONVERT_TO_CPU_PARTICLES: { @@ -350,7 +350,7 @@ void Particles2DEditorPlugin::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { menu->get_popup()->connect("id_pressed", callable_mp(this, &Particles2DEditorPlugin::_menu_callback)); - menu->set_icon(menu->get_popup()->get_icon("Particles2D", "EditorIcons")); + menu->set_icon(menu->get_theme_icon("Particles2D", "EditorIcons")); file->connect("file_selected", callable_mp(this, &Particles2DEditorPlugin::_file_selected)); } } @@ -389,7 +389,7 @@ Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) { for (List<String>::Element *E = ext.front(); E; E = E->next()) { file->add_filter("*." + E->get() + "; " + E->get().to_upper()); } - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); toolbar->add_child(file); epoints = memnew(SpinBox); diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index a4d704c6e1..63acf7cfb6 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -244,7 +244,7 @@ void ParticlesEditor::_node_removed(Node *p_node) { void ParticlesEditor::_notification(int p_notification) { if (p_notification == NOTIFICATION_ENTER_TREE) { - options->set_icon(options->get_popup()->get_icon("Particles", "EditorIcons")); + options->set_icon(options->get_popup()->get_theme_icon("Particles", "EditorIcons")); get_tree()->connect("node_removed", callable_mp(this, &ParticlesEditor::_node_removed)); } } @@ -260,7 +260,7 @@ void ParticlesEditor::_menu_option(int p_option) { generate_seconds->set_value(1.0); else generate_seconds->set_value(trunc(gen_time) + 1.0); - generate_aabb->popup_centered_minsize(); + generate_aabb->popup_centered(); } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { Ref<ParticlesMaterial> material = node->get_process_material(); diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 165df6b500..75c5fcb994 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -373,12 +373,12 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - const Ref<Texture2D> path_sharp_handle = get_icon("EditorPathSharpHandle", "EditorIcons"); - const Ref<Texture2D> path_smooth_handle = get_icon("EditorPathSmoothHandle", "EditorIcons"); + const Ref<Texture2D> path_sharp_handle = get_theme_icon("EditorPathSharpHandle", "EditorIcons"); + const Ref<Texture2D> path_smooth_handle = get_theme_icon("EditorPathSmoothHandle", "EditorIcons"); // Both handle icons must be of the same size const Size2 handle_size = path_sharp_handle->get_size(); - const Ref<Texture2D> curve_handle = get_icon("EditorCurveHandle", "EditorIcons"); + const Ref<Texture2D> curve_handle = get_theme_icon("EditorCurveHandle", "EditorIcons"); const Size2 curve_handle_size = curve_handle->get_size(); Ref<Curve2D> curve = node->get_curve(); @@ -420,7 +420,7 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } if (on_edge) { - Ref<Texture2D> add_handle = get_icon("EditorHandleAdd", "EditorIcons"); + Ref<Texture2D> add_handle = get_theme_icon("EditorHandleAdd", "EditorIcons"); p_overlay->draw_texture(add_handle, edge_point - add_handle->get_size() * 0.5); } } @@ -548,35 +548,35 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { sep = memnew(VSeparator); base_hb->add_child(sep); curve_edit = memnew(ToolButton); - curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); + curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT)); base_hb->add_child(curve_edit); curve_edit_curve = memnew(ToolButton); - curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCurve", "EditorIcons")); + curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCurve", "EditorIcons")); curve_edit_curve->set_toggle_mode(true); curve_edit_curve->set_focus_mode(Control::FOCUS_NONE); curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)")); curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT_CURVE)); base_hb->add_child(curve_edit_curve); curve_create = memnew(ToolButton); - curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); + curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)")); curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_CREATE)); base_hb->add_child(curve_create); curve_del = memnew(ToolButton); - curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons")); + curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_DELETE)); base_hb->add_child(curve_del); curve_close = memnew(ToolButton); - curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveClose", "EditorIcons")); + curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip(TTR("Close Curve")); curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(ACTION_CLOSE)); diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index 42b1045666..b6842be76c 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -571,28 +571,28 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { sep->hide(); SpatialEditor::get_singleton()->add_control_to_menu_panel(sep); curve_edit = memnew(ToolButton); - curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); + curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit); curve_create = memnew(ToolButton); - curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); + curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->hide(); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create); curve_del = memnew(ToolButton); - curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons")); + curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->hide(); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del); curve_close = memnew(ToolButton); - curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveClose", "EditorIcons")); + curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->hide(); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip(TTR("Close Curve")); diff --git a/editor/plugins/physical_bone_plugin.cpp b/editor/plugins/physical_bone_plugin.cpp index e0d48afeef..ec29310029 100644 --- a/editor/plugins/physical_bone_plugin.cpp +++ b/editor/plugins/physical_bone_plugin.cpp @@ -61,7 +61,7 @@ PhysicalBoneEditor::PhysicalBoneEditor(EditorNode *p_editor) : spatial_editor_hb->add_child(button_transform_joint); button_transform_joint->set_text(TTR("Move Joint")); - button_transform_joint->set_icon(SpatialEditor::get_singleton()->get_icon("PhysicalBone", "EditorIcons")); + button_transform_joint->set_icon(SpatialEditor::get_singleton()->get_theme_icon("PhysicalBone", "EditorIcons")); button_transform_joint->set_toggle_mode(true); button_transform_joint->connect("toggled", callable_mp(this, &PhysicalBoneEditor::_on_toggle_button_transform_joint)); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 8c115586a4..5a94c95dd7 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -31,8 +31,8 @@ #include "polygon_2d_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/os/file_access.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -70,28 +70,28 @@ void Polygon2DEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - uv_edit_draw->add_style_override("panel", get_stylebox("bg", "Tree")); - bone_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + bone_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); } break; case NOTIFICATION_READY: { - button_uv->set_icon(get_icon("Uv", "EditorIcons")); + button_uv->set_icon(get_theme_icon("Uv", "EditorIcons")); - uv_button[UV_MODE_CREATE]->set_icon(get_icon("Edit", "EditorIcons")); - uv_button[UV_MODE_CREATE_INTERNAL]->set_icon(get_icon("EditInternal", "EditorIcons")); - uv_button[UV_MODE_REMOVE_INTERNAL]->set_icon(get_icon("RemoveInternal", "EditorIcons")); - uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect", "EditorIcons")); - uv_button[UV_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons")); - uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); - uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); - uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_icon("Edit", "EditorIcons")); - uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_icon("Close", "EditorIcons")); - uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_icon("PaintVertex", "EditorIcons")); - uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_icon("UnpaintVertex", "EditorIcons")); + uv_button[UV_MODE_CREATE]->set_icon(get_theme_icon("Edit", "EditorIcons")); + uv_button[UV_MODE_CREATE_INTERNAL]->set_icon(get_theme_icon("EditInternal", "EditorIcons")); + uv_button[UV_MODE_REMOVE_INTERNAL]->set_icon(get_theme_icon("RemoveInternal", "EditorIcons")); + uv_button[UV_MODE_EDIT_POINT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + uv_button[UV_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); + uv_button[UV_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); + uv_button[UV_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); + uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_theme_icon("Edit", "EditorIcons")); + uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_theme_icon("Close", "EditorIcons")); + uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_theme_icon("PaintVertex", "EditorIcons")); + uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_theme_icon("UnpaintVertex", "EditorIcons")); - b_snap_grid->set_icon(get_icon("Grid", "EditorIcons")); - b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); - uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); + b_snap_grid->set_icon(get_theme_icon("Grid", "EditorIcons")); + b_snap_enable->set_icon(get_theme_icon("SnapGrid", "EditorIcons")); + uv_icon_zoom->set_texture(get_theme_icon("Zoom", "EditorIcons")); uv_vscroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE); uv_hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE); @@ -110,7 +110,7 @@ void Polygon2DEditor::_sync_bones() { Skeleton2D *skeleton = NULL; if (!node->has_node(node->get_skeleton())) { error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node")); - error->popup_centered_minsize(); + error->popup_centered(); } else { Node *sn = node->get_node(node->get_skeleton()); skeleton = Object::cast_to<Skeleton2D>(sn); @@ -121,7 +121,7 @@ void Polygon2DEditor::_sync_bones() { if (!skeleton) { error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node")); - error->popup_centered_minsize(); + error->popup_centered(); } else { for (int i = 0; i < skeleton->get_bone_count(); i++) { NodePath path = skeleton->get_path_to(skeleton->get_bone(i)); @@ -275,7 +275,7 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { void Polygon2DEditor::_uv_edit_popup_hide() { - EditorSettings::get_singleton()->set("interface/dialogs/uv_editor_bounds", uv_edit->get_rect()); + EditorSettings::get_singleton()->set("interface/dialogs/uv_editor_bounds", Rect2(uv_edit->get_position(), uv_edit->get_size())); _cancel_editing(); } @@ -289,7 +289,7 @@ void Polygon2DEditor::_menu_option(int p_option) { if (node->get_texture().is_null()) { error->set_text(TTR("No texture in this polygon.\nSet a texture to be able to edit UV.")); - error->popup_centered_minsize(); + error->popup_centered(); return; } @@ -351,7 +351,7 @@ void Polygon2DEditor::_menu_option(int p_option) { } break; case UVEDIT_GRID_SETTINGS: { - grid_settings->popup_centered_minsize(); + grid_settings->popup_centered(); } break; default: { @@ -683,7 +683,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { //close if (polygon_create.size() < 3) { error->set_text(TTR("Invalid Polygon (need 3 different vertices)")); - error->popup_centered_minsize(); + error->popup_centered(); } else { Array polygons = node->get_polygons(); polygons = polygons.duplicate(); //copy because its a reference @@ -810,7 +810,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (mm.is_valid()) { - if ((mm->get_button_mask() & BUTTON_MASK_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if ((mm->get_button_mask() & BUTTON_MASK_MIDDLE) || InputFilter::get_singleton()->is_key_pressed(KEY_SPACE)) { Vector2 drag(mm->get_relative().x, mm->get_relative().y); uv_hscroll->set_value(uv_hscroll->get_value() - drag.x); @@ -1050,7 +1050,7 @@ void Polygon2DEditor::_uv_draw() { } // All UV points are sharp, so use the sharp handle icon - Ref<Texture2D> handle = get_icon("EditorPathSharpHandle", "EditorIcons"); + Ref<Texture2D> handle = get_theme_icon("EditorPathSharpHandle", "EditorIcons"); Color poly_line_color = Color(0.9, 0.5, 0.5); if (polygons.size() || polygon_create.size()) { @@ -1265,8 +1265,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit = memnew(AcceptDialog); add_child(uv_edit); uv_edit->set_title(TTR("Polygon 2D UV Editor")); - uv_edit->set_resizable(true); - uv_edit->connect("popup_hide", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); + uv_edit->connect("cancelled", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); VBoxContainer *uv_main_vb = memnew(VBoxContainer); uv_edit->add_child(uv_main_vb); diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index feef505acc..8def56f968 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -41,7 +41,7 @@ void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) { void ResourcePreloaderEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - load->set_icon(get_icon("Folder", "EditorIcons")); + load->set_icon(get_theme_icon("Folder", "EditorIcons")); } if (p_what == NOTIFICATION_READY) { @@ -67,7 +67,7 @@ void ResourcePreloaderEditor::_files_load_request(const Vector<String> &p_paths) dialog->set_title(TTR("Error!")); //dialog->get_cancel()->set_text("Close"); dialog->get_ok()->set_text(TTR("Close")); - dialog->popup_centered_minsize(); + dialog->popup_centered(); return; ///beh should show an error i guess } @@ -98,7 +98,7 @@ void ResourcePreloaderEditor::_load_pressed() { for (int i = 0; i < extensions.size(); i++) file->add_filter("*." + extensions[i]); - file->set_mode(EditorFileDialog::MODE_OPEN_FILES); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); file->popup_centered_ratio(); } @@ -152,7 +152,7 @@ void ResourcePreloaderEditor::_paste_pressed() { dialog->set_text(TTR("Resource clipboard is empty!")); dialog->set_title(TTR("Error!")); dialog->get_ok()->set_text(TTR("Close")); - dialog->popup_centered_minsize(); + dialog->popup_centered(); return; ///beh should show an error i guess } @@ -215,11 +215,11 @@ void ResourcePreloaderEditor::_update_library() { ti->set_selectable(1, false); if (type == "PackedScene") { - ti->add_button(1, get_icon("InstanceOptions", "EditorIcons"), BUTTON_OPEN_SCENE, false, TTR("Open in Editor")); + ti->add_button(1, get_theme_icon("InstanceOptions", "EditorIcons"), BUTTON_OPEN_SCENE, false, TTR("Open in Editor")); } else { - ti->add_button(1, get_icon("Load", "EditorIcons"), BUTTON_EDIT_RESOURCE, false, TTR("Open in Editor")); + ti->add_button(1, get_theme_icon("Load", "EditorIcons"), BUTTON_EDIT_RESOURCE, false, TTR("Open in Editor")); } - ti->add_button(1, get_icon("Remove", "EditorIcons"), BUTTON_REMOVE, false, TTR("Remove")); + ti->add_button(1, get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE, false, TTR("Remove")); } //player->add_resource("default",resource); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index d932305c63..0f803218ea 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "root_motion_editor_plugin.h" #include "editor/editor_node.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void EditorPropertyRootMotion::_confirmed() { @@ -152,7 +152,7 @@ void EditorPropertyRootMotion::_node_assign() { ti->set_text(0, F->get()); ti->set_selectable(0, true); ti->set_editable(0, false); - ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, accum); } else { ti = parenthood[accum]; @@ -161,7 +161,7 @@ void EditorPropertyRootMotion::_node_assign() { ti->set_selectable(0, true); ti->set_text(0, concat); - ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); + ti->set_icon(0, get_theme_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, path); if (path == current) { ti->select(0); @@ -242,7 +242,7 @@ void EditorPropertyRootMotion::setup(const NodePath &p_base_hint) { void EditorPropertyRootMotion::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - Ref<Texture2D> t = get_icon("Clear", "EditorIcons"); + Ref<Texture2D> t = get_theme_icon("Clear", "EditorIcons"); clear->set_icon(t); } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index b3f78b5406..0e867f7b16 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "script_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" #include "core/os/file_access.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/project_settings.h" @@ -45,9 +45,10 @@ #include "editor/find_in_files.h" #include "editor/node_dock.h" #include "editor/plugins/shader_editor_plugin.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" #include "script_text_editor.h" +#include "servers/display_server.h" #include "text_editor.h" /*** SCRIPT EDITOR ****/ @@ -215,8 +216,8 @@ void ScriptEditorQuickOpen::_notification(int p_what) { search_box->set_clear_button_enabled(true); [[fallthrough]]; } - case NOTIFICATION_THEME_CHANGED: { - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + case NOTIFICATION_VISIBILITY_CHANGED: { + search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons")); } break; case NOTIFICATION_EXIT_TREE: { disconnect("confirmed", callable_mp(this, &ScriptEditorQuickOpen::_confirmed)); @@ -246,7 +247,7 @@ ScriptEditorQuickOpen::ScriptEditorQuickOpen() { search_options->connect("item_activated", callable_mp(this, &ScriptEditorQuickOpen::_confirmed)); search_options->set_hide_root(true); search_options->set_hide_folding(true); - search_options->add_constant_override("draw_guides", 1); + search_options->add_theme_constant_override("draw_guides", 1); } ///////////////////////////////// @@ -428,7 +429,7 @@ void ScriptEditor::_go_to_tab(int p_idx) { if (Object::cast_to<ScriptEditorBase>(c)) { script_name_label->set_text(Object::cast_to<ScriptEditorBase>(c)->get_name()); - script_icon->set_texture(Object::cast_to<ScriptEditorBase>(c)->get_icon()); + script_icon->set_texture(Object::cast_to<ScriptEditorBase>(c)->get_theme_icon()); if (is_visible_in_tree()) Object::cast_to<ScriptEditorBase>(c)->ensure_focus(); @@ -442,7 +443,7 @@ void ScriptEditor::_go_to_tab(int p_idx) { if (Object::cast_to<EditorHelp>(c)) { script_name_label->set_text(Object::cast_to<EditorHelp>(c)->get_class()); - script_icon->set_texture(get_icon("Help", "EditorIcons")); + script_icon->set_texture(get_theme_icon("Help", "EditorIcons")); if (is_visible_in_tree()) Object::cast_to<EditorHelp>(c)->set_focused(); } @@ -556,7 +557,7 @@ void ScriptEditor::_open_recent_script(int p_idx) { void ScriptEditor::_show_error_dialog(String p_path) { error_dialog->set_text(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_path)); - error_dialog->popup_centered_minsize(); + error_dialog->popup_centered(); } void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { @@ -651,7 +652,7 @@ void ScriptEditor::_close_docs_tab() { void ScriptEditor::_copy_script_path() { ScriptEditorBase *se = _get_current_editor(); RES script = se->get_edited_resource(); - OS::get_singleton()->set_clipboard(script->get_path()); + DisplayServer::get_singleton()->clipboard_set(script->get_path()); } void ScriptEditor::_close_other_tabs() { @@ -703,7 +704,7 @@ void ScriptEditor::_close_all_tabs() { void ScriptEditor::_ask_close_current_unsaved_tab(ScriptEditorBase *current) { erase_tab_confirm->set_text(TTR("Close and save changes?") + "\n\"" + current->get_name() + "\""); - erase_tab_confirm->popup_centered_minsize(); + erase_tab_confirm->popup_centered(); } void ScriptEditor::_resave_scripts(const String &p_str) { @@ -995,7 +996,7 @@ void ScriptEditor::_menu_option(int p_option) { script_create_dialog->popup_centered(); } break; case FILE_NEW_TEXTFILE: { - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_dialog_option = FILE_NEW_TEXTFILE; @@ -1004,7 +1005,7 @@ void ScriptEditor::_menu_option(int p_option) { file_dialog->set_title(TTR("New Text File...")); } break; case FILE_OPEN: { - file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_dialog_option = FILE_OPEN; @@ -1169,7 +1170,7 @@ void ScriptEditor::_menu_option(int p_option) { Ref<TextFile> text_file = current->get_edited_resource(); if (text_file != NULL) { - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_dialog_option = FILE_SAVE_AS; @@ -1335,7 +1336,7 @@ void ScriptEditor::_menu_option(int p_option) { void ScriptEditor::_theme_option(int p_option) { switch (p_option) { case THEME_IMPORT: { - file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_dialog_option = THEME_IMPORT; file_dialog->clear_filters(); @@ -1360,7 +1361,7 @@ void ScriptEditor::_theme_option(int p_option) { } void ScriptEditor::_show_save_theme_as_dialog() { - file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM); file_dialog_option = THEME_SAVE_AS; file_dialog->clear_filters(); @@ -1395,19 +1396,19 @@ void ScriptEditor::_notification(int p_what) { } case NOTIFICATION_THEME_CHANGED: { - help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); - site_search->set_icon(get_icon("Instance", "EditorIcons")); - request_docs->set_icon(get_icon("Issue", "EditorIcons")); + help_search->set_icon(get_theme_icon("HelpSearch", "EditorIcons")); + site_search->set_icon(get_theme_icon("Instance", "EditorIcons")); + request_docs->set_icon(get_theme_icon("Issue", "EditorIcons")); - script_forward->set_icon(get_icon("Forward", "EditorIcons")); - script_back->set_icon(get_icon("Back", "EditorIcons")); + script_forward->set_icon(get_theme_icon("Forward", "EditorIcons")); + script_back->set_icon(get_theme_icon("Back", "EditorIcons")); - members_overview_alphabeta_sort_button->set_icon(get_icon("Sort", "EditorIcons")); + members_overview_alphabeta_sort_button->set_icon(get_theme_icon("Sort", "EditorIcons")); - filter_scripts->set_right_icon(get_icon("Search", "EditorIcons")); - filter_methods->set_right_icon(get_icon("Search", "EditorIcons")); + filter_scripts->set_right_icon(get_theme_icon("Search", "EditorIcons")); + filter_methods->set_right_icon(get_theme_icon("Search", "EditorIcons")); - filename->add_style_override("normal", editor->get_gui_base()->get_stylebox("normal", "LineEdit")); + filename->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("normal", "LineEdit")); recent_scripts->set_as_minsize(); } break; @@ -1424,7 +1425,7 @@ void ScriptEditor::_notification(int p_what) { editor->disconnect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop)); } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_FOCUS_IN: { _test_script_times_on_disk(); _update_modified_scripts_for_external_editor(); @@ -1550,7 +1551,7 @@ void ScriptEditor::_help_overview_selected(int p_idx) { void ScriptEditor::_script_selected(int p_idx) { - grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing + grab_focus_block = !InputFilter::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing _go_to_tab(script_list->get_item_metadata(p_idx)); grab_focus_block = false; @@ -1717,8 +1718,8 @@ void ScriptEditor::_update_script_colors() { bool highlight_current = EditorSettings::get_singleton()->get("text_editor/script_list/highlight_current_script"); int hist_size = EditorSettings::get_singleton()->get("text_editor/script_list/script_temperature_history_size"); - Color hot_color = get_color("accent_color", "Editor"); - Color cold_color = get_color("font_color", "Editor"); + Color hot_color = get_theme_color("accent_color", "Editor"); + Color cold_color = get_theme_color("font_color", "Editor"); for (int i = 0; i < script_list->get_item_count(); i++) { @@ -1775,7 +1776,7 @@ void ScriptEditor::_update_script_names() { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); if (se) { - Ref<Texture2D> icon = se->get_icon(); + Ref<Texture2D> icon = se->get_theme_icon(); String path = se->get_edited_resource()->get_path(); bool built_in = !path.is_resource_file(); String name; @@ -1836,7 +1837,7 @@ void ScriptEditor::_update_script_names() { if (eh) { String name = eh->get_class(); - Ref<Texture2D> icon = get_icon("Help", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon("Help", "EditorIcons"); String tooltip = vformat(TTR("%s Class Reference"), name); _ScriptEditorItemData sd; @@ -2346,12 +2347,12 @@ Variant ScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(cur_node); if (se) { preview_name = se->get_name(); - preview_icon = se->get_icon(); + preview_icon = se->get_theme_icon(); } EditorHelp *eh = Object::cast_to<EditorHelp>(cur_node); if (eh) { preview_name = eh->get_class(); - preview_icon = get_icon("Help", "EditorIcons"); + preview_icon = get_theme_icon("Help", "EditorIcons"); } if (!preview_icon.is_null()) { @@ -2952,7 +2953,7 @@ void ScriptEditor::_on_find_in_files_requested(String text) { find_in_files_dialog->set_find_in_files_mode(FindInFilesDialog::SEARCH_MODE); find_in_files_dialog->set_search_text(text); - find_in_files_dialog->popup_centered_minsize(); + find_in_files_dialog->popup_centered(); } void ScriptEditor::_on_replace_in_files_requested(String text) { @@ -2960,7 +2961,7 @@ void ScriptEditor::_on_replace_in_files_requested(String text) { find_in_files_dialog->set_find_in_files_mode(FindInFilesDialog::REPLACE_MODE); find_in_files_dialog->set_search_text(text); find_in_files_dialog->set_replace_text(""); - find_in_files_dialog->popup_centered_minsize(); + find_in_files_dialog->popup_centered(); } void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_number, int begin, int end) { @@ -3111,7 +3112,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { context_menu = memnew(PopupMenu); add_child(context_menu); context_menu->connect("id_pressed", callable_mp(this, &ScriptEditor::_menu_option)); - context_menu->set_hide_on_window_lose_focus(true); overview_vbox = memnew(VBoxContainer); overview_vbox->set_custom_minimum_size(Size2(0, 90)); @@ -3124,7 +3124,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { filename = memnew(Label); filename->set_clip_text(true); filename->set_h_size_flags(SIZE_EXPAND_FILL); - filename->add_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_stylebox("normal", "LineEdit")); + filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("normal", "LineEdit")); buttons_hbox->add_child(filename); members_overview_alphabeta_sort_button = memnew(ToolButton); @@ -3172,7 +3172,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(file_menu); file_menu->set_text(TTR("File")); file_menu->set_switch_on_hover(true); - file_menu->get_popup()->set_hide_on_window_lose_focus(true); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script...")), FILE_NEW); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New Text File...")), FILE_NEW_TEXTFILE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open...")), FILE_OPEN); @@ -3229,7 +3229,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(script_search_menu); script_search_menu->set_text(TTR("Search")); script_search_menu->set_switch_on_hover(true); - script_search_menu->get_popup()->set_hide_on_window_lose_focus(true); script_search_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptEditor::_menu_option)); MenuButton *debug_menu = memnew(MenuButton); @@ -3291,7 +3290,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { erase_tab_confirm = memnew(ConfirmationDialog); erase_tab_confirm->get_ok()->set_text(TTR("Save")); - erase_tab_confirm->add_button(TTR("Discard"), OS::get_singleton()->get_swap_ok_cancel(), "discard"); + erase_tab_confirm->add_button(TTR("Discard"), DisplayServer::get_singleton()->get_swap_ok_cancel(), "discard"); erase_tab_confirm->connect("confirmed", callable_mp(this, &ScriptEditor::_close_current_tab)); erase_tab_confirm->connect("custom_action", callable_mp(this, &ScriptEditor::_close_discard_current_tab)); add_child(erase_tab_confirm); @@ -3325,7 +3324,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { disk_changed->connect("confirmed", callable_mp(this, &ScriptEditor::_reload_scripts)); disk_changed->get_ok()->set_text(TTR("Reload")); - disk_changed->add_button(TTR("Resave"), !OS::get_singleton()->get_swap_ok_cancel(), "resave"); + disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "resave"); disk_changed->connect("custom_action", callable_mp(this, &ScriptEditor::_resave_scripts)); } @@ -3366,8 +3365,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { ScriptServer::edit_request_func = _open_script_request; - add_style_override("panel", editor->get_gui_base()->get_stylebox("ScriptEditorPanel", "EditorStyles")); - tab_container->add_style_override("panel", editor->get_gui_base()->get_stylebox("ScriptEditor", "EditorStyles")); + add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("ScriptEditorPanel", "EditorStyles")); + tab_container->add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("ScriptEditor", "EditorStyles")); } ScriptEditor::~ScriptEditor() { diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 81f9595264..ec598f0b42 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -92,7 +92,7 @@ public: virtual void set_edited_resource(const RES &p_res) = 0; virtual void reload_text() = 0; virtual String get_name() = 0; - virtual Ref<Texture2D> get_icon() = 0; + virtual Ref<Texture2D> get_theme_icon() = 0; virtual bool is_unsaved() = 0; virtual Variant get_edit_state() = 0; virtual void set_edit_state(const Variant &p_state) = 0; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 176df7efb8..2e95bb92f4 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -65,7 +65,8 @@ void ConnectionInfoDialog::popup_connections(String p_method, Vector<Node *> p_n node_item->set_editable(0, false); node_item->set_text(1, connection.signal.get_name()); - node_item->set_icon(1, get_parent_control()->get_icon("Slot", "EditorIcons")); + Control *p = Object::cast_to<Control>(get_parent()); + node_item->set_icon(1, p->get_theme_icon("Slot", "EditorIcons")); node_item->set_selectable(1, false); node_item->set_editable(1, false); @@ -83,10 +84,10 @@ ConnectionInfoDialog::ConnectionInfoDialog() { set_title(TTR("Connections to method:")); VBoxContainer *vbc = memnew(VBoxContainer); - vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -8 * EDSCALE); - vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -8 * EDSCALE); + vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -8 * EDSCALE); add_child(vbc); method = memnew(Label); @@ -101,7 +102,7 @@ ConnectionInfoDialog::ConnectionInfoDialog() { tree->set_column_title(1, TTR("Signal")); tree->set_column_title(2, TTR("Target")); vbc->add_child(tree); - tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->set_allow_rmb_select(true); } @@ -229,36 +230,36 @@ void ScriptTextEditor::_load_theme_settings() { Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); Color string_color = EDITOR_GET("text_editor/highlighting/string_color"); - text_edit->add_color_override("background_color", background_color); - text_edit->add_color_override("completion_background_color", completion_background_color); - text_edit->add_color_override("completion_selected_color", completion_selected_color); - text_edit->add_color_override("completion_existing_color", completion_existing_color); - text_edit->add_color_override("completion_scroll_color", completion_scroll_color); - text_edit->add_color_override("completion_font_color", completion_font_color); - text_edit->add_color_override("font_color", text_color); - text_edit->add_color_override("line_number_color", line_number_color); - text_edit->add_color_override("safe_line_number_color", safe_line_number_color); - text_edit->add_color_override("caret_color", caret_color); - text_edit->add_color_override("caret_background_color", caret_background_color); - text_edit->add_color_override("font_color_selected", text_selected_color); - text_edit->add_color_override("selection_color", selection_color); - text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color); - text_edit->add_color_override("current_line_color", current_line_color); - text_edit->add_color_override("line_length_guideline_color", line_length_guideline_color); - text_edit->add_color_override("word_highlighted_color", word_highlighted_color); - text_edit->add_color_override("number_color", number_color); - text_edit->add_color_override("function_color", function_color); - text_edit->add_color_override("member_variable_color", member_variable_color); - text_edit->add_color_override("bookmark_color", bookmark_color); - text_edit->add_color_override("breakpoint_color", breakpoint_color); - text_edit->add_color_override("executing_line_color", executing_line_color); - text_edit->add_color_override("mark_color", mark_color); - text_edit->add_color_override("code_folding_color", code_folding_color); - text_edit->add_color_override("search_result_color", search_result_color); - text_edit->add_color_override("search_result_border_color", search_result_border_color); - text_edit->add_color_override("symbol_color", symbol_color); - - text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6)); + text_edit->add_theme_color_override("background_color", background_color); + text_edit->add_theme_color_override("completion_background_color", completion_background_color); + text_edit->add_theme_color_override("completion_selected_color", completion_selected_color); + text_edit->add_theme_color_override("completion_existing_color", completion_existing_color); + text_edit->add_theme_color_override("completion_scroll_color", completion_scroll_color); + text_edit->add_theme_color_override("completion_font_color", completion_font_color); + text_edit->add_theme_color_override("font_color", text_color); + text_edit->add_theme_color_override("line_number_color", line_number_color); + text_edit->add_theme_color_override("safe_line_number_color", safe_line_number_color); + text_edit->add_theme_color_override("caret_color", caret_color); + text_edit->add_theme_color_override("caret_background_color", caret_background_color); + text_edit->add_theme_color_override("font_color_selected", text_selected_color); + text_edit->add_theme_color_override("selection_color", selection_color); + text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); + text_edit->add_theme_color_override("current_line_color", current_line_color); + text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); + text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color); + text_edit->add_theme_color_override("number_color", number_color); + text_edit->add_theme_color_override("function_color", function_color); + text_edit->add_theme_color_override("member_variable_color", member_variable_color); + text_edit->add_theme_color_override("bookmark_color", bookmark_color); + text_edit->add_theme_color_override("breakpoint_color", breakpoint_color); + text_edit->add_theme_color_override("executing_line_color", executing_line_color); + text_edit->add_theme_color_override("mark_color", mark_color); + text_edit->add_theme_color_override("code_folding_color", code_folding_color); + text_edit->add_theme_color_override("search_result_color", search_result_color); + text_edit->add_theme_color_override("search_result_border_color", search_result_border_color); + text_edit->add_theme_color_override("symbol_color", symbol_color); + + text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6)); colors_cache.symbol_color = symbol_color; colors_cache.keyword_color = keyword_color; @@ -555,10 +556,10 @@ String ScriptTextEditor::get_name() { return name; } -Ref<Texture2D> ScriptTextEditor::get_icon() { +Ref<Texture2D> ScriptTextEditor::get_theme_icon() { - if (get_parent_control() && get_parent_control()->has_icon(script->get_class(), "EditorIcons")) { - return get_parent_control()->get_icon(script->get_class(), "EditorIcons"); + if (get_parent_control() && get_parent_control()->has_theme_icon(script->get_class(), "EditorIcons")) { + return get_parent_control()->get_theme_icon(script->get_class(), "EditorIcons"); } return Ref<Texture2D>(); @@ -614,7 +615,7 @@ void ScriptTextEditor::_validate_script() { String target_path = base == connection.callable.get_object() ? base_path : base_path + "/" + base->get_path_to(Object::cast_to<Node>(connection.callable.get_object())); warnings_panel->push_cell(); - warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor")); + warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor")); warnings_panel->add_text(vformat(TTR("Missing connected method '%s' for signal '%s' from node '%s' to node '%s'."), connection.callable.get_method(), connection.signal.get_name(), source_path, target_path)); warnings_panel->pop(); // Color. warnings_panel->pop(); // Cell. @@ -634,7 +635,7 @@ void ScriptTextEditor::_validate_script() { warnings_panel->push_cell(); warnings_panel->push_meta(w.line - 1); - warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor")); + warnings_panel->push_color(warnings_panel->get_theme_color("warning_color", "Editor")); warnings_panel->add_text(TTR("Line") + " " + itos(w.line)); warnings_panel->add_text(" (" + w.string_code + "):"); warnings_panel->pop(); // Color. @@ -821,7 +822,7 @@ void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force) { - if (color_panel->is_visible_in_tree()) return; + if (color_panel->is_visible()) return; Node *base = get_tree()->get_edited_scene_root(); if (base) { base = _find_node_for_script(base, base, script); @@ -1046,7 +1047,7 @@ void ScriptTextEditor::_update_connected_methods() { String name = functions[j].get_slice(":", 0); if (name == connection.callable.get_method()) { line = functions[j].get_slice(":", 1).to_int(); - text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.callable.get_method()); + text_edit->set_line_info_icon(line - 1, get_parent_control()->get_theme_icon("Slot", "EditorIcons"), connection.callable.get_method()); methods_found.insert(connection.callable.get_method()); break; } @@ -1779,7 +1780,7 @@ ScriptTextEditor::ScriptTextEditor() { code_editor = memnew(CodeTextEditor); editor_box->add_child(code_editor); - code_editor->add_constant_override("separation", 2); + code_editor->add_theme_constant_override("separation", 2); code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE); code_editor->connect("validate_script", callable_mp(this, &ScriptTextEditor::_validate_script)); code_editor->connect("load_theme_settings", callable_mp(this, &ScriptTextEditor::_load_theme_settings)); @@ -1817,7 +1818,6 @@ ScriptTextEditor::ScriptTextEditor() { context_menu = memnew(PopupMenu); add_child(context_menu); context_menu->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option)); - context_menu->set_hide_on_window_lose_focus(true); color_panel = memnew(PopupPanel); add_child(color_panel); @@ -1838,7 +1838,7 @@ ScriptTextEditor::ScriptTextEditor() { edit_menu = memnew(MenuButton); edit_menu->set_text(TTR("Edit")); edit_menu->set_switch_on_hover(true); - edit_menu->get_popup()->set_hide_on_window_lose_focus(true); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO); edit_menu->get_popup()->add_separator(); @@ -1889,7 +1889,7 @@ ScriptTextEditor::ScriptTextEditor() { edit_hb->add_child(search_menu); search_menu->set_text(TTR("Search")); search_menu->set_switch_on_hover(true); - search_menu->get_popup()->set_hide_on_window_lose_focus(true); + search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV); @@ -1918,7 +1918,7 @@ ScriptTextEditor::ScriptTextEditor() { goto_menu->get_popup()->add_child(bookmarks_menu); goto_menu->get_popup()->add_submenu_item(TTR("Bookmarks"), "Bookmarks"); _update_bookmark_list(); - bookmarks_menu->connect("about_to_show", callable_mp(this, &ScriptTextEditor::_update_bookmark_list)); + bookmarks_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_update_bookmark_list)); bookmarks_menu->connect("index_pressed", callable_mp(this, &ScriptTextEditor::_bookmark_item_pressed)); breakpoints_menu = memnew(PopupMenu); @@ -1926,7 +1926,7 @@ ScriptTextEditor::ScriptTextEditor() { goto_menu->get_popup()->add_child(breakpoints_menu); goto_menu->get_popup()->add_submenu_item(TTR("Breakpoints"), "Breakpoints"); _update_breakpoint_list(); - breakpoints_menu->connect("about_to_show", callable_mp(this, &ScriptTextEditor::_update_breakpoint_list)); + breakpoints_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_update_breakpoint_list)); breakpoints_menu->connect("index_pressed", callable_mp(this, &ScriptTextEditor::_breakpoint_item_pressed)); quick_open = memnew(ScriptEditorQuickOpen); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index d2f0b310e6..51ce30c831 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -201,7 +201,7 @@ public: virtual Vector<String> get_functions(); virtual void reload_text(); virtual String get_name(); - virtual Ref<Texture2D> get_icon(); + virtual Ref<Texture2D> get_theme_icon(); virtual bool is_unsaved(); virtual Variant get_edit_state(); virtual void set_edit_state(const Variant &p_state); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 01b1e21153..c38bb09567 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -38,6 +38,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/property_editor.h" +#include "servers/display_server.h" #include "servers/visual/shader_types.h" /*** SHADER SCRIPT EDITOR ****/ @@ -116,33 +117,33 @@ void ShaderTextEditor::_load_theme_settings() { Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - get_text_edit()->add_color_override("background_color", background_color); - get_text_edit()->add_color_override("completion_background_color", completion_background_color); - get_text_edit()->add_color_override("completion_selected_color", completion_selected_color); - get_text_edit()->add_color_override("completion_existing_color", completion_existing_color); - get_text_edit()->add_color_override("completion_scroll_color", completion_scroll_color); - get_text_edit()->add_color_override("completion_font_color", completion_font_color); - get_text_edit()->add_color_override("font_color", text_color); - get_text_edit()->add_color_override("line_number_color", line_number_color); - get_text_edit()->add_color_override("caret_color", caret_color); - get_text_edit()->add_color_override("caret_background_color", caret_background_color); - get_text_edit()->add_color_override("font_color_selected", text_selected_color); - get_text_edit()->add_color_override("selection_color", selection_color); - get_text_edit()->add_color_override("brace_mismatch_color", brace_mismatch_color); - get_text_edit()->add_color_override("current_line_color", current_line_color); - get_text_edit()->add_color_override("line_length_guideline_color", line_length_guideline_color); - get_text_edit()->add_color_override("word_highlighted_color", word_highlighted_color); - get_text_edit()->add_color_override("number_color", number_color); - get_text_edit()->add_color_override("function_color", function_color); - get_text_edit()->add_color_override("member_variable_color", member_variable_color); - get_text_edit()->add_color_override("mark_color", mark_color); - get_text_edit()->add_color_override("bookmark_color", bookmark_color); - get_text_edit()->add_color_override("breakpoint_color", breakpoint_color); - get_text_edit()->add_color_override("executing_line_color", executing_line_color); - get_text_edit()->add_color_override("code_folding_color", code_folding_color); - get_text_edit()->add_color_override("search_result_color", search_result_color); - get_text_edit()->add_color_override("search_result_border_color", search_result_border_color); - get_text_edit()->add_color_override("symbol_color", symbol_color); + get_text_edit()->add_theme_color_override("background_color", background_color); + get_text_edit()->add_theme_color_override("completion_background_color", completion_background_color); + get_text_edit()->add_theme_color_override("completion_selected_color", completion_selected_color); + get_text_edit()->add_theme_color_override("completion_existing_color", completion_existing_color); + get_text_edit()->add_theme_color_override("completion_scroll_color", completion_scroll_color); + get_text_edit()->add_theme_color_override("completion_font_color", completion_font_color); + get_text_edit()->add_theme_color_override("font_color", text_color); + get_text_edit()->add_theme_color_override("line_number_color", line_number_color); + get_text_edit()->add_theme_color_override("caret_color", caret_color); + get_text_edit()->add_theme_color_override("caret_background_color", caret_background_color); + get_text_edit()->add_theme_color_override("font_color_selected", text_selected_color); + get_text_edit()->add_theme_color_override("selection_color", selection_color); + get_text_edit()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); + get_text_edit()->add_theme_color_override("current_line_color", current_line_color); + get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); + get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color); + get_text_edit()->add_theme_color_override("number_color", number_color); + get_text_edit()->add_theme_color_override("function_color", function_color); + get_text_edit()->add_theme_color_override("member_variable_color", member_variable_color); + get_text_edit()->add_theme_color_override("mark_color", mark_color); + get_text_edit()->add_theme_color_override("bookmark_color", bookmark_color); + get_text_edit()->add_theme_color_override("breakpoint_color", breakpoint_color); + get_text_edit()->add_theme_color_override("executing_line_color", executing_line_color); + get_text_edit()->add_theme_color_override("code_folding_color", code_folding_color); + get_text_edit()->add_theme_color_override("search_result_color", search_result_color); + get_text_edit()->add_theme_color_override("search_result_border_color", search_result_border_color); + get_text_edit()->add_theme_color_override("symbol_color", symbol_color); List<String> keywords; ShaderLanguage::get_keyword_list(&keywords); @@ -351,7 +352,7 @@ void ShaderEditor::_menu_option(int p_option) { void ShaderEditor::_notification(int p_what) { - if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_FOCUS_IN) { _check_for_external_edit(); } } @@ -376,7 +377,7 @@ void ShaderEditor::_editor_settings_changed() { shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line")); shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink")); shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed")); - shader_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); + shader_editor->get_text_edit()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret")); shader_editor->get_text_edit()->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling")); shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed")); @@ -595,7 +596,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { shader_editor = memnew(ShaderTextEditor); shader_editor->set_v_size_flags(SIZE_EXPAND_FILL); - shader_editor->add_constant_override("separation", 0); + shader_editor->add_theme_constant_override("separation", 0); shader_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE); shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders)); @@ -614,7 +615,6 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { context_menu = memnew(PopupMenu); add_child(context_menu); context_menu->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option)); - context_menu->set_hide_on_window_lose_focus(true); VBoxContainer *main_container = memnew(VBoxContainer); HBoxContainer *hbc = memnew(HBoxContainer); @@ -622,7 +622,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { edit_menu = memnew(MenuButton); edit_menu->set_text(TTR("Edit")); edit_menu->set_switch_on_hover(true); - edit_menu->get_popup()->set_hide_on_window_lose_focus(true); + edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO); edit_menu->get_popup()->add_separator(); @@ -646,7 +646,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { search_menu = memnew(MenuButton); search_menu->set_text(TTR("Search")); search_menu->set_switch_on_hover(true); - search_menu->get_popup()->set_hide_on_window_lose_focus(true); + search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT); search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV); @@ -666,13 +666,13 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { goto_menu->get_popup()->add_child(bookmarks_menu); goto_menu->get_popup()->add_submenu_item(TTR("Bookmarks"), "Bookmarks"); _update_bookmark_list(); - bookmarks_menu->connect("about_to_show", callable_mp(this, &ShaderEditor::_update_bookmark_list)); + bookmarks_menu->connect("about_to_popup", callable_mp(this, &ShaderEditor::_update_bookmark_list)); bookmarks_menu->connect("index_pressed", callable_mp(this, &ShaderEditor::_bookmark_item_pressed)); help_menu = memnew(MenuButton); help_menu->set_text(TTR("Help")); help_menu->set_switch_on_hover(true); - help_menu->get_popup()->add_icon_item(p_node->get_gui_base()->get_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS); + help_menu->get_popup()->add_icon_item(p_node->get_gui_base()->get_theme_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS); help_menu->get_popup()->connect("id_pressed", callable_mp(this, &ShaderEditor::_menu_option)); add_child(main_container); @@ -681,7 +681,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { hbc->add_child(edit_menu); hbc->add_child(goto_menu); hbc->add_child(help_menu); - hbc->add_style_override("panel", p_node->get_gui_base()->get_stylebox("ScriptEditorPanel", "EditorStyles")); + hbc->add_theme_style_override("panel", p_node->get_gui_base()->get_theme_stylebox("ScriptEditorPanel", "EditorStyles")); main_container->add_child(shader_editor); goto_line_dialog = memnew(GotoLineDialog); @@ -699,7 +699,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload_shader_from_disk)); disk_changed->get_ok()->set_text(TTR("Reload")); - disk_changed->add_button(TTR("Resave"), !OS::get_singleton()->get_swap_ok_cancel(), "resave"); + disk_changed->add_button(TTR("Resave"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "resave"); disk_changed->connect("custom_action", callable_mp(this, &ShaderEditor::save_external_data)); add_child(disk_changed); diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index 0b77b987bf..96b2e56538 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -59,7 +59,7 @@ void Skeleton2DEditor::_menu_option(int p_option) { if (node->get_bone_count() == 0) { err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -75,7 +75,7 @@ void Skeleton2DEditor::_menu_option(int p_option) { case MENU_OPTION_SET_REST: { if (node->get_bone_count() == 0) { err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); @@ -101,7 +101,7 @@ Skeleton2DEditor::Skeleton2DEditor() { CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Skeleton2D")); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Skeleton2D", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Skeleton2D", "EditorIcons")); options->get_popup()->add_item(TTR("Make Rest Pose (From Bones)"), MENU_OPTION_MAKE_REST); options->get_popup()->add_separator(); diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index 07bd6a0e41..ac9980b79f 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -158,7 +158,7 @@ SkeletonEditor::SkeletonEditor() { SpatialEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Skeleton")); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Skeleton", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Skeleton", "EditorIcons")); options->get_popup()->add_item(TTR("Create physical skeleton"), MENU_OPTION_CREATE_PHYSICAL_SKELETON); diff --git a/editor/plugins/skeleton_ik_editor_plugin.cpp b/editor/plugins/skeleton_ik_editor_plugin.cpp index 418e10a0f0..8b120e9543 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.cpp +++ b/editor/plugins/skeleton_ik_editor_plugin.cpp @@ -84,7 +84,7 @@ SkeletonIKEditorPlugin::SkeletonIKEditorPlugin(EditorNode *p_node) { editor = p_node; play_btn = memnew(Button); - play_btn->set_icon(editor->get_gui_base()->get_icon("Play", "EditorIcons")); + play_btn->set_icon(editor->get_gui_base()->get_theme_icon("Play", "EditorIcons")); play_btn->set_text(TTR("Play IK")); play_btn->set_toggle_mode(true); play_btn->hide(); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 2f1274a99a..f0730f0144 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -30,8 +30,8 @@ #include "spatial_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/math/camera_matrix.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/print_string.h" #include "core/project_settings.h" @@ -51,6 +51,7 @@ #include "scene/gui/viewport_container.h" #include "scene/resources/packed_scene.h" #include "scene/resources/surface_tool.h" +#include "servers/display_server.h" #define DISTANCE_DEFAULT 4 @@ -88,9 +89,9 @@ void ViewportRotationControl::_notification(int p_what) { axis_menu_options.push_back(SpatialEditorViewport::VIEW_REAR); axis_colors.clear(); - axis_colors.push_back(get_color("axis_x_color", "Editor")); - axis_colors.push_back(get_color("axis_y_color", "Editor")); - axis_colors.push_back(get_color("axis_z_color", "Editor")); + axis_colors.push_back(get_theme_color("axis_x_color", "Editor")); + axis_colors.push_back(get_theme_color("axis_y_color", "Editor")); + axis_colors.push_back(get_theme_color("axis_z_color", "Editor")); update(); if (!is_connected("mouse_exited", callable_mp(this, &ViewportRotationControl::_on_mouse_exited))) { @@ -139,7 +140,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) { if (front) { String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z"); draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c); - draw_char(get_font("rotation_control", "EditorFonts"), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", Color(0.3, 0.3, 0.3)); + draw_char(get_theme_font("rotation_control", "EditorFonts"), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", Color(0.3, 0.3, 0.3)); } else { draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS * (0.55 + (0.2 * (1.0 + p_axis.z_axis))), c); } @@ -297,10 +298,10 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) { float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia"); //determine if being manipulated - bool manipulated = Input::get_singleton()->get_mouse_button_mask() & (2 | 4); - manipulated |= Input::get_singleton()->is_key_pressed(KEY_SHIFT); - manipulated |= Input::get_singleton()->is_key_pressed(KEY_ALT); - manipulated |= Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool manipulated = InputFilter::get_singleton()->get_mouse_button_mask() & (2 | 4); + manipulated |= InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT); + manipulated |= InputFilter::get_singleton()->is_key_pressed(KEY_ALT); + manipulated |= InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); @@ -1090,7 +1091,7 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) { selection_menu->set_item_tooltip(i, String(spat->get_name()) + "\nType: " + spat->get_class() + "\nPath: " + node_path); } - selection_menu->set_global_position(b->get_global_position()); + selection_menu->set_position(get_screen_transform().xform(b->get_position())); selection_menu->popup(); } } @@ -2213,14 +2214,14 @@ void SpatialEditorViewport::set_freelook_active(bool active_now) { } // Hide mouse like in an FPS (warping doesn't work) - OS::get_singleton()->set_mouse_mode(OS::MOUSE_MODE_CAPTURED); + DisplayServer::get_singleton()->mouse_set_mode(DisplayServer::MOUSE_MODE_CAPTURED); } else if (freelook_active && !active_now) { // Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential cursor = camera_cursor; // Restore mouse - OS::get_singleton()->set_mouse_mode(OS::MOUSE_MODE_VISIBLE); + DisplayServer::get_singleton()->mouse_set_mode(DisplayServer::MOUSE_MODE_VISIBLE); } freelook_active = active_now; @@ -2259,7 +2260,7 @@ void SpatialEditorViewport::scale_freelook_speed(real_t scale) { Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const { Point2i relative; if (bool(EDITOR_DEF("editors/3d/navigation/warped_mouse_panning", false))) { - relative = Input::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect()); + relative = InputFilter::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect()); } else { relative = p_ev_mouse_motion->get_relative(); } @@ -2275,7 +2276,7 @@ static bool is_shortcut_pressed(const String &p_path) { if (k == NULL) { return false; } - const Input &input = *Input::get_singleton(); + const InputFilter &input = *InputFilter::get_singleton(); int keycode = k->get_keycode(); return input.is_key_pressed(keycode); } @@ -2366,7 +2367,7 @@ void SpatialEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { // The crosshair icon doesn't depend on the editor theme. - crosshair->set_texture(get_icon("Crosshair", "EditorIcons")); + crosshair->set_texture(get_theme_icon("Crosshair", "EditorIcons")); // Set the anchors and margins after changing the icon to ensure it's centered correctly. crosshair->set_anchors_and_margins_preset(PRESET_CENTER); } @@ -2554,25 +2555,25 @@ void SpatialEditorViewport::_notification(int p_what) { if (p_what == NOTIFICATION_THEME_CHANGED) { - view_menu->set_icon(get_icon("GuiTabMenu", "EditorIcons")); - preview_camera->set_icon(get_icon("Camera", "EditorIcons")); + view_menu->set_icon(get_theme_icon("GuiTabMenu", "EditorIcons")); + preview_camera->set_icon(get_theme_icon("Camera", "EditorIcons")); - view_menu->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - view_menu->add_style_override("hover", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - view_menu->add_style_override("pressed", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - view_menu->add_style_override("focus", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - view_menu->add_style_override("disabled", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_theme_style_override("pressed", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_theme_style_override("focus", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + view_menu->add_theme_style_override("disabled", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); - preview_camera->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - preview_camera->add_style_override("hover", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - preview_camera->add_style_override("pressed", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - preview_camera->add_style_override("focus", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - preview_camera->add_style_override("disabled", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_theme_style_override("hover", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_theme_style_override("pressed", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_theme_style_override("focus", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + preview_camera->add_theme_style_override("disabled", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); - info_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - fps_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - cinema_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); - locked_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles")); + info_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + fps_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + cinema_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); + locked_label->add_theme_style_override("normal", editor->get_gui_base()->get_theme_stylebox("Information3dViewport", "EditorStyles")); } } @@ -2612,7 +2613,7 @@ void SpatialEditorViewport::_draw() { if (surface->has_focus()) { Size2 size = surface->get_size(); Rect2 r = Rect2(Point2(), size); - get_stylebox("Focus", "EditorStyles")->draw(surface->get_canvas_item(), r); + get_theme_stylebox("Focus", "EditorStyles")->draw(surface->get_canvas_item(), r); } if (cursor.region_select) { @@ -2620,11 +2621,11 @@ void SpatialEditorViewport::_draw() { surface->draw_rect( selection_rect, - get_color("box_selection_fill_color", "Editor")); + get_theme_color("box_selection_fill_color", "Editor")); surface->draw_rect( selection_rect, - get_color("box_selection_stroke_color", "Editor"), + get_theme_color("box_selection_stroke_color", "Editor"), false, Math::round(EDSCALE)); } @@ -2632,7 +2633,7 @@ void SpatialEditorViewport::_draw() { RID ci = surface->get_canvas_item(); if (message_time > 0) { - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); Point2 msgpos = Point2(5, get_size().y - 20); font->draw(ci, msgpos + Point2(1, 1), message, Color(0, 0, 0, 0.8)); font->draw(ci, msgpos + Point2(-1, -1), message, Color(0, 0, 0, 0.8)); @@ -2646,7 +2647,7 @@ void SpatialEditorViewport::_draw() { ci, _edit.mouse_pos, center, - get_color("accent_color", "Editor") * Color(1, 1, 1, 0.6), + get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.6), Math::round(2 * EDSCALE)); } if (previewing) { @@ -2697,7 +2698,7 @@ void SpatialEditorViewport::_draw() { if (logscale_t < 0.25) logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); - draw_indicator_bar(*surface, 1.0 - logscale_t, get_icon("ViewportSpeed", "EditorIcons")); + draw_indicator_bar(*surface, 1.0 - logscale_t, get_theme_icon("ViewportSpeed", "EditorIcons")); } } else { @@ -2715,7 +2716,7 @@ void SpatialEditorViewport::_draw() { if (logscale_t < 0.25) logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); - draw_indicator_bar(*surface, logscale_t, get_icon("ViewportZoom", "EditorIcons")); + draw_indicator_bar(*surface, logscale_t, get_theme_icon("ViewportZoom", "EditorIcons")); } } } @@ -3705,7 +3706,7 @@ void SpatialEditorViewport::_perform_drop_data() { } files_str = files_str.substr(0, files_str.length() - 1); accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); - accept->popup_centered_minsize(); + accept->popup_centered(); } } @@ -3770,7 +3771,7 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p if (!can_drop_data_fw(p_point, p_data, p_from)) return; - bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT); + bool is_shift = InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT); selected_files.clear(); Dictionary d = p_data; @@ -3785,14 +3786,14 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p list.push_back(root_node); } else { accept->set_text(TTR("No parent to instance a child at.")); - accept->popup_centered_minsize(); + accept->popup_centered(); _remove_preview(); return; } } if (list.size() != 1) { accept->set_text(TTR("This operation requires a single selected node.")); - accept->popup_centered_minsize(); + accept->popup_centered(); _remove_preview(); return; } @@ -3833,7 +3834,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed c->set_stretch(true); add_child(c); c->set_anchors_and_margins_preset(Control::PRESET_WIDE); - viewport = memnew(Viewport); + viewport = memnew(SubViewport); viewport->set_disable_input(true); c->add_child(viewport); @@ -3926,8 +3927,11 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_menu_option)); display_submenu->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_menu_option)); view_menu->set_disable_shortcuts(true); - - if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { +#ifndef _MSC_VER +#warning this needs to be fixed +#endif + //if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { + if (false) { // Alternate display modes only work when using the Vulkan renderer; make this explicit. const int normal_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL); const int wireframe_idx = view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME); @@ -4033,7 +4037,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed selection_menu = memnew(PopupMenu); add_child(selection_menu); - selection_menu->set_custom_minimum_size(Size2(100, 0) * EDSCALE); + selection_menu->set_min_size(Size2(100, 0) * EDSCALE); selection_menu->connect("id_pressed", callable_mp(this, &SpatialEditorViewport::_selection_result_pressed)); selection_menu->connect("popup_hide", callable_mp(this, &SpatialEditorViewport::_selection_menu_hide)); @@ -4059,8 +4063,8 @@ void SpatialEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) if (mb->is_pressed()) { Vector2 size = get_size(); - int h_sep = get_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + int h_sep = get_theme_constant("separation", "HSplitContainer"); + int v_sep = get_theme_constant("separation", "VSplitContainer"); int mid_w = size.width * ratio_h; int mid_h = size.height * ratio_v; @@ -4110,8 +4114,8 @@ void SpatialEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) if (view == VIEW_USE_3_VIEWPORTS || view == VIEW_USE_3_VIEWPORTS_ALT || view == VIEW_USE_4_VIEWPORTS) { Vector2 size = get_size(); - int h_sep = get_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + int h_sep = get_theme_constant("separation", "HSplitContainer"); + int v_sep = get_theme_constant("separation", "VSplitContainer"); int mid_w = size.width * ratio_h; int mid_h = size.height * ratio_v; @@ -4153,18 +4157,18 @@ void SpatialEditorViewportContainer::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW && mouseover) { - Ref<Texture2D> h_grabber = get_icon("grabber", "HSplitContainer"); - Ref<Texture2D> v_grabber = get_icon("grabber", "VSplitContainer"); + Ref<Texture2D> h_grabber = get_theme_icon("grabber", "HSplitContainer"); + Ref<Texture2D> v_grabber = get_theme_icon("grabber", "VSplitContainer"); - Ref<Texture2D> hdiag_grabber = get_icon("GuiViewportHdiagsplitter", "EditorIcons"); - Ref<Texture2D> vdiag_grabber = get_icon("GuiViewportVdiagsplitter", "EditorIcons"); - Ref<Texture2D> vh_grabber = get_icon("GuiViewportVhsplitter", "EditorIcons"); + Ref<Texture2D> hdiag_grabber = get_theme_icon("GuiViewportHdiagsplitter", "EditorIcons"); + Ref<Texture2D> vdiag_grabber = get_theme_icon("GuiViewportVdiagsplitter", "EditorIcons"); + Ref<Texture2D> vh_grabber = get_theme_icon("GuiViewportVhsplitter", "EditorIcons"); Vector2 size = get_size(); - int h_sep = get_constant("separation", "HSplitContainer"); + int h_sep = get_theme_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + int v_sep = get_theme_constant("separation", "VSplitContainer"); int mid_w = size.width * ratio_h; int mid_h = size.height * ratio_v; @@ -4258,9 +4262,9 @@ void SpatialEditorViewportContainer::_notification(int p_what) { } return; } - int h_sep = get_constant("separation", "HSplitContainer"); + int h_sep = get_theme_constant("separation", "HSplitContainer"); - int v_sep = get_constant("separation", "VSplitContainer"); + int v_sep = get_theme_constant("separation", "VSplitContainer"); int mid_w = size.width * ratio_h; int mid_h = size.height * ratio_v; @@ -4797,13 +4801,13 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) { const int state = gizmos_menu->get_item_state(idx); switch (state) { case EditorSpatialGizmoPlugin::VISIBLE: - gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_visible")); + gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_visible")); break; case EditorSpatialGizmoPlugin::ON_TOP: - gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_xray")); + gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_xray")); break; case EditorSpatialGizmoPlugin::HIDDEN: - gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_icon("visibility_hidden")); + gizmos_menu->set_item_icon(idx, view_menu->get_popup()->get_theme_icon("visibility_hidden")); break; } @@ -5098,13 +5102,13 @@ void SpatialEditor::_init_indicators() { Color origin_color; switch (i) { case 0: - origin_color = get_color("axis_x_color", "Editor"); + origin_color = get_theme_color("axis_x_color", "Editor"); break; case 1: - origin_color = get_color("axis_y_color", "Editor"); + origin_color = get_theme_color("axis_y_color", "Editor"); break; case 2: - origin_color = get_color("axis_z_color", "Editor"); + origin_color = get_theme_color("axis_z_color", "Editor"); break; default: origin_color = Color(); @@ -5149,13 +5153,13 @@ void SpatialEditor::_init_indicators() { Color col; switch (i) { case 0: - col = get_color("axis_x_color", "Editor"); + col = get_theme_color("axis_x_color", "Editor"); break; case 1: - col = get_color("axis_y_color", "Editor"); + col = get_theme_color("axis_y_color", "Editor"); break; case 2: - col = get_color("axis_z_color", "Editor"); + col = get_theme_color("axis_z_color", "Editor"); break; default: col = Color(); @@ -5427,13 +5431,13 @@ void SpatialEditor::_update_gizmos_menu() { const int idx = gizmos_menu->get_item_index(i); switch (plugin_state) { case EditorSpatialGizmoPlugin::VISIBLE: - gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_visible")); + gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible")); break; case EditorSpatialGizmoPlugin::ON_TOP: - gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_xray")); + gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_xray")); break; case EditorSpatialGizmoPlugin::HIDDEN: - gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_hidden")); + gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_hidden")); break; } } @@ -5446,13 +5450,13 @@ void SpatialEditor::_update_gizmos_menu_theme() { const int idx = gizmos_menu->get_item_index(i); switch (plugin_state) { case EditorSpatialGizmoPlugin::VISIBLE: - gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_visible")); + gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_visible")); break; case EditorSpatialGizmoPlugin::ON_TOP: - gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_xray")); + gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_xray")); break; case EditorSpatialGizmoPlugin::HIDDEN: - gizmos_menu->set_item_icon(idx, gizmos_menu->get_icon("visibility_hidden")); + gizmos_menu->set_item_icon(idx, gizmos_menu->get_theme_icon("visibility_hidden")); break; } } @@ -5714,35 +5718,35 @@ void SpatialEditor::snap_selected_nodes_to_floor() { void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) { - if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack()) + if (!is_visible_in_tree()) return; - snap_key_enabled = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + snap_key_enabled = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); } void SpatialEditor::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { - tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_icon("ListSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_icon("Lock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_icon("Unlock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_icon("Group", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_icon("Ungroup", "EditorIcons")); - - tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_icon("Object", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_icon("Snap", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_icon("Camera", "EditorIcons")); - - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_icon("Panels2Alt", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_icon("Panels3", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_icon("Panels3Alt", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_icon("Panels4", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons")); + tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons")); + tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons")); + tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); + tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + + tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); + tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); + tool_option_button[SpatialEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon("Camera", "EditorIcons")); + + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon("Panels1", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon("Panels2", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon("Panels2Alt", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon("Panels3", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon("Panels3Alt", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon("Panels4", "EditorIcons")); _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT); @@ -5765,25 +5769,25 @@ void SpatialEditor::_notification(int p_what) { _finish_indicators(); } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); - tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_icon("ListSelect", "EditorIcons")); - tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_icon("Lock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_icon("Unlock", "EditorIcons")); - tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_icon("Group", "EditorIcons")); - tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_icon("Ungroup", "EditorIcons")); - - tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_icon("Object", "EditorIcons")); - tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_icon("Snap", "EditorIcons")); - - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_icon("Panels2Alt", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_icon("Panels3", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_icon("Panels3Alt", "EditorIcons")); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_icon("Panels4", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon("ToolMove", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon("ToolRotate", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon("ToolScale", "EditorIcons")); + tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon("ListSelect", "EditorIcons")); + tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon("Lock", "EditorIcons")); + tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon("Unlock", "EditorIcons")); + tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); + tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + + tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); + tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); + + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon("Panels1", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon("Panels2", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon("Panels2Alt", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon("Panels3", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon("Panels3Alt", "EditorIcons")); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon("Panels4", "EditorIcons")); // Update grid color by rebuilding grid. _finish_grid(); @@ -6377,7 +6381,7 @@ Vector3 SpatialEditor::snap_point(Vector3 p_target, Vector3 p_start) const { float SpatialEditor::get_translate_snap() const { float snap_value; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { snap_value = snap_translate->get_text().to_double() / 10.0; } else { snap_value = snap_translate->get_text().to_double(); @@ -6388,7 +6392,7 @@ float SpatialEditor::get_translate_snap() const { float SpatialEditor::get_rotate_snap() const { float snap_value; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { snap_value = snap_rotate->get_text().to_double() / 3.0; } else { snap_value = snap_rotate->get_text().to_double(); @@ -6399,7 +6403,7 @@ float SpatialEditor::get_rotate_snap() const { float SpatialEditor::get_scale_snap() const { float snap_value; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { snap_value = snap_scale->get_text().to_double() / 2.0; } else { snap_value = snap_scale->get_text().to_double(); @@ -6556,7 +6560,7 @@ void EditorSpatialGizmoPlugin::create_handle_material(const String &p_name, bool handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true); - Ref<Texture2D> handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons"); + Ref<Texture2D> handle_t = SpatialEditor::get_singleton()->get_theme_icon("Editor3DHandle", "EditorIcons"); handle_material->set_point_size(handle_t->get_width()); handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t); handle_material->set_albedo(Color(1, 1, 1)); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index b67459b9d0..9dad66b647 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -262,7 +262,7 @@ private: PopupMenu *display_submenu; Control *surface; - Viewport *viewport; + SubViewport *viewport; Camera *camera; bool transforming; bool orthogonal; @@ -467,7 +467,7 @@ public: AABB *p_preview_bounds, AcceptDialog *p_accept); - Viewport *get_viewport_node() { return viewport; } + SubViewport *get_viewport_node() { return viewport; } Camera *get_camera() { return camera; } // return the default camera object. SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index); diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 2897341f06..251957eaa5 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -170,13 +170,13 @@ void SpriteEditor::_update_mesh_data() { Ref<Texture2D> texture = node->get_texture(); if (texture.is_null()) { err_dialog->set_text(TTR("Sprite is empty!")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } if (node->get_hframes() > 1 || node->get_vframes() > 1) { err_dialog->set_text(TTR("Can't convert a sprite using animation frames to mesh.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -317,7 +317,7 @@ void SpriteEditor::_convert_to_mesh_2d_node() { if (computed_vertices.size() < 3) { err_dialog->set_text(TTR("Invalid geometry, can't replace by mesh.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -348,7 +348,7 @@ void SpriteEditor::_convert_to_polygon_2d_node() { if (computed_outline_lines.empty()) { err_dialog->set_text(TTR("Invalid geometry, can't create polygon.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -407,7 +407,7 @@ void SpriteEditor::_create_collision_polygon_2d_node() { if (computed_outline_lines.empty()) { err_dialog->set_text(TTR("Invalid geometry, can't create collision polygon.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -431,7 +431,7 @@ void SpriteEditor::_create_light_occluder_2d_node() { if (computed_outline_lines.empty()) { err_dialog->set_text(TTR("Invalid geometry, can't create light occluder.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } @@ -514,7 +514,7 @@ SpriteEditor::SpriteEditor() { CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text(TTR("Sprite")); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Sprite", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Sprite", "EditorIcons")); options->get_popup()->add_item(TTR("Convert to Mesh2D"), MENU_OPTION_CONVERT_TO_MESH_2D); options->get_popup()->add_item(TTR("Convert to Polygon2D"), MENU_OPTION_CONVERT_TO_POLYGON_2D); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index e6b0e3142c..776b80d73b 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -81,7 +81,7 @@ void SpriteFramesEditor::_sheet_preview_draw() { return; } - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { int idx = E->get(); @@ -223,24 +223,24 @@ void SpriteFramesEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - load->set_icon(get_icon("Load", "EditorIcons")); - load_sheet->set_icon(get_icon("SpriteSheet", "EditorIcons")); - copy->set_icon(get_icon("ActionCopy", "EditorIcons")); - paste->set_icon(get_icon("ActionPaste", "EditorIcons")); - empty->set_icon(get_icon("InsertBefore", "EditorIcons")); - empty2->set_icon(get_icon("InsertAfter", "EditorIcons")); - move_up->set_icon(get_icon("MoveLeft", "EditorIcons")); - move_down->set_icon(get_icon("MoveRight", "EditorIcons")); - _delete->set_icon(get_icon("Remove", "EditorIcons")); - new_anim->set_icon(get_icon("New", "EditorIcons")); - remove_anim->set_icon(get_icon("Remove", "EditorIcons")); + load->set_icon(get_theme_icon("Load", "EditorIcons")); + load_sheet->set_icon(get_theme_icon("SpriteSheet", "EditorIcons")); + copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); + paste->set_icon(get_theme_icon("ActionPaste", "EditorIcons")); + empty->set_icon(get_theme_icon("InsertBefore", "EditorIcons")); + empty2->set_icon(get_theme_icon("InsertAfter", "EditorIcons")); + move_up->set_icon(get_theme_icon("MoveLeft", "EditorIcons")); + move_down->set_icon(get_theme_icon("MoveRight", "EditorIcons")); + _delete->set_icon(get_theme_icon("Remove", "EditorIcons")); + new_anim->set_icon(get_theme_icon("New", "EditorIcons")); + remove_anim->set_icon(get_theme_icon("Remove", "EditorIcons")); [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { - splite_sheet_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + splite_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); } break; case NOTIFICATION_READY: { - add_constant_override("autohide", 1); // Fixes the dragger always showing up. + add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up. } break; } } @@ -262,7 +262,7 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_ //dialog->get_cancel()->set_text("Close"); dialog->get_ok()->set_text(TTR("Close")); - dialog->popup_centered_minsize(); + dialog->popup_centered(); return; ///beh should show an error i guess } @@ -301,7 +301,7 @@ void SpriteFramesEditor::_load_pressed() { for (int i = 0; i < extensions.size(); i++) file->add_filter("*." + extensions[i]); - file->set_mode(EditorFileDialog::MODE_OPEN_FILES); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); file->popup_centered_ratio(); } @@ -316,7 +316,7 @@ void SpriteFramesEditor::_paste_pressed() { dialog->set_title(TTR("Error!")); //dialog->get_cancel()->set_text("Close"); dialog->get_ok()->set_text(TTR("Close")); - dialog->popup_centered_minsize(); + dialog->popup_centered(); return; ///beh should show an error i guess } @@ -591,7 +591,7 @@ void SpriteFramesEditor::_animation_remove() { return; delete_dialog->set_text(TTR("Delete Animation?")); - delete_dialog->popup_centered_minsize(); + delete_dialog->popup_centered(); } void SpriteFramesEditor::_animation_remove_confirmed() { @@ -1058,7 +1058,7 @@ SpriteFramesEditor::SpriteFramesEditor() { file_split_sheet = memnew(EditorFileDialog); file_split_sheet->set_title(TTR("Create Frames from Sprite Sheet")); - file_split_sheet->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_split_sheet->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); add_child(file_split_sheet); file_split_sheet->connect("file_selected", callable_mp(this, &SpriteFramesEditor::_prepare_sprite_sheet)); } diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index a92194da17..41db0308c2 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -57,7 +57,7 @@ void StyleBoxPreview::edit(const Ref<StyleBox> &p_stylebox) { stylebox->disconnect("changed", callable_mp(this, &StyleBoxPreview::_sb_changed)); stylebox = p_stylebox; if (p_stylebox.is_valid()) { - preview->add_style_override("panel", stylebox); + preview->add_theme_style_override("panel", stylebox); stylebox->connect("changed", callable_mp(this, &StyleBoxPreview::_sb_changed)); } _sb_changed(); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 35f23ccf1d..aa86c48af1 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -51,10 +51,10 @@ void TextEditor::set_syntax_highlighter(SyntaxHighlighter *p_highlighter) { // so to remove all colours we need to set and unset them here. if (p_highlighter == NULL) { // standard TextEdit *text_edit = code_editor->get_text_edit(); - text_edit->add_color_override("number_color", colors_cache.font_color); - text_edit->add_color_override("function_color", colors_cache.font_color); - text_edit->add_color_override("number_color", colors_cache.font_color); - text_edit->add_color_override("member_variable_color", colors_cache.font_color); + text_edit->add_theme_color_override("number_color", colors_cache.font_color); + text_edit->add_theme_color_override("function_color", colors_cache.font_color); + text_edit->add_theme_color_override("number_color", colors_cache.font_color); + text_edit->add_theme_color_override("member_variable_color", colors_cache.font_color); } else { _load_theme_settings(); } @@ -107,35 +107,35 @@ void TextEditor::_load_theme_settings() { Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); Color string_color = EDITOR_GET("text_editor/highlighting/string_color"); - text_edit->add_color_override("background_color", background_color); - text_edit->add_color_override("completion_background_color", completion_background_color); - text_edit->add_color_override("completion_selected_color", completion_selected_color); - text_edit->add_color_override("completion_existing_color", completion_existing_color); - text_edit->add_color_override("completion_scroll_color", completion_scroll_color); - text_edit->add_color_override("completion_font_color", completion_font_color); - text_edit->add_color_override("font_color", text_color); - text_edit->add_color_override("line_number_color", line_number_color); - text_edit->add_color_override("caret_color", caret_color); - text_edit->add_color_override("caret_background_color", caret_background_color); - text_edit->add_color_override("font_color_selected", text_selected_color); - text_edit->add_color_override("selection_color", selection_color); - text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color); - text_edit->add_color_override("current_line_color", current_line_color); - text_edit->add_color_override("line_length_guideline_color", line_length_guideline_color); - text_edit->add_color_override("word_highlighted_color", word_highlighted_color); - text_edit->add_color_override("number_color", number_color); - text_edit->add_color_override("function_color", function_color); - text_edit->add_color_override("member_variable_color", member_variable_color); - text_edit->add_color_override("breakpoint_color", breakpoint_color); - text_edit->add_color_override("executing_line_color", executing_line_color); - text_edit->add_color_override("mark_color", mark_color); - text_edit->add_color_override("bookmark_color", bookmark_color); - text_edit->add_color_override("code_folding_color", code_folding_color); - text_edit->add_color_override("search_result_color", search_result_color); - text_edit->add_color_override("search_result_border_color", search_result_border_color); - text_edit->add_color_override("symbol_color", symbol_color); - - text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6)); + text_edit->add_theme_color_override("background_color", background_color); + text_edit->add_theme_color_override("completion_background_color", completion_background_color); + text_edit->add_theme_color_override("completion_selected_color", completion_selected_color); + text_edit->add_theme_color_override("completion_existing_color", completion_existing_color); + text_edit->add_theme_color_override("completion_scroll_color", completion_scroll_color); + text_edit->add_theme_color_override("completion_font_color", completion_font_color); + text_edit->add_theme_color_override("font_color", text_color); + text_edit->add_theme_color_override("line_number_color", line_number_color); + text_edit->add_theme_color_override("caret_color", caret_color); + text_edit->add_theme_color_override("caret_background_color", caret_background_color); + text_edit->add_theme_color_override("font_color_selected", text_selected_color); + text_edit->add_theme_color_override("selection_color", selection_color); + text_edit->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); + text_edit->add_theme_color_override("current_line_color", current_line_color); + text_edit->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); + text_edit->add_theme_color_override("word_highlighted_color", word_highlighted_color); + text_edit->add_theme_color_override("number_color", number_color); + text_edit->add_theme_color_override("function_color", function_color); + text_edit->add_theme_color_override("member_variable_color", member_variable_color); + text_edit->add_theme_color_override("breakpoint_color", breakpoint_color); + text_edit->add_theme_color_override("executing_line_color", executing_line_color); + text_edit->add_theme_color_override("mark_color", mark_color); + text_edit->add_theme_color_override("bookmark_color", bookmark_color); + text_edit->add_theme_color_override("code_folding_color", code_folding_color); + text_edit->add_theme_color_override("search_result_color", search_result_color); + text_edit->add_theme_color_override("search_result_border_color", search_result_border_color); + text_edit->add_theme_color_override("symbol_color", symbol_color); + + text_edit->add_theme_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 6)); colors_cache.font_color = text_color; colors_cache.symbol_color = symbol_color; @@ -163,7 +163,7 @@ String TextEditor::get_name() { return name; } -Ref<Texture2D> TextEditor::get_icon() { +Ref<Texture2D> TextEditor::get_theme_icon() { return EditorNode::get_singleton()->get_object_icon(text_file.operator->(), ""); } @@ -624,7 +624,7 @@ void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is TextEditor::TextEditor() { code_editor = memnew(CodeTextEditor); add_child(code_editor); - code_editor->add_constant_override("separation", 0); + code_editor->add_theme_constant_override("separation", 0); code_editor->connect("load_theme_settings", callable_mp(this, &TextEditor::_load_theme_settings)); code_editor->connect("validate_script", callable_mp(this, &TextEditor::_validate_script)); code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE); @@ -716,7 +716,7 @@ TextEditor::TextEditor() { goto_menu->get_popup()->add_child(bookmarks_menu); goto_menu->get_popup()->add_submenu_item(TTR("Bookmarks"), "Bookmarks"); _update_bookmark_list(); - bookmarks_menu->connect("about_to_show", callable_mp(this, &TextEditor::_update_bookmark_list)); + bookmarks_menu->connect("about_to_popup", callable_mp(this, &TextEditor::_update_bookmark_list)); bookmarks_menu->connect("index_pressed", callable_mp(this, &TextEditor::_bookmark_item_pressed)); goto_line_dialog = memnew(GotoLineDialog); diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index c80052e7ba..b41e11c3aa 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -121,7 +121,7 @@ public: virtual void set_syntax_highlighter(SyntaxHighlighter *p_highlighter); virtual String get_name(); - virtual Ref<Texture2D> get_icon(); + virtual Ref<Texture2D> get_theme_icon(); virtual RES get_edited_resource() const; virtual void set_edited_resource(const RES &p_res); void set_edited_file(const Ref<TextFile> &p_file); diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index 60f9bb5dc1..3f76854571 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -46,7 +46,7 @@ void TextureEditor::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<Texture2D> checkerboard = get_icon("Checkerboard", "EditorIcons"); + Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons"); Size2 size = get_size(); draw_texture_rect(checkerboard, Rect2(Point2(), size), true); @@ -79,7 +79,7 @@ void TextureEditor::_notification(int p_what) { draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height)); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); String format; if (Object::cast_to<ImageTexture>(*texture)) { diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 2262e12f5d..2186c7d5c3 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -31,7 +31,7 @@ #include "texture_region_editor_plugin.h" #include "core/core_string_names.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" #include "scene/gui/check_box.h" @@ -43,7 +43,7 @@ void draw_margin_line(Control *edit_draw, Vector2 from, Vector2 to) { Vector2 line = (to - from).normalized() * 10; while ((to - from).length_squared() > 200) { - edit_draw->draw_line(from, from + line, EditorNode::get_singleton()->get_theme_base()->get_color("mono_color", "Editor"), 2); + edit_draw->draw_line(from, from + line, EditorNode::get_singleton()->get_theme_base()->get_theme_color("mono_color", "Editor"), 2); from += line * 2; } } @@ -134,7 +134,7 @@ void TextureRegionEditor::_region_draw() { } } - Ref<Texture2D> select_handle = get_icon("EditorHandle", "EditorIcons"); + Ref<Texture2D> select_handle = get_theme_icon("EditorHandle", "EditorIcons"); Rect2 scroll_rect(Point2(), base_tex->get_size()); @@ -150,7 +150,7 @@ void TextureRegionEditor::_region_draw() { mtx.basis_xform(raw_endpoints[2]), mtx.basis_xform(raw_endpoints[3]) }; - Color color = get_color("mono_color", "Editor"); + Color color = get_theme_color("mono_color", "Editor"); for (int i = 0; i < 4; i++) { int prev = (i + 3) % 4; @@ -307,7 +307,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) { if (E->get().has_point(point)) { rect = E->get(); - if (Input::get_singleton()->is_key_pressed(KEY_CONTROL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL) && !(InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) { Rect2 r; if (node_sprite) r = node_sprite->get_region_rect(); @@ -449,7 +449,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { if (mm.is_valid()) { - if (mm->get_button_mask() & BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + if (mm->get_button_mask() & BUTTON_MASK_MIDDLE || InputFilter::get_singleton()->is_key_pressed(KEY_SPACE)) { Vector2 dragged(mm->get_relative().x / draw_zoom, mm->get_relative().y / draw_zoom); hscroll->set_value(hscroll->get_value() - dragged.x); @@ -741,12 +741,12 @@ void TextureRegionEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - edit_draw->add_style_override("panel", get_stylebox("bg", "Tree")); + edit_draw->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); } break; case NOTIFICATION_READY: { - zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons")); - zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); - zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons")); + zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons")); + zoom_reset->set_icon(get_theme_icon("ZoomReset", "EditorIcons")); + zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons")); vscroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE); hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE); @@ -756,7 +756,7 @@ void TextureRegionEditor::_notification(int p_what) { _update_autoslice(); } } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_FOCUS_IN: { // This happens when the user leaves the Editor and returns, // they could have changed the textures, so the cache is cleared. cache_map.clear(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index aa5caf6658..b246b611fd 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -592,7 +592,7 @@ void ThemeEditor::_notification(int p_what) { } } break; case NOTIFICATION_THEME_CHANGED: { - theme_menu->set_icon(get_icon("Theme", "EditorIcons")); + theme_menu->set_icon(get_theme_icon("Theme", "EditorIcons")); } break; } } @@ -645,10 +645,10 @@ ThemeEditor::ThemeEditor() { main_container = memnew(MarginContainer); root_container->add_child(main_container); - main_container->add_constant_override("margin_right", 4 * EDSCALE); - main_container->add_constant_override("margin_top", 4 * EDSCALE); - main_container->add_constant_override("margin_left", 4 * EDSCALE); - main_container->add_constant_override("margin_bottom", 4 * EDSCALE); + main_container->add_theme_constant_override("margin_right", 4 * EDSCALE); + main_container->add_theme_constant_override("margin_top", 4 * EDSCALE); + main_container->add_theme_constant_override("margin_left", 4 * EDSCALE); + main_container->add_theme_constant_override("margin_bottom", 4 * EDSCALE); HBoxContainer *main_hb = memnew(HBoxContainer); main_container->add_child(main_hb); @@ -656,7 +656,7 @@ ThemeEditor::ThemeEditor() { VBoxContainer *first_vb = memnew(VBoxContainer); main_hb->add_child(first_vb); first_vb->set_h_size_flags(SIZE_EXPAND_FILL); - first_vb->add_constant_override("separation", 10 * EDSCALE); + first_vb->add_theme_constant_override("separation", 10 * EDSCALE); first_vb->add_child(memnew(Label("Label"))); @@ -716,7 +716,7 @@ ThemeEditor::ThemeEditor() { VBoxContainer *second_vb = memnew(VBoxContainer); second_vb->set_h_size_flags(SIZE_EXPAND_FILL); main_hb->add_child(second_vb); - second_vb->add_constant_override("separation", 10 * EDSCALE); + second_vb->add_theme_constant_override("separation", 10 * EDSCALE); LineEdit *le = memnew(LineEdit); le->set_text("LineEdit"); second_vb->add_child(le); @@ -756,7 +756,7 @@ ThemeEditor::ThemeEditor() { VBoxContainer *third_vb = memnew(VBoxContainer); third_vb->set_h_size_flags(SIZE_EXPAND_FILL); - third_vb->add_constant_override("separation", 10 * EDSCALE); + third_vb->add_theme_constant_override("separation", 10 * EDSCALE); main_hb->add_child(third_vb); TabContainer *tc = memnew(TabContainer); @@ -776,7 +776,7 @@ ThemeEditor::ThemeEditor() { Tree *test_tree = memnew(Tree); third_vb->add_child(test_tree); test_tree->set_custom_minimum_size(Size2(0, 175) * EDSCALE); - test_tree->add_constant_override("draw_relationship_lines", 1); + test_tree->add_theme_constant_override("draw_relationship_lines", 1); TreeItem *item = test_tree->create_item(); item->set_text(0, "Tree"); @@ -802,7 +802,7 @@ ThemeEditor::ThemeEditor() { item->set_text(0, TTR("Has,Many,Options")); item->set_range(0, 2); - main_hb->add_constant_override("separation", 20 * EDSCALE); + main_hb->add_theme_constant_override("separation", 20 * EDSCALE); //////// @@ -846,7 +846,7 @@ ThemeEditor::ThemeEditor() { name_menu->set_text(".."); name_hbc->add_child(name_menu); - name_menu->get_popup()->connect("about_to_show", callable_mp(this, &ThemeEditor::_name_menu_about_to_show)); + name_menu->get_popup()->connect("about_to_popup", callable_mp(this, &ThemeEditor::_name_menu_about_to_show)); name_menu->get_popup()->connect("id_pressed", callable_mp(this, &ThemeEditor::_name_menu_cbk)); type_select_label = memnew(Label); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 017f986469..83dc84a0c2 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -31,8 +31,8 @@ #include "tile_map_editor_plugin.h" #include "canvas_item_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/math/math_funcs.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -60,24 +60,24 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { - paint_button->set_icon(get_icon("Edit", "EditorIcons")); - bucket_fill_button->set_icon(get_icon("Bucket", "EditorIcons")); - picker_button->set_icon(get_icon("ColorPick", "EditorIcons")); - select_button->set_icon(get_icon("ActionCopy", "EditorIcons")); + paint_button->set_icon(get_theme_icon("Edit", "EditorIcons")); + bucket_fill_button->set_icon(get_theme_icon("Bucket", "EditorIcons")); + picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons")); + select_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); - rotate_left_button->set_icon(get_icon("RotateLeft", "EditorIcons")); - rotate_right_button->set_icon(get_icon("RotateRight", "EditorIcons")); - flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons")); - flip_vertical_button->set_icon(get_icon("MirrorY", "EditorIcons")); - clear_transform_button->set_icon(get_icon("Clear", "EditorIcons")); + rotate_left_button->set_icon(get_theme_icon("RotateLeft", "EditorIcons")); + rotate_right_button->set_icon(get_theme_icon("RotateRight", "EditorIcons")); + flip_horizontal_button->set_icon(get_theme_icon("MirrorX", "EditorIcons")); + flip_vertical_button->set_icon(get_theme_icon("MirrorY", "EditorIcons")); + clear_transform_button->set_icon(get_theme_icon("Clear", "EditorIcons")); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); PopupMenu *p = options->get_popup(); - p->set_item_icon(p->get_item_index(OPTION_CUT), get_icon("ActionCut", "EditorIcons")); - p->set_item_icon(p->get_item_index(OPTION_COPY), get_icon("Duplicate", "EditorIcons")); - p->set_item_icon(p->get_item_index(OPTION_ERASE_SELECTION), get_icon("Remove", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_CUT), get_theme_icon("ActionCut", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_COPY), get_theme_icon("Duplicate", "EditorIcons")); + p->set_item_icon(p->get_item_index(OPTION_ERASE_SELECTION), get_theme_icon("Remove", "EditorIcons")); } break; } @@ -421,7 +421,7 @@ void TileMapEditor::_update_palette() { bool show_tile_ids = bool(EDITOR_DEF("editors/tile_map/show_tile_ids", false)); bool sort_by_name = bool(EDITOR_DEF("editors/tile_map/sort_tiles_by_name", true)); - palette->add_constant_override("hseparation", hseparation * EDSCALE); + palette->add_theme_constant_override("hseparation", hseparation * EDSCALE); palette->set_fixed_icon_size(Size2(min_size, min_size)); palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1)); @@ -984,7 +984,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (mb->is_pressed()) { - if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) + if (InputFilter::get_singleton()->is_key_pressed(KEY_SPACE)) return false; // Drag. if (tool == TOOL_NONE) { @@ -1365,7 +1365,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } - if (tool == TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (tool == TOOL_PICKING && InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { _pick_tile(over_tile); @@ -1960,7 +1960,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { palette->set_icon_mode(ItemList::ICON_MODE_TOP); palette->set_max_text_lines(2); palette->set_select_mode(ItemList::SELECT_MULTI); - palette->add_constant_override("vseparation", 8 * EDSCALE); + palette->add_theme_constant_override("vseparation", 8 * EDSCALE); palette->connect("item_selected", callable_mp(this, &TileMapEditor::_palette_selected)); palette->connect("multi_selected", callable_mp(this, &TileMapEditor::_palette_multi_selected)); palette_container->add_child(palette); @@ -2031,7 +2031,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { tile_info = memnew(Label); tile_info->set_modulate(Color(1, 1, 1, 0.8)); tile_info->set_mouse_filter(MOUSE_FILTER_IGNORE); - tile_info->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts")); + tile_info->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts")); // The tile info is only displayed after a tile has been hovered. tile_info->hide(); CanvasItemEditor::get_singleton()->add_control_to_info_overlay(tile_info); @@ -2039,7 +2039,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { // Menu. options = memnew(MenuButton); options->set_text("TileMap"); - options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons")); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("TileMap", "EditorIcons")); options->set_process_unhandled_key_input(false); toolbar_right->add_child(options); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index a5a667802e..5d13b834cf 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -30,7 +30,7 @@ #include "tile_set_editor_plugin.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "editor/editor_scale.h" #include "editor/plugins/canvas_item_editor_plugin.h" @@ -284,47 +284,47 @@ void TileSetEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - add_constant_override("autohide", 1); // Fixes the dragger always showing up. + add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up. } break; case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_icon(get_icon("ToolAddNode", "EditorIcons")); - tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_icon(get_icon("Remove", "EditorIcons")); - tileset_toolbar_tools->set_icon(get_icon("Tools", "EditorIcons")); - - tool_workspacemode[WORKSPACE_EDIT]->set_icon(get_icon("Edit", "EditorIcons")); - tool_workspacemode[WORKSPACE_CREATE_SINGLE]->set_icon(get_icon("AddSingleTile", "EditorIcons")); - tool_workspacemode[WORKSPACE_CREATE_AUTOTILE]->set_icon(get_icon("AddAutotile", "EditorIcons")); - tool_workspacemode[WORKSPACE_CREATE_ATLAS]->set_icon(get_icon("AddAtlasTile", "EditorIcons")); - - tools[TOOL_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); - tools[BITMASK_COPY]->set_icon(get_icon("Duplicate", "EditorIcons")); - tools[BITMASK_PASTE]->set_icon(get_icon("Override", "EditorIcons")); - tools[BITMASK_CLEAR]->set_icon(get_icon("Clear", "EditorIcons")); - tools[SHAPE_NEW_POLYGON]->set_icon(get_icon("CollisionPolygon2D", "EditorIcons")); - tools[SHAPE_NEW_RECTANGLE]->set_icon(get_icon("CollisionShape2D", "EditorIcons")); - tools[SELECT_PREVIOUS]->set_icon(get_icon("ArrowLeft", "EditorIcons")); - tools[SELECT_NEXT]->set_icon(get_icon("ArrowRight", "EditorIcons")); - tools[SHAPE_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); - tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); - tools[TOOL_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); - tools[ZOOM_OUT]->set_icon(get_icon("ZoomLess", "EditorIcons")); - tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons")); - tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons")); - tools[VISIBLE_INFO]->set_icon(get_icon("InformationSign", "EditorIcons")); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_icon(get_theme_icon("ToolAddNode", "EditorIcons")); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_icon(get_theme_icon("Remove", "EditorIcons")); + tileset_toolbar_tools->set_icon(get_theme_icon("Tools", "EditorIcons")); + + tool_workspacemode[WORKSPACE_EDIT]->set_icon(get_theme_icon("Edit", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_SINGLE]->set_icon(get_theme_icon("AddSingleTile", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_AUTOTILE]->set_icon(get_theme_icon("AddAutotile", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_ATLAS]->set_icon(get_theme_icon("AddAtlasTile", "EditorIcons")); + + tools[TOOL_SELECT]->set_icon(get_theme_icon("ToolSelect", "EditorIcons")); + tools[BITMASK_COPY]->set_icon(get_theme_icon("Duplicate", "EditorIcons")); + tools[BITMASK_PASTE]->set_icon(get_theme_icon("Override", "EditorIcons")); + tools[BITMASK_CLEAR]->set_icon(get_theme_icon("Clear", "EditorIcons")); + tools[SHAPE_NEW_POLYGON]->set_icon(get_theme_icon("CollisionPolygon2D", "EditorIcons")); + tools[SHAPE_NEW_RECTANGLE]->set_icon(get_theme_icon("CollisionShape2D", "EditorIcons")); + tools[SELECT_PREVIOUS]->set_icon(get_theme_icon("ArrowLeft", "EditorIcons")); + tools[SELECT_NEXT]->set_icon(get_theme_icon("ArrowRight", "EditorIcons")); + tools[SHAPE_DELETE]->set_icon(get_theme_icon("Remove", "EditorIcons")); + tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_theme_icon("Snap", "EditorIcons")); + tools[TOOL_GRID_SNAP]->set_icon(get_theme_icon("SnapGrid", "EditorIcons")); + tools[ZOOM_OUT]->set_icon(get_theme_icon("ZoomLess", "EditorIcons")); + tools[ZOOM_1]->set_icon(get_theme_icon("ZoomReset", "EditorIcons")); + tools[ZOOM_IN]->set_icon(get_theme_icon("ZoomMore", "EditorIcons")); + tools[VISIBLE_INFO]->set_icon(get_theme_icon("InformationSign", "EditorIcons")); _update_toggle_shape_button(); - tool_editmode[EDITMODE_REGION]->set_icon(get_icon("RegionEdit", "EditorIcons")); - tool_editmode[EDITMODE_COLLISION]->set_icon(get_icon("StaticBody2D", "EditorIcons")); - tool_editmode[EDITMODE_OCCLUSION]->set_icon(get_icon("LightOccluder2D", "EditorIcons")); - tool_editmode[EDITMODE_NAVIGATION]->set_icon(get_icon("Navigation2D", "EditorIcons")); - tool_editmode[EDITMODE_BITMASK]->set_icon(get_icon("PackedDataContainer", "EditorIcons")); - tool_editmode[EDITMODE_PRIORITY]->set_icon(get_icon("MaterialPreviewLight1", "EditorIcons")); - tool_editmode[EDITMODE_ICON]->set_icon(get_icon("LargeTexture", "EditorIcons")); - tool_editmode[EDITMODE_Z_INDEX]->set_icon(get_icon("Sort", "EditorIcons")); + tool_editmode[EDITMODE_REGION]->set_icon(get_theme_icon("RegionEdit", "EditorIcons")); + tool_editmode[EDITMODE_COLLISION]->set_icon(get_theme_icon("StaticBody2D", "EditorIcons")); + tool_editmode[EDITMODE_OCCLUSION]->set_icon(get_theme_icon("LightOccluder2D", "EditorIcons")); + tool_editmode[EDITMODE_NAVIGATION]->set_icon(get_theme_icon("Navigation2D", "EditorIcons")); + tool_editmode[EDITMODE_BITMASK]->set_icon(get_theme_icon("PackedDataContainer", "EditorIcons")); + tool_editmode[EDITMODE_PRIORITY]->set_icon(get_theme_icon("MaterialPreviewLight1", "EditorIcons")); + tool_editmode[EDITMODE_ICON]->set_icon(get_theme_icon("LargeTexture", "EditorIcons")); + tool_editmode[EDITMODE_Z_INDEX]->set_icon(get_theme_icon("Sort", "EditorIcons")); - scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); } break; } } @@ -619,7 +619,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { //--------------- texture_dialog = memnew(EditorFileDialog); texture_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); - texture_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILES); + texture_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); texture_dialog->clear_filters(); List<String> extensions; @@ -1113,7 +1113,7 @@ void TileSetEditor::_on_workspace_draw() { void TileSetEditor::_on_workspace_process() { - if (Input::get_singleton()->is_key_pressed(KEY_ALT) || tools[VISIBLE_INFO]->is_pressed()) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_ALT) || tools[VISIBLE_INFO]->is_pressed()) { if (!tile_names_visible) { tile_names_visible = true; workspace_overlay->update(); @@ -1153,7 +1153,7 @@ void TileSetEditor::_on_workspace_overlay_draw() { else if (tileset->tile_get_tile_mode(t_id) == TileSet::ATLAS_TILE) c = COLOR_ATLAS; String tile_id_name = String::num(t_id, 0) + ": " + tileset->tile_get_name(t_id); - Ref<Font> font = get_font("font", "Label"); + Ref<Font> font = get_theme_font("font", "Label"); region.set_size(font->get_string_size(tile_id_name)); workspace_overlay->draw_rect(region, c); region.position.y += region.size.y - 2; @@ -1167,7 +1167,7 @@ void TileSetEditor::_on_workspace_overlay_draw() { if (t_id < 0) return; - Ref<Texture2D> handle = get_icon("EditorHandle", "EditorIcons"); + Ref<Texture2D> handle = get_theme_icon("EditorHandle", "EditorIcons"); if (draw_handles) { for (int i = 0; i < current_shape.size(); i++) { workspace_overlay->draw_texture(handle, current_shape[i] * workspace->get_scale().x - handle->get_size() * 0.5); @@ -1395,7 +1395,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { if ((mb->get_button_index() == BUTTON_RIGHT || mb->get_button_index() == BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) { dragging = true; erasing = (mb->get_button_index() == BUTTON_RIGHT); - alternative = Input::get_singleton()->is_key_pressed(KEY_SHIFT); + alternative = InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT); Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); pos = mb->get_position() - (pos + current_tile_region.position); @@ -2019,10 +2019,10 @@ void TileSetEditor::_update_toggle_shape_button() { separator_shape_toggle->hide(); tools[SHAPE_TOGGLE_TYPE]->hide(); } else if (concave.is_valid()) { - tools[SHAPE_TOGGLE_TYPE]->set_icon(get_icon("ConvexPolygonShape2D", "EditorIcons")); + tools[SHAPE_TOGGLE_TYPE]->set_icon(get_theme_icon("ConvexPolygonShape2D", "EditorIcons")); tools[SHAPE_TOGGLE_TYPE]->set_text(TTR("Make Convex")); } else if (convex.is_valid()) { - tools[SHAPE_TOGGLE_TYPE]->set_icon(get_icon("ConcavePolygonShape2D", "EditorIcons")); + tools[SHAPE_TOGGLE_TYPE]->set_icon(get_theme_icon("ConcavePolygonShape2D", "EditorIcons")); tools[SHAPE_TOGGLE_TYPE]->set_text(TTR("Make Concave")); } else { // Shouldn't happen diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index da80eee253..3998a3233b 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -217,12 +217,12 @@ void VersionControlEditorPlugin::_stage_selected() { if (file_entry->is_checked(0)) { EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0)); - file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor")); staged_files_count++; } else { EditorVCSInterface::get_singleton()->unstage_file(file_entry->get_metadata(0)); - file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); } file_entry = file_entry->get_next(); @@ -248,7 +248,7 @@ void VersionControlEditorPlugin::_stage_all() { while (file_entry) { EditorVCSInterface::get_singleton()->stage_file(file_entry->get_metadata(0)); - file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + file_entry->set_icon_modulate(0, EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor")); file_entry->set_checked(0, true); staged_files_count++; @@ -275,20 +275,20 @@ void VersionControlEditorPlugin::_display_file_diff(String p_file_path) { diff_file_name->set_text(p_file_path); diff->clear(); - diff->push_font(EditorNode::get_singleton()->get_gui_base()->get_font("source", "EditorFonts")); + diff->push_font(EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts")); for (int i = 0; i < diff_content.size(); i++) { Dictionary line_result = diff_content[i]; if (line_result["status"] == "+") { - diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor")); } else if (line_result["status"] == "-") { - diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); } else { - diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_color("font_color", "Label")); + diff->push_color(EditorNode::get_singleton()->get_gui_base()->get_theme_color("font_color", "Label")); } diff->add_text((String)line_result["content"]); @@ -408,11 +408,10 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { staged_files_count = 0; version_control_actions = memnew(PopupMenu); - version_control_actions->set_v_size_flags(BoxContainer::SIZE_SHRINK_CENTER); set_up_dialog = memnew(AcceptDialog); set_up_dialog->set_title(TTR("Set Up Version Control")); - set_up_dialog->set_custom_minimum_size(Size2(400, 100)); + set_up_dialog->set_min_size(Size2(400, 100)); version_control_actions->add_child(set_up_dialog); set_up_ok_button = set_up_dialog->get_ok(); @@ -446,9 +445,6 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { set_up_init_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_initialize_vcs)); set_up_vbc->add_child(set_up_init_button); - version_control_actions->set_v_size_flags(PopupMenu::SIZE_EXPAND_FILL); - version_control_actions->set_h_size_flags(PopupMenu::SIZE_EXPAND_FILL); - version_commit_dock = memnew(VBoxContainer); version_commit_dock->set_visible(false); @@ -470,7 +466,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { refresh_button = memnew(Button); refresh_button->set_tooltip(TTR("Detect new changes")); refresh_button->set_text(TTR("Refresh")); - refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Reload", "EditorIcons")); + refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Reload", "EditorIcons")); refresh_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_refresh_stage_area)); stage_tools->add_child(refresh_button); @@ -495,11 +491,11 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { change_type_to_strings[CHANGE_TYPE_DELETED] = TTR("Deleted"); change_type_to_strings[CHANGE_TYPE_TYPECHANGE] = TTR("Typechange"); - change_type_to_color[CHANGE_TYPE_NEW] = EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor"); - change_type_to_color[CHANGE_TYPE_MODIFIED] = EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor"); - change_type_to_color[CHANGE_TYPE_RENAMED] = EditorNode::get_singleton()->get_gui_base()->get_color("disabled_font_color", "Editor"); - change_type_to_color[CHANGE_TYPE_DELETED] = EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"); - change_type_to_color[CHANGE_TYPE_TYPECHANGE] = EditorNode::get_singleton()->get_gui_base()->get_color("font_color", "Editor"); + change_type_to_color[CHANGE_TYPE_NEW] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor"); + change_type_to_color[CHANGE_TYPE_MODIFIED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor"); + change_type_to_color[CHANGE_TYPE_RENAMED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("disabled_font_color", "Editor"); + change_type_to_color[CHANGE_TYPE_DELETED] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor"); + change_type_to_color[CHANGE_TYPE_TYPECHANGE] = EditorNode::get_singleton()->get_gui_base()->get_theme_color("font_color", "Editor"); stage_buttons = memnew(HSplitContainer); stage_buttons->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN_COLLAPSED); @@ -562,7 +558,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { diff_refresh_button = memnew(Button); diff_refresh_button->set_tooltip(TTR("Detect changes in file diff")); - diff_refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Reload", "EditorIcons")); + diff_refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Reload", "EditorIcons")); diff_refresh_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_refresh_file_diff)); diff_hbc->add_child(diff_refresh_button); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index a10e1c1d2c..36f81b21ba 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -30,9 +30,9 @@ #include "visual_shader_editor_plugin.h" +#include "core/input/input_filter.h" #include "core/io/resource_loader.h" #include "core/math/math_defs.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "core/version.h" @@ -42,8 +42,9 @@ #include "scene/animation/animation_player.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/visual_shader_nodes.h" +#include "servers/display_server.h" #include "servers/visual/shader_types.h" Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) { @@ -312,8 +313,8 @@ void VisualShaderEditor::_update_options_menu() { bool is_first_item = true; - Color unsupported_color = get_color("error_color", "Editor"); - Color supported_color = get_color("warning_color", "Editor"); + Color unsupported_color = get_theme_color("error_color", "Editor"); + Color supported_color = get_theme_color("warning_color", "Editor"); static bool low_driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES2"; @@ -385,22 +386,22 @@ void VisualShaderEditor::_update_options_menu() { } switch (options[i].return_type) { case VisualShaderNode::PORT_TYPE_SCALAR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons")); + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("float", "EditorIcons")); break; case VisualShaderNode::PORT_TYPE_SCALAR_INT: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("int", "EditorIcons")); + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons")); break; case VisualShaderNode::PORT_TYPE_VECTOR: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons")); + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons")); break; case VisualShaderNode::PORT_TYPE_BOOLEAN: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons")); + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons")); break; case VisualShaderNode::PORT_TYPE_TRANSFORM: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons")); + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform", "EditorIcons")); break; case VisualShaderNode::PORT_TYPE_SAMPLER: - item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("ImageTexture", "EditorIcons")); + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons")); break; default: break; @@ -420,7 +421,7 @@ void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) { if (!button) return; - Ref<StyleBox> normal = get_stylebox("normal", "Button"); + Ref<StyleBox> normal = get_theme_stylebox("normal", "Button"); button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } @@ -436,7 +437,7 @@ static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_ void VisualShaderEditor::_update_created_node(GraphNode *node) { if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Ref<StyleBoxFlat> sb = node->get_stylebox("frame", "GraphNode"); + Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); Color c = sb->get_border_color(); Color ic; Color mono_color; @@ -450,10 +451,10 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) { mono_color.a = 0.85; c = mono_color; - node->add_color_override("title_color", c); + node->add_theme_color_override("title_color", c); c.a = 0.7; - node->add_color_override("close_color", c); - node->add_color_override("resizer_color", ic); + node->add_theme_color_override("close_color", c); + node->add_theme_color_override("resizer_color", ic); } } @@ -641,7 +642,7 @@ void VisualShaderEditor::_update_graph() { } HBoxContainer *hb = memnew(HBoxContainer); - hb->add_constant_override("separation", 7 * EDSCALE); + hb->add_theme_constant_override("separation", 7 * EDSCALE); Variant default_value; @@ -705,7 +706,7 @@ void VisualShaderEditor::_update_graph() { name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, false)); Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); remove_btn->set_tooltip(TTR("Remove") + " " + name_left); remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_input_port), varray(nodes[n_i], i), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -713,15 +714,15 @@ void VisualShaderEditor::_update_graph() { Label *label = memnew(Label); label->set_text(name_left); - label->add_style_override("normal", label_style); //more compact + label->add_theme_style_override("normal", label_style); //more compact hb->add_child(label); if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { Label *hint_label = memnew(Label); hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); - hint_label->add_color_override("font_color", get_color("font_color_readonly", "TextEdit")); - hint_label->add_style_override("normal", label_style); + hint_label->add_theme_color_override("font_color", get_theme_color("font_color_readonly", "TextEdit")); + hint_label->add_theme_style_override("normal", label_style); hb->add_child(hint_label); } } @@ -734,7 +735,7 @@ void VisualShaderEditor::_update_graph() { if (valid_right) { if (is_group) { Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); remove_btn->set_tooltip(TTR("Remove") + " " + name_left); remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_output_port), varray(nodes[n_i], i), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -760,7 +761,7 @@ void VisualShaderEditor::_update_graph() { } else { Label *label = memnew(Label); label->set_text(name_right); - label->add_style_override("normal", label_style); //more compact + label->add_theme_style_override("normal", label_style); //more compact hb->add_child(label); } } @@ -769,8 +770,8 @@ void VisualShaderEditor::_update_graph() { if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { TextureButton *preview = memnew(TextureButton); preview->set_toggle_mode(true); - preview->set_normal_texture(get_icon("GuiVisibilityHidden", "EditorIcons")); - preview->set_pressed_texture(get_icon("GuiVisibilityVisible", "EditorIcons")); + preview->set_normal_texture(get_theme_icon("GuiVisibilityHidden", "EditorIcons")); + preview->set_pressed_texture(get_theme_icon("GuiVisibilityVisible", "EditorIcons")); preview->set_v_size_flags(SIZE_SHRINK_CENTER); if (vsnode->get_output_port_for_preview() == i) { @@ -815,7 +816,7 @@ void VisualShaderEditor::_update_graph() { String error = vsnode->get_warning(visual_shader->get_mode(), type); if (error != String()) { Label *error_label = memnew(Label); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); error_label->set_text(error); node->add_child(error_label); } @@ -833,16 +834,16 @@ void VisualShaderEditor::_update_graph() { Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); expression_box->set_syntax_coloring(true); - expression_box->add_color_override("background_color", background_color); + expression_box->add_theme_color_override("background_color", background_color); for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) { expression_box->add_keyword_color(E->get(), keyword_color); } - expression_box->add_font_override("font", get_font("expression", "EditorFonts")); - expression_box->add_color_override("font_color", text_color); - expression_box->add_color_override("symbol_color", symbol_color); + expression_box->add_theme_font_override("font", get_theme_font("expression", "EditorFonts")); + expression_box->add_theme_color_override("font_color", text_color); + expression_box->add_theme_color_override("symbol_color", symbol_color); expression_box->add_color_region("/*", "*/", comment_color, false); expression_box->add_color_region("//", "", comment_color, false); @@ -1272,7 +1273,7 @@ void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, Button *button = Object::cast_to<Button>(p_button); ERR_FAIL_COND(!button); Variant value = vsn->get_input_port_default_value(p_port); - property_editor->set_global_position(button->get_global_position() + Vector2(0, button->get_size().height)); + property_editor->set_position(button->get_screen_position() + Vector2(0, button->get_size().height)); property_editor->edit(NULL, "", value.get_type(), value, 0, ""); property_editor->popup(); editing_node = p_node; @@ -1623,7 +1624,7 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { popup_menu->set_item_disabled(NodeMenuOptions::DELETE, to_change.empty()); popup_menu->set_item_disabled(NodeMenuOptions::DUPLICATE, to_change.empty()); menu_point = graph->get_local_mouse_position(); - Point2 gpos = Input::get_singleton()->get_mouse_position(); + Point2 gpos = InputFilter::get_singleton()->get_mouse_position(); popup_menu->set_position(gpos); popup_menu->popup(); } @@ -1636,7 +1637,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) { saved_node_pos_dirty = true; saved_node_pos = graph->get_local_mouse_position(); - Point2 gpos = Input::get_singleton()->get_mouse_position(); + Point2 gpos = InputFilter::get_singleton()->get_mouse_position(); members_dialog->popup(); members_dialog->set_position(gpos); } else { @@ -1646,8 +1647,8 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) { } // keep dialog within window bounds - Size2 window_size = OS::get_singleton()->get_window_size(); - Rect2 dialog_rect = members_dialog->get_global_rect(); + Size2 window_size = DisplayServer::get_singleton()->window_get_size(); + Rect2 dialog_rect = Rect2(members_dialog->get_position(), members_dialog->get_size()); if (dialog_rect.position.y + dialog_rect.size.y > window_size.y) { int difference = dialog_rect.position.y + dialog_rect.size.y - window_size.y; members_dialog->set_position(members_dialog->get_position() - Point2(0, difference)); @@ -1703,14 +1704,14 @@ void VisualShaderEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - highend_label->set_modulate(get_color("vulkan_color", "Editor")); + highend_label->set_modulate(get_theme_color("vulkan_color", "Editor")); - error_panel->add_style_override("panel", get_stylebox("bg", "Tree")); - error_label->add_color_override("font_color", get_color("error_color", "Editor")); + error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree")); + error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - node_filter->set_right_icon(Control::get_icon("Search", "EditorIcons")); + node_filter->set_right_icon(Control::get_theme_icon("Search", "EditorIcons")); - preview_shader->set_icon(Control::get_icon("Shader", "EditorIcons")); + preview_shader->set_icon(Control::get_theme_icon("Shader", "EditorIcons")); { Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); @@ -1719,24 +1720,24 @@ void VisualShaderEditor::_notification(int p_what) { Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - preview_text->add_color_override("background_color", background_color); + preview_text->add_theme_color_override("background_color", background_color); for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) { preview_text->add_keyword_color(E->get(), keyword_color); } - preview_text->add_font_override("font", get_font("expression", "EditorFonts")); - preview_text->add_color_override("font_color", text_color); - preview_text->add_color_override("symbol_color", symbol_color); + preview_text->add_theme_font_override("font", get_theme_font("expression", "EditorFonts")); + preview_text->add_theme_color_override("font_color", text_color); + preview_text->add_theme_color_override("symbol_color", symbol_color); preview_text->add_color_region("/*", "*/", comment_color, false); preview_text->add_color_region("//", "", comment_color, false); - error_text->add_font_override("font", get_font("status_source", "EditorFonts")); - error_text->add_color_override("font_color", get_color("error_color", "Editor")); + error_text->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts")); + error_text->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); } - tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Tools", "EditorIcons")); + tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Tools", "EditorIcons")); if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) _update_graph(); @@ -2489,13 +2490,10 @@ VisualShaderEditor::VisualShaderEditor() { members_dialog->get_ok()->set_text(TTR("Create")); members_dialog->get_ok()->connect("pressed", callable_mp(this, &VisualShaderEditor::_member_create)); members_dialog->get_ok()->set_disabled(true); - members_dialog->set_resizable(true); - members_dialog->set_as_minsize(); - members_dialog->connect("hide", callable_mp(this, &VisualShaderEditor::_member_cancel)); + members_dialog->connect("cancelled", callable_mp(this, &VisualShaderEditor::_member_cancel)); add_child(members_dialog); alert = memnew(AcceptDialog); - alert->set_as_minsize(); alert->get_label()->set_autowrap(true); alert->get_label()->set_align(Label::ALIGN_CENTER); alert->get_label()->set_valign(Label::VALIGN_CENTER); @@ -2982,12 +2980,12 @@ public: void setup(const Ref<VisualShaderNodeInput> &p_input) { input = p_input; Ref<Texture2D> type_icon[6] = { - EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons"), - EditorNode::get_singleton()->get_gui_base()->get_icon("int", "EditorIcons"), - EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons"), - EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons"), - EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons"), - EditorNode::get_singleton()->get_gui_base()->get_icon("ImageTexture", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon("float", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon("int", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Vector3", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon("bool", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Transform", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_theme_icon("ImageTexture", "EditorIcons"), }; add_item("[None]"); diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index cdc5255edd..859718cba4 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "editor_scale.h" #include "main/main.h" +#include "servers/display_server.h" void BackgroundProgress::_add_task(const String &p_task, const String &p_label, int p_steps) { @@ -137,16 +138,6 @@ void BackgroundProgress::end_task(const String &p_task) { ProgressDialog *ProgressDialog::singleton = NULL; void ProgressDialog::_notification(int p_what) { - - switch (p_what) { - - case NOTIFICATION_DRAW: { - - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); - draw_style_box(style, Rect2(Point2(), get_size())); - - } break; - } } void ProgressDialog::_popup() { @@ -154,14 +145,14 @@ void ProgressDialog::_popup() { Size2 ms = main->get_combined_minimum_size(); ms.width = MAX(500 * EDSCALE, ms.width); - Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); + Ref<StyleBox> style = main->get_theme_stylebox("panel", "PopupMenu"); ms += style->get_minimum_size(); main->set_margin(MARGIN_LEFT, style->get_margin(MARGIN_LEFT)); main->set_margin(MARGIN_RIGHT, -style->get_margin(MARGIN_RIGHT)); main->set_margin(MARGIN_TOP, style->get_margin(MARGIN_TOP)); main->set_margin(MARGIN_BOTTOM, -style->get_margin(MARGIN_BOTTOM)); - raise(); + //raise(); popup_centered(ms); } @@ -219,7 +210,7 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int t.state->set_text(p_state); last_progress_tick = OS::get_singleton()->get_ticks_usec(); if (cancel_hb->is_visible()) { - OS::get_singleton()->force_process_input(); + DisplayServer::get_singleton()->process_events(); } Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor diff --git a/editor/progress_dialog.h b/editor/progress_dialog.h index e01c7d802b..82f479ae9d 100644 --- a/editor/progress_dialog.h +++ b/editor/progress_dialog.h @@ -68,9 +68,9 @@ public: BackgroundProgress() {} }; -class ProgressDialog : public Popup { +class ProgressDialog : public PopupPanel { - GDCLASS(ProgressDialog, Popup); + GDCLASS(ProgressDialog, PopupPanel); struct Task { String task; diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 37b959c78a..39c24519c0 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -46,25 +46,28 @@ #include "scene/gui/margin_container.h" #include "scene/gui/scroll_container.h" #include "scene/gui/tab_container.h" - +#include "servers/display_server.h" + +void ProjectExportDialog::_theme_changed() { + duplicate_preset->set_icon(presets->get_theme_icon("Duplicate", "EditorIcons")); + delete_preset->set_icon(presets->get_theme_icon("Remove", "EditorIcons")); + Control *panel = custom_feature_display->get_parent_control(); + if (panel) + panel->add_theme_style_override("panel", patches->get_theme_stylebox("bg", "Tree")); +} void ProjectExportDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "export", Rect2(get_position(), get_size())); + } + } break; case NOTIFICATION_READY: { - duplicate_preset->set_icon(get_icon("Duplicate", "EditorIcons")); - delete_preset->set_icon(get_icon("Remove", "EditorIcons")); + duplicate_preset->set_icon(presets->get_theme_icon("Duplicate", "EditorIcons")); + delete_preset->set_icon(presets->get_theme_icon("Remove", "EditorIcons")); connect("confirmed", callable_mp(this, &ProjectExportDialog::_export_pck_zip)); - custom_feature_display->get_parent_control()->add_style_override("panel", get_stylebox("bg", "Tree")); - } break; - case NOTIFICATION_POPUP_HIDE: { - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "export", get_rect()); - } break; - case NOTIFICATION_THEME_CHANGED: { - duplicate_preset->set_icon(get_icon("Duplicate", "EditorIcons")); - delete_preset->set_icon(get_icon("Remove", "EditorIcons")); - Control *panel = custom_feature_display->get_parent_control(); - if (panel) - panel->add_style_override("panel", get_stylebox("bg", "Tree")); + custom_feature_display->get_parent_control()->add_theme_style_override("panel", patches->get_theme_stylebox("bg", "Tree")); } break; } } @@ -247,8 +250,8 @@ void ProjectExportDialog::_edit_preset(int p_index) { patch->set_checked(0, true); patch->set_tooltip(0, patchlist[i]); patch->set_metadata(0, i); - patch->add_button(0, get_icon("Remove", "EditorIcons"), 0); - patch->add_button(0, get_icon("folder", "FileDialog"), 1); + patch->add_button(0, presets->get_theme_icon("Remove", "EditorIcons"), 0); + patch->add_button(0, presets->get_theme_icon("folder", "FileDialog"), 1); } TreeItem *patch_add = patches->create_item(patch_root); @@ -258,7 +261,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { else patch_add->set_text(0, TTR("Add previous patches...")); - patch_add->add_button(0, get_icon("folder", "FileDialog"), 1); + patch_add->add_button(0, presets->get_theme_icon("folder", "FileDialog"), 1); _fill_resource_tree(); @@ -299,7 +302,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { custom_features->set_text(current->get_custom_features()); _update_feature_list(); _update_export_all(); - minimum_size_changed(); + child_controls_changed(); int script_export_mode = current->get_script_export_mode(); script_mode->select(script_export_mode); @@ -388,7 +391,7 @@ void ProjectExportDialog::_patch_button_pressed(Object *p_item, int p_column, in Vector<String> patches = current->get_patches(); ERR_FAIL_INDEX(patch_index, patches.size()); patch_erase->set_text(vformat(TTR("Delete patch '%s' from list?"), patches[patch_index].get_file())); - patch_erase->popup_centered_minsize(); + patch_erase->popup_centered(); } else { patch_dialog->popup_centered_ratio(); } @@ -618,7 +621,7 @@ void ProjectExportDialog::_delete_preset() { return; delete_confirm->set_text(vformat(TTR("Delete preset '%s'?"), current->get_name())); - delete_confirm->popup_centered_minsize(); + delete_confirm->popup_centered(); } void ProjectExportDialog::_delete_preset_confirm() { @@ -649,7 +652,7 @@ Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_ label->set_text(presets->get_item_text(pos)); drag->add_child(label); - set_drag_preview(drag); + presets->set_drag_preview(drag); return d; } @@ -666,7 +669,7 @@ Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_ Label *label = memnew(Label); label->set_text(item->get_text(0)); - set_drag_preview(label); + patches->set_drag_preview(label); return d; } @@ -816,7 +819,7 @@ void ProjectExportDialog::_fill_resource_tree() { bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, bool p_only_scenes) { - p_item->set_icon(0, get_icon("folder", "FileDialog")); + p_item->set_icon(0, presets->get_theme_icon("folder", "FileDialog")); p_item->set_text(0, p_dir->get_name() + "/"); bool used = false; @@ -954,7 +957,7 @@ void ProjectExportDialog::_export_project() { export_project->get_line_edit()->connect_compat("text_entered", export_project, "_file_entered"); } - export_project->set_mode(EditorFileDialog::MODE_SAVE_FILE); + export_project->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); export_project->popup_centered_ratio(); } @@ -979,14 +982,14 @@ void ProjectExportDialog::_export_project_to_path(const String &p_path) { ERR_PRINT(vformat("Failed to export the project for platform '%s'.", platform->get_name())); error_dialog->show(); - error_dialog->popup_centered_minsize(Size2(300, 80)); + error_dialog->popup_centered(Size2(300, 80)); } } void ProjectExportDialog::_export_all_dialog() { export_all_dialog->show(); - export_all_dialog->popup_centered_minsize(Size2(300, 80)); + export_all_dialog->popup_centered(Size2(300, 80)); } void ProjectExportDialog::_export_all_dialog_action(const String &p_str) { @@ -1017,7 +1020,7 @@ void ProjectExportDialog::_export_all(bool p_debug) { error_dialog->set_text(TTR("Export templates for this platform are missing/corrupted:") + " " + platform->get_name()); } error_dialog->show(); - error_dialog->popup_centered_minsize(Size2(300, 80)); + error_dialog->popup_centered(Size2(300, 80)); ERR_PRINT("Failed to export project"); } } @@ -1039,13 +1042,13 @@ void ProjectExportDialog::_bind_methods() { ProjectExportDialog::ProjectExportDialog() { set_title(TTR("Export")); - set_resizable(true); VBoxContainer *main_vb = memnew(VBoxContainer); + main_vb->connect("theme_changed", callable_mp(this, &ProjectExportDialog::_theme_changed)); add_child(main_vb); HSplitContainer *hbox = memnew(HSplitContainer); main_vb->add_child(hbox); - hbox->set_v_size_flags(SIZE_EXPAND_FILL); + hbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); // Presets list. @@ -1064,9 +1067,12 @@ ProjectExportDialog::ProjectExportDialog() { preset_hb->add_child(add_preset); MarginContainer *mc = memnew(MarginContainer); preset_vb->add_child(mc); - mc->set_v_size_flags(SIZE_EXPAND_FILL); + mc->set_v_size_flags(Control::SIZE_EXPAND_FILL); presets = memnew(ItemList); - presets->set_drag_forwarding(this); +#ifndef _MSC_VER +#warning must reimplement drag forward +#endif + //presets->set_drag_forwarding(this); mc->add_child(presets); presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset)); duplicate_preset = memnew(ToolButton); @@ -1104,14 +1110,14 @@ ProjectExportDialog::ProjectExportDialog() { sections->set_tab_align(TabContainer::ALIGN_LEFT); sections->set_use_hidden_tabs_for_min_size(true); settings_vb->add_child(sections); - sections->set_v_size_flags(SIZE_EXPAND_FILL); + sections->set_v_size_flags(Control::SIZE_EXPAND_FILL); // Main preset parameters. parameters = memnew(EditorInspector); sections->add_child(parameters); parameters->set_name(TTR("Options")); - parameters->set_v_size_flags(SIZE_EXPAND_FILL); + parameters->set_v_size_flags(Control::SIZE_EXPAND_FILL); parameters->connect("property_edited", callable_mp(this, &ProjectExportDialog::_update_parameters)); // Resources export parameters. @@ -1131,7 +1137,7 @@ ProjectExportDialog::ProjectExportDialog() { include_label->set_text(TTR("Resources to export:")); resources_vb->add_child(include_label); include_margin = memnew(MarginContainer); - include_margin->set_v_size_flags(SIZE_EXPAND_FILL); + include_margin->set_v_size_flags(Control::SIZE_EXPAND_FILL); resources_vb->add_child(include_margin); include_files = memnew(Tree); @@ -1163,11 +1169,14 @@ ProjectExportDialog::ProjectExportDialog() { patches = memnew(Tree); patch_vb->add_child(patches); - patches->set_v_size_flags(SIZE_EXPAND_FILL); + patches->set_v_size_flags(Control::SIZE_EXPAND_FILL); patches->set_hide_root(true); patches->connect("button_pressed", callable_mp(this, &ProjectExportDialog::_patch_button_pressed)); patches->connect("item_edited", callable_mp(this, &ProjectExportDialog::_patch_edited)); - patches->set_drag_forwarding(this); +#ifndef _MSC_VER +#warning must reimplement drag forward +#endif + //patches->set_drag_forwarding(this); patches->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); HBoxContainer *patches_hb = memnew(HBoxContainer); @@ -1180,7 +1189,7 @@ ProjectExportDialog::ProjectExportDialog() { patch_dialog = memnew(EditorFileDialog); patch_dialog->add_filter("*.pck ; " + TTR("Pack File")); - patch_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); + patch_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); patch_dialog->connect("file_selected", callable_mp(this, &ProjectExportDialog::_patch_selected)); add_child(patch_dialog); @@ -1200,7 +1209,7 @@ ProjectExportDialog::ProjectExportDialog() { custom_feature_display = memnew(RichTextLabel); features_panel->add_child(custom_feature_display); custom_feature_display->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 10 * EDSCALE); - custom_feature_display->set_v_size_flags(SIZE_EXPAND_FILL); + custom_feature_display->set_v_size_flags(Control::SIZE_EXPAND_FILL); feature_vb->add_margin_child(TTR("Feature List:"), features_panel, true); sections->add_child(feature_vb); @@ -1220,7 +1229,7 @@ ProjectExportDialog::ProjectExportDialog() { script_key->connect("text_changed", callable_mp(this, &ProjectExportDialog::_script_encryption_key_changed)); script_key_error = memnew(Label); script_key_error->set_text("- " + TTR("Invalid Encryption Key (must be 64 characters long)")); - script_key_error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + script_key_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); script_vb->add_margin_child(TTR("Script Encryption Key (256-bits as hex):"), script_key); script_vb->add_child(script_key_error); sections->add_child(script_vb); @@ -1250,7 +1259,7 @@ ProjectExportDialog::ProjectExportDialog() { get_cancel()->set_text(TTR("Close")); get_ok()->set_text(TTR("Export PCK/Zip")); - export_button = add_button(TTR("Export Project"), !OS::get_singleton()->get_swap_ok_cancel(), "export"); + export_button = add_button(TTR("Export Project"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "export"); export_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_project)); // Disable initially before we select a valid preset export_button->set_disabled(true); @@ -1265,7 +1274,7 @@ ProjectExportDialog::ProjectExportDialog() { export_all_dialog->add_button(TTR("Release"), true, "release"); export_all_dialog->connect("custom_action", callable_mp(this, &ProjectExportDialog::_export_all_dialog_action)); - export_all_button = add_button(TTR("Export All"), !OS::get_singleton()->get_swap_ok_cancel(), "export"); + export_all_button = add_button(TTR("Export All"), !DisplayServer::get_singleton()->get_swap_ok_cancel(), "export"); export_all_button->connect("pressed", callable_mp(this, &ProjectExportDialog::_export_all_dialog)); export_all_button->set_disabled(true); @@ -1273,14 +1282,14 @@ ProjectExportDialog::ProjectExportDialog() { export_pck_zip->add_filter("*.zip ; " + TTR("ZIP File")); export_pck_zip->add_filter("*.pck ; " + TTR("Godot Game Pack")); export_pck_zip->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - export_pck_zip->set_mode(EditorFileDialog::MODE_SAVE_FILE); + export_pck_zip->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); add_child(export_pck_zip); export_pck_zip->connect("file_selected", callable_mp(this, &ProjectExportDialog::_export_pck_zip_selected)); export_error = memnew(Label); main_vb->add_child(export_error); export_error->hide(); - export_error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + export_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); export_templates_error = memnew(HBoxContainer); main_vb->add_child(export_templates_error); @@ -1288,7 +1297,7 @@ ProjectExportDialog::ProjectExportDialog() { Label *export_error2 = memnew(Label); export_templates_error->add_child(export_error2); - export_error2->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + export_error2->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " "); error_dialog = memnew(AcceptDialog); @@ -1299,7 +1308,7 @@ ProjectExportDialog::ProjectExportDialog() { LinkButton *download_templates = memnew(LinkButton); download_templates->set_text(TTR("Manage Export Templates")); - download_templates->set_v_size_flags(SIZE_SHRINK_CENTER); + download_templates->set_v_size_flags(Control::SIZE_SHRINK_CENTER); export_templates_error->add_child(download_templates); download_templates->connect("pressed", callable_mp(this, &ProjectExportDialog::_open_export_template_manager)); diff --git a/editor/project_export.h b/editor/project_export.h index 00e6dfd6e3..2e311eb3b3 100644 --- a/editor/project_export.h +++ b/editor/project_export.h @@ -167,6 +167,7 @@ private: void _tab_changed(int); protected: + void _theme_changed(); void _notification(int p_what); static void _bind_methods(); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 4e157e927e..d3856cf778 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -51,6 +51,8 @@ #include "scene/gui/separator.h" #include "scene/gui/texture_rect.h" #include "scene/gui/tool_button.h" +#include "scene/main/window.h" +#include "servers/display_server.h" static inline String get_project_key_from_path(const String &dir) { return dir.replace("/", "::"); @@ -115,22 +117,22 @@ private: case MESSAGE_ERROR: { - msg->add_color_override("font_color", get_color("error_color", "Editor")); + msg->add_theme_color_override("font_color", msg->get_theme_color("error_color", "Editor")); msg->set_modulate(Color(1, 1, 1, 1)); - new_icon = get_icon("StatusError", "EditorIcons"); + new_icon = msg->get_theme_icon("StatusError", "EditorIcons"); } break; case MESSAGE_WARNING: { - msg->add_color_override("font_color", get_color("warning_color", "Editor")); + msg->add_theme_color_override("font_color", msg->get_theme_color("warning_color", "Editor")); msg->set_modulate(Color(1, 1, 1, 1)); - new_icon = get_icon("StatusWarning", "EditorIcons"); + new_icon = msg->get_theme_icon("StatusWarning", "EditorIcons"); } break; case MESSAGE_SUCCESS: { msg->set_modulate(Color(1, 1, 1, 0)); - new_icon = get_icon("StatusSuccess", "EditorIcons"); + new_icon = msg->get_theme_icon("StatusSuccess", "EditorIcons"); } break; } @@ -141,7 +143,7 @@ private: install_status_rect->set_texture(new_icon); } - set_size(Size2(500, 0) * EDSCALE); + set_size(Size2i(500, 0) * EDSCALE); } String _test_path() { @@ -377,19 +379,19 @@ private: if (mode == MODE_IMPORT) { - fdialog->set_mode(FileDialog::MODE_OPEN_FILE); + fdialog->set_file_mode(FileDialog::FILE_MODE_OPEN_FILE); fdialog->clear_filters(); fdialog->add_filter(vformat("project.godot ; %s %s", VERSION_NAME, TTR("Project"))); fdialog->add_filter("*.zip ; " + TTR("ZIP File")); } else { - fdialog->set_mode(FileDialog::MODE_OPEN_DIR); + fdialog->set_file_mode(FileDialog::FILE_MODE_OPEN_DIR); } fdialog->popup_centered_ratio(); } void _browse_install_path() { fdialog_install->set_current_dir(install_path->get_text()); - fdialog_install->set_mode(FileDialog::MODE_OPEN_DIR); + fdialog_install->set_file_mode(FileDialog::FILE_MODE_OPEN_DIR); fdialog_install->popup_centered_ratio(); } @@ -416,12 +418,12 @@ private: } else { dialog_error->set_text(TTR("Couldn't create folder.")); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); } } else { dialog_error->set_text(TTR("There is already a folder in this path with the specified name.")); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); } } @@ -498,7 +500,7 @@ private: if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("project.godot"), initial_settings, Vector<String>(), false) != OK) { set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR); } else { - ResourceSaver::save(dir.plus_file("icon.png"), get_icon("DefaultProjectIcon", "EditorIcons")); + ResourceSaver::save(dir.plus_file("icon.png"), msg->get_theme_icon("DefaultProjectIcon", "EditorIcons")); FileAccess *f = FileAccess::open(dir.plus_file("default_env.tres"), FileAccess::WRITE); if (!f) { @@ -527,7 +529,7 @@ private: if (!pkg) { dialog_error->set_text(TTR("Error opening package file, not in ZIP format.")); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); return; } @@ -605,11 +607,11 @@ private: } dialog_error->set_text(msg); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); } else if (!project_path->get_text().ends_with(".zip")) { dialog_error->set_text(TTR("Package installed successfully!")); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); } } } @@ -647,16 +649,16 @@ private: project_name->clear(); _text_changed(""); - if (status_rect->get_texture() == get_icon("StatusError", "EditorIcons")) + if (status_rect->get_texture() == msg->get_theme_icon("StatusError", "EditorIcons")) msg->show(); - if (install_status_rect->get_texture() == get_icon("StatusError", "EditorIcons")) + if (install_status_rect->get_texture() == msg->get_theme_icon("StatusError", "EditorIcons")) msg->show(); } void _notification(int p_what) { - if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) + if (p_what == NOTIFICATION_WM_CLOSE_REQUEST) _remove_created_folder(); } @@ -786,7 +788,7 @@ public: _test_path(); } - popup_centered_minsize(Size2(500, 0) * EDSCALE); + popup_centered(Size2i(500, 0) * EDSCALE); } ProjectDialog() { @@ -805,7 +807,7 @@ public: name_container->add_child(pnhb); project_name = memnew(LineEdit); - project_name->set_h_size_flags(SIZE_EXPAND_FILL); + project_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); pnhb->add_child(project_name); create_dir = memnew(Button); @@ -824,7 +826,7 @@ public: path_container->add_child(pphb); project_path = memnew(LineEdit); - project_path->set_h_size_flags(SIZE_EXPAND_FILL); + project_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); pphb->add_child(project_path); install_path_container = memnew(VBoxContainer); @@ -838,7 +840,7 @@ public: install_path_container->add_child(iphb); install_path = memnew(LineEdit); - install_path->set_h_size_flags(SIZE_EXPAND_FILL); + install_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); iphb->add_child(install_path); // status icon @@ -876,7 +878,7 @@ public: rasterizer_button_group.instance(); Container *rvb = memnew(VBoxContainer); - rvb->set_h_size_flags(SIZE_EXPAND_FILL); + rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); rshb->add_child(rvb); Button *rs_button = memnew(CheckBox); rs_button->set_button_group(rasterizer_button_group); @@ -895,7 +897,7 @@ public: TTR("The GLES2 renderer is currently unavailable, as it needs to be reworked for Godot 4.0.\nUse Godot 3.2 if you need GLES2 support."); rvb = memnew(VBoxContainer); - rvb->set_h_size_flags(SIZE_EXPAND_FILL); + rvb->set_h_size_flags(Control::SIZE_EXPAND_FILL); rshb->add_child(rvb); rs_button = memnew(CheckBox); rs_button->set_button_group(rasterizer_button_group); @@ -910,7 +912,7 @@ public: // Also set the tooltip on the label so it appears when hovering either the checkbox or label. l->set_tooltip(gles2_unsupported_tooltip); // Required for the tooltip to show. - l->set_mouse_filter(MOUSE_FILTER_STOP); + l->set_mouse_filter(Control::MOUSE_FILTER_STOP); rvb->add_child(l); l = memnew(Label); @@ -975,7 +977,7 @@ public: } break; case NOTIFICATION_DRAW: { if (hover) { - draw_style_box(get_stylebox("hover", "Tree"), Rect2(Point2(), get_size() - Size2(10, 0) * EDSCALE)); + draw_style_box(get_theme_stylebox("hover", "Tree"), Rect2(Point2(), get_size() - Size2(10, 0) * EDSCALE)); } } break; } @@ -1045,6 +1047,9 @@ public: ProjectList(); ~ProjectList(); + void _global_menu_new_window(const Variant &p_tag); + void _global_menu_open_project(const Variant &p_tag); + void update_dock_menu(); void load_projects(); void set_search_term(String p_search_term); @@ -1116,7 +1121,7 @@ ProjectList::ProjectList() { _order_option = ProjectListFilter::FILTER_EDIT_DATE; _scroll_children = memnew(VBoxContainer); - _scroll_children->set_h_size_flags(SIZE_EXPAND_FILL); + _scroll_children->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_child(_scroll_children); _icon_load_index = 0; @@ -1150,7 +1155,7 @@ void ProjectList::_notification(int p_what) { void ProjectList::load_project_icon(int p_index) { Item &item = _projects.write[p_index]; - Ref<Texture2D> default_icon = get_icon("DefaultProjectIcon", "EditorIcons"); + Ref<Texture2D> default_icon = get_theme_icon("DefaultProjectIcon", "EditorIcons"); Ref<Texture2D> icon; if (item.icon != "") { Ref<Image> img; @@ -1284,7 +1289,11 @@ void ProjectList::load_projects() { } void ProjectList::update_dock_menu() { - OS::get_singleton()->global_menu_clear("_dock"); + + if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { + return; + } + DisplayServer::get_singleton()->global_menu_clear("_dock"); int favs_added = 0; int total_added = 0; @@ -1294,18 +1303,41 @@ void ProjectList::update_dock_menu() { favs_added++; } else { if (favs_added != 0) { - OS::get_singleton()->global_menu_add_separator("_dock"); + DisplayServer::get_singleton()->global_menu_add_separator("_dock"); } favs_added = 0; } - OS::get_singleton()->global_menu_add_item("_dock", _projects[i].project_name + " ( " + _projects[i].path + " )", GLOBAL_OPEN_PROJECT, Variant(_projects[i].path.plus_file("project.godot"))); + DisplayServer::get_singleton()->global_menu_add_item("_dock", _projects[i].project_name + " ( " + _projects[i].path + " )", callable_mp(this, &ProjectList::_global_menu_open_project), i); total_added++; } } if (total_added != 0) { - OS::get_singleton()->global_menu_add_separator("_dock"); + DisplayServer::get_singleton()->global_menu_add_separator("_dock"); + } + DisplayServer::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), callable_mp(this, &ProjectList::_global_menu_new_window)); +} + +void ProjectList::_global_menu_new_window(const Variant &p_tag) { + List<String> args; + args.push_back("-p"); + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); +} + +void ProjectList::_global_menu_open_project(const Variant &p_tag) { + int idx = (int)p_tag; + + if (idx >= 0 && idx < _projects.size()) { + String conf = _projects[idx].path.plus_file("project.godot"); + List<String> args; + args.push_back(conf); + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); } - OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant()); } void ProjectList::create_project_item_control(int p_index) { @@ -1316,13 +1348,13 @@ void ProjectList::create_project_item_control(int p_index) { Item &item = _projects.write[p_index]; ERR_FAIL_COND(item.control != NULL); // Already created - Ref<Texture2D> favorite_icon = get_icon("Favorites", "EditorIcons"); - Color font_color = get_color("font_color", "Tree"); + Ref<Texture2D> favorite_icon = get_theme_icon("Favorites", "EditorIcons"); + Color font_color = get_theme_color("font_color", "Tree"); ProjectListItemControl *hb = memnew(ProjectListItemControl); hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw), varray(hb)); hb->connect("gui_input", callable_mp(this, &ProjectList::_panel_input), varray(hb)); - hb->add_constant_override("separation", 10 * EDSCALE); + hb->add_theme_constant_override("separation", 10 * EDSCALE); hb->set_tooltip(item.description); VBoxContainer *favorite_box = memnew(VBoxContainer); @@ -1342,7 +1374,7 @@ void ProjectList::create_project_item_control(int p_index) { TextureRect *tf = memnew(TextureRect); // The project icon may not be loaded by the time the control is displayed, // so use a loading placeholder. - tf->set_texture(get_icon("ProjectIconLoading", "EditorIcons")); + tf->set_texture(get_theme_icon("ProjectIconLoading", "EditorIcons")); tf->set_v_size_flags(SIZE_SHRINK_CENTER); if (item.missing) { tf->set_modulate(Color(1, 1, 1, 0.5)); @@ -1353,25 +1385,25 @@ void ProjectList::create_project_item_control(int p_index) { VBoxContainer *vb = memnew(VBoxContainer); if (item.grayed) vb->set_modulate(Color(1, 1, 1, 0.5)); - vb->set_h_size_flags(SIZE_EXPAND_FILL); + vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(vb); Control *ec = memnew(Control); ec->set_custom_minimum_size(Size2(0, 1)); ec->set_mouse_filter(MOUSE_FILTER_PASS); vb->add_child(ec); Label *title = memnew(Label(!item.missing ? item.project_name : TTR("Missing Project"))); - title->add_font_override("font", get_font("title", "EditorFonts")); - title->add_color_override("font_color", font_color); + title->add_theme_font_override("font", get_theme_font("title", "EditorFonts")); + title->add_theme_color_override("font_color", font_color); title->set_clip_text(true); vb->add_child(title); HBoxContainer *path_hb = memnew(HBoxContainer); - path_hb->set_h_size_flags(SIZE_EXPAND_FILL); + path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); vb->add_child(path_hb); Button *show = memnew(Button); // Display a folder icon if the project directory can be opened, or a "broken file" icon if it can't - show->set_icon(get_icon(!item.missing ? "Load" : "FileBroken", "EditorIcons")); + show->set_icon(get_theme_icon(!item.missing ? "Load" : "FileBroken", "EditorIcons")); show->set_flat(true); if (!item.grayed) { // Don't make the icon less prominent if the parent is already grayed out @@ -1388,9 +1420,9 @@ void ProjectList::create_project_item_control(int p_index) { Label *fpath = memnew(Label(item.path)); path_hb->add_child(fpath); - fpath->set_h_size_flags(SIZE_EXPAND_FILL); + fpath->set_h_size_flags(Control::SIZE_EXPAND_FILL); fpath->set_modulate(Color(1, 1, 1, 0.5)); - fpath->add_color_override("font_color", font_color); + fpath->add_theme_color_override("font_color", font_color); fpath->set_clip_text(true); _scroll_children->add_child(hb); @@ -1722,12 +1754,12 @@ void ProjectList::erase_selected_projects() { void ProjectList::_panel_draw(Node *p_hb) { Control *hb = Object::cast_to<Control>(p_hb); - hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x - 10, hb->get_size().y + 1), get_color("guide_color", "Tree")); + hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x - 10, hb->get_size().y + 1), get_theme_color("guide_color", "Tree")); String key = _projects[p_hb->get_index()].project_key; if (_selected_project_keys.has(key)) { - hb->draw_style_box(get_stylebox("selected", "Tree"), Rect2(Point2(), hb->get_size() - Size2(10, 0) * EDSCALE)); + hb->draw_style_box(get_theme_stylebox("selected", "Tree"), Rect2(Point2(), hb->get_size() - Size2(10, 0) * EDSCALE)); } } @@ -1827,13 +1859,13 @@ void ProjectManager::_notification(int p_what) { case NOTIFICATION_RESIZED: { if (open_templates->is_visible()) { - open_templates->popup_centered_minsize(); + open_templates->popup_centered(); } } break; case NOTIFICATION_READY: { if (_project_list->get_project_count() == 0 && StreamPeerSSL::is_available()) - open_templates->popup_centered_minsize(); + open_templates->popup_centered(); if (_project_list->get_project_count() >= 1) { // Focus on the search box immediately to allow the user @@ -1845,7 +1877,7 @@ void ProjectManager::_notification(int p_what) { set_process_unhandled_input(is_visible_in_tree()); } break; - case NOTIFICATION_WM_QUIT_REQUEST: { + case NOTIFICATION_WM_CLOSE_REQUEST: { _dim_window(); } break; @@ -2018,30 +2050,6 @@ void ProjectManager::_confirm_update_settings() { _open_selected_projects(); } -void ProjectManager::_global_menu_action(const Variant &p_id, const Variant &p_meta) { - - int id = (int)p_id; - if (id == ProjectList::GLOBAL_NEW_WINDOW) { - List<String> args; - args.push_back("-p"); - String exec = OS::get_singleton()->get_executable_path(); - - OS::ProcessID pid = 0; - OS::get_singleton()->execute(exec, args, false, &pid); - } else if (id == ProjectList::GLOBAL_OPEN_PROJECT) { - String conf = (String)p_meta; - - if (conf != String()) { - List<String> args; - args.push_back(conf); - String exec = OS::get_singleton()->get_executable_path(); - - OS::ProcessID pid = 0; - OS::get_singleton()->execute(exec, args, false, &pid); - } - } -} - void ProjectManager::_open_selected_projects() { const Set<String> &selected_list = _project_list->get_selected_project_keys(); @@ -2053,7 +2061,7 @@ void ProjectManager::_open_selected_projects() { if (!FileAccess::exists(conf)) { dialog_error->set_text(vformat(TTR("Can't open project at '%s'."), path)); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); return; } @@ -2091,7 +2099,7 @@ void ProjectManager::_open_selected_projects_ask() { if (selected_list.size() > 1) { multi_open_ask->set_text(TTR("Are you sure to open more than one project?")); - multi_open_ask->popup_centered_minsize(); + multi_open_ask->popup_centered(); return; } @@ -2107,19 +2115,19 @@ void ProjectManager::_open_selected_projects_ask() { // Check if the config_version property was empty or 0 if (config_version == 0) { ask_update_settings->set_text(vformat(TTR("The following project settings file does not specify the version of Godot through which it was created.\n\n%s\n\nIf you proceed with opening it, it will be converted to Godot's current configuration file format.\nWarning: You won't be able to open the project with previous versions of the engine anymore."), conf)); - ask_update_settings->popup_centered_minsize(); + ask_update_settings->popup_centered(); return; } // Check if we need to convert project settings from an earlier engine version if (config_version < ProjectSettings::CONFIG_VERSION) { ask_update_settings->set_text(vformat(TTR("The following project settings file was generated by an older engine version, and needs to be converted for this version:\n\n%s\n\nDo you want to convert it?\nWarning: You won't be able to open the project with previous versions of the engine anymore."), conf)); - ask_update_settings->popup_centered_minsize(); + ask_update_settings->popup_centered(); return; } // Check if the file was generated by a newer, incompatible engine version if (config_version > ProjectSettings::CONFIG_VERSION) { dialog_error->set_text(vformat(TTR("Can't open project at '%s'.") + "\n" + TTR("The project settings were created by a newer engine version, whose settings are not compatible with this version."), project.path)); - dialog_error->popup_centered_minsize(); + dialog_error->popup_centered(); return; } @@ -2179,7 +2187,7 @@ void ProjectManager::_run_project() { if (selected_list.size() > 1) { multi_run_ask->set_text(vformat(TTR("Are you sure to run %d projects at once?"), selected_list.size())); - multi_run_ask->popup_centered_minsize(); + multi_run_ask->popup_centered(); } else { _run_project_confirm(); } @@ -2276,13 +2284,13 @@ void ProjectManager::_erase_project() { } erase_ask->set_text(confirm_message); - erase_ask->popup_centered_minsize(); + erase_ask->popup_centered(); } void ProjectManager::_erase_missing_projects() { erase_missing_ask->set_text(TTR("Remove all missing projects from the list?\nThe project folders' contents won't be modified.")); - erase_missing_ask->popup_centered_minsize(); + erase_missing_ask->popup_centered(); } void ProjectManager::_language_selected(int p_id) { @@ -2290,7 +2298,7 @@ void ProjectManager::_language_selected(int p_id) { String lang = language_btn->get_item_metadata(p_id); EditorSettings::get_singleton()->set("interface/editor/editor_language", lang); language_btn->set_text(lang); - language_btn->set_icon(get_icon("Environment", "EditorIcons")); + language_btn->set_icon(get_theme_icon("Environment", "EditorIcons")); language_restart_ask->set_text(TTR("Language changed.\nThe interface will update after restarting the editor or project manager.")); language_restart_ask->popup_centered(); @@ -2357,7 +2365,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) { multi_scan_ask->get_ok()->connect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders), varray(folders)); multi_scan_ask->set_text( vformat(TTR("Are you sure to scan %s folders for existing Godot projects?\nThis could take a while."), folders.size())); - multi_scan_ask->popup_centered_minsize(); + multi_scan_ask->popup_centered(); } else { _scan_multiple_folders(folders); } @@ -2413,8 +2421,12 @@ ProjectManager::ProjectManager() { switch (display_scale) { case 0: { // Try applying a suitable display scale automatically - const int screen = OS::get_singleton()->get_current_screen(); - editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0); + const int screen = DisplayServer::get_singleton()->window_get_current_screen(); +#ifdef OSX_ENABLED + editor_set_scale(DisplayServer::get_singleton()->screen_get_scale(screen)); +#else + editor_set_scale(DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).x > 2000 ? 2.0 : 1.0); +#endif } break; case 1: editor_set_scale(0.75); break; @@ -2430,12 +2442,12 @@ ProjectManager::ProjectManager() { } // Define a minimum window size to prevent UI elements from overlapping or being cut off - OS::get_singleton()->set_min_window_size(Size2(750, 420) * EDSCALE); + DisplayServer::get_singleton()->window_set_min_size(Size2(750, 420) * EDSCALE); #ifndef OSX_ENABLED // The macOS platform implementation uses its own hiDPI window resizing code // TODO: Resize windows on hiDPI displays on Windows and Linux and remove the line below - OS::get_singleton()->set_window_size(OS::get_singleton()->get_window_size() * MAX(1, EDSCALE)); + DisplayServer::get_singleton()->window_set_size(DisplayServer::get_singleton()->window_get_size() * MAX(1, EDSCALE)); #endif } @@ -2451,7 +2463,7 @@ ProjectManager::ProjectManager() { Panel *panel = memnew(Panel); gui_base->add_child(panel); panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); - panel->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles")); + panel->add_theme_style_override("panel", gui_base->get_theme_stylebox("Background", "EditorStyles")); VBoxContainer *vb = memnew(VBoxContainer); panel->add_child(vb); @@ -2459,10 +2471,10 @@ ProjectManager::ProjectManager() { String cp; cp += 0xA9; - OS::get_singleton()->set_window_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors"); + DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors"); Control *center_box = memnew(Control); - center_box->set_v_size_flags(SIZE_EXPAND_FILL); + center_box->set_v_size_flags(Control::SIZE_EXPAND_FILL); vb->add_child(center_box); tabs = memnew(TabContainer); @@ -2479,7 +2491,7 @@ ProjectManager::ProjectManager() { VBoxContainer *search_tree_vb = memnew(VBoxContainer); tree_hb->add_child(search_tree_vb); - search_tree_vb->set_h_size_flags(SIZE_EXPAND_FILL); + search_tree_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); HBoxContainer *sort_filters = memnew(HBoxContainer); Label *sort_label = memnew(Label); @@ -2511,9 +2523,9 @@ ProjectManager::ProjectManager() { search_tree_vb->add_child(sort_filters); PanelContainer *pc = memnew(PanelContainer); - pc->add_style_override("panel", gui_base->get_stylebox("bg", "Tree")); + pc->add_theme_style_override("panel", gui_base->get_theme_stylebox("bg", "Tree")); search_tree_vb->add_child(pc); - pc->set_v_size_flags(SIZE_EXPAND_FILL); + pc->set_v_size_flags(Control::SIZE_EXPAND_FILL); _project_list = memnew(ProjectList); _project_list->connect(ProjectList::SIGNAL_SELECTION_CHANGED, callable_mp(this, &ProjectManager::_update_project_buttons)); @@ -2547,7 +2559,7 @@ ProjectManager::ProjectManager() { scan_dir = memnew(FileDialog); scan_dir->set_access(FileDialog::ACCESS_FILESYSTEM); - scan_dir->set_mode(FileDialog::MODE_OPEN_DIR); + scan_dir->set_file_mode(FileDialog::FILE_MODE_OPEN_DIR); scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden scan_dir->set_current_dir(EditorSettings::get_singleton()->get("filesystem/directories/default_project_path")); gui_base->add_child(scan_dir); @@ -2631,7 +2643,7 @@ ProjectManager::ProjectManager() { language_btn->set_text(lang); } } - language_btn->set_icon(get_icon("Environment", "EditorIcons")); + language_btn->set_icon(get_theme_icon("Environment", "EditorIcons")); settings_hb->add_child(language_btn); language_btn->connect("item_selected", callable_mp(this, &ProjectManager::_language_selected)); @@ -2689,8 +2701,7 @@ ProjectManager::ProjectManager() { _scan_begin(EditorSettings::get_singleton()->get("filesystem/directories/autoscan_project_path")); } - SceneTree::get_singleton()->connect("files_dropped", callable_mp(this, &ProjectManager::_files_dropped)); - SceneTree::get_singleton()->connect("global_menu_action", callable_mp(this, &ProjectManager::_global_menu_action)); + SceneTree::get_singleton()->get_root()->connect("files_dropped", callable_mp(this, &ProjectManager::_files_dropped)); run_error_diag = memnew(AcceptDialog); gui_base->add_child(run_error_diag); @@ -2748,7 +2759,7 @@ void ProjectListFilter::_filter_option_selected(int p_idx) { void ProjectListFilter::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE && has_search_box) { - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); } } @@ -2769,7 +2780,7 @@ void ProjectListFilter::add_search_box() { search_box = memnew(LineEdit); search_box->set_placeholder(TTR("Search")); search_box->connect("text_changed", callable_mp(this, &ProjectListFilter::_search_text_changed)); - search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); add_child(search_box); has_search_box = true; diff --git a/editor/project_manager.h b/editor/project_manager.h index 8b9c769c59..6385000821 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -97,7 +97,6 @@ class ProjectManager : public Control { void _restart_confirm(); void _exit_dialog(); void _scan_begin(const String &p_base); - void _global_menu_action(const Variant &p_id, const Variant &p_meta); void _confirm_update_settings(); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 4fb61929a3..dfecadeda5 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -31,7 +31,7 @@ #include "project_settings_editor.h" #include "core/global_constants.h" -#include "core/input_map.h" +#include "core/input/input_map.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "core/translation.h" @@ -80,7 +80,7 @@ void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) { const Ref<InputEventKey> k = p_event; - if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) { + if (k.is_valid() && k->is_pressed()) { if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) { if (search_button->is_pressed()) { @@ -91,7 +91,7 @@ void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) { search_button->set_pressed(true); } - accept_event(); + set_input_as_handled(); } } } @@ -99,22 +99,28 @@ void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) { void ProjectSettingsEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", Rect2(get_position(), get_size())); + set_process_unhandled_input(false); + } + } break; case NOTIFICATION_ENTER_TREE: { globals_editor->edit(ProjectSettings::get_singleton()); - search_button->set_icon(get_icon("Search", "EditorIcons")); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_button->set_icon(input_editor->get_theme_icon("Search", "EditorIcons")); + search_box->set_right_icon(input_editor->get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); - action_add_error->add_color_override("font_color", get_color("error_color", "Editor")); + action_add_error->add_theme_color_override("font_color", input_editor->get_theme_color("error_color", "Editor")); translation_list->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_delete)); _update_actions(); - popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key"), INPUT_KEY); //"Key " - because the word 'key' has already been used as a key animation - popup_add->add_icon_item(get_icon("KeyboardPhysical", "EditorIcons"), TTR("Physical Key"), INPUT_KEY_PHYSICAL); - popup_add->add_icon_item(get_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), INPUT_JOY_BUTTON); - popup_add->add_icon_item(get_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), INPUT_JOY_MOTION); - popup_add->add_icon_item(get_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), INPUT_MOUSE_BUTTON); + popup_add->add_icon_item(input_editor->get_theme_icon("Keyboard", "EditorIcons"), TTR("Key"), INPUT_KEY); + popup_add->add_icon_item(input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons"), TTR("Physical Key"), INPUT_KEY_PHYSICAL); + popup_add->add_icon_item(input_editor->get_theme_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), INPUT_JOY_BUTTON); + popup_add->add_icon_item(input_editor->get_theme_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), INPUT_JOY_MOTION); + popup_add->add_icon_item(input_editor->get_theme_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), INPUT_MOUSE_BUTTON); List<String> tfn; ResourceLoader::get_recognized_extensions_for_type("Translation", &tfn); @@ -131,26 +137,22 @@ void ProjectSettingsEditor::_notification(int p_what) { translation_res_option_file_open->add_filter("*." + E->get()); } - restart_close_button->set_icon(get_icon("Close", "EditorIcons")); - restart_container->add_style_override("panel", get_stylebox("bg", "Tree")); - restart_icon->set_texture(get_icon("StatusWarning", "EditorIcons")); - restart_label->add_color_override("font_color", get_color("warning_color", "Editor")); + restart_close_button->set_icon(input_editor->get_theme_icon("Close", "EditorIcons")); + restart_container->add_theme_style_override("panel", input_editor->get_theme_stylebox("bg", "Tree")); + restart_icon->set_texture(input_editor->get_theme_icon("StatusWarning", "EditorIcons")); + restart_label->add_theme_color_override("font_color", input_editor->get_theme_color("warning_color", "Editor")); } break; - case NOTIFICATION_POPUP_HIDE: { - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "project_settings", get_rect()); - set_process_unhandled_input(false); - } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - search_button->set_icon(get_icon("Search", "EditorIcons")); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_button->set_icon(input_editor->get_theme_icon("Search", "EditorIcons")); + search_box->set_right_icon(input_editor->get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); - action_add_error->add_color_override("font_color", get_color("error_color", "Editor")); - popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY), get_icon("Keyboard", "EditorIcons")); - popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY_PHYSICAL), get_icon("KeyboardPhysical", "EditorIcons")); - popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_BUTTON), get_icon("JoyButton", "EditorIcons")); - popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_MOTION), get_icon("JoyAxis", "EditorIcons")); - popup_add->set_item_icon(popup_add->get_item_index(INPUT_MOUSE_BUTTON), get_icon("Mouse", "EditorIcons")); + action_add_error->add_theme_color_override("font_color", input_editor->get_theme_color("error_color", "Editor")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY), input_editor->get_theme_icon("Keyboard", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY_PHYSICAL), input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_BUTTON), input_editor->get_theme_icon("JoyButton", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_MOTION), input_editor->get_theme_icon("JoyAxis", "EditorIcons")); + popup_add->set_item_icon(popup_add->get_item_index(INPUT_MOUSE_BUTTON), input_editor->get_theme_icon("Mouse", "EditorIcons")); _update_actions(); } break; } @@ -462,7 +464,7 @@ void ProjectSettingsEditor::_wait_for_key(const Ref<InputEvent> &p_event) { press_a_key_label->set_text(str); press_a_key->get_ok()->set_disabled(false); - press_a_key->accept_event(); + press_a_key->set_input_as_handled(); } } @@ -479,7 +481,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even press_a_key->get_ok()->set_disabled(true); last_wait_for_key = Ref<InputEvent>(); press_a_key->popup_centered(Size2(250, 80) * EDSCALE); - press_a_key->grab_focus(); + //press_a_key->grab_focus(); } break; case INPUT_KEY_PHYSICAL: { @@ -505,7 +507,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even device_index->add_item(TTR("Wheel Right Button")); device_index->add_item(TTR("X Button 1")); device_index->add_item(TTR("X Button 2")); - device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE); + device_input->popup_centered(Size2(350, 95) * EDSCALE); Ref<InputEventMouseButton> mb = p_exiting_event; if (mb.is_valid()) { @@ -527,7 +529,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even String desc = _axis_names[i]; device_index->add_item(TTR("Axis") + " " + itos(i / 2) + " " + ((i & 1) ? "+" : "-") + desc); } - device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE); + device_input->popup_centered(Size2(350, 95) * EDSCALE); Ref<InputEventJoypadMotion> jm = p_exiting_event; if (jm.is_valid()) { @@ -549,7 +551,7 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even device_index->add_item(itos(i) + ": " + String(_button_names[i])); } - device_input->popup_centered_minsize(Size2(350, 95) * EDSCALE); + device_input->popup_centered(Size2(350, 95) * EDSCALE); Ref<InputEventJoypadButton> jb = p_exiting_event; if (jb.is_valid()) { @@ -738,7 +740,7 @@ void ProjectSettingsEditor::_update_actions() { TreeItem *item = input_editor->create_item(root); item->set_text(0, name); - item->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + item->set_custom_bg_color(0, input_editor->get_theme_color("prop_subsection", "Editor")); if (collapsed.has(name)) item->set_collapsed(collapsed[name]); @@ -746,12 +748,12 @@ void ProjectSettingsEditor::_update_actions() { item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE); item->set_range_config(1, 0.0, 1.0, 0.01); item->set_range(1, action["deadzone"]); - item->set_custom_bg_color(1, get_color("prop_subsection", "Editor")); + item->set_custom_bg_color(1, input_editor->get_theme_color("prop_subsection", "Editor")); const bool is_builtin_input = ProjectSettings::get_singleton()->get_input_presets().find(pi.name) != NULL; const String tooltip = is_builtin_input ? TTR("Built-in actions can't be removed as they're used for UI navigation.") : TTR("Remove"); - item->add_button(2, get_icon("Add", "EditorIcons"), 1, false, TTR("Add Event")); - item->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, tooltip); + item->add_button(2, input_editor->get_theme_icon("Add", "EditorIcons"), 1, false, TTR("Add Event")); + item->add_button(2, input_editor->get_theme_icon("Remove", "EditorIcons"), 2, false, tooltip); if (is_builtin_input) { // Built-in action (like `ui_up`). Make the action not removable, @@ -778,9 +780,9 @@ void ProjectSettingsEditor::_update_actions() { action2->set_text(0, str); if ((k->get_keycode() != 0)) { - action2->set_icon(0, get_icon("Keyboard", "EditorIcons")); + action2->set_icon(0, input_editor->get_theme_icon("Keyboard", "EditorIcons")); } else { - action2->set_icon(0, get_icon("KeyboardPhysical", "EditorIcons")); + action2->set_icon(0, input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons")); } } @@ -794,7 +796,7 @@ void ProjectSettingsEditor::_update_actions() { } action2->set_text(0, str); - action2->set_icon(0, get_icon("JoyButton", "EditorIcons")); + action2->set_icon(0, input_editor->get_theme_icon("JoyButton", "EditorIcons")); } Ref<InputEventMouseButton> mb = event; @@ -811,7 +813,7 @@ void ProjectSettingsEditor::_update_actions() { } action2->set_text(0, str); - action2->set_icon(0, get_icon("Mouse", "EditorIcons")); + action2->set_icon(0, input_editor->get_theme_icon("Mouse", "EditorIcons")); } Ref<InputEventJoypadMotion> jm = event; @@ -823,13 +825,13 @@ void ProjectSettingsEditor::_update_actions() { String desc = _axis_names[n]; String str = _get_device_string(jm->get_device()) + ", " + TTR("Axis") + " " + itos(ax) + " " + (jm->get_axis_value() < 0 ? "-" : "+") + desc; action2->set_text(0, str); - action2->set_icon(0, get_icon("JoyAxis", "EditorIcons")); + action2->set_icon(0, input_editor->get_theme_icon("JoyAxis", "EditorIcons")); } action2->set_metadata(0, i); action2->set_meta("__input", event); - action2->add_button(2, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); - action2->add_button(2, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); + action2->add_button(2, input_editor->get_theme_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); + action2->add_button(2, input_editor->get_theme_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); // Fade out the individual event buttons slightly to make the // Add/Remove buttons stand out more. action2->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1112,7 +1114,7 @@ Variant ProjectSettingsEditor::get_drag_data_fw(const Point2 &p_point, Control * hb->set_modulate(Color(1, 1, 1, 1.0f)); hb->add_child(label); vb->add_child(hb); - set_drag_preview(vb); + input_editor->set_drag_preview(vb); Dictionary drag_data; drag_data["type"] = "nodes"; @@ -1547,7 +1549,7 @@ void ProjectSettingsEditor::_update_translations() { t->set_text(0, translations[i].replace_first("res://", "")); t->set_tooltip(0, translations[i]); t->set_metadata(0, i); - t->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); + t->add_button(0, input_editor->get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); } } @@ -1670,7 +1672,7 @@ void ProjectSettingsEditor::_update_translations() { t->set_text(0, keys[i].replace_first("res://", "")); t->set_tooltip(0, keys[i]); t->set_metadata(0, keys[i]); - t->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); + t->add_button(0, input_editor->get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); if (keys[i] == remap_selected) { t->select(0); translation_res_option_add_button->set_disabled(false); @@ -1688,7 +1690,7 @@ void ProjectSettingsEditor::_update_translations() { t2->set_text(0, path.replace_first("res://", "")); t2->set_tooltip(0, path); t2->set_metadata(0, j); - t2->add_button(0, get_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); + t2->add_button(0, input_editor->get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE); t2->set_text(1, langnames); t2->set_editable(1, true); @@ -1774,7 +1776,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { singleton = this; set_title(TTR("Project Settings (project.godot)")); - set_resizable(true); + undo_redo = &p_data->get_undo_redo(); data = p_data; @@ -1873,7 +1875,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { add_prop_bar->add_child(popup_copy_to_feature); popup_copy_to_feature->get_popup()->connect("id_pressed", callable_mp(this, &ProjectSettingsEditor::_copy_to_platform)); - popup_copy_to_feature->get_popup()->connect("about_to_show", callable_mp(this, &ProjectSettingsEditor::_copy_to_platform_about_to_show)); + popup_copy_to_feature->get_popup()->connect("about_to_popup", callable_mp(this, &ProjectSettingsEditor::_copy_to_platform_about_to_show)); get_ok()->set_text(TTR("Close")); set_hide_on_ok(true); @@ -1883,7 +1885,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { HBoxContainer *restart_hb = memnew(HBoxContainer); restart_container->add_child(restart_hb); restart_icon = memnew(TextureRect); - restart_icon->set_v_size_flags(SIZE_SHRINK_CENTER); + restart_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); restart_hb->add_child(restart_icon); restart_label = memnew(Label); restart_label->set_text(TTR("The editor must be restarted for changes to take effect.")); @@ -1907,10 +1909,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { VBoxContainer *vbc = memnew(VBoxContainer); input_base->add_child(vbc); - vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0); - vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0); - vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0); - vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0); + vbc->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 0); + vbc->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, 0); + vbc->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 0); + vbc->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, 0); hbc = memnew(HBoxContainer); vbc->add_child(hbc); @@ -1920,7 +1922,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { l->set_text(TTR("Action:")); action_name = memnew(LineEdit); - action_name->set_h_size_flags(SIZE_EXPAND_FILL); + action_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->add_child(action_name); action_name->connect("text_entered", callable_mp(this, &ProjectSettingsEditor::_action_adds)); action_name->connect("text_changed", callable_mp(this, &ProjectSettingsEditor::_action_check)); @@ -1938,7 +1940,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { input_editor = memnew(Tree); vbc->add_child(input_editor); - input_editor->set_v_size_flags(SIZE_EXPAND_FILL); + input_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); input_editor->set_columns(3); input_editor->set_column_titles_visible(true); input_editor->set_column_title(0, TTR("Action")); @@ -1951,7 +1953,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { input_editor->connect("item_activated", callable_mp(this, &ProjectSettingsEditor::_action_activated)); input_editor->connect("cell_selected", callable_mp(this, &ProjectSettingsEditor::_action_selected)); input_editor->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_action_button_pressed)); - input_editor->set_drag_forwarding(this); +#ifndef _MSC_VER +#warning need to make drag data forwarding to non controls happen +#endif + //input_editor->set_drag_forwarding(this); popup_add = memnew(PopupMenu); add_child(popup_add); @@ -1960,7 +1965,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { press_a_key_physical = false; press_a_key = memnew(ConfirmationDialog); - press_a_key->set_focus_mode(FOCUS_ALL); + //press_a_key->set_focus_mode(Control::FOCUS_ALL); add_child(press_a_key); l = memnew(Label); @@ -1968,11 +1973,11 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { l->set_anchors_and_margins_preset(Control::PRESET_WIDE); l->set_align(Label::ALIGN_CENTER); l->set_margin(MARGIN_TOP, 20); - l->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 30); + l->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_BEGIN, 30); press_a_key->get_ok()->set_disabled(true); press_a_key_label = l; press_a_key->add_child(l); - press_a_key->connect("gui_input", callable_mp(this, &ProjectSettingsEditor::_wait_for_key)); + press_a_key->connect("window_input", callable_mp(this, &ProjectSettingsEditor::_wait_for_key)); press_a_key->connect("confirmed", callable_mp(this, &ProjectSettingsEditor::_press_a_key_confirm)); device_input = memnew(ConfirmationDialog); @@ -1998,7 +2003,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { VBoxContainer *vbc_right = memnew(VBoxContainer); hbc->add_child(vbc_right); - vbc_right->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_right->set_h_size_flags(Control::SIZE_EXPAND_FILL); l = memnew(Label); l->set_text(TTR("Index:")); @@ -2035,14 +2040,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { thb->add_child(addtr); VBoxContainer *tmc = memnew(VBoxContainer); tvb->add_child(tmc); - tmc->set_v_size_flags(SIZE_EXPAND_FILL); + tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); translation_list = memnew(Tree); - translation_list->set_v_size_flags(SIZE_EXPAND_FILL); + translation_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); tmc->add_child(translation_list); translation_file_open = memnew(EditorFileDialog); add_child(translation_file_open); - translation_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE); + translation_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); translation_file_open->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_add)); } @@ -2059,16 +2064,16 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { thb->add_child(addtr); VBoxContainer *tmc = memnew(VBoxContainer); tvb->add_child(tmc); - tmc->set_v_size_flags(SIZE_EXPAND_FILL); + tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); translation_remap = memnew(Tree); - translation_remap->set_v_size_flags(SIZE_EXPAND_FILL); + translation_remap->set_v_size_flags(Control::SIZE_EXPAND_FILL); translation_remap->connect("cell_selected", callable_mp(this, &ProjectSettingsEditor::_translation_res_select)); tmc->add_child(translation_remap); translation_remap->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_res_delete)); translation_res_file_open = memnew(EditorFileDialog); add_child(translation_res_file_open); - translation_res_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE); + translation_res_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); translation_res_file_open->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_res_add)); thb = memnew(HBoxContainer); @@ -2081,9 +2086,9 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { thb->add_child(addtr); tmc = memnew(VBoxContainer); tvb->add_child(tmc); - tmc->set_v_size_flags(SIZE_EXPAND_FILL); + tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); translation_remap_options = memnew(Tree); - translation_remap_options->set_v_size_flags(SIZE_EXPAND_FILL); + translation_remap_options->set_v_size_flags(Control::SIZE_EXPAND_FILL); tmc->add_child(translation_remap_options); translation_remap_options->set_columns(2); @@ -2098,7 +2103,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { translation_res_option_file_open = memnew(EditorFileDialog); add_child(translation_res_option_file_open); - translation_res_option_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE); + translation_res_option_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); translation_res_option_file_open->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_res_option_add)); } @@ -2107,7 +2112,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { translations->add_child(tvb); tvb->set_name(TTR("Locales Filter")); VBoxContainer *tmc = memnew(VBoxContainer); - tmc->set_v_size_flags(SIZE_EXPAND_FILL); + tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); tvb->add_child(tmc); translation_locale_filter_mode = memnew(OptionButton); @@ -2118,7 +2123,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { translation_locale_filter_mode->connect("item_selected", callable_mp(this, &ProjectSettingsEditor::_translation_filter_mode_changed)); translation_filter = memnew(Tree); - translation_filter->set_v_size_flags(SIZE_EXPAND_FILL); + translation_filter->set_v_size_flags(Control::SIZE_EXPAND_FILL); translation_filter->set_columns(1); tmc->add_child(memnew(Label(TTR("Locales:")))); tmc->add_child(translation_filter); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 6913b0253b..41e15f47cc 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -31,11 +31,11 @@ #include "property_editor.h" #include "core/class_db.h" +#include "core/input/input_filter.h" #include "core/io/image_loader.h" #include "core/io/marshalls.h" #include "core/io/resource_loader.h" #include "core/math/expression.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/pair.h" #include "core/print_string.h" @@ -53,7 +53,7 @@ #include "editor/multi_node_edit.h" #include "editor/property_selector.h" #include "scene/gui/label.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/font.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" @@ -103,12 +103,7 @@ Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_res void CustomPropertyEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_DRAW) { - - RID ci = get_canvas_item(); - get_stylebox("panel", "PopupMenu")->draw(ci, Rect2(Point2(), get_size())); - } - if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) { + if (p_what == NOTIFICATION_WM_CLOSE_REQUEST) { hide(); } } @@ -151,7 +146,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { switch (p_which) { case OBJ_MENU_LOAD: { - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); List<String> extensions; @@ -493,14 +488,14 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_EXP_EASING) { - easing_draw->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5 * EDSCALE); - easing_draw->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -5 * EDSCALE); - easing_draw->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 5 * EDSCALE); - easing_draw->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -30 * EDSCALE); - type_button->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 3 * EDSCALE); - type_button->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -3 * EDSCALE); - type_button->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -25 * EDSCALE); - type_button->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -7 * EDSCALE); + easing_draw->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 5 * EDSCALE); + easing_draw->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -5 * EDSCALE); + easing_draw->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, 5 * EDSCALE); + easing_draw->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -30 * EDSCALE); + type_button->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, 3 * EDSCALE); + type_button->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -3 * EDSCALE); + type_button->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_END, -25 * EDSCALE); + type_button->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -7 * EDSCALE); type_button->set_text(TTR("Preset...")); type_button->get_popup()->clear(); type_button->get_popup()->add_item(TTR("Linear"), EASING_LINEAR); @@ -573,13 +568,13 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: text_edit->set_text(v); text_edit->deselect(); - int button_margin = get_constant("button_margin", "Dialogs"); - int margin = get_constant("margin", "Dialogs"); + int button_margin = text_edit->get_theme_constant("button_margin", "Dialogs"); + int margin = text_edit->get_theme_constant("margin", "Dialogs"); - action_buttons[0]->set_anchor(MARGIN_LEFT, ANCHOR_END); - action_buttons[0]->set_anchor(MARGIN_TOP, ANCHOR_END); - action_buttons[0]->set_anchor(MARGIN_RIGHT, ANCHOR_END); - action_buttons[0]->set_anchor(MARGIN_BOTTOM, ANCHOR_END); + action_buttons[0]->set_anchor(MARGIN_LEFT, Control::ANCHOR_END); + action_buttons[0]->set_anchor(MARGIN_TOP, Control::ANCHOR_END); + action_buttons[0]->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END); + action_buttons[0]->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END); action_buttons[0]->set_begin(Point2(-70 * EDSCALE, -button_margin + 5 * EDSCALE)); action_buttons[0]->set_end(Point2(-margin, -margin)); action_buttons[0]->set_text(TTR("Close")); @@ -900,7 +895,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: break; if (p_name == "script" && hint_text == "Script" && Object::cast_to<Node>(owner)) { - menu->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT); + menu->add_item(TTR("New Script"), OBJ_MENU_NEW_SCRIPT); menu->add_separator(); } else if (hint_text != "") { int idx = 0; @@ -953,17 +948,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: int id = TYPE_BASE_ID + idx; - if (!icon.is_valid() && has_icon(t, "EditorIcons")) { - icon = get_icon(t, "EditorIcons"); - } - - if (icon.is_valid()) { - - menu->add_icon_item(icon, vformat(TTR("New %s"), t), id); - } else { - - menu->add_item(vformat(TTR("New %s"), t), id); - } + menu->add_item(vformat(TTR("New %s"), t), id); idx++; } @@ -973,13 +958,14 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: menu->add_separator(); } - menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); + menu->add_item(TTR("Load"), OBJ_MENU_LOAD); if (!RES(v).is_null()) { - menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); - menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); - menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); + menu->add_item(TTR("Edit"), OBJ_MENU_EDIT); + menu->add_item(TTR("Clear"), OBJ_MENU_CLEAR); + menu->add_item(TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); + RES r = v; if (r.is_valid() && r->get_path().is_resource_file()) { menu->add_separator(); @@ -1022,16 +1008,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } for (int i = 0; i < conversions.size(); i++) { String what = conversions[i]->converts_to(); - Ref<Texture2D> icon; - if (has_icon(what, "EditorIcons")) { - - icon = get_icon(what, "EditorIcons"); - } else { - - icon = get_icon(what, "Resource"); - } - - menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); + menu->add_item(vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); } } @@ -1105,7 +1082,7 @@ void CustomPropertyEditor::_file_selected(String p_file) { RES res = ResourceLoader::load(p_file, type); if (res.is_null()) { error->set_text(TTR("Error loading file: Not a resource!")); - error->popup_centered_minsize(); + error->popup_centered(); break; } v = res; @@ -1282,7 +1259,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { else file->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file->clear_filters(); file->clear_filters(); @@ -1316,7 +1293,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { file->set_access(EditorFileDialog::ACCESS_RESOURCES); else file->set_access(EditorFileDialog::ACCESS_FILESYSTEM); - file->set_mode(EditorFileDialog::MODE_OPEN_DIR); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); file->clear_filters(); file->popup_centered_ratio(); } else { @@ -1385,7 +1362,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) { } else if (p_which == 1) { file->set_access(EditorFileDialog::ACCESS_RESOURCES); - file->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); List<String> extensions; String type = (hint == PROPERTY_HINT_RESOURCE_TYPE) ? hint_text : String(); @@ -1500,7 +1477,7 @@ void CustomPropertyEditor::_draw_easing() { Size2 s = easing_draw->get_size(); Rect2 r(Point2(), s); r = r.grow(3); - get_stylebox("normal", "LineEdit")->draw(ci, r); + easing_draw->get_theme_stylebox("normal", "LineEdit")->draw(ci, r); int points = 48; @@ -1508,8 +1485,8 @@ void CustomPropertyEditor::_draw_easing() { float exp = v; bool flip = hint_text == "attenuation"; - Ref<Font> f = get_font("font", "Label"); - Color color = get_color("font_color", "Label"); + Ref<Font> f = easing_draw->get_theme_font("font", "Label"); + Color color = easing_draw->get_theme_color("font_color", "Label"); for (int i = 1; i <= points; i++) { @@ -1743,7 +1720,7 @@ real_t CustomPropertyEditor::_parse_real_expression(String text) { void CustomPropertyEditor::_emit_changed_whole_or_field() { - if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { emit_signal("variant_changed"); } else { emit_signal("variant_field_changed", field_names[focused_value_editor]); @@ -1805,7 +1782,7 @@ void CustomPropertyEditor::_focus_exit() { void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) { - Ref<StyleBox> sb = get_stylebox("panel"); + Ref<StyleBox> sb = action_buttons[0]->get_theme_stylebox("panel"); int margin_top = sb->get_margin(MARGIN_TOP); int margin_left = sb->get_margin(MARGIN_LEFT); int margin_bottom = sb->get_margin(MARGIN_BOTTOM); @@ -1921,7 +1898,7 @@ CustomPropertyEditor::CustomPropertyEditor() { checks20[i] = memnew(CheckBox); checks20[i]->set_toggle_mode(true); - checks20[i]->set_focus_mode(FOCUS_NONE); + checks20[i]->set_focus_mode(Control::FOCUS_NONE); checks20gc->add_child(checks20[i]); checks20[i]->hide(); checks20[i]->connect("pressed", callable_mp(this, &CustomPropertyEditor::_action_pressed), make_binds(i)); @@ -1949,7 +1926,6 @@ CustomPropertyEditor::CustomPropertyEditor() { color_picker = NULL; - set_as_toplevel(true); file = memnew(EditorFileDialog); add_child(file); file->hide(); @@ -1983,7 +1959,7 @@ CustomPropertyEditor::CustomPropertyEditor() { type_button->get_popup()->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_type_create_selected)); menu = memnew(PopupMenu); - menu->set_pass_on_modal_close_click(false); + // menu->set_pass_on_modal_close_click(false); add_child(menu); menu->connect("id_pressed", callable_mp(this, &CustomPropertyEditor::_menu_option)); diff --git a/editor/property_editor.h b/editor/property_editor.h index bc2a222714..45466eaa42 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -63,9 +63,9 @@ public: virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const; }; -class CustomPropertyEditor : public Popup { +class CustomPropertyEditor : public PopupPanel { - GDCLASS(CustomPropertyEditor, Popup); + GDCLASS(CustomPropertyEditor, PopupPanel); enum { MAX_VALUE_EDITORS = 12, diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index ede7b860d6..54b94ebb95 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -121,33 +121,33 @@ void PropertySelector::_update_search() { bool found = false; Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("Path", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("Object", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + search_options->get_theme_icon("Variant", "EditorIcons"), + search_options->get_theme_icon("bool", "EditorIcons"), + search_options->get_theme_icon("int", "EditorIcons"), + search_options->get_theme_icon("float", "EditorIcons"), + search_options->get_theme_icon("String", "EditorIcons"), + search_options->get_theme_icon("Vector2", "EditorIcons"), + search_options->get_theme_icon("Rect2", "EditorIcons"), + search_options->get_theme_icon("Vector3", "EditorIcons"), + search_options->get_theme_icon("Transform2D", "EditorIcons"), + search_options->get_theme_icon("Plane", "EditorIcons"), + search_options->get_theme_icon("Quat", "EditorIcons"), + search_options->get_theme_icon("AABB", "EditorIcons"), + search_options->get_theme_icon("Basis", "EditorIcons"), + search_options->get_theme_icon("Transform", "EditorIcons"), + search_options->get_theme_icon("Color", "EditorIcons"), + search_options->get_theme_icon("Path", "EditorIcons"), + search_options->get_theme_icon("RID", "EditorIcons"), + search_options->get_theme_icon("Object", "EditorIcons"), + search_options->get_theme_icon("Dictionary", "EditorIcons"), + search_options->get_theme_icon("Array", "EditorIcons"), + search_options->get_theme_icon("PackedByteArray", "EditorIcons"), + search_options->get_theme_icon("PackedInt32Array", "EditorIcons"), + search_options->get_theme_icon("PackedFloat32Array", "EditorIcons"), + search_options->get_theme_icon("PackedStringArray", "EditorIcons"), + search_options->get_theme_icon("PackedVector2Array", "EditorIcons"), + search_options->get_theme_icon("PackedVector3Array", "EditorIcons"), + search_options->get_theme_icon("PackedColorArray", "EditorIcons") }; for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { @@ -161,7 +161,7 @@ void PropertySelector::_update_search() { Ref<Texture2D> icon; if (E->get().name == "Script Variables") { - icon = get_icon("Script", "EditorIcons"); + icon = search_options->get_theme_icon("Script", "EditorIcons"); } else { icon = EditorNode::get_singleton()->get_class_icon(E->get().name); } @@ -238,7 +238,7 @@ void PropertySelector::_update_search() { script_methods = false; String rep = E->get().name.replace("*", ""); if (E->get().name == "*Script Methods") { - icon = get_icon("Script", "EditorIcons"); + icon = search_options->get_theme_icon("Script", "EditorIcons"); script_methods = true; } else { icon = EditorNode::get_singleton()->get_class_icon(rep); @@ -390,7 +390,7 @@ void PropertySelector::_item_selected() { } void PropertySelector::_hide_requested() { - _closed(); // From WindowDialog. + _cancel_pressed(); // From AcceptDialog. } void PropertySelector::_notification(int p_what) { diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index 95277e72d7..58bb061b58 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -142,7 +142,7 @@ void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<Str if (search_text.is_subsequence_ofi(path)) { Pair<String, Ref<Texture2D>> pair; pair.first = path; - pair.second = get_icon("folder", "FileDialog"); + pair.second = search_options->get_theme_icon("folder", "FileDialog"); if (search_text != String() && list.size() > 0) { @@ -171,7 +171,7 @@ void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<Str if (ClassDB::is_parent_class(efsd->get_file_type(i), base_type) && (search_text.is_subsequence_ofi(file))) { Pair<String, Ref<Texture2D>> pair; pair.first = file; - pair.second = get_icon((has_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei); + pair.second = search_options->get_theme_icon((search_options->has_theme_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei); list.push_back(pair); } } @@ -253,6 +253,11 @@ void EditorQuickOpen::_confirmed() { hide(); } +void EditorQuickOpen::_theme_changed() { + + search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons")); +} + void EditorQuickOpen::_notification(int p_what) { switch (p_what) { @@ -262,9 +267,6 @@ void EditorQuickOpen::_notification(int p_what) { search_box->set_clear_button_enabled(true); [[fallthrough]]; } - case NOTIFICATION_THEME_CHANGED: { - search_box->set_right_icon(get_icon("Search", "EditorIcons")); - } break; case NOTIFICATION_EXIT_TREE: { disconnect("confirmed", callable_mp(this, &EditorQuickOpen::_confirmed)); } break; @@ -284,6 +286,8 @@ void EditorQuickOpen::_bind_methods() { EditorQuickOpen::EditorQuickOpen() { VBoxContainer *vbc = memnew(VBoxContainer); + vbc->connect("theme_changed", callable_mp(this, &EditorQuickOpen::_theme_changed)); + add_child(vbc); search_box = memnew(LineEdit); vbc->add_margin_child(TTR("Search:"), search_box); @@ -298,7 +302,7 @@ EditorQuickOpen::EditorQuickOpen() { search_options->connect("item_activated", callable_mp(this, &EditorQuickOpen::_confirmed)); search_options->set_hide_root(true); search_options->set_hide_folding(true); - search_options->add_constant_override("draw_guides", 1); + search_options->add_theme_constant_override("draw_guides", 1); ei = "EditorIcons"; ot = "Object"; add_directories = false; diff --git a/editor/quick_open.h b/editor/quick_open.h index 722bad3429..c0e2cb85d8 100644 --- a/editor/quick_open.h +++ b/editor/quick_open.h @@ -56,6 +56,8 @@ class EditorQuickOpen : public ConfirmationDialog { void _confirmed(); void _text_changed(const String &p_newtext); + void _theme_changed(); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 2d7b7027c8..c14462f07d 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -56,7 +56,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und GridContainer *grd_main = memnew(GridContainer); grd_main->set_columns(2); - grd_main->set_v_size_flags(SIZE_EXPAND_FILL); + grd_main->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbc->add_child(grd_main); // ---- 1st & 2nd row @@ -67,7 +67,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und lne_search = memnew(LineEdit); lne_search->set_placeholder(TTR("Search")); lne_search->set_name("lne_search"); - lne_search->set_h_size_flags(SIZE_EXPAND_FILL); + lne_search->set_h_size_flags(Control::SIZE_EXPAND_FILL); Label *lbl_replace = memnew(Label); lbl_replace->set_text(TTR("Replace")); @@ -75,7 +75,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und lne_replace = memnew(LineEdit); lne_replace->set_placeholder(TTR("Replace")); lne_replace->set_name("lne_replace"); - lne_replace->set_h_size_flags(SIZE_EXPAND_FILL); + lne_replace->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_main->add_child(lbl_search); grd_main->add_child(lbl_replace); @@ -90,7 +90,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und lne_prefix = memnew(LineEdit); lne_prefix->set_placeholder(TTR("Prefix")); lne_prefix->set_name("lne_prefix"); - lne_prefix->set_h_size_flags(SIZE_EXPAND_FILL); + lne_prefix->set_h_size_flags(Control::SIZE_EXPAND_FILL); Label *lbl_suffix = memnew(Label); lbl_suffix->set_text(TTR("Suffix")); @@ -98,7 +98,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und lne_suffix = memnew(LineEdit); lne_suffix->set_placeholder(TTR("Suffix")); lne_suffix->set_name("lne_suffix"); - lne_suffix->set_h_size_flags(SIZE_EXPAND_FILL); + lne_suffix->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_main->add_child(lbl_prefix); grd_main->add_child(lbl_suffix); @@ -124,7 +124,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und // ---- Tab Substitute VBoxContainer *vbc_substitute = memnew(VBoxContainer); - vbc_substitute->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_substitute->set_h_size_flags(Control::SIZE_EXPAND_FILL); vbc_substitute->set_custom_minimum_size(Size2(0, feature_min_height)); vbc_substitute->set_name(TTR("Substitute")); @@ -143,9 +143,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_name = memnew(Button); but_insert_name->set_text("NAME"); but_insert_name->set_tooltip(String("${NAME}\n") + TTR("Node name")); - but_insert_name->set_focus_mode(FOCUS_NONE); + but_insert_name->set_focus_mode(Control::FOCUS_NONE); but_insert_name->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${NAME}")); - but_insert_name->set_h_size_flags(SIZE_EXPAND_FILL); + but_insert_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_name); // Parent @@ -153,9 +153,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_parent = memnew(Button); but_insert_parent->set_text("PARENT"); but_insert_parent->set_tooltip(String("${PARENT}\n") + TTR("Node's parent name, if available")); - but_insert_parent->set_focus_mode(FOCUS_NONE); + but_insert_parent->set_focus_mode(Control::FOCUS_NONE); but_insert_parent->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${PARENT}")); - but_insert_parent->set_h_size_flags(SIZE_EXPAND_FILL); + but_insert_parent->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_parent); // Type @@ -163,9 +163,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_type = memnew(Button); but_insert_type->set_text("TYPE"); but_insert_type->set_tooltip(String("${TYPE}\n") + TTR("Node type")); - but_insert_type->set_focus_mode(FOCUS_NONE); + but_insert_type->set_focus_mode(Control::FOCUS_NONE); but_insert_type->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${TYPE}")); - but_insert_type->set_h_size_flags(SIZE_EXPAND_FILL); + but_insert_type->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_type); // Scene @@ -173,9 +173,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_scene = memnew(Button); but_insert_scene->set_text("SCENE"); but_insert_scene->set_tooltip(String("${SCENE}\n") + TTR("Current scene name")); - but_insert_scene->set_focus_mode(FOCUS_NONE); + but_insert_scene->set_focus_mode(Control::FOCUS_NONE); but_insert_scene->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${SCENE}")); - but_insert_scene->set_h_size_flags(SIZE_EXPAND_FILL); + but_insert_scene->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_scene); // Root @@ -183,9 +183,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_root = memnew(Button); but_insert_root->set_text("ROOT"); but_insert_root->set_tooltip(String("${ROOT}\n") + TTR("Root node name")); - but_insert_root->set_focus_mode(FOCUS_NONE); + but_insert_root->set_focus_mode(Control::FOCUS_NONE); but_insert_root->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${ROOT}")); - but_insert_root->set_h_size_flags(SIZE_EXPAND_FILL); + but_insert_root->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_root); // Count @@ -193,9 +193,9 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und but_insert_count = memnew(Button); but_insert_count->set_text("COUNTER"); but_insert_count->set_tooltip(String("${COUNTER}\n") + TTR("Sequential integer counter.\nCompare counter options.")); - but_insert_count->set_focus_mode(FOCUS_NONE); + but_insert_count->set_focus_mode(Control::FOCUS_NONE); but_insert_count->connect("pressed", callable_mp(this, &RenameDialog::_insert_text), make_binds("${COUNTER}")); - but_insert_count->set_h_size_flags(SIZE_EXPAND_FILL); + but_insert_count->set_h_size_flags(Control::SIZE_EXPAND_FILL); grd_substitute->add_child(but_insert_count); chk_per_level_counter = memnew(CheckBox); @@ -240,7 +240,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und // ---- Tab Process VBoxContainer *vbc_process = memnew(VBoxContainer); - vbc_process->set_h_size_flags(SIZE_EXPAND_FILL); + vbc_process->set_h_size_flags(Control::SIZE_EXPAND_FILL); vbc_process->set_name(TTR("Post-Process")); vbc_process->set_custom_minimum_size(Size2(0, feature_min_height)); tabc_features->add_child(vbc_process); @@ -291,13 +291,13 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_und lbl_preview = memnew(Label); lbl_preview->set_text(""); - lbl_preview->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); vbc->add_child(lbl_preview); // ---- Dialog related - set_custom_minimum_size(Size2(383, 0)); - set_as_toplevel(true); + set_min_size(Size2(383, 0)); + //set_as_toplevel(true); get_ok()->set_text(TTR("Rename")); Button *but_reset = add_button(TTR("Reset")); @@ -347,7 +347,7 @@ void RenameDialog::_bind_methods() { void RenameDialog::_update_substitute() { - LineEdit *focus_owner_line_edit = Object::cast_to<LineEdit>(get_focus_owner()); + LineEdit *focus_owner_line_edit = Object::cast_to<LineEdit>(scene_tree_editor->get_focus_owner()); bool is_main_field = _is_main_field(focus_owner_line_edit); but_insert_name->set_disabled(!is_main_field); @@ -358,12 +358,12 @@ void RenameDialog::_update_substitute() { but_insert_count->set_disabled(!is_main_field); // The focus mode seems to be reset when disabling/re-enabling - but_insert_name->set_focus_mode(FOCUS_NONE); - but_insert_parent->set_focus_mode(FOCUS_NONE); - but_insert_type->set_focus_mode(FOCUS_NONE); - but_insert_scene->set_focus_mode(FOCUS_NONE); - but_insert_root->set_focus_mode(FOCUS_NONE); - but_insert_count->set_focus_mode(FOCUS_NONE); + but_insert_name->set_focus_mode(Control::FOCUS_NONE); + but_insert_parent->set_focus_mode(Control::FOCUS_NONE); + but_insert_type->set_focus_mode(Control::FOCUS_NONE); + but_insert_scene->set_focus_mode(Control::FOCUS_NONE); + but_insert_root->set_focus_mode(Control::FOCUS_NONE); + but_insert_count->set_focus_mode(Control::FOCUS_NONE); } void RenameDialog::_post_popup() { @@ -401,11 +401,11 @@ void RenameDialog::_update_preview(String new_text) { if (new_name == preview_node->get_name()) { // New name is identical to the old one. Don't color it as much to avoid distracting the user. - const Color accent_color = EditorNode::get_singleton()->get_gui_base()->get_color("accent_color", "Editor"); - const Color text_color = EditorNode::get_singleton()->get_gui_base()->get_color("default_color", "RichTextLabel"); - lbl_preview->add_color_override("font_color", accent_color.linear_interpolate(text_color, 0.5)); + const Color accent_color = EditorNode::get_singleton()->get_gui_base()->get_theme_color("accent_color", "Editor"); + const Color text_color = EditorNode::get_singleton()->get_gui_base()->get_theme_color("default_color", "RichTextLabel"); + lbl_preview->add_theme_color_override("font_color", accent_color.linear_interpolate(text_color, 0.5)); } else { - lbl_preview->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("success_color", "Editor")); + lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("success_color", "Editor")); } } @@ -491,7 +491,7 @@ void RenameDialog::_error_handler(void *p_self, const char *p_func, const char * self->has_errors = true; self->lbl_preview_title->set_text(TTR("Regular Expression Error")); - self->lbl_preview->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); + self->lbl_preview->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); self->lbl_preview->set_text(vformat(TTR("At character %s"), err_str)); } @@ -652,7 +652,7 @@ bool RenameDialog::_is_main_field(LineEdit *line_edit) { void RenameDialog::_insert_text(String text) { - LineEdit *focus_owner = Object::cast_to<LineEdit>(get_focus_owner()); + LineEdit *focus_owner = Object::cast_to<LineEdit>(scene_tree_editor->get_focus_owner()); if (_is_main_field(focus_owner)) { focus_owner->selection_delete(); diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h index 537aa1703b..1cd0a2cb0f 100644 --- a/editor/rename_dialog.h +++ b/editor/rename_dialog.h @@ -103,7 +103,6 @@ class RenameDialog : public ConfirmationDialog { bool has_errors; protected: - void _notification(int p_what){}; static void _bind_methods(); virtual void _post_popup(); diff --git a/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp index 551d20eddb..b71c2bd078 100644 --- a/editor/reparent_dialog.cpp +++ b/editor/reparent_dialog.cpp @@ -45,12 +45,6 @@ void ReparentDialog::_notification(int p_what) { disconnect("confirmed", callable_mp(this, &ReparentDialog::_reparent)); } - - if (p_what == NOTIFICATION_DRAW) { - - //RID ci = get_canvas_item(); - //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size())); - } } void ReparentDialog::_cancel() { diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 7845af7f79..613ba53fed 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -30,8 +30,8 @@ #include "scene_tree_dock.h" +#include "core/input/input_filter.h" #include "core/io/resource_saver.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/project_settings.h" #include "editor/debugger/editor_debugger_node.h" @@ -44,8 +44,10 @@ #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" #include "editor/plugins/spatial_editor_plugin.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" +#include "servers/display_server.h" +#include "servers/visual_server.h" void SceneTreeDock::_nodes_drag_begin() { @@ -73,9 +75,6 @@ void SceneTreeDock::_input(Ref<InputEvent> p_event) { void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) { - if (get_viewport()->get_modal_stack_top()) - return; //ignore because of modal window - if (get_focus_owner() && get_focus_owner()->is_text_field()) return; @@ -131,7 +130,7 @@ void SceneTreeDock::instance(const String &p_file) { current_option = -1; accept->set_text(TTR("No parent to instance a child at.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; }; @@ -153,7 +152,7 @@ void SceneTreeDock::instance_scenes(const Vector<String> &p_files, Node *p_paren if (!parent || !edited_scene) { accept->set_text(TTR("No parent to instance the scenes at.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; }; @@ -174,7 +173,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node if (!sdata.is_valid()) { current_option = -1; accept->set_text(vformat(TTR("Error loading scene from %s"), p_files[i])); - accept->popup_centered_minsize(); + accept->popup_centered(); error = true; break; } @@ -183,7 +182,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node if (!instanced_scene) { current_option = -1; accept->set_text(vformat(TTR("Error instancing scene from %s"), p_files[i])); - accept->popup_centered_minsize(); + accept->popup_centered(); error = true; break; } @@ -193,7 +192,7 @@ void SceneTreeDock::_perform_instance_scenes(const Vector<String> &p_files, Node if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) { accept->set_text(vformat(TTR("Cannot instance the scene '%s' because the current scene exists within one of its nodes."), p_files[i])); - accept->popup_centered_minsize(); + accept->popup_centered(); error = true; break; } @@ -240,14 +239,14 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) Ref<PackedScene> sdata = ResourceLoader::load(p_file); if (!sdata.is_valid()) { accept->set_text(vformat(TTR("Error loading scene from %s"), p_file)); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instanced_scene) { accept->set_text(vformat(TTR("Error instancing scene from %s"), p_file)); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } @@ -471,7 +470,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option = -1; accept->set_text(TTR("This operation can't be done on the tree root.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } @@ -535,7 +534,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option = -1; accept->set_text(TTR("This operation can't be done on the tree root.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } @@ -618,7 +617,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option = -1; accept->set_text(TTR("This operation can't be done on the tree root.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } @@ -654,19 +653,19 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (root->get_scene_inherited_state().is_valid()) { accept->set_text(TTR("Can't reparent nodes in inherited scenes, order of nodes can't change.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } if (node->get_owner() != root) { accept->set_text(TTR("Node must belong to the edited scene to become root.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } if (node->get_filename() != String()) { accept->set_text(TTR("Instantiated scenes can't become root")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } @@ -745,7 +744,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { // This prevents the dialog from being too wide after displaying // a deletion confirmation for a node with a long name. delete_dialog->set_size(Size2()); - delete_dialog->popup_centered_minsize(); + delete_dialog->popup_centered(); } } break; @@ -767,7 +766,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!scene) { accept->set_text(TTR("This operation can't be done without a scene.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } @@ -775,7 +774,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (selection.size() != 1) { accept->set_text(TTR("This operation requires a single selected node.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } @@ -783,17 +782,17 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (tocopy == scene) { accept->set_text(TTR("Can not perform with the root node.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } if (tocopy != editor_data->get_edited_scene_root() && tocopy->get_filename() != "") { accept->set_text(TTR("This operation can't be done on instanced scenes.")); - accept->popup_centered_minsize(); + accept->popup_centered(); break; } - new_scene_from_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + new_scene_from_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); List<String> extensions; Ref<PackedScene> sd = memnew(PackedScene); @@ -822,7 +821,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (node) { Node *root = EditorNode::get_singleton()->get_edited_scene(); NodePath path = root->get_path().rel_path_to(node->get_path()); - OS::get_singleton()->set_clipboard(path); + DisplayServer::get_singleton()->clipboard_set(path); } } } break; @@ -848,7 +847,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (editable) { editable_instance_remove_dialog->set_text(TTR("Disabling \"editable_instance\" will cause all properties of the node to be reverted to their default.")); - editable_instance_remove_dialog->popup_centered_minsize(); + editable_instance_remove_dialog->popup_centered(); break; } _toggle_editable_children(node); @@ -872,7 +871,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { // Fire confirmation dialog when children are editable. if (editable && !placeholder) { placeholder_editable_instance_remove_dialog->set_text(TTR("Enabling \"Load As Placeholder\" will disable \"Editable Children\" and cause all properties of the node to be reverted to their default.")); - placeholder_editable_instance_remove_dialog->popup_centered_minsize(); + placeholder_editable_instance_remove_dialog->popup_centered(); break; } @@ -929,7 +928,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } - clear_inherit_confirm->popup_centered_minsize(); + clear_inherit_confirm->popup_centered(); } break; case TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM: { if (!profile_allow_editing) { @@ -1031,7 +1030,7 @@ void SceneTreeDock::_node_collapsed(Object *p_obj) { if (!ti) return; - if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { _set_collapsed_recursive(ti, ti->is_collapsed()); } } @@ -1058,12 +1057,12 @@ void SceneTreeDock::_notification(int p_what) { spatial_editor_plugin->get_spatial_editor()->connect_compat("item_lock_status_changed", scene_tree, "_update_tree"); spatial_editor_plugin->get_spatial_editor()->connect_compat("item_group_status_changed", scene_tree, "_update_tree"); - button_add->set_icon(get_icon("Add", "EditorIcons")); - button_instance->set_icon(get_icon("Instance", "EditorIcons")); - button_create_script->set_icon(get_icon("ScriptCreate", "EditorIcons")); - button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons")); + button_add->set_icon(get_theme_icon("Add", "EditorIcons")); + button_instance->set_icon(get_theme_icon("Instance", "EditorIcons")); + button_create_script->set_icon(get_theme_icon("ScriptCreate", "EditorIcons")); + button_clear_script->set_icon(get_theme_icon("ScriptRemove", "EditorIcons")); - filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed)); @@ -1078,7 +1077,7 @@ void SceneTreeDock::_notification(int p_what) { ToolButton *node_shortcuts_toggle = memnew(ToolButton); node_shortcuts_toggle->set_name("NodeShortcutsToggle"); - node_shortcuts_toggle->set_icon(get_icon("Favorites", "EditorIcons")); + node_shortcuts_toggle->set_icon(get_theme_icon("Favorites", "EditorIcons")); node_shortcuts_toggle->set_toggle_mode(true); node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection")); node_shortcuts_toggle->set_anchors_and_margins_preset(Control::PRESET_CENTER_RIGHT); @@ -1097,18 +1096,19 @@ void SceneTreeDock::_notification(int p_what) { Button *button_2d = memnew(Button); beginner_node_shortcuts->add_child(button_2d); button_2d->set_text(TTR("2D Scene")); - button_2d->set_icon(get_icon("Node2D", "EditorIcons")); + button_2d->set_icon(get_theme_icon("Node2D", "EditorIcons")); button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_2D_SCENE, false)); + button_3d = memnew(Button); beginner_node_shortcuts->add_child(button_3d); button_3d->set_text(TTR("3D Scene")); - button_3d->set_icon(get_icon("Spatial", "EditorIcons")); + button_3d->set_icon(get_theme_icon("Spatial", "EditorIcons")); button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_3D_SCENE, false)); Button *button_ui = memnew(Button); beginner_node_shortcuts->add_child(button_ui); button_ui->set_text(TTR("User Interface")); - button_ui->set_icon(get_icon("Control", "EditorIcons")); + button_ui->set_icon(get_theme_icon("Control", "EditorIcons")); button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_CREATE_USER_INTERFACE, false)); VBoxContainer *favorite_node_shortcuts = memnew(VBoxContainer); @@ -1118,7 +1118,7 @@ void SceneTreeDock::_notification(int p_what) { Button *button_custom = memnew(Button); node_shortcuts->add_child(button_custom); button_custom->set_text(TTR("Other Node")); - button_custom->set_icon(get_icon("Add", "EditorIcons")); + button_custom->set_icon(get_theme_icon("Add", "EditorIcons")); button_custom->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_NEW, false)); node_shortcuts->add_spacer(); @@ -1134,12 +1134,12 @@ void SceneTreeDock::_notification(int p_what) { clear_inherit_confirm->disconnect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected)); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - button_add->set_icon(get_icon("Add", "EditorIcons")); - button_instance->set_icon(get_icon("Instance", "EditorIcons")); - button_create_script->set_icon(get_icon("ScriptCreate", "EditorIcons")); - button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons")); + button_add->set_icon(get_theme_icon("Add", "EditorIcons")); + button_instance->set_icon(get_theme_icon("Instance", "EditorIcons")); + button_create_script->set_icon(get_theme_icon("ScriptCreate", "EditorIcons")); + button_clear_script->set_icon(get_theme_icon("ScriptRemove", "EditorIcons")); - filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_right_icon(get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); } break; case NOTIFICATION_PROCESS: { @@ -1478,7 +1478,7 @@ bool SceneTreeDock::_validate_no_foreign() { if (E->get() != edited_scene && E->get()->get_owner() != edited_scene) { accept->set_text(TTR("Can't operate on nodes from a foreign scene!")); - accept->popup_centered_minsize(); + accept->popup_centered(); return false; } @@ -1492,7 +1492,7 @@ bool SceneTreeDock::_validate_no_foreign() { if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E->get())) >= 0) { accept->set_text(TTR("Can't operate on nodes the current scene inherits from!")); - accept->popup_centered_minsize(); + accept->popup_centered(); return false; } } @@ -2187,13 +2187,13 @@ void SceneTreeDock::_new_scene_from(String p_file) { if (selection.size() != 1) { accept->set_text(TTR("This operation requires a single selected node.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } if (EditorNode::get_singleton()->is_scene_open(p_file)) { accept->set_text(TTR("Can't overwrite scene that is still open!")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } @@ -2210,7 +2210,7 @@ void SceneTreeDock::_new_scene_from(String p_file) { if (err != OK) { accept->set_text(TTR("Couldn't save new scene. Likely dependencies (instances) couldn't be satisfied.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } @@ -2221,13 +2221,13 @@ void SceneTreeDock::_new_scene_from(String p_file) { err = ResourceSaver::save(p_file, sdata, flg); if (err != OK) { accept->set_text(TTR("Error saving scene.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } _replace_with_branch_scene(p_file, base); } else { accept->set_text(TTR("Error duplicating scene to save it.")); - accept->popup_centered_minsize(); + accept->popup_centered(); return; } } @@ -2346,7 +2346,7 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) { int to_pos = -1; _normalize_drop(to_node, to_pos, p_type); - _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(KEY_SHIFT)); + _do_reparent(to_node, to_pos, nodes, !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)); } void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) { @@ -2390,8 +2390,8 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->clear(); if (profile_allow_editing) { - menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW); - menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE); + menu->add_icon_shortcut(get_theme_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW); + menu->add_icon_shortcut(get_theme_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE); } menu->set_size(Size2(1, 1)); @@ -2422,10 +2422,10 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (menu->get_item_count() > 0) menu->add_separator(); - menu->add_icon_shortcut(get_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW); - menu->add_icon_shortcut(get_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE); + menu->add_icon_shortcut(get_theme_icon("Add", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW); + menu->add_icon_shortcut(get_theme_icon("Instance", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE); } - menu->add_icon_shortcut(get_icon("Collapse", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE); + menu->add_icon_shortcut(get_theme_icon("Collapse", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE); menu->add_separator(); existing_script = selected->get_script(); @@ -2440,14 +2440,14 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (full_selection.size() == 1) { add_separator = true; - menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); + menu->add_icon_shortcut(get_theme_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); if (existing_script.is_valid()) { - menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT); + menu->add_icon_shortcut(get_theme_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT); } } if (existing_script.is_valid() && existing_script_removable) { add_separator = true; - menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + menu->add_icon_shortcut(get_theme_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); } else if (full_selection.size() > 1) { bool script_exists = false; for (List<Node *>::Element *E = full_selection.front(); E; E = E->next()) { @@ -2459,7 +2459,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (script_exists) { add_separator = true; - menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + menu->add_icon_shortcut(get_theme_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); } } @@ -2470,19 +2470,19 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (profile_allow_editing) { if (full_selection.size() == 1) { - menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME); + menu->add_icon_shortcut(get_theme_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME); } - menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE); + menu->add_icon_shortcut(get_theme_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE); if (scene_tree->get_selected() != edited_scene) { menu->add_separator(); - menu->add_icon_shortcut(get_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP); - menu->add_icon_shortcut(get_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN); - menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE); - menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT); - menu->add_icon_shortcut(get_icon("ReparentToNewNode", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE); + menu->add_icon_shortcut(get_theme_icon("MoveUp", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP); + menu->add_icon_shortcut(get_theme_icon("MoveDown", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN); + menu->add_icon_shortcut(get_theme_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE); + menu->add_icon_shortcut(get_theme_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT); + menu->add_icon_shortcut(get_theme_icon("ReparentToNewNode", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE); if (selection.size() == 1) { - menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT); + menu->add_icon_shortcut(get_theme_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT); } } } @@ -2490,12 +2490,12 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (profile_allow_editing) { menu->add_separator(); - menu->add_icon_shortcut(get_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE); - menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM); + menu->add_icon_shortcut(get_theme_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE); + menu->add_icon_shortcut(get_theme_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM); } if (full_selection.size() == 1) { menu->add_separator(); - menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH); + menu->add_icon_shortcut(get_theme_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH); } bool is_external = (selection[0]->get_filename() != ""); @@ -2507,7 +2507,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (profile_allow_editing) { menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE); } - menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED); + menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED); } else if (!is_top_level) { menu->add_separator(); bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]); @@ -2517,7 +2517,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER); menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL); } - menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN); + menu->add_icon_item(get_theme_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN); if (profile_allow_editing) { menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable); menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder); @@ -2529,14 +2529,14 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { if (profile_allow_editing && selection.size() > 1) { //this is not a commonly used action, it makes no sense for it to be where it was nor always present. menu->add_separator(); - menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME); + menu->add_icon_shortcut(get_theme_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME); } menu->add_separator(); - menu->add_icon_item(get_icon("Help", "EditorIcons"), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION); + menu->add_icon_item(get_theme_icon("Help", "EditorIcons"), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION); if (profile_allow_editing) { menu->add_separator(); - menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); + menu->add_icon_shortcut(get_theme_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); } menu->set_size(Size2(1, 1)); menu->set_position(p_menu_pos); @@ -2795,7 +2795,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel VBoxContainer *vbc = this; HBoxContainer *filter_hbc = memnew(HBoxContainer); - filter_hbc->add_constant_override("separate", 0); + filter_hbc->add_theme_constant_override("separate", 0); ED_SHORTCUT("scene_tree/rename", TTR("Rename")); ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KEY_MASK_CMD | KEY_F2); @@ -2835,7 +2835,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel filter->set_h_size_flags(SIZE_EXPAND_FILL); filter->set_placeholder(TTR("Filter nodes")); filter_hbc->add_child(filter); - filter->add_constant_override("minimum_spaces", 0); + filter->add_theme_constant_override("minimum_spaces", 0); filter->connect("text_changed", callable_mp(this, &SceneTreeDock::_filter_changed)); button_create_script = memnew(ToolButton); @@ -2939,14 +2939,14 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel import_subscene_dialog->connect("subscene_selected", callable_mp(this, &SceneTreeDock::_import_subscene)); new_scene_from_dialog = memnew(EditorFileDialog); - new_scene_from_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE); + new_scene_from_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); add_child(new_scene_from_dialog); new_scene_from_dialog->connect("file_selected", callable_mp(this, &SceneTreeDock::_new_scene_from)); menu = memnew(PopupMenu); add_child(menu); menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); - menu->set_hide_on_window_lose_focus(true); + menu_subresources = memnew(PopupMenu); menu_subresources->set_name("Sub-Resources"); menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false)); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 782df12d4b..a290e57a4e 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -37,7 +37,7 @@ #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "scene/gui/label.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" Node *SceneTreeEditor::get_scene_node() { @@ -129,7 +129,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i return; config_err = config_err.word_wrap(80); warning->set_text(config_err); - warning->popup_centered_minsize(); + warning->popup_centered(); } else if (p_id == BUTTON_SIGNALS) { @@ -201,19 +201,19 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->set_metadata(0, p_node->get_path()); if (connect_to_script_mode) { - Color accent = get_color("accent_color", "Editor"); + Color accent = get_theme_color("accent_color", "Editor"); Ref<Script> script = p_node->get_script(); if (!script.is_null() && EditorNode::get_singleton()->get_object_custom_type_base(p_node) != script) { //has script - item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT); + item->add_button(0, get_theme_icon("Script", "EditorIcons"), BUTTON_SCRIPT); } else { //has no script (or script is a custom type) - item->set_custom_color(0, get_color("disabled_font_color", "Editor")); + item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor")); item->set_selectable(0, false); if (!script.is_null()) { // make sure to mark the script if a custom type - item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT); + item->add_button(0, get_theme_icon("Script", "EditorIcons"), BUTTON_SCRIPT); item->set_button_disabled(0, item->get_button_count(0) - 1, true); } @@ -231,7 +231,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } else if (part_of_subscene) { if (valid_types.size() == 0) { - item->set_custom_color(0, get_color("disabled_font_color", "Editor")); + item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor")); } } else if (marked.has(p_node)) { @@ -241,14 +241,14 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } item->set_text(0, node_name); item->set_selectable(0, marked_selectable); - item->set_custom_color(0, get_color("accent_color", "Editor")); + item->set_custom_color(0, get_theme_color("accent_color", "Editor")); } else if (!marked_selectable && !marked_children_selectable) { Node *node = p_node; while (node) { if (marked.has(node)) { item->set_selectable(0, false); - item->set_custom_color(0, get_color("error_color", "Editor")); + item->set_custom_color(0, get_theme_color("error_color", "Editor")); break; } node = node->get_parent(); @@ -259,7 +259,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { String warning = p_node->get_configuration_warning(); if (warning != String()) { - item->add_button(0, get_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + p_node->get_configuration_warning()); + item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + p_node->get_configuration_warning()); } int num_connections = p_node->get_persistent_signal_connection_count(); @@ -268,21 +268,21 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { if (num_connections >= 1 && num_groups >= 1) { item->add_button( 0, - get_icon("SignalsAndGroups", "EditorIcons"), + get_theme_icon("SignalsAndGroups", "EditorIcons"), BUTTON_SIGNALS, false, vformat(TTR("Node has %s connection(s) and %s group(s).\nClick to show signals dock."), num_connections, num_groups)); } else if (num_connections >= 1) { item->add_button( 0, - get_icon("Signals", "EditorIcons"), + get_theme_icon("Signals", "EditorIcons"), BUTTON_SIGNALS, false, vformat(TTR("Node has %s connection(s).\nClick to show signals dock."), num_connections)); } else if (num_groups >= 1) { item->add_button( 0, - get_icon("Groups", "EditorIcons"), + get_theme_icon("Groups", "EditorIcons"), BUTTON_GROUPS, false, vformat(TTR("Node is in %s group(s).\nClick to show groups dock."), num_groups)); @@ -290,7 +290,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (p_node == get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { - item->add_button(0, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor")); + item->add_button(0, get_theme_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor")); String tooltip = TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path() + "\n" + TTR("Type:") + " " + p_node->get_class(); if (p_node->get_editor_description() != String()) { @@ -299,7 +299,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->set_tooltip(0, tooltip); } else if (p_node != get_scene_node() && p_node->get_filename() != "" && can_open_instance) { - item->add_button(0, get_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor")); + item->add_button(0, get_theme_icon("InstanceOptions", "EditorIcons"), BUTTON_SUBSCENE, false, TTR("Open in Editor")); String tooltip = TTR("Instance:") + " " + p_node->get_filename() + "\n" + TTR("Type:") + " " + p_node->get_class(); if (p_node->get_editor_description() != String()) { @@ -328,7 +328,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { Ref<Script> script = p_node->get_script(); if (!script.is_null()) { - item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path()); + item->add_button(0, get_theme_icon("Script", "EditorIcons"), BUTTON_SCRIPT, false, TTR("Open Script:") + " " + script->get_path()); if (EditorNode::get_singleton()->get_object_custom_type_base(p_node) == script) { item->set_button_color(0, item->get_button_count(0) - 1, Color(1, 1, 1, 0.5)); } @@ -338,17 +338,17 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { bool is_locked = p_node->has_meta("_edit_lock_"); //_edit_group_ if (is_locked) - item->add_button(0, get_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it.")); + item->add_button(0, get_theme_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it.")); bool is_grouped = p_node->has_meta("_edit_group_"); if (is_grouped) - item->add_button(0, get_icon("Group", "EditorIcons"), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable.")); + item->add_button(0, get_theme_icon("Group", "EditorIcons"), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable.")); bool v = p_node->call("is_visible"); if (v) - item->add_button(0, get_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); + item->add_button(0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); else - item->add_button(0, get_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); + item->add_button(0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node)); @@ -358,17 +358,17 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { bool is_locked = p_node->has_meta("_edit_lock_"); if (is_locked) - item->add_button(0, get_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it.")); + item->add_button(0, get_theme_icon("Lock", "EditorIcons"), BUTTON_LOCK, false, TTR("Node is locked.\nClick to unlock it.")); bool is_grouped = p_node->has_meta("_edit_group_"); if (is_grouped) - item->add_button(0, get_icon("Group", "EditorIcons"), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable.")); + item->add_button(0, get_theme_icon("Group", "EditorIcons"), BUTTON_GROUP, false, TTR("Children are not selectable.\nClick to make selectable.")); bool v = p_node->call("is_visible"); if (v) - item->add_button(0, get_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); + item->add_button(0, get_theme_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); else - item->add_button(0, get_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); + item->add_button(0, get_theme_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility")); if (!p_node->is_connected("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed))) p_node->connect("visibility_changed", callable_mp(this, &SceneTreeEditor::_node_visibility_changed), varray(p_node)); @@ -379,7 +379,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { bool is_pinned = AnimationPlayerEditor::singleton->get_player() == p_node && AnimationPlayerEditor::singleton->is_pinned(); if (is_pinned) { - item->add_button(0, get_icon("Pin", "EditorIcons"), BUTTON_PIN, false, TTR("AnimationPlayer is pinned.\nClick to unpin.")); + item->add_button(0, get_theme_icon("Pin", "EditorIcons"), BUTTON_PIN, false, TTR("AnimationPlayer is pinned.\nClick to unpin.")); } } } @@ -417,7 +417,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { if (!valid) { //item->set_selectable(0,marked_selectable); - item->set_custom_color(0, get_color("disabled_font_color", "Editor")); + item->set_custom_color(0, get_theme_color("disabled_font_color", "Editor")); item->set_selectable(0, false); } } @@ -462,9 +462,9 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) { } if (visible) - item->set_button(0, idx, get_icon("GuiVisibilityVisible", "EditorIcons")); + item->set_button(0, idx, get_theme_icon("GuiVisibilityVisible", "EditorIcons")); else - item->set_button(0, idx, get_icon("GuiVisibilityHidden", "EditorIcons")); + item->set_button(0, idx, get_theme_icon("GuiVisibilityHidden", "EditorIcons")); _update_visibility_color(p_node, item); } @@ -757,7 +757,7 @@ void SceneTreeEditor::_renamed() { if (!Node::_validate_node_name(new_name)) { error->set_text(TTR("Invalid node name, the following characters are not allowed:") + "\n" + Node::invalid_character); - error->popup_centered_minsize(); + error->popup_centered(); if (new_name.empty()) { which->set_text(0, n->get_name()); @@ -1141,7 +1141,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope tree->set_anchor(MARGIN_BOTTOM, ANCHOR_END); tree->set_begin(Point2(0, p_label ? 18 : 0)); tree->set_end(Point2(0, 0)); - tree->add_constant_override("button_margin", 0); + tree->add_theme_constant_override("button_margin", 0); add_child(tree); @@ -1193,18 +1193,19 @@ SceneTreeEditor::~SceneTreeEditor() { void SceneTreeDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + + if (is_visible()) + tree->update_tree(); + } break; case NOTIFICATION_ENTER_TREE: { connect("confirmed", callable_mp(this, &SceneTreeDialog::_select)); - filter->set_right_icon(get_icon("Search", "EditorIcons")); + filter->set_right_icon(tree->get_theme_icon("Search", "EditorIcons")); filter->set_clear_button_enabled(true); } break; case NOTIFICATION_EXIT_TREE: { disconnect("confirmed", callable_mp(this, &SceneTreeDialog::_select)); } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - if (is_visible_in_tree()) - tree->update_tree(); - } break; } } @@ -1239,14 +1240,14 @@ SceneTreeDialog::SceneTreeDialog() { add_child(vbc); filter = memnew(LineEdit); - filter->set_h_size_flags(SIZE_EXPAND_FILL); + filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); filter->set_placeholder(TTR("Filter nodes")); - filter->add_constant_override("minimum_spaces", 0); + filter->add_theme_constant_override("minimum_spaces", 0); filter->connect("text_changed", callable_mp(this, &SceneTreeDialog::_filter_changed)); vbc->add_child(filter); tree = memnew(SceneTreeEditor(false, false, true)); - tree->set_v_size_flags(SIZE_EXPAND_FILL); + tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); tree->get_scene_tree()->connect("item_activated", callable_mp(this, &SceneTreeDialog::_select)); vbc->add_child(tree); } diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 5a111afe32..82199fc1f1 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -40,36 +40,38 @@ #include "editor/editor_scale.h" #include "editor_file_system.h" -void ScriptCreateDialog::_notification(int p_what) { +void ScriptCreateDialog::_theme_changed() { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + String lang = ScriptServer::get_language(i)->get_type(); + Ref<Texture2D> lang_icon = gc->get_theme_icon(lang, "EditorIcons"); + if (lang_icon.is_valid()) { + language_menu->set_item_icon(i, lang_icon); + } + } - switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - String lang = ScriptServer::get_language(i)->get_type(); - Ref<Texture2D> lang_icon = get_icon(lang, "EditorIcons"); - if (lang_icon.is_valid()) { - language_menu->set_item_icon(i, lang_icon); - } + String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", ""); + if (!last_lang.empty()) { + for (int i = 0; i < language_menu->get_item_count(); i++) { + if (language_menu->get_item_text(i) == last_lang) { + language_menu->select(i); + current_language = i; + break; } + } + } else { + language_menu->select(default_language); + } - String last_lang = EditorSettings::get_singleton()->get_project_metadata("script_setup", "last_selected_language", ""); - if (!last_lang.empty()) { - for (int i = 0; i < language_menu->get_item_count(); i++) { - if (language_menu->get_item_text(i) == last_lang) { - language_menu->select(i); - current_language = i; - break; - } - } - } else { - language_menu->select(default_language); - } + path_button->set_icon(gc->get_theme_icon("Folder", "EditorIcons")); + parent_browse_button->set_icon(gc->get_theme_icon("Folder", "EditorIcons")); + parent_search_button->set_icon(gc->get_theme_icon("ClassList", "EditorIcons")); + status_panel->add_theme_style_override("panel", gc->get_theme_stylebox("bg", "Tree")); +} +void ScriptCreateDialog::_notification(int p_what) { - path_button->set_icon(get_icon("Folder", "EditorIcons")); - parent_browse_button->set_icon(get_icon("Folder", "EditorIcons")); - parent_search_button->set_icon(get_icon("ClassList", "EditorIcons")); - status_panel->add_style_override("panel", get_stylebox("bg", "Tree")); + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + _theme_changed(); } break; } } @@ -442,7 +444,7 @@ void ScriptCreateDialog::_lang_changed(int l) { override_info += ", "; } } - template_menu->set_item_icon(extended.id, get_icon("Override", "EditorIcons")); + template_menu->set_item_icon(extended.id, gc->get_theme_icon("Override", "EditorIcons")); template_menu->get_popup()->set_item_tooltip(extended.id, override_info.as_string()); } // Reselect last selected template @@ -517,11 +519,11 @@ void ScriptCreateDialog::_browse_path(bool browse_parent, bool p_save) { is_browsing_parent = browse_parent; if (p_save) { - file_browse->set_mode(EditorFileDialog::MODE_SAVE_FILE); + file_browse->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); file_browse->set_title(TTR("Open Script / Choose Location")); file_browse->get_ok()->set_text(TTR("Open")); } else { - file_browse->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_browse->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); file_browse->set_title(TTR("Open Script")); } @@ -607,9 +609,9 @@ void ScriptCreateDialog::_msg_script_valid(bool valid, const String &p_msg) { error_label->set_text("- " + TTR(p_msg)); if (valid) { - error_label->add_color_override("font_color", get_color("success_color", "Editor")); + error_label->add_theme_color_override("font_color", gc->get_theme_color("success_color", "Editor")); } else { - error_label->add_color_override("font_color", get_color("error_color", "Editor")); + error_label->add_theme_color_override("font_color", gc->get_theme_color("error_color", "Editor")); } } @@ -617,9 +619,9 @@ void ScriptCreateDialog::_msg_path_valid(bool valid, const String &p_msg) { path_error_label->set_text("- " + TTR(p_msg)); if (valid) { - path_error_label->add_color_override("font_color", get_color("success_color", "Editor")); + path_error_label->add_theme_color_override("font_color", gc->get_theme_color("success_color", "Editor")); } else { - path_error_label->add_color_override("font_color", get_color("error_color", "Editor")); + path_error_label->add_theme_color_override("font_color", gc->get_theme_color("error_color", "Editor")); } } @@ -739,9 +741,11 @@ ScriptCreateDialog::ScriptCreateDialog() { /* Main Controls */ - GridContainer *gc = memnew(GridContainer); + gc = memnew(GridContainer); gc->set_columns(2); + gc->connect("theme_changed", callable_mp(this, &ScriptCreateDialog::_theme_changed)); + /* Error Messages Field */ VBoxContainer *vb = memnew(VBoxContainer); @@ -774,7 +778,7 @@ ScriptCreateDialog::ScriptCreateDialog() { language_menu = memnew(OptionButton); language_menu->set_custom_minimum_size(Size2(250, 0) * EDSCALE); - language_menu->set_h_size_flags(SIZE_EXPAND_FILL); + language_menu->set_h_size_flags(Control::SIZE_EXPAND_FILL); gc->add_child(memnew(Label(TTR("Language:")))); gc->add_child(language_menu); @@ -798,10 +802,10 @@ ScriptCreateDialog::ScriptCreateDialog() { base_type = "Object"; hb = memnew(HBoxContainer); - hb->set_h_size_flags(SIZE_EXPAND_FILL); + hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); parent_name = memnew(LineEdit); parent_name->connect("text_changed", callable_mp(this, &ScriptCreateDialog::_parent_name_changed)); - parent_name->set_h_size_flags(SIZE_EXPAND_FILL); + parent_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(parent_name); parent_search_button = memnew(Button); parent_search_button->set_flat(true); @@ -819,7 +823,7 @@ ScriptCreateDialog::ScriptCreateDialog() { class_name = memnew(LineEdit); class_name->connect("text_changed", callable_mp(this, &ScriptCreateDialog::_class_name_changed)); - class_name->set_h_size_flags(SIZE_EXPAND_FILL); + class_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); gc->add_child(memnew(Label(TTR("Class Name:")))); gc->add_child(class_name); @@ -845,7 +849,7 @@ ScriptCreateDialog::ScriptCreateDialog() { file_path = memnew(LineEdit); file_path->connect("text_changed", callable_mp(this, &ScriptCreateDialog::_path_changed)); file_path->connect("text_entered", callable_mp(this, &ScriptCreateDialog::_path_entered)); - file_path->set_h_size_flags(SIZE_EXPAND_FILL); + file_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(file_path); path_button = memnew(Button); path_button->set_flat(true); @@ -863,18 +867,16 @@ ScriptCreateDialog::ScriptCreateDialog() { file_browse = memnew(EditorFileDialog); file_browse->connect("file_selected", callable_mp(this, &ScriptCreateDialog::_file_selected)); - file_browse->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_browse->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); add_child(file_browse); get_ok()->set_text(TTR("Create")); alert = memnew(AcceptDialog); - alert->set_as_minsize(); alert->get_label()->set_autowrap(true); alert->get_label()->set_align(Label::ALIGN_CENTER); alert->get_label()->set_valign(Label::VALIGN_CENTER); alert->get_label()->set_custom_minimum_size(Size2(325, 60) * EDSCALE); add_child(alert); - set_as_minsize(); set_hide_on_ok(false); set_title(TTR("Attach Node Script")); diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index f73309c373..f164cd2a15 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -45,6 +45,7 @@ class CreateDialog; class ScriptCreateDialog : public ConfirmationDialog { GDCLASS(ScriptCreateDialog, ConfirmationDialog); + GridContainer *gc; LineEdit *class_name; Label *error_label; Label *path_error_label; @@ -123,6 +124,7 @@ class ScriptCreateDialog : public ConfirmationDialog { void _update_dialog(); protected: + void _theme_changed(); void _notification(int p_what); static void _bind_methods(); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index cf93fab9a8..6bd06aff64 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -118,6 +118,12 @@ void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_nam void EditorSettingsDialog::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "editor_settings", Rect2(get_position(), get_size())); + set_process_unhandled_input(false); + } + } break; case NOTIFICATION_READY: { undo_redo->set_method_notify_callback(EditorDebuggerNode::_method_changeds, NULL); undo_redo->set_property_notify_callback(EditorDebuggerNode::_property_changeds, NULL); @@ -126,10 +132,6 @@ void EditorSettingsDialog::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { _update_icons(); } break; - case NOTIFICATION_POPUP_HIDE: { - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "editor_settings", get_rect()); - set_process_unhandled_input(false); - } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { _update_icons(); // Update theme colors. @@ -143,7 +145,7 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) { const Ref<InputEventKey> k = p_event; - if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) { + if (k.is_valid() && k->is_pressed()) { bool handled = false; @@ -169,22 +171,22 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) { } if (handled) { - accept_event(); + set_input_as_handled(); } } } void EditorSettingsDialog::_update_icons() { - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + search_box->set_right_icon(shortcuts->get_theme_icon("Search", "EditorIcons")); search_box->set_clear_button_enabled(true); - shortcut_search_box->set_right_icon(get_icon("Search", "EditorIcons")); + shortcut_search_box->set_right_icon(shortcuts->get_theme_icon("Search", "EditorIcons")); shortcut_search_box->set_clear_button_enabled(true); - restart_close_button->set_icon(get_icon("Close", "EditorIcons")); - restart_container->add_style_override("panel", get_stylebox("bg", "Tree")); - restart_icon->set_texture(get_icon("StatusWarning", "EditorIcons")); - restart_label->add_color_override("font_color", get_color("warning_color", "Editor")); + restart_close_button->set_icon(shortcuts->get_theme_icon("Close", "EditorIcons")); + restart_container->add_theme_style_override("panel", shortcuts->get_theme_stylebox("bg", "Tree")); + restart_icon->set_texture(shortcuts->get_theme_icon("StatusWarning", "EditorIcons")); + restart_label->add_theme_color_override("font_color", shortcuts->get_theme_color("warning_color", "Editor")); } void EditorSettingsDialog::_update_shortcuts() { @@ -230,8 +232,8 @@ void EditorSettingsDialog::_update_shortcuts() { } sections[section_name] = section; - section->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); - section->set_custom_bg_color(1, get_color("prop_subsection", "Editor")); + section->set_custom_bg_color(0, shortcuts->get_theme_color("prop_subsection", "Editor")); + section->set_custom_bg_color(1, shortcuts->get_theme_color("prop_subsection", "Editor")); } // Don't match unassigned shortcuts when searching for assigned keys in search results. @@ -243,16 +245,16 @@ void EditorSettingsDialog::_update_shortcuts() { item->set_text(1, sc->get_as_text()); if (!sc->is_shortcut(original) && !(sc->get_shortcut().is_null() && original.is_null())) { - item->add_button(1, get_icon("Reload", "EditorIcons"), 2); + item->add_button(1, shortcuts->get_theme_icon("Reload", "EditorIcons"), 2); } if (sc->get_as_text() == "None") { // Fade out unassigned shortcut labels for easier visual grepping. - item->set_custom_color(1, get_color("font_color", "Label") * Color(1, 1, 1, 0.5)); + item->set_custom_color(1, shortcuts->get_theme_color("font_color", "Label") * Color(1, 1, 1, 0.5)); } - item->add_button(1, get_icon("Edit", "EditorIcons"), 0); - item->add_button(1, get_icon("Close", "EditorIcons"), 1); + item->add_button(1, shortcuts->get_theme_icon("Edit", "EditorIcons"), 0); + item->add_button(1, shortcuts->get_theme_icon("Close", "EditorIcons"), 1); item->set_tooltip(0, E->get()); item->set_metadata(0, E->get()); } @@ -279,9 +281,9 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column press_a_key_label->set_text(TTR("Press a Key...")); last_wait_for_key = Ref<InputEventKey>(); press_a_key->popup_centered(Size2(250, 80) * EDSCALE); - press_a_key->grab_focus(); - press_a_key->get_ok()->set_focus_mode(FOCUS_NONE); - press_a_key->get_cancel()->set_focus_mode(FOCUS_NONE); + //press_a_key->grab_focus(); + press_a_key->get_ok()->set_focus_mode(Control::FOCUS_NONE); + press_a_key->get_cancel()->set_focus_mode(Control::FOCUS_NONE); shortcut_configured = item; } else if (p_idx == 1) { //erase @@ -323,7 +325,7 @@ void EditorSettingsDialog::_wait_for_key(const Ref<InputEvent> &p_event) { const String str = keycode_get_string(k->get_keycode_with_modifiers()); press_a_key_label->set_text(str); - press_a_key->accept_event(); + press_a_key->set_input_as_handled(); } } @@ -394,7 +396,7 @@ void EditorSettingsDialog::_bind_methods() { EditorSettingsDialog::EditorSettingsDialog() { set_title(TTR("Editor Settings")); - set_resizable(true); + undo_redo = memnew(UndoRedo); tabs = memnew(TabContainer); @@ -430,7 +432,7 @@ EditorSettingsDialog::EditorSettingsDialog() { HBoxContainer *restart_hb = memnew(HBoxContainer); restart_container->add_child(restart_hb); restart_icon = memnew(TextureRect); - restart_icon->set_v_size_flags(SIZE_SHRINK_CENTER); + restart_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); restart_hb->add_child(restart_icon); restart_label = memnew(Label); restart_label->set_text(TTR("The editor must be restarted for changes to take effect.")); @@ -462,7 +464,7 @@ EditorSettingsDialog::EditorSettingsDialog() { shortcuts = memnew(Tree); tab_shortcuts->add_child(shortcuts, true); - shortcuts->set_v_size_flags(SIZE_EXPAND_FILL); + shortcuts->set_v_size_flags(Control::SIZE_EXPAND_FILL); shortcuts->set_columns(2); shortcuts->set_hide_root(true); shortcuts->set_column_titles_visible(true); @@ -471,7 +473,7 @@ EditorSettingsDialog::EditorSettingsDialog() { shortcuts->connect("button_pressed", callable_mp(this, &EditorSettingsDialog::_shortcut_button_pressed)); press_a_key = memnew(ConfirmationDialog); - press_a_key->set_focus_mode(FOCUS_ALL); + //press_a_key->set_focus_mode(Control::FOCUS_ALL); add_child(press_a_key); Label *l = memnew(Label); @@ -479,10 +481,10 @@ EditorSettingsDialog::EditorSettingsDialog() { l->set_anchors_and_margins_preset(Control::PRESET_WIDE); l->set_align(Label::ALIGN_CENTER); l->set_margin(MARGIN_TOP, 20); - l->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 30); + l->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_BEGIN, 30); press_a_key_label = l; press_a_key->add_child(l); - press_a_key->connect("gui_input", callable_mp(this, &EditorSettingsDialog::_wait_for_key)); + press_a_key->connect("window_input", callable_mp(this, &EditorSettingsDialog::_wait_for_key)); press_a_key->connect("confirmed", callable_mp(this, &EditorSettingsDialog::_press_a_key_confirm)); set_hide_on_ok(true); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index d6e443ec14..a3030e7380 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -803,9 +803,9 @@ LightSpatialGizmoPlugin::LightSpatialGizmoPlugin() { create_material("lines_secondary", Color(1, 1, 1, 0.35), false, false, true); create_material("lines_billboard", Color(1, 1, 1), true, false, true); - create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons")); - create_icon_material("light_omni_icon", SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons")); - create_icon_material("light_spot_icon", SpatialEditor::get_singleton()->get_icon("GizmoSpotLight", "EditorIcons")); + create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoDirectionalLight", "EditorIcons")); + create_icon_material("light_omni_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoLight", "EditorIcons")); + create_icon_material("light_spot_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoSpotLight", "EditorIcons")); create_handle_material("handles"); create_handle_material("handles_billboard", true); @@ -1090,7 +1090,7 @@ AudioStreamPlayer3DSpatialGizmoPlugin::AudioStreamPlayer3DSpatialGizmoPlugin() { Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/stream_player_3d", Color(0.4, 0.8, 1)); - create_icon_material("stream_player_3d_icon", SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer", "EditorIcons")); + create_icon_material("stream_player_3d_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoSpatialSamplePlayer", "EditorIcons")); create_material("stream_player_3d_material_primary", gizmo_color); create_material("stream_player_3d_material_secondary", gizmo_color * Color(1, 1, 1, 0.35)); create_handle_material("handles"); @@ -1571,12 +1571,12 @@ Position3DSpatialGizmoPlugin::Position3DSpatialGizmoPlugin() { cursor_points.push_back(Vector3(0, -cs, 0)); cursor_points.push_back(Vector3(0, 0, +cs)); cursor_points.push_back(Vector3(0, 0, -cs)); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_color("axis_x_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_color("axis_x_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_color("axis_y_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_color("axis_y_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_color("axis_z_color", "Editor")); - cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_color("axis_z_color", "Editor")); + cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor")); + cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_x_color", "Editor")); + cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor")); + cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_y_color", "Editor")); + cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor")); + cursor_colors.push_back(EditorNode::get_singleton()->get_gui_base()->get_theme_color("axis_z_color", "Editor")); Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D); mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); @@ -2343,7 +2343,7 @@ void VisibilityNotifierGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { //// CPUParticlesGizmoPlugin::CPUParticlesGizmoPlugin() { - create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_icon("GizmoCPUParticles", "EditorIcons")); + create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoCPUParticles", "EditorIcons")); } bool CPUParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) { @@ -2374,7 +2374,7 @@ ParticlesGizmoPlugin::ParticlesGizmoPlugin() { create_material("particles_material", gizmo_color); gizmo_color.a = 0.1; create_material("particles_solid_material", gizmo_color); - create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_icon("GizmoParticles", "EditorIcons")); + create_icon_material("particles_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoParticles", "EditorIcons")); create_handle_material("handles"); } @@ -2543,7 +2543,7 @@ ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() { gizmo_color.a = 0.1; create_material("reflection_probe_solid_material", gizmo_color); - create_icon_material("reflection_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoReflectionProbe", "EditorIcons")); + create_icon_material("reflection_probe_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoReflectionProbe", "EditorIcons")); create_handle_material("handles"); } @@ -2731,7 +2731,7 @@ GIProbeGizmoPlugin::GIProbeGizmoPlugin() { gizmo_color.a = 0.05; create_material("gi_probe_solid_material", gizmo_color); - create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoGIProbe", "EditorIcons")); + create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_theme_icon("GizmoGIProbe", "EditorIcons")); create_handle_material("handles"); } diff --git a/main/SCsub b/main/SCsub index e1efc7e6ed..0262701d79 100644 --- a/main/SCsub +++ b/main/SCsub @@ -9,15 +9,6 @@ env.main_sources = [] env.add_source_files(env.main_sources, "*.cpp") -# Order matters here. Higher index controller database files write on top of lower index database files. -controller_databases = ["#main/gamecontrollerdb_204.txt", "#main/gamecontrollerdb_205.txt", "#main/gamecontrollerdb.txt", "#main/godotcontrollerdb.txt"] - -env.Depends("#main/default_controller_mappings.gen.cpp", controller_databases) -env.CommandNoCache("#main/default_controller_mappings.gen.cpp", controller_databases, run_in_subprocess(main_builders.make_default_controller_mappings)) - -# Don't warn about duplicate entry here, we need it registered manually for first build, -# even if later builds will pick it up twice due to above *.cpp globbing. -env.add_source_files(env.main_sources, "#main/default_controller_mappings.gen.cpp", warn_duplicates=False) env.Depends("#main/splash.gen.h", "#main/splash.png") env.CommandNoCache("#main/splash.gen.h", "#main/splash.png", run_in_subprocess(main_builders.make_splash)) diff --git a/main/main.cpp b/main/main.cpp index 0047d05771..bc97f9f8c5 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -32,7 +32,8 @@ #include "core/crypto/crypto.h" #include "core/debugger/engine_debugger.h" -#include "core/input_map.h" +#include "core/input/input_filter.h" +#include "core/input/input_map.h" #include "core/io/file_access_network.h" #include "core/io/file_access_pack.h" #include "core/io/file_access_zip.h" @@ -49,7 +50,6 @@ #include "core/version_hash.gen.h" #include "drivers/register_driver_types.h" #include "main/app_icon.gen.h" -#include "main/input_default.h" #include "main/main_timer_sync.h" #include "main/performance.h" #include "main/splash.gen.h" @@ -58,17 +58,20 @@ #include "modules/register_module_types.h" #include "platform/register_platform_apis.h" #include "scene/main/scene_tree.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/register_scene_types.h" #include "scene/resources/packed_scene.h" #include "servers/arvr_server.h" #include "servers/audio_server.h" #include "servers/camera_server.h" +#include "servers/display_server.h" #include "servers/navigation_2d_server.h" #include "servers/navigation_server.h" #include "servers/physics_2d_server.h" #include "servers/physics_server.h" #include "servers/register_server_types.h" +#include "servers/visual/visual_server_raster.h" +#include "servers/visual/visual_server_wrap_mt.h" #ifdef TOOLS_ENABLED #include "editor/doc_data.h" @@ -86,6 +89,7 @@ // Initialized in setup() static Engine *engine = NULL; static ProjectSettings *globals = NULL; +static InputFilter *input = NULL; static InputMap *input_map = NULL; static TranslationServer *translation_server = NULL; static Performance *performance = NULL; @@ -98,6 +102,8 @@ static MessageQueue *message_queue = NULL; // Initialized in setup2() static AudioServer *audio_server = NULL; +static DisplayServer *display_server = NULL; +static VisualServer *visual_server = NULL; static CameraServer *camera_server = NULL; static ARVRServer *arvr_server = NULL; static PhysicsServer *physics_server = NULL; @@ -109,11 +115,12 @@ static bool _start_success = false; // Drivers -static int video_driver_idx = -1; +static int display_driver_idx = -1; static int audio_driver_idx = -1; // Engine config/tools +static bool single_window = false; static bool editor = false; static bool project_manager = false; static String locale; @@ -126,7 +133,12 @@ static bool auto_build_solutions = false; // Display -static OS::VideoMode video_mode; +static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOWED; +static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE; +static uint32_t window_flags = 0; +static Size2i window_size = Size2i(1024, 600); +static bool window_vsync_via_compositor = false; + static int init_screen = -1; static bool init_fullscreen = false; static bool init_maximized = false; @@ -191,6 +203,7 @@ void initialize_physics() { } void finalize_physics() { + physics_server->finish(); memdelete(physics_server); @@ -198,6 +211,14 @@ void finalize_physics() { memdelete(physics_2d_server); } +void finalize_display() { + + visual_server->finish(); + memdelete(visual_server); + + memdelete(display_server); +} + void initialize_navigation_server() { ERR_FAIL_COND(navigation_server != NULL); @@ -251,20 +272,25 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n"); OS::get_singleton()->print(" --remote-fs-password <password> Password for remote filesystem.\n"); OS::get_singleton()->print(" --audio-driver <driver> Audio driver ("); - for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) { + for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { if (i != 0) OS::get_singleton()->print(", "); - OS::get_singleton()->print("'%s'", OS::get_singleton()->get_audio_driver_name(i)); + OS::get_singleton()->print("'%s'", AudioDriverManager::get_driver(i)->get_name()); } OS::get_singleton()->print(").\n"); - OS::get_singleton()->print(" --video-driver <driver> Video driver ("); - for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) { - if (i != 0) - OS::get_singleton()->print(", "); - OS::get_singleton()->print("'%s'", OS::get_singleton()->get_video_driver_name(i)); + OS::get_singleton()->print(" --display-driver <driver> Display driver (and rendering driver):\n"); + for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { + OS::get_singleton()->print("\t\t'%s' (", DisplayServer::get_create_function_name(i)); + Vector<String> rd = DisplayServer::get_create_function_rendering_drivers(i); + for (int j = 0; j < rd.size(); j++) { + if (j > 0) { + OS::get_singleton()->print(", "); + } + OS::get_singleton()->print("'%s'", rd[j].utf8().get_data()); + } + OS::get_singleton()->print(")\n"); } - OS::get_singleton()->print(").\n"); - OS::get_singleton()->print("\n"); + OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n"); #ifndef SERVER_ENABLED OS::get_singleton()->print("Display options:\n"); @@ -278,6 +304,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n"); OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n"); OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n"); + OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n"); OS::get_singleton()->print("\n"); #endif @@ -353,7 +380,7 @@ void Main::print_help(const char *p_binary) { Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) { - OS::get_singleton()->initialize_core(); + OS::get_singleton()->initialize(); engine = memnew(Engine); @@ -403,7 +430,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph I = args.front(); - String video_driver = ""; + String display_driver = ""; String audio_driver = ""; String project_path = "."; bool upwards = false; @@ -423,6 +450,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #ifdef TOOLS_ENABLED bool found_project = false; #endif + bool use_vsync = false; packed_data = PackedData::get_singleton(); if (!packed_data) @@ -469,8 +497,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph audio_driver = I->next()->get(); bool found = false; - for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) { - if (audio_driver == OS::get_singleton()->get_audio_driver_name(i)) { + for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { + if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) { found = true; } } @@ -478,14 +506,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (!found) { OS::get_singleton()->print("Unknown audio driver '%s', aborting.\nValid options are ", audio_driver.utf8().get_data()); - for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) { - if (i == OS::get_singleton()->get_audio_driver_count() - 1) { + for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { + if (i == AudioDriverManager::get_driver_count() - 1) { OS::get_singleton()->print(" and "); } else if (i != 0) { OS::get_singleton()->print(", "); } - OS::get_singleton()->print("'%s'", OS::get_singleton()->get_audio_driver_name(i)); + OS::get_singleton()->print("'%s'", AudioDriverManager::get_driver(i)->get_name()); } OS::get_singleton()->print(".\n"); @@ -499,30 +527,30 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph goto error; } - } else if (I->get() == "--video-driver") { // force video driver + } else if (I->get() == "--display-driver") { // force video driver if (I->next()) { - video_driver = I->next()->get(); + display_driver = I->next()->get(); bool found = false; - for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) { - if (video_driver == OS::get_singleton()->get_video_driver_name(i)) { + for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { + if (display_driver == DisplayServer::get_create_function_name(i)) { found = true; } } if (!found) { - OS::get_singleton()->print("Unknown video driver '%s', aborting.\nValid options are ", video_driver.utf8().get_data()); + OS::get_singleton()->print("Unknown display driver '%s', aborting.\nValid options are ", display_driver.utf8().get_data()); - for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) { - if (i == OS::get_singleton()->get_video_driver_count() - 1) { + for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { + if (i == DisplayServer::get_create_function_count() - 1) { OS::get_singleton()->print(" and "); } else if (i != 0) { OS::get_singleton()->print(", "); } - OS::get_singleton()->print("'%s'", OS::get_singleton()->get_video_driver_name(i)); + OS::get_singleton()->print("'%s'", DisplayServer::get_create_function_name(i)); } OS::get_singleton()->print(".\n"); @@ -542,7 +570,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get() == "-m" || I->get() == "--maximized") { // force maximized window init_maximized = true; - video_mode.maximized = true; + window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED; } else if (I->get() == "-w" || I->get() == "--windowed") { // force windowed window @@ -550,6 +578,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get() == "--gpu-abort") { // force windowed window Engine::singleton->abort_on_gpu_errors = true; + } else if (I->get() == "--single-window") { // force single window + + single_window = true; } else if (I->get() == "-t" || I->get() == "--always-on-top") { // force always-on-top window init_always_on_top = true; @@ -574,8 +605,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph goto error; } - video_mode.width = w; - video_mode.height = h; + window_size.width = w; + window_size.height = h; force_res = true; N = I->next()->next(); @@ -616,11 +647,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->set_no_window_mode(true); } else if (I->get() == "--enable-vsync-via-compositor") { - video_mode.vsync_via_compositor = true; + window_vsync_via_compositor = true; saw_vsync_via_compositor_override = true; } else if (I->get() == "--disable-vsync-via-compositor") { - video_mode.vsync_via_compositor = false; + window_vsync_via_compositor = false; saw_vsync_via_compositor_override = true; #endif } else if (I->get() == "--profiling") { // enable profiling @@ -874,7 +905,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #else const String error_msg = "Error: Couldn't load project data at path \"" + project_path + "\". Is the .pck file missing?\nIf you've renamed the executable, the associated .pck file should also be renamed to match the executable's name (without the extension).\n"; OS::get_singleton()->print("%s", error_msg.ascii().get_data()); - OS::get_singleton()->alert(error_msg); + DisplayServer::get_singleton()->alert(error_msg); goto error; #endif @@ -917,7 +948,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph main_args.push_back("--editor"); if (!init_windowed) { init_maximized = true; - video_mode.maximized = true; + window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED; } } @@ -960,8 +991,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF("rendering/quality/driver/driver_name", "Vulkan"); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name", PropertyInfo(Variant::STRING, "rendering/quality/driver/driver_name", PROPERTY_HINT_ENUM, "Vulkan,GLES2")); - if (video_driver == "") { - video_driver = GLOBAL_GET("rendering/quality/driver/driver_name"); + if (display_driver == "") { + display_driver = GLOBAL_GET("rendering/quality/driver/driver_name"); } // Assigning here even though it's GLES2-specific, to be sure that it appears in docs @@ -983,48 +1014,58 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (use_custom_res) { if (!force_res) { - video_mode.width = GLOBAL_GET("display/window/size/width"); - video_mode.height = GLOBAL_GET("display/window/size/height"); + window_size.width = GLOBAL_GET("display/window/size/width"); + window_size.height = GLOBAL_GET("display/window/size/height"); if (globals->has_setting("display/window/size/test_width") && globals->has_setting("display/window/size/test_height")) { int tw = globals->get("display/window/size/test_width"); if (tw > 0) { - video_mode.width = tw; + window_size.width = tw; } int th = globals->get("display/window/size/test_height"); if (th > 0) { - video_mode.height = th; + window_size.height = th; } } } - video_mode.resizable = GLOBAL_GET("display/window/size/resizable"); - video_mode.borderless_window = GLOBAL_GET("display/window/size/borderless"); - video_mode.fullscreen = GLOBAL_GET("display/window/size/fullscreen"); - video_mode.always_on_top = GLOBAL_GET("display/window/size/always_on_top"); + if (!bool(GLOBAL_GET("display/window/size/resizable"))) { + window_flags |= DisplayServer::WINDOW_FLAG_RESIZE_DISABLED_BIT; + } + if (bool(GLOBAL_GET("display/window/size/borderless"))) { + window_flags |= DisplayServer::WINDOW_FLAG_BORDERLESS_BIT; + } + if (bool(GLOBAL_GET("display/window/size/fullscreen"))) { + window_mode = DisplayServer::WINDOW_MODE_FULLSCREEN; + } + + if (bool(GLOBAL_GET("display/window/size/always_on_top"))) { + window_flags |= DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP; + } } if (!force_lowdpi) { OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false); } - video_mode.use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true); - OS::get_singleton()->_use_vsync = video_mode.use_vsync; + use_vsync = GLOBAL_DEF_RST("display/window/vsync/use_vsync", true); + OS::get_singleton()->_use_vsync = use_vsync; if (!saw_vsync_via_compositor_override) { // If one of the command line options to enable/disable vsync via the // window compositor ("--enable-vsync-via-compositor" or // "--disable-vsync-via-compositor") was present then it overrides the // project setting. - video_mode.vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false); + window_vsync_via_compositor = GLOBAL_DEF("display/window/vsync/vsync_via_compositor", false); } - OS::get_singleton()->_vsync_via_compositor = video_mode.vsync_via_compositor; + OS::get_singleton()->_vsync_via_compositor = window_vsync_via_compositor; + /* todo restore OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false); - +*/ GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2); GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3); @@ -1049,26 +1090,26 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph /* Determine audio and video drivers */ - for (int i = 0; i < OS::get_singleton()->get_video_driver_count(); i++) { + for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { - if (video_driver == OS::get_singleton()->get_video_driver_name(i)) { + if (display_driver == DisplayServer::get_create_function_name(i)) { - video_driver_idx = i; + display_driver_idx = i; break; } } - if (video_driver_idx < 0) { - video_driver_idx = 0; + if (display_driver_idx < 0) { + display_driver_idx = 0; } if (audio_driver == "") { // specified in project.godot - audio_driver = GLOBAL_DEF_RST("audio/driver", OS::get_singleton()->get_audio_driver_name(0)); + audio_driver = GLOBAL_DEF_RST("audio/driver", AudioDriverManager::get_driver(0)->get_name()); } - for (int i = 0; i < OS::get_singleton()->get_audio_driver_count(); i++) { + for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { - if (audio_driver == OS::get_singleton()->get_audio_driver_name(i)) { + if (audio_driver == AudioDriverManager::get_driver(i)->get_name()) { audio_driver_idx = i; break; @@ -1083,19 +1124,19 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph String orientation = GLOBAL_DEF("display/window/handheld/orientation", "landscape"); if (orientation == "portrait") - OS::get_singleton()->set_screen_orientation(OS::SCREEN_PORTRAIT); + window_orientation = DisplayServer::SCREEN_PORTRAIT; else if (orientation == "reverse_landscape") - OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_LANDSCAPE); + window_orientation = DisplayServer::SCREEN_REVERSE_LANDSCAPE; else if (orientation == "reverse_portrait") - OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_PORTRAIT); + window_orientation = DisplayServer::SCREEN_REVERSE_PORTRAIT; else if (orientation == "sensor_landscape") - OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_LANDSCAPE); + window_orientation = DisplayServer::SCREEN_SENSOR_LANDSCAPE; else if (orientation == "sensor_portrait") - OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_PORTRAIT); + window_orientation = DisplayServer::SCREEN_SENSOR_PORTRAIT; else if (orientation == "sensor") - OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR); + window_orientation = DisplayServer::SCREEN_SENSOR; else - OS::get_singleton()->set_screen_orientation(OS::SCREEN_LANDSCAPE); + window_orientation = DisplayServer::SCREEN_LANDSCAPE; } Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/common/physics_fps", 60)); @@ -1131,7 +1172,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph error: - video_driver = ""; + display_driver = ""; audio_driver = ""; project_path = ""; @@ -1183,15 +1224,64 @@ Error Main::setup2(Thread::ID p_main_tid_override) { Thread::_main_thread_id = p_main_tid_override; } - Error err = OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx); - if (err != OK) { - return err; + /* Initialize user data dir */ + + OS::get_singleton()->ensure_user_data_dir(); + + /* Initialize Input */ + + input = memnew(InputFilter); + + /* Iniitalize Display Server */ + + { + + String rendering_driver; // temp broken + + Error err; + display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err); + if (err != OK) { + //ok i guess we can't use this display server, try other ones + for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { + if (i == display_driver_idx) { + continue; //don't try the same twice + } + display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_flags, window_size, err); + if (err == OK) { + break; + } + } + } + + if (!display_server) { + ERR_PRINT("Unable to create DisplayServer, all display drivers failed."); + return err; + } + } + + if (display_server->has_feature(DisplayServer::FEATURE_ORIENTATION)) { + display_server->screen_set_orientation(window_orientation); + } + + /* Initialize Visual Server */ + + visual_server = memnew(VisualServerRaster); + if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) { + visual_server = memnew(VisualServerWrapMT(visual_server, OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD)); } + visual_server->init(); + + OS::get_singleton()->initialize_joypads(); + + /* Initialize Audio Driver */ + + AudioDriverManager::initialize(audio_driver_idx); + print_line(" "); //add a blank line for readability if (init_use_custom_pos) { - OS::get_singleton()->set_window_position(init_custom_pos); + display_server->window_set_position(init_custom_pos); } // right moment to create and initialize the audio server @@ -1213,21 +1303,21 @@ Error Main::setup2(Thread::ID p_main_tid_override) { #endif if (init_screen != -1) { - OS::get_singleton()->set_current_screen(init_screen); + DisplayServer::get_singleton()->window_set_current_screen(init_screen); } if (init_windowed) { //do none.. } else if (init_maximized) { - OS::get_singleton()->set_window_maximized(true); + DisplayServer::get_singleton()->window_set_mode(DisplayServer::WINDOW_MODE_MAXIMIZED); } else if (init_fullscreen) { - OS::get_singleton()->set_window_fullscreen(true); + DisplayServer::get_singleton()->window_set_mode(DisplayServer::WINDOW_MODE_FULLSCREEN); } if (init_always_on_top) { - OS::get_singleton()->set_window_always_on_top(true); + DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true); } if (allow_focus_steal_pid) { - OS::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid); + DisplayServer::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid); } register_server_types(); @@ -1277,7 +1367,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { #ifdef TOOLS_ENABLED Ref<Image> icon = memnew(Image(app_icon_png)); - OS::get_singleton()->set_icon(icon); + DisplayServer::get_singleton()->set_icon(icon); #endif } @@ -1294,10 +1384,17 @@ Error Main::setup2(Thread::ID p_main_tid_override) { GLOBAL_DEF("application/config/windows_native_icon", String()); ProjectSettings::get_singleton()->set_custom_property_info("application/config/windows_native_icon", PropertyInfo(Variant::STRING, "application/config/windows_native_icon", PROPERTY_HINT_FILE, "*.ico")); - InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); + InputFilter *id = InputFilter::get_singleton(); if (id) { if (bool(GLOBAL_DEF("input_devices/pointing/emulate_touch_from_mouse", false)) && !(editor || project_manager)) { - if (!OS::get_singleton()->has_touchscreen_ui_hint()) { + + bool found_touchscreen = false; + for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) { + if (DisplayServer::get_singleton()->screen_is_touchscreen(i)) { + found_touchscreen = true; + } + } + if (!found_touchscreen) { //only if no touchscreen ui hint, set emulation id->set_emulate_touch_from_mouse(true); } @@ -1322,7 +1419,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { Ref<Texture2D> cursor = ResourceLoader::load(ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image")); if (cursor.is_valid()) { Vector2 hotspot = ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image_hotspot"); - Input::get_singleton()->set_custom_mouse_cursor(cursor, Input::CURSOR_ARROW, hotspot); + InputFilter::get_singleton()->set_custom_mouse_cursor(cursor, InputFilter::CURSOR_ARROW, hotspot); } } #ifdef TOOLS_ENABLED @@ -1589,7 +1686,7 @@ bool Main::start() { if (!main_loop) { if (!ClassDB::class_exists(main_loop_type)) { - OS::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type); + DisplayServer::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type); return false; } else { @@ -1618,6 +1715,9 @@ bool Main::start() { } #endif + if (single_window) { + sml->get_root()->set_embed_subwindows_hint(true); + } ResourceLoader::add_custom_loaders(); ResourceSaver::add_custom_savers(); @@ -1727,31 +1827,32 @@ bool Main::start() { String stretch_mode = GLOBAL_DEF("display/window/stretch/mode", "disabled"); String stretch_aspect = GLOBAL_DEF("display/window/stretch/aspect", "ignore"); Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0)); - real_t stretch_shrink = GLOBAL_DEF("display/window/stretch/shrink", 1.0); - SceneTree::StretchMode sml_sm = SceneTree::STRETCH_MODE_DISABLED; - if (stretch_mode == "2d") - sml_sm = SceneTree::STRETCH_MODE_2D; - else if (stretch_mode == "viewport") - sml_sm = SceneTree::STRETCH_MODE_VIEWPORT; + Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED; + if (stretch_mode == "objects") + cs_sm = Window::CONTENT_SCALE_MODE_OBJECTS; + else if (stretch_mode == "pixels") + cs_sm = Window::CONTENT_SCALE_MODE_PIXELS; - SceneTree::StretchAspect sml_aspect = SceneTree::STRETCH_ASPECT_IGNORE; + Window::ContentScaleAspect cs_aspect = Window::CONTENT_SCALE_ASPECT_IGNORE; if (stretch_aspect == "keep") - sml_aspect = SceneTree::STRETCH_ASPECT_KEEP; + cs_aspect = Window::CONTENT_SCALE_ASPECT_KEEP; else if (stretch_aspect == "keep_width") - sml_aspect = SceneTree::STRETCH_ASPECT_KEEP_WIDTH; + cs_aspect = Window::CONTENT_SCALE_ASPECT_KEEP_WIDTH; else if (stretch_aspect == "keep_height") - sml_aspect = SceneTree::STRETCH_ASPECT_KEEP_HEIGHT; + cs_aspect = Window::CONTENT_SCALE_ASPECT_KEEP_HEIGHT; else if (stretch_aspect == "expand") - sml_aspect = SceneTree::STRETCH_ASPECT_EXPAND; + cs_aspect = Window::CONTENT_SCALE_ASPECT_EXPAND; - sml->set_screen_stretch(sml_sm, sml_aspect, stretch_size, stretch_shrink); + sml->get_root()->set_content_scale_mode(cs_sm); + sml->get_root()->set_content_scale_aspect(cs_aspect); + sml->get_root()->set_content_scale_size(stretch_size); sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true)); sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); String appname = ProjectSettings::get_singleton()->get("application/config/name"); appname = TranslationServer::get_singleton()->translate(appname); - OS::get_singleton()->set_window_title(appname); + DisplayServer::get_singleton()->window_set_title(appname); int shadow_atlas_size = GLOBAL_GET("rendering/quality/shadow_atlas/size"); int shadow_atlas_q0_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_0_subdiv"); @@ -1769,7 +1870,7 @@ bool Main::start() { sml->get_root()->set_snap_controls_to_pixels(snap_controls); bool font_oversampling = GLOBAL_DEF("rendering/quality/dynamic_fonts/use_oversampling", true); - sml->set_use_font_oversampling(font_oversampling); + sml->get_root()->set_use_font_oversampling(font_oversampling); int texture_filter = GLOBAL_DEF("rendering/canvas_textures/default_texture_filter", 1); int texture_repeat = GLOBAL_DEF("rendering/canvas_textures/default_texture_repeat", 0); @@ -1838,11 +1939,11 @@ bool Main::start() { if (serr != OK) ERR_PRINT("Failed to load scene"); } - OS::get_singleton()->set_context(OS::CONTEXT_EDITOR); + DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_EDITOR); } #endif if (!editor) { - OS::get_singleton()->set_context(OS::CONTEXT_ENGINE); + DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_ENGINE); } } @@ -1863,7 +1964,7 @@ bool Main::start() { #ifdef OSX_ENABLED String mac_iconpath = GLOBAL_DEF("application/config/macos_native_icon", "Variant()"); if (mac_iconpath != "") { - OS::get_singleton()->set_native_icon(mac_iconpath); + DisplayServer::get_singleton()->set_native_icon(mac_iconpath); hasicon = true; } #endif @@ -1871,7 +1972,7 @@ bool Main::start() { #ifdef WINDOWS_ENABLED String win_iconpath = GLOBAL_DEF("application/config/windows_native_icon", "Variant()"); if (win_iconpath != "") { - OS::get_singleton()->set_native_icon(win_iconpath); + DisplayServer::get_singleton()->set_native_icon(win_iconpath); hasicon = true; } #endif @@ -1881,7 +1982,7 @@ bool Main::start() { Ref<Image> icon; icon.instance(); if (ImageLoader::load_image(iconpath, icon) == OK) { - OS::get_singleton()->set_icon(icon); + DisplayServer::get_singleton()->set_icon(icon); hasicon = true; } } @@ -1896,14 +1997,14 @@ bool Main::start() { ProgressDialog *progress_dialog = memnew(ProgressDialog); pmanager->add_child(progress_dialog); sml->get_root()->add_child(pmanager); - OS::get_singleton()->set_context(OS::CONTEXT_PROJECTMAN); + DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_PROJECTMAN); project_manager = true; } if (project_manager || editor) { // Hide console window if requested (Windows-only). bool hide_console = EditorSettings::get_singleton()->get_setting("interface/editor/hide_console_window"); - OS::get_singleton()->set_console_visible(!hide_console); + DisplayServer::get_singleton()->console_set_visible(!hide_console); // Load SSL Certificates from Editor Settings (or builtin) Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String()); @@ -1913,7 +2014,7 @@ bool Main::start() { if (!hasicon) { Ref<Image> icon = memnew(Image(app_icon_png)); - OS::get_singleton()->set_icon(icon); + DisplayServer::get_singleton()->set_icon(icon); } OS::get_singleton()->set_main_loop(main_loop); @@ -2030,7 +2131,7 @@ bool Main::iteration() { VisualServer::get_singleton()->sync(); //sync if still drawing from previous frames. - if (OS::get_singleton()->can_draw() && !disable_render_loop) { + if (DisplayServer::get_singleton()->can_any_window_draw() && !disable_render_loop) { if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { if (VisualServer::get_singleton()->has_changed()) { @@ -2085,7 +2186,7 @@ bool Main::iteration() { if (fixed_fps != -1) return exit; - if (OS::get_singleton()->is_in_low_processor_usage_mode() || !OS::get_singleton()->can_draw()) + if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->can_any_window_draw()) OS::get_singleton()->delay_usec(OS::get_singleton()->get_low_processor_usage_mode_sleep_usec()); //apply some delay to force idle time else { uint32_t frame_delay = Engine::get_singleton()->get_frame_delay(); @@ -2182,8 +2283,14 @@ void Main::cleanup() { } OS::get_singleton()->finalize(); + finalize_physics(); finalize_navigation_server(); + finalize_display(); + + if (input) { + memdelete(input); + } if (packed_data) memdelete(packed_data); diff --git a/main/main_builders.py b/main/main_builders.py index e24070ccc3..aebac2b022 100644 --- a/main/main_builders.py +++ b/main/main_builders.py @@ -63,67 +63,5 @@ def make_app_icon(target, source, env): g.write("#endif") -def make_default_controller_mappings(target, source, env): - dst = target[0] - g = open(dst, "w") - - g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") - g.write("#include \"core/typedefs.h\"\n") - g.write("#include \"main/default_controller_mappings.h\"\n") - - # ensure mappings have a consistent order - platform_mappings = OrderedDict() - for src_path in source: - with open(src_path, "r") as f: - # read mapping file and skip header - mapping_file_lines = f.readlines()[2:] - - current_platform = None - for line in mapping_file_lines: - if not line: - continue - line = line.strip() - if len(line) == 0: - continue - if line[0] == "#": - current_platform = line[1:].strip() - if current_platform not in platform_mappings: - platform_mappings[current_platform] = {} - elif current_platform: - line_parts = line.split(",") - guid = line_parts[0] - if guid in platform_mappings[current_platform]: - g.write("// WARNING - DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(src_path, current_platform, platform_mappings[current_platform][guid])) - valid_mapping = True - for input_map in line_parts[2:]: - if "+" in input_map or "-" in input_map or "~" in input_map: - g.write("// WARNING - DISCARDED UNSUPPORTED MAPPING TYPE FROM DATABASE {}: {} {}\n".format(src_path, current_platform, line)) - valid_mapping = False - break - if valid_mapping: - platform_mappings[current_platform][guid] = line - - platform_variables = { - "Linux": "#if X11_ENABLED", - "Windows": "#ifdef WINDOWS_ENABLED", - "Mac OS X": "#ifdef OSX_ENABLED", - "Android": "#if defined(__ANDROID__)", - "iOS": "#ifdef IPHONE_ENABLED", - "Javascript": "#ifdef JAVASCRIPT_ENABLED", - "UWP": "#ifdef UWP_ENABLED", - } - - g.write("const char* DefaultControllerMappings::mappings[] = {\n") - for platform, mappings in platform_mappings.items(): - variable = platform_variables[platform] - g.write("{}\n".format(variable)) - for mapping in mappings.values(): - g.write("\t\"{}\",\n".format(mapping)) - g.write("#endif\n") - - g.write("\tNULL\n};\n") - g.close() - - if __name__ == '__main__': subprocess_main(globals()) diff --git a/main/tests/test_gui.cpp b/main/tests/test_gui.cpp index f0b00aeeae..5ad1b2fe31 100644 --- a/main/tests/test_gui.cpp +++ b/main/tests/test_gui.cpp @@ -54,7 +54,7 @@ #include "scene/main/scene_tree.h" #include "scene/3d/camera.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" namespace TestGUI { @@ -220,7 +220,7 @@ public: richtext->add_text("faeries.\n"); richtext->pop(); richtext->add_text("In this new episode, we will attempt to "); - richtext->push_font(richtext->get_font("mono_font", "Fonts")); + richtext->push_font(richtext->get_theme_font("mono_font", "Fonts")); richtext->push_color(Color(0.7, 0.5, 1.0)); richtext->add_text("deliver something nice"); richtext->pop(); diff --git a/main/tests/test_physics.cpp b/main/tests/test_physics.cpp index 4931d42674..7727af6ad1 100644 --- a/main/tests/test_physics.cpp +++ b/main/tests/test_physics.cpp @@ -36,6 +36,7 @@ #include "core/os/main_loop.h" #include "core/os/os.h" #include "core/print_string.h" +#include "servers/display_server.h" #include "servers/physics_server.h" #include "servers/visual_server.h" @@ -313,7 +314,7 @@ public: camera = vs->camera_create(); RID viewport = vs->viewport_create(); - Size2i screen_size = OS::get_singleton()->get_window_size(); + Size2i screen_size = DisplayServer::get_singleton()->window_get_size(); vs->viewport_set_size(viewport, screen_size.x, screen_size.y); vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size)); vs->viewport_set_active(viewport, true); diff --git a/main/tests/test_physics_2d.cpp b/main/tests/test_physics_2d.cpp index 160c25f43a..4403e40b76 100644 --- a/main/tests/test_physics_2d.cpp +++ b/main/tests/test_physics_2d.cpp @@ -35,6 +35,7 @@ #include "core/os/os.h" #include "core/print_string.h" #include "scene/resources/texture.h" +#include "servers/display_server.h" #include "servers/physics_2d_server.h" #include "servers/visual_server.h" @@ -354,7 +355,7 @@ public: RID vp = vs->viewport_create(); canvas = vs->canvas_create(); - Size2i screen_size = OS::get_singleton()->get_window_size(); + Size2i screen_size = DisplayServer::get_singleton()->window_get_size(); vs->viewport_attach_canvas(vp, canvas); vs->viewport_set_size(vp, screen_size.x, screen_size.y); vs->viewport_attach_to_screen(vp, Rect2(Vector2(), screen_size)); diff --git a/main/tests/test_render.cpp b/main/tests/test_render.cpp index 62239a5cb5..0fbc5ea697 100644 --- a/main/tests/test_render.cpp +++ b/main/tests/test_render.cpp @@ -36,6 +36,7 @@ #include "core/os/main_loop.h" #include "core/os/os.h" #include "core/print_string.h" +#include "servers/display_server.h" #include "servers/visual_server.h" #define OBJECT_COUNT 50 @@ -163,7 +164,7 @@ public: // vs->camera_set_perspective( camera, 60.0,0.1, 100.0 ); viewport = vs->viewport_create(); - Size2i screen_size = OS::get_singleton()->get_window_size(); + Size2i screen_size = DisplayServer::get_singleton()->window_get_size(); vs->viewport_set_size(viewport, screen_size.x, screen_size.y); vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size)); vs->viewport_set_active(viewport, true); diff --git a/modules/arkit/arkit_interface.mm b/modules/arkit/arkit_interface.mm index 39447e8dab..90d9d7b03a 100644 --- a/modules/arkit/arkit_interface.mm +++ b/modules/arkit/arkit_interface.mm @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/os.h" #include "scene/resources/surface_tool.h" #include "servers/visual/visual_server_globals.h" diff --git a/modules/assimp/SCsub b/modules/assimp/SCsub index 90cdd7f5fc..cef2396dfb 100644 --- a/modules/assimp/SCsub +++ b/modules/assimp/SCsub @@ -75,7 +75,7 @@ if True: # env['builtin_assimp']: if(env['platform'] == 'windows'): env_assimp.Append(CPPDEFINES=['PLATFORM_WINDOWS']) env_assimp.Append(CPPDEFINES=[('PLATFORM', 'WINDOWS')]) - elif(env['platform'] == 'x11'): + elif(env['platform'] == 'linuxbsd'): env_assimp.Append(CPPDEFINES=['PLATFORM_LINUX']) env_assimp.Append(CPPDEFINES=[('PLATFORM', 'LINUX')]) elif(env['platform'] == 'osx'): diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index a033c2b7f9..0f0c864df2 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "arvr_interface_gdnative.h" -#include "main/input_default.h" +#include "core/input/input_filter.h" #include "servers/arvr/arvr_positional_tracker.h" #include "servers/visual/visual_server_globals.h" @@ -317,7 +317,7 @@ godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL_V(arvr_server, 0); - InputDefault *input = (InputDefault *)Input::get_singleton(); + InputFilter *input = InputFilter::get_singleton(); ERR_FAIL_NULL_V(input, 0); ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker); @@ -356,7 +356,7 @@ void GDAPI godot_arvr_remove_controller(godot_int p_controller_id) { ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL(arvr_server); - InputDefault *input = (InputDefault *)Input::get_singleton(); + InputFilter *input = InputFilter::get_singleton(); ERR_FAIL_NULL(input); ARVRPositionalTracker *remove_tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); @@ -394,7 +394,7 @@ void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL(arvr_server); - InputDefault *input = (InputDefault *)Input::get_singleton(); + InputFilter *input = InputFilter::get_singleton(); ERR_FAIL_NULL(input); ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); @@ -410,14 +410,14 @@ void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL(arvr_server); - InputDefault *input = (InputDefault *)Input::get_singleton(); + InputFilter *input = InputFilter::get_singleton(); ERR_FAIL_NULL(input); ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id); if (tracker != NULL) { int joyid = tracker->get_joy_id(); if (joyid != -1) { - InputDefault::JoyAxis jx; + InputFilter::JoyAxis jx; jx.min = p_can_be_negative ? -1 : 0; jx.value = p_value; input->joy_axis(joyid, p_axis, jx); diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp index db90199e63..9b4c3c794e 100644 --- a/modules/gdnative/gdnative_library_editor_plugin.cpp +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -77,9 +77,9 @@ void GDNativeLibraryEditor::_update_tree() { platform->set_text(0, E->get().name); platform->set_metadata(0, E->get().library_extension); - platform->set_custom_bg_color(0, get_color("prop_category", "Editor")); - platform->set_custom_bg_color(1, get_color("prop_category", "Editor")); - platform->set_custom_bg_color(2, get_color("prop_category", "Editor")); + platform->set_custom_bg_color(0, get_theme_color("prop_category", "Editor")); + platform->set_custom_bg_color(1, get_theme_color("prop_category", "Editor")); + platform->set_custom_bg_color(2, get_theme_color("prop_category", "Editor")); platform->set_selectable(0, false); platform->set_expand_right(0, true); @@ -91,31 +91,31 @@ void GDNativeLibraryEditor::_update_tree() { bit->set_text(0, it->get()); bit->set_metadata(0, target); bit->set_selectable(0, false); - bit->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); + bit->set_custom_bg_color(0, get_theme_color("prop_subsection", "Editor")); - bit->add_button(1, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry")); + bit->add_button(1, get_theme_icon("Folder", "EditorIcons"), BUTTON_SELECT_LIBRARY, false, TTR("Select the dynamic library for this entry")); String file = entry_configs[target].library; if (!file.empty()) { - bit->add_button(1, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear")); + bit->add_button(1, get_theme_icon("Clear", "EditorIcons"), BUTTON_CLEAR_LIBRARY, false, TTR("Clear")); } bit->set_text(1, file); - bit->add_button(2, get_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry")); + bit->add_button(2, get_theme_icon("Folder", "EditorIcons"), BUTTON_SELECT_DEPENDENCES, false, TTR("Select dependencies of the library for this entry")); Array files = entry_configs[target].dependencies; if (files.size()) { - bit->add_button(2, get_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear")); + bit->add_button(2, get_theme_icon("Clear", "EditorIcons"), BUTTON_CLEAR_DEPENDENCES, false, TTR("Clear")); } bit->set_text(2, Variant(files)); - bit->add_button(3, get_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up")); - bit->add_button(3, get_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down")); - bit->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry")); + bit->add_button(3, get_theme_icon("MoveUp", "EditorIcons"), BUTTON_MOVE_UP, false, TTR("Move Up")); + bit->add_button(3, get_theme_icon("MoveDown", "EditorIcons"), BUTTON_MOVE_DOWN, false, TTR("Move Down")); + bit->add_button(3, get_theme_icon("Remove", "EditorIcons"), BUTTON_ERASE_ENTRY, false, TTR("Remove current entry")); } TreeItem *new_arch = tree->create_item(platform); new_arch->set_text(0, TTR("Double click to create a new entry")); new_arch->set_text_align(0, TreeItem::ALIGN_CENTER); - new_arch->set_custom_color(0, get_color("accent_color", "Editor")); + new_arch->set_custom_color(0, get_theme_color("accent_color", "Editor")); new_arch->set_expand_right(0, true); new_arch->set_metadata(1, E->key()); @@ -133,15 +133,15 @@ void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { if (id == BUTTON_SELECT_LIBRARY || id == BUTTON_SELECT_DEPENDENCES) { - EditorFileDialog::Mode mode = EditorFileDialog::MODE_OPEN_FILE; + EditorFileDialog::FileMode mode = EditorFileDialog::FILE_MODE_OPEN_FILE; if (id == BUTTON_SELECT_DEPENDENCES) - mode = EditorFileDialog::MODE_OPEN_FILES; + mode = EditorFileDialog::FILE_MODE_OPEN_FILES; file_dialog->set_meta("target", target); file_dialog->set_meta("section", section); file_dialog->clear_filters(); file_dialog->add_filter(Object::cast_to<TreeItem>(item)->get_parent()->get_metadata(0)); - file_dialog->set_mode(mode); + file_dialog->set_file_mode(mode); file_dialog->popup_centered_ratio(); } else if (id == BUTTON_CLEAR_LIBRARY) { @@ -372,7 +372,7 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { file_dialog = memnew(EditorFileDialog); file_dialog->set_access(EditorFileDialog::ACCESS_RESOURCES); - file_dialog->set_resizable(true); + //file_dialog->set_resizable(true); add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &GDNativeLibraryEditor::_on_library_selected)); file_dialog->connect("files_selected", callable_mp(this, &GDNativeLibraryEditor::_on_dependencies_selected)); @@ -382,7 +382,7 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { new_architecture_dialog->set_title(TTR("Add an architecture entry")); new_architecture_input = memnew(LineEdit); new_architecture_dialog->add_child(new_architecture_input); - new_architecture_dialog->set_custom_minimum_size(Vector2(300, 80) * EDSCALE); + // new_architecture_dialog->set_custom_minimum_size(Vector2(300, 80) * EDSCALE); new_architecture_input->set_anchors_and_margins_preset(PRESET_HCENTER_WIDE, PRESET_MODE_MINSIZE, 5 * EDSCALE); new_architecture_dialog->get_ok()->connect("pressed", callable_mp(this, &GDNativeLibraryEditor::_on_create_new_entry)); } diff --git a/modules/gdnative/nativescript/SCsub b/modules/gdnative/nativescript/SCsub index 92c9d6630d..c28a1c8659 100644 --- a/modules/gdnative/nativescript/SCsub +++ b/modules/gdnative/nativescript/SCsub @@ -5,5 +5,5 @@ Import('env_gdnative') env_gdnative.add_source_files(env.modules_sources, '*.cpp') -if "platform" in env and env["platform"] in ["x11", "iphone"]: +if "platform" in env and env["platform"] in ["linuxbsd", "iphone"]: env.Append(LINKFLAGS=["-rdynamic"]) diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index fb88479ca3..80aebaccd1 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1827,7 +1827,7 @@ void NativeReloadNode::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { - case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_FOCUS_OUT: { if (unloaded) break; @@ -1862,7 +1862,7 @@ void NativeReloadNode::_notification(int p_what) { } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_FOCUS_IN: { if (!unloaded) break; diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp index e6ff7a7afa..05feb97131 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp @@ -50,8 +50,8 @@ void NavigationMeshEditor::_notification(int p_option) { if (p_option == NOTIFICATION_ENTER_TREE) { - button_bake->set_icon(get_icon("Bake", "EditorIcons")); - button_reset->set_icon(get_icon("Reload", "EditorIcons")); + button_bake->set_icon(get_theme_icon("Bake", "EditorIcons")); + button_reset->set_icon(get_theme_icon("Reload", "EditorIcons")); } } @@ -61,7 +61,7 @@ void NavigationMeshEditor::_bake_pressed() { ERR_FAIL_COND(!node); if (!node->get_navigation_mesh().is_valid()) { err_dialog->set_text(TTR("A NavigationMesh resource must be set or created for this node to work.")); - err_dialog->popup_centered_minsize(); + err_dialog->popup_centered(); return; } diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 687e1785be..0aca4dbc5e 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -358,11 +358,11 @@ List<String> GDScriptSyntaxHighlighter::get_supported_languages() { } void GDScriptSyntaxHighlighter::_update_cache() { - font_color = text_editor->get_color("font_color"); - symbol_color = text_editor->get_color("symbol_color"); - function_color = text_editor->get_color("function_color"); - number_color = text_editor->get_color("number_color"); - member_color = text_editor->get_color("member_variable_color"); + font_color = text_editor->get_theme_color("font_color"); + symbol_color = text_editor->get_theme_color("symbol_color"); + function_color = text_editor->get_theme_color("function_color"); + number_color = text_editor->get_theme_color("number_color"); + member_color = text_editor->get_theme_color("member_variable_color"); const String text_editor_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme"); const bool default_theme = text_editor_color_theme == "Default"; diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index d5723fd20f..fbf8ef2f8f 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -35,6 +35,7 @@ #include "editor/plugins/script_text_editor.h" #include "gdscript_extend_parser.h" #include "gdscript_language_protocol.h" +#include "servers/display_server.h" void GDScriptTextDocument::_bind_methods() { ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen); @@ -419,7 +420,8 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id); - OS::get_singleton()->move_window_to_foreground(); + + DisplayServer::get_singleton()->window_move_to_foreground(); } Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &p_location, List<const lsp::DocumentSymbol *> &r_list) { diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index a656ee8b63..1917a69388 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "grid_map_editor_plugin.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/plugins/spatial_editor_plugin.h" @@ -37,6 +37,7 @@ #include "core/math/geometry.h" #include "core/os/keyboard.h" +#include "scene/main/window.h" void GridMapEditor::_node_removed(Node *p_node) { @@ -1146,8 +1147,8 @@ void GridMapEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - options->set_icon(get_icon("GridMap", "EditorIcons")); - search_box->set_right_icon(get_icon("Search", "EditorIcons")); + options->set_icon(get_theme_icon("GridMap", "EditorIcons")); + search_box->set_right_icon(get_theme_icon("Search", "EditorIcons")); } break; } } @@ -1226,7 +1227,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { floor->set_min(-32767); floor->set_max(32767); floor->set_step(1); - floor->get_line_edit()->add_constant_override("minimum_spaces", 16); + floor->get_line_edit()->add_theme_constant_override("minimum_spaces", 16); spatial_editor_hb->add_child(floor); floor->connect("value_changed", callable_mp(this, &GridMapEditor::_floor_changed)); @@ -1304,14 +1305,14 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { mode_thumbnail = memnew(ToolButton); mode_thumbnail->set_toggle_mode(true); mode_thumbnail->set_pressed(true); - mode_thumbnail->set_icon(p_editor->get_gui_base()->get_icon("FileThumbnail", "EditorIcons")); + mode_thumbnail->set_icon(p_editor->get_gui_base()->get_theme_icon("FileThumbnail", "EditorIcons")); hb->add_child(mode_thumbnail); mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL)); mode_list = memnew(ToolButton); mode_list->set_toggle_mode(true); mode_list->set_pressed(false); - mode_list->set_icon(p_editor->get_gui_base()->get_icon("FileList", "EditorIcons")); + mode_list->set_icon(p_editor->get_gui_base()->get_theme_icon("FileList", "EditorIcons")); hb->add_child(mode_list); mode_list->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_LIST)); diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 2f1d95cd42..1b253d3699 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -29,8 +29,9 @@ /*************************************************************************/ #include "mobile_vr_interface.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/os.h" +#include "servers/display_server.h" #include "servers/visual/visual_server_globals.h" StringName MobileVRInterface::get_name() const { @@ -117,7 +118,7 @@ void MobileVRInterface::set_position_from_sensors() { float delta_time = (double)ticks_elapsed / 1000000.0; // few things we need - Input *input = Input::get_singleton(); + InputFilter *input = InputFilter::get_singleton(); Vector3 down(0.0, -1.0, 0.0); // Down is Y negative Vector3 north(0.0, 0.0, 1.0); // North is Z positive @@ -339,7 +340,7 @@ Size2 MobileVRInterface::get_render_targetsize() { _THREAD_SAFE_METHOD_ // we use half our window size - Size2 target_size = OS::get_singleton()->get_window_size(); + Size2 target_size = DisplayServer::get_singleton()->window_get_size(); target_size.x *= 0.5 * oversample; target_size.y *= oversample; diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 9a6198f13a..4e101583ef 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -45,11 +45,11 @@ def copy_file(src_dir, dst_dir, name): def is_desktop(platform): - return platform in ['windows', 'osx', 'x11', 'server', 'uwp', 'haiku'] + return platform in ['windows', 'osx', 'linuxbsd', 'server', 'uwp', 'haiku'] def is_unix_like(platform): - return platform in ['osx', 'x11', 'server', 'android', 'haiku'] + return platform in ['osx', 'linuxbsd', 'server', 'android', 'haiku'] def module_supports_tools_on(platform): diff --git a/modules/mono/config.py b/modules/mono/config.py index a5d3059ecc..3ee1618366 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -3,7 +3,7 @@ def can_build(env, platform): def configure(env): - if env['platform'] not in ['windows', 'osx', 'x11', 'server', 'android', 'haiku', 'javascript']: + if env['platform'] not in ['windows', 'osx', 'linuxbsd', 'server', 'android', 'haiku', 'javascript']: raise RuntimeError('This module does not currently support building for this platform') env.use_ptrcall = True diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 279e67b3eb..11a4109d97 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -33,7 +33,7 @@ namespace GodotTools.Utils { public const string Windows = "windows"; public const string OSX = "osx"; - public const string X11 = "x11"; + public const string X11 = "linuxbsd"; public const string Server = "server"; public const string UWP = "uwp"; public const string Haiku = "haiku"; diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index ca255ebf82..19771ef373 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -30,15 +30,15 @@ #include "visual_script_editor.h" +#include "core/input/input_filter.h" #include "core/object.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/script_language.h" #include "core/variant.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "visual_script_expression.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" @@ -504,36 +504,36 @@ void VisualScriptEditor::_update_graph(int p_only_id) { select_func_text->hide(); Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("NodePath", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("MiniObject", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + Control::get_theme_icon("Variant", "EditorIcons"), + Control::get_theme_icon("bool", "EditorIcons"), + Control::get_theme_icon("int", "EditorIcons"), + Control::get_theme_icon("float", "EditorIcons"), + Control::get_theme_icon("String", "EditorIcons"), + Control::get_theme_icon("Vector2", "EditorIcons"), + Control::get_theme_icon("Rect2", "EditorIcons"), + Control::get_theme_icon("Vector3", "EditorIcons"), + Control::get_theme_icon("Transform2D", "EditorIcons"), + Control::get_theme_icon("Plane", "EditorIcons"), + Control::get_theme_icon("Quat", "EditorIcons"), + Control::get_theme_icon("AABB", "EditorIcons"), + Control::get_theme_icon("Basis", "EditorIcons"), + Control::get_theme_icon("Transform", "EditorIcons"), + Control::get_theme_icon("Color", "EditorIcons"), + Control::get_theme_icon("NodePath", "EditorIcons"), + Control::get_theme_icon("RID", "EditorIcons"), + Control::get_theme_icon("MiniObject", "EditorIcons"), + Control::get_theme_icon("Dictionary", "EditorIcons"), + Control::get_theme_icon("Array", "EditorIcons"), + Control::get_theme_icon("PackedByteArray", "EditorIcons"), + Control::get_theme_icon("PackedInt32Array", "EditorIcons"), + Control::get_theme_icon("PackedFloat32Array", "EditorIcons"), + Control::get_theme_icon("PackedStringArray", "EditorIcons"), + Control::get_theme_icon("PackedVector2Array", "EditorIcons"), + Control::get_theme_icon("PackedVector3Array", "EditorIcons"), + Control::get_theme_icon("PackedColorArray", "EditorIcons") }; - Ref<Texture2D> seq_port = Control::get_icon("VisualShaderPort", "EditorIcons"); + Ref<Texture2D> seq_port = Control::get_theme_icon("VisualShaderPort", "EditorIcons"); for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions @@ -596,7 +596,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { LineEdit *line_edit = memnew(LineEdit); line_edit->set_text(node->get_text()); line_edit->set_expand_to_text_length(true); - line_edit->add_font_override("font", get_font("source", "EditorFonts")); + line_edit->add_theme_font_override("font", get_theme_font("source", "EditorFonts")); gnode->add_child(line_edit); line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get())); } else { @@ -637,14 +637,14 @@ void VisualScriptEditor::_update_graph(int p_only_id) { mono_color.a = 0.85; c = mono_color; } - gnode->add_color_override("title_color", c); + gnode->add_theme_color_override("title_color", c); c.a = 0.7; - gnode->add_color_override("close_color", c); - gnode->add_color_override("resizer_color", ic); - gnode->add_style_override("frame", sbf); + gnode->add_theme_color_override("close_color", c); + gnode->add_theme_color_override("resizer_color", ic); + gnode->add_theme_style_override("frame", sbf); } - const Color mono_color = get_color("mono_color", "Editor"); + const Color mono_color = get_theme_color("mono_color", "Editor"); int slot_idx = 0; @@ -750,7 +750,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { } Button *rmbtn = memnew(Button); - rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); hbc->add_child(rmbtn); rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E->get(), i), CONNECT_DEFERRED); } else { @@ -812,7 +812,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { if (is_vslist) { Button *rmbtn = memnew(Button); - rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); hbc->add_child(rmbtn); rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E->get(), i), CONNECT_DEFERRED); @@ -856,7 +856,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->add_child(vbc); - bool dark_theme = get_constant("dark_theme", "Editor"); + bool dark_theme = get_theme_constant("dark_theme", "Editor"); if (i < mixed_seq_ports) { gnode->set_slot(slot_idx, left_ok, left_type, _color_from_type(left_type, dark_theme), true, TYPE_SEQUENCE, mono_color, Ref<Texture2D>(), seq_port); } else { @@ -940,9 +940,9 @@ void VisualScriptEditor::_update_members() { TreeItem *functions = members->create_item(root); functions->set_selectable(0, false); functions->set_text(0, TTR("Functions:")); - functions->add_button(0, Control::get_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function.")); - functions->add_button(0, Control::get_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function.")); - functions->set_custom_color(0, Control::get_color("mono_color", "Editor")); + functions->add_button(0, Control::get_theme_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function.")); + functions->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function.")); + functions->set_custom_color(0, Control::get_theme_color("mono_color", "Editor")); List<StringName> func_names; script->get_function_list(&func_names); @@ -956,7 +956,7 @@ void VisualScriptEditor::_update_members() { ti->set_text(0, E->get()); ti->set_selectable(0, true); ti->set_metadata(0, E->get()); - ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); + ti->add_button(0, Control::get_theme_icon("Edit", "EditorIcons"), 0); if (selected == E->get()) ti->select(0); } @@ -964,37 +964,37 @@ void VisualScriptEditor::_update_members() { TreeItem *variables = members->create_item(root); variables->set_selectable(0, false); variables->set_text(0, TTR("Variables:")); - variables->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable.")); - variables->set_custom_color(0, Control::get_color("mono_color", "Editor")); + variables->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable.")); + variables->set_custom_color(0, Control::get_theme_color("mono_color", "Editor")); Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("NodePath", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("MiniObject", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + Control::get_theme_icon("Variant", "EditorIcons"), + Control::get_theme_icon("bool", "EditorIcons"), + Control::get_theme_icon("int", "EditorIcons"), + Control::get_theme_icon("float", "EditorIcons"), + Control::get_theme_icon("String", "EditorIcons"), + Control::get_theme_icon("Vector2", "EditorIcons"), + Control::get_theme_icon("Rect2", "EditorIcons"), + Control::get_theme_icon("Vector3", "EditorIcons"), + Control::get_theme_icon("Transform2D", "EditorIcons"), + Control::get_theme_icon("Plane", "EditorIcons"), + Control::get_theme_icon("Quat", "EditorIcons"), + Control::get_theme_icon("AABB", "EditorIcons"), + Control::get_theme_icon("Basis", "EditorIcons"), + Control::get_theme_icon("Transform", "EditorIcons"), + Control::get_theme_icon("Color", "EditorIcons"), + Control::get_theme_icon("NodePath", "EditorIcons"), + Control::get_theme_icon("RID", "EditorIcons"), + Control::get_theme_icon("MiniObject", "EditorIcons"), + Control::get_theme_icon("Dictionary", "EditorIcons"), + Control::get_theme_icon("Array", "EditorIcons"), + Control::get_theme_icon("PackedByteArray", "EditorIcons"), + Control::get_theme_icon("PackedInt32Array", "EditorIcons"), + Control::get_theme_icon("PackedFloat32Array", "EditorIcons"), + Control::get_theme_icon("PackedStringArray", "EditorIcons"), + Control::get_theme_icon("PackedVector2Array", "EditorIcons"), + Control::get_theme_icon("PackedVector3Array", "EditorIcons"), + Control::get_theme_icon("PackedColorArray", "EditorIcons") }; List<StringName> var_names; @@ -1017,8 +1017,8 @@ void VisualScriptEditor::_update_members() { TreeItem *_signals = members->create_item(root); _signals->set_selectable(0, false); _signals->set_text(0, TTR("Signals:")); - _signals->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal.")); - _signals->set_custom_color(0, Control::get_color("mono_color", "Editor")); + _signals->add_button(0, Control::get_theme_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal.")); + _signals->set_custom_color(0, Control::get_theme_color("mono_color", "Editor")); List<StringName> signal_names; script->get_custom_signal_list(&signal_names); @@ -1034,12 +1034,12 @@ void VisualScriptEditor::_update_members() { String base_type = script->get_instance_base_type(); String icon_type = base_type; - if (!Control::has_icon(base_type, "EditorIcons")) { + if (!Control::has_theme_icon(base_type, "EditorIcons")) { icon_type = "Object"; } base_type_select->set_text(base_type); - base_type_select->set_icon(Control::get_icon(icon_type, "EditorIcons")); + base_type_select->set_icon(Control::get_theme_icon(icon_type, "EditorIcons")); updating_members = false; } @@ -1057,9 +1057,9 @@ void VisualScriptEditor::_member_selected() { if (ti->get_parent() == members->get_root()->get_children()) { #ifdef OSX_ENABLED - bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META); + bool held_ctrl = InputFilter::get_singleton()->is_key_pressed(KEY_META); #else - bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool held_ctrl = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); #endif if (held_ctrl) { ERR_FAIL_COND(!script->has_function(selected)); @@ -1252,7 +1252,7 @@ void VisualScriptEditor::_add_func_input() { hbox->add_child(type_box); Button *delete_button = memnew(Button); - delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons")); + delete_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); delete_button->set_tooltip(vformat(TTR("Delete input port"))); hbox->add_child(delete_button); @@ -1360,7 +1360,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt } } else if (ti->get_parent() == root->get_children()) { selected = ti->get_text(0); - function_name_edit->set_position(Input::get_singleton()->get_mouse_position() - Vector2(60, -10)); + function_name_edit->set_position(InputFilter::get_singleton()->get_mouse_position() - Vector2(60, -10)); function_name_edit->popup(); function_name_box->set_text(selected); function_name_box->select_all(); @@ -1722,7 +1722,7 @@ void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> key = p_event; if (key.is_valid() && !key->is_pressed()) { - mouse_up_position = Input::get_singleton()->get_mouse_position(); + mouse_up_position = InputFilter::get_singleton()->get_mouse_position(); } } @@ -1732,7 +1732,7 @@ void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { if (key.is_valid() && key->is_pressed() && key->get_button_mask() == BUTTON_RIGHT) { saved_position = graph->get_local_mouse_position(); - Point2 gpos = Input::get_singleton()->get_mouse_position(); + Point2 gpos = InputFilter::get_singleton()->get_mouse_position(); _generic_search(script->get_instance_base_type(), gpos); } } @@ -1986,9 +1986,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da if (String(d["type"]) == "visual_script_variable_drag") { #ifdef OSX_ENABLED - bool use_set = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_set = InputFilter::get_singleton()->is_key_pressed(KEY_META); #else - bool use_set = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool use_set = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); #endif Vector2 ofs = graph->get_scroll_ofs() + p_point; if (graph->is_using_snap()) { @@ -2181,9 +2181,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } #ifdef OSX_ENABLED - bool use_node = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_node = InputFilter::get_singleton()->is_key_pressed(KEY_META); #else - bool use_node = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool use_node = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); #endif Array nodes = d["nodes"]; @@ -2245,7 +2245,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script); - if (!sn && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!sn && !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { EditorNode::get_singleton()->show_warning(vformat(TTR("Can't drop properties because script '%s' is not used in this scene.\nDrop holding 'Shift' to just copy the signature."), get_name())); return; } @@ -2265,12 +2265,12 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da ofs /= EDSCALE; #ifdef OSX_ENABLED - bool use_get = Input::get_singleton()->is_key_pressed(KEY_META); + bool use_get = InputFilter::get_singleton()->is_key_pressed(KEY_META); #else - bool use_get = Input::get_singleton()->is_key_pressed(KEY_CONTROL); + bool use_get = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL); #endif - if (!node || Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (!node || InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { if (use_get) undo_redo->create_action(TTR("Add Getter Property")); @@ -2377,7 +2377,7 @@ void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) { if (!button) return; - Ref<StyleBox> normal = get_stylebox("normal", "Button"); + Ref<StyleBox> normal = get_theme_stylebox("normal", "Button"); button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } @@ -2459,9 +2459,9 @@ String VisualScriptEditor::get_name() { return name; } -Ref<Texture2D> VisualScriptEditor::get_icon() { +Ref<Texture2D> VisualScriptEditor::get_theme_icon() { - return Control::get_icon("VisualScript", "EditorIcons"); + return Control::get_theme_icon("VisualScript", "EditorIcons"); } bool VisualScriptEditor::is_unsaved() { @@ -3925,9 +3925,9 @@ void VisualScriptEditor::_notification(int p_what) { return; } - edit_variable_edit->add_style_override("bg", get_stylebox("bg", "Tree")); - edit_signal_edit->add_style_override("bg", get_stylebox("bg", "Tree")); - func_input_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + edit_variable_edit->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); + edit_signal_edit->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); + func_input_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree")); Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); @@ -4479,9 +4479,9 @@ void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { TreeItem *root = members->get_root(); - Ref<Texture2D> del_icon = Control::get_icon("Remove", "EditorIcons"); + Ref<Texture2D> del_icon = Control::get_theme_icon("Remove", "EditorIcons"); - Ref<Texture2D> edit_icon = Control::get_icon("Edit", "EditorIcons"); + Ref<Texture2D> edit_icon = Control::get_theme_icon("Edit", "EditorIcons"); if (ti->get_parent() == root->get_children()) { @@ -4578,7 +4578,7 @@ void VisualScriptEditor::_member_option(int p_option) { } else if (p_option == MEMBER_EDIT) { variable_editor->edit(name); edit_variable_dialog->set_title(TTR("Editing Variable:") + " " + name); - edit_variable_dialog->popup_centered_minsize(Size2(400, 200) * EDSCALE); + edit_variable_dialog->popup_centered(Size2(400, 200) * EDSCALE); } } break; case MEMBER_SIGNAL: { @@ -4599,7 +4599,7 @@ void VisualScriptEditor::_member_option(int p_option) { } else if (p_option == MEMBER_EDIT) { signal_editor->edit(name); edit_signal_dialog->set_title(TTR("Editing Signal:") + " " + name); - edit_signal_dialog->popup_centered_minsize(Size2(400, 300) * EDSCALE); + edit_signal_dialog->popup_centered(Size2(400, 300) * EDSCALE); } } break; } @@ -4687,10 +4687,9 @@ VisualScriptEditor::VisualScriptEditor() { add_child(member_popup); member_popup->connect("id_pressed", callable_mp(this, &VisualScriptEditor::_member_option)); - function_name_edit = memnew(PopupDialog); + function_name_edit = memnew(AcceptDialog); function_name_box = memnew(LineEdit); function_name_edit->add_child(function_name_box); - function_name_edit->set_h_size_flags(SIZE_EXPAND); function_name_box->connect("gui_input", callable_mp(this, &VisualScriptEditor::_fn_name_box_input)); function_name_box->set_expand_to_text_length(true); add_child(function_name_edit); @@ -4770,7 +4769,6 @@ VisualScriptEditor::VisualScriptEditor() { func_input_scroll->add_child(func_input_vbox); function_create_dialog = memnew(ConfirmationDialog); - function_create_dialog->set_v_size_flags(SIZE_EXPAND_FILL); function_create_dialog->set_title(TTR("Create Function")); function_create_dialog->add_child(function_vb); function_create_dialog->get_ok()->set_text(TTR("Create")); @@ -4859,7 +4857,6 @@ VisualScriptEditor::VisualScriptEditor() { new_connect_node_select = memnew(VisualScriptPropertySelector); add_child(new_connect_node_select); - new_connect_node_select->set_resizable(true); new_connect_node_select->connect("selected", callable_mp(this, &VisualScriptEditor::_selected_connect_node)); new_connect_node_select->get_cancel()->connect("pressed", callable_mp(this, &VisualScriptEditor::_cancel_connect_node)); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 6ff00cf0a6..d9494e4d04 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -114,7 +114,7 @@ class VisualScriptEditor : public ScriptEditorBase { UndoRedo *undo_redo; Tree *members; - PopupDialog *function_name_edit; + AcceptDialog *function_name_edit; LineEdit *function_name_box; Label *hint_text; @@ -298,7 +298,7 @@ public: virtual Vector<String> get_functions(); virtual void reload_text(); virtual String get_name(); - virtual Ref<Texture2D> get_icon(); + virtual Ref<Texture2D> get_theme_icon(); virtual bool is_unsaved(); virtual Variant get_edit_state(); virtual void set_edit_state(const Variant &p_state); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 41c1ea4ca2..1b496dad32 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "core/global_constants.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/os.h" #include "core/project_settings.h" #include "scene/main/node.h" @@ -3870,16 +3870,16 @@ public: switch (mode) { case VisualScriptInputAction::MODE_PRESSED: { - *p_outputs[0] = Input::get_singleton()->is_action_pressed(action); + *p_outputs[0] = InputFilter::get_singleton()->is_action_pressed(action); } break; case VisualScriptInputAction::MODE_RELEASED: { - *p_outputs[0] = !Input::get_singleton()->is_action_pressed(action); + *p_outputs[0] = !InputFilter::get_singleton()->is_action_pressed(action); } break; case VisualScriptInputAction::MODE_JUST_PRESSED: { - *p_outputs[0] = Input::get_singleton()->is_action_just_pressed(action); + *p_outputs[0] = InputFilter::get_singleton()->is_action_just_pressed(action); } break; case VisualScriptInputAction::MODE_JUST_RELEASED: { - *p_outputs[0] = Input::get_singleton()->is_action_just_released(action); + *p_outputs[0] = InputFilter::get_singleton()->is_action_just_released(action); } break; } diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index d799f19143..d749e3257a 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -39,7 +39,7 @@ #include "modules/visual_script/visual_script_func_nodes.h" #include "modules/visual_script/visual_script_nodes.h" #include "scene/main/node.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void VisualScriptPropertySelector::_text_changed(const String &p_newtext) { _update_search(); @@ -99,35 +99,35 @@ void VisualScriptPropertySelector::_update_search() { List<PropertyInfo> props; TreeItem *category = NULL; Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { - Control::get_icon("Variant", "EditorIcons"), - Control::get_icon("bool", "EditorIcons"), - Control::get_icon("int", "EditorIcons"), - Control::get_icon("float", "EditorIcons"), - Control::get_icon("String", "EditorIcons"), - Control::get_icon("Vector2", "EditorIcons"), - Control::get_icon("Rect2", "EditorIcons"), - Control::get_icon("Vector3", "EditorIcons"), - Control::get_icon("Transform2D", "EditorIcons"), - Control::get_icon("Plane", "EditorIcons"), - Control::get_icon("Quat", "EditorIcons"), - Control::get_icon("AABB", "EditorIcons"), - Control::get_icon("Basis", "EditorIcons"), - Control::get_icon("Transform", "EditorIcons"), - Control::get_icon("Color", "EditorIcons"), - Control::get_icon("Path", "EditorIcons"), - Control::get_icon("RID", "EditorIcons"), - Control::get_icon("Object", "EditorIcons"), - Control::get_icon("Dictionary", "EditorIcons"), - Control::get_icon("Array", "EditorIcons"), - Control::get_icon("PackedByteArray", "EditorIcons"), - Control::get_icon("PackedInt32Array", "EditorIcons"), - Control::get_icon("PackedFloat32Array", "EditorIcons"), - Control::get_icon("PackedInt64Array", "EditorIcons"), - Control::get_icon("PackedFloat64Array", "EditorIcons"), - Control::get_icon("PackedStringArray", "EditorIcons"), - Control::get_icon("PackedVector2Array", "EditorIcons"), - Control::get_icon("PackedVector3Array", "EditorIcons"), - Control::get_icon("PackedColorArray", "EditorIcons") + vbc->get_theme_icon("Variant", "EditorIcons"), + vbc->get_theme_icon("bool", "EditorIcons"), + vbc->get_theme_icon("int", "EditorIcons"), + vbc->get_theme_icon("float", "EditorIcons"), + vbc->get_theme_icon("String", "EditorIcons"), + vbc->get_theme_icon("Vector2", "EditorIcons"), + vbc->get_theme_icon("Rect2", "EditorIcons"), + vbc->get_theme_icon("Vector3", "EditorIcons"), + vbc->get_theme_icon("Transform2D", "EditorIcons"), + vbc->get_theme_icon("Plane", "EditorIcons"), + vbc->get_theme_icon("Quat", "EditorIcons"), + vbc->get_theme_icon("AABB", "EditorIcons"), + vbc->get_theme_icon("Basis", "EditorIcons"), + vbc->get_theme_icon("Transform", "EditorIcons"), + vbc->get_theme_icon("Color", "EditorIcons"), + vbc->get_theme_icon("Path", "EditorIcons"), + vbc->get_theme_icon("RID", "EditorIcons"), + vbc->get_theme_icon("Object", "EditorIcons"), + vbc->get_theme_icon("Dictionary", "EditorIcons"), + vbc->get_theme_icon("Array", "EditorIcons"), + vbc->get_theme_icon("PackedByteArray", "EditorIcons"), + vbc->get_theme_icon("PackedInt32Array", "EditorIcons"), + vbc->get_theme_icon("PackedFloat32Array", "EditorIcons"), + vbc->get_theme_icon("PackedInt64Array", "EditorIcons"), + vbc->get_theme_icon("PackedFloat64Array", "EditorIcons"), + vbc->get_theme_icon("PackedStringArray", "EditorIcons"), + vbc->get_theme_icon("PackedVector2Array", "EditorIcons"), + vbc->get_theme_icon("PackedVector3Array", "EditorIcons"), + vbc->get_theme_icon("PackedColorArray", "EditorIcons") }; { String b = String(E->get()); @@ -252,7 +252,7 @@ void VisualScriptPropertySelector::_update_search() { TreeItem *item = search_options->create_item(category ? category : root); item->set_text(0, desc); - item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); + item->set_icon(0, vbc->get_theme_icon("MemberMethod", "EditorIcons")); item->set_metadata(0, name); item->set_selectable(0, true); @@ -316,7 +316,7 @@ void VisualScriptPropertySelector::create_visualscript_item(const String &name, if (search_input == String() || text.findn(search_input) != -1) { TreeItem *item = search_options->create_item(root); item->set_text(0, text); - item->set_icon(0, get_icon("VisualScript", "EditorIcons")); + item->set_icon(0, vbc->get_theme_icon("VisualScript", "EditorIcons")); item->set_metadata(0, name); item->set_metadata(1, "action"); item->set_selectable(0, true); @@ -399,7 +399,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt } item->set_text(0, type_name + String("").join(desc)); - item->set_icon(0, get_icon("VisualScript", "EditorIcons")); + item->set_icon(0, vbc->get_theme_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); item->set_selectable(0, true); @@ -416,7 +416,7 @@ void VisualScriptPropertySelector::_confirmed() { if (!ti) return; emit_signal("selected", ti->get_metadata(0), ti->get_metadata(1), ti->get_metadata(2)); - hide(); + set_visible(false); } void VisualScriptPropertySelector::_item_selected() { @@ -519,7 +519,7 @@ void VisualScriptPropertySelector::_item_selected() { } void VisualScriptPropertySelector::_hide_requested() { - _closed(); // From WindowDialog. + _cancel_pressed(); // From AcceptDialog. } void VisualScriptPropertySelector::_notification(int p_what) { @@ -684,12 +684,8 @@ void VisualScriptPropertySelector::select_from_visual_script(const String &p_bas } void VisualScriptPropertySelector::show_window(float p_screen_ratio) { - Rect2 rect; - Point2 window_size = get_viewport_rect().size; - rect.size = (window_size * p_screen_ratio).floor(); - rect.size.x = rect.size.x / 2.2f; - rect.position = ((window_size - rect.size) / 2.0f).floor(); - popup(rect); + + popup_centered_ratio(p_screen_ratio); } void VisualScriptPropertySelector::_bind_methods() { @@ -699,7 +695,7 @@ void VisualScriptPropertySelector::_bind_methods() { VisualScriptPropertySelector::VisualScriptPropertySelector() { - VBoxContainer *vbc = memnew(VBoxContainer); + vbc = memnew(VBoxContainer); add_child(vbc); //set_child_rect(vbc); search_box = memnew(LineEdit); diff --git a/modules/visual_script/visual_script_property_selector.h b/modules/visual_script/visual_script_property_selector.h index f438ca1f5b..cc49b2863d 100644 --- a/modules/visual_script/visual_script_property_selector.h +++ b/modules/visual_script/visual_script_property_selector.h @@ -64,6 +64,7 @@ class VisualScriptPropertySelector : public ConfirmationDialog { Object *instance; bool virtuals_only; bool seq_connect; + VBoxContainer *vbc; Vector<Variant::Type> type_filter; diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub index 14fa6c1268..6aed8a16f5 100644 --- a/modules/webm/libvpx/SCsub +++ b/modules/webm/libvpx/SCsub @@ -270,12 +270,12 @@ if env["platform"] == 'uwp': webm_cpu_x86 = True else: import platform - is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and (platform.machine().startswith('arm') or platform.machine().startswith('aarch'))) + is_x11_or_server_arm = ((env["platform"] == 'linuxbsd' or env["platform"] == 'server') and (platform.machine().startswith('arm') or platform.machine().startswith('aarch'))) is_ios_x86 = (env["platform"] == 'iphone' and ("arch" in env and env["arch"].startswith('x86'))) is_android_x86 = (env["platform"] == 'android' and env["android_arch"].startswith('x86')) if is_android_x86: cpu_bits = '32' if env["android_arch"] == 'x86' else '64' - webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) + webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'linuxbsd' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android') if webm_cpu_x86: @@ -330,7 +330,7 @@ if webm_cpu_x86: if webm_cpu_arm: if env["platform"] == 'iphone': env_libvpx["ASFLAGS"] = '-arch armv7' - elif env["platform"] == 'android' and env["android_arch"] == 'armv7' or env["platform"] == 'x11' or env["platform"] == 'server': + elif env["platform"] == 'android' and env["android_arch"] == 'armv7' or env["platform"] == 'linuxbsd' or env["platform"] == 'server': env_libvpx["ASFLAGS"] = '-mfpu=neon' elif env["platform"] == 'uwp': env_libvpx["AS"] = 'armasm' diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 8bbf41d82d..e018ee69f0 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "java_godot_lib_jni.h" + #include "java_godot_io_wrapper.h" #include "java_godot_wrapper.h" @@ -37,17 +38,18 @@ #include "api/java_class_wrapper.h" #include "audio_driver_jandroid.h" #include "core/engine.h" +#include "core/input/input_filter.h" #include "core/project_settings.h" #include "dir_access_jandroid.h" #include "file_access_android.h" #include "file_access_jandroid.h" #include "jni_utils.h" -#include "main/input_default.h" #include "main/main.h" #include "net_socket_android.h" #include "os_android.h" #include "string_android.h" #include "thread_jandroid.h" + #include <unistd.h> static JavaClassWrapper *java_class_wrapper = NULL; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 8021d6dd07..e3792b1f31 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -306,14 +306,14 @@ void OS_Android::main_loop_end() { void OS_Android::main_loop_focusout() { if (main_loop) - main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + main_loop->notification(NOTIFICATION_WM_FOCUS_OUT); audio_driver_android.set_pause(true); } void OS_Android::main_loop_focusin() { if (main_loop) - main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); + main_loop->notification(NOTIFICATION_WM_FOCUS_IN); audio_driver_android.set_pause(false); } @@ -568,7 +568,7 @@ void OS_Android::init_video_mode(int p_video_width, int p_video_height) { void OS_Android::main_loop_request_go_back() { if (main_loop) - main_loop->notification(MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST); + main_loop->notification(NOTIFICATION_WM_GO_BACK_REQUEST); } void OS_Android::set_display_size(Size2 p_size) { diff --git a/platform/android/os_android.h b/platform/android/os_android.h index ec6ffe5438..d09f4e10d6 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -33,10 +33,9 @@ #include "audio_driver_jandroid.h" #include "audio_driver_opensl.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/main_loop.h" #include "drivers/unix/os_unix.h" -#include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" diff --git a/platform/haiku/haiku_direct_window.cpp b/platform/haiku/haiku_direct_window.cpp index 2d7efe6b61..18e1862d33 100644 --- a/platform/haiku/haiku_direct_window.cpp +++ b/platform/haiku/haiku_direct_window.cpp @@ -74,7 +74,7 @@ void HaikuDirectWindow::SetMainLoop(MainLoop *p_main_loop) { bool HaikuDirectWindow::QuitRequested() { StopMessageRunner(); - main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); + main_loop->notification(NOTIFICATION_WM_CLOSE_REQUEST); return false; } diff --git a/platform/haiku/haiku_direct_window.h b/platform/haiku/haiku_direct_window.h index ccc9542f0e..925bb9ac5d 100644 --- a/platform/haiku/haiku_direct_window.h +++ b/platform/haiku/haiku_direct_window.h @@ -35,8 +35,8 @@ #include <DirectWindow.h> +#include "core/input/input_filter.h" #include "core/os/os.h" -#include "main/input_default.h" #include "haiku_gl_view.h" diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index fc8cb77a91..90c0abc3ef 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -33,10 +33,10 @@ #include "audio_driver_media_kit.h" #include "context_gl_haiku.h" +#include "core/input/input_filter.h" #include "drivers/unix/os_unix.h" #include "haiku_application.h" #include "haiku_direct_window.h" -#include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual_server.h" diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index f42679e754..2efb7af7c2 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -33,15 +33,13 @@ #ifndef OS_IPHONE_H #define OS_IPHONE_H -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/unix/os_unix.h" - #include "game_center.h" #include "icloud.h" #include "in_app_store.h" #include "ios.h" -#include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index db90b01f8f..b7feb5bfbd 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -1009,10 +1009,10 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, update_clipboard(evt.clipboardData.getData('text')); }, true); }, - MainLoop::NOTIFICATION_WM_MOUSE_ENTER, - MainLoop::NOTIFICATION_WM_MOUSE_EXIT, - MainLoop::NOTIFICATION_WM_FOCUS_IN, - MainLoop::NOTIFICATION_WM_FOCUS_OUT + NOTIFICATION_WM_MOUSE_ENTER, + NOTIFICATION_WM_MOUSE_EXIT, + NOTIFICATION_WM_FOCUS_IN, + NOTIFICATION_WM_FOCUS_OUT ); /* clang-format on */ @@ -1121,8 +1121,8 @@ int OS_JavaScript::get_process_id() const { extern "C" EMSCRIPTEN_KEEPALIVE void send_notification(int p_notification) { - if (p_notification == MainLoop::NOTIFICATION_WM_MOUSE_ENTER || p_notification == MainLoop::NOTIFICATION_WM_MOUSE_EXIT) { - cursor_inside_canvas = p_notification == MainLoop::NOTIFICATION_WM_MOUSE_ENTER; + if (p_notification == NOTIFICATION_WM_MOUSE_ENTER || p_notification == NOTIFICATION_WM_MOUSE_EXIT) { + cursor_inside_canvas = p_notification == NOTIFICATION_WM_MOUSE_ENTER; } OS_JavaScript::get_singleton()->get_main_loop()->notification(p_notification); } diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index ed59477914..1a3a6616b0 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -32,8 +32,8 @@ #define OS_JAVASCRIPT_H #include "audio_driver_javascript.h" +#include "core/input/input_filter.h" #include "drivers/unix/os_unix.h" -#include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub new file mode 100644 index 0000000000..f3f65e216e --- /dev/null +++ b/platform/linuxbsd/SCsub @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +Import('env') + +from platform_methods import run_in_subprocess +import platform_linuxbsd_builders + +common_x11 = [ + "crash_handler_linuxbsd.cpp", + "os_linuxbsd.cpp", + "joypad_linux.cpp", + "context_gl_x11.cpp", + "detect_prime_x11.cpp", + "display_server_x11.cpp", + "vulkan_context_x11.cpp", + "key_mapping_x11.cpp", + +] + +prog = env.add_program('#bin/godot', ['godot_linuxbsd.cpp'] + common_x11) + +if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]: + env.AddPostAction(prog, run_in_subprocess(platform_linuxbsd_builders.make_debug_linuxbsd)) diff --git a/platform/x11/context_gl_x11.cpp b/platform/linuxbsd/context_gl_x11.cpp index 5442af3bef..5442af3bef 100644 --- a/platform/x11/context_gl_x11.cpp +++ b/platform/linuxbsd/context_gl_x11.cpp diff --git a/platform/x11/context_gl_x11.h b/platform/linuxbsd/context_gl_x11.h index 2c0643c95a..2c0643c95a 100644 --- a/platform/x11/context_gl_x11.h +++ b/platform/linuxbsd/context_gl_x11.h diff --git a/platform/x11/crash_handler_x11.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp index 19c8f71d0e..1b3804e3ed 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_x11.cpp */ +/* crash_handler_linuxbsd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "crash_handler_x11.h" +#include "crash_handler_linuxbsd.h" #include "core/os/os.h" #include "core/project_settings.h" diff --git a/platform/x11/crash_handler_x11.h b/platform/linuxbsd/crash_handler_linuxbsd.h index 98620cc789..94b4649690 100644 --- a/platform/x11/crash_handler_x11.h +++ b/platform/linuxbsd/crash_handler_linuxbsd.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* crash_handler_x11.h */ +/* crash_handler_linuxbsd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/platform/x11/detect.py b/platform/linuxbsd/detect.py index 9a9ab86068..1a395efffe 100644 --- a/platform/x11/detect.py +++ b/platform/linuxbsd/detect.py @@ -8,7 +8,7 @@ def is_active(): def get_name(): - return "X11" + return "LinuxBSD" def can_build(): @@ -317,7 +317,7 @@ def configure(env): if not env['builtin_zlib']: env.ParseConfig('pkg-config zlib --cflags --libs') - env.Prepend(CPPPATH=['#platform/x11']) + env.Prepend(CPPPATH=['#platform/linuxbsd']) env.Append(CPPDEFINES=['X11_ENABLED', 'UNIX_ENABLED']) env.Append(CPPDEFINES=['VULKAN_ENABLED']) @@ -350,9 +350,9 @@ def configure(env): print("Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld") else: if float(gnu_ld_version.group(1)) >= 2.30: - env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld']) + env.Append(LINKFLAGS=['-T', 'platform/linuxbsd/pck_embed.ld']) else: - env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.legacy.ld']) + env.Append(LINKFLAGS=['-T', 'platform/linuxbsd/pck_embed.legacy.ld']) ## Cross-compilation diff --git a/platform/x11/detect_prime.cpp b/platform/linuxbsd/detect_prime_x11.cpp index d79fd00118..69b0837e6c 100644 --- a/platform/x11/detect_prime.cpp +++ b/platform/linuxbsd/detect_prime_x11.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* detect_prime.cpp */ +/* detect_prime_x11.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/platform/x11/detect_prime.h b/platform/linuxbsd/detect_prime_x11.h index df636449f4..039bdee76b 100644 --- a/platform/x11/detect_prime.h +++ b/platform/linuxbsd/detect_prime_x11.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* detect_prime.h */ +/* detect_prime_x11.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/platform/x11/os_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 772913980b..4bea458187 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* os_x11.cpp */ +/* display_server_x11.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "os_x11.h" -#include "detect_prime.h" +#include "display_server_x11.h" + +#ifdef X11_ENABLED + +#include "detect_prime_x11.h" #include "core/os/dir_access.h" #include "core/print_string.h" @@ -44,8 +47,7 @@ #include "servers/visual/rasterizer_rd/rasterizer_rd.h" #endif -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "scene/resources/texture.h" #ifdef HAVE_MNTENT #include <mntent.h> @@ -86,6 +88,8 @@ #include <X11/XKBlib.h> +#include "core/project_settings.h" + // 2.2 is the first release with multitouch #define XINPUT_CLIENT_VERSION_MAJOR 2 #define XINPUT_CLIENT_VERSION_MINOR 2 @@ -99,584 +103,117 @@ static const double abs_resolution_mult = 10000.0; static const double abs_resolution_range_mult = 10.0; -void OS_X11::initialize_core() { - - crash_handler.initialize(); - - OS_Unix::initialize_core(); -} - -int OS_X11::get_current_video_driver() const { - return video_driver_index; -} - -Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { - - long im_event_mask = 0; - last_button_state = 0; - - xmbstring = NULL; - x11_window = 0; - last_click_ms = 0; - last_click_button_index = -1; - last_click_pos = Point2(-100, -100); - args = OS::get_singleton()->get_cmdline_args(); - current_videomode = p_desired; - main_loop = NULL; - last_timestamp = 0; - last_mouse_pos_valid = false; - last_keyrelease_time = 0; - xdnd_version = 0; - - if (get_render_thread_mode() == RENDER_SEPARATE_THREAD) { - XInitThreads(); - } - - /** XLIB INITIALIZATION **/ - x11_display = XOpenDisplay(NULL); - - if (!x11_display) { - ERR_PRINT("X11 Display is not available"); - return ERR_UNAVAILABLE; - } - - char *modifiers = NULL; - Bool xkb_dar = False; - XAutoRepeatOn(x11_display); - xkb_dar = XkbSetDetectableAutoRepeat(x11_display, True, NULL); - - // Try to support IME if detectable auto-repeat is supported - if (xkb_dar == True) { - -#ifdef X_HAVE_UTF8_STRING - // Xutf8LookupString will be used later instead of XmbLookupString before - // the multibyte sequences can be converted to unicode string. - modifiers = XSetLocaleModifiers(""); +bool DisplayServerX11::has_feature(Feature p_feature) const { + switch (p_feature) { + case FEATURE_SUBWINDOWS: +#ifdef TOUCH_ENABLED + case FEATURE_TOUCHSCREEN: #endif - } - - if (modifiers == NULL) { - if (is_stdout_verbose()) { - WARN_PRINT("IME is disabled"); - } - XSetLocaleModifiers("@im=none"); - WARN_PRINT("Error setting locale modifiers"); - } - - const char *err; - xrr_get_monitors = NULL; - xrr_free_monitors = NULL; - int xrandr_major = 0; - int xrandr_minor = 0; - int event_base, error_base; - xrandr_ext_ok = XRRQueryExtension(x11_display, &event_base, &error_base); - xrandr_handle = dlopen("libXrandr.so.2", RTLD_LAZY); - if (!xrandr_handle) { - err = dlerror(); - fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err); - } else { - XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor); - if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) { - xrr_get_monitors = (xrr_get_monitors_t)dlsym(xrandr_handle, "XRRGetMonitors"); - if (!xrr_get_monitors) { - err = dlerror(); - fprintf(stderr, "could not find symbol XRRGetMonitors\nError: %s\n", err); - } else { - xrr_free_monitors = (xrr_free_monitors_t)dlsym(xrandr_handle, "XRRFreeMonitors"); - if (!xrr_free_monitors) { - err = dlerror(); - fprintf(stderr, "could not find XRRFreeMonitors\nError: %s\n", err); - xrr_get_monitors = NULL; - } - } - } - } - - if (!refresh_device_info()) { - OS::get_singleton()->alert("Your system does not support XInput 2.\n" - "Please upgrade your distribution.", - "Unable to initialize XInput"); - return ERR_UNAVAILABLE; - } - - xim = XOpenIM(x11_display, NULL, NULL, NULL); - - if (xim == NULL) { - WARN_PRINT("XOpenIM failed"); - xim_style = 0L; - } else { - ::XIMCallback im_destroy_callback; - im_destroy_callback.client_data = (::XPointer)(this); - im_destroy_callback.callback = (::XIMProc)(xim_destroy_callback); - if (XSetIMValues(xim, XNDestroyCallback, &im_destroy_callback, - NULL) != NULL) { - WARN_PRINT("Error setting XIM destroy callback"); - } - - ::XIMStyles *xim_styles = NULL; - xim_style = 0L; - char *imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); - if (imvalret != NULL || xim_styles == NULL) { - fprintf(stderr, "Input method doesn't support any styles\n"); - } - - if (xim_styles) { - xim_style = 0L; - for (int i = 0; i < xim_styles->count_styles; i++) { - - if (xim_styles->supported_styles[i] == - (XIMPreeditNothing | XIMStatusNothing)) { - - xim_style = xim_styles->supported_styles[i]; - break; - } - } - - XFree(xim_styles); + case FEATURE_MOUSE: + case FEATURE_MOUSE_WARP: + case FEATURE_CLIPBOARD: + case FEATURE_CURSOR_SHAPE: + case FEATURE_CUSTOM_CURSOR_SHAPE: + case FEATURE_IME: + case FEATURE_WINDOW_TRANSPARENCY: + //case FEATURE_HIDPI: + case FEATURE_ICON: + case FEATURE_NATIVE_ICON: + case FEATURE_SWAP_BUFFERS: + return true; + default: { } - XFree(imvalret); } - //!!!!!!!!!!!!!!!!!!!!!!!!!! - //TODO - do Vulkan and GLES2 support checks, driver selection and fallback - video_driver_index = p_video_driver; -#ifndef _MSC_VER -#warning Forcing vulkan video driver because OpenGL not implemented yet -#endif - video_driver_index = VIDEO_DRIVER_VULKAN; - - print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]"); - //!!!!!!!!!!!!!!!!!!!!!!!!!! - - //Create window - - long visualMask = VisualScreenMask; - int numberOfVisuals; - XVisualInfo vInfoTemplate = {}; - vInfoTemplate.screen = DefaultScreen(x11_display); - XVisualInfo *visualInfo = XGetVisualInfo(x11_display, visualMask, &vInfoTemplate, &numberOfVisuals); - - Colormap colormap = XCreateColormap(x11_display, RootWindow(x11_display, vInfoTemplate.screen), visualInfo->visual, AllocNone); - - XSetWindowAttributes windowAttributes = {}; - windowAttributes.colormap = colormap; - windowAttributes.background_pixel = 0xFFFFFFFF; - windowAttributes.border_pixel = 0; - windowAttributes.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask; - - unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask; - x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes); - - wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); - XSetWMProtocols(x11_display, x11_window, &wm_delete, 1); - - //set_class_hint(x11_display, x11_window); - XMapWindow(x11_display, x11_window); - XFlush(x11_display); - - XSync(x11_display, False); - //XSetErrorHandler(oldHandler); - - XFree(visualInfo); - - // Init context and rendering device -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - if (getenv("DRI_PRIME") == NULL) { - int use_prime = -1; - - if (getenv("PRIMUS_DISPLAY") || - getenv("PRIMUS_libGLd") || - getenv("PRIMUS_libGLa") || - getenv("PRIMUS_libGL") || - getenv("PRIMUS_LOAD_GLOBAL") || - getenv("BUMBLEBEE_SOCKET")) { - - print_verbose("Optirun/primusrun detected. Skipping GPU detection"); - use_prime = 0; - } - - if (getenv("LD_LIBRARY_PATH")) { - String ld_library_path(getenv("LD_LIBRARY_PATH")); - Vector<String> libraries = ld_library_path.split(":"); + return false; +} +String DisplayServerX11::get_name() const { + return "X11"; +} - for (int i = 0; i < libraries.size(); ++i) { - if (FileAccess::exists(libraries[i] + "/libGL.so.1") || - FileAccess::exists(libraries[i] + "/libGL.so")) { +void DisplayServerX11::alert(const String &p_alert, const String &p_title) { + const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" }; - print_verbose("Custom libGL override detected. Skipping GPU detection"); - use_prime = 0; - } - } - } + String path = OS::get_singleton()->get_environment("PATH"); + Vector<String> path_elems = path.split(":", false); + String program; - if (use_prime == -1) { - print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); - use_prime = detect_prime(); - } + for (int i = 0; i < path_elems.size(); i++) { + for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) { + String tested_path = path_elems[i].plus_file(message_programs[k]); - if (use_prime) { - print_line("Found discrete GPU, setting DRI_PRIME=1 to use it."); - print_line("Note: Set DRI_PRIME=0 in the environment to disable Godot from using the discrete GPU."); - setenv("DRI_PRIME", "1", 1); + if (FileAccess::exists(tested_path)) { + program = tested_path; + break; } } - ContextGL_X11::ContextType opengl_api_type = ContextGL_X11::GLES_2_0_COMPATIBLE; - - context_gles2 = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, opengl_api_type)); - - if (context_gles2->initialize() != OK) { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - context_gles2->set_use_vsync(current_videomode.use_vsync); - - if (RasterizerGLES2::is_viable() == OK) { - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); - } else { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - context_vulkan = memnew(VulkanContextX11); - if (context_vulkan->initialize() != OK) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - if (context_vulkan->window_create(x11_window, x11_display, get_video_mode().width, get_video_mode().height) == -1) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - //temporary - rendering_device_vulkan = memnew(RenderingDeviceVulkan); - rendering_device_vulkan->initialize(context_vulkan); - - RasterizerRD::make_current(); - } -#endif - - visual_server = memnew(VisualServerRaster); - if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + if (program.length()) + break; } - if (current_videomode.maximized) { - current_videomode.maximized = false; - set_window_maximized(true); - // borderless fullscreen window mode - } else if (current_videomode.fullscreen) { - current_videomode.fullscreen = false; - set_window_fullscreen(true); - } else if (current_videomode.borderless_window) { - Hints hints; - Atom property; - hints.flags = 2; - hints.decorations = 0; - property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); - XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); - } + List<String> args; - // make PID known to X11 - { - const long pid = this->get_process_id(); - Atom net_wm_pid = XInternAtom(x11_display, "_NET_WM_PID", False); - XChangeProperty(x11_display, x11_window, net_wm_pid, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1); + if (program.ends_with("zenity")) { + args.push_back("--error"); + args.push_back("--width"); + args.push_back("500"); + args.push_back("--title"); + args.push_back(p_title); + args.push_back("--text"); + args.push_back(p_alert); } - // disable resizable window - if (!current_videomode.resizable && !current_videomode.fullscreen) { - XSizeHints *xsh; - xsh = XAllocSizeHints(); - xsh->flags = PMinSize | PMaxSize; - XWindowAttributes xwa; - if (current_videomode.fullscreen) { - XGetWindowAttributes(x11_display, DefaultRootWindow(x11_display), &xwa); - } else { - XGetWindowAttributes(x11_display, x11_window, &xwa); - } - xsh->min_width = xwa.width; - xsh->max_width = xwa.width; - xsh->min_height = xwa.height; - xsh->max_height = xwa.height; - XSetWMNormalHints(x11_display, x11_window, xsh); - XFree(xsh); + if (program.ends_with("kdialog")) { + args.push_back("--error"); + args.push_back(p_alert); + args.push_back("--title"); + args.push_back(p_title); } - if (current_videomode.always_on_top) { - current_videomode.always_on_top = false; - set_window_always_on_top(true); + if (program.ends_with("Xdialog")) { + args.push_back("--title"); + args.push_back(p_title); + args.push_back("--msgbox"); + args.push_back(p_alert); + args.push_back("0"); + args.push_back("0"); } - ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); - ERR_FAIL_COND_V(x11_window == 0, ERR_UNAVAILABLE); - - XSetWindowAttributes new_attr; - - new_attr.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | - ButtonReleaseMask | EnterWindowMask | - LeaveWindowMask | PointerMotionMask | - Button1MotionMask | - Button2MotionMask | Button3MotionMask | - Button4MotionMask | Button5MotionMask | - ButtonMotionMask | KeymapStateMask | - ExposureMask | VisibilityChangeMask | - StructureNotifyMask | - SubstructureNotifyMask | SubstructureRedirectMask | - FocusChangeMask | PropertyChangeMask | - ColormapChangeMask | OwnerGrabButtonMask | - im_event_mask; - - XChangeWindowAttributes(x11_display, x11_window, CWEventMask, &new_attr); - - static unsigned char all_mask_data[XIMaskLen(XI_LASTEVENT)] = {}; - static unsigned char all_master_mask_data[XIMaskLen(XI_LASTEVENT)] = {}; - - xi.all_event_mask.deviceid = XIAllDevices; - xi.all_event_mask.mask_len = sizeof(all_mask_data); - xi.all_event_mask.mask = all_mask_data; - - xi.all_master_event_mask.deviceid = XIAllMasterDevices; - xi.all_master_event_mask.mask_len = sizeof(all_master_mask_data); - xi.all_master_event_mask.mask = all_master_mask_data; - - XISetMask(xi.all_event_mask.mask, XI_HierarchyChanged); - XISetMask(xi.all_master_event_mask.mask, XI_DeviceChanged); - XISetMask(xi.all_master_event_mask.mask, XI_RawMotion); - -#ifdef TOUCH_ENABLED - if (xi.touch_devices.size()) { - XISetMask(xi.all_event_mask.mask, XI_TouchBegin); - XISetMask(xi.all_event_mask.mask, XI_TouchUpdate); - XISetMask(xi.all_event_mask.mask, XI_TouchEnd); - XISetMask(xi.all_event_mask.mask, XI_TouchOwnership); + if (program.ends_with("xmessage")) { + args.push_back("-center"); + args.push_back("-title"); + args.push_back(p_title); + args.push_back(p_alert); } -#endif - - XISelectEvents(x11_display, x11_window, &xi.all_event_mask, 1); - XISelectEvents(x11_display, DefaultRootWindow(x11_display), &xi.all_master_event_mask, 1); - - // Disabled by now since grabbing also blocks mouse events - // (they are received as extended events instead of standard events) - /*XIClearMask(xi.touch_event_mask.mask, XI_TouchOwnership); - - // Grab touch devices to avoid OS gesture interference - for (int i = 0; i < xi.touch_devices.size(); ++i) { - XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask); - }*/ - - /* set the titlebar name */ - XStoreName(x11_display, x11_window, "Godot"); - - im_active = false; - im_position = Vector2(); - if (xim && xim_style) { - - xic = XCreateIC(xim, XNInputStyle, xim_style, XNClientWindow, x11_window, XNFocusWindow, x11_window, (char *)NULL); - if (XGetICValues(xic, XNFilterEvents, &im_event_mask, NULL) != NULL) { - WARN_PRINT("XGetICValues couldn't obtain XNFilterEvents value"); - XDestroyIC(xic); - xic = NULL; - } - if (xic) { - XUnsetICFocus(xic); - } else { - WARN_PRINT("XCreateIC couldn't create xic"); - } + if (program.length()) { + OS::get_singleton()->execute(program, args, true); } else { - - xic = NULL; - WARN_PRINT("XCreateIC couldn't create xic"); - } - - cursor_size = XcursorGetDefaultSize(x11_display); - cursor_theme = XcursorGetTheme(x11_display); - - if (!cursor_theme) { - print_verbose("XcursorGetTheme could not get cursor theme"); - cursor_theme = "default"; - } - - for (int i = 0; i < CURSOR_MAX; i++) { - - cursors[i] = None; - img[i] = NULL; - } - - current_cursor = CURSOR_ARROW; - - for (int i = 0; i < CURSOR_MAX; i++) { - - static const char *cursor_file[] = { - "left_ptr", - "xterm", - "hand2", - "cross", - "watch", - "left_ptr_watch", - "fleur", - "dnd-move", - "crossed_circle", - "v_double_arrow", - "h_double_arrow", - "size_bdiag", - "size_fdiag", - "move", - "row_resize", - "col_resize", - "question_arrow" - }; - - img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size); - if (!img[i]) { - const char *fallback = NULL; - - switch (i) { - case CURSOR_POINTING_HAND: - fallback = "pointer"; - break; - case CURSOR_CROSS: - fallback = "crosshair"; - break; - case CURSOR_WAIT: - fallback = "wait"; - break; - case CURSOR_BUSY: - fallback = "progress"; - break; - case CURSOR_DRAG: - fallback = "grabbing"; - break; - case CURSOR_CAN_DROP: - fallback = "hand1"; - break; - case CURSOR_FORBIDDEN: - fallback = "forbidden"; - break; - case CURSOR_VSIZE: - fallback = "ns-resize"; - break; - case CURSOR_HSIZE: - fallback = "ew-resize"; - break; - case CURSOR_BDIAGSIZE: - fallback = "fd_double_arrow"; - break; - case CURSOR_FDIAGSIZE: - fallback = "bd_double_arrow"; - break; - case CURSOR_MOVE: - img[i] = img[CURSOR_DRAG]; - break; - case CURSOR_VSPLIT: - fallback = "sb_v_double_arrow"; - break; - case CURSOR_HSPLIT: - fallback = "sb_h_double_arrow"; - break; - case CURSOR_HELP: - fallback = "help"; - break; - } - if (fallback != NULL) { - img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size); - } - } - if (img[i]) { - cursors[i] = XcursorImageLoadCursor(x11_display, img[i]); - } else { - print_verbose("Failed loading custom cursor: " + String(cursor_file[i])); - } - } - - { - // Creating an empty/transparent cursor - - // Create 1x1 bitmap - Pixmap cursormask = XCreatePixmap(x11_display, - RootWindow(x11_display, DefaultScreen(x11_display)), 1, 1, 1); - - // Fill with zero - XGCValues xgc; - xgc.function = GXclear; - GC gc = XCreateGC(x11_display, cursormask, GCFunction, &xgc); - XFillRectangle(x11_display, cursormask, gc, 0, 0, 1, 1); - - // Color value doesn't matter. Mask zero means no foreground or background will be drawn - XColor col = {}; - - Cursor cursor = XCreatePixmapCursor(x11_display, - cursormask, // source (using cursor mask as placeholder, since it'll all be ignored) - cursormask, // mask - &col, &col, 0, 0); - - XFreePixmap(x11_display, cursormask); - XFreeGC(x11_display, gc); - - if (cursor == None) { - ERR_PRINT("FAILED CREATING CURSOR"); - } - - null_cursor = cursor; + print_line(p_alert); } - set_cursor_shape(CURSOR_BUSY); - - //Set Xdnd (drag & drop) support - Atom XdndAware = XInternAtom(x11_display, "XdndAware", False); - Atom version = 5; - XChangeProperty(x11_display, x11_window, XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char *)&version, 1); - - xdnd_enter = XInternAtom(x11_display, "XdndEnter", False); - xdnd_position = XInternAtom(x11_display, "XdndPosition", False); - xdnd_status = XInternAtom(x11_display, "XdndStatus", False); - xdnd_action_copy = XInternAtom(x11_display, "XdndActionCopy", False); - xdnd_drop = XInternAtom(x11_display, "XdndDrop", False); - xdnd_finished = XInternAtom(x11_display, "XdndFinished", False); - xdnd_selection = XInternAtom(x11_display, "XdndSelection", False); - requested = None; - - visual_server->init(); - - AudioDriverManager::initialize(p_audio_driver); +} - input = memnew(InputDefault); +void DisplayServerX11::_update_real_mouse_position(const WindowData &wd) { + Window root_return, child_return; + int root_x, root_y, win_x, win_y; + unsigned int mask_return; - window_has_focus = true; // Set focus to true at init -#ifdef JOYDEV_ENABLED - joypad = memnew(JoypadLinux(input)); -#endif - _ensure_user_data_dir(); + Bool xquerypointer_result = XQueryPointer(x11_display, wd.x11_window, &root_return, &child_return, &root_x, &root_y, + &win_x, &win_y, &mask_return); - if (p_desired.layered) { - set_window_per_pixel_transparency_enabled(true); - } + if (xquerypointer_result) { + if (win_x > 0 && win_y > 0 && win_x <= wd.size.width && win_y <= wd.size.height) { - XEvent xevent; - while (XPending(x11_display) > 0) { - XNextEvent(x11_display, &xevent); - if (xevent.type == ConfigureNotify) { - _window_changed(&xevent); + last_mouse_pos.x = win_x; + last_mouse_pos.y = win_y; + last_mouse_pos_valid = true; + InputFilter::get_singleton()->set_mouse_position(last_mouse_pos); } } - - update_real_mouse_position(); - - return OK; } -bool OS_X11::refresh_device_info() { +bool DisplayServerX11::_refresh_device_info() { int event_base, error_base; print_verbose("XInput: Refreshing devices."); @@ -786,136 +323,35 @@ bool OS_X11::refresh_device_info() { return true; } -void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data, - ::XPointer call_data) { - - WARN_PRINT("Input method stopped"); - OS_X11 *os = reinterpret_cast<OS_X11 *>(client_data); - os->xim = NULL; - os->xic = NULL; -} - -void OS_X11::set_ime_active(const bool p_active) { - - im_active = p_active; - - if (!xic) - return; - - if (p_active) { - XSetICFocus(xic); - set_ime_position(im_position); - } else { - XUnsetICFocus(xic); - } -} - -void OS_X11::set_ime_position(const Point2 &p_pos) { - - im_position = p_pos; - - if (!xic) - return; - - ::XPoint spot; - spot.x = short(p_pos.x); - spot.y = short(p_pos.y); - XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); - XSetICValues(xic, XNPreeditAttributes, preedit_attr, NULL); - XFree(preedit_attr); -} +void DisplayServerX11::_flush_mouse_motion() { + while (true) { + if (XPending(x11_display) > 0) { + XEvent event; + XPeekEvent(x11_display, &event); -String OS_X11::get_unique_id() const { + if (XGetEventData(x11_display, &event.xcookie) && event.xcookie.type == GenericEvent && event.xcookie.extension == xi.opcode) { + XIDeviceEvent *event_data = (XIDeviceEvent *)event.xcookie.data; - static String machine_id; - if (machine_id.empty()) { - if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) { - while (machine_id.empty() && !f->eof_reached()) { - machine_id = f->get_line().strip_edges(); + if (event_data->evtype == XI_RawMotion) { + XNextEvent(x11_display, &event); + } else { + break; + } + } else { + break; } - f->close(); - memdelete(f); - } - } - return machine_id; -} - -void OS_X11::finalize() { - - if (main_loop) - memdelete(main_loop); - main_loop = NULL; - - /* - if (debugger_connection_console) { - memdelete(debugger_connection_console); - } - */ -#ifdef ALSAMIDI_ENABLED - driver_alsamidi.close(); -#endif - -#ifdef JOYDEV_ENABLED - memdelete(joypad); -#endif - - xi.touch_devices.clear(); - xi.state.clear(); - - memdelete(input); - - cursors_cache.clear(); - visual_server->finish(); - memdelete(visual_server); - -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - if (context_gles2) - memdelete(context_gles2); - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - if (rendering_device_vulkan) { - rendering_device_vulkan->finalize(); - memdelete(rendering_device_vulkan); + } else { + break; } - - if (context_vulkan) - memdelete(context_vulkan); - } -#endif - - if (xrandr_handle) - dlclose(xrandr_handle); - - XUnmapWindow(x11_display, x11_window); - XDestroyWindow(x11_display, x11_window); - - for (int i = 0; i < CURSOR_MAX; i++) { - if (cursors[i] != None) - XFreeCursor(x11_display, cursors[i]); - if (img[i] != NULL) - XcursorImageDestroy(img[i]); - }; - - if (xic) { - XDestroyIC(xic); } - if (xim) { - XCloseIM(xim); - } - - XCloseDisplay(x11_display); - if (xmbstring) - memfree(xmbstring); - args.clear(); + xi.relative_motion.x = 0; + xi.relative_motion.y = 0; } -void OS_X11::set_mouse_mode(MouseMode p_mode) { +void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { + + _THREAD_SAFE_METHOD_ if (p_mode == mouse_mode) return; @@ -926,34 +362,37 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { // The only modes that show a cursor are VISIBLE and CONFINED bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); - if (showCursor) { - XDefineCursor(x11_display, x11_window, cursors[current_cursor]); // show cursor - } else { - XDefineCursor(x11_display, x11_window, null_cursor); // hide cursor - } + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (showCursor) { + XDefineCursor(x11_display, E->get().x11_window, cursors[current_cursor]); // show cursor + } else { + XDefineCursor(x11_display, E->get().x11_window, null_cursor); // hide cursor + } + } mouse_mode = p_mode; if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) { //flush pending motion events - flush_mouse_motion(); + _flush_mouse_motion(); + WindowData &main_window = windows[MAIN_WINDOW_ID]; if (XGrabPointer( - x11_display, x11_window, True, + x11_display, main_window.x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime) != GrabSuccess) { + GrabModeAsync, GrabModeAsync, windows[MAIN_WINDOW_ID].x11_window, None, CurrentTime) != GrabSuccess) { ERR_PRINT("NO GRAB"); } if (mouse_mode == MOUSE_MODE_CAPTURED) { - center.x = current_videomode.width / 2; - center.y = current_videomode.height / 2; + center.x = main_window.size.width / 2; + center.y = main_window.size.height / 2; - XWarpPointer(x11_display, None, x11_window, + XWarpPointer(x11_display, None, main_window.x11_window, 0, 0, 0, 0, (int)center.x, (int)center.y); - input->set_mouse_position(center); + InputFilter::get_singleton()->set_mouse_position(center); } } else { do_mouse_warp = false; @@ -961,8 +400,13 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { XFlush(x11_display); } +DisplayServerX11::MouseMode DisplayServerX11::mouse_get_mode() const { + return mouse_mode; +} -void OS_X11::warp_mouse_position(const Point2 &p_to) { +void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) { + + _THREAD_SAFE_METHOD_ if (mouse_mode == MOUSE_MODE_CAPTURED) { @@ -973,184 +417,133 @@ void OS_X11::warp_mouse_position(const Point2 &p_to) { XGetWindowAttributes(x11_display, x11_window, &xwa); printf("%d %d\n", xwa.x, xwa.y); needed? */ - XWarpPointer(x11_display, None, x11_window, + XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, 0, 0, 0, 0, (int)p_to.x, (int)p_to.y); } } -void OS_X11::flush_mouse_motion() { - while (true) { - if (XPending(x11_display) > 0) { - XEvent event; - XPeekEvent(x11_display, &event); +Point2i DisplayServerX11::mouse_get_position() const { + return last_mouse_pos; +} - if (XGetEventData(x11_display, &event.xcookie) && event.xcookie.type == GenericEvent && event.xcookie.extension == xi.opcode) { - XIDeviceEvent *event_data = (XIDeviceEvent *)event.xcookie.data; +Point2i DisplayServerX11::mouse_get_absolute_position() const { + int number_of_screens = XScreenCount(x11_display); + for (int i = 0; i < number_of_screens; i++) { + Window root, child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + if (XQueryPointer(x11_display, XRootWindow(x11_display, i), &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) { + XWindowAttributes root_attrs; + XGetWindowAttributes(x11_display, root, &root_attrs); - if (event_data->evtype == XI_RawMotion) { - XNextEvent(x11_display, &event); - } else { - break; - } - } else { - break; - } - } else { - break; + return Vector2i(root_attrs.x + root_x, root_attrs.y + root_y); } } - - xi.relative_motion.x = 0; - xi.relative_motion.y = 0; -} - -OS::MouseMode OS_X11::get_mouse_mode() const { - return mouse_mode; + return Vector2i(); } -int OS_X11::get_mouse_button_state() const { +int DisplayServerX11::mouse_get_button_state() const { return last_button_state; } -Point2 OS_X11::get_mouse_position() const { - return last_mouse_pos; -} +void DisplayServerX11::clipboard_set(const String &p_text) { -bool OS_X11::get_window_per_pixel_transparency_enabled() const { + _THREAD_SAFE_METHOD_ - if (!is_layered_allowed()) return false; - return layered_window; + internal_clipboard = p_text; + XSetSelectionOwner(x11_display, XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window, CurrentTime); + XSetSelectionOwner(x11_display, XInternAtom(x11_display, "CLIPBOARD", 0), windows[MAIN_WINDOW_ID].x11_window, CurrentTime); } -void OS_X11::set_window_per_pixel_transparency_enabled(bool p_enabled) { +static String _clipboard_get_impl(Atom p_source, Window x11_window, ::Display *x11_display, String p_internal_clipboard, Atom target) { - if (!is_layered_allowed()) return; - if (layered_window != p_enabled) { - if (p_enabled) { - set_borderless_window(true); - layered_window = true; - } else { - layered_window = false; - } - } -} - -void OS_X11::set_window_title(const String &p_title) { - XStoreName(x11_display, x11_window, p_title.utf8().get_data()); + String ret; - Atom _net_wm_name = XInternAtom(x11_display, "_NET_WM_NAME", false); - Atom utf8_string = XInternAtom(x11_display, "UTF8_STRING", false); - XChangeProperty(x11_display, x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length()); -} + Atom type; + Atom selection = XA_PRIMARY; + int format, result; + unsigned long len, bytes_left, dummy; + unsigned char *data; + Window Sown = XGetSelectionOwner(x11_display, p_source); -void OS_X11::set_video_mode(const VideoMode &p_video_mode, int p_screen) { -} + if (Sown == x11_window) { -OS::VideoMode OS_X11::get_video_mode(int p_screen) const { - return current_videomode; -} + return p_internal_clipboard; + }; -void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { -} + if (Sown != None) { + XConvertSelection(x11_display, p_source, target, selection, + x11_window, CurrentTime); + XFlush(x11_display); + while (true) { + XEvent event; + XNextEvent(x11_display, &event); + if (event.type == SelectionNotify && event.xselection.requestor == x11_window) { + break; + }; + }; -void OS_X11::set_wm_fullscreen(bool p_enabled) { - if (p_enabled && !get_borderless_window()) { - // remove decorations if the window is not already borderless - Hints hints; - Atom property; - hints.flags = 2; - hints.decorations = 0; - property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); - XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + // + // Do not get any data, see how much data is there + // + XGetWindowProperty(x11_display, x11_window, + selection, // Tricky.. + 0, 0, // offset - len + 0, // Delete 0==FALSE + AnyPropertyType, //flag + &type, // return type + &format, // return format + &len, &bytes_left, //that + &data); + // DATA is There + if (bytes_left > 0) { + result = XGetWindowProperty(x11_display, x11_window, + selection, 0, bytes_left, 0, + AnyPropertyType, &type, &format, + &len, &dummy, &data); + if (result == Success) { + ret.parse_utf8((const char *)data); + } else + printf("FAIL\n"); + if (data) { + XFree(data); + } + } } - if (p_enabled && !is_window_resizable()) { - // Set the window as resizable to prevent window managers to ignore the fullscreen state flag. - XSizeHints *xsh; + return ret; +} - xsh = XAllocSizeHints(); - xsh->flags = 0L; - XSetWMNormalHints(x11_display, x11_window, xsh); - XFree(xsh); +static String _clipboard_get(Atom p_source, Window x11_window, ::Display *x11_display, String p_internal_clipboard) { + String ret; + Atom utf8_atom = XInternAtom(x11_display, "UTF8_STRING", True); + if (utf8_atom != None) { + ret = _clipboard_get_impl(p_source, x11_window, x11_display, p_internal_clipboard, utf8_atom); } + if (ret == "") { + ret = _clipboard_get_impl(p_source, x11_window, x11_display, p_internal_clipboard, XA_STRING); + } + return ret; +} - // Using EWMH -- Extended Window Manager Hints - XEvent xev; - Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); - Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); - - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.xclient.window = x11_window; - xev.xclient.message_type = wm_state; - xev.xclient.format = 32; - xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - xev.xclient.data.l[1] = wm_fullscreen; - xev.xclient.data.l[2] = 0; - - XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +String DisplayServerX11::clipboard_get() const { - // set bypass compositor hint - Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False); - unsigned long compositing_disable_on = p_enabled ? 1 : 0; - XChangeProperty(x11_display, x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1); + _THREAD_SAFE_METHOD_ - XFlush(x11_display); + String ret; + ret = _clipboard_get(XInternAtom(x11_display, "CLIPBOARD", 0), windows[MAIN_WINDOW_ID].x11_window, x11_display, internal_clipboard); - if (!p_enabled) { - // Reset the non-resizable flags if we un-set these before. - Size2 size = get_window_size(); - XSizeHints *xsh; - xsh = XAllocSizeHints(); - if (!is_window_resizable()) { - xsh->flags = PMinSize | PMaxSize; - xsh->min_width = size.x; - xsh->max_width = size.x; - xsh->min_height = size.y; - xsh->max_height = size.y; - } else { - xsh->flags = 0L; - if (min_size != Size2()) { - xsh->flags |= PMinSize; - xsh->min_width = min_size.x; - xsh->min_height = min_size.y; - } - if (max_size != Size2()) { - xsh->flags |= PMaxSize; - xsh->max_width = max_size.x; - xsh->max_height = max_size.y; - } - } - XSetWMNormalHints(x11_display, x11_window, xsh); - XFree(xsh); + if (ret == "") { + ret = _clipboard_get(XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window, x11_display, internal_clipboard); + }; - // put back or remove decorations according to the last set borderless state - Hints hints; - Atom property; - hints.flags = 2; - hints.decorations = current_videomode.borderless_window ? 0 : 1; - property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); - XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); - } + return ret; } -void OS_X11::set_wm_above(bool p_enabled) { - Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); - Atom wm_above = XInternAtom(x11_display, "_NET_WM_STATE_ABOVE", False); +int DisplayServerX11::get_screen_count() const { - XClientMessageEvent xev; - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.window = x11_window; - xev.message_type = wm_state; - xev.format = 32; - xev.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - xev.data.l[1] = wm_above; - xev.data.l[3] = 1; - XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev); -} + _THREAD_SAFE_METHOD_ -int OS_X11::get_screen_count() const { // Using Xinerama Extension int event_base, error_base; const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); @@ -1161,42 +554,12 @@ int OS_X11::get_screen_count() const { XFree(xsi); return count; } +Point2i DisplayServerX11::screen_get_position(int p_screen) const { -int OS_X11::get_current_screen() const { - int x, y; - Window child; - XTranslateCoordinates(x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + _THREAD_SAFE_METHOD_ - int count = get_screen_count(); - for (int i = 0; i < count; i++) { - Point2i pos = get_screen_position(i); - Size2i size = get_screen_size(i); - if ((x >= pos.x && x < pos.x + size.width) && (y >= pos.y && y < pos.y + size.height)) - return i; - } - return 0; -} - -void OS_X11::set_current_screen(int p_screen) { - int count = get_screen_count(); - if (p_screen >= count) return; - - if (current_videomode.fullscreen) { - Point2i position = get_screen_position(p_screen); - Size2i size = get_screen_size(p_screen); - - XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y); - } else { - if (p_screen != get_current_screen()) { - Point2i position = get_screen_position(p_screen); - XMoveWindow(x11_display, x11_window, position.x, position.y); - } - } -} - -Point2 OS_X11::get_screen_position(int p_screen) const { - if (p_screen == -1) { - p_screen = get_current_screen(); + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); } // Using Xinerama Extension @@ -1219,39 +582,48 @@ Point2 OS_X11::get_screen_position(int p_screen) const { return position; } -Size2 OS_X11::get_screen_size(int p_screen) const { - if (p_screen == -1) { - p_screen = get_current_screen(); +Size2i DisplayServerX11::screen_get_size(int p_screen) const { + return screen_get_usable_rect(p_screen).size; +} + +Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const { + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); } // Using Xinerama Extension int event_base, error_base; const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); - if (!ext_okay) return Size2i(0, 0); + if (!ext_okay) return Rect2i(0, 0, 0, 0); int count; XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &count); - if (p_screen >= count) return Size2i(0, 0); + if (p_screen >= count) return Rect2i(0, 0, 0, 0); - Size2i size = Point2i(xsi[p_screen].width, xsi[p_screen].height); + Rect2i rect = Rect2i(xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height); XFree(xsi); - return size; + return rect; } -int OS_X11::get_screen_dpi(int p_screen) const { - if (p_screen == -1) { - p_screen = get_current_screen(); +int DisplayServerX11::screen_get_dpi(int p_screen) const { + + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); } //invalid screen? ERR_FAIL_INDEX_V(p_screen, get_screen_count(), 0); //Get physical monitor Dimensions through XRandR and calculate dpi - Size2 sc = get_screen_size(p_screen); + Size2i sc = screen_get_size(p_screen); if (xrandr_ext_ok) { int count = 0; if (xrr_get_monitors) { - xrr_monitor_info *monitors = xrr_get_monitors(x11_display, x11_window, true, &count); + xrr_monitor_info *monitors = xrr_get_monitors(x11_display, windows[MAIN_WINDOW_ID].x11_window, true, &count); if (p_screen < count) { double xdpi = sc.width / (double)monitors[p_screen].mwidth * 25.4; double ydpi = sc.height / (double)monitors[p_screen].mheight * 25.4; @@ -1279,18 +651,249 @@ int OS_X11::get_screen_dpi(int p_screen) const { //could not get dpi return 96; } +bool DisplayServerX11::screen_is_touchscreen(int p_screen) const { + + _THREAD_SAFE_METHOD_ + +#ifndef _MSC_VER +#warning Need to get from proper window +#endif + + return DisplayServer::screen_is_touchscreen(p_screen); +} + +Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const { + _THREAD_SAFE_METHOD_ + + Vector<int> ret; + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + return ret; +} + +DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { + + _THREAD_SAFE_METHOD_ + + WindowID id = _create_window(p_mode, p_flags, p_rect); + for (int i = 0; i < WINDOW_FLAG_MAX; i++) { + if (p_flags & (1 << i)) { + window_set_flag(WindowFlags(i), true, id); + } + } + + return id; +} + +void DisplayServerX11::delete_sub_window(WindowID p_id) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_id)); + ERR_FAIL_COND_MSG(p_id == MAIN_WINDOW_ID, "Main window can't be deleted"); //ma + + WindowData &wd = windows[p_id]; + + while (wd.transient_children.size()) { + window_set_transient(wd.transient_children.front()->get(), INVALID_WINDOW_ID); + } + + if (wd.transient_parent != INVALID_WINDOW_ID) { + window_set_transient(p_id, INVALID_WINDOW_ID); + } + +#ifdef VULKAN_ENABLED + if (rendering_driver == "vulkan") { + context_vulkan->window_destroy(p_id); + } +#endif + XUnmapWindow(x11_display, wd.x11_window); + XDestroyWindow(x11_display, wd.x11_window); + if (wd.xic) { + XDestroyIC(wd.xic); + } + + windows.erase(p_id); +} + +void DisplayServerX11::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.instance_id = p_instance; +} + +ObjectID DisplayServerX11::window_get_attached_instance_id(WindowID p_window) const { + + ERR_FAIL_COND_V(!windows.has(p_window), ObjectID()); + const WindowData &wd = windows[p_window]; + return wd.instance_id; +} + +DisplayServerX11::WindowID DisplayServerX11::get_window_at_screen_position(const Point2i &p_position) const { + + return INVALID_WINDOW_ID; +} + +void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + XStoreName(x11_display, wd.x11_window, p_title.utf8().get_data()); + + Atom _net_wm_name = XInternAtom(x11_display, "_NET_WM_NAME", false); + Atom utf8_string = XInternAtom(x11_display, "UTF8_STRING", false); + XChangeProperty(x11_display, wd.x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length()); +} + +void DisplayServerX11::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.rect_changed_callback = p_callable; +} + +void DisplayServerX11::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.event_callback = p_callable; +} + +void DisplayServerX11::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.input_event_callback = p_callable; +} +void DisplayServerX11::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.input_text_callback = p_callable; +} + +void DisplayServerX11::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.drop_files_callback = p_callable; +} + +int DisplayServerX11::window_get_current_screen(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), -1); + const WindowData &wd = windows[p_window]; -Point2 OS_X11::get_window_position() const { int x, y; Window child; - XTranslateCoordinates(x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); - return Point2i(x, y); + XTranslateCoordinates(x11_display, wd.x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + + int count = get_screen_count(); + for (int i = 0; i < count; i++) { + Point2i pos = screen_get_position(i); + Size2i size = screen_get_size(i); + if ((x >= pos.x && x < pos.x + size.width) && (y >= pos.y && y < pos.y + size.height)) + return i; + } + return 0; +} +void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + int count = get_screen_count(); + if (p_screen >= count) return; + + if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) { + Point2i position = screen_get_position(p_screen); + Size2i size = screen_get_size(p_screen); + + XMoveResizeWindow(x11_display, wd.x11_window, position.x, position.y, size.x, size.y); + } else { + if (p_screen != window_get_current_screen(p_window)) { + Point2i position = screen_get_position(p_screen); + XMoveWindow(x11_display, wd.x11_window, position.x, position.y); + } + } +} + +void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(p_window == p_parent); + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd_window = windows[p_window]; + + ERR_FAIL_COND(wd_window.transient_parent == p_parent); + + ERR_FAIL_COND_MSG(wd_window.on_top, "Windows with the 'on top' can't become transient."); + if (p_parent == INVALID_WINDOW_ID) { + //remove transient + + ERR_FAIL_COND(wd_window.transient_parent == INVALID_WINDOW_ID); + ERR_FAIL_COND(!windows.has(wd_window.transient_parent)); + + WindowData &wd_parent = windows[wd_window.transient_parent]; + + wd_window.transient_parent = INVALID_WINDOW_ID; + wd_parent.transient_children.erase(p_window); + + XSetTransientForHint(x11_display, wd_window.x11_window, None); + } else { + ERR_FAIL_COND(!windows.has(p_parent)); + ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent"); + WindowData &wd_parent = windows[p_parent]; + + wd_window.transient_parent = p_parent; + wd_parent.transient_children.insert(p_window); + + XSetTransientForHint(x11_display, wd_window.x11_window, wd_parent.x11_window); + } +} + +Point2i DisplayServerX11::window_get_position(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Point2i()); + const WindowData &wd = windows[p_window]; + + return wd.position; } -void OS_X11::set_window_position(const Point2 &p_position) { +void DisplayServerX11::window_set_position(const Point2i &p_position, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + int x = 0; int y = 0; - if (!get_borderless_window()) { + if (!window_get_flag(WINDOW_FLAG_BORDERLESS, p_window)) { //exclude window decorations XSync(x11_display, False); Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True); @@ -1300,8 +903,8 @@ void OS_X11::set_window_position(const Point2 &p_position) { unsigned long len; unsigned long remaining; unsigned char *data = NULL; - if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { - if (format == 32 && len == 4) { + if (XGetWindowProperty(x11_display, wd.x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { + if (format == 32 && len == 4 && data) { long *extents = (long *)data; x = extents[0]; y = extents[2]; @@ -1310,153 +913,151 @@ void OS_X11::set_window_position(const Point2 &p_position) { } } } - XMoveWindow(x11_display, x11_window, p_position.x - x, p_position.y - y); - update_real_mouse_position(); + XMoveWindow(x11_display, wd.x11_window, p_position.x - x, p_position.y - y); + _update_real_mouse_position(wd); } -Size2 OS_X11::get_window_size() const { - // Use current_videomode width and height instead of XGetWindowAttributes - // since right after a XResizeWindow the attributes may not be updated yet - return Size2i(current_videomode.width, current_videomode.height); -} +void DisplayServerX11::window_set_max_size(const Size2i p_size, WindowID p_window) { -Size2 OS_X11::get_real_window_size() const { - XWindowAttributes xwa; - XSync(x11_display, False); - XGetWindowAttributes(x11_display, x11_window, &xwa); - int w = xwa.width; - int h = xwa.height; - Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True); - if (prop != None) { - Atom type; - int format; - unsigned long len; - unsigned long remaining; - unsigned char *data = NULL; - if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { - if (format == 32 && len == 4) { - long *extents = (long *)data; - w += extents[0] + extents[1]; // left, right - h += extents[2] + extents[3]; // top, bottom - } - XFree(data); - } - } - return Size2(w, h); -} + _THREAD_SAFE_METHOD_ -Size2 OS_X11::get_max_window_size() const { - return max_size; -} - -Size2 OS_X11::get_min_window_size() const { - return min_size; -} + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; -void OS_X11::set_min_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { - ERR_PRINT("Minimum window size can't be larger than maximum window size!"); + if ((p_size != Size2i()) && ((p_size.x < wd.min_size.x) || (p_size.y < wd.min_size.y))) { + ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); return; } - min_size = p_size; + wd.max_size = p_size; - if (is_window_resizable()) { + if (!window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) { XSizeHints *xsh; xsh = XAllocSizeHints(); xsh->flags = 0L; - if (min_size != Size2()) { + if (wd.min_size != Size2i()) { xsh->flags |= PMinSize; - xsh->min_width = min_size.x; - xsh->min_height = min_size.y; + xsh->min_width = wd.min_size.x; + xsh->min_height = wd.min_size.y; } - if (max_size != Size2()) { + if (wd.max_size != Size2i()) { xsh->flags |= PMaxSize; - xsh->max_width = max_size.x; - xsh->max_height = max_size.y; + xsh->max_width = wd.max_size.x; + xsh->max_height = wd.max_size.y; } - XSetWMNormalHints(x11_display, x11_window, xsh); + XSetWMNormalHints(x11_display, wd.x11_window, xsh); XFree(xsh); XFlush(x11_display); } } +Size2i DisplayServerX11::window_get_max_size(WindowID p_window) const { -void OS_X11::set_max_window_size(const Size2 p_size) { + _THREAD_SAFE_METHOD_ - if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { - ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + + return wd.max_size; +} + +void DisplayServerX11::window_set_min_size(const Size2i p_size, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if ((p_size != Size2i()) && (wd.max_size != Size2i()) && ((p_size.x > wd.max_size.x) || (p_size.y > wd.max_size.y))) { + ERR_PRINT("Minimum window size can't be larger than maximum window size!"); return; } - max_size = p_size; + wd.min_size = p_size; - if (is_window_resizable()) { + if (!window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) { XSizeHints *xsh; xsh = XAllocSizeHints(); xsh->flags = 0L; - if (min_size != Size2()) { + if (wd.min_size != Size2i()) { xsh->flags |= PMinSize; - xsh->min_width = min_size.x; - xsh->min_height = min_size.y; + xsh->min_width = wd.min_size.x; + xsh->min_height = wd.min_size.y; } - if (max_size != Size2()) { + if (wd.max_size != Size2i()) { xsh->flags |= PMaxSize; - xsh->max_width = max_size.x; - xsh->max_height = max_size.y; + xsh->max_width = wd.max_size.x; + xsh->max_height = wd.max_size.y; } - XSetWMNormalHints(x11_display, x11_window, xsh); + XSetWMNormalHints(x11_display, wd.x11_window, xsh); XFree(xsh); XFlush(x11_display); } } +Size2i DisplayServerX11::window_get_min_size(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ -void OS_X11::set_window_size(const Size2 p_size) { + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + + return wd.min_size; +} - if (current_videomode.width == p_size.width && current_videomode.height == p_size.height) +void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + + Size2i size = p_size; + size.x = MAX(1, size.x); + size.y = MAX(1, size.y); + + WindowData &wd = windows[p_window]; + + if (wd.size.width == size.width && wd.size.height == size.height) return; XWindowAttributes xwa; XSync(x11_display, False); - XGetWindowAttributes(x11_display, x11_window, &xwa); + XGetWindowAttributes(x11_display, wd.x11_window, &xwa); int old_w = xwa.width; int old_h = xwa.height; // If window resizable is disabled we need to update the attributes first XSizeHints *xsh; xsh = XAllocSizeHints(); - if (!is_window_resizable()) { + if (!window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) { xsh->flags = PMinSize | PMaxSize; - xsh->min_width = p_size.x; - xsh->max_width = p_size.x; - xsh->min_height = p_size.y; - xsh->max_height = p_size.y; + xsh->min_width = size.x; + xsh->max_width = size.x; + xsh->min_height = size.y; + xsh->max_height = size.y; } else { xsh->flags = 0L; - if (min_size != Size2()) { + if (wd.min_size != Size2i()) { xsh->flags |= PMinSize; - xsh->min_width = min_size.x; - xsh->min_height = min_size.y; + xsh->min_width = wd.min_size.x; + xsh->min_height = wd.min_size.y; } - if (max_size != Size2()) { + if (wd.max_size != Size2i()) { xsh->flags |= PMaxSize; - xsh->max_width = max_size.x; - xsh->max_height = max_size.y; + xsh->max_width = wd.max_size.x; + xsh->max_height = wd.max_size.y; } } - XSetWMNormalHints(x11_display, x11_window, xsh); + XSetWMNormalHints(x11_display, wd.x11_window, xsh); XFree(xsh); // Resize the window - XResizeWindow(x11_display, x11_window, p_size.x, p_size.y); + XResizeWindow(x11_display, wd.x11_window, size.x, size.y); // Update our videomode width and height - current_videomode.width = p_size.x; - current_videomode.height = p_size.y; + wd.size = size; for (int timeout = 0; timeout < 50; ++timeout) { XSync(x11_display, False); - XGetWindowAttributes(x11_display, x11_window, &xwa); + XGetWindowAttributes(x11_display, wd.x11_window, &xwa); if (old_w != xwa.width || old_h != xwa.height) break; @@ -1464,105 +1065,53 @@ void OS_X11::set_window_size(const Size2 p_size) { usleep(10000); } } +Size2i DisplayServerX11::window_get_size(WindowID p_window) const { -void OS_X11::set_window_fullscreen(bool p_enabled) { - - if (current_videomode.fullscreen == p_enabled) - return; + _THREAD_SAFE_METHOD_ - if (layered_window) - set_window_per_pixel_transparency_enabled(false); - - if (p_enabled && current_videomode.always_on_top) { - // Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity) - set_window_maximized(true); - } - set_wm_fullscreen(p_enabled); - if (!p_enabled && current_videomode.always_on_top) { - // Restore - set_window_maximized(false); - } - if (!p_enabled) { - set_window_position(last_position_before_fs); - } else { - last_position_before_fs = get_window_position(); - } - current_videomode.fullscreen = p_enabled; + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + return wd.size; } +Size2i DisplayServerX11::window_get_real_size(WindowID p_window) const { -bool OS_X11::is_window_fullscreen() const { - return current_videomode.fullscreen; -} + _THREAD_SAFE_METHOD_ -void OS_X11::set_window_resizable(bool p_enabled) { + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; - XSizeHints *xsh; - xsh = XAllocSizeHints(); - if (!p_enabled) { - Size2 size = get_window_size(); - - xsh->flags = PMinSize | PMaxSize; - xsh->min_width = size.x; - xsh->max_width = size.x; - xsh->min_height = size.y; - xsh->max_height = size.y; - } else { - xsh->flags = 0L; - if (min_size != Size2()) { - xsh->flags |= PMinSize; - xsh->min_width = min_size.x; - xsh->min_height = min_size.y; - } - if (max_size != Size2()) { - xsh->flags |= PMaxSize; - xsh->max_width = max_size.x; - xsh->max_height = max_size.y; + XWindowAttributes xwa; + XSync(x11_display, False); + XGetWindowAttributes(x11_display, wd.x11_window, &xwa); + int w = xwa.width; + int h = xwa.height; + Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True); + if (prop != None) { + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + if (XGetWindowProperty(x11_display, wd.x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { + if (format == 32 && len == 4 && data) { + long *extents = (long *)data; + w += extents[0] + extents[1]; // left, right + h += extents[2] + extents[3]; // top, bottom + } + XFree(data); } } - - XSetWMNormalHints(x11_display, x11_window, xsh); - XFree(xsh); - - current_videomode.resizable = p_enabled; - - XFlush(x11_display); -} - -bool OS_X11::is_window_resizable() const { - return current_videomode.resizable; + return Size2i(w, h); } -void OS_X11::set_window_minimized(bool p_enabled) { - // Using ICCCM -- Inter-Client Communication Conventions Manual - XEvent xev; - Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False); - - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.xclient.window = x11_window; - xev.xclient.message_type = wm_change; - xev.xclient.format = 32; - xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState; - - XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - - Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); - Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False); +bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.xclient.window = x11_window; - xev.xclient.message_type = wm_state; - xev.xclient.format = 32; - xev.xclient.data.l[0] = _NET_WM_STATE_ADD; - xev.xclient.data.l[1] = wm_hidden; + _THREAD_SAFE_METHOD_ - XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); -} + ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; -bool OS_X11::is_window_minimized() const { - // Using ICCCM -- Inter-Client Communication Conventions Manual - Atom property = XInternAtom(x11_display, "WM_STATE", True); + Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False); Atom type; int format; unsigned long len; @@ -1571,29 +1120,44 @@ bool OS_X11::is_window_minimized() const { int result = XGetWindowProperty( x11_display, - x11_window, + wd.x11_window, property, 0, - 32, + 1024, False, - AnyPropertyType, + XA_ATOM, &type, &format, &len, &remaining, &data); - if (result == Success) { - long *state = (long *)data; - if (state[0] == WM_IconicState) - return true; + if (result == Success && data) { + Atom *atoms = (Atom *)data; + Atom wm_act_max_horz = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); + Atom wm_act_max_vert = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_VERT", False); + bool found_wm_act_max_horz = false; + bool found_wm_act_max_vert = false; + + for (uint64_t i = 0; i < len; i++) { + if (atoms[i] == wm_act_max_horz) + found_wm_act_max_horz = true; + if (atoms[i] == wm_act_max_vert) + found_wm_act_max_vert = true; + + if (found_wm_act_max_horz || found_wm_act_max_vert) + return true; + } + XFree(atoms); } + return false; } -void OS_X11::set_window_maximized(bool p_enabled) { - if (is_window_maximized() == p_enabled) - return; +void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) { + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; // Using EWMH -- Extended Window Manager Hints XEvent xev; @@ -1603,7 +1167,7 @@ void OS_X11::set_window_maximized(bool p_enabled) { memset(&xev, 0, sizeof(xev)); xev.type = ClientMessage; - xev.xclient.window = x11_window; + xev.xclient.window = wd.x11_window; xev.xclient.message_type = wm_state; xev.xclient.format = 32; xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; @@ -1612,178 +1176,454 @@ void OS_X11::set_window_maximized(bool p_enabled) { XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - if (p_enabled && is_window_maximize_allowed()) { + if (p_enabled && window_is_maximize_allowed(p_window)) { // Wait for effective resizing (so the GLX context is too). // Give up after 0.5s, it's not going to happen on this WM. // https://github.com/godotengine/godot/issues/19978 - for (int attempt = 0; !is_window_maximized() && attempt < 50; attempt++) { + for (int attempt = 0; window_get_mode(p_window) != WINDOW_MODE_MAXIMIZED && attempt < 50; attempt++) { usleep(10000); } } - - maximized = p_enabled; } -bool OS_X11::is_window_maximize_allowed() { - Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False); - Atom type; - int format; - unsigned long len; - unsigned long remaining; - unsigned char *data = NULL; +void DisplayServerX11::_set_wm_fullscreen(WindowID p_window, bool p_enabled) { - int result = XGetWindowProperty( - x11_display, - x11_window, - property, - 0, - 1024, - False, - XA_ATOM, - &type, - &format, - &len, - &remaining, - &data); + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; - if (result == Success) { - Atom *atoms = (Atom *)data; - Atom wm_act_max_horz = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); - Atom wm_act_max_vert = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_VERT", False); - bool found_wm_act_max_horz = false; - bool found_wm_act_max_vert = false; + if (p_enabled && !window_get_flag(WINDOW_FLAG_BORDERLESS, p_window)) { + // remove decorations if the window is not already borderless + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = 0; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + } - for (uint64_t i = 0; i < len; i++) { - if (atoms[i] == wm_act_max_horz) - found_wm_act_max_horz = true; - if (atoms[i] == wm_act_max_vert) - found_wm_act_max_vert = true; + if (p_enabled && window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) { + // Set the window as resizable to prevent window managers to ignore the fullscreen state flag. + XSizeHints *xsh; - if (found_wm_act_max_horz || found_wm_act_max_vert) - return true; - } - XFree(atoms); + xsh = XAllocSizeHints(); + xsh->flags = 0L; + XSetWMNormalHints(x11_display, wd.x11_window, xsh); + XFree(xsh); } - return false; -} - -bool OS_X11::is_window_maximized() const { // Using EWMH -- Extended Window Manager Hints - Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False); - Atom type; - int format; - unsigned long len; - unsigned long remaining; - unsigned char *data = NULL; - bool retval = false; + XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); - int result = XGetWindowProperty( - x11_display, - x11_window, - property, - 0, - 1024, - False, - XA_ATOM, - &type, - &format, - &len, - &remaining, - &data); + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = wm_fullscreen; + xev.xclient.data.l[2] = 0; - if (result == Success) { - Atom *atoms = (Atom *)data; - Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - bool found_wm_max_horz = false; - bool found_wm_max_vert = false; + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - for (uint64_t i = 0; i < len; i++) { - if (atoms[i] == wm_max_horz) - found_wm_max_horz = true; - if (atoms[i] == wm_max_vert) - found_wm_max_vert = true; + // set bypass compositor hint + Atom bypass_compositor = XInternAtom(x11_display, "_NET_WM_BYPASS_COMPOSITOR", False); + unsigned long compositing_disable_on = p_enabled ? 1 : 0; + XChangeProperty(x11_display, wd.x11_window, bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&compositing_disable_on, 1); - if (found_wm_max_horz && found_wm_max_vert) { - retval = true; - break; + XFlush(x11_display); + + if (!p_enabled) { + // Reset the non-resizable flags if we un-set these before. + Size2i size = window_get_size(p_window); + XSizeHints *xsh; + xsh = XAllocSizeHints(); + if (window_get_flag(WINDOW_FLAG_RESIZE_DISABLED, p_window)) { + xsh->flags = PMinSize | PMaxSize; + xsh->min_width = size.x; + xsh->max_width = size.x; + xsh->min_height = size.y; + xsh->max_height = size.y; + } else { + xsh->flags = 0L; + if (wd.min_size != Size2i()) { + xsh->flags |= PMinSize; + xsh->min_width = wd.min_size.x; + xsh->min_height = wd.min_size.y; + } + if (wd.max_size != Size2i()) { + xsh->flags |= PMaxSize; + xsh->max_width = wd.max_size.x; + xsh->max_height = wd.max_size.y; } } - } + XSetWMNormalHints(x11_display, wd.x11_window, xsh); + XFree(xsh); - XFree(data); - return retval; + // put back or remove decorations according to the last set borderless state + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = window_get_flag(WINDOW_FLAG_BORDERLESS, p_window) ? 0 : 1; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + } } -void OS_X11::set_window_always_on_top(bool p_enabled) { - if (is_window_always_on_top() == p_enabled) - return; +void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) { - if (p_enabled && current_videomode.fullscreen) { - // Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity) - set_window_maximized(true); - } - set_wm_above(p_enabled); - if (!p_enabled && !current_videomode.fullscreen) { - // Restore - set_window_maximized(false); + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + WindowMode old_mode = window_get_mode(p_window); + if (old_mode == p_mode) { + return; // do nothing } + //remove all "extra" modes - current_videomode.always_on_top = p_enabled; -} + switch (old_mode) { + case WINDOW_MODE_WINDOWED: { + //do nothing + } break; + case WINDOW_MODE_MINIMIZED: { + //Un-Minimize + // Using ICCCM -- Inter-Client Communication Conventions Manual + XEvent xev; + Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = wm_change; + xev.xclient.format = 32; + xev.xclient.data.l[0] = WM_NormalState; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + xev.xclient.data.l[1] = wm_hidden; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } break; + case WINDOW_MODE_FULLSCREEN: { + //Remove full-screen + _set_wm_fullscreen(p_window, false); -bool OS_X11::is_window_always_on_top() const { - return current_videomode.always_on_top; -} + //un-maximize required for always on top + bool on_top = window_get_flag(WINDOW_FLAG_ALWAYS_ON_TOP, p_window); -bool OS_X11::is_window_focused() const { - return window_focused; -} + wd.fullscreen = false; -void OS_X11::set_borderless_window(bool p_borderless) { + window_set_position(wd.last_position_before_fs, p_window); - if (get_borderless_window() == p_borderless) - return; + if (on_top) { + _set_wm_maximized(p_window, false); + } - if (!p_borderless && layered_window) - set_window_per_pixel_transparency_enabled(false); + } break; + case WINDOW_MODE_MAXIMIZED: { - current_videomode.borderless_window = p_borderless; + _set_wm_maximized(p_window, false); + } break; + } - Hints hints; - Atom property; - hints.flags = 2; - hints.decorations = current_videomode.borderless_window ? 0 : 1; - property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); - XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + switch (p_mode) { + case WINDOW_MODE_WINDOWED: { + //do nothing + } break; + case WINDOW_MODE_MINIMIZED: { + // Using ICCCM -- Inter-Client Communication Conventions Manual + XEvent xev; + Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = wm_change; + xev.xclient.format = 32; + xev.xclient.data.l[0] = WM_IconicState; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + xev.xclient.data.l[1] = wm_hidden; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } break; + case WINDOW_MODE_FULLSCREEN: { + wd.last_position_before_fs = wd.position; + if (window_get_flag(WINDOW_FLAG_ALWAYS_ON_TOP, p_window)) { + _set_wm_maximized(p_window, true); + } + _set_wm_fullscreen(p_window, true); + wd.fullscreen = true; + } break; + case WINDOW_MODE_MAXIMIZED: { + + _set_wm_maximized(p_window, true); - // Preserve window size - set_window_size(Size2(current_videomode.width, current_videomode.height)); + } break; + } } -bool OS_X11::get_borderless_window() { +DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) const { - bool borderless = current_videomode.borderless_window; - Atom prop = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); - if (prop != None) { + _THREAD_SAFE_METHOD_ + ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED); + const WindowData &wd = windows[p_window]; + + if (wd.fullscreen) { //if fullscreen, it's not in another mode + return WINDOW_MODE_FULLSCREEN; + } + { //test maximized + // Using EWMH -- Extended Window Manager Hints + Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False); Atom type; int format; unsigned long len; unsigned long remaining; unsigned char *data = NULL; - if (XGetWindowProperty(x11_display, x11_window, prop, 0, sizeof(Hints), False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { - if (data && (format == 32) && (len >= 5)) { - borderless = !((Hints *)data)->decorations; + bool retval = false; + + int result = XGetWindowProperty( + x11_display, + wd.x11_window, + property, + 0, + 1024, + False, + XA_ATOM, + &type, + &format, + &len, + &remaining, + &data); + + if (result == Success && data) { + Atom *atoms = (Atom *)data; + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + bool found_wm_max_horz = false; + bool found_wm_max_vert = false; + + for (uint64_t i = 0; i < len; i++) { + if (atoms[i] == wm_max_horz) + found_wm_max_horz = true; + if (atoms[i] == wm_max_vert) + found_wm_max_vert = true; + + if (found_wm_max_horz && found_wm_max_vert) { + retval = true; + break; + } } + XFree(data); } + + if (retval) { + return WINDOW_MODE_MAXIMIZED; + } + } + + { // test minimzed + // Using ICCCM -- Inter-Client Communication Conventions Manual + Atom property = XInternAtom(x11_display, "WM_STATE", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + wd.x11_window, + property, + 0, + 32, + False, + AnyPropertyType, + &type, + &format, + &len, + &remaining, + &data); + + if (result == Success && data) { + long *state = (long *)data; + if (state[0] == WM_IconicState) + return WINDOW_MODE_MINIMIZED; + } + } + + // all other discarded, return windowed. + + return WINDOW_MODE_WINDOWED; +} + +void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + switch (p_flag) { + case WINDOW_FLAG_RESIZE_DISABLED: { + XSizeHints *xsh; + xsh = XAllocSizeHints(); + if (p_enabled) { + Size2i size = window_get_size(p_window); + + xsh->flags = PMinSize | PMaxSize; + xsh->min_width = size.x; + xsh->max_width = size.x; + xsh->min_height = size.y; + xsh->max_height = size.y; + } else { + xsh->flags = 0L; + if (wd.min_size != Size2i()) { + xsh->flags |= PMinSize; + xsh->min_width = wd.min_size.x; + xsh->min_height = wd.min_size.y; + } + if (wd.max_size != Size2i()) { + xsh->flags |= PMaxSize; + xsh->max_width = wd.max_size.x; + xsh->max_height = wd.max_size.y; + } + } + + XSetWMNormalHints(x11_display, wd.x11_window, xsh); + XFree(xsh); + + wd.resize_disabled = p_enabled; + + XFlush(x11_display); + + } break; + case WINDOW_FLAG_BORDERLESS: { + + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = p_enabled ? 0 : 1; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + + // Preserve window size + window_set_size(window_get_size(p_window), p_window); + + wd.borderless = p_enabled; + } break; + case WINDOW_FLAG_ALWAYS_ON_TOP: { + + ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID, "Can't make a window transient if the 'on top' flag is active."); + if (p_enabled && wd.fullscreen) { + _set_wm_maximized(p_window, true); + } + + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_above = XInternAtom(x11_display, "_NET_WM_STATE_ABOVE", False); + + XClientMessageEvent xev; + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.window = wd.x11_window; + xev.message_type = wm_state; + xev.format = 32; + xev.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.data.l[1] = wm_above; + xev.data.l[3] = 1; + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev); + + if (!p_enabled && !wd.fullscreen) { + _set_wm_maximized(p_window, false); + } + wd.on_top = p_enabled; + + } break; + case WINDOW_FLAG_TRANSPARENT: { + //todo reimplement + } break; + default: { + } } - return borderless; } +bool DisplayServerX11::window_get_flag(WindowFlags p_flag, WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; + + switch (p_flag) { + case WINDOW_FLAG_RESIZE_DISABLED: { + + return wd.resize_disabled; + } break; + case WINDOW_FLAG_BORDERLESS: { + + bool borderless = wd.borderless; + Atom prop = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + if (prop != None) { + + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + if (XGetWindowProperty(x11_display, wd.x11_window, prop, 0, sizeof(Hints), False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { + if (data && (format == 32) && (len >= 5)) { + borderless = !((Hints *)data)->decorations; + } + if (data) { + XFree(data); + } + } + } + return borderless; + } break; + case WINDOW_FLAG_ALWAYS_ON_TOP: { -void OS_X11::request_attention() { + return wd.on_top; + } break; + case WINDOW_FLAG_TRANSPARENT: { + //todo reimplement + } break; + default: { + } + } + + return false; +} + +void DisplayServerX11::window_request_attention(WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; // Using EWMH -- Extended Window Manager Hints // // Sets the _NET_WM_STATE_DEMANDS_ATTENTION atom for WM_STATE @@ -1795,7 +1635,7 @@ void OS_X11::request_attention() { memset(&xev, 0, sizeof(xev)); xev.type = ClientMessage; - xev.xclient.window = x11_window; + xev.xclient.window = wd.x11_window; xev.xclient.message_type = wm_state; xev.xclient.format = 32; xev.xclient.data.l[0] = _NET_WM_STATE_ADD; @@ -1805,7 +1645,314 @@ void OS_X11::request_attention() { XFlush(x11_display); } -void OS_X11::get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state) { +void DisplayServerX11::window_move_to_foreground(WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + XEvent xev; + Atom net_active_window = XInternAtom(x11_display, "_NET_ACTIVE_WINDOW", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = net_active_window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = CurrentTime; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + XFlush(x11_display); +} + +bool DisplayServerX11::window_can_draw(WindowID p_window) const { + + //this seems to be all that is provided by X11 + return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED; +} +bool DisplayServerX11::can_any_window_draw() const { + + _THREAD_SAFE_METHOD_ + + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (window_get_mode(E->key()) != WINDOW_MODE_MINIMIZED) { + return true; + } + } + + return false; +} + +void DisplayServerX11::window_set_ime_active(const bool p_active, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.im_active = p_active; + + if (!wd.xic) + return; + + if (p_active) { + XSetICFocus(wd.xic); + window_set_ime_position(wd.im_position, p_window); + } else { + XUnsetICFocus(wd.xic); + } +} +void DisplayServerX11::window_set_ime_position(const Point2i &p_pos, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.im_position = p_pos; + + if (!wd.xic) + return; + + ::XPoint spot; + spot.x = short(p_pos.x); + spot.y = short(p_pos.y); + XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + XSetICValues(wd.xic, XNPreeditAttributes, preedit_attr, NULL); + XFree(preedit_attr); +} + +void DisplayServerX11::cursor_set_shape(CursorShape p_shape) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_INDEX(p_shape, CURSOR_MAX); + + if (p_shape == current_cursor) { + return; + } + + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + if (cursors[p_shape] != None) { + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + XDefineCursor(x11_display, E->get().x11_window, cursors[p_shape]); + } + } else if (cursors[CURSOR_ARROW] != None) { + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + XDefineCursor(x11_display, E->get().x11_window, cursors[CURSOR_ARROW]); + } + } + } + + current_cursor = p_shape; +} +DisplayServerX11::CursorShape DisplayServerX11::cursor_get_shape() const { + return current_cursor; +} +void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + + _THREAD_SAFE_METHOD_ + + if (p_cursor.is_valid()) { + + Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + + if (cursor_c) { + if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + cursor_set_shape(p_shape); + return; + } + + cursors_cache.erase(p_shape); + } + + Ref<Texture2D> texture = p_cursor; + Ref<AtlasTexture> atlas_texture = p_cursor; + Ref<Image> image; + Size2i texture_size; + Rect2i atlas_rect; + + if (texture.is_valid()) { + image = texture->get_data(); + } + + if (!image.is_valid() && atlas_texture.is_valid()) { + texture = atlas_texture->get_atlas(); + + atlas_rect.size.width = texture->get_width(); + atlas_rect.size.height = texture->get_height(); + atlas_rect.position.x = atlas_texture->get_region().position.x; + atlas_rect.position.y = atlas_texture->get_region().position.y; + + texture_size.width = atlas_texture->get_region().size.x; + texture_size.height = atlas_texture->get_region().size.y; + } else if (image.is_valid()) { + texture_size.width = texture->get_width(); + texture_size.height = texture->get_height(); + } + + ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); + ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); + + image = texture->get_data(); + + ERR_FAIL_COND(!image.is_valid()); + + // Create the cursor structure + XcursorImage *cursor_image = XcursorImageCreate(texture_size.width, texture_size.height); + XcursorUInt image_size = texture_size.width * texture_size.height; + XcursorDim size = sizeof(XcursorPixel) * image_size; + + cursor_image->version = 1; + cursor_image->size = size; + cursor_image->xhot = p_hotspot.x; + cursor_image->yhot = p_hotspot.y; + + // allocate memory to contain the whole file + cursor_image->pixels = (XcursorPixel *)memalloc(size); + + for (XcursorPixel index = 0; index < image_size; index++) { + int row_index = floor(index / texture_size.width) + atlas_rect.position.y; + int column_index = (index % int(texture_size.width)) + atlas_rect.position.x; + + if (atlas_texture.is_valid()) { + column_index = MIN(column_index, atlas_rect.size.width - 1); + row_index = MIN(row_index, atlas_rect.size.height - 1); + } + + *(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32(); + } + + ERR_FAIL_COND(cursor_image->pixels == NULL); + + // Save it for a further usage + cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image); + + Vector<Variant> params; + params.push_back(p_cursor); + params.push_back(p_hotspot); + cursors_cache.insert(p_shape, params); + + if (p_shape == current_cursor) { + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + XDefineCursor(x11_display, E->get().x11_window, cursors[p_shape]); + } + } + } + + memfree(cursor_image->pixels); + XcursorImageDestroy(cursor_image); + } else { + // Reset to default system cursor + if (img[p_shape]) { + cursors[p_shape] = XcursorImageLoadCursor(x11_display, img[p_shape]); + } + + CursorShape c = current_cursor; + current_cursor = CURSOR_MAX; + cursor_set_shape(c); + + cursors_cache.erase(p_shape); + } +} + +DisplayServerX11::LatinKeyboardVariant DisplayServerX11::get_latin_keyboard_variant() const { + _THREAD_SAFE_METHOD_ + + XkbDescRec *xkbdesc = XkbAllocKeyboard(); + ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY); + + XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc); + ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY); + ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY); + + char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols); + ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY); + + Vector<String> info = String(layout).split("+"); + ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY); + + if (info[1].find("colemak") != -1) { + return LATIN_KEYBOARD_COLEMAK; + } else if (info[1].find("qwertz") != -1) { + return LATIN_KEYBOARD_QWERTZ; + } else if (info[1].find("azerty") != -1) { + return LATIN_KEYBOARD_AZERTY; + } else if (info[1].find("qzerty") != -1) { + return LATIN_KEYBOARD_QZERTY; + } else if (info[1].find("dvorak") != -1) { + return LATIN_KEYBOARD_DVORAK; + } else if (info[1].find("neo") != -1) { + return LATIN_KEYBOARD_NEO; + } + + return LATIN_KEYBOARD_QWERTY; +} + +DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, Window p_window, Atom p_property) { + + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *ret = 0; + + int read_bytes = 1024; + + //Keep trying to read the property until there are no + //bytes unread. + do { + if (ret != 0) + XFree(ret); + + XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType, + &actual_type, &actual_format, &nitems, &bytes_after, + &ret); + + read_bytes *= 2; + + } while (bytes_after != 0); + + Property p = { ret, actual_format, (int)nitems, actual_type }; + + return p; +} + +static Atom pick_target_from_list(Display *p_display, Atom *p_list, int p_count) { + + static const char *target_type = "text/uri-list"; + + for (int i = 0; i < p_count; i++) { + + Atom atom = p_list[i]; + + if (atom != None && String(XGetAtomName(p_display, atom)) == target_type) + return atom; + } + return None; +} + +static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p_t3) { + + static const char *target_type = "text/uri-list"; + if (p_t1 != None && String(XGetAtomName(p_disp, p_t1)) == target_type) + return p_t1; + + if (p_t2 != None && String(XGetAtomName(p_disp, p_t2)) == target_type) + return p_t2; + + if (p_t3 != None && String(XGetAtomName(p_disp, p_t3)) == target_type) + return p_t3; + + return None; +} + +void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state) { state->set_shift((p_x11_state & ShiftMask)); state->set_control((p_x11_state & ControlMask)); @@ -1813,7 +1960,7 @@ void OS_X11::get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWith state->set_metakey((p_x11_state & Mod4Mask)); } -unsigned int OS_X11::get_mouse_button_state(unsigned int p_x11_button, int p_x11_type) { +unsigned int DisplayServerX11::_get_mouse_button_state(unsigned int p_x11_button, int p_x11_type) { unsigned int mask = 1 << (p_x11_button - 1); @@ -1826,8 +1973,9 @@ unsigned int OS_X11::get_mouse_button_state(unsigned int p_x11_button, int p_x11 return last_button_state; } -void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { +void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, bool p_echo) { + WindowData wd = windows[p_window]; // X11 functions don't know what const is XKeyEvent *xkeyevent = p_event; @@ -1853,7 +2001,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { KeySym keysym_keycode = 0; // keysym used to find a keycode KeySym keysym_unicode = 0; // keysym used to find unicode - // XLookupString returns keysyms usable as nice scancodes/ + // XLookupString returns keysyms usable as nice keycodes. char str[256 + 1]; XKeyEvent xkeyevent_no_mod = *xkeyevent; xkeyevent_no_mod.state &= ~ShiftMask; @@ -1869,18 +2017,18 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { xmblen = 8; } - if (xkeyevent->type == KeyPress && xic) { + if (xkeyevent->type == KeyPress && wd.xic) { Status status; #ifdef X_HAVE_UTF8_STRING int utf8len = 8; char *utf8string = (char *)memalloc(sizeof(char) * utf8len); - int utf8bytes = Xutf8LookupString(xic, xkeyevent, utf8string, + int utf8bytes = Xutf8LookupString(wd.xic, xkeyevent, utf8string, utf8len - 1, &keysym_unicode, &status); if (status == XBufferOverflow) { utf8len = utf8bytes + 1; utf8string = (char *)memrealloc(utf8string, utf8len); - utf8bytes = Xutf8LookupString(xic, xkeyevent, utf8string, + utf8bytes = Xutf8LookupString(wd.xic, xkeyevent, utf8string, utf8len - 1, &keysym_unicode, &status); } utf8string[utf8bytes] = '\0'; @@ -1902,11 +2050,13 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { continue; } - if (keycode == 0) + if (keycode == 0) { keycode = physical_keycode; + } - get_key_modifier_state(xkeyevent->state, k); + _get_key_modifier_state(xkeyevent->state, k); + k->set_window_id(p_window); k->set_unicode(tmp[i]); k->set_pressed(keypress); @@ -1924,7 +2074,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { k->set_shift(true); } - input->accumulate_input_event(k); + InputFilter::get_singleton()->accumulate_input_event(k); } memfree(utf8string); return; @@ -1944,7 +2094,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { #endif } - /* Phase 2, obtain a pigui keycode from the keysym */ + /* Phase 2, obtain a Godot keycode from the keysym */ // KeyMappingX11 just translated the X11 keysym to a PIGUI // keysym, so it works in all platforms the same. @@ -1970,11 +2120,13 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { bool keypress = xkeyevent->type == KeyPress; - if (physical_keycode == 0 && keycode == 0 && unicode == 0) + if (physical_keycode == 0 && keycode == 0 && unicode == 0) { return; + } - if (keycode == 0) + if (keycode == 0) { keycode = physical_keycode; + } /* Phase 5, determine modifier mask */ @@ -1986,8 +2138,9 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { Ref<InputEventKey> k; k.instance(); + k->set_window_id(p_window); - get_key_modifier_state(xkeyevent->state, k); + _get_key_modifier_state(xkeyevent->state, k); /* Phase 6, determine echo character */ @@ -2021,7 +2174,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { if (rk == keysym_keycode) { XEvent event; XNextEvent(x11_display, &event); //erase next event - handle_key_event((XKeyEvent *)&event, true); + _handle_key_event(p_window, (XKeyEvent *)&event, true); return; //ignore current, echo next } } @@ -2064,104 +2217,133 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { k->set_metakey(false); } - bool last_is_pressed = Input::get_singleton()->is_key_pressed(k->get_keycode()); + bool last_is_pressed = InputFilter::get_singleton()->is_key_pressed(k->get_keycode()); if (k->is_pressed()) { if (last_is_pressed) { k->set_echo(true); } } - //printf("key: %x\n",k->get_keycode()); - input->accumulate_input_event(k); + InputFilter::get_singleton()->accumulate_input_event(k); } -struct Property { - unsigned char *data; - int format, nitems; - Atom type; -}; - -static Property read_property(Display *p_display, Window p_window, Atom p_property) { - - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *ret = 0; - - int read_bytes = 1024; - - //Keep trying to read the property until there are no - //bytes unread. - do { - if (ret != 0) - XFree(ret); +void DisplayServerX11::_xim_destroy_callback(::XIM im, ::XPointer client_data, + ::XPointer call_data) { - XGetWindowProperty(p_display, p_window, p_property, 0, read_bytes, False, AnyPropertyType, - &actual_type, &actual_format, &nitems, &bytes_after, - &ret); + WARN_PRINT("Input method stopped"); + DisplayServerX11 *ds = reinterpret_cast<DisplayServerX11 *>(client_data); + ds->xim = NULL; - read_bytes *= 2; + for (Map<WindowID, WindowData>::Element *E = ds->windows.front(); E; E = E->next()) { + E->get().xic = NULL; + } +} - } while (bytes_after != 0); +void DisplayServerX11::_window_changed(XEvent *event) { - Property p = { ret, actual_format, (int)nitems, actual_type }; + WindowID window_id = MAIN_WINDOW_ID; - return p; -} + // Assign the event to the relevant window + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (event->xany.window == E->get().x11_window) { + window_id = E->key(); + break; + } + } -static Atom pick_target_from_list(Display *p_display, Atom *p_list, int p_count) { + Rect2i new_rect; - static const char *target_type = "text/uri-list"; + WindowData &wd = windows[window_id]; + if (wd.x11_window != event->xany.window) { // Check if the correct window, in case it was not main window or anything else + return; + } - for (int i = 0; i < p_count; i++) { + { + //the position in xconfigure is not useful here, obtain it manually + int x, y; + Window child; + XTranslateCoordinates(x11_display, wd.x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + new_rect.position.x = x; + new_rect.position.y = y; - Atom atom = p_list[i]; + new_rect.size.width = event->xconfigure.width; + new_rect.size.height = event->xconfigure.height; + } - if (atom != None && String(XGetAtomName(p_display, atom)) == target_type) - return atom; + if (new_rect == Rect2i(wd.position, wd.size)) { + return; + } + if (wd.xic) { + // Not portable. + window_set_ime_position(Point2(0, 1)); } - return None; -} -static Atom pick_target_from_atoms(Display *p_disp, Atom p_t1, Atom p_t2, Atom p_t3) { + wd.position = new_rect.position; + wd.size = new_rect.size; - static const char *target_type = "text/uri-list"; - if (p_t1 != None && String(XGetAtomName(p_disp, p_t1)) == target_type) - return p_t1; +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + context_vulkan->window_resize(window_id, wd.size.width, wd.size.height); + } +#endif - if (p_t2 != None && String(XGetAtomName(p_disp, p_t2)) == target_type) - return p_t2; + print_line("DisplayServer::_window_changed: " + itos(window_id) + " rect: " + new_rect); + if (!wd.rect_changed_callback.is_null()) { + Rect2i r = new_rect; - if (p_t3 != None && String(XGetAtomName(p_disp, p_t3)) == target_type) - return p_t3; + Variant rect = r; - return None; + Variant *rectp = ▭ + Variant ret; + Callable::CallError ce; + wd.rect_changed_callback.call((const Variant **)&rectp, 1, ret, ce); + } } -void OS_X11::_window_changed(XEvent *event) { +void DisplayServerX11::_dispatch_input_events(const Ref<InputEvent> &p_event) { + ((DisplayServerX11 *)(get_singleton()))->_dispatch_input_event(p_event); +} - if (xic) { - // Not portable. - set_ime_position(Point2(0, 1)); - } - if ((event->xconfigure.width == current_videomode.width) && - (event->xconfigure.height == current_videomode.height)) - return; +void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) { - current_videomode.width = event->xconfigure.width; - current_videomode.height = event->xconfigure.height; + Variant ev = p_event; + Variant *evp = &ev; + Variant ret; + Callable::CallError ce; -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->window_resize(0, current_videomode.width, current_videomode.height); + Ref<InputEventFromWindow> event_from_window = p_event; + if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) { + //send to a window + ERR_FAIL_COND(!windows.has(event_from_window->get_window_id())); + Callable callable = windows[event_from_window->get_window_id()].input_event_callback; + if (callable.is_null()) { + return; + } + callable.call((const Variant **)&evp, 1, ret, ce); + } else { + //send to all windows + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + Callable callable = E->get().input_event_callback; + if (callable.is_null()) { + continue; + } + callable.call((const Variant **)&evp, 1, ret, ce); + } } -#endif } -void OS_X11::process_xevents() { +void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_event) { + if (!wd.event_callback.is_null()) { + Variant event = int(p_event); + Variant *eventp = &event; + Variant ret; + Callable::CallError ce; + wd.event_callback.call((const Variant **)&eventp, 1, ret, ce); + } +} +void DisplayServerX11::process_events() { - //printf("checking events %i\n", XPending(x11_display)); + _THREAD_SAFE_METHOD_ do_mouse_warp = false; @@ -2172,6 +2354,16 @@ void OS_X11::process_xevents() { XEvent event; XNextEvent(x11_display, &event); + WindowID window_id = MAIN_WINDOW_ID; + + // Assign the event to the relevant window + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (event.xany.window == E->get().x11_window) { + window_id = E->key(); + break; + } + } + if (XFilterEvent(&event, None)) { continue; } @@ -2187,7 +2379,7 @@ void OS_X11::process_xevents() { switch (event_data->evtype) { case XI_HierarchyChanged: case XI_DeviceChanged: { - refresh_device_info(); + _refresh_device_info(); } break; case XI_RawMotion: { XIRawEvent *raw_event = (XIRawEvent *)event_data; @@ -2277,6 +2469,7 @@ void OS_X11::process_xevents() { Ref<InputEventScreenTouch> st; st.instance(); + st->set_window_id(window_id); st->set_index(index); st->set_position(pos); st->set_pressed(is_begin); @@ -2290,12 +2483,12 @@ void OS_X11::process_xevents() { // in a spurious mouse motion event being sent to Godot; remember it to be able to filter it out xi.mouse_pos_to_filter = pos; } - input->accumulate_input_event(st); + InputFilter::get_singleton()->accumulate_input_event(st); } else { if (!xi.state.has(index)) // Defensive break; xi.state.erase(index); - input->accumulate_input_event(st); + InputFilter::get_singleton()->accumulate_input_event(st); } } break; @@ -2310,10 +2503,11 @@ void OS_X11::process_xevents() { Ref<InputEventScreenDrag> sd; sd.instance(); + sd->set_window_id(window_id); sd->set_index(index); sd->set_position(pos); sd->set_relative(pos - curr_pos_elem->value()); - input->accumulate_input_event(sd); + InputFilter::get_singleton()->accumulate_input_event(sd); curr_pos_elem->value() = pos; } @@ -2338,31 +2532,37 @@ void OS_X11::process_xevents() { minimized = (visibility->state == VisibilityFullyObscured); } break; case LeaveNotify: { - if (main_loop && !mouse_mode_grab) - main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT); + if (!mouse_mode_grab) { + _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT); + } } break; case EnterNotify: { - if (main_loop && !mouse_mode_grab) - main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); + if (!mouse_mode_grab) { + _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER); + } } break; case FocusIn: minimized = false; window_has_focus = true; - main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); + _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN); window_focused = true; if (mouse_mode_grab) { // Show and update the cursor if confined and the window regained focus. - if (mouse_mode == MOUSE_MODE_CONFINED) - XUndefineCursor(x11_display, x11_window); - else if (mouse_mode == MOUSE_MODE_CAPTURED) // or re-hide it in captured mode - XDefineCursor(x11_display, x11_window, null_cursor); - - XGrabPointer( - x11_display, x11_window, True, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime); + + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + + if (mouse_mode == MOUSE_MODE_CONFINED) + XUndefineCursor(x11_display, E->get().x11_window); + else if (mouse_mode == MOUSE_MODE_CAPTURED) // or re-hide it in captured mode + XDefineCursor(x11_display, E->get().x11_window, null_cursor); + + XGrabPointer( + x11_display, E->get().x11_window, True, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, E->get().x11_window, None, CurrentTime); + } } #ifdef TOUCH_ENABLED // Grab touch devices to avoid OS gesture interference @@ -2370,22 +2570,25 @@ void OS_X11::process_xevents() { XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask); }*/ #endif - if (xic) { - XSetICFocus(xic); + if (windows[window_id].xic) { + XSetICFocus(windows[window_id].xic); } break; case FocusOut: window_has_focus = false; - input->release_pressed_events(); - main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + InputFilter::get_singleton()->release_pressed_events(); + _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT); window_focused = false; if (mouse_mode_grab) { - //dear X11, I try, I really try, but you never work, you do whathever you want. - if (mouse_mode == MOUSE_MODE_CAPTURED) { - // Show the cursor if we're in captured mode so it doesn't look weird. - XUndefineCursor(x11_display, x11_window); + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + + //dear X11, I try, I really try, but you never work, you do whathever you want. + if (mouse_mode == MOUSE_MODE_CAPTURED) { + // Show the cursor if we're in captured mode so it doesn't look weird. + XUndefineCursor(x11_display, E->get().x11_window); + } } XUngrabPointer(x11_display, CurrentTime); } @@ -2401,13 +2604,14 @@ void OS_X11::process_xevents() { Ref<InputEventScreenTouch> st; st.instance(); st->set_index(E->key()); + st->set_window_id(window_id); st->set_position(E->get()); - input->accumulate_input_event(st); + InputFilter::get_singleton()->accumulate_input_event(st); } xi.state.clear(); #endif - if (xic) { - XUnsetICFocus(xic); + if (windows[window_id].xic) { + XSetICFocus(windows[window_id].xic); } break; @@ -2427,13 +2631,14 @@ void OS_X11::process_xevents() { Ref<InputEventMouseButton> mb; mb.instance(); - get_key_modifier_state(event.xbutton.state, mb); + mb->set_window_id(window_id); + _get_key_modifier_state(event.xbutton.state, mb); mb->set_button_index(event.xbutton.button); if (mb->get_button_index() == 2) mb->set_button_index(3); else if (mb->get_button_index() == 3) mb->set_button_index(2); - mb->set_button_mask(get_mouse_button_state(mb->get_button_index(), event.xbutton.type)); + mb->set_button_mask(_get_mouse_button_state(mb->get_button_index(), event.xbutton.type)); mb->set_position(Vector2(event.xbutton.x, event.xbutton.y)); mb->set_global_position(mb->get_position()); @@ -2441,14 +2646,14 @@ void OS_X11::process_xevents() { if (event.type == ButtonPress) { - uint64_t diff = get_ticks_usec() / 1000 - last_click_ms; + uint64_t diff = OS::get_singleton()->get_ticks_usec() / 1000 - last_click_ms; if (mb->get_button_index() == last_click_button_index) { - if (diff < 400 && Point2(last_click_pos).distance_to(Point2(event.xbutton.x, event.xbutton.y)) < 5) { + if (diff < 400 && Vector2(last_click_pos).distance_to(Vector2(event.xbutton.x, event.xbutton.y)) < 5) { last_click_ms = 0; - last_click_pos = Point2(-100, -100); + last_click_pos = Point2i(-100, -100); last_click_button_index = -1; mb->set_doubleclick(true); } @@ -2459,11 +2664,11 @@ void OS_X11::process_xevents() { if (!mb->is_doubleclick()) { last_click_ms += diff; - last_click_pos = Point2(event.xbutton.x, event.xbutton.y); + last_click_pos = Point2i(event.xbutton.x, event.xbutton.y); } } - input->accumulate_input_event(mb); + InputFilter::get_singleton()->accumulate_input_event(mb); } break; case MotionNotify: { @@ -2473,7 +2678,7 @@ void OS_X11::process_xevents() { // generated by warping the mouse pointer. while (true) { - if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == current_videomode.width / 2 && event.xmotion.y == current_videomode.height / 2) { + if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[MAIN_WINDOW_ID].size.width / 2 && event.xmotion.y == windows[MAIN_WINDOW_ID].size.height / 2) { //this is likely the warp event since it was warped here center = Vector2(event.xmotion.x, event.xmotion.y); break; @@ -2497,7 +2702,7 @@ void OS_X11::process_xevents() { // Motion is also simple. // A little hack is in order // to be able to send relative motion events. - Point2 pos(event.xmotion.x, event.xmotion.y); + Point2i pos(event.xmotion.x, event.xmotion.y); // Avoidance of spurious mouse motion (see handling of touch) bool filter = false; @@ -2534,7 +2739,7 @@ void OS_X11::process_xevents() { // RawMotion provides more precision than MotionNotify, which doesn't sense subpixel motion. // Therefore, MotionNotify cannot be the authority on relative mouse motion. // This means we need to take a combined approach... - Point2 rel; + Point2i rel; // Only use raw input if in capture mode. Otherwise use the classic behavior. if (mouse_mode == MOUSE_MODE_CAPTURED) { @@ -2548,24 +2753,25 @@ void OS_X11::process_xevents() { xi.relative_motion.y = 0; if (mouse_mode == MOUSE_MODE_CAPTURED) { - pos = Point2i(current_videomode.width / 2, current_videomode.height / 2); + pos = Point2i(windows[MAIN_WINDOW_ID].size.width / 2, windows[MAIN_WINDOW_ID].size.height / 2); } Ref<InputEventMouseMotion> mm; mm.instance(); + mm->set_window_id(window_id); mm->set_pressure(xi.pressure); mm->set_tilt(xi.tilt); // Make the absolute position integral so it doesn't look _too_ weird :) Point2i posi(pos); - get_key_modifier_state(event.xmotion.state, mm); - mm->set_button_mask(get_mouse_button_state()); + _get_key_modifier_state(event.xmotion.state, mm); + mm->set_button_mask(mouse_get_button_state()); mm->set_position(posi); mm->set_global_position(posi); - input->set_mouse_position(posi); - mm->set_speed(input->get_last_mouse_speed()); + InputFilter::get_singleton()->set_mouse_position(posi); + mm->set_speed(InputFilter::get_singleton()->get_last_mouse_speed()); mm->set_relative(rel); @@ -2576,7 +2782,7 @@ void OS_X11::process_xevents() { // this is so that the relative motion doesn't get messed up // after we regain focus. if (window_has_focus || !mouse_mode_grab) - input->accumulate_input_event(mm); + InputFilter::get_singleton()->accumulate_input_event(mm); } break; case KeyPress: @@ -2586,7 +2792,7 @@ void OS_X11::process_xevents() { // key event is a little complex, so // it will be handled in its own function. - handle_key_event((XKeyEvent *)&event); + _handle_key_event(window_id, (XKeyEvent *)&event); } break; case SelectionRequest: { @@ -2601,7 +2807,7 @@ void OS_X11::process_xevents() { req->target == XA_STRING || req->target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) || req->target == XInternAtom(x11_display, "text/plain", 0)) { - CharString clip = OS::get_clipboard().utf8(); + CharString clip = clipboard_get().utf8(); XChangeProperty(x11_display, req->requestor, req->property, @@ -2654,13 +2860,20 @@ void OS_X11::process_xevents() { if (event.xselection.target == requested) { - Property p = read_property(x11_display, x11_window, XInternAtom(x11_display, "PRIMARY", 0)); + Property p = _read_property(x11_display, windows[window_id].x11_window, XInternAtom(x11_display, "PRIMARY", 0)); Vector<String> files = String((char *)p.data).split("\n", false); for (int i = 0; i < files.size(); i++) { files.write[i] = files[i].replace("file://", "").http_unescape().strip_edges(); } - main_loop->drop_files(files); + + if (!windows[window_id].drop_files_callback.is_null()) { + Variant v = files; + Variant *vp = &v; + Variant ret; + Callable::CallError ce; + windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + } //Reply that all is well. XClientMessageEvent m; @@ -2670,7 +2883,7 @@ void OS_X11::process_xevents() { m.window = xdnd_source_window; m.message_type = xdnd_finished; m.format = 32; - m.data.l[0] = x11_window; + m.data.l[0] = windows[window_id].x11_window; m.data.l[1] = 1; m.data.l[2] = xdnd_action_copy; //We only ever copy. @@ -2680,8 +2893,9 @@ void OS_X11::process_xevents() { case ClientMessage: - if ((unsigned int)event.xclient.data.l[0] == (unsigned int)wm_delete) - main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); + if ((unsigned int)event.xclient.data.l[0] == (unsigned int)wm_delete) { + _send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST); + } else if ((unsigned int)event.xclient.message_type == (unsigned int)xdnd_enter) { @@ -2690,7 +2904,7 @@ void OS_X11::process_xevents() { Window source = event.xclient.data.l[0]; bool more_than_3 = event.xclient.data.l[1] & 1; if (more_than_3) { - Property p = read_property(x11_display, source, XInternAtom(x11_display, "XdndTypeList", False)); + Property p = _read_property(x11_display, source, XInternAtom(x11_display, "XdndTypeList", False)); requested = pick_target_from_list(x11_display, (Atom *)p.data, p.nitems); } else requested = pick_target_from_atoms(x11_display, event.xclient.data.l[2], event.xclient.data.l[3], event.xclient.data.l[4]); @@ -2705,7 +2919,7 @@ void OS_X11::process_xevents() { m.window = event.xclient.data.l[0]; m.message_type = xdnd_status; m.format = 32; - m.data.l[0] = x11_window; + m.data.l[0] = windows[window_id].x11_window; m.data.l[1] = (requested != None); m.data.l[2] = 0; //empty rectangle m.data.l[3] = 0; @@ -2718,9 +2932,9 @@ void OS_X11::process_xevents() { if (requested != None) { xdnd_source_window = event.xclient.data.l[0]; if (xdnd_version >= 1) - XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), x11_window, event.xclient.data.l[2]); + XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), windows[window_id].x11_window, event.xclient.data.l[2]); else - XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), x11_window, CurrentTime); + XConvertSelection(x11_display, xdnd_selection, requested, XInternAtom(x11_display, "PRIMARY", 0), windows[window_id].x11_window, CurrentTime); } else { //Reply that we're not interested. XClientMessageEvent m; @@ -2730,7 +2944,7 @@ void OS_X11::process_xevents() { m.window = event.xclient.data.l[0]; m.message_type = xdnd_finished; m.format = 32; - m.data.l[0] = x11_window; + m.data.l[0] = windows[window_id].x11_window; m.data.l[1] = 0; m.data.l[2] = None; //Failed. XSendEvent(x11_display, event.xclient.data.l[0], False, NoEventMask, (XEvent *)&m); @@ -2746,8 +2960,8 @@ void OS_X11::process_xevents() { if (do_mouse_warp) { - XWarpPointer(x11_display, None, x11_window, - 0, 0, 0, 0, (int)current_videomode.width / 2, (int)current_videomode.height / 2); + XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, + 0, 0, 0, 0, (int)windows[MAIN_WINDOW_ID].size.width / 2, (int)windows[MAIN_WINDOW_ID].size.height / 2); /* Window root, child; @@ -2761,808 +2975,878 @@ void OS_X11::process_xevents() { */ } - input->flush_accumulated_events(); + InputFilter::get_singleton()->flush_accumulated_events(); } -MainLoop *OS_X11::get_main_loop() const { - - return main_loop; +void DisplayServerX11::release_rendering_thread() { } -void OS_X11::delete_main_loop() { - - if (main_loop) - memdelete(main_loop); - main_loop = NULL; +void DisplayServerX11::make_rendering_thread() { } -void OS_X11::set_main_loop(MainLoop *p_main_loop) { - - main_loop = p_main_loop; - input->set_main_loop(p_main_loop); +void DisplayServerX11::swap_buffers() { } -bool OS_X11::can_draw() const { +void DisplayServerX11::_update_context(WindowData &wd) { + XClassHint *classHint = XAllocClassHint(); - return !minimized; -}; + if (classHint) { -void OS_X11::set_clipboard(const String &p_text) { + CharString name_str; + switch (context) { + case CONTEXT_EDITOR: + name_str = "Godot_Editor"; + break; + case CONTEXT_PROJECTMAN: + name_str = "Godot_ProjectList"; + break; + case CONTEXT_ENGINE: + name_str = "Godot_Engine"; + break; + } - OS::set_clipboard(p_text); + CharString class_str; + if (context == CONTEXT_ENGINE) { + String config_name = GLOBAL_GET("application/config/name"); + if (config_name.length() == 0) { + class_str = "Godot_Engine"; + } else { + class_str = config_name.utf8(); + } + } else { + class_str = "Godot"; + } - XSetSelectionOwner(x11_display, XA_PRIMARY, x11_window, CurrentTime); - XSetSelectionOwner(x11_display, XInternAtom(x11_display, "CLIPBOARD", 0), x11_window, CurrentTime); -}; + classHint->res_class = class_str.ptrw(); + classHint->res_name = name_str.ptrw(); -static String _get_clipboard_impl(Atom p_source, Window x11_window, ::Display *x11_display, String p_internal_clipboard, Atom target) { + XSetClassHint(x11_display, wd.x11_window, classHint); + XFree(classHint); + } +} +void DisplayServerX11::set_context(Context p_context) { - String ret; + _THREAD_SAFE_METHOD_ - Atom type; - Atom selection = XA_PRIMARY; - int format, result; - unsigned long len, bytes_left, dummy; - unsigned char *data; - Window Sown = XGetSelectionOwner(x11_display, p_source); + context = p_context; - if (Sown == x11_window) { + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + _update_context(E->get()); + } +} +void DisplayServerX11::set_native_icon(const String &p_filename) { + WARN_PRINT("Native icon not supported by this display server."); +} - return p_internal_clipboard; - }; +bool g_set_icon_error = false; +int set_icon_errorhandler(Display *dpy, XErrorEvent *ev) { + g_set_icon_error = true; + return 0; +} - if (Sown != None) { - XConvertSelection(x11_display, p_source, target, selection, - x11_window, CurrentTime); - XFlush(x11_display); - while (true) { - XEvent event; - XNextEvent(x11_display, &event); - if (event.type == SelectionNotify && event.xselection.requestor == x11_window) { - break; - }; - }; +void DisplayServerX11::set_icon(const Ref<Image> &p_icon) { + _THREAD_SAFE_METHOD_ - // - // Do not get any data, see how much data is there - // - XGetWindowProperty(x11_display, x11_window, - selection, // Tricky.. - 0, 0, // offset - len - 0, // Delete 0==FALSE - AnyPropertyType, //flag - &type, // return type - &format, // return format - &len, &bytes_left, //that - &data); - // DATA is There - if (bytes_left > 0) { - result = XGetWindowProperty(x11_display, x11_window, - selection, 0, bytes_left, 0, - AnyPropertyType, &type, &format, - &len, &dummy, &data); - if (result == Success) { - ret.parse_utf8((const char *)data); - } else - printf("FAIL\n"); - XFree(data); - } - } + WindowData &wd = windows[MAIN_WINDOW_ID]; - return ret; -} + int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&set_icon_errorhandler); -static String _get_clipboard(Atom p_source, Window x11_window, ::Display *x11_display, String p_internal_clipboard) { - String ret; - Atom utf8_atom = XInternAtom(x11_display, "UTF8_STRING", True); - if (utf8_atom != None) { - ret = _get_clipboard_impl(p_source, x11_window, x11_display, p_internal_clipboard, utf8_atom); - } - if (ret == "") { - ret = _get_clipboard_impl(p_source, x11_window, x11_display, p_internal_clipboard, XA_STRING); - } - return ret; -} + Atom net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); -String OS_X11::get_clipboard() const { + if (p_icon.is_valid()) { + Ref<Image> img = p_icon->duplicate(); + img->convert(Image::FORMAT_RGBA8); - String ret; - ret = _get_clipboard(XInternAtom(x11_display, "CLIPBOARD", 0), x11_window, x11_display, OS::get_clipboard()); + while (true) { + int w = img->get_width(); + int h = img->get_height(); - if (ret == "") { - ret = _get_clipboard(XA_PRIMARY, x11_window, x11_display, OS::get_clipboard()); - }; + if (g_set_icon_error) { + g_set_icon_error = false; - return ret; -} + WARN_PRINT("Icon too large, attempting to resize icon."); -String OS_X11::get_name() const { + int new_width, new_height; + if (w > h) { + new_width = w / 2; + new_height = h * new_width / w; + } else { + new_height = h / 2; + new_width = w * new_height / h; + } - return "X11"; -} + w = new_width; + h = new_height; -Error OS_X11::shell_open(String p_uri) { + if (!w || !h) { + WARN_PRINT("Unable to set icon."); + break; + } - Error ok; - List<String> args; - args.push_back(p_uri); - ok = execute("xdg-open", args, false); - if (ok == OK) - return OK; - ok = execute("gnome-open", args, false); - if (ok == OK) - return OK; - ok = execute("kde-open", args, false); - return ok; -} + img->resize(w, h, Image::INTERPOLATE_CUBIC); + } -bool OS_X11::_check_internal_feature_support(const String &p_feature) { + // We're using long to have wordsize (32Bit build -> 32 Bits, 64 Bit build -> 64 Bits + Vector<long> pd; - return p_feature == "pc"; -} + pd.resize(2 + w * h); -String OS_X11::get_config_path() const { + pd.write[0] = w; + pd.write[1] = h; - if (has_environment("XDG_CONFIG_HOME")) { - return get_environment("XDG_CONFIG_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file(".config"); - } else { - return "."; - } -} + const uint8_t *r = img->get_data().ptr(); -String OS_X11::get_data_path() const { + long *wr = &pd.write[2]; + uint8_t const *pr = r; - if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file(".local/share"); - } else { - return get_config_path(); - } -} + for (int i = 0; i < w * h; i++) { + long v = 0; + // A R G B + v |= pr[3] << 24 | pr[0] << 16 | pr[1] << 8 | pr[2]; + *wr++ = v; + pr += 4; + } -String OS_X11::get_cache_path() const { + XChangeProperty(x11_display, wd.x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pd.ptr(), pd.size()); - if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file(".cache"); + if (!g_set_icon_error) + break; + } } else { - return get_config_path(); + XDeleteProperty(x11_display, wd.x11_window, net_wm_icon); } + + XFlush(x11_display); + XSetErrorHandler(oldHandler); } -String OS_X11::get_system_dir(SystemDir p_dir) const { +Vector<String> DisplayServerX11::get_rendering_drivers_func() { + Vector<String> drivers; - String xdgparam; +#ifdef VULKAN_ENABLED + drivers.push_back("vulkan"); +#endif +#ifdef OPENGL_ENABLED + drivers.push_back("opengl"); +#endif - switch (p_dir) { - case SYSTEM_DIR_DESKTOP: { + return drivers; +} - xdgparam = "DESKTOP"; - } break; - case SYSTEM_DIR_DCIM: { +DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - xdgparam = "PICTURES"; + return memnew(DisplayServerX11(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); +} - } break; - case SYSTEM_DIR_DOCUMENTS: { +DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { - xdgparam = "DOCUMENTS"; + //Create window - } break; - case SYSTEM_DIR_DOWNLOADS: { + long visualMask = VisualScreenMask; + int numberOfVisuals; + XVisualInfo vInfoTemplate = {}; + vInfoTemplate.screen = DefaultScreen(x11_display); + XVisualInfo *visualInfo = XGetVisualInfo(x11_display, visualMask, &vInfoTemplate, &numberOfVisuals); - xdgparam = "DOWNLOAD"; + Colormap colormap = XCreateColormap(x11_display, RootWindow(x11_display, vInfoTemplate.screen), visualInfo->visual, AllocNone); - } break; - case SYSTEM_DIR_MOVIES: { + XSetWindowAttributes windowAttributes = {}; + windowAttributes.colormap = colormap; + windowAttributes.background_pixel = 0xFFFFFFFF; + windowAttributes.border_pixel = 0; + windowAttributes.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask; - xdgparam = "VIDEOS"; + unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask; - } break; - case SYSTEM_DIR_MUSIC: { + WindowID id; + { + WindowData wd; + wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo->screen), p_rect.position.x, p_rect.position.y, p_rect.size.width > 0 ? p_rect.size.width : 1, p_rect.size.height > 0 ? p_rect.size.height : 1, 0, visualInfo->depth, InputOutput, visualInfo->visual, valuemask, &windowAttributes); - xdgparam = "MUSIC"; + XMapWindow(x11_display, wd.x11_window); - } break; - case SYSTEM_DIR_PICTURES: { + //associate PID + // make PID known to X11 + { + const long pid = OS::get_singleton()->get_process_id(); + Atom net_wm_pid = XInternAtom(x11_display, "_NET_WM_PID", False); + XChangeProperty(x11_display, wd.x11_window, net_wm_pid, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1); + } - xdgparam = "PICTURES"; + long im_event_mask = 0; - } break; - case SYSTEM_DIR_RINGTONES: { + { + XIEventMask all_event_mask; + XSetWindowAttributes new_attr; - xdgparam = "MUSIC"; + new_attr.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | + LeaveWindowMask | PointerMotionMask | + Button1MotionMask | + Button2MotionMask | Button3MotionMask | + Button4MotionMask | Button5MotionMask | + ButtonMotionMask | KeymapStateMask | + ExposureMask | VisibilityChangeMask | + StructureNotifyMask | + SubstructureNotifyMask | SubstructureRedirectMask | + FocusChangeMask | PropertyChangeMask | + ColormapChangeMask | OwnerGrabButtonMask | + im_event_mask; - } break; - } + XChangeWindowAttributes(x11_display, wd.x11_window, CWEventMask, &new_attr); - String pipe; - List<String> arg; - arg.push_back(xdgparam); - Error err = const_cast<OS_X11 *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe); - if (err != OK) - return "."; - return pipe.strip_edges(); -} + static unsigned char all_mask_data[XIMaskLen(XI_LASTEVENT)] = {}; -void OS_X11::move_window_to_foreground() { + all_event_mask.deviceid = XIAllDevices; + all_event_mask.mask_len = sizeof(all_mask_data); + all_event_mask.mask = all_mask_data; - XEvent xev; - Atom net_active_window = XInternAtom(x11_display, "_NET_ACTIVE_WINDOW", False); + XISetMask(all_event_mask.mask, XI_HierarchyChanged); - memset(&xev, 0, sizeof(xev)); - xev.type = ClientMessage; - xev.xclient.window = x11_window; - xev.xclient.message_type = net_active_window; - xev.xclient.format = 32; - xev.xclient.data.l[0] = 1; - xev.xclient.data.l[1] = CurrentTime; +#ifdef TOUCH_ENABLED + if (xi.touch_devices.size()) { + XISetMask(all_event_mask.mask, XI_TouchBegin); + XISetMask(all_event_mask.mask, XI_TouchUpdate); + XISetMask(all_event_mask.mask, XI_TouchEnd); + XISetMask(all_event_mask.mask, XI_TouchOwnership); + } +#endif - XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - XFlush(x11_display); -} + XISelectEvents(x11_display, wd.x11_window, &all_event_mask, 1); + } -void OS_X11::set_cursor_shape(CursorShape p_shape) { + /* set the titlebar name */ + XStoreName(x11_display, wd.x11_window, "Godot"); + XSetWMProtocols(x11_display, wd.x11_window, &wm_delete, 1); + XChangeProperty(x11_display, wd.x11_window, xdnd_aware, XA_ATOM, 32, PropModeReplace, (unsigned char *)&xdnd_version, 1); - ERR_FAIL_INDEX(p_shape, CURSOR_MAX); + if (xim && xim_style) { - if (p_shape == current_cursor) { - return; - } + wd.xic = XCreateIC(xim, XNInputStyle, xim_style, XNClientWindow, wd.x11_window, XNFocusWindow, wd.x11_window, (char *)NULL); + if (XGetICValues(wd.xic, XNFilterEvents, &im_event_mask, NULL) != NULL) { + WARN_PRINT("XGetICValues couldn't obtain XNFilterEvents value"); + XDestroyIC(wd.xic); + wd.xic = NULL; + } + if (wd.xic) { + XUnsetICFocus(wd.xic); + } else { + WARN_PRINT("XCreateIC couldn't create wd.xic"); + } + } else { - if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { - if (cursors[p_shape] != None) { - XDefineCursor(x11_display, x11_window, cursors[p_shape]); - } else if (cursors[CURSOR_ARROW] != None) { - XDefineCursor(x11_display, x11_window, cursors[CURSOR_ARROW]); + wd.xic = NULL; + WARN_PRINT("XCreateIC couldn't create wd.xic"); } - } - current_cursor = p_shape; -} + _update_context(wd); -OS::CursorShape OS_X11::get_cursor_shape() const { + id = window_id_counter++; - return current_cursor; -} + windows[id] = wd; -void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + { - if (p_cursor.is_valid()) { + if (p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT) { - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + XSizeHints *xsh; + xsh = XAllocSizeHints(); - if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { - set_cursor_shape(p_shape); - return; + xsh->flags = PMinSize | PMaxSize; + xsh->min_width = p_rect.size.width; + xsh->max_width = p_rect.size.width; + xsh->min_height = p_rect.size.height; + xsh->max_height = p_rect.size.height; + + XSetWMNormalHints(x11_display, wd.x11_window, xsh); + XFree(xsh); } - cursors_cache.erase(p_shape); - } + bool make_utility = false; - Ref<Texture2D> texture = p_cursor; - Ref<AtlasTexture> atlas_texture = p_cursor; - Ref<Image> image; - Size2 texture_size; - Rect2 atlas_rect; + if (p_flags & WINDOW_FLAG_BORDERLESS_BIT) { + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = 0; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, wd.x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); - if (texture.is_valid()) { - image = texture->get_data(); - } + make_utility = true; + } + if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) { + make_utility = true; + } - if (!image.is_valid() && atlas_texture.is_valid()) { - texture = atlas_texture->get_atlas(); + if (make_utility) { + //this one seems to disable the fade animations for regular windows + //but has the drawback that will not get focus by default, so + //we need fo force it, unless no focus requested - atlas_rect.size.width = texture->get_width(); - atlas_rect.size.height = texture->get_height(); - atlas_rect.position.x = atlas_texture->get_region().position.x; - atlas_rect.position.y = atlas_texture->get_region().position.y; + Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_UTILITY", False); + Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False); - texture_size.width = atlas_texture->get_region().size.x; - texture_size.height = atlas_texture->get_region().size.y; - } else if (image.is_valid()) { - texture_size.width = texture->get_width(); - texture_size.height = texture->get_height(); - } + XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1); - ERR_FAIL_COND(!texture.is_valid()); - ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); - ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); - ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); + if (!(p_flags & WINDOW_FLAG_NO_FOCUS_BIT)) { + //but as utility appears unfocused, it needs to be forcefuly focused, unless no focus requested + XEvent xev; + Atom net_active_window = XInternAtom(x11_display, "_NET_ACTIVE_WINDOW", False); - image = texture->get_data(); + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = wd.x11_window; + xev.xclient.message_type = net_active_window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = CurrentTime; - ERR_FAIL_COND(!image.is_valid()); + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } else { + Atom type_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE_NORMAL", False); + Atom wt_atom = XInternAtom(x11_display, "_NET_WM_WINDOW_TYPE", False); - // Create the cursor structure - XcursorImage *cursor_image = XcursorImageCreate(texture_size.width, texture_size.height); - XcursorUInt image_size = texture_size.width * texture_size.height; - XcursorDim size = sizeof(XcursorPixel) * image_size; + XChangeProperty(x11_display, wd.x11_window, wt_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_atom, 1); + } + } - cursor_image->version = 1; - cursor_image->size = size; - cursor_image->xhot = p_hotspot.x; - cursor_image->yhot = p_hotspot.y; + if (id != MAIN_WINDOW_ID) { - // allocate memory to contain the whole file - cursor_image->pixels = (XcursorPixel *)memalloc(size); + XSizeHints my_hints = XSizeHints(); - for (XcursorPixel index = 0; index < image_size; index++) { - int row_index = floor(index / texture_size.width) + atlas_rect.position.y; - int column_index = (index % int(texture_size.width)) + atlas_rect.position.x; + my_hints.flags = PPosition | PSize; /* I want to specify position and size */ + my_hints.x = p_rect.position.x; /* The origin and size coords I want */ + my_hints.y = p_rect.position.y; + my_hints.width = p_rect.size.width; + my_hints.height = p_rect.size.height; - if (atlas_texture.is_valid()) { - column_index = MIN(column_index, atlas_rect.size.width - 1); - row_index = MIN(row_index, atlas_rect.size.height - 1); - } + XSetNormalHints(x11_display, wd.x11_window, &my_hints); + XMoveWindow(x11_display, wd.x11_window, p_rect.position.x, p_rect.position.y); + } - *(cursor_image->pixels + index) = image->get_pixel(column_index, row_index).to_argb32(); +#if defined(VULKAN_ENABLED) + if (context_vulkan) { + Error err = context_vulkan->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height); + ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window"); } +#endif - ERR_FAIL_COND(cursor_image->pixels == NULL); + //set_class_hint(x11_display, wd.x11_window); + XFlush(x11_display); - // Save it for a further usage - cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image); + XSync(x11_display, False); + //XSetErrorHandler(oldHandler); - Vector<Variant> params; - params.push_back(p_cursor); - params.push_back(p_hotspot); - cursors_cache.insert(p_shape, params); + XFree(visualInfo); + } - if (p_shape == current_cursor) { - if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { - XDefineCursor(x11_display, x11_window, cursors[p_shape]); - } - } + WindowData &wd = windows[id]; - memfree(cursor_image->pixels); - XcursorImageDestroy(cursor_image); - } else { - // Reset to default system cursor - if (img[p_shape]) { - cursors[p_shape] = XcursorImageLoadCursor(x11_display, img[p_shape]); - } + window_set_mode(p_mode, id); - CursorShape c = current_cursor; - current_cursor = CURSOR_MAX; - set_cursor_shape(c); + //sync size + { + XWindowAttributes xwa; - cursors_cache.erase(p_shape); - } -} + XSync(x11_display, False); + XGetWindowAttributes(x11_display, wd.x11_window, &xwa); -void OS_X11::release_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->release_current(); - } -#endif -} + wd.position.x = xwa.x; + wd.position.y = xwa.y; + wd.size.width = xwa.width; + wd.size.height = xwa.height; -void OS_X11::make_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->make_current(); + print_line("DisplayServer::_create_window " + itos(id) + " want rect: " + p_rect + " got rect " + Rect2i(xwa.x, xwa.y, xwa.width, xwa.height)); } -#endif -} -void OS_X11::swap_buffers() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->swap_buffers(); - } -#endif - /* not needed for now -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->swap_buffers(); + //set cursor + if (cursors[current_cursor] != None) { + + XDefineCursor(x11_display, wd.x11_window, cursors[current_cursor]); } -#endif*/ + return id; } -void OS_X11::alert(const String &p_alert, const String &p_title) { - const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" }; +DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - String path = get_environment("PATH"); - Vector<String> path_elems = path.split(":", false); - String program; + InputFilter::get_singleton()->set_event_dispatch_function(_dispatch_input_events); - for (int i = 0; i < path_elems.size(); i++) { - for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) { - String tested_path = path_elems[i].plus_file(message_programs[k]); + r_error = OK; - if (FileAccess::exists(tested_path)) { - program = tested_path; - break; - } - } + last_button_state = 0; - if (program.length()) - break; - } + xmbstring = NULL; - List<String> args; + last_click_ms = 0; + last_click_button_index = -1; + last_click_pos = Point2i(-100, -100); - if (program.ends_with("zenity")) { - args.push_back("--error"); - args.push_back("--width"); - args.push_back("500"); - args.push_back("--title"); - args.push_back(p_title); - args.push_back("--text"); - args.push_back(p_alert); - } + last_timestamp = 0; + last_mouse_pos_valid = false; + last_keyrelease_time = 0; - if (program.ends_with("kdialog")) { - args.push_back("--error"); - args.push_back(p_alert); - args.push_back("--title"); - args.push_back(p_title); + XInitThreads(); //always use threads + + /** XLIB INITIALIZATION **/ + x11_display = XOpenDisplay(NULL); + + if (!x11_display) { + ERR_PRINT("X11 Display is not available"); + r_error = ERR_UNAVAILABLE; + return; } - if (program.ends_with("Xdialog")) { - args.push_back("--title"); - args.push_back(p_title); - args.push_back("--msgbox"); - args.push_back(p_alert); - args.push_back("0"); - args.push_back("0"); + char *modifiers = NULL; + Bool xkb_dar = False; + XAutoRepeatOn(x11_display); + xkb_dar = XkbSetDetectableAutoRepeat(x11_display, True, NULL); + + // Try to support IME if detectable auto-repeat is supported + if (xkb_dar == True) { + +#ifdef X_HAVE_UTF8_STRING + // Xutf8LookupString will be used later instead of XmbLookupString before + // the multibyte sequences can be converted to unicode string. + modifiers = XSetLocaleModifiers(""); +#endif } - if (program.ends_with("xmessage")) { - args.push_back("-center"); - args.push_back("-title"); - args.push_back(p_title); - args.push_back(p_alert); + if (modifiers == NULL) { + if (OS::get_singleton()->is_stdout_verbose()) { + WARN_PRINT("IME is disabled"); + } + XSetLocaleModifiers("@im=none"); + WARN_PRINT("Error setting locale modifiers"); } - if (program.length()) { - execute(program, args, true); + const char *err; + xrr_get_monitors = NULL; + xrr_free_monitors = NULL; + int xrandr_major = 0; + int xrandr_minor = 0; + int event_base, error_base; + xrandr_ext_ok = XRRQueryExtension(x11_display, &event_base, &error_base); + xrandr_handle = dlopen("libXrandr.so.2", RTLD_LAZY); + if (!xrandr_handle) { + err = dlerror(); + fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err); } else { - print_line(p_alert); + XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor); + if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) { + xrr_get_monitors = (xrr_get_monitors_t)dlsym(xrandr_handle, "XRRGetMonitors"); + if (!xrr_get_monitors) { + err = dlerror(); + fprintf(stderr, "could not find symbol XRRGetMonitors\nError: %s\n", err); + } else { + xrr_free_monitors = (xrr_free_monitors_t)dlsym(xrandr_handle, "XRRFreeMonitors"); + if (!xrr_free_monitors) { + err = dlerror(); + fprintf(stderr, "could not find XRRFreeMonitors\nError: %s\n", err); + xrr_get_monitors = NULL; + } + } + } } -} - -bool g_set_icon_error = false; -int set_icon_errorhandler(Display *dpy, XErrorEvent *ev) { - g_set_icon_error = true; - return 0; -} - -void OS_X11::set_icon(const Ref<Image> &p_icon) { - int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&set_icon_errorhandler); - Atom net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); - - if (p_icon.is_valid()) { - Ref<Image> img = p_icon->duplicate(); - img->convert(Image::FORMAT_RGBA8); + if (!_refresh_device_info()) { + alert("Your system does not support XInput 2.\n" + "Please upgrade your distribution.", + "Unable to initialize XInput"); + r_error = ERR_UNAVAILABLE; + return; + } - while (true) { - int w = img->get_width(); - int h = img->get_height(); + xim = XOpenIM(x11_display, NULL, NULL, NULL); - if (g_set_icon_error) { - g_set_icon_error = false; + if (xim == NULL) { + WARN_PRINT("XOpenIM failed"); + xim_style = 0L; + } else { + ::XIMCallback im_destroy_callback; + im_destroy_callback.client_data = (::XPointer)(this); + im_destroy_callback.callback = (::XIMProc)(_xim_destroy_callback); + if (XSetIMValues(xim, XNDestroyCallback, &im_destroy_callback, + NULL) != NULL) { + WARN_PRINT("Error setting XIM destroy callback"); + } - WARN_PRINT("Icon too large, attempting to resize icon."); + ::XIMStyles *xim_styles = NULL; + xim_style = 0L; + char *imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); + if (imvalret != NULL || xim_styles == NULL) { + fprintf(stderr, "Input method doesn't support any styles\n"); + } - int new_width, new_height; - if (w > h) { - new_width = w / 2; - new_height = h * new_width / w; - } else { - new_height = h / 2; - new_width = w * new_height / h; - } + if (xim_styles) { + xim_style = 0L; + for (int i = 0; i < xim_styles->count_styles; i++) { - w = new_width; - h = new_height; + if (xim_styles->supported_styles[i] == + (XIMPreeditNothing | XIMStatusNothing)) { - if (!w || !h) { - WARN_PRINT("Unable to set icon."); + xim_style = xim_styles->supported_styles[i]; break; } - - img->resize(w, h, Image::INTERPOLATE_CUBIC); } - // We're using long to have wordsize (32Bit build -> 32 Bits, 64 Bit build -> 64 Bits - Vector<long> pd; - - pd.resize(2 + w * h); - - pd.write[0] = w; - pd.write[1] = h; + XFree(xim_styles); + } + XFree(imvalret); + } - const uint8_t *r = img->get_data().ptr(); + /* Atorm internment */ + wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); + //Set Xdnd (drag & drop) support + xdnd_aware = XInternAtom(x11_display, "XdndAware", False); + xdnd_version = 5; + xdnd_enter = XInternAtom(x11_display, "XdndEnter", False); + xdnd_position = XInternAtom(x11_display, "XdndPosition", False); + xdnd_status = XInternAtom(x11_display, "XdndStatus", False); + xdnd_action_copy = XInternAtom(x11_display, "XdndActionCopy", False); + xdnd_drop = XInternAtom(x11_display, "XdndDrop", False); + xdnd_finished = XInternAtom(x11_display, "XdndFinished", False); + xdnd_selection = XInternAtom(x11_display, "XdndSelection", False); - long *wr = &pd.write[2]; - uint8_t const *pr = r; + //!!!!!!!!!!!!!!!!!!!!!!!!!! + //TODO - do Vulkan and GLES2 support checks, driver selection and fallback + rendering_driver = p_rendering_driver; - for (int i = 0; i < w * h; i++) { - long v = 0; - // A R G B - v |= pr[3] << 24 | pr[0] << 16 | pr[1] << 8 | pr[2]; - *wr++ = v; - pr += 4; - } +#ifndef _MSC_VER +#warning Forcing vulkan rendering driver because OpenGL not implemented yet +#endif + rendering_driver = "vulkan"; - XChangeProperty(x11_display, x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pd.ptr(), pd.size()); +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { - if (!g_set_icon_error) - break; + context_vulkan = memnew(VulkanContextX11); + if (context_vulkan->initialize() != OK) { + memdelete(context_vulkan); + context_vulkan = NULL; + r_error = ERR_CANT_CREATE; + ERR_FAIL_MSG("Could not initialize Vulkan"); } - } else { - XDeleteProperty(x11_display, x11_window, net_wm_icon); } - - XFlush(x11_display); - XSetErrorHandler(oldHandler); -} - -void OS_X11::force_process_input() { - process_xevents(); // get rid of pending events -#ifdef JOYDEV_ENABLED - joypad->process_joypads(); #endif -} + // Init context and rendering device +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + if (getenv("DRI_PRIME") == NULL) { + int use_prime = -1; -void OS_X11::run() { + if (getenv("PRIMUS_DISPLAY") || + getenv("PRIMUS_libGLd") || + getenv("PRIMUS_libGLa") || + getenv("PRIMUS_libGL") || + getenv("PRIMUS_LOAD_GLOBAL") || + getenv("BUMBLEBEE_SOCKET")) { - force_quit = false; + print_verbose("Optirun/primusrun detected. Skipping GPU detection"); + use_prime = 0; + } - if (!main_loop) - return; + if (getenv("LD_LIBRARY_PATH")) { + String ld_library_path(getenv("LD_LIBRARY_PATH")); + Vector<String> libraries = ld_library_path.split(":"); - main_loop->init(); + for (int i = 0; i < libraries.size(); ++i) { + if (FileAccess::exists(libraries[i] + "/libGL.so.1") || + FileAccess::exists(libraries[i] + "/libGL.so")) { - //uint64_t last_ticks=get_ticks_usec(); + print_verbose("Custom libGL override detected. Skipping GPU detection"); + use_prime = 0; + } + } + } - //int frames=0; - //uint64_t frame=0; + if (use_prime == -1) { + print_verbose("Detecting GPUs, set DRI_PRIME in the environment to override GPU detection logic."); + use_prime = detect_prime(); + } - while (!force_quit) { + if (use_prime) { + print_line("Found discrete GPU, setting DRI_PRIME=1 to use it."); + print_line("Note: Set DRI_PRIME=0 in the environment to disable Godot from using the discrete GPU."); + setenv("DRI_PRIME", "1", 1); + } + } - process_xevents(); // get rid of pending events -#ifdef JOYDEV_ENABLED - joypad->process_joypads(); -#endif - if (Main::iteration()) - break; - }; + ContextGL_X11::ContextType opengl_api_type = ContextGL_X11::GLES_2_0_COMPATIBLE; - main_loop->finish(); -} + context_gles2 = memnew(ContextGL_X11(x11_display, x11_window, current_videomode, opengl_api_type)); -bool OS_X11::is_joy_known(int p_device) { - return input->is_joy_mapped(p_device); -} + if (context_gles2->initialize() != OK) { + memdelete(context_gles2); + context_gles2 = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } -String OS_X11::get_joy_guid(int p_device) const { - return input->get_joy_guid_remapped(p_device); -} + context_gles2->set_use_vsync(current_videomode.use_vsync); -void OS_X11::_set_use_vsync(bool p_enable) { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - if (context_gles2) - context_gles2->set_use_vsync(p_enable); + if (RasterizerGLES2::is_viable() == OK) { + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + } else { + memdelete(context_gles2); + context_gles2 = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } } #endif -} - -void OS_X11::set_context(int p_context) { - XClassHint *classHint = XAllocClassHint(); + WindowID main_window = _create_window(p_mode, p_flags, Rect2i(Point2(), p_resolution)); + for (int i = 0; i < WINDOW_FLAG_MAX; i++) { + if (p_flags & (1 << i)) { + window_set_flag(WindowFlags(i), true, main_window); + } + } - if (classHint) { +//create RenderingDevice if used +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { - CharString name_str; - switch (p_context) { - case CONTEXT_EDITOR: - name_str = "Godot_Editor"; - break; - case CONTEXT_PROJECTMAN: - name_str = "Godot_ProjectList"; - break; - case CONTEXT_ENGINE: - name_str = "Godot_Engine"; - break; - } + //temporary + rendering_device_vulkan = memnew(RenderingDeviceVulkan); + rendering_device_vulkan->initialize(context_vulkan); - CharString class_str; - if (p_context == CONTEXT_ENGINE) { - String config_name = GLOBAL_GET("application/config/name"); - if (config_name.length() == 0) { - class_str = "Godot_Engine"; - } else { - class_str = config_name.utf8(); - } - } else { - class_str = "Godot"; - } + RasterizerRD::make_current(); + } +#endif - classHint->res_class = class_str.ptrw(); - classHint->res_name = name_str.ptrw(); + /* + visual_server = memnew(VisualServerRaster); + if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { + visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + } + */ - XSetClassHint(x11_display, x11_window, classHint); - XFree(classHint); + { + //set all event master mask + XIEventMask all_master_event_mask; + static unsigned char all_master_mask_data[XIMaskLen(XI_LASTEVENT)] = {}; + all_master_event_mask.deviceid = XIAllMasterDevices; + all_master_event_mask.mask_len = sizeof(all_master_mask_data); + all_master_event_mask.mask = all_master_mask_data; + XISetMask(all_master_event_mask.mask, XI_DeviceChanged); + XISetMask(all_master_event_mask.mask, XI_RawMotion); + XISelectEvents(x11_display, DefaultRootWindow(x11_display), &all_master_event_mask, 1); } -} -void OS_X11::disable_crash_handler() { - crash_handler.disable(); -} + // Disabled by now since grabbing also blocks mouse events + // (they are received as extended events instead of standard events) + /*XIClearMask(xi.touch_event_mask.mask, XI_TouchOwnership); -bool OS_X11::is_disable_crash_handler() const { - return crash_handler.is_disabled(); -} + // Grab touch devices to avoid OS gesture interference + for (int i = 0; i < xi.touch_devices.size(); ++i) { + XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask); + }*/ -static String get_mountpoint(const String &p_path) { - struct stat s; - if (stat(p_path.utf8().get_data(), &s)) { - return ""; - } + cursor_size = XcursorGetDefaultSize(x11_display); + cursor_theme = XcursorGetTheme(x11_display); -#ifdef HAVE_MNTENT - dev_t dev = s.st_dev; - FILE *fd = setmntent("/proc/mounts", "r"); - if (!fd) { - return ""; + if (!cursor_theme) { + print_verbose("XcursorGetTheme could not get cursor theme"); + cursor_theme = "default"; } - struct mntent mnt; - char buf[1024]; - size_t buflen = 1024; - while (getmntent_r(fd, &mnt, buf, buflen)) { - if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) { - endmntent(fd); - return String(mnt.mnt_dir); - } + for (int i = 0; i < CURSOR_MAX; i++) { + + cursors[i] = None; + img[i] = NULL; } - endmntent(fd); -#endif - return ""; -} + current_cursor = CURSOR_ARROW; -Error OS_X11::move_to_trash(const String &p_path) { - String trash_can = ""; - String mnt = get_mountpoint(p_path); + for (int i = 0; i < CURSOR_MAX; i++) { - // If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can. - if (mnt != "") { - String path(mnt + "/.Trash-" + itos(getuid()) + "/files"); - struct stat s; - if (!stat(path.utf8().get_data(), &s)) { - trash_can = path; - } - } + static const char *cursor_file[] = { + "left_ptr", + "xterm", + "hand2", + "cross", + "watch", + "left_ptr_watch", + "fleur", + "dnd-move", + "crossed_circle", + "v_double_arrow", + "h_double_arrow", + "size_bdiag", + "size_fdiag", + "move", + "row_resize", + "col_resize", + "question_arrow" + }; - // Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can. - if (trash_can == "") { - char *dhome = getenv("XDG_DATA_HOME"); - if (dhome) { - trash_can = String(dhome) + "/Trash/files"; - } - } + img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size); + if (!img[i]) { + const char *fallback = NULL; - // Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can. - if (trash_can == "") { - char *home = getenv("HOME"); - if (home) { - trash_can = String(home) + "/.local/share/Trash/files"; + switch (i) { + case CURSOR_POINTING_HAND: + fallback = "pointer"; + break; + case CURSOR_CROSS: + fallback = "crosshair"; + break; + case CURSOR_WAIT: + fallback = "wait"; + break; + case CURSOR_BUSY: + fallback = "progress"; + break; + case CURSOR_DRAG: + fallback = "grabbing"; + break; + case CURSOR_CAN_DROP: + fallback = "hand1"; + break; + case CURSOR_FORBIDDEN: + fallback = "forbidden"; + break; + case CURSOR_VSIZE: + fallback = "ns-resize"; + break; + case CURSOR_HSIZE: + fallback = "ew-resize"; + break; + case CURSOR_BDIAGSIZE: + fallback = "fd_double_arrow"; + break; + case CURSOR_FDIAGSIZE: + fallback = "bd_double_arrow"; + break; + case CURSOR_MOVE: + img[i] = img[CURSOR_DRAG]; + break; + case CURSOR_VSPLIT: + fallback = "sb_v_double_arrow"; + break; + case CURSOR_HSPLIT: + fallback = "sb_h_double_arrow"; + break; + case CURSOR_HELP: + fallback = "help"; + break; + } + if (fallback != NULL) { + img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size); + } + } + if (img[i]) { + cursors[i] = XcursorImageLoadCursor(x11_display, img[i]); + } else { + print_verbose("Failed loading custom cursor: " + String(cursor_file[i])); } } - // Issue an error if none of the previous locations is appropriate for the trash can. - if (trash_can == "") { - ERR_PRINT("move_to_trash: Could not determine the trash can location"); - return FAILED; - } + { + // Creating an empty/transparent cursor - // Create needed directories for decided trash can location. - DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - Error err = dir_access->make_dir_recursive(trash_can); - memdelete(dir_access); + // Create 1x1 bitmap + Pixmap cursormask = XCreatePixmap(x11_display, + RootWindow(x11_display, DefaultScreen(x11_display)), 1, 1, 1); - // Issue an error if trash can is not created proprely. - if (err != OK) { - ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\""); - return err; - } + // Fill with zero + XGCValues xgc; + xgc.function = GXclear; + GC gc = XCreateGC(x11_display, cursormask, GCFunction, &xgc); + XFillRectangle(x11_display, cursormask, gc, 0, 0, 1, 1); - // The trash can is successfully created, now move the given resource to it. - // Do not use DirAccess:rename() because it can't move files across multiple mountpoints. - List<String> mv_args; - mv_args.push_back(p_path); - mv_args.push_back(trash_can); - int retval; - err = execute("mv", mv_args, true, NULL, NULL, &retval); + // Color value doesn't matter. Mask zero means no foreground or background will be drawn + XColor col = {}; - // Issue an error if "mv" failed to move the given resource to the trash can. - if (err != OK || retval != 0) { - ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\""); - return FAILED; - } + Cursor cursor = XCreatePixmapCursor(x11_display, + cursormask, // source (using cursor mask as placeholder, since it'll all be ignored) + cursormask, // mask + &col, &col, 0, 0); - return OK; -} + XFreePixmap(x11_display, cursormask); + XFreeGC(x11_display, gc); -OS::LatinKeyboardVariant OS_X11::get_latin_keyboard_variant() const { + if (cursor == None) { + ERR_PRINT("FAILED CREATING CURSOR"); + } - XkbDescRec *xkbdesc = XkbAllocKeyboard(); - ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY); + null_cursor = cursor; + } + cursor_set_shape(CURSOR_BUSY); - XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc); - ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY); - ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY); + requested = None; - char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols); - ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY); + window_has_focus = true; // Set focus to true at init - Vector<String> info = String(layout).split("+"); - ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY); + /*if (p_desired.layered) { + set_window_per_pixel_transparency_enabled(true); + }*/ - if (info[1].find("colemak") != -1) { - return LATIN_KEYBOARD_COLEMAK; - } else if (info[1].find("qwertz") != -1) { - return LATIN_KEYBOARD_QWERTZ; - } else if (info[1].find("azerty") != -1) { - return LATIN_KEYBOARD_AZERTY; - } else if (info[1].find("qzerty") != -1) { - return LATIN_KEYBOARD_QZERTY; - } else if (info[1].find("dvorak") != -1) { - return LATIN_KEYBOARD_DVORAK; - } else if (info[1].find("neo") != -1) { - return LATIN_KEYBOARD_NEO; + XEvent xevent; + while (XPending(x11_display) > 0) { + XNextEvent(x11_display, &xevent); + if (xevent.type == ConfigureNotify) { + _window_changed(&xevent); + } } - return LATIN_KEYBOARD_QWERTY; + _update_real_mouse_position(windows[MAIN_WINDOW_ID]); + + r_error = OK; } +DisplayServerX11::~DisplayServerX11() { -void OS_X11::update_real_mouse_position() { - Window root_return, child_return; - int root_x, root_y, win_x, win_y; - unsigned int mask_return; + //destroy all windows + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { +#ifdef VULKAN_ENABLED + if (rendering_driver == "vulkan") { + context_vulkan->window_destroy(E->key()); + } +#endif - Bool xquerypointer_result = XQueryPointer(x11_display, x11_window, &root_return, &child_return, &root_x, &root_y, - &win_x, &win_y, &mask_return); + if (E->get().xic) { + XDestroyIC(E->get().xic); + } + XUnmapWindow(x11_display, E->get().x11_window); + XDestroyWindow(x11_display, E->get().x11_window); + } - if (xquerypointer_result) { - if (win_x > 0 && win_y > 0 && win_x <= current_videomode.width && win_y <= current_videomode.height) { + //destroy drivers +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { - last_mouse_pos.x = win_x; - last_mouse_pos.y = win_y; - last_mouse_pos_valid = true; - input->set_mouse_position(last_mouse_pos); + if (rendering_device_vulkan) { + rendering_device_vulkan->finalize(); + memdelete(rendering_device_vulkan); } + + if (context_vulkan) + memdelete(context_vulkan); } -} +#endif -OS_X11::OS_X11() { + if (xrandr_handle) + dlclose(xrandr_handle); -#ifdef PULSEAUDIO_ENABLED - AudioDriverManager::add_driver(&driver_pulseaudio); -#endif + for (int i = 0; i < CURSOR_MAX; i++) { + if (cursors[i] != None) + XFreeCursor(x11_display, cursors[i]); + if (img[i] != NULL) + XcursorImageDestroy(img[i]); + }; -#ifdef ALSA_ENABLED - AudioDriverManager::add_driver(&driver_alsa); -#endif + if (xim) { + XCloseIM(xim); + } - xi.opcode = 0; - xi.last_relative_time = 0; - layered_window = false; - minimized = false; - window_focused = true; - xim_style = 0L; - mouse_mode = MOUSE_MODE_VISIBLE; - last_position_before_fs = Vector2(); + XCloseDisplay(x11_display); + if (xmbstring) + memfree(xmbstring); } + +void DisplayServerX11::register_x11_driver() { + + register_create_function("x11", create_func, get_rendering_drivers_func); +} + +#endif // X11 enabled diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h new file mode 100644 index 0000000000..d1680b0508 --- /dev/null +++ b/platform/linuxbsd/display_server_x11.h @@ -0,0 +1,352 @@ +/*************************************************************************/ +/* display_server_x11.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DISPLAY_SERVER_X11_H +#define DISPLAY_SERVER_X11_H + +#ifdef X11_ENABLED + +#include "servers/display_server.h" + +#include "core/input/input_filter.h" + +#include "drivers/alsa/audio_driver_alsa.h" +#include "drivers/alsamidi/midi_driver_alsamidi.h" +#include "drivers/pulseaudio/audio_driver_pulseaudio.h" +#include "drivers/unix/os_unix.h" +#include "joypad_linux.h" +#include "servers/audio_server.h" +#include "servers/visual/rasterizer.h" +#include "servers/visual_server.h" + +#if defined(OPENGL_ENABLED) +#include "context_gl_x11.h" +#endif + +#if defined(VULKAN_ENABLED) +#include "drivers/vulkan/rendering_device_vulkan.h" +#include "platform/linuxbsd/vulkan_context_x11.h" +#endif + +#include <X11/Xcursor/Xcursor.h> +#include <X11/Xlib.h> +#include <X11/extensions/XInput2.h> +#include <X11/extensions/Xrandr.h> +#include <X11/keysym.h> + +// Hints for X11 fullscreen +typedef struct { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long inputMode; + unsigned long status; +} Hints; + +typedef struct _xrr_monitor_info { + Atom name; + Bool primary; + Bool automatic; + int noutput; + int x; + int y; + int width; + int height; + int mwidth; + int mheight; + RROutput *outputs; +} xrr_monitor_info; + +#undef CursorShape + +class DisplayServerX11 : public DisplayServer { + //No need to register, it's platform-specific and nothing is added + //GDCLASS(DisplayServerX11, DisplayServer) + + _THREAD_SAFE_CLASS_ + + Atom wm_delete; + Atom xdnd_enter; + Atom xdnd_position; + Atom xdnd_status; + Atom xdnd_action_copy; + Atom xdnd_drop; + Atom xdnd_finished; + Atom xdnd_selection; + Atom xdnd_aware; + Atom requested; + int xdnd_version; + +#if defined(OPENGL_ENABLED) + ContextGL_X11 *context_gles2; +#endif +#if defined(VULKAN_ENABLED) + VulkanContextX11 *context_vulkan; + RenderingDeviceVulkan *rendering_device_vulkan; +#endif + + struct WindowData { + Window x11_window; + ::XIC xic; + + Size2i min_size; + Size2i max_size; + Point2i position; + Size2i size; + Point2i im_position; + bool im_active = false; + Callable rect_changed_callback; + Callable event_callback; + Callable input_event_callback; + Callable input_text_callback; + Callable drop_files_callback; + + WindowID transient_parent = INVALID_WINDOW_ID; + Set<WindowID> transient_children; + + ObjectID instance_id; + + //better to guess on the fly, given WM can change it + //WindowMode mode; + bool fullscreen = false; //OS can't exit from this mode + bool on_top = false; + bool borderless = false; + bool resize_disabled = false; + Vector2i last_position_before_fs; + }; + + Map<WindowID, WindowData> windows; + + WindowID window_id_counter = MAIN_WINDOW_ID; + WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect); + + String internal_clipboard; + Window xdnd_source_window; + ::Display *x11_display; + char *xmbstring; + int xmblen; + unsigned long last_timestamp; + ::Time last_keyrelease_time; + ::XIM xim; + ::XIMStyle xim_style; + static void _xim_destroy_callback(::XIM im, ::XPointer client_data, + ::XPointer call_data); + + Point2i last_mouse_pos; + bool last_mouse_pos_valid; + Point2i last_click_pos; + uint64_t last_click_ms; + int last_click_button_index; + uint32_t last_button_state; + + struct { + int opcode; + Vector<int> touch_devices; + Map<int, Vector2> absolute_devices; + Map<int, Vector3> pen_devices; + XIEventMask all_event_mask; + Map<int, Vector2> state; + double pressure; + Vector2 tilt; + Vector2 mouse_pos_to_filter; + Vector2 relative_motion; + Vector2 raw_pos; + Vector2 old_raw_pos; + ::Time last_relative_time; + } xi; + + bool _refresh_device_info(); + + unsigned int _get_mouse_button_state(unsigned int p_x11_button, int p_x11_type); + void _get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state); + void _flush_mouse_motion(); + + MouseMode mouse_mode; + Point2i center; + + void _handle_key_event(WindowID p_window, XKeyEvent *p_event, bool p_echo = false); + + bool force_quit; + bool minimized; + bool window_has_focus; + bool do_mouse_warp; + + const char *cursor_theme; + int cursor_size; + XcursorImage *img[CURSOR_MAX]; + Cursor cursors[CURSOR_MAX]; + Cursor null_cursor; + CursorShape current_cursor; + Map<CursorShape, Vector<Variant>> cursors_cache; + + bool layered_window; + + String rendering_driver; + bool window_focused; + //void set_wm_border(bool p_enabled); + void set_wm_fullscreen(bool p_enabled); + void set_wm_above(bool p_enabled); + + typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors); + typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors); + xrr_get_monitors_t xrr_get_monitors; + xrr_free_monitors_t xrr_free_monitors; + void *xrandr_handle; + Bool xrandr_ext_ok; + + struct Property { + unsigned char *data; + int format, nitems; + Atom type; + }; + static Property _read_property(Display *p_display, Window p_window, Atom p_property); + + void _update_real_mouse_position(const WindowData &wd); + void _set_wm_fullscreen(WindowID p_window, bool p_enabled); + void _set_wm_maximized(WindowID p_window, bool p_enabled); + + void _update_context(WindowData &wd); + + Context context = CONTEXT_ENGINE; + + void _send_window_event(const WindowData &wd, WindowEvent p_event); + static void _dispatch_input_events(const Ref<InputEvent> &p_event); + void _dispatch_input_event(const Ref<InputEvent> &p_event); + +protected: + void _window_changed(XEvent *event); + +public: + virtual bool has_feature(Feature p_feature) const; + virtual String get_name() const; + + virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); + + virtual void mouse_set_mode(MouseMode p_mode); + virtual MouseMode mouse_get_mode() const; + + virtual void mouse_warp_to_position(const Point2i &p_to); + virtual Point2i mouse_get_position() const; + virtual Point2i mouse_get_absolute_position() const; + virtual int mouse_get_button_state() const; + + virtual void clipboard_set(const String &p_text); + virtual String clipboard_get() const; + + virtual int get_screen_count() const; + virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + + virtual Vector<DisplayServer::WindowID> get_window_list() const; + + virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); + virtual void delete_sub_window(WindowID p_id); + + virtual WindowID get_window_at_screen_position(const Point2i &p_position) const; + + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID); + virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + + virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const; + virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID); + + virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const; + virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_transient(WindowID p_window, WindowID p_parent); + + virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const; + virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID); + virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID); + virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID); + + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual bool can_any_window_draw() const; + + virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); + + virtual void cursor_set_shape(CursorShape p_shape); + virtual CursorShape cursor_get_shape() const; + virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); + + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + + virtual void process_events(); + + virtual void release_rendering_thread(); + virtual void make_rendering_thread(); + virtual void swap_buffers(); + + virtual void set_context(Context p_context); + + virtual void set_native_icon(const String &p_filename); + virtual void set_icon(const Ref<Image> &p_icon); + + static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + static Vector<String> get_rendering_drivers_func(); + + static void register_x11_driver(); + + DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + ~DisplayServerX11(); +}; + +#endif // X11 enabled + +#endif // DISPLAY_SERVER_X11_H diff --git a/platform/x11/export/export.cpp b/platform/linuxbsd/export/export.cpp index 1c0c6ec096..53e3ce8f85 100644 --- a/platform/x11/export/export.cpp +++ b/platform/linuxbsd/export/export.cpp @@ -32,17 +32,17 @@ #include "core/os/file_access.h" #include "editor/editor_export.h" -#include "platform/x11/logo.gen.h" +#include "platform/linuxbsd/logo.gen.h" #include "scene/resources/texture.h" static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size); -void register_x11_exporter() { +void register_linuxbsd_exporter() { Ref<EditorExportPlatformPC> platform; platform.instance(); - Ref<Image> img = memnew(Image(_x11_logo)); + Ref<Image> img = memnew(Image(_linuxbsd_logo)); Ref<ImageTexture> logo; logo.instance(); logo->create_from_image(img); diff --git a/platform/x11/export/export.h b/platform/linuxbsd/export/export.h index 4049e6a8bf..5ee81f485e 100644 --- a/platform/x11/export/export.h +++ b/platform/linuxbsd/export/export.h @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef X11_EXPORT_H -#define X11_EXPORT_H +#ifndef LINUXBSD_EXPORT_H +#define LINUXBSD_EXPORT_H -void register_x11_exporter(); +void register_linuxbsd_exporter(); -#endif // X11_EXPORT_H +#endif // LINUXBSD_EXPORT_H diff --git a/platform/x11/godot_x11.cpp b/platform/linuxbsd/godot_linuxbsd.cpp index 77b74184ad..710ba3ca40 100644 --- a/platform/x11/godot_x11.cpp +++ b/platform/linuxbsd/godot_linuxbsd.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_x11.cpp */ +/* godot_linuxbsd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -34,11 +34,11 @@ #include <unistd.h> #include "main/main.h" -#include "os_x11.h" +#include "os_linuxbsd.h" int main(int argc, char *argv[]) { - OS_X11 os; + OS_LinuxBSD os; setlocale(LC_CTYPE, ""); diff --git a/platform/x11/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp index 1aacc6a250..c4c793093d 100644 --- a/platform/x11/joypad_linux.cpp +++ b/platform/linuxbsd/joypad_linux.cpp @@ -71,7 +71,7 @@ void JoypadLinux::Joypad::reset() { dpad = 0; fd = -1; - InputDefault::JoyAxis jx; + InputFilter::JoyAxis jx; jx.min = -1; jx.value = 0.0f; for (int i = 0; i < MAX_ABS; i++) { @@ -80,7 +80,7 @@ void JoypadLinux::Joypad::reset() { } } -JoypadLinux::JoypadLinux(InputDefault *in) { +JoypadLinux::JoypadLinux(InputFilter *in) { exit_udev = false; input = in; joy_thread = Thread::create(joy_thread_func, this); @@ -436,11 +436,11 @@ void JoypadLinux::joypad_vibration_stop(int p_id, uint64_t p_timestamp) { joy.ff_effect_timestamp = p_timestamp; } -InputDefault::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { +InputFilter::JoyAxis JoypadLinux::axis_correct(const input_absinfo *p_abs, int p_value) const { int min = p_abs->minimum; int max = p_abs->maximum; - InputDefault::JoyAxis jx; + InputFilter::JoyAxis jx; if (min < 0) { jx.min = -1; @@ -492,11 +492,11 @@ void JoypadLinux::process_joypads() { case ABS_HAT0X: if (ev.value != 0) { if (ev.value < 0) - joy->dpad |= InputDefault::HAT_MASK_LEFT; + joy->dpad |= InputFilter::HAT_MASK_LEFT; else - joy->dpad |= InputDefault::HAT_MASK_RIGHT; + joy->dpad |= InputFilter::HAT_MASK_RIGHT; } else - joy->dpad &= ~(InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_RIGHT); + joy->dpad &= ~(InputFilter::HAT_MASK_LEFT | InputFilter::HAT_MASK_RIGHT); input->joy_hat(i, joy->dpad); break; @@ -504,11 +504,11 @@ void JoypadLinux::process_joypads() { case ABS_HAT0Y: if (ev.value != 0) { if (ev.value < 0) - joy->dpad |= InputDefault::HAT_MASK_UP; + joy->dpad |= InputFilter::HAT_MASK_UP; else - joy->dpad |= InputDefault::HAT_MASK_DOWN; + joy->dpad |= InputFilter::HAT_MASK_DOWN; } else - joy->dpad &= ~(InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_DOWN); + joy->dpad &= ~(InputFilter::HAT_MASK_UP | InputFilter::HAT_MASK_DOWN); input->joy_hat(i, joy->dpad); break; @@ -517,7 +517,7 @@ void JoypadLinux::process_joypads() { if (ev.code >= MAX_ABS) return; if (joy->abs_map[ev.code] != -1 && joy->abs_info[ev.code]) { - InputDefault::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value); + InputFilter::JoyAxis value = axis_correct(joy->abs_info[ev.code], ev.value); joy->curr_axis[joy->abs_map[ev.code]] = value; } break; diff --git a/platform/x11/joypad_linux.h b/platform/linuxbsd/joypad_linux.h index d5719b6dbe..1d2ed5bbc1 100644 --- a/platform/x11/joypad_linux.h +++ b/platform/linuxbsd/joypad_linux.h @@ -33,15 +33,15 @@ #define JOYPAD_LINUX_H #ifdef JOYDEV_ENABLED +#include "core/input/input_filter.h" #include "core/os/mutex.h" #include "core/os/thread.h" -#include "main/input_default.h" struct input_absinfo; class JoypadLinux { public: - JoypadLinux(InputDefault *in); + JoypadLinux(InputFilter *in); ~JoypadLinux(); void process_joypads(); @@ -53,7 +53,7 @@ private: }; struct Joypad { - InputDefault::JoyAxis curr_axis[MAX_ABS]; + InputFilter::JoyAxis curr_axis[MAX_ABS]; int key_map[MAX_KEY]; int abs_map[MAX_ABS]; int dpad; @@ -74,7 +74,7 @@ private: bool exit_udev; Mutex joy_mutex; Thread *joy_thread; - InputDefault *input; + InputFilter *input; Joypad joypads[JOYPADS_MAX]; Vector<String> attached_devices; @@ -95,7 +95,7 @@ private: void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); void joypad_vibration_stop(int p_id, uint64_t p_timestamp); - InputDefault::JoyAxis axis_correct(const input_absinfo *p_abs, int p_value) const; + InputFilter::JoyAxis axis_correct(const input_absinfo *p_abs, int p_value) const; }; #endif diff --git a/platform/x11/key_mapping_x11.cpp b/platform/linuxbsd/key_mapping_x11.cpp index 78bd2b71a0..78bd2b71a0 100644 --- a/platform/x11/key_mapping_x11.cpp +++ b/platform/linuxbsd/key_mapping_x11.cpp diff --git a/platform/x11/key_mapping_x11.h b/platform/linuxbsd/key_mapping_x11.h index 10db43bcc4..10db43bcc4 100644 --- a/platform/x11/key_mapping_x11.h +++ b/platform/linuxbsd/key_mapping_x11.h diff --git a/platform/x11/logo.png b/platform/linuxbsd/logo.png Binary files differindex 078654b757..078654b757 100644 --- a/platform/x11/logo.png +++ b/platform/linuxbsd/logo.png diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp new file mode 100644 index 0000000000..084453bdc6 --- /dev/null +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -0,0 +1,381 @@ +/*************************************************************************/ +/* os_linuxbsd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "os_linuxbsd.h" + +#include "core/os/dir_access.h" +#include "core/print_string.h" +#include "errno.h" + +#ifdef HAVE_MNTENT +#include <mntent.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <dlfcn.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "main/main.h" + +#ifdef X11_ENABLED +#include "display_server_x11.h" +#endif + +void OS_LinuxBSD::initialize() { + + crash_handler.initialize(); + + OS_Unix::initialize_core(); +} + +void OS_LinuxBSD::initialize_joypads() { + +#ifdef JOYDEV_ENABLED + joypad = memnew(JoypadLinux(InputFilter::get_singleton())); +#endif +} + +String OS_LinuxBSD::get_unique_id() const { + + static String machine_id; + if (machine_id.empty()) { + if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) { + while (machine_id.empty() && !f->eof_reached()) { + machine_id = f->get_line().strip_edges(); + } + f->close(); + memdelete(f); + } + } + return machine_id; +} + +void OS_LinuxBSD::finalize() { + + if (main_loop) + memdelete(main_loop); + main_loop = NULL; + +#ifdef ALSAMIDI_ENABLED + driver_alsamidi.close(); +#endif + +#ifdef JOYDEV_ENABLED + memdelete(joypad); +#endif +} + +MainLoop *OS_LinuxBSD::get_main_loop() const { + + return main_loop; +} + +void OS_LinuxBSD::delete_main_loop() { + + if (main_loop) + memdelete(main_loop); + main_loop = NULL; +} + +void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) { + + main_loop = p_main_loop; +} + +String OS_LinuxBSD::get_name() const { + +#ifdef __linux__ + return "Linux"; +#elif defined(__FreeBSD__) + return "FreeBSD"; +#elif defined(__NetBSD__) + return "NetBSD"; +#else + return "BSD"; +#endif +} + +Error OS_LinuxBSD::shell_open(String p_uri) { + + Error ok; + List<String> args; + args.push_back(p_uri); + ok = execute("xdg-open", args, false); + if (ok == OK) + return OK; + ok = execute("gnome-open", args, false); + if (ok == OK) + return OK; + ok = execute("kde-open", args, false); + return ok; +} + +bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) { + + return p_feature == "pc"; +} + +String OS_LinuxBSD::get_config_path() const { + + if (has_environment("XDG_CONFIG_HOME")) { + return get_environment("XDG_CONFIG_HOME"); + } else if (has_environment("HOME")) { + return get_environment("HOME").plus_file(".config"); + } else { + return "."; + } +} + +String OS_LinuxBSD::get_data_path() const { + + if (has_environment("XDG_DATA_HOME")) { + return get_environment("XDG_DATA_HOME"); + } else if (has_environment("HOME")) { + return get_environment("HOME").plus_file(".local/share"); + } else { + return get_config_path(); + } +} + +String OS_LinuxBSD::get_cache_path() const { + + if (has_environment("XDG_CACHE_HOME")) { + return get_environment("XDG_CACHE_HOME"); + } else if (has_environment("HOME")) { + return get_environment("HOME").plus_file(".cache"); + } else { + return get_config_path(); + } +} + +String OS_LinuxBSD::get_system_dir(SystemDir p_dir) const { + + String xdgparam; + + switch (p_dir) { + case SYSTEM_DIR_DESKTOP: { + + xdgparam = "DESKTOP"; + } break; + case SYSTEM_DIR_DCIM: { + + xdgparam = "PICTURES"; + + } break; + case SYSTEM_DIR_DOCUMENTS: { + + xdgparam = "DOCUMENTS"; + + } break; + case SYSTEM_DIR_DOWNLOADS: { + + xdgparam = "DOWNLOAD"; + + } break; + case SYSTEM_DIR_MOVIES: { + + xdgparam = "VIDEOS"; + + } break; + case SYSTEM_DIR_MUSIC: { + + xdgparam = "MUSIC"; + + } break; + case SYSTEM_DIR_PICTURES: { + + xdgparam = "PICTURES"; + + } break; + case SYSTEM_DIR_RINGTONES: { + + xdgparam = "MUSIC"; + + } break; + } + + String pipe; + List<String> arg; + arg.push_back(xdgparam); + Error err = const_cast<OS_LinuxBSD *>(this)->execute("xdg-user-dir", arg, true, NULL, &pipe); + if (err != OK) + return "."; + return pipe.strip_edges(); +} + +void OS_LinuxBSD::run() { + + force_quit = false; + + if (!main_loop) + return; + + main_loop->init(); + + //uint64_t last_ticks=get_ticks_usec(); + + //int frames=0; + //uint64_t frame=0; + + while (!force_quit) { + + DisplayServer::get_singleton()->process_events(); // get rid of pending events +#ifdef JOYDEV_ENABLED + joypad->process_joypads(); +#endif + if (Main::iteration()) + break; + }; + + main_loop->finish(); +} + +void OS_LinuxBSD::disable_crash_handler() { + crash_handler.disable(); +} + +bool OS_LinuxBSD::is_disable_crash_handler() const { + return crash_handler.is_disabled(); +} + +static String get_mountpoint(const String &p_path) { + struct stat s; + if (stat(p_path.utf8().get_data(), &s)) { + return ""; + } + +#ifdef HAVE_MNTENT + dev_t dev = s.st_dev; + FILE *fd = setmntent("/proc/mounts", "r"); + if (!fd) { + return ""; + } + + struct mntent mnt; + char buf[1024]; + size_t buflen = 1024; + while (getmntent_r(fd, &mnt, buf, buflen)) { + if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) { + endmntent(fd); + return String(mnt.mnt_dir); + } + } + + endmntent(fd); +#endif + return ""; +} + +Error OS_LinuxBSD::move_to_trash(const String &p_path) { + String trash_can = ""; + String mnt = get_mountpoint(p_path); + + // If there is a directory "[Mountpoint]/.Trash-[UID]/files", use it as the trash can. + if (mnt != "") { + String path(mnt + "/.Trash-" + itos(getuid()) + "/files"); + struct stat s; + if (!stat(path.utf8().get_data(), &s)) { + trash_can = path; + } + } + + // Otherwise, if ${XDG_DATA_HOME} is defined, use "${XDG_DATA_HOME}/Trash/files" as the trash can. + if (trash_can == "") { + char *dhome = getenv("XDG_DATA_HOME"); + if (dhome) { + trash_can = String(dhome) + "/Trash/files"; + } + } + + // Otherwise, if ${HOME} is defined, use "${HOME}/.local/share/Trash/files" as the trash can. + if (trash_can == "") { + char *home = getenv("HOME"); + if (home) { + trash_can = String(home) + "/.local/share/Trash/files"; + } + } + + // Issue an error if none of the previous locations is appropriate for the trash can. + if (trash_can == "") { + ERR_PRINT("move_to_trash: Could not determine the trash can location"); + return FAILED; + } + + // Create needed directories for decided trash can location. + DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + Error err = dir_access->make_dir_recursive(trash_can); + memdelete(dir_access); + + // Issue an error if trash can is not created proprely. + if (err != OK) { + ERR_PRINT("move_to_trash: Could not create the trash can \"" + trash_can + "\""); + return err; + } + + // The trash can is successfully created, now move the given resource to it. + // Do not use DirAccess:rename() because it can't move files across multiple mountpoints. + List<String> mv_args; + mv_args.push_back(p_path); + mv_args.push_back(trash_can); + int retval; + err = execute("mv", mv_args, true, NULL, NULL, &retval); + + // Issue an error if "mv" failed to move the given resource to the trash can. + if (err != OK || retval != 0) { + ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_can + "\""); + return FAILED; + } + + return OK; +} + +OS_LinuxBSD::OS_LinuxBSD() { + + main_loop = NULL; + force_quit = false; + +#ifdef PULSEAUDIO_ENABLED + AudioDriverManager::add_driver(&driver_pulseaudio); +#endif + +#ifdef ALSA_ENABLED + AudioDriverManager::add_driver(&driver_alsa); +#endif + +#ifdef X11_ENABLED + DisplayServerX11::register_x11_driver(); +#endif +} diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h new file mode 100644 index 0000000000..6c656c1945 --- /dev/null +++ b/platform/linuxbsd/os_linuxbsd.h @@ -0,0 +1,106 @@ +/*************************************************************************/ +/* os_linuxbsd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef OS_LINUXBSD_H +#define OS_LINUXBSD_H + +#include "core/input/input_filter.h" +#include "crash_handler_linuxbsd.h" +#include "drivers/alsa/audio_driver_alsa.h" +#include "drivers/alsamidi/midi_driver_alsamidi.h" +#include "drivers/pulseaudio/audio_driver_pulseaudio.h" +#include "drivers/unix/os_unix.h" +#include "joypad_linux.h" +#include "servers/audio_server.h" +#include "servers/visual/rasterizer.h" +#include "servers/visual_server.h" + +class OS_LinuxBSD : public OS_Unix { + + virtual void delete_main_loop(); + + bool force_quit; + +#ifdef JOYDEV_ENABLED + JoypadLinux *joypad; +#endif + +#ifdef ALSA_ENABLED + AudioDriverALSA driver_alsa; +#endif + +#ifdef ALSAMIDI_ENABLED + MIDIDriverALSAMidi driver_alsamidi; +#endif + +#ifdef PULSEAUDIO_ENABLED + AudioDriverPulseAudio driver_pulseaudio; +#endif + + CrashHandler crash_handler; + + MainLoop *main_loop; + +protected: + virtual void initialize(); + virtual void finalize(); + + virtual void initialize_joypads(); + + virtual void set_main_loop(MainLoop *p_main_loop); + +public: + virtual String get_name() const; + + virtual MainLoop *get_main_loop() const; + + virtual String get_config_path() const; + virtual String get_data_path() const; + virtual String get_cache_path() const; + + virtual String get_system_dir(SystemDir p_dir) const; + + virtual Error shell_open(String p_uri); + + virtual String get_unique_id() const; + + virtual bool _check_internal_feature_support(const String &p_feature); + + void run(); + + void disable_crash_handler(); + bool is_disable_crash_handler() const; + + virtual Error move_to_trash(const String &p_path); + + OS_LinuxBSD(); +}; + +#endif diff --git a/platform/x11/pck_embed.ld b/platform/linuxbsd/pck_embed.ld index 57a1994043..57a1994043 100644 --- a/platform/x11/pck_embed.ld +++ b/platform/linuxbsd/pck_embed.ld diff --git a/platform/x11/pck_embed.legacy.ld b/platform/linuxbsd/pck_embed.legacy.ld index a23013ba7a..a23013ba7a 100644 --- a/platform/x11/pck_embed.legacy.ld +++ b/platform/linuxbsd/pck_embed.legacy.ld diff --git a/platform/x11/platform_config.h b/platform/linuxbsd/platform_config.h index ac30519132..ac30519132 100644 --- a/platform/x11/platform_config.h +++ b/platform/linuxbsd/platform_config.h diff --git a/platform/x11/platform_x11_builders.py b/platform/linuxbsd/platform_linuxbsd_builders.py index 5ff0c6fb14..a72306a9c0 100644 --- a/platform/x11/platform_x11_builders.py +++ b/platform/linuxbsd/platform_linuxbsd_builders.py @@ -7,7 +7,7 @@ import os from platform_methods import subprocess_main -def make_debug_x11(target, source, env): +def make_debug_linuxbsd(target, source, env): os.system('objcopy --only-keep-debug {0} {0}.debugsymbols'.format(target[0])) os.system('strip --strip-debug --strip-unneeded {0}'.format(target[0])) os.system('objcopy --add-gnu-debuglink={0}.debugsymbols {0}'.format(target[0])) diff --git a/platform/x11/vulkan_context_x11.cpp b/platform/linuxbsd/vulkan_context_x11.cpp index 602dbc77a2..d0e1b1678c 100644 --- a/platform/x11/vulkan_context_x11.cpp +++ b/platform/linuxbsd/vulkan_context_x11.cpp @@ -35,7 +35,7 @@ const char *VulkanContextX11::_get_platform_surface_extension() const { return VK_KHR_XLIB_SURFACE_EXTENSION_NAME; } -int VulkanContextX11::window_create(::Window p_window, Display *p_display, int p_width, int p_height) { +Error VulkanContextX11::window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height) { VkXlibSurfaceCreateInfoKHR createInfo; createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; @@ -46,8 +46,8 @@ int VulkanContextX11::window_create(::Window p_window, Display *p_display, int p VkSurfaceKHR surface; VkResult err = vkCreateXlibSurfaceKHR(_get_instance(), &createInfo, NULL, &surface); - ERR_FAIL_COND_V(err, -1); - return _window_create(surface, p_width, p_height); + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + return _window_create(p_window_id, surface, p_width, p_height); } VulkanContextX11::VulkanContextX11() { diff --git a/platform/x11/vulkan_context_x11.h b/platform/linuxbsd/vulkan_context_x11.h index 573f994ea6..6e144ab2d9 100644 --- a/platform/x11/vulkan_context_x11.h +++ b/platform/linuxbsd/vulkan_context_x11.h @@ -39,7 +39,7 @@ class VulkanContextX11 : public VulkanContext { virtual const char *_get_platform_surface_extension() const; public: - int window_create(::Window p_window, Display *p_display, int p_width, int p_height); + Error window_create(DisplayServer::WindowID p_window_id, ::Window p_window, Display *p_display, int p_width, int p_height); VulkanContextX11(); ~VulkanContextX11(); diff --git a/platform/osx/SCsub b/platform/osx/SCsub index 0a4e0a45e1..4ec8aeab6d 100644 --- a/platform/osx/SCsub +++ b/platform/osx/SCsub @@ -8,6 +8,7 @@ import platform_osx_builders files = [ 'crash_handler_osx.mm', 'os_osx.mm', + 'display_server_osx.mm', 'godot_main_osx.mm', 'dir_access_osx.mm', 'joypad_osx.cpp', diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h new file mode 100644 index 0000000000..d0e2babd06 --- /dev/null +++ b/platform/osx/display_server_osx.h @@ -0,0 +1,306 @@ +/*************************************************************************/ +/* display_server_osx.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DISPLAY_SERVER_OSX_H +#define DISPLAY_SERVER_OSX_H + +#define BitMap _QDBitMap // Suppress deprecated QuickDraw definition. + +#include "core/input/input_filter.h" +#include "servers/display_server.h" + +#if defined(OPENGL_ENABLED) +#include "context_gl_osx.h" +//TODO - reimplement OpenGLES +#endif + +#if defined(VULKAN_ENABLED) +#include "drivers/vulkan/rendering_device_vulkan.h" +#include "platform/osx/vulkan_context_osx.h" +#endif + +#include <AppKit/AppKit.h> +#include <AppKit/NSCursor.h> +#include <ApplicationServices/ApplicationServices.h> +#include <CoreVideo/CoreVideo.h> + +#undef BitMap +#undef CursorShape + +class DisplayServerOSX : public DisplayServer { + GDCLASS(DisplayServerOSX, DisplayServer) + + _THREAD_SAFE_CLASS_ + +public: +#if defined(OPENGL_ENABLED) + ContextGL_OSX *context_gles2; +#endif +#if defined(VULKAN_ENABLED) + VulkanContextOSX *context_vulkan; + RenderingDeviceVulkan *rendering_device_vulkan; +#endif + + const NSMenu *_get_menu_root(const String &p_menu_root) const; + NSMenu *_get_menu_root(const String &p_menu_root); + + NSMenu *apple_menu = NULL; + NSMenu *dock_menu = NULL; + Map<String, NSMenu *> submenu; + + struct KeyEvent { + WindowID window_id; + unsigned int osx_state; + bool pressed; + bool echo; + bool raw; + uint32_t keycode; + uint32_t physical_keycode; + uint32_t unicode; + }; + + Vector<KeyEvent> key_event_buffer; + int key_event_pos; + + struct WindowData { + id window_delegate; + id window_object; + id window_view; + +#if defined(OPENGL_ENABLED) + ContextGL_OSX *context_gles2 = NULL; +#endif + Point2i mouse_pos; + + Size2i min_size; + Size2i max_size; + Size2i size; + + bool mouse_down_control = false; + + bool im_active = false; + Size2i im_position; + + Callable rect_changed_callback; + Callable event_callback; + Callable input_event_callback; + Callable input_text_callback; + Callable drop_files_callback; + + ObjectID instance_id; + + WindowID transient_parent = INVALID_WINDOW_ID; + Set<WindowID> transient_children; + + bool layered_window = false; + bool fullscreen = false; + bool on_top = false; + bool borderless = false; + bool resize_disabled = false; + }; + + Point2i im_selection; + String im_text; + + Map<WindowID, WindowData> windows; + + WindowID window_id_counter = MAIN_WINDOW_ID; + + WindowID _create_window(WindowMode p_mode, const Rect2i &p_rect); + void _update_window(WindowData p_wd); + void _send_window_event(const WindowData &wd, WindowEvent p_event); + static void _dispatch_input_events(const Ref<InputEvent> &p_event); + void _dispatch_input_event(const Ref<InputEvent> &p_event); + WindowID _find_window_id(id p_window); + + void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window); + + float _display_scale(id screen) const; + Point2i _get_screens_origin() const; + Point2i _get_native_screen_position(int p_screen) const; + + void _push_input(const Ref<InputEvent> &p_event); + void _process_key_events(); + + String rendering_driver; + + id delegate; + id autoreleasePool; + CGEventSourceRef eventSource; + + CursorShape cursor_shape; + NSCursor *cursors[CURSOR_MAX]; + Map<CursorShape, Vector<Variant>> cursors_cache; + + MouseMode mouse_mode; + Point2i last_mouse_pos; + uint32_t last_button_state; + + bool window_focused; + bool drop_events; + +public: + virtual bool has_feature(Feature p_feature) const; + virtual String get_name() const; + + virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()); + virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()); + virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu); + virtual void global_menu_add_separator(const String &p_menu_root); + + virtual bool global_menu_is_item_checked(const String &p_menu_root, int p_idx) const; + virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const; + virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx); + virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx); + virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx); + virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx); + + virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked); + virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); + virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback); + virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag); + virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text); + virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu); + + virtual int global_menu_get_item_count(const String &p_menu_root) const; + + virtual void global_menu_remove_item(const String &p_menu_root, int p_idx); + virtual void global_menu_clear(const String &p_menu_root); + + virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); + virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback); + virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback); + + virtual void mouse_set_mode(MouseMode p_mode); + virtual MouseMode mouse_get_mode() const; + + virtual void mouse_warp_to_position(const Point2i &p_to); + virtual Point2i mouse_get_position() const; + virtual Point2i mouse_get_absolute_position() const; + virtual int mouse_get_button_state() const; + + virtual void clipboard_set(const String &p_text); + virtual String clipboard_get() const; + + virtual int get_screen_count() const; + virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + + virtual Vector<int> get_window_list() const; + + virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i()); + virtual void delete_sub_window(WindowID p_id); + + virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID); + + virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const; + virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID); + + virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const; + virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_transient(WindowID p_window, WindowID p_parent); + + virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const; + virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID); + virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID); + virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID); + virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID); + + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual bool can_any_window_draw() const; + + virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); + + virtual WindowID get_window_at_screen_position(const Point2i &p_position) const; + + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID); + virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual Point2i ime_get_selection() const; + virtual String ime_get_text() const; + + virtual void cursor_set_shape(CursorShape p_shape); + virtual CursorShape cursor_get_shape() const; + virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); + + virtual bool get_swap_ok_cancel(); + + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + + virtual void process_events(); + virtual void force_process_and_drop_events(); + + virtual void release_rendering_thread(); + virtual void make_rendering_thread(); + virtual void swap_buffers(); + + virtual void set_native_icon(const String &p_filename); + virtual void set_icon(const Ref<Image> &p_icon); + + virtual void console_set_visible(bool p_enabled); + virtual bool is_console_visible() const; + + static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + static Vector<String> get_rendering_drivers_func(); + + static void register_osx_driver(); + + DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + ~DisplayServerOSX(); +}; + +#endif // DISPLAY_SERVER_OSX_H diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm new file mode 100644 index 0000000000..a7099c1207 --- /dev/null +++ b/platform/osx/display_server_osx.mm @@ -0,0 +1,3587 @@ +/*************************************************************************/ +/* display_server_osx.mm */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "display_server_osx.h" + +#include "os_osx.h" + +#include "core/io/marshalls.h" +#include "core/os/keyboard.h" +#include "main/main.h" +#include "scene/resources/texture.h" + +#include <Carbon/Carbon.h> +#include <Cocoa/Cocoa.h> +#include <IOKit/IOCFPlugIn.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/hid/IOHIDKeys.h> +#include <IOKit/hid/IOHIDLib.h> + +#if defined(OPENGL_ENABLED) +#include "drivers/gles2/rasterizer_gles2.h" +//TODO - reimplement OpenGLES +#endif + +#if defined(VULKAN_ENABLED) +#include "servers/visual/rasterizer_rd/rasterizer_rd.h" + +#include <QuartzCore/CAMetalLayer.h> +#endif + +#define DS_OSX ((DisplayServerOSX *)(DisplayServerOSX::get_singleton())) + +static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) { + r_state->set_shift((p_osx_state & NSEventModifierFlagShift)); + r_state->set_control((p_osx_state & NSEventModifierFlagControl)); + r_state->set_alt((p_osx_state & NSEventModifierFlagOption)); + r_state->set_metakey((p_osx_state & NSEventModifierFlagCommand)); +} + +static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow, CGFloat p_backingScaleFactor) { + const NSRect contentRect = [p_wd.window_view frame]; + const NSPoint p = p_locationInWindow; + p_wd.mouse_pos.x = p.x * p_backingScaleFactor; + p_wd.mouse_pos.y = (contentRect.size.height - p.y) * p_backingScaleFactor; + DS_OSX->last_mouse_pos = p_wd.mouse_pos; + InputFilter::get_singleton()->set_mouse_position(p_wd.mouse_pos); + return p_wd.mouse_pos; +} + +static void _push_to_key_event_buffer(const DisplayServerOSX::KeyEvent &p_event) { + Vector<DisplayServerOSX::KeyEvent> &buffer = DS_OSX->key_event_buffer; + if (DS_OSX->key_event_pos >= buffer.size()) { + buffer.resize(1 + DS_OSX->key_event_pos); + } + buffer.write[DS_OSX->key_event_pos++] = p_event; +} + +static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { + if ([NSCursor respondsToSelector:selector]) { + id object = [NSCursor performSelector:selector]; + if ([object isKindOfClass:[NSCursor class]]) { + return object; + } + } + if (fallback) { + // Fallback should be a reasonable default, no need to check. + return [NSCursor performSelector:fallback]; + } + return [NSCursor arrowCursor]; +} + +/*************************************************************************/ +/* GodotApplication */ +/*************************************************************************/ + +@interface GodotApplication : NSApplication +@end + +@implementation GodotApplication + +- (void)sendEvent:(NSEvent *)event { + // special case handling of command-period, which is traditionally a special + // shortcut in macOS and doesn't arrive at our regular keyDown handler. + if ([event type] == NSEventTypeKeyDown) { + if (([event modifierFlags] & NSEventModifierFlagCommand) && [event keyCode] == 0x2f) { + Ref<InputEventKey> k; + k.instance(); + + _get_key_modifier_state([event modifierFlags], k); + k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID); + k->set_pressed(true); + k->set_keycode(KEY_PERIOD); + k->set_physical_keycode(KEY_PERIOD); + k->set_echo([event isARepeat]); + + InputFilter::get_singleton()->accumulate_input_event(k); + } + } + + // From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost + // This works around an AppKit bug, where key up events while holding + // down the command key don't get sent to the key window. + if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) + [[self keyWindow] sendEvent:event]; + else + [super sendEvent:event]; +} + +@end + +/*************************************************************************/ +/* GlobalMenuItem */ +/*************************************************************************/ + +@interface GlobalMenuItem : NSObject { +@public + Callable callback; + Variant meta; + bool checkable; +} +@end + +@implementation GlobalMenuItem +@end + +/*************************************************************************/ +/* GodotApplicationDelegate */ +/*************************************************************************/ + +@interface GodotApplicationDelegate : NSObject +- (void)forceUnbundledWindowActivationHackStep1; +- (void)forceUnbundledWindowActivationHackStep2; +- (void)forceUnbundledWindowActivationHackStep3; +@end + +@implementation GodotApplicationDelegate + +- (void)forceUnbundledWindowActivationHackStep1 { + // Step1: Switch focus to macOS Dock. + // Required to perform step 2, TransformProcessType will fail if app is already the in focus. + for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) { + [app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; + break; + } + [self performSelector:@selector(forceUnbundledWindowActivationHackStep2) withObject:nil afterDelay:0.02]; +} + +- (void)forceUnbundledWindowActivationHackStep2 { + // Step 2: Register app as foreground process. + ProcessSerialNumber psn = { 0, kCurrentProcess }; + (void)TransformProcessType(&psn, kProcessTransformToForegroundApplication); + [self performSelector:@selector(forceUnbundledWindowActivationHackStep3) withObject:nil afterDelay:0.02]; +} + +- (void)forceUnbundledWindowActivationHackStep3 { + // Step 3: Switch focus back to app window. + [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notice { + NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + if (nsappname == nil) { + // If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored). + [self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02]; + } +} + +- (void)globalMenuCallback:(id)sender { + if (![sender representedObject]) + return; + + GlobalMenuItem *value = [sender representedObject]; + + if (value) { + if (value->checkable) { + if ([sender state] == NSControlStateValueOff) { + [sender setState:NSControlStateValueOn]; + } else { + [sender setState:NSControlStateValueOff]; + } + } + + if (value->callback != Callable()) { + Variant tag = value->meta; + Variant *tagp = &tag; + Variant ret; + Callable::CallError ce; + value->callback.call((const Variant **)&tagp, 1, ret, ce); + } + } +} + +- (NSMenu *)applicationDockMenu:(NSApplication *)sender { + return DS_OSX->dock_menu; +} + +- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { + // Note: may be called called before main loop init! + char *utfs = strdup([filename UTF8String]); + ((OS_OSX *)(OS_OSX::get_singleton()))->open_with_filename.parse_utf8(utfs); + free(utfs); + +#ifdef TOOLS_ENABLED + // Open new instance + if (OS_OSX::get_singleton()->get_main_loop()) { + List<String> args; + args.push_back(((OS_OSX *)(OS_OSX::get_singleton()))->open_with_filename); + String exec = OS::get_singleton()->get_executable_path(); + + OS::ProcessID pid = 0; + OS::get_singleton()->execute(exec, args, false, &pid); + } +#endif + return YES; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { + DS_OSX->_send_window_event(DS_OSX->windows[DisplayServerOSX::MAIN_WINDOW_ID], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + return NSTerminateCancel; +} + +- (void)showAbout:(id)sender { + if (OS_OSX::get_singleton()->get_main_loop()) + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT); +} + +@end + +/*************************************************************************/ +/* GodotWindowDelegate */ +/*************************************************************************/ + +@interface GodotWindowDelegate : NSObject { + DisplayServerOSX::WindowID window_id; +} + +- (void)windowWillClose:(NSNotification *)notification; +- (void)setWindowID:(DisplayServerOSX::WindowID)wid; + +@end + +@implementation GodotWindowDelegate + +- (void)setWindowID:(DisplayServerOSX::WindowID)wid { + window_id = wid; +} + +- (BOOL)windowShouldClose:(id)sender { + ERR_FAIL_COND_V(!DS_OSX->windows.has(window_id), YES); + DS_OSX->_send_window_event(DS_OSX->windows[window_id], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST); + return NO; +} + +- (void)windowWillClose:(NSNotification *)notification { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + while (wd.transient_children.size()) { + DS_OSX->window_set_transient(wd.transient_children.front()->get(), DisplayServerOSX::INVALID_WINDOW_ID); + } + + if (wd.transient_parent != DisplayServerOSX::INVALID_WINDOW_ID) { + DS_OSX->window_set_transient(window_id, DisplayServerOSX::INVALID_WINDOW_ID); + } + +#ifdef VULKAN_ENABLED + if (DS_OSX->rendering_driver == "vulkan") { + DS_OSX->context_vulkan->window_destroy(window_id); + } +#endif + DS_OSX->windows.erase(window_id); +} + +- (void)windowDidEnterFullScreen:(NSNotification *)notification { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + wd.fullscreen = true; + + [wd.window_object setContentMinSize:NSMakeSize(0, 0)]; + [wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; +} + +- (void)windowDidExitFullScreen:(NSNotification *)notification { + if (!DS_OSX || !DS_OSX->windows.has(window_id)) + return; + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + wd.fullscreen = false; + + if (wd.min_size != Size2i()) { + Size2i size = wd.min_size / DS_OSX->_display_scale([wd.window_object screen]); + [wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)]; + } + if (wd.max_size != Size2i()) { + Size2i size = wd.max_size / DS_OSX->_display_scale([wd.window_object screen]); + [wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; + } + + if (wd.resize_disabled) + [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable]; +} + +- (void)windowDidChangeBackingProperties:(NSNotification *)notification { + if (!DisplayServerOSX::get_singleton()) + return; + + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + CGFloat newBackingScaleFactor = [wd.window_object backingScaleFactor]; + CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; + +#if defined(OPENGL_ENABLED) + if (DS_OSX->rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + if (OS_OSX::get_singleton()->is_hidpi_allowed()) { + [wd.window_view setWantsBestResolutionOpenGLSurface:YES]; + } else { + [wd.window_view setWantsBestResolutionOpenGLSurface:NO]; + } + } +#endif + + if (newBackingScaleFactor != oldBackingScaleFactor) { + //Set new display scale and window size + float newDisplayScale = OS_OSX::get_singleton()->is_hidpi_allowed() ? newBackingScaleFactor : 1.0; + + const NSRect contentRect = [wd.window_view frame]; + + wd.size.width = contentRect.size.width * newDisplayScale; + wd.size.height = contentRect.size.height * newDisplayScale; + + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_DPI_CHANGE); + +#if defined(VULKAN_ENABLED) + if (DS_OSX->rendering_driver == "vulkan") { + CALayer *layer = [wd.window_view layer]; + layer.contentsScale = DS_OSX->_display_scale([wd.window_object screen]); + } +#endif + //Force window resize event + [self windowDidResize:notification]; + } +} + +- (void)windowDidResize:(NSNotification *)notification { + if (!DS_OSX || !DS_OSX->windows.has(window_id)) + return; + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + +#if defined(OPENGL_ENABLED) + if (DS_OSX->rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + wd.context_gles2->update(); + } +#endif + const NSRect contentRect = [wd.window_view frame]; + + float displayScale = DS_OSX->_display_scale([wd.window_object screen]); + wd.size.width = contentRect.size.width * displayScale; + wd.size.height = contentRect.size.height * displayScale; + +#if defined(VULKAN_ENABLED) + if (DS_OSX->rendering_driver == "vulkan") { + CALayer *layer = [wd.window_view layer]; + layer.contentsScale = displayScale; + DS_OSX->context_vulkan->window_resize(window_id, wd.size.width, wd.size.height); + } +#endif + + if (!wd.rect_changed_callback.is_null()) { + Variant size = Rect2i(DS_OSX->window_get_position(window_id), DS_OSX->window_get_size(window_id)); + Variant *sizep = &size; + Variant ret; + Callable::CallError ce; + wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); + } + + if (OS_OSX::get_singleton()->get_main_loop()) { + Main::force_redraw(); + //Event retrieval blocks until resize is over. Call Main::iteration() directly. + if (!Main::is_iterating()) { //avoid cyclic loop + Main::iteration(); + } + } +} + +- (void)windowDidMove:(NSNotification *)notification { + if (InputFilter::get_singleton()) { + InputFilter::get_singleton()->release_pressed_events(); + } +} + +- (void)windowDidBecomeKey:(NSNotification *)notification { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [wd.window_view backingScaleFactor] : 1.0; + _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream], backingScaleFactor); + InputFilter::get_singleton()->set_mouse_position(wd.mouse_pos); + + DS_OSX->window_focused = true; + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); +} + +- (void)windowDidResignKey:(NSNotification *)notification { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + DS_OSX->window_focused = false; + + InputFilter::get_singleton()->release_pressed_events(); + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_OUT); +} + +- (void)windowDidMiniaturize:(NSNotification *)notification { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + DS_OSX->window_focused = false; + + InputFilter::get_singleton()->release_pressed_events(); + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_OUT); +} + +- (void)windowDidDeminiaturize:(NSNotification *)notification { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + DS_OSX->window_focused = true; + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); +} + +@end + +/*************************************************************************/ +/* GodotContentView */ +/*************************************************************************/ + +@interface GodotContentView : NSView <NSTextInputClient> { + DisplayServerOSX::WindowID window_id; + NSTrackingArea *trackingArea; + NSMutableAttributedString *markedText; + bool imeInputEventInProgress; +} + +- (void)cancelComposition; +- (CALayer *)makeBackingLayer; +- (BOOL)wantsUpdateLayer; +- (void)updateLayer; +- (void)setWindowID:(DisplayServerOSX::WindowID)wid; + +@end + +@implementation GodotContentView + +- (void)setWindowID:(DisplayServerOSX::WindowID)wid { + window_id = wid; +} + ++ (void)initialize { + if (self == [GodotContentView class]) { + // nothing left to do here at the moment.. + } +} + +- (CALayer *)makeBackingLayer { +#if defined(VULKAN_ENABLED) + if (DS_OSX->rendering_driver == "vulkan") { + CALayer *layer = [[CAMetalLayer class] layer]; + return layer; + } +#endif + return [super makeBackingLayer]; +} + +- (void)updateLayer { +#if defined(VULKAN_ENABLED) + if (DS_OSX->rendering_driver == "vulkan") { + [super updateLayer]; + } +#endif +#if defined(OPENGL_ENABLED) + if (DS_OSX->rendering_driver == "opengl_es") { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + wd.context_gles2->update(); + //TODO - reimplement OpenGLES + } +#endif +} + +- (BOOL)wantsUpdateLayer { + return YES; +} + +- (id)init { + self = [super init]; + trackingArea = nil; + imeInputEventInProgress = false; + [self updateTrackingAreas]; + [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; + markedText = [[NSMutableAttributedString alloc] init]; + return self; +} + +- (void)dealloc { + [trackingArea release]; + [markedText release]; + [super dealloc]; +} + +static const NSRange kEmptyRange = { NSNotFound, 0 }; + +- (BOOL)hasMarkedText { + return (markedText.length > 0); +} + +- (NSRange)markedRange { + return NSMakeRange(0, markedText.length); +} + +- (NSRange)selectedRange { + return kEmptyRange; +} + +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { + if ([aString isKindOfClass:[NSAttributedString class]]) { + [markedText initWithAttributedString:aString]; + } else { + [markedText initWithString:aString]; + } + if (markedText.length == 0) { + [self unmarkText]; + return; + } + + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (wd.im_active) { + imeInputEventInProgress = true; + DS_OSX->im_text.parse_utf8([[markedText mutableString] UTF8String]); + DS_OSX->im_selection = Point2i(selectedRange.location, selectedRange.length); + + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); + } +} + +- (void)doCommandBySelector:(SEL)aSelector { + if ([self respondsToSelector:aSelector]) + [self performSelector:aSelector]; +} + +- (void)unmarkText { + imeInputEventInProgress = false; + [[markedText mutableString] setString:@""]; + + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (wd.im_active) { + DS_OSX->im_text = String(); + DS_OSX->im_selection = Point2i(); + + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); + } +} + +- (NSArray *)validAttributesForMarkedText { + return [NSArray array]; +} + +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { + return nil; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { + return 0; +} + +- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { + ERR_FAIL_COND_V(!DS_OSX->windows.has(window_id), NSMakeRect(0, 0, 0, 0)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + const NSRect contentRect = [wd.window_view frame]; + float displayScale = DS_OSX->_display_scale([wd.window_object screen]); + NSRect pointInWindowRect = NSMakeRect(wd.im_position.x / displayScale, contentRect.size.height - (wd.im_position.y / displayScale) - 1, 0, 0); + NSPoint pointOnScreen = [wd.window_object convertRectToScreen:pointInWindowRect].origin; + + return NSMakeRect(pointOnScreen.x, pointOnScreen.y, 0, 0); +} + +- (void)cancelComposition { + [self unmarkText]; + NSTextInputContext *currentInputContext = [NSTextInputContext currentInputContext]; + [currentInputContext discardMarkedText]; +} + +- (void)insertText:(id)aString { + [self insertText:aString replacementRange:NSMakeRange(0, 0)]; +} + +- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { + NSEvent *event = [NSApp currentEvent]; + + NSString *characters; + if ([aString isKindOfClass:[NSAttributedString class]]) { + characters = [aString string]; + } else { + characters = (NSString *)aString; + } + + NSUInteger i, length = [characters length]; + + NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet]; + NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet]; + if ([characters rangeOfCharacterFromSet:ctrlChars].length && [characters rangeOfCharacterFromSet:wsnlChars].length == 0) { + NSTextInputContext *currentInputContext = [NSTextInputContext currentInputContext]; + [currentInputContext discardMarkedText]; + [self cancelComposition]; + return; + } + + for (i = 0; i < length; i++) { + const unichar codepoint = [characters characterAtIndex:i]; + if ((codepoint & 0xFF00) == 0xF700) + continue; + + DisplayServerOSX::KeyEvent ke; + + ke.window_id = window_id; + ke.osx_state = [event modifierFlags]; + ke.pressed = true; + ke.echo = false; + ke.raw = false; // IME input event + ke.keycode = 0; + ke.physical_keycode = 0; + ke.unicode = codepoint; + + _push_to_key_event_buffer(ke); + } + [self cancelComposition]; +} + +- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender { + return NSDragOperationCopy; +} + +- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender { + return NSDragOperationCopy; +} + +- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender { + ERR_FAIL_COND_V(!DS_OSX->windows.has(window_id), NO); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + NSPasteboard *pboard = [sender draggingPasteboard]; + NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; + + Vector<String> files; + for (NSUInteger i = 0; i < filenames.count; i++) { + NSString *ns = [filenames objectAtIndex:i]; + char *utfs = strdup([ns UTF8String]); + String ret; + ret.parse_utf8(utfs); + free(utfs); + files.push_back(ret); + } + + if (!wd.drop_files_callback.is_null()) { + Variant v = files; + Variant *vp = &v; + Variant ret; + Callable::CallError ce; + wd.drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + } + + return NO; +} + +- (BOOL)isOpaque { + return YES; +} + +- (BOOL)canBecomeKeyView { + return YES; +} + +- (BOOL)acceptsFirstResponder { + return YES; +} + +- (void)cursorUpdate:(NSEvent *)event { + DisplayServer::CursorShape p_shape = DS_OSX->cursor_shape; + DS_OSX->cursor_shape = DisplayServer::CURSOR_MAX; + DS_OSX->cursor_set_shape(p_shape); +} + +static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, int index, int mask, bool pressed) { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (pressed) { + DS_OSX->last_button_state |= mask; + } else { + DS_OSX->last_button_state &= ~mask; + } + + Ref<InputEventMouseButton> mb; + mb.instance(); + mb->set_window_id(window_id); + const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0; + const Vector2 pos = _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor); + _get_key_modifier_state([event modifierFlags], mb); + mb->set_button_index(index); + mb->set_pressed(pressed); + mb->set_position(pos); + mb->set_global_position(pos); + mb->set_button_mask(DS_OSX->last_button_state); + if (index == BUTTON_LEFT && pressed) { + mb->set_doubleclick([event clickCount] == 2); + } + + InputFilter::get_singleton()->accumulate_input_event(mb); +} + +- (void)mouseDown:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (([event modifierFlags] & NSEventModifierFlagControl)) { + wd.mouse_down_control = true; + _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true); + } else { + wd.mouse_down_control = false; + _mouseDownEvent(window_id, event, BUTTON_LEFT, BUTTON_MASK_LEFT, true); + } +} + +- (void)mouseDragged:(NSEvent *)event { + [self mouseMoved:event]; +} + +- (void)mouseUp:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (wd.mouse_down_control) { + _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false); + } else { + _mouseDownEvent(window_id, event, BUTTON_LEFT, BUTTON_MASK_LEFT, false); + } +} + +- (void)mouseMoved:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + Ref<InputEventMouseMotion> mm; + mm.instance(); + + mm->set_window_id(window_id); + mm->set_button_mask(DS_OSX->last_button_state); + const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0; + const Vector2i pos = _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor); + mm->set_position(pos); + mm->set_pressure([event pressure]); + if ([event subtype] == NSEventSubtypeTabletPoint) { + const NSPoint p = [event tilt]; + mm->set_tilt(Vector2(p.x, p.y)); + } + mm->set_global_position(pos); + mm->set_speed(InputFilter::get_singleton()->get_last_mouse_speed()); + Vector2i relativeMotion = Vector2i(); + relativeMotion.x = [event deltaX] * backingScaleFactor; + relativeMotion.y = [event deltaY] * backingScaleFactor; + mm->set_relative(relativeMotion); + _get_key_modifier_state([event modifierFlags], mm); + + InputFilter::get_singleton()->set_mouse_position(wd.mouse_pos); + InputFilter::get_singleton()->accumulate_input_event(mm); +} + +- (void)rightMouseDown:(NSEvent *)event { + _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true); +} + +- (void)rightMouseDragged:(NSEvent *)event { + [self mouseMoved:event]; +} + +- (void)rightMouseUp:(NSEvent *)event { + _mouseDownEvent(window_id, event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false); +} + +- (void)otherMouseDown:(NSEvent *)event { + if ((int)[event buttonNumber] == 2) { + _mouseDownEvent(window_id, event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, true); + } else if ((int)[event buttonNumber] == 3) { + _mouseDownEvent(window_id, event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, true); + } else if ((int)[event buttonNumber] == 4) { + _mouseDownEvent(window_id, event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, true); + } else { + return; + } +} + +- (void)otherMouseDragged:(NSEvent *)event { + [self mouseMoved:event]; +} + +- (void)otherMouseUp:(NSEvent *)event { + if ((int)[event buttonNumber] == 2) { + _mouseDownEvent(window_id, event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, false); + } else if ((int)[event buttonNumber] == 3) { + _mouseDownEvent(window_id, event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, false); + } else if ((int)[event buttonNumber] == 4) { + _mouseDownEvent(window_id, event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, false); + } else { + return; + } +} + +- (void)mouseExited:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED) + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_EXIT); +} + +- (void)mouseEntered:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED) + DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_ENTER); + + DisplayServer::CursorShape p_shape = DS_OSX->cursor_shape; + DS_OSX->cursor_shape = DisplayServer::CURSOR_MAX; + DS_OSX->cursor_set_shape(p_shape); +} + +- (void)magnifyWithEvent:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + Ref<InputEventMagnifyGesture> ev; + ev.instance(); + ev->set_window_id(window_id); + _get_key_modifier_state([event modifierFlags], ev); + const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0; + ev->set_position(_get_mouse_pos(wd, [event locationInWindow], backingScaleFactor)); + ev->set_factor([event magnification] + 1.0); + + InputFilter::get_singleton()->accumulate_input_event(ev); +} + +- (void)viewDidChangeBackingProperties { + // nothing left to do here +} + +- (void)updateTrackingAreas { + if (trackingArea != nil) { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + NSTrackingAreaOptions options = + NSTrackingMouseEnteredAndExited | + NSTrackingActiveInKeyWindow | + NSTrackingCursorUpdate | + NSTrackingInVisibleRect; + + trackingArea = [[NSTrackingArea alloc] + initWithRect:[self bounds] + options:options + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; + [super updateTrackingAreas]; +} + +static bool isNumpadKey(unsigned int key) { + + static const unsigned int table[] = { + 0x41, /* kVK_ANSI_KeypadDecimal */ + 0x43, /* kVK_ANSI_KeypadMultiply */ + 0x45, /* kVK_ANSI_KeypadPlus */ + 0x47, /* kVK_ANSI_KeypadClear */ + 0x4b, /* kVK_ANSI_KeypadDivide */ + 0x4c, /* kVK_ANSI_KeypadEnter */ + 0x4e, /* kVK_ANSI_KeypadMinus */ + 0x51, /* kVK_ANSI_KeypadEquals */ + 0x52, /* kVK_ANSI_Keypad0 */ + 0x53, /* kVK_ANSI_Keypad1 */ + 0x54, /* kVK_ANSI_Keypad2 */ + 0x55, /* kVK_ANSI_Keypad3 */ + 0x56, /* kVK_ANSI_Keypad4 */ + 0x57, /* kVK_ANSI_Keypad5 */ + 0x58, /* kVK_ANSI_Keypad6 */ + 0x59, /* kVK_ANSI_Keypad7 */ + 0x5b, /* kVK_ANSI_Keypad8 */ + 0x5c, /* kVK_ANSI_Keypad9 */ + 0x5f, /* kVK_JIS_KeypadComma */ + 0x00 + }; + for (int i = 0; table[i] != 0; i++) { + if (key == table[i]) + return true; + } + return false; +} + +// Translates a OS X keycode to a Godot keycode +// +static int translateKey(unsigned int key) { + + // Keyboard symbol translation table + static const unsigned int table[128] = { + /* 00 */ KEY_A, + /* 01 */ KEY_S, + /* 02 */ KEY_D, + /* 03 */ KEY_F, + /* 04 */ KEY_H, + /* 05 */ KEY_G, + /* 06 */ KEY_Z, + /* 07 */ KEY_X, + /* 08 */ KEY_C, + /* 09 */ KEY_V, + /* 0a */ KEY_SECTION, /* ISO Section */ + /* 0b */ KEY_B, + /* 0c */ KEY_Q, + /* 0d */ KEY_W, + /* 0e */ KEY_E, + /* 0f */ KEY_R, + /* 10 */ KEY_Y, + /* 11 */ KEY_T, + /* 12 */ KEY_1, + /* 13 */ KEY_2, + /* 14 */ KEY_3, + /* 15 */ KEY_4, + /* 16 */ KEY_6, + /* 17 */ KEY_5, + /* 18 */ KEY_EQUAL, + /* 19 */ KEY_9, + /* 1a */ KEY_7, + /* 1b */ KEY_MINUS, + /* 1c */ KEY_8, + /* 1d */ KEY_0, + /* 1e */ KEY_BRACERIGHT, + /* 1f */ KEY_O, + /* 20 */ KEY_U, + /* 21 */ KEY_BRACELEFT, + /* 22 */ KEY_I, + /* 23 */ KEY_P, + /* 24 */ KEY_ENTER, + /* 25 */ KEY_L, + /* 26 */ KEY_J, + /* 27 */ KEY_APOSTROPHE, + /* 28 */ KEY_K, + /* 29 */ KEY_SEMICOLON, + /* 2a */ KEY_BACKSLASH, + /* 2b */ KEY_COMMA, + /* 2c */ KEY_SLASH, + /* 2d */ KEY_N, + /* 2e */ KEY_M, + /* 2f */ KEY_PERIOD, + /* 30 */ KEY_TAB, + /* 31 */ KEY_SPACE, + /* 32 */ KEY_QUOTELEFT, + /* 33 */ KEY_BACKSPACE, + /* 34 */ KEY_UNKNOWN, + /* 35 */ KEY_ESCAPE, + /* 36 */ KEY_META, + /* 37 */ KEY_META, + /* 38 */ KEY_SHIFT, + /* 39 */ KEY_CAPSLOCK, + /* 3a */ KEY_ALT, + /* 3b */ KEY_CONTROL, + /* 3c */ KEY_SHIFT, + /* 3d */ KEY_ALT, + /* 3e */ KEY_CONTROL, + /* 3f */ KEY_UNKNOWN, /* Function */ + /* 40 */ KEY_UNKNOWN, /* F17 */ + /* 41 */ KEY_KP_PERIOD, + /* 42 */ KEY_UNKNOWN, + /* 43 */ KEY_KP_MULTIPLY, + /* 44 */ KEY_UNKNOWN, + /* 45 */ KEY_KP_ADD, + /* 46 */ KEY_UNKNOWN, + /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */ + /* 48 */ KEY_VOLUMEUP, /* VolumeUp */ + /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */ + /* 4a */ KEY_VOLUMEMUTE, /* Mute */ + /* 4b */ KEY_KP_DIVIDE, + /* 4c */ KEY_KP_ENTER, + /* 4d */ KEY_UNKNOWN, + /* 4e */ KEY_KP_SUBTRACT, + /* 4f */ KEY_UNKNOWN, /* F18 */ + /* 50 */ KEY_UNKNOWN, /* F19 */ + /* 51 */ KEY_EQUAL, /* KeypadEqual */ + /* 52 */ KEY_KP_0, + /* 53 */ KEY_KP_1, + /* 54 */ KEY_KP_2, + /* 55 */ KEY_KP_3, + /* 56 */ KEY_KP_4, + /* 57 */ KEY_KP_5, + /* 58 */ KEY_KP_6, + /* 59 */ KEY_KP_7, + /* 5a */ KEY_UNKNOWN, /* F20 */ + /* 5b */ KEY_KP_8, + /* 5c */ KEY_KP_9, + /* 5d */ KEY_YEN, /* JIS Yen */ + /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */ + /* 5f */ KEY_COMMA, /* JIS KeypadComma */ + /* 60 */ KEY_F5, + /* 61 */ KEY_F6, + /* 62 */ KEY_F7, + /* 63 */ KEY_F3, + /* 64 */ KEY_F8, + /* 65 */ KEY_F9, + /* 66 */ KEY_UNKNOWN, /* JIS Eisu */ + /* 67 */ KEY_F11, + /* 68 */ KEY_UNKNOWN, /* JIS Kana */ + /* 69 */ KEY_F13, + /* 6a */ KEY_F16, + /* 6b */ KEY_F14, + /* 6c */ KEY_UNKNOWN, + /* 6d */ KEY_F10, + /* 6e */ KEY_MENU, + /* 6f */ KEY_F12, + /* 70 */ KEY_UNKNOWN, + /* 71 */ KEY_F15, + /* 72 */ KEY_INSERT, /* Really Help... */ + /* 73 */ KEY_HOME, + /* 74 */ KEY_PAGEUP, + /* 75 */ KEY_DELETE, + /* 76 */ KEY_F4, + /* 77 */ KEY_END, + /* 78 */ KEY_F2, + /* 79 */ KEY_PAGEDOWN, + /* 7a */ KEY_F1, + /* 7b */ KEY_LEFT, + /* 7c */ KEY_RIGHT, + /* 7d */ KEY_DOWN, + /* 7e */ KEY_UP, + /* 7f */ KEY_UNKNOWN, + }; + + if (key >= 128) + return KEY_UNKNOWN; + + return table[key]; +} + +struct _KeyCodeMap { + UniChar kchar; + int kcode; +}; + +static const _KeyCodeMap _keycodes[55] = { + { '`', KEY_QUOTELEFT }, + { '~', KEY_ASCIITILDE }, + { '0', KEY_0 }, + { '1', KEY_1 }, + { '2', KEY_2 }, + { '3', KEY_3 }, + { '4', KEY_4 }, + { '5', KEY_5 }, + { '6', KEY_6 }, + { '7', KEY_7 }, + { '8', KEY_8 }, + { '9', KEY_9 }, + { '-', KEY_MINUS }, + { '_', KEY_UNDERSCORE }, + { '=', KEY_EQUAL }, + { '+', KEY_PLUS }, + { 'q', KEY_Q }, + { 'w', KEY_W }, + { 'e', KEY_E }, + { 'r', KEY_R }, + { 't', KEY_T }, + { 'y', KEY_Y }, + { 'u', KEY_U }, + { 'i', KEY_I }, + { 'o', KEY_O }, + { 'p', KEY_P }, + { '[', KEY_BRACELEFT }, + { ']', KEY_BRACERIGHT }, + { '{', KEY_BRACELEFT }, + { '}', KEY_BRACERIGHT }, + { 'a', KEY_A }, + { 's', KEY_S }, + { 'd', KEY_D }, + { 'f', KEY_F }, + { 'g', KEY_G }, + { 'h', KEY_H }, + { 'j', KEY_J }, + { 'k', KEY_K }, + { 'l', KEY_L }, + { ';', KEY_SEMICOLON }, + { ':', KEY_COLON }, + { '\'', KEY_APOSTROPHE }, + { '\"', KEY_QUOTEDBL }, + { '\\', KEY_BACKSLASH }, + { '#', KEY_NUMBERSIGN }, + { 'z', KEY_Z }, + { 'x', KEY_X }, + { 'c', KEY_C }, + { 'v', KEY_V }, + { 'b', KEY_B }, + { 'n', KEY_N }, + { 'm', KEY_M }, + { ',', KEY_COMMA }, + { '.', KEY_PERIOD }, + { '/', KEY_SLASH } +}; + +static int remapKey(unsigned int key, unsigned int state) { + if (isNumpadKey(key)) + return translateKey(key); + + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + if (!currentKeyboard) + return translateKey(key); + + CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + if (!layoutData) + return translateKey(key); + + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); + + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; + + OSStatus err = UCKeyTranslate(keyboardLayout, + key, + kUCKeyActionDisplay, + (state >> 8) & 0xFF, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &keysDown, + sizeof(chars) / sizeof(chars[0]), + &realLength, + chars); + + if (err != noErr) { + return translateKey(key); + } + + for (unsigned int i = 0; i < 55; i++) { + if (_keycodes[i].kchar == chars[0]) { + return _keycodes[i].kcode; + } + } + return translateKey(key); +} + +- (void)keyDown:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + // Ignore all input if IME input is in progress + if (!imeInputEventInProgress) { + NSString *characters = [event characters]; + NSUInteger length = [characters length]; + + if (!wd.im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) { + // Fallback unicode character handler used if IME is not active + for (NSUInteger i = 0; i < length; i++) { + DisplayServerOSX::KeyEvent ke; + + ke.window_id = window_id; + ke.osx_state = [event modifierFlags]; + ke.pressed = true; + ke.echo = [event isARepeat]; + ke.keycode = remapKey([event keyCode], [event modifierFlags]); + ke.physical_keycode = translateKey([event keyCode]); + ke.raw = true; + ke.unicode = [characters characterAtIndex:i]; + + _push_to_key_event_buffer(ke); + } + } else { + DisplayServerOSX::KeyEvent ke; + + ke.window_id = window_id; + ke.osx_state = [event modifierFlags]; + ke.pressed = true; + ke.echo = [event isARepeat]; + ke.keycode = remapKey([event keyCode], [event modifierFlags]); + ke.physical_keycode = translateKey([event keyCode]); + ke.raw = false; + ke.unicode = 0; + + _push_to_key_event_buffer(ke); + } + } + + // Pass events to IME handler + if (wd.im_active) + [self interpretKeyEvents:[NSArray arrayWithObject:event]]; +} + +- (void)flagsChanged:(NSEvent *)event { + // Ignore all input if IME input is in progress + if (!imeInputEventInProgress) { + DisplayServerOSX::KeyEvent ke; + + ke.window_id = window_id; + ke.echo = false; + ke.raw = true; + + int key = [event keyCode]; + int mod = [event modifierFlags]; + + if (key == 0x36 || key == 0x37) { + if (mod & NSEventModifierFlagCommand) { + mod &= ~NSEventModifierFlagCommand; + ke.pressed = true; + } else { + ke.pressed = false; + } + } else if (key == 0x38 || key == 0x3c) { + if (mod & NSEventModifierFlagShift) { + mod &= ~NSEventModifierFlagShift; + ke.pressed = true; + } else { + ke.pressed = false; + } + } else if (key == 0x3a || key == 0x3d) { + if (mod & NSEventModifierFlagOption) { + mod &= ~NSEventModifierFlagOption; + ke.pressed = true; + } else { + ke.pressed = false; + } + } else if (key == 0x3b || key == 0x3e) { + if (mod & NSEventModifierFlagControl) { + mod &= ~NSEventModifierFlagControl; + ke.pressed = true; + } else { + ke.pressed = false; + } + } else { + return; + } + + ke.osx_state = mod; + ke.keycode = remapKey(key, mod); + ke.physical_keycode = translateKey(key); + ke.unicode = 0; + + _push_to_key_event_buffer(ke); + } +} + +- (void)keyUp:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + // Ignore all input if IME input is in progress + if (!imeInputEventInProgress) { + NSString *characters = [event characters]; + NSUInteger length = [characters length]; + + // Fallback unicode character handler used if IME is not active + if (!wd.im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) { + for (NSUInteger i = 0; i < length; i++) { + DisplayServerOSX::KeyEvent ke; + + ke.window_id = window_id; + ke.osx_state = [event modifierFlags]; + ke.pressed = false; + ke.echo = [event isARepeat]; + ke.keycode = remapKey([event keyCode], [event modifierFlags]); + ke.physical_keycode = translateKey([event keyCode]); + ke.raw = true; + ke.unicode = [characters characterAtIndex:i]; + + _push_to_key_event_buffer(ke); + } + } else { + DisplayServerOSX::KeyEvent ke; + + ke.window_id = window_id; + ke.osx_state = [event modifierFlags]; + ke.pressed = false; + ke.echo = [event isARepeat]; + ke.keycode = remapKey([event keyCode], [event modifierFlags]); + ke.physical_keycode = translateKey([event keyCode]); + ke.raw = true; + ke.unicode = 0; + + _push_to_key_event_buffer(ke); + } + } +} + +inline void sendScrollEvent(DisplayServer::WindowID window_id, int button, double factor, int modifierFlags) { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + unsigned int mask = 1 << (button - 1); + + Ref<InputEventMouseButton> sc; + sc.instance(); + + sc->set_window_id(window_id); + _get_key_modifier_state(modifierFlags, sc); + sc->set_button_index(button); + sc->set_factor(factor); + sc->set_pressed(true); + sc->set_position(wd.mouse_pos); + sc->set_global_position(wd.mouse_pos); + DS_OSX->last_button_state |= mask; + sc->set_button_mask(DS_OSX->last_button_state); + + InputFilter::get_singleton()->accumulate_input_event(sc); + + sc.instance(); + sc->set_window_id(window_id); + sc->set_button_index(button); + sc->set_factor(factor); + sc->set_pressed(false); + sc->set_position(wd.mouse_pos); + sc->set_global_position(wd.mouse_pos); + DS_OSX->last_button_state &= ~mask; + sc->set_button_mask(DS_OSX->last_button_state); + + InputFilter::get_singleton()->accumulate_input_event(sc); +} + +inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy, int modifierFlags) { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + Ref<InputEventPanGesture> pg; + pg.instance(); + + pg->set_window_id(window_id); + _get_key_modifier_state(modifierFlags, pg); + pg->set_position(wd.mouse_pos); + pg->set_delta(Vector2(-dx, -dy)); + + InputFilter::get_singleton()->accumulate_input_event(pg); +} + +- (void)scrollWheel:(NSEvent *)event { + ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); + DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + + double deltaX, deltaY; + + const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0; + _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor); + + deltaX = [event scrollingDeltaX]; + deltaY = [event scrollingDeltaY]; + + if ([event hasPreciseScrollingDeltas]) { + deltaX *= 0.03; + deltaY *= 0.03; + } + + if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) { + sendPanEvent(window_id, deltaX, deltaY, [event modifierFlags]); + } else { + if (fabs(deltaX)) { + sendScrollEvent(window_id, 0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]); + } + if (fabs(deltaY)) { + sendScrollEvent(window_id, 0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]); + } + } +} + +@end + +/*************************************************************************/ +/* GodotWindow */ +/*************************************************************************/ + +@interface GodotWindow : NSWindow { +} +@end + +@implementation GodotWindow + +- (BOOL)canBecomeKeyWindow { + // Required for NSBorderlessWindowMask windows + return YES; +} + +@end + +/*************************************************************************/ +/* DisplayServerOSX */ +/*************************************************************************/ + +bool DisplayServerOSX::has_feature(Feature p_feature) const { + switch (p_feature) { + case FEATURE_GLOBAL_MENU: + case FEATURE_SUBWINDOWS: + //case FEATURE_TOUCHSCREEN: + case FEATURE_MOUSE: + case FEATURE_MOUSE_WARP: + case FEATURE_CLIPBOARD: + case FEATURE_CURSOR_SHAPE: + case FEATURE_CUSTOM_CURSOR_SHAPE: + case FEATURE_NATIVE_DIALOG: + //case FEATURE_CONSOLE_WINDOW: + case FEATURE_IME: + case FEATURE_WINDOW_TRANSPARENCY: + case FEATURE_HIDPI: + case FEATURE_ICON: + case FEATURE_NATIVE_ICON: + case FEATURE_SWAP_BUFFERS: + return true; + default: { + } + } + return false; +} + +String DisplayServerOSX::get_name() const { + return "OSX"; +} + +const NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) const { + const NSMenu *menu = NULL; + if (p_menu_root == "") { + // Main menu.x + menu = [NSApp mainMenu]; + } else if (p_menu_root.to_lower() == "_dock") { + // macOS dock menu. + menu = dock_menu; + } else { + // Submenu. + if (submenu.has(p_menu_root)) { + menu = submenu[p_menu_root]; + } + } + if (menu == apple_menu) { + // Do not allow to change Apple menu. + return NULL; + } + return menu; +} + +NSMenu *DisplayServerOSX::_get_menu_root(const String &p_menu_root) { + NSMenu *menu = NULL; + if (p_menu_root == "") { + // Main menu. + menu = [NSApp mainMenu]; + } else if (p_menu_root.to_lower() == "_dock") { + // macOS dock menu. + menu = dock_menu; + } else { + // Submenu. + if (!submenu.has(p_menu_root)) { + NSMenu *n_menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:p_menu_root.utf8().get_data()]]; + submenu[p_menu_root] = n_menu; + } + menu = submenu[p_menu_root]; + } + if (menu == apple_menu) { + // Do not allow to change Apple menu. + return NULL; + } + return menu; +} + +void DisplayServerOSX::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:@""]; + GlobalMenuItem *obj = [[[GlobalMenuItem alloc] init] autorelease]; + obj->callback = p_callback; + obj->meta = p_tag; + obj->checkable = false; + [menu_item setRepresentedObject:obj]; + } +} + +void DisplayServerOSX::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:@""]; + GlobalMenuItem *obj = [[[GlobalMenuItem alloc] init] autorelease]; + obj->callback = p_callback; + obj->meta = p_tag; + obj->checkable = true; + [menu_item setRepresentedObject:obj]; + } +} + +void DisplayServerOSX::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + NSMenu *sub_menu = _get_menu_root(p_submenu); + if (menu && sub_menu) { + if (sub_menu == menu) { + ERR_PRINT("Can't set submenu to self!"); + return; + } + if ([sub_menu supermenu]) { + ERR_PRINT("Can't set submenu to menu that is already a submenu of some other menu!"); + return; + } + NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:p_label.utf8().get_data()] action:nil keyEquivalent:@""]; + [menu setSubmenu:sub_menu forItem:menu_item]; + } +} + +void DisplayServerOSX::global_menu_add_separator(const String &p_menu_root) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + [menu addItem:[NSMenuItem separatorItem]]; + } +} + +bool DisplayServerOSX::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + const NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + return ([menu_item state] == NSControlStateValueOn); + } + } + return false; +} + +bool DisplayServerOSX::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + const NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + GlobalMenuItem *obj = [menu_item representedObject]; + if (obj) { + return obj->checkable; + } + } + } + return false; +} + +Callable DisplayServerOSX::global_menu_get_item_callback(const String &p_menu_root, int p_idx) { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + const NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + GlobalMenuItem *obj = [menu_item representedObject]; + if (obj) { + return obj->callback; + } + } + } + return Callable(); +} + +Variant DisplayServerOSX::global_menu_get_item_tag(const String &p_menu_root, int p_idx) { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + const NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + GlobalMenuItem *obj = [menu_item representedObject]; + if (obj) { + return obj->meta; + } + } + } + return Variant(); +} + +String DisplayServerOSX::global_menu_get_item_text(const String &p_menu_root, int p_idx) { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + const NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + char *utfs = strdup([[menu_item title] UTF8String]); + String ret; + ret.parse_utf8(utfs); + free(utfs); + return ret; + } + } + return String(); +} + +String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + const NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + const NSMenu *sub_menu = [menu_item submenu]; + if (sub_menu) { + for (Map<String, NSMenu *>::Element *E = submenu.front(); E; E = E->next()) { + if (E->get() == sub_menu) return E->key(); + } + } + } + } + return String(); +} + +void DisplayServerOSX::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not edit Apple menu. + return; + } + NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + if (p_checked) { + [menu_item setState:NSControlStateValueOn]; + } else { + [menu_item setState:NSControlStateValueOff]; + } + } + } +} + +void DisplayServerOSX::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not edit Apple menu. + return; + } + NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + GlobalMenuItem *obj = [menu_item representedObject]; + obj->checkable = p_checkable; + } + } +} + +void DisplayServerOSX::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not edit Apple menu. + return; + } + NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + GlobalMenuItem *obj = [menu_item representedObject]; + obj->callback = p_callback; + } + } +} + +void DisplayServerOSX::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not edit Apple menu. + return; + } + NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + GlobalMenuItem *obj = [menu_item representedObject]; + obj->meta = p_tag; + } + } +} + +void DisplayServerOSX::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not edit Apple menu. + return; + } + NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + [menu_item setTitle:[NSString stringWithUTF8String:p_text.utf8().get_data()]]; + } + } +} + +void DisplayServerOSX::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + NSMenu *sub_menu = _get_menu_root(p_submenu); + if (menu && sub_menu) { + if (sub_menu == menu) { + ERR_PRINT("Can't set submenu to self!"); + return; + } + if ([sub_menu supermenu]) { + ERR_PRINT("Can't set submenu to menu that is already a submenu of some other menu!"); + return; + } + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not edit Apple menu. + return; + } + NSMenuItem *menu_item = [menu itemAtIndex:p_idx]; + if (menu_item) { + [menu setSubmenu:sub_menu forItem:menu_item]; + } + } +} + +int DisplayServerOSX::global_menu_get_item_count(const String &p_menu_root) const { + _THREAD_SAFE_METHOD_ + + const NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + return [menu numberOfItems]; + } else { + return 0; + } +} + +void DisplayServerOSX::global_menu_remove_item(const String &p_menu_root, int p_idx) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + if ((menu == [NSApp mainMenu]) && (p_idx == 0)) { // Do not delete Apple menu. + return; + } + [menu removeItemAtIndex:p_idx]; + } +} + +void DisplayServerOSX::global_menu_clear(const String &p_menu_root) { + _THREAD_SAFE_METHOD_ + + NSMenu *menu = _get_menu_root(p_menu_root); + if (menu) { + [menu removeAllItems]; + // Restore Apple menu. + if (menu == [NSApp mainMenu]) { + NSMenuItem *menu_item = [menu addItemWithTitle:@"" action:nil keyEquivalent:@""]; + [menu setSubmenu:apple_menu forItem:menu_item]; + } + } +} + +void DisplayServerOSX::alert(const String &p_alert, const String &p_title) { + _THREAD_SAFE_METHOD_ + + NSAlert *window = [[NSAlert alloc] init]; + NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; + NSString *ns_alert = [NSString stringWithUTF8String:p_alert.utf8().get_data()]; + + [window addButtonWithTitle:@"OK"]; + [window setMessageText:ns_title]; + [window setInformativeText:ns_alert]; + [window setAlertStyle:NSAlertStyleWarning]; + + [window runModal]; + [window release]; +} + +Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) { + _THREAD_SAFE_METHOD_ + + NSAlert *window = [[NSAlert alloc] init]; + NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; + NSString *ns_description = [NSString stringWithUTF8String:p_description.utf8().get_data()]; + + for (int i = 0; i < p_buttons.size(); i++) { + NSString *ns_button = [NSString stringWithUTF8String:p_buttons[i].utf8().get_data()]; + [window addButtonWithTitle:ns_button]; + } + [window setMessageText:ns_title]; + [window setInformativeText:ns_description]; + [window setAlertStyle:NSAlertStyleInformational]; + + int button_pressed; + NSInteger ret = [window runModal]; + if (ret == NSAlertFirstButtonReturn) { + button_pressed = 0; + } else if (ret == NSAlertSecondButtonReturn) { + button_pressed = 1; + } else if (ret == NSAlertThirdButtonReturn) { + button_pressed = 2; + } else { + button_pressed = 2 + (ret - NSAlertThirdButtonReturn); + } + + if (!p_callback.is_null()) { + Variant button = button_pressed; + Variant *buttonp = &button; + Variant ret; + Callable::CallError ce; + p_callback.call((const Variant **)&buttonp, 1, ret, ce); + } + + [window release]; + return OK; +} + +Error DisplayServerOSX::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) { + _THREAD_SAFE_METHOD_ + + NSAlert *window = [[NSAlert alloc] init]; + NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; + NSString *ns_description = [NSString stringWithUTF8String:p_description.utf8().get_data()]; + NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 250, 30)]; + + [window addButtonWithTitle:@"OK"]; + [window setMessageText:ns_title]; + [window setInformativeText:ns_description]; + [window setAlertStyle:NSAlertStyleInformational]; + + [input setStringValue:[NSString stringWithUTF8String:p_partial.utf8().get_data()]]; + [window setAccessoryView:input]; + + [window runModal]; + + char *utfs = strdup([[input stringValue] UTF8String]); + String ret; + ret.parse_utf8(utfs); + free(utfs); + + if (!p_callback.is_null()) { + Variant text = ret; + Variant *textp = &text; + Variant ret; + Callable::CallError ce; + p_callback.call((const Variant **)&textp, 1, ret, ce); + } + + [window release]; + return OK; +} + +void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { + _THREAD_SAFE_METHOD_ + + if (p_mode == mouse_mode) + return; + + if (p_mode == MOUSE_MODE_CAPTURED) { + // Apple Docs state that the display parameter is not used. + // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." + // https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html + CGDisplayHideCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(false); + } else if (p_mode == MOUSE_MODE_HIDDEN) { + CGDisplayHideCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(true); + } else { + CGDisplayShowCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(true); + } + + mouse_mode = p_mode; +} + +DisplayServer::MouseMode DisplayServerOSX::mouse_get_mode() const { + return mouse_mode; +} + +void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) { + _THREAD_SAFE_METHOD_ + + if (mouse_mode == MOUSE_MODE_CAPTURED) { + last_mouse_pos = p_to; + } else { + WindowData &wd = windows[MAIN_WINDOW_ID]; + + //local point in window coords + const NSRect contentRect = [wd.window_view frame]; + float displayScale = _display_scale([wd.window_object screen]); + NSRect pointInWindowRect = NSMakeRect(p_to.x / displayScale, contentRect.size.height - (p_to.y / displayScale) - 1, 0, 0); + NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin; + + //point in scren coords + CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y }; + + //do the warping + CGEventSourceRef lEventRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); + CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0); + CGAssociateMouseAndMouseCursorPosition(false); + CGWarpMouseCursorPosition(lMouseWarpPos); + CGAssociateMouseAndMouseCursorPosition(true); + } +} + +Point2i DisplayServerOSX::mouse_get_position() const { + return last_mouse_pos; +} + +Point2i DisplayServerOSX::mouse_get_absolute_position() const { + _THREAD_SAFE_METHOD_ + + const NSPoint mouse_pos = [NSEvent mouseLocation]; + + for (NSScreen *screen in [NSScreen screens]) { + NSRect frame = [screen frame]; + if (NSMouseInRect(mouse_pos, frame, NO)) { + return Vector2i((int)mouse_pos.x, (int)-mouse_pos.y) + _get_screens_origin(); + } + } + return Vector2i(); +} + +int DisplayServerOSX::mouse_get_button_state() const { + return last_button_state; +} + +void DisplayServerOSX::clipboard_set(const String &p_text) { + _THREAD_SAFE_METHOD_ + + NSString *copiedString = [NSString stringWithUTF8String:p_text.utf8().get_data()]; + NSArray *copiedStringArray = [NSArray arrayWithObject:copiedString]; + + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard clearContents]; + [pasteboard writeObjects:copiedStringArray]; +} + +String DisplayServerOSX::clipboard_get() const { + _THREAD_SAFE_METHOD_ + + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSDictionary *options = [NSDictionary dictionary]; + + BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; + + if (!ok) { + return ""; + } + + NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; + NSString *string = [objectsToPaste objectAtIndex:0]; + + char *utfs = strdup([string UTF8String]); + String ret; + ret.parse_utf8(utfs); + free(utfs); + + return ret; +} + +int DisplayServerOSX::get_screen_count() const { + _THREAD_SAFE_METHOD_ + + NSArray *screenArray = [NSScreen screens]; + return [screenArray count]; +} + +// Returns the native top-left screen coordinate of the smallest rectangle +// that encompasses all screens. Needed in get_screen_position(), +// window_get_position, and window_set_position() +// to convert between OS X native screen coordinates and the ones expected by Godot + +static bool displays_arrangement_dirty = true; +static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) { + displays_arrangement_dirty = true; +} + +float DisplayServerOSX::_display_scale(id screen) const { + if (OS_OSX::get_singleton()->is_hidpi_allowed()) { + if ([screen respondsToSelector:@selector(backingScaleFactor)]) { + return fmax(1.0, [screen backingScaleFactor]); + } + } + return 1.0; +} + +Point2i DisplayServerOSX::_get_screens_origin() const { + static Point2i origin; + + if (displays_arrangement_dirty) { + origin = Point2i(); + + for (int i = 0; i < get_screen_count(); i++) { + Point2i position = _get_native_screen_position(i); + if (position.x < origin.x) { + origin.x = position.x; + } + if (position.y > origin.y) { + origin.y = position.y; + } + } + displays_arrangement_dirty = false; + } + + return origin; +} + +Point2i DisplayServerOSX::_get_native_screen_position(int p_screen) const { + NSArray *screenArray = [NSScreen screens]; + if ((NSUInteger)p_screen < [screenArray count]) { + float display_scale = _display_scale([screenArray objectAtIndex:p_screen]); + NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; + // Return the top-left corner of the screen, for OS X the y starts at the bottom + return Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * display_scale; + } + + return Point2i(); +} + +Point2i DisplayServerOSX::screen_get_position(int p_screen) const { + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); + } + + Point2i position = _get_native_screen_position(p_screen) - _get_screens_origin(); + // OS X native y-coordinate relative to _get_screens_origin() is negative, + // Godot expects a positive value + position.y *= -1; + return position; +} + +Size2i DisplayServerOSX::screen_get_size(int p_screen) const { + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); + } + + NSArray *screenArray = [NSScreen screens]; + if ((NSUInteger)p_screen < [screenArray count]) { + float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); + // Note: Use frame to get the whole screen size + NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; + return Size2i(nsrect.size.width, nsrect.size.height) * displayScale; + } + + return Size2i(); +} + +int DisplayServerOSX::screen_get_dpi(int p_screen) const { + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); + } + + NSArray *screenArray = [NSScreen screens]; + if ((NSUInteger)p_screen < [screenArray count]) { + float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); + NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription]; + NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue]; + CGSize displayPhysicalSize = CGDisplayScreenSize( + [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]); + + return (displayPixelSize.width * 25.4f / displayPhysicalSize.width) * displayScale; + } + + return 96; +} + +float DisplayServerOSX::screen_get_scale(int p_screen) const { + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); + } + NSArray *screenArray = [NSScreen screens]; + if ((NSUInteger)p_screen < [screenArray count]) { + return _display_scale([screenArray objectAtIndex:p_screen]); + } + + return 1.f; +} + +Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const { + _THREAD_SAFE_METHOD_ + + if (p_screen == SCREEN_OF_MAIN_WINDOW) { + p_screen = window_get_current_screen(); + } + + NSArray *screenArray = [NSScreen screens]; + if ((NSUInteger)p_screen < [screenArray count]) { + float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); + NSRect nsrect = [[screenArray objectAtIndex:p_screen] visibleFrame]; + + Point2i position = Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * displayScale - _get_screens_origin(); + position.y *= -1; + Size2i size = Size2i(nsrect.size.width, nsrect.size.height) * displayScale; + + return Rect2i(position, size); + } + + return Rect2i(); +} + +Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const { + _THREAD_SAFE_METHOD_ + + Vector<int> ret; + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + return ret; +} + +DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { + _THREAD_SAFE_METHOD_ + + WindowID id = _create_window(p_mode, p_rect); + WindowData &wd = windows[id]; + for (int i = 0; i < WINDOW_FLAG_MAX; i++) { + if (p_flags & (1 << i)) { + window_set_flag(WindowFlags(i), true, id); + } + } + [wd.window_object makeKeyAndOrderFront:nil]; + return id; +} + +void DisplayServerOSX::_send_window_event(const WindowData &wd, WindowEvent p_event) { + if (!wd.event_callback.is_null()) { + Variant event = int(p_event); + Variant *eventp = &event; + Variant ret; + Callable::CallError ce; + wd.event_callback.call((const Variant **)&eventp, 1, ret, ce); + } +} + +DisplayServerOSX::WindowID DisplayServerOSX::_find_window_id(id p_window) { + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (E->get().window_object == p_window) + return E->key(); + } + return INVALID_WINDOW_ID; +} + +void DisplayServerOSX::_update_window(WindowData p_wd) { + bool borderless_full = false; + + if (p_wd.borderless) { + NSRect frameRect = [p_wd.window_object frame]; + NSRect screenRect = [[p_wd.window_object screen] frame]; + + // Check if our window covers up the screen + if (frameRect.origin.x <= screenRect.origin.x && frameRect.origin.y <= frameRect.origin.y && + frameRect.size.width >= screenRect.size.width && frameRect.size.height >= screenRect.size.height) { + borderless_full = true; + } + } + + if (borderless_full) { + // If the window covers up the screen set the level to above the main menu and hide on deactivate + [p_wd.window_object setLevel:NSMainMenuWindowLevel + 1]; + [p_wd.window_object setHidesOnDeactivate:YES]; + } else { + // Reset these when our window is not a borderless window that covers up the screen + [p_wd.window_object setLevel:NSNormalWindowLevel]; + [p_wd.window_object setHidesOnDeactivate:NO]; + } +} + +void DisplayServerOSX::delete_sub_window(WindowID p_id) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_id)); + ERR_FAIL_COND_MSG(p_id == MAIN_WINDOW_ID, "Main window can't be deleted"); + + WindowData &wd = windows[p_id]; + + while (wd.transient_children.size()) { + window_set_transient(wd.transient_children.front()->get(), INVALID_WINDOW_ID); + } + + if (wd.transient_parent != INVALID_WINDOW_ID) { + WindowData &pwd = windows[wd.transient_parent]; + [pwd.window_object makeKeyAndOrderFront:nil]; // Move focus back to parent. + window_set_transient(p_id, INVALID_WINDOW_ID); + } + + [wd.window_object setContentView:nil]; + [wd.window_object close]; + + windows.erase(p_id); +} + +void DisplayServerOSX::window_set_title(const String &p_title, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + [wd.window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]]; +} + +void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.rect_changed_callback = p_callable; +} + +void DisplayServerOSX::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.event_callback = p_callable; +} + +void DisplayServerOSX::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.input_event_callback = p_callable; +} + +void DisplayServerOSX::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { + _THREAD_SAFE_METHOD_ + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.input_text_callback = p_callable; +} + +void DisplayServerOSX::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { + _THREAD_SAFE_METHOD_ + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.drop_files_callback = p_callable; +} + +int DisplayServerOSX::window_get_current_screen(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + ERR_FAIL_COND_V(!windows.has(p_window), -1); + const WindowData &wd = windows[p_window]; + + const NSUInteger index = [[NSScreen screens] indexOfObject:[wd.window_object screen]]; + return (index == NSNotFound) ? 0 : index; +} + +void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window) { + _THREAD_SAFE_METHOD_ + Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); + window_set_position(wpos + screen_get_position(p_screen), p_window); +} + +void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent) { + _THREAD_SAFE_METHOD_ + ERR_FAIL_COND(p_window == p_parent); + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd_window = windows[p_window]; + + ERR_FAIL_COND(wd_window.transient_parent == p_parent); + + ERR_FAIL_COND_MSG(wd_window.on_top, "Windows with the 'on top' can't become transient."); + if (p_parent == INVALID_WINDOW_ID) { + //remove transient + ERR_FAIL_COND(wd_window.transient_parent == INVALID_WINDOW_ID); + ERR_FAIL_COND(!windows.has(wd_window.transient_parent)); + + WindowData &wd_parent = windows[wd_window.transient_parent]; + + wd_window.transient_parent = INVALID_WINDOW_ID; + wd_parent.transient_children.erase(p_window); + + [wd_window.window_object setParentWindow:nil]; + } else { + ERR_FAIL_COND(!windows.has(p_parent)); + ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent"); + WindowData &wd_parent = windows[p_parent]; + + wd_window.transient_parent = p_parent; + wd_parent.transient_children.insert(p_window); + + [wd_window.window_object setParentWindow:wd_parent.window_object]; + } +} + +Point2i DisplayServerOSX::window_get_position(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Point2i()); + const WindowData &wd = windows[p_window]; + + NSRect nsrect = [wd.window_object frame]; + Point2i pos; + float display_scale = _display_scale([wd.window_object screen]); + + // Return the position of the top-left corner, for OS X the y starts at the bottom + pos.x = nsrect.origin.x * display_scale; + pos.y = (nsrect.origin.y + nsrect.size.height) * display_scale; + pos -= _get_screens_origin(); + // OS X native y-coordinate relative to _get_screens_origin() is negative, + // Godot expects a positive value + pos.y *= -1; + return pos; +} + +void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + Point2i position = p_position; + // OS X native y-coordinate relative to _get_screens_origin() is negative, + // Godot passes a positive value + position.y *= -1; + position += _get_screens_origin(); + + NSPoint pos; + float displayScale = _display_scale([wd.window_object screen]); + + pos.x = position.x / displayScale; + pos.y = position.y / displayScale; + + [wd.window_object setFrameTopLeftPoint:pos]; + + _update_window(wd); + _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream], displayScale); +} + +void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if ((p_size != Size2i()) && ((p_size.x < wd.min_size.x) || (p_size.y < wd.min_size.y))) { + ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); + return; + } + wd.max_size = p_size; + + if ((wd.max_size != Size2i()) && !wd.fullscreen) { + Size2i size = wd.max_size / _display_scale([wd.window_object screen]); + [wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; + } else { + [wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; + } +} + +Size2i DisplayServerOSX::window_get_max_size(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + return wd.max_size; +} + +void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if ((p_size != Size2i()) && (wd.max_size != Size2i()) && ((p_size.x > wd.max_size.x) || (p_size.y > wd.max_size.y))) { + ERR_PRINT("Minimum window size can't be larger than maximum window size!"); + return; + } + wd.min_size = p_size; + + if ((wd.min_size != Size2i()) && !wd.fullscreen) { + Size2i size = wd.min_size / _display_scale([wd.window_object screen]); + [wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)]; + } else { + [wd.window_object setContentMinSize:NSMakeSize(0, 0)]; + } +} + +Size2i DisplayServerOSX::window_get_min_size(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + + return wd.min_size; +} + +void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + Size2i size = p_size / _display_scale([wd.window_object screen]); + + if (!wd.borderless) { + // NSRect used by setFrame includes the title bar, so add it to our size.y + CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + if (menuBarHeight != 0.f) { + size.y += menuBarHeight; + } + } + + NSRect frame = [wd.window_object frame]; + [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, size.x, size.y) display:YES]; + + _update_window(wd); +} + +Size2i DisplayServerOSX::window_get_size(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + return wd.size; +} + +Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + NSRect frame = [wd.window_object frame]; + return Size2i(frame.size.width, frame.size.height) * _display_scale([wd.window_object screen]); +} + +bool DisplayServerOSX::window_is_maximize_allowed(WindowID p_window) const { + return true; +} + +void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) { + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if (!OS_OSX::get_singleton()->is_layered_allowed()) return; + if (wd.layered_window != p_enabled) { + if (p_enabled) { + [wd.window_object setBackgroundColor:[NSColor clearColor]]; + [wd.window_object setOpaque:NO]; + [wd.window_object setHasShadow:NO]; +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + CALayer *layer = [wd.window_view layer]; + [layer setOpaque:NO]; + //TODO - implement transparency for Vulkan + } +#endif +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + wd.context_gles2->set_opacity(0); + } +#endif + wd.layered_window = true; + } else { + [wd.window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]]; + [wd.window_object setOpaque:YES]; + [wd.window_object setHasShadow:YES]; +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + CALayer *layer = [wd.window_view layer]; + [layer setOpaque:YES]; + //TODO - implement transparency for Vulkan + } +#endif +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + wd.context_gles2->set_opacity(1); + } +#endif + wd.layered_window = false; + } +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + wd.context_gles2->update(); + } +#endif + NSRect frameRect = [wd.window_object frame]; + [wd.window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:YES]; + [wd.window_object setFrame:frameRect display:YES]; + } +} + +void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + WindowMode old_mode = window_get_mode(p_window); + if (old_mode == p_mode) { + return; // do nothing + } + + switch (old_mode) { + case WINDOW_MODE_WINDOWED: { + //do nothing + } break; + case WINDOW_MODE_MINIMIZED: { + [wd.window_object deminiaturize:nil]; + } break; + case WINDOW_MODE_FULLSCREEN: { + if (wd.layered_window) + _set_window_per_pixel_transparency_enabled(true, p_window); + if (wd.resize_disabled) //restore resize disabled + [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable]; + if (wd.min_size != Size2i()) { + Size2i size = wd.min_size / _display_scale([wd.window_object screen]); + [wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)]; + } + if (wd.max_size != Size2i()) { + Size2i size = wd.max_size / _display_scale([wd.window_object screen]); + [wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; + } + [wd.window_object toggleFullScreen:nil]; + wd.fullscreen = false; + } break; + case WINDOW_MODE_MAXIMIZED: { + if ([wd.window_object isZoomed]) { + [wd.window_object zoom:nil]; + } + } break; + } + + switch (p_mode) { + case WINDOW_MODE_WINDOWED: { + //do nothing + } break; + case WINDOW_MODE_MINIMIZED: { + [wd.window_object performMiniaturize:nil]; + } break; + case WINDOW_MODE_FULLSCREEN: { + if (wd.layered_window) + _set_window_per_pixel_transparency_enabled(false, p_window); + if (wd.resize_disabled) //fullscreen window should be resizable to work + [wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable]; + [wd.window_object setContentMinSize:NSMakeSize(0, 0)]; + [wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; + [wd.window_object toggleFullScreen:nil]; + wd.fullscreen = true; + } break; + case WINDOW_MODE_MAXIMIZED: { + if (![wd.window_object isZoomed]) { + [wd.window_object zoom:nil]; + } + } break; + } +} + +DisplayServer::WindowMode DisplayServerOSX::window_get_mode(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED); + const WindowData &wd = windows[p_window]; + + if (wd.fullscreen) { //if fullscreen, it's not in another mode + return WINDOW_MODE_FULLSCREEN; + } + if ([wd.window_object isZoomed] && !wd.resize_disabled) { + return WINDOW_MODE_MAXIMIZED; + } + if ([wd.window_object respondsToSelector:@selector(isMiniaturized)]) { + if ([wd.window_object isMiniaturized]) { + return WINDOW_MODE_MINIMIZED; + } + } + + // all other discarded, return windowed. + return WINDOW_MODE_WINDOWED; +} + +void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + switch (p_flag) { + case WINDOW_FLAG_RESIZE_DISABLED: { + wd.resize_disabled = p_enabled; + if (wd.fullscreen) //fullscreen window should be resizable, style will be applyed on exiting fs + return; + if (p_enabled) { + [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable]; + } else { + [wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable]; + } + } break; + case WINDOW_FLAG_BORDERLESS: { + // OrderOut prevents a lose focus bug with the window + [wd.window_object orderOut:nil]; + wd.borderless = p_enabled; + if (p_enabled) { + [wd.window_object setStyleMask:NSWindowStyleMaskBorderless]; + } else { + if (wd.layered_window) + _set_window_per_pixel_transparency_enabled(false, p_window); + [wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)]; + // Force update of the window styles + NSRect frameRect = [wd.window_object frame]; + [wd.window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO]; + [wd.window_object setFrame:frameRect display:NO]; + } + _update_window(wd); + [wd.window_object makeKeyAndOrderFront:nil]; + } break; + case WINDOW_FLAG_ALWAYS_ON_TOP: { + wd.on_top = p_enabled; + if (p_enabled) { + [wd.window_object setLevel:NSFloatingWindowLevel]; + } else { + [wd.window_object setLevel:NSNormalWindowLevel]; + } + } break; + case WINDOW_FLAG_TRANSPARENT: { + wd.layered_window = p_enabled; + if (p_enabled) { + [wd.window_object setStyleMask:NSWindowStyleMaskBorderless]; // force borderless + } else if (!wd.borderless) { + [wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)]; + } + _set_window_per_pixel_transparency_enabled(p_enabled, p_window); + + } break; + default: { + } + } +} + +bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; + + switch (p_flag) { + case WINDOW_FLAG_RESIZE_DISABLED: { + return wd.resize_disabled; + } break; + case WINDOW_FLAG_BORDERLESS: { + return [wd.window_object styleMask] == NSWindowStyleMaskBorderless; + } break; + case WINDOW_FLAG_ALWAYS_ON_TOP: { + return [wd.window_object level] == NSFloatingWindowLevel; + } break; + case WINDOW_FLAG_TRANSPARENT: { + return wd.layered_window; + } break; + default: { + } + } + + return false; +} + +void DisplayServerOSX::window_request_attention(WindowID p_window) { + // It's app global, ignore window id. + [NSApp requestUserAttention:NSCriticalRequest]; +} + +void DisplayServerOSX::window_move_to_foreground(WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + const WindowData &wd = windows[p_window]; + + [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; + [wd.window_object makeKeyAndOrderFront:nil]; +} + +bool DisplayServerOSX::window_can_draw(WindowID p_window) const { + return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED; +} + +bool DisplayServerOSX::can_any_window_draw() const { + _THREAD_SAFE_METHOD_ + + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (window_get_mode(E->key()) != WINDOW_MODE_MINIMIZED) { + return true; + } + } + return false; +} + +void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.im_active = p_active; + + if (!p_active) + [wd.window_view cancelComposition]; +} + +void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.im_position = p_pos; +} + +bool DisplayServerOSX::get_swap_ok_cancel() { + return true; +} + +void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_INDEX(p_shape, CURSOR_MAX); + + if (cursor_shape == p_shape) + return; + + if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { + cursor_shape = p_shape; + return; + } + + if (cursors[p_shape] != NULL) { + [cursors[p_shape] set]; + } else { + switch (p_shape) { + case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break; + case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break; + case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break; + case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break; + case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break; + case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break; + case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break; + case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break; + case CURSOR_FORBIDDEN: [[NSCursor operationNotAllowedCursor] set]; break; + case CURSOR_VSIZE: [_cursorFromSelector(@selector(_windowResizeNorthSouthCursor), @selector(resizeUpDownCursor)) set]; break; + case CURSOR_HSIZE: [_cursorFromSelector(@selector(_windowResizeEastWestCursor), @selector(resizeLeftRightCursor)) set]; break; + case CURSOR_BDIAGSIZE: [_cursorFromSelector(@selector(_windowResizeNorthEastSouthWestCursor)) set]; break; + case CURSOR_FDIAGSIZE: [_cursorFromSelector(@selector(_windowResizeNorthWestSouthEastCursor)) set]; break; + case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break; + case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break; + case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break; + case CURSOR_HELP: [_cursorFromSelector(@selector(_helpCursor)) set]; break; + default: { + } + } + } + + cursor_shape = p_shape; +} + +DisplayServerOSX::CursorShape DisplayServerOSX::cursor_get_shape() const { + return cursor_shape; +} + +void DisplayServerOSX::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + _THREAD_SAFE_METHOD_ + + if (p_cursor.is_valid()) { + Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + + if (cursor_c) { + if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + cursor_set_shape(p_shape); + return; + } + cursors_cache.erase(p_shape); + } + + Ref<Texture2D> texture = p_cursor; + Ref<AtlasTexture> atlas_texture = p_cursor; + Ref<Image> image; + Size2 texture_size; + Rect2 atlas_rect; + + if (texture.is_valid()) { + image = texture->get_data(); + } + + if (!image.is_valid() && atlas_texture.is_valid()) { + texture = atlas_texture->get_atlas(); + + atlas_rect.size.width = texture->get_width(); + atlas_rect.size.height = texture->get_height(); + atlas_rect.position.x = atlas_texture->get_region().position.x; + atlas_rect.position.y = atlas_texture->get_region().position.y; + + texture_size.width = atlas_texture->get_region().size.x; + texture_size.height = atlas_texture->get_region().size.y; + } else if (image.is_valid()) { + texture_size.width = texture->get_width(); + texture_size.height = texture->get_height(); + } + + ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); + ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); + + image = texture->get_data(); + + ERR_FAIL_COND(!image.is_valid()); + + NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:NULL + pixelsWide:int(texture_size.width) + pixelsHigh:int(texture_size.height) + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:int(texture_size.width) * 4 + bitsPerPixel:32]; + + ERR_FAIL_COND(imgrep == nil); + uint8_t *pixels = [imgrep bitmapData]; + + int len = int(texture_size.width * texture_size.height); + + for (int i = 0; i < len; i++) { + int row_index = floor(i / texture_size.width) + atlas_rect.position.y; + int column_index = (i % int(texture_size.width)) + atlas_rect.position.x; + + if (atlas_texture.is_valid()) { + column_index = MIN(column_index, atlas_rect.size.width - 1); + row_index = MIN(row_index, atlas_rect.size.height - 1); + } + + uint32_t color = image->get_pixel(column_index, row_index).to_argb32(); + + uint8_t alpha = (color >> 24) & 0xFF; + pixels[i * 4 + 0] = ((color >> 16) & 0xFF) * alpha / 255; + pixels[i * 4 + 1] = ((color >> 8) & 0xFF) * alpha / 255; + pixels[i * 4 + 2] = ((color)&0xFF) * alpha / 255; + pixels[i * 4 + 3] = alpha; + } + + NSImage *nsimage = [[NSImage alloc] initWithSize:NSMakeSize(texture_size.width, texture_size.height)]; + [nsimage addRepresentation:imgrep]; + + NSCursor *cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(p_hotspot.x, p_hotspot.y)]; + + [cursors[p_shape] release]; + cursors[p_shape] = cursor; + + Vector<Variant> params; + params.push_back(p_cursor); + params.push_back(p_hotspot); + cursors_cache.insert(p_shape, params); + + if (p_shape == cursor_shape) { + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + [cursor set]; + } + } + + [imgrep release]; + [nsimage release]; + } else { + // Reset to default system cursor + if (cursors[p_shape] != NULL) { + [cursors[p_shape] release]; + cursors[p_shape] = NULL; + } + + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + cursor_set_shape(c); + + cursors_cache.erase(p_shape); + } +} + +static bool keyboard_layout_dirty = true; +static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) { + keyboard_layout_dirty = true; +} + +// Returns string representation of keys, if they are printable. +static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) { + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + if (!currentKeyboard) + return nil; + + CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + if (!layoutData) + return nil; + + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); + + OSStatus err; + CFMutableStringRef output = CFStringCreateMutable(NULL, 0); + + for (int i = 0; i < length; ++i) { + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; + + err = UCKeyTranslate(keyboardLayout, + keyCode[i], + kUCKeyActionDisplay, + 0, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &keysDown, + sizeof(chars) / sizeof(chars[0]), + &realLength, + chars); + + if (err != noErr) { + CFRelease(output); + return nil; + } + + CFStringAppendCharacters(output, chars, 1); + } + + return (NSString *)output; +} + +DisplayServerOSX::LatinKeyboardVariant DisplayServerOSX::get_latin_keyboard_variant() const { + _THREAD_SAFE_METHOD_ + + static LatinKeyboardVariant layout = LATIN_KEYBOARD_QWERTY; + + if (keyboard_layout_dirty) { + + layout = LATIN_KEYBOARD_QWERTY; + + CGKeyCode keys[] = { kVK_ANSI_Q, kVK_ANSI_W, kVK_ANSI_E, kVK_ANSI_R, kVK_ANSI_T, kVK_ANSI_Y }; + NSString *test = createStringForKeys(keys, 6); + + if ([test isEqualToString:@"qwertz"]) { + layout = LATIN_KEYBOARD_QWERTZ; + } else if ([test isEqualToString:@"azerty"]) { + layout = LATIN_KEYBOARD_AZERTY; + } else if ([test isEqualToString:@"qzerty"]) { + layout = LATIN_KEYBOARD_QZERTY; + } else if ([test isEqualToString:@"',.pyf"]) { + layout = LATIN_KEYBOARD_DVORAK; + } else if ([test isEqualToString:@"xvlcwk"]) { + layout = LATIN_KEYBOARD_NEO; + } else if ([test isEqualToString:@"qwfpgj"]) { + layout = LATIN_KEYBOARD_COLEMAK; + } + + [test release]; + + keyboard_layout_dirty = false; + return layout; + } + + return layout; +} + +void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) { + Ref<InputEvent> ev = p_event; + InputFilter::get_singleton()->accumulate_input_event(ev); +} + +void DisplayServerOSX::_process_key_events() { + Ref<InputEventKey> k; + for (int i = 0; i < key_event_pos; i++) { + const KeyEvent &ke = key_event_buffer[i]; + if (ke.raw) { + // Non IME input - no composite characters, pass events as is + k.instance(); + + k->set_window_id(ke.window_id); + _get_key_modifier_state(ke.osx_state, k); + k->set_pressed(ke.pressed); + k->set_echo(ke.echo); + k->set_keycode(ke.keycode); + k->set_physical_keycode(ke.physical_keycode); + k->set_unicode(ke.unicode); + + _push_input(k); + } else { + // IME input + if ((i == 0 && ke.keycode == 0) || (i > 0 && key_event_buffer[i - 1].keycode == 0)) { + k.instance(); + + k->set_window_id(ke.window_id); + _get_key_modifier_state(ke.osx_state, k); + k->set_pressed(ke.pressed); + k->set_echo(ke.echo); + k->set_keycode(0); + k->set_physical_keycode(0); + k->set_unicode(ke.unicode); + + _push_input(k); + } + if (ke.keycode != 0) { + k.instance(); + + k->set_window_id(ke.window_id); + _get_key_modifier_state(ke.osx_state, k); + k->set_pressed(ke.pressed); + k->set_echo(ke.echo); + k->set_keycode(ke.keycode); + k->set_physical_keycode(ke.physical_keycode); + + if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == 0) { + k->set_unicode(key_event_buffer[i + 1].unicode); + } + + _push_input(k); + } + } + } + + key_event_pos = 0; +} + +void DisplayServerOSX::process_events() { + _THREAD_SAFE_METHOD_ + + while (true) { + NSEvent *event = [NSApp + nextEventMatchingMask:NSEventMaskAny + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + + if (event == nil) + break; + + [NSApp sendEvent:event]; + } + + if (!drop_events) { + _process_key_events(); + InputFilter::get_singleton()->flush_accumulated_events(); + } + + [autoreleasePool drain]; + autoreleasePool = [[NSAutoreleasePool alloc] init]; +} + +void DisplayServerOSX::force_process_and_drop_events() { + _THREAD_SAFE_METHOD_ + + drop_events = true; + process_events(); + drop_events = false; +} + +void DisplayServerOSX::set_native_icon(const String &p_filename) { + _THREAD_SAFE_METHOD_ + + FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); + ERR_FAIL_COND(!f); + + Vector<uint8_t> data; + uint32_t len = f->get_len(); + data.resize(len); + f->get_buffer((uint8_t *)&data.write[0], len); + memdelete(f); + + NSData *icon_data = [[[NSData alloc] initWithBytes:&data.write[0] length:len] autorelease]; + ERR_FAIL_COND_MSG(!icon_data, "Error reading icon data."); + + NSImage *icon = [[[NSImage alloc] initWithData:icon_data] autorelease]; + ERR_FAIL_COND_MSG(!icon, "Error loading icon."); + + [NSApp setApplicationIconImage:icon]; +} + +void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) { + _THREAD_SAFE_METHOD_ + + Ref<Image> img = p_icon; + img = img->duplicate(); + img->convert(Image::FORMAT_RGBA8); + NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:NULL + pixelsWide:img->get_width() + pixelsHigh:img->get_height() + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:img->get_width() * 4 + bitsPerPixel:32]; + ERR_FAIL_COND(imgrep == nil); + uint8_t *pixels = [imgrep bitmapData]; + + int len = img->get_width() * img->get_height(); + const uint8_t *r = img->get_data().ptr(); + + /* Premultiply the alpha channel */ + for (int i = 0; i < len; i++) { + uint8_t alpha = r[i * 4 + 3]; + pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255); + pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255); + pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255); + pixels[i * 4 + 3] = alpha; + } + + NSImage *nsimg = [[NSImage alloc] initWithSize:NSMakeSize(img->get_width(), img->get_height())]; + ERR_FAIL_COND(nsimg == nil); + + [nsimg addRepresentation:imgrep]; + [NSApp setApplicationIconImage:nsimg]; + + [imgrep release]; + [nsimg release]; +} + +Vector<String> DisplayServerOSX::get_rendering_drivers_func() { + Vector<String> drivers; + +#ifdef VULKAN_ENABLED + drivers.push_back("vulkan"); +#endif +#ifdef OPENGL_ENABLED + drivers.push_back("opengl"); +#endif + + return drivers; +} + +Point2i DisplayServerOSX::ime_get_selection() const { + return im_selection; +} + +String DisplayServerOSX::ime_get_text() const { + return im_text; +} + +DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Point2i &p_position) const { + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + Rect2i win_rect = Rect2i(window_get_position(E->key()), window_get_size(E->key())); + if (win_rect.has_point(p_position)) { + return E->key(); + } + } + return INVALID_WINDOW_ID; +} + +void DisplayServerOSX::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].instance_id = p_instance; +} + +ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), ObjectID()); + return windows[p_window].instance_id; +} + +DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + return memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); +} + +DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, const Rect2i &p_rect) { + WindowID id; + { + WindowData wd; + + float displayScale = 1.0; + if (OS_OSX::get_singleton()->is_hidpi_allowed()) { + // note that mainScreen is not screen #0 but the one with the keyboard focus. + NSScreen *screen = [NSScreen mainScreen]; + if ([screen respondsToSelector:@selector(backingScaleFactor)]) { + displayScale = fmax(displayScale, [screen backingScaleFactor]); + } + } + + wd.window_delegate = [[GodotWindowDelegate alloc] init]; + ERR_FAIL_COND_V_MSG(wd.window_delegate == nil, INVALID_WINDOW_ID, "Can't create a window delegate"); + [wd.window_delegate setWindowID:window_id_counter]; + + Point2i position = p_rect.position; + // OS X native y-coordinate relative to _get_screens_origin() is negative, + // Godot passes a positive value + position.y *= -1; + position += _get_screens_origin(); + + // initWithContentRect uses bottom-left corner of the window’s frame as origin. + wd.window_object = [[GodotWindow alloc] + initWithContentRect:NSMakeRect(position.x / displayScale, (position.y - p_rect.size.height) / displayScale, p_rect.size.width / displayScale, p_rect.size.height / displayScale) + styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable + backing:NSBackingStoreBuffered + defer:NO]; + ERR_FAIL_COND_V_MSG(wd.window_object == nil, INVALID_WINDOW_ID, "Can't create a window"); + + wd.window_view = [[GodotContentView alloc] init]; + ERR_FAIL_COND_V_MSG(wd.window_view == nil, INVALID_WINDOW_ID, "Can't create a window view"); + [wd.window_view setWindowID:window_id_counter]; + if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_14) { + [wd.window_view setWantsLayer:TRUE]; + } + + if (displayScale > 1.0) { +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + [wd.window_view setWantsBestResolutionOpenGLSurface:YES]; + } +#endif + [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + } else { +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + [wd.window_view setWantsBestResolutionOpenGLSurface:NO]; + } +#endif + } + + [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + [wd.window_object setContentView:wd.window_view]; + [wd.window_object setDelegate:wd.window_delegate]; + [wd.window_object setAcceptsMouseMovedEvents:YES]; + [wd.window_object setRestorable:NO]; + + if ([wd.window_object respondsToSelector:@selector(setTabbingMode:)]) + [wd.window_object setTabbingMode:NSWindowTabbingModeDisallowed]; + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + if (context_vulkan) { + CALayer *layer = [wd.window_view layer]; + layer.contentsScale = displayScale; + Error err = context_vulkan->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height); + ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan context"); + } + } +#endif +#ifdef OPENGL_ENABLED + if (rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + wd.context_gles2 = memnew(ContextGL_OSX(wd.window_view, false)); + + if (wd.context_gles2->initialize() != OK) { + memdelete(wd.context_gles2); + ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a OpenGL context"); + } + + //if (RasterizerGLES2::is_viable() == OK) { + // RasterizerGLES2::register_config(); + // RasterizerGLES2::make_current(); + //} + } +#endif + id = window_id_counter++; + windows[id] = wd; + } + + WindowData &wd = windows[id]; + window_set_mode(p_mode, id); + + float displayScale = _display_scale([wd.window_object screen]); + const NSRect contentRect = [wd.window_view frame]; + wd.size.width = contentRect.size.width * displayScale; + wd.size.height = contentRect.size.height * displayScale; + +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + if (OS_OSX::singleton->is_hidpi_allowed()) { + [wd.window_view setWantsBestResolutionOpenGLSurface:YES]; + } else { + [wd.window_view setWantsBestResolutionOpenGLSurface:NO]; + } + wd.context_gles2->update(); + } +#endif +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + CALayer *layer = [wd.window_view layer]; + layer.contentsScale = displayScale; + context_vulkan->window_resize(id, wd.size.width, wd.size.height); + } +#endif + + return id; +} + +void DisplayServerOSX::_dispatch_input_events(const Ref<InputEvent> &p_event) { + ((DisplayServerOSX *)(get_singleton()))->_dispatch_input_event(p_event); +} + +void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) { + Variant ev = p_event; + Variant *evp = &ev; + Variant ret; + Callable::CallError ce; + + Ref<InputEventFromWindow> event_from_window = p_event; + if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) { + //send to a window + if (windows.has(event_from_window->get_window_id())) { + Callable callable = windows[event_from_window->get_window_id()].input_event_callback; + if (callable.is_null()) { + return; + } + callable.call((const Variant **)&evp, 1, ret, ce); + } + } else { + //send to all windows + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + Callable callable = E->get().input_event_callback; + if (callable.is_null()) { + continue; + } + callable.call((const Variant **)&evp, 1, ret, ce); + } + } +} + +void DisplayServerOSX::release_rendering_thread() { + //TODO - reimplement OpenGLES +} + +void DisplayServerOSX::make_rendering_thread() { + //TODO - reimplement OpenGLES +} + +void DisplayServerOSX::swap_buffers() { + //TODO - reimplement OpenGLES +} + +void DisplayServerOSX::console_set_visible(bool p_enabled) { + //TODO - open terminal and redirect +} + +bool DisplayServerOSX::is_console_visible() const { + return isatty(STDIN_FILENO); +} + +DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + InputFilter::get_singleton()->set_event_dispatch_function(_dispatch_input_events); + + r_error = OK; + drop_events = false; + + memset(cursors, 0, sizeof(cursors)); + cursor_shape = CURSOR_ARROW; + + key_event_pos = 0; + mouse_mode = MOUSE_MODE_VISIBLE; + last_button_state = 0; + + autoreleasePool = [[NSAutoreleasePool alloc] init]; + + eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + ERR_FAIL_COND(!eventSource); + + CGEventSourceSetLocalEventsSuppressionInterval(eventSource, 0.0); + + // Implicitly create shared NSApplication instance + [GodotApplication sharedApplication]; + + // In case we are unbundled, make us a proper UI application + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + + keyboard_layout_dirty = true; + displays_arrangement_dirty = true; + + // Register to be notified on keyboard layout changes + CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), + NULL, keyboard_layout_changed, + kTISNotifySelectedKeyboardInputSourceChanged, NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); + + // Register to be notified on displays arrangement changes + CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL); + + // Menu bar setup must go between sharedApplication above and + // finishLaunching below, in order to properly emulate the behavior + // of NSApplicationMain + NSMenuItem *menu_item; + NSString *title; + + NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + if (nsappname == nil) + nsappname = [[NSProcessInfo processInfo] processName]; + + // Setup Dock menu + dock_menu = [[NSMenu alloc] initWithTitle:@"_dock"]; + + // Setup Apple menu + apple_menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; + title = [NSString stringWithFormat:NSLocalizedString(@"About %@", nil), nsappname]; + [apple_menu addItemWithTitle:title action:@selector(showAbout:) keyEquivalent:@""]; + + [apple_menu addItem:[NSMenuItem separatorItem]]; + + NSMenu *services = [[NSMenu alloc] initWithTitle:@""]; + menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Services", nil) action:nil keyEquivalent:@""]; + [apple_menu setSubmenu:services forItem:menu_item]; + [NSApp setServicesMenu:services]; + [services release]; + + [apple_menu addItem:[NSMenuItem separatorItem]]; + + title = [NSString stringWithFormat:NSLocalizedString(@"Hide %@", nil), nsappname]; + [apple_menu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Hide Others", nil) action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menu_item setKeyEquivalentModifierMask:(NSEventModifierFlagOption | NSEventModifierFlagCommand)]; + + [apple_menu addItemWithTitle:NSLocalizedString(@"Show all", nil) action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [apple_menu addItem:[NSMenuItem separatorItem]]; + + title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname]; + [apple_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + // Setup menu bar + NSMenu *main_menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; + menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""]; + [main_menu setSubmenu:apple_menu forItem:menu_item]; + [NSApp setMainMenu:main_menu]; + + [NSApp finishLaunching]; + + delegate = [[GodotApplicationDelegate alloc] init]; + ERR_FAIL_COND(!delegate); + [NSApp setDelegate:delegate]; + + //process application:openFile: event + while (true) { + NSEvent *event = [NSApp + nextEventMatchingMask:NSEventMaskAny + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + + if (event == nil) + break; + + [NSApp sendEvent:event]; + } + + //!!!!!!!!!!!!!!!!!!!!!!!!!! + //TODO - do Vulkan and GLES2 support checks, driver selection and fallback + rendering_driver = p_rendering_driver; + +#ifndef _MSC_VER +#warning Forcing vulkan rendering driver because OpenGL not implemented yet +#endif + rendering_driver = "vulkan"; + +#if defined(OPENGL_ENABLED) + if (rendering_driver == "opengl_es") { + //TODO - reimplement OpenGLES + } +#endif +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + + context_vulkan = memnew(VulkanContextOSX); + if (context_vulkan->initialize() != OK) { + memdelete(context_vulkan); + context_vulkan = NULL; + r_error = ERR_CANT_CREATE; + ERR_FAIL_MSG("Could not initialize Vulkan"); + } + } +#endif + + WindowID main_window = _create_window(p_mode, Rect2i(Point2i(), p_resolution)); + for (int i = 0; i < WINDOW_FLAG_MAX; i++) { + if (p_flags & (1 << i)) { + window_set_flag(WindowFlags(i), true, main_window); + } + } + [windows[main_window].window_object makeKeyAndOrderFront:nil]; + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + rendering_device_vulkan = memnew(RenderingDeviceVulkan); + rendering_device_vulkan->initialize(context_vulkan); + + RasterizerRD::make_current(); + } +#endif + + [NSApp activateIgnoringOtherApps:YES]; + + /* + visual_server = memnew(VisualServerRaster); + if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { + visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + } + visual_server->init(); + */ +} + +DisplayServerOSX::~DisplayServerOSX() { + if (dock_menu) { + [dock_menu release]; + } + + for (Map<String, NSMenu *>::Element *E = submenu.front(); E; E = E->next()) { + [E->get() release]; + } + + //destroy all windows + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + [E->get().window_object setContentView:nil]; + [E->get().window_object close]; + } + + //destroy drivers +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + + if (rendering_device_vulkan) { + rendering_device_vulkan->finalize(); + memdelete(rendering_device_vulkan); + } + + if (context_vulkan) + memdelete(context_vulkan); + } +#endif + + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); + CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL); + + cursors_cache.clear(); + + //visual_server->finish(); + //memdelete(visual_server); +} + +void DisplayServerOSX::register_osx_driver() { + register_create_function("osx", create_func, get_rendering_drivers_func); +} diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp index e9f46fb5a4..f2d9de6fbd 100644 --- a/platform/osx/joypad_osx.cpp +++ b/platform/osx/joypad_osx.cpp @@ -395,38 +395,38 @@ bool joypad::check_ff_features() { static int process_hat_value(int p_min, int p_max, int p_value) { int range = (p_max - p_min + 1); int value = p_value - p_min; - int hat_value = InputDefault::HAT_MASK_CENTER; + int hat_value = InputFilter::HAT_MASK_CENTER; if (range == 4) { value *= 2; } switch (value) { case 0: - hat_value = InputDefault::HAT_MASK_UP; + hat_value = InputFilter::HAT_MASK_UP; break; case 1: - hat_value = InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_RIGHT; + hat_value = InputFilter::HAT_MASK_UP | InputFilter::HAT_MASK_RIGHT; break; case 2: - hat_value = InputDefault::HAT_MASK_RIGHT; + hat_value = InputFilter::HAT_MASK_RIGHT; break; case 3: - hat_value = InputDefault::HAT_MASK_DOWN | InputDefault::HAT_MASK_RIGHT; + hat_value = InputFilter::HAT_MASK_DOWN | InputFilter::HAT_MASK_RIGHT; break; case 4: - hat_value = InputDefault::HAT_MASK_DOWN; + hat_value = InputFilter::HAT_MASK_DOWN; break; case 5: - hat_value = InputDefault::HAT_MASK_DOWN | InputDefault::HAT_MASK_LEFT; + hat_value = InputFilter::HAT_MASK_DOWN | InputFilter::HAT_MASK_LEFT; break; case 6: - hat_value = InputDefault::HAT_MASK_LEFT; + hat_value = InputFilter::HAT_MASK_LEFT; break; case 7: - hat_value = InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_LEFT; + hat_value = InputFilter::HAT_MASK_UP | InputFilter::HAT_MASK_LEFT; break; default: - hat_value = InputDefault::HAT_MASK_CENTER; + hat_value = InputFilter::HAT_MASK_CENTER; break; } return hat_value; @@ -438,8 +438,8 @@ void JoypadOSX::poll_joypads() const { } } -static const InputDefault::JoyAxis axis_correct(int p_value, int p_min, int p_max) { - InputDefault::JoyAxis jx; +static const InputFilter::JoyAxis axis_correct(int p_value, int p_min, int p_max) { + InputFilter::JoyAxis jx; if (p_min < 0) { jx.min = -1; if (p_value < 0) { @@ -571,9 +571,9 @@ void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const { } } -JoypadOSX::JoypadOSX() { +JoypadOSX::JoypadOSX(InputFilter *in) { self = this; - input = (InputDefault *)Input::get_singleton(); + input = in; int okay = 1; const void *vals[] = { diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h index 2c076b3680..62027c6a30 100644 --- a/platform/osx/joypad_osx.h +++ b/platform/osx/joypad_osx.h @@ -40,7 +40,7 @@ #include <ForceFeedback/ForceFeedbackConstants.h> #include <IOKit/hid/IOHIDLib.h> -#include "main/input_default.h" +#include "core/input/input_filter.h" struct rec_element { IOHIDElementRef ref; @@ -94,7 +94,7 @@ class JoypadOSX { }; private: - InputDefault *input; + InputFilter *input; IOHIDManagerRef hid_manager; Vector<joypad> device_list; @@ -118,7 +118,7 @@ public: void _device_added(IOReturn p_res, IOHIDDeviceRef p_device); void _device_removed(IOReturn p_res, IOHIDDeviceRef p_device); - JoypadOSX(); + JoypadOSX(InputFilter *in); ~JoypadOSX(); }; diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index e865c3078f..d2c67cff9f 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -31,57 +31,20 @@ #ifndef OS_OSX_H #define OS_OSX_H -#define BitMap _QDBitMap // Suppress deprecated QuickDraw definition. - -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "crash_handler_osx.h" #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/coremidi/midi_driver_coremidi.h" #include "drivers/unix/os_unix.h" #include "joypad_osx.h" -#include "main/input_default.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/visual_server_wrap_mt.h" -#include "servers/visual_server.h" - -#if defined(OPENGL_ENABLED) -#include "context_gl_osx.h" -#endif - -#if defined(VULKAN_ENABLED) -#include "drivers/vulkan/rendering_device_vulkan.h" -#include "platform/osx/vulkan_context_osx.h" -#endif - -#include <AppKit/AppKit.h> -#include <AppKit/NSCursor.h> -#include <ApplicationServices/ApplicationServices.h> -#include <CoreVideo/CoreVideo.h> - -#undef BitMap -#undef CursorShape class OS_OSX : public OS_Unix { -public: - struct KeyEvent { - unsigned int osx_state; - bool pressed; - bool echo; - bool raw; - uint32_t keycode; - uint32_t physical_keycode; - uint32_t unicode; - }; - - Vector<KeyEvent> key_event_buffer; - int key_event_pos; + virtual void delete_main_loop(); bool force_quit; - VisualServer *visual_server; - List<String> args; - MainLoop *main_loop; + JoypadOSX *joypad_osx; #ifdef COREAUDIO_ENABLED AudioDriverCoreAudio audio_driver; @@ -90,143 +53,27 @@ public: MIDIDriverCoreMidi midi_driver; #endif - InputDefault *input; - JoypadOSX *joypad_osx; - - /* objc */ - - CGEventSourceRef eventSource; - - void process_events(); - void process_key_events(); - - // pthread_key_t current; - bool mouse_grab; - Point2 mouse_pos; - - id delegate; - id window_delegate; - id window_object; - id window_view; - id autoreleasePool; - id cursor; - -#if defined(OPENGL_ENABLED) - ContextGL_OSX *context_gles2; -#endif - -#if defined(VULKAN_ENABLED) - VulkanContextOSX *context_vulkan; - RenderingDeviceVulkan *rendering_device_vulkan; -#endif - - bool layered_window; - - CursorShape cursor_shape; - NSCursor *cursors[CURSOR_MAX]; - Map<CursorShape, Vector<Variant>> cursors_cache; - MouseMode mouse_mode; - - String title; - bool minimized; - bool maximized; - bool zoomed; - bool resizable; - bool window_focused; - - Size2 window_size; - Rect2 restore_rect; - - String open_with_filename; - - Point2 im_position; - bool im_active; - String im_text; - Point2 im_selection; - - Size2 min_size; - Size2 max_size; - CrashHandler crash_handler; - float _mouse_scale(float p_scale) { - if (_display_scale() > 1.0) - return p_scale; - else - return 1.0; - } - - float _display_scale() const; - float _display_scale(id screen) const; - - void _update_window(); - - int video_driver_index; - virtual int get_current_video_driver() const; - - struct GlobalMenuItem { - String label; - Variant signal; - Variant meta; - - GlobalMenuItem() { - //NOP - } - - GlobalMenuItem(const String &p_label, const Variant &p_signal, const Variant &p_meta) { - label = p_label; - signal = p_signal; - meta = p_meta; - } - }; - - Map<String, Vector<GlobalMenuItem>> global_menus; + MainLoop *main_loop; - void _update_global_menu(); +public: + String open_with_filename; protected: virtual void initialize_core(); - virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual void initialize(); virtual void finalize(); + virtual void initialize_joypads(); + virtual void set_main_loop(MainLoop *p_main_loop); - virtual void delete_main_loop(); public: - static OS_OSX *singleton; - - void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta); - void global_menu_add_separator(const String &p_menu); - void global_menu_remove_item(const String &p_menu, int p_idx); - void global_menu_clear(const String &p_menu); - - void wm_minimized(bool p_minimized); - virtual String get_name() const; - virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); - virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false); - virtual void set_cursor_shape(CursorShape p_shape); - virtual CursorShape get_cursor_shape() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); - - virtual void set_mouse_show(bool p_show); - virtual void set_mouse_grab(bool p_grab); - virtual bool is_mouse_grab_enabled() const; - virtual void warp_mouse_position(const Point2 &p_to); - virtual Point2 get_mouse_position() const; - virtual int get_mouse_button_state() const; - void update_real_mouse_position(); - virtual void set_window_title(const String &p_title); - - virtual Size2 get_window_size() const; - virtual Size2 get_real_window_size() const; - - virtual void set_native_icon(const String &p_filename); - virtual void set_icon(const Ref<Image> &p_icon); - virtual MainLoop *get_main_loop() const; virtual String get_config_path() const; @@ -237,95 +84,24 @@ public: virtual String get_system_dir(SystemDir p_dir) const; - virtual bool can_draw() const; - - virtual void set_clipboard(const String &p_text); - virtual String get_clipboard() const; - - virtual void release_rendering_thread(); - virtual void make_rendering_thread(); - virtual void swap_buffers(); - Error shell_open(String p_uri); - void push_input(const Ref<InputEvent> &p_event); String get_locale() const; - virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0); - virtual VideoMode get_video_mode(int p_screen = 0) const; - virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; - virtual String get_executable_path() const; - virtual LatinKeyboardVariant get_latin_keyboard_variant() const; - - virtual void move_window_to_foreground(); - - virtual int get_screen_count() const; - virtual int get_current_screen() const; - virtual void set_current_screen(int p_screen); - virtual Point2 get_screen_position(int p_screen = -1) const; - virtual Size2 get_screen_size(int p_screen = -1) const; - virtual int get_screen_dpi(int p_screen = -1) const; - - virtual Point2 get_window_position() const; - virtual void set_window_position(const Point2 &p_position); - virtual Size2 get_max_window_size() const; - virtual Size2 get_min_window_size() const; - virtual void set_min_window_size(const Size2 p_size); - virtual void set_max_window_size(const Size2 p_size); - virtual void set_window_size(const Size2 p_size); - virtual void set_window_fullscreen(bool p_enabled); - virtual bool is_window_fullscreen() const; - virtual void set_window_resizable(bool p_enabled); - virtual bool is_window_resizable() const; - virtual void set_window_minimized(bool p_enabled); - virtual bool is_window_minimized() const; - virtual void set_window_maximized(bool p_enabled); - virtual bool is_window_maximized() const; - virtual void set_window_always_on_top(bool p_enabled); - virtual bool is_window_always_on_top() const; - virtual bool is_window_focused() const; - virtual void request_attention(); - virtual String get_joy_guid(int p_device) const; - - virtual void set_borderless_window(bool p_borderless); - virtual bool get_borderless_window(); - - virtual bool get_window_per_pixel_transparency_enabled() const; - virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); - - virtual void set_ime_active(const bool p_active); - virtual void set_ime_position(const Point2 &p_pos); - virtual Point2 get_ime_selection() const; - virtual String get_ime_text() const; - - virtual String get_unique_id() const; + virtual String get_unique_id() const; //++ virtual bool _check_internal_feature_support(const String &p_feature); - virtual void _set_use_vsync(bool p_enable); - //virtual bool is_vsync_enabled() const; - void run(); - void set_mouse_mode(MouseMode p_mode); - MouseMode get_mouse_mode() const; - void disable_crash_handler(); bool is_disable_crash_handler() const; virtual Error move_to_trash(const String &p_path); - void force_process_input(); - OS_OSX(); - -private: - Point2 get_native_screen_position(int p_screen) const; - Point2 get_native_window_position() const; - void set_native_window_position(const Point2 &p_position); - Point2 get_screens_origin() const; }; #endif diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 8ba8ca8a33..49cb056c9f 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -30,1668 +30,21 @@ #include "os_osx.h" -#include "core/os/keyboard.h" -#include "core/print_string.h" #include "core/version_generated.gen.h" -#include "dir_access_osx.h" - -#if defined(OPENGL_ENABLED) -#include "drivers/gles2/rasterizer_gles2.h" -#endif - -#if defined(VULKAN_ENABLED) -#include "servers/visual/rasterizer_rd/rasterizer_rd.h" -#endif +#include "dir_access_osx.h" +#include "display_server_osx.h" #include "main/main.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" - -#include <mach-o/dyld.h> - -#include <Carbon/Carbon.h> -#import <Cocoa/Cocoa.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/hid/IOHIDKeys.h> -#include <IOKit/hid/IOHIDLib.h> -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 -#include <os/log.h> -#endif - -#import <QuartzCore/CAMetalLayer.h> -#include <vulkan/vulkan_metal.h> #include <dlfcn.h> -#include <fcntl.h> #include <libproc.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 -#define NSEventMaskAny NSAnyEventMask -#define NSEventTypeKeyDown NSKeyDown -#define NSEventTypeKeyUp NSKeyUp -#define NSEventModifierFlagShift NSShiftKeyMask -#define NSEventModifierFlagCommand NSCommandKeyMask -#define NSEventModifierFlagControl NSControlKeyMask -#define NSEventModifierFlagOption NSAlternateKeyMask -#define NSWindowStyleMaskTitled NSTitledWindowMask -#define NSWindowStyleMaskResizable NSResizableWindowMask -#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask -#define NSWindowStyleMaskClosable NSClosableWindowMask -#define NSWindowStyleMaskBorderless NSBorderlessWindowMask -#endif - -#ifndef NSAppKitVersionNumber10_12 -#define NSAppKitVersionNumber10_12 1504 -#endif -#ifndef NSAppKitVersionNumber10_14 -#define NSAppKitVersionNumber10_14 1671 -#endif - -static void get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> state) { - - state->set_shift((p_osx_state & NSEventModifierFlagShift)); - state->set_control((p_osx_state & NSEventModifierFlagControl)); - state->set_alt((p_osx_state & NSEventModifierFlagOption)); - state->set_metakey((p_osx_state & NSEventModifierFlagCommand)); -} - -static void push_to_key_event_buffer(const OS_OSX::KeyEvent &p_event) { - - Vector<OS_OSX::KeyEvent> &buffer = OS_OSX::singleton->key_event_buffer; - if (OS_OSX::singleton->key_event_pos >= buffer.size()) { - buffer.resize(1 + OS_OSX::singleton->key_event_pos); - } - buffer.write[OS_OSX::singleton->key_event_pos++] = p_event; -} - -static int mouse_x = 0; -static int mouse_y = 0; -static int button_mask = 0; -static bool mouse_down_control = false; - -static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFactor) { - - const NSRect contentRect = [OS_OSX::singleton->window_view frame]; - const NSPoint p = locationInWindow; - const float s = OS_OSX::singleton->_mouse_scale(backingScaleFactor); - mouse_x = p.x * s; - mouse_y = (contentRect.size.height - p.y) * s; - return Vector2(mouse_x, mouse_y); -} - -static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) { - if ([NSCursor respondsToSelector:selector]) { - id object = [NSCursor performSelector:selector]; - if ([object isKindOfClass:[NSCursor class]]) { - return object; - } - } - if (fallback) { - // Fallback should be a reasonable default, no need to check. - return [NSCursor performSelector:fallback]; - } - return [NSCursor arrowCursor]; -} - -@interface GodotApplication : NSApplication -@end - -@implementation GodotApplication - -- (void)sendEvent:(NSEvent *)event { - - // special case handling of command-period, which is traditionally a special - // shortcut in macOS and doesn't arrive at our regular keyDown handler. - if ([event type] == NSEventTypeKeyDown) { - if (([event modifierFlags] & NSEventModifierFlagCommand) && [event keyCode] == 0x2f) { - - Ref<InputEventKey> k; - k.instance(); - - get_key_modifier_state([event modifierFlags], k); - k->set_pressed(true); - k->set_keycode(KEY_PERIOD); - k->set_physical_keycode(KEY_PERIOD); - k->set_echo([event isARepeat]); - - OS_OSX::singleton->push_input(k); - } - } - - // From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost - // This works around an AppKit bug, where key up events while holding - // down the command key don't get sent to the key window. - if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) - [[self keyWindow] sendEvent:event]; - else - [super sendEvent:event]; -} - -@end - -@interface GodotApplicationDelegate : NSObject -- (void)forceUnbundledWindowActivationHackStep1; -- (void)forceUnbundledWindowActivationHackStep2; -- (void)forceUnbundledWindowActivationHackStep3; -@end - -@implementation GodotApplicationDelegate - -- (void)forceUnbundledWindowActivationHackStep1 { - // Step1: Switch focus to macOS Dock. - // Required to perform step 2, TransformProcessType will fail if app is already the in focus. - for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) { - [app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; - break; - } - [self performSelector:@selector(forceUnbundledWindowActivationHackStep2) withObject:nil afterDelay:0.02]; -} - -- (void)forceUnbundledWindowActivationHackStep2 { - // Step 2: Register app as foreground process. - ProcessSerialNumber psn = { 0, kCurrentProcess }; - (void)TransformProcessType(&psn, kProcessTransformToForegroundApplication); - - [self performSelector:@selector(forceUnbundledWindowActivationHackStep3) withObject:nil afterDelay:0.02]; -} - -- (void)forceUnbundledWindowActivationHackStep3 { - // Step 3: Switch focus back to app window. - [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)notice { - NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; - if (nsappname == nil) { - // If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored). - [self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02]; - } -} - -- (void)globalMenuCallback:(id)sender { - - if (![sender representedObject]) - return; - - OS_OSX::GlobalMenuItem *item = (OS_OSX::GlobalMenuItem *)[[sender representedObject] pointerValue]; - - if (!item) - return; - - OS_OSX::singleton->main_loop->global_menu_action(item->signal, item->meta); -} - -- (NSMenu *)applicationDockMenu:(NSApplication *)sender { - - NSMenu *menu = [[[NSMenu alloc] initWithTitle:@""] autorelease]; - - Vector<OS_OSX::GlobalMenuItem> &E = OS_OSX::singleton->global_menus["_dock"]; - for (int i = 0; i < E.size(); i++) { - if (E[i].label == String()) { - [menu addItem:[NSMenuItem separatorItem]]; - } else { - NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:E[i].label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:@""]; - [menu_item setRepresentedObject:[NSValue valueWithPointer:&(E[i])]]; - } - } - - return menu; -} - -- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { - // Note: may be called called before main loop init! - char *utfs = strdup([filename UTF8String]); - OS_OSX::singleton->open_with_filename.parse_utf8(utfs); - free(utfs); - -#ifdef TOOLS_ENABLED - // Open new instance - if (OS_OSX::singleton->get_main_loop()) { - List<String> args; - args.push_back(OS_OSX::singleton->open_with_filename); - String exec = OS::get_singleton()->get_executable_path(); - - OS::ProcessID pid = 0; - OS::get_singleton()->execute(exec, args, false, &pid); - } -#endif - return YES; -} - -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); - - return NSTerminateCancel; -} - -- (void)showAbout:(id)sender { - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT); -} - -@end - -@interface GodotWindowDelegate : NSObject { - //_Godotwindow* window; -} - -- (void)windowWillClose:(NSNotification *)notification; - -@end - -@implementation GodotWindowDelegate - -- (BOOL)windowShouldClose:(id)sender { - //_GodotInputWindowCloseRequest(window); - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); - - return NO; -} - -- (void)windowWillClose:(NSNotification *)notification { -#if defined(VULKAN_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { - - if (OS_OSX::singleton->rendering_device_vulkan) { - OS_OSX::singleton->rendering_device_vulkan->finalize(); - memdelete(OS_OSX::singleton->rendering_device_vulkan); - OS_OSX::singleton->rendering_device_vulkan = NULL; - } - - if (OS_OSX::singleton->context_vulkan) { - memdelete(OS_OSX::singleton->context_vulkan); - OS_OSX::singleton->context_vulkan = NULL; - } - } -#endif -} - -- (void)windowDidEnterFullScreen:(NSNotification *)notification { - OS_OSX::singleton->zoomed = true; - - [OS_OSX::singleton->window_object setContentMinSize:NSMakeSize(0, 0)]; - [OS_OSX::singleton->window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; -} - -- (void)windowDidExitFullScreen:(NSNotification *)notification { - OS_OSX::singleton->zoomed = false; - - if (OS_OSX::singleton->min_size != Size2()) { - Size2 size = OS_OSX::singleton->min_size / OS_OSX::singleton->_display_scale(); - [OS_OSX::singleton->window_object setContentMinSize:NSMakeSize(size.x, size.y)]; - } - if (OS_OSX::singleton->max_size != Size2()) { - Size2 size = OS_OSX::singleton->max_size / OS_OSX::singleton->_display_scale(); - [OS_OSX::singleton->window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; - } - - if (!OS_OSX::singleton->resizable) - [OS_OSX::singleton->window_object setStyleMask:[OS_OSX::singleton->window_object styleMask] & ~NSWindowStyleMaskResizable]; -} - -- (void)windowDidChangeBackingProperties:(NSNotification *)notification { - if (!OS_OSX::singleton) - return; - - NSWindow *window = (NSWindow *)[notification object]; - CGFloat newBackingScaleFactor = [window backingScaleFactor]; - CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - -#if defined(OPENGL_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) { - if (OS_OSX::singleton->is_hidpi_allowed()) { - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; - } else { - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:NO]; - } - } -#endif - - if (newBackingScaleFactor != oldBackingScaleFactor) { - //Set new display scale and window size - float newDisplayScale = OS_OSX::singleton->is_hidpi_allowed() ? newBackingScaleFactor : 1.0; - - const NSRect contentRect = [OS_OSX::singleton->window_view frame]; - const NSRect fbRect = contentRect; - - OS_OSX::singleton->window_size.width = fbRect.size.width * newDisplayScale; - OS_OSX::singleton->window_size.height = fbRect.size.height * newDisplayScale; - -#if defined(VULKAN_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { - CALayer *layer = [OS_OSX::singleton->window_view layer]; - layer.contentsScale = OS_OSX::singleton->_display_scale(); - } -#endif - //Update context - if (OS_OSX::singleton->main_loop) { - //Force window resize event - [self windowDidResize:notification]; - } - } -} - -- (void)windowDidResize:(NSNotification *)notification { - -#if defined(OPENGL_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) { - OS_OSX::singleton->context_gles2->update(); - } -#endif - const NSRect contentRect = [OS_OSX::singleton->window_view frame]; - const NSRect fbRect = contentRect; - - float displayScale = OS_OSX::singleton->_display_scale(); - OS_OSX::singleton->window_size.width = fbRect.size.width * displayScale; - OS_OSX::singleton->window_size.height = fbRect.size.height * displayScale; - -#if defined(VULKAN_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { - CALayer *layer = [OS_OSX::singleton->window_view layer]; - layer.contentsScale = OS_OSX::singleton->_display_scale(); - OS_OSX::singleton->context_vulkan->window_resize(0, OS_OSX::singleton->window_size.width, OS_OSX::singleton->window_size.height); - } -#endif - - if (OS_OSX::singleton->main_loop) { - Main::force_redraw(); - //Event retrieval blocks until resize is over. Call Main::iteration() directly. - if (!Main::is_iterating()) { //avoid cyclic loop - Main::iteration(); - } - } -} - -- (void)windowDidMove:(NSNotification *)notification { - - if (OS_OSX::singleton->get_main_loop()) { - OS_OSX::singleton->input->release_pressed_events(); - } -} - -- (void)windowDidBecomeKey:(NSNotification *)notification { - if (OS_OSX::singleton->get_main_loop()) { - get_mouse_pos( - [OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream], - [OS_OSX::singleton->window_view backingScaleFactor]); - OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y)); - - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); - } - - OS_OSX::singleton->window_focused = true; -} - -- (void)windowDidResignKey:(NSNotification *)notification { - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); - - OS_OSX::singleton->window_focused = false; -} - -- (void)windowDidMiniaturize:(NSNotification *)notification { - OS_OSX::singleton->wm_minimized(true); - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); - - OS_OSX::singleton->window_focused = false; -}; - -- (void)windowDidDeminiaturize:(NSNotification *)notification { - OS_OSX::singleton->wm_minimized(false); - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); - - OS_OSX::singleton->window_focused = true; -}; - -@end - -@interface GodotContentView : NSView <NSTextInputClient> { - NSTrackingArea *trackingArea; - NSMutableAttributedString *markedText; - bool imeInputEventInProgress; -} -- (void)cancelComposition; - -- (CALayer *)makeBackingLayer; - -- (BOOL)wantsUpdateLayer; -- (void)updateLayer; - -@end - -@implementation GodotContentView - -+ (void)initialize { - if (self == [GodotContentView class]) { - // nothing left to do here at the moment.. - } -} - -- (CALayer *)makeBackingLayer { -#if defined(VULKAN_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { - CALayer *layer = [[CAMetalLayer class] layer]; - layer.contentsScale = OS_OSX::singleton->_display_scale(); - return layer; - } -#endif - return [super makeBackingLayer]; -} - -- (void)updateLayer { -#if defined(VULKAN_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) { - [super updateLayer]; - } -#endif -#if defined(OPENGL_ENABLED) - if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) { - OS_OSX::singleton->context_gles2->update(); - } -#endif -} - -- (BOOL)wantsUpdateLayer { - return YES; -} - -- (id)init { - self = [super init]; - trackingArea = nil; - imeInputEventInProgress = false; - [self updateTrackingAreas]; - [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; - markedText = [[NSMutableAttributedString alloc] init]; - return self; -} - -- (void)dealloc { - [trackingArea release]; - [markedText release]; - [super dealloc]; -} - -static const NSRange kEmptyRange = { NSNotFound, 0 }; - -- (BOOL)hasMarkedText { - return (markedText.length > 0); -} - -- (NSRange)markedRange { - return NSMakeRange(0, markedText.length); -} - -- (NSRange)selectedRange { - return kEmptyRange; -} - -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { - if ([aString isKindOfClass:[NSAttributedString class]]) { - [markedText initWithAttributedString:aString]; - } else { - [markedText initWithString:aString]; - } - if (markedText.length == 0) { - [self unmarkText]; - return; - } - if (OS_OSX::singleton->im_active) { - imeInputEventInProgress = true; - OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]); - OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length); - - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); - } -} - -- (void)doCommandBySelector:(SEL)aSelector { - if ([self respondsToSelector:aSelector]) - [self performSelector:aSelector]; -} - -- (void)unmarkText { - imeInputEventInProgress = false; - [[markedText mutableString] setString:@""]; - if (OS_OSX::singleton->im_active) { - OS_OSX::singleton->im_text = String(); - OS_OSX::singleton->im_selection = Point2(); - - if (OS_OSX::singleton->get_main_loop()) - OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); - } -} - -- (NSArray *)validAttributesForMarkedText { - return [NSArray array]; -} - -- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { - return nil; -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { - return 0; -} - -- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { - const NSRect contentRect = [OS_OSX::singleton->window_view frame]; - float displayScale = OS_OSX::singleton->_display_scale(); - NSRect pointInWindowRect = NSMakeRect(OS_OSX::singleton->im_position.x / displayScale, contentRect.size.height - (OS_OSX::singleton->im_position.y / displayScale) - 1, 0, 0); - NSPoint pointOnScreen = [[OS_OSX::singleton->window_view window] convertRectToScreen:pointInWindowRect].origin; - - return NSMakeRect(pointOnScreen.x, pointOnScreen.y, 0, 0); -} - -- (void)cancelComposition { - [self unmarkText]; - NSTextInputContext *currentInputContext = [NSTextInputContext currentInputContext]; - [currentInputContext discardMarkedText]; -} - -- (void)insertText:(id)aString { - [self insertText:aString replacementRange:NSMakeRange(0, 0)]; -} - -- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { - NSEvent *event = [NSApp currentEvent]; - - NSString *characters; - if ([aString isKindOfClass:[NSAttributedString class]]) { - characters = [aString string]; - } else { - characters = (NSString *)aString; - } - - NSUInteger i, length = [characters length]; - - NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet]; - NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet]; - if ([characters rangeOfCharacterFromSet:ctrlChars].length && [characters rangeOfCharacterFromSet:wsnlChars].length == 0) { - NSTextInputContext *currentInputContext = [NSTextInputContext currentInputContext]; - [currentInputContext discardMarkedText]; - [self cancelComposition]; - return; - } - - for (i = 0; i < length; i++) { - const unichar codepoint = [characters characterAtIndex:i]; - if ((codepoint & 0xFF00) == 0xF700) - continue; - - OS_OSX::KeyEvent ke; - - ke.osx_state = [event modifierFlags]; - ke.pressed = true; - ke.echo = false; - ke.raw = false; // IME input event - ke.keycode = 0; - ke.physical_keycode = 0; - ke.unicode = codepoint; - - push_to_key_event_buffer(ke); - } - [self cancelComposition]; -} - -- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender { - return NSDragOperationCopy; -} - -- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender { - return NSDragOperationCopy; -} - -- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender { - - NSPasteboard *pboard = [sender draggingPasteboard]; - NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; - - Vector<String> files; - for (NSUInteger i = 0; i < filenames.count; i++) { - NSString *ns = [filenames objectAtIndex:i]; - char *utfs = strdup([ns UTF8String]); - String ret; - ret.parse_utf8(utfs); - free(utfs); - files.push_back(ret); - } - - if (files.size()) { - OS_OSX::singleton->main_loop->drop_files(files, 0); - OS_OSX::singleton->move_window_to_foreground(); - } - - return NO; -} - -- (BOOL)isOpaque { - return YES; -} - -- (BOOL)canBecomeKeyView { - return YES; -} - -- (BOOL)acceptsFirstResponder { - return YES; -} - -- (void)cursorUpdate:(NSEvent *)event { - OS::CursorShape p_shape = OS_OSX::singleton->cursor_shape; - OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX; - OS_OSX::singleton->set_cursor_shape(p_shape); -} - -static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { - if (pressed) { - button_mask |= mask; - } else { - button_mask &= ~mask; - } - - Ref<InputEventMouseButton> mb; - mb.instance(); - const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; - const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor); - get_key_modifier_state([event modifierFlags], mb); - mb->set_button_index(index); - mb->set_pressed(pressed); - mb->set_position(pos); - mb->set_global_position(pos); - mb->set_button_mask(button_mask); - if (index == BUTTON_LEFT && pressed) { - mb->set_doubleclick([event clickCount] == 2); - } - OS_OSX::singleton->push_input(mb); -} - -- (void)mouseDown:(NSEvent *)event { - if (([event modifierFlags] & NSEventModifierFlagControl)) { - mouse_down_control = true; - _mouseDownEvent(event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true); - } else { - mouse_down_control = false; - _mouseDownEvent(event, BUTTON_LEFT, BUTTON_MASK_LEFT, true); - } -} - -- (void)mouseDragged:(NSEvent *)event { - [self mouseMoved:event]; -} - -- (void)mouseUp:(NSEvent *)event { - if (mouse_down_control) { - _mouseDownEvent(event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false); - } else { - _mouseDownEvent(event, BUTTON_LEFT, BUTTON_MASK_LEFT, false); - } -} - -- (void)mouseMoved:(NSEvent *)event { - - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_button_mask(button_mask); - const CGFloat backingScaleFactor = [[event window] backingScaleFactor]; - const Vector2 pos = get_mouse_pos([event locationInWindow], backingScaleFactor); - mm->set_position(pos); - mm->set_pressure([event pressure]); - if ([event subtype] == NSEventSubtypeTabletPoint) { - const NSPoint p = [event tilt]; - mm->set_tilt(Vector2(p.x, p.y)); - } - mm->set_global_position(pos); - mm->set_speed(OS_OSX::singleton->input->get_last_mouse_speed()); - Vector2 relativeMotion = Vector2(); - relativeMotion.x = [event deltaX] * OS_OSX::singleton -> _mouse_scale(backingScaleFactor); - relativeMotion.y = [event deltaY] * OS_OSX::singleton -> _mouse_scale(backingScaleFactor); - mm->set_relative(relativeMotion); - get_key_modifier_state([event modifierFlags], mm); - - OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y)); - OS_OSX::singleton->push_input(mm); -} - -- (void)rightMouseDown:(NSEvent *)event { - _mouseDownEvent(event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, true); -} - -- (void)rightMouseDragged:(NSEvent *)event { - [self mouseMoved:event]; -} - -- (void)rightMouseUp:(NSEvent *)event { - _mouseDownEvent(event, BUTTON_RIGHT, BUTTON_MASK_RIGHT, false); -} - -- (void)otherMouseDown:(NSEvent *)event { - - if ((int)[event buttonNumber] == 2) { - _mouseDownEvent(event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, true); - - } else if ((int)[event buttonNumber] == 3) { - _mouseDownEvent(event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, true); - - } else if ((int)[event buttonNumber] == 4) { - _mouseDownEvent(event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, true); - - } else { - return; - } -} - -- (void)otherMouseDragged:(NSEvent *)event { - [self mouseMoved:event]; -} - -- (void)otherMouseUp:(NSEvent *)event { - - if ((int)[event buttonNumber] == 2) { - _mouseDownEvent(event, BUTTON_MIDDLE, BUTTON_MASK_MIDDLE, false); - - } else if ((int)[event buttonNumber] == 3) { - _mouseDownEvent(event, BUTTON_XBUTTON1, BUTTON_MASK_XBUTTON1, false); - - } else if ((int)[event buttonNumber] == 4) { - _mouseDownEvent(event, BUTTON_XBUTTON2, BUTTON_MASK_XBUTTON2, false); - - } else { - return; - } -} - -- (void)mouseExited:(NSEvent *)event { - if (!OS_OSX::singleton) - return; - - if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED) - OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT); -} - -- (void)mouseEntered:(NSEvent *)event { - if (!OS_OSX::singleton) - return; - if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED) - OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); - - OS::CursorShape p_shape = OS_OSX::singleton->cursor_shape; - OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX; - OS_OSX::singleton->set_cursor_shape(p_shape); -} - -- (void)magnifyWithEvent:(NSEvent *)event { - Ref<InputEventMagnifyGesture> ev; - ev.instance(); - get_key_modifier_state([event modifierFlags], ev); - ev->set_position(get_mouse_pos([event locationInWindow], [[event window] backingScaleFactor])); - ev->set_factor([event magnification] + 1.0); - OS_OSX::singleton->push_input(ev); -} - -- (void)viewDidChangeBackingProperties { - // nothing left to do here -} - -- (void)updateTrackingAreas { - if (trackingArea != nil) { - [self removeTrackingArea:trackingArea]; - [trackingArea release]; - } - - NSTrackingAreaOptions options = - NSTrackingMouseEnteredAndExited | - NSTrackingActiveInKeyWindow | - NSTrackingCursorUpdate | - NSTrackingInVisibleRect; - - trackingArea = [[NSTrackingArea alloc] - initWithRect:[self bounds] - options:options - owner:self - userInfo:nil]; - - [self addTrackingArea:trackingArea]; - [super updateTrackingAreas]; -} - -static bool isNumpadKey(unsigned int key) { - - static const unsigned int table[] = { - 0x41, /* kVK_ANSI_KeypadDecimal */ - 0x43, /* kVK_ANSI_KeypadMultiply */ - 0x45, /* kVK_ANSI_KeypadPlus */ - 0x47, /* kVK_ANSI_KeypadClear */ - 0x4b, /* kVK_ANSI_KeypadDivide */ - 0x4c, /* kVK_ANSI_KeypadEnter */ - 0x4e, /* kVK_ANSI_KeypadMinus */ - 0x51, /* kVK_ANSI_KeypadEquals */ - 0x52, /* kVK_ANSI_Keypad0 */ - 0x53, /* kVK_ANSI_Keypad1 */ - 0x54, /* kVK_ANSI_Keypad2 */ - 0x55, /* kVK_ANSI_Keypad3 */ - 0x56, /* kVK_ANSI_Keypad4 */ - 0x57, /* kVK_ANSI_Keypad5 */ - 0x58, /* kVK_ANSI_Keypad6 */ - 0x59, /* kVK_ANSI_Keypad7 */ - 0x5b, /* kVK_ANSI_Keypad8 */ - 0x5c, /* kVK_ANSI_Keypad9 */ - 0x5f, /* kVK_JIS_KeypadComma */ - 0x00 - }; - for (int i = 0; table[i] != 0; i++) { - if (key == table[i]) - return true; - } - return false; -} - -// Translates a OS X keycode to a Godot keycode -// -static int translateKey(unsigned int key) { - - // Keyboard symbol translation table - static const unsigned int table[128] = { - /* 00 */ KEY_A, - /* 01 */ KEY_S, - /* 02 */ KEY_D, - /* 03 */ KEY_F, - /* 04 */ KEY_H, - /* 05 */ KEY_G, - /* 06 */ KEY_Z, - /* 07 */ KEY_X, - /* 08 */ KEY_C, - /* 09 */ KEY_V, - /* 0a */ KEY_SECTION, /* ISO Section */ - /* 0b */ KEY_B, - /* 0c */ KEY_Q, - /* 0d */ KEY_W, - /* 0e */ KEY_E, - /* 0f */ KEY_R, - /* 10 */ KEY_Y, - /* 11 */ KEY_T, - /* 12 */ KEY_1, - /* 13 */ KEY_2, - /* 14 */ KEY_3, - /* 15 */ KEY_4, - /* 16 */ KEY_6, - /* 17 */ KEY_5, - /* 18 */ KEY_EQUAL, - /* 19 */ KEY_9, - /* 1a */ KEY_7, - /* 1b */ KEY_MINUS, - /* 1c */ KEY_8, - /* 1d */ KEY_0, - /* 1e */ KEY_BRACERIGHT, - /* 1f */ KEY_O, - /* 20 */ KEY_U, - /* 21 */ KEY_BRACELEFT, - /* 22 */ KEY_I, - /* 23 */ KEY_P, - /* 24 */ KEY_ENTER, - /* 25 */ KEY_L, - /* 26 */ KEY_J, - /* 27 */ KEY_APOSTROPHE, - /* 28 */ KEY_K, - /* 29 */ KEY_SEMICOLON, - /* 2a */ KEY_BACKSLASH, - /* 2b */ KEY_COMMA, - /* 2c */ KEY_SLASH, - /* 2d */ KEY_N, - /* 2e */ KEY_M, - /* 2f */ KEY_PERIOD, - /* 30 */ KEY_TAB, - /* 31 */ KEY_SPACE, - /* 32 */ KEY_QUOTELEFT, - /* 33 */ KEY_BACKSPACE, - /* 34 */ KEY_UNKNOWN, - /* 35 */ KEY_ESCAPE, - /* 36 */ KEY_META, - /* 37 */ KEY_META, - /* 38 */ KEY_SHIFT, - /* 39 */ KEY_CAPSLOCK, - /* 3a */ KEY_ALT, - /* 3b */ KEY_CONTROL, - /* 3c */ KEY_SHIFT, - /* 3d */ KEY_ALT, - /* 3e */ KEY_CONTROL, - /* 3f */ KEY_UNKNOWN, /* Function */ - /* 40 */ KEY_UNKNOWN, /* F17 */ - /* 41 */ KEY_KP_PERIOD, - /* 42 */ KEY_UNKNOWN, - /* 43 */ KEY_KP_MULTIPLY, - /* 44 */ KEY_UNKNOWN, - /* 45 */ KEY_KP_ADD, - /* 46 */ KEY_UNKNOWN, - /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */ - /* 48 */ KEY_VOLUMEUP, /* VolumeUp */ - /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */ - /* 4a */ KEY_VOLUMEMUTE, /* Mute */ - /* 4b */ KEY_KP_DIVIDE, - /* 4c */ KEY_KP_ENTER, - /* 4d */ KEY_UNKNOWN, - /* 4e */ KEY_KP_SUBTRACT, - /* 4f */ KEY_UNKNOWN, /* F18 */ - /* 50 */ KEY_UNKNOWN, /* F19 */ - /* 51 */ KEY_EQUAL, /* KeypadEqual */ - /* 52 */ KEY_KP_0, - /* 53 */ KEY_KP_1, - /* 54 */ KEY_KP_2, - /* 55 */ KEY_KP_3, - /* 56 */ KEY_KP_4, - /* 57 */ KEY_KP_5, - /* 58 */ KEY_KP_6, - /* 59 */ KEY_KP_7, - /* 5a */ KEY_UNKNOWN, /* F20 */ - /* 5b */ KEY_KP_8, - /* 5c */ KEY_KP_9, - /* 5d */ KEY_YEN, /* JIS Yen */ - /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */ - /* 5f */ KEY_COMMA, /* JIS KeypadComma */ - /* 60 */ KEY_F5, - /* 61 */ KEY_F6, - /* 62 */ KEY_F7, - /* 63 */ KEY_F3, - /* 64 */ KEY_F8, - /* 65 */ KEY_F9, - /* 66 */ KEY_UNKNOWN, /* JIS Eisu */ - /* 67 */ KEY_F11, - /* 68 */ KEY_UNKNOWN, /* JIS Kana */ - /* 69 */ KEY_F13, - /* 6a */ KEY_F16, - /* 6b */ KEY_F14, - /* 6c */ KEY_UNKNOWN, - /* 6d */ KEY_F10, - /* 6e */ KEY_MENU, - /* 6f */ KEY_F12, - /* 70 */ KEY_UNKNOWN, - /* 71 */ KEY_F15, - /* 72 */ KEY_INSERT, /* Really Help... */ - /* 73 */ KEY_HOME, - /* 74 */ KEY_PAGEUP, - /* 75 */ KEY_DELETE, - /* 76 */ KEY_F4, - /* 77 */ KEY_END, - /* 78 */ KEY_F2, - /* 79 */ KEY_PAGEDOWN, - /* 7a */ KEY_F1, - /* 7b */ KEY_LEFT, - /* 7c */ KEY_RIGHT, - /* 7d */ KEY_DOWN, - /* 7e */ KEY_UP, - /* 7f */ KEY_UNKNOWN, - }; - - if (key >= 128) - return KEY_UNKNOWN; - - return table[key]; -} - -struct _KeyCodeMap { - UniChar kchar; - int kcode; -}; - -static const _KeyCodeMap _keycodes[55] = { - { '`', KEY_QUOTELEFT }, - { '~', KEY_ASCIITILDE }, - { '0', KEY_0 }, - { '1', KEY_1 }, - { '2', KEY_2 }, - { '3', KEY_3 }, - { '4', KEY_4 }, - { '5', KEY_5 }, - { '6', KEY_6 }, - { '7', KEY_7 }, - { '8', KEY_8 }, - { '9', KEY_9 }, - { '-', KEY_MINUS }, - { '_', KEY_UNDERSCORE }, - { '=', KEY_EQUAL }, - { '+', KEY_PLUS }, - { 'q', KEY_Q }, - { 'w', KEY_W }, - { 'e', KEY_E }, - { 'r', KEY_R }, - { 't', KEY_T }, - { 'y', KEY_Y }, - { 'u', KEY_U }, - { 'i', KEY_I }, - { 'o', KEY_O }, - { 'p', KEY_P }, - { '[', KEY_BRACELEFT }, - { ']', KEY_BRACERIGHT }, - { '{', KEY_BRACELEFT }, - { '}', KEY_BRACERIGHT }, - { 'a', KEY_A }, - { 's', KEY_S }, - { 'd', KEY_D }, - { 'f', KEY_F }, - { 'g', KEY_G }, - { 'h', KEY_H }, - { 'j', KEY_J }, - { 'k', KEY_K }, - { 'l', KEY_L }, - { ';', KEY_SEMICOLON }, - { ':', KEY_COLON }, - { '\'', KEY_APOSTROPHE }, - { '\"', KEY_QUOTEDBL }, - { '\\', KEY_BACKSLASH }, - { '#', KEY_NUMBERSIGN }, - { 'z', KEY_Z }, - { 'x', KEY_X }, - { 'c', KEY_C }, - { 'v', KEY_V }, - { 'b', KEY_B }, - { 'n', KEY_N }, - { 'm', KEY_M }, - { ',', KEY_COMMA }, - { '.', KEY_PERIOD }, - { '/', KEY_SLASH } -}; - -static int remapKey(unsigned int key, unsigned int state) { - - if (isNumpadKey(key)) - return translateKey(key); - - TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); - if (!currentKeyboard) - return translateKey(key); - - CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); - if (!layoutData) - return translateKey(key); - - const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); - - UInt32 keysDown = 0; - UniChar chars[4]; - UniCharCount realLength; - - OSStatus err = UCKeyTranslate(keyboardLayout, - key, - kUCKeyActionDisplay, - (state >> 8) & 0xFF, - LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &keysDown, - sizeof(chars) / sizeof(chars[0]), - &realLength, - chars); - - if (err != noErr) { - return translateKey(key); - } - - for (unsigned int i = 0; i < 55; i++) { - if (_keycodes[i].kchar == chars[0]) { - return _keycodes[i].kcode; - } - } - return translateKey(key); -} - -- (void)keyDown:(NSEvent *)event { - - // Ignore all input if IME input is in progress - if (!imeInputEventInProgress) { - NSString *characters = [event characters]; - NSUInteger length = [characters length]; - - if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) { - // Fallback unicode character handler used if IME is not active - for (NSUInteger i = 0; i < length; i++) { - OS_OSX::KeyEvent ke; - - ke.osx_state = [event modifierFlags]; - ke.pressed = true; - ke.echo = [event isARepeat]; - ke.keycode = remapKey([event keyCode], [event modifierFlags]); - ke.physical_keycode = translateKey([event keyCode]); - ke.raw = true; - ke.unicode = [characters characterAtIndex:i]; - - push_to_key_event_buffer(ke); - } - } else { - OS_OSX::KeyEvent ke; - - ke.osx_state = [event modifierFlags]; - ke.pressed = true; - ke.echo = [event isARepeat]; - ke.keycode = remapKey([event keyCode], [event modifierFlags]); - ke.physical_keycode = translateKey([event keyCode]); - ke.raw = false; - ke.unicode = 0; - - push_to_key_event_buffer(ke); - } - } - - // Pass events to IME handler - if (OS_OSX::singleton->im_active) - [self interpretKeyEvents:[NSArray arrayWithObject:event]]; -} - -- (void)flagsChanged:(NSEvent *)event { - - // Ignore all input if IME input is in progress - if (!imeInputEventInProgress) { - OS_OSX::KeyEvent ke; - - ke.echo = false; - ke.raw = true; - - int key = [event keyCode]; - int mod = [event modifierFlags]; - - if (key == 0x36 || key == 0x37) { - if (mod & NSEventModifierFlagCommand) { - mod &= ~NSEventModifierFlagCommand; - ke.pressed = true; - } else { - ke.pressed = false; - } - } else if (key == 0x38 || key == 0x3c) { - if (mod & NSEventModifierFlagShift) { - mod &= ~NSEventModifierFlagShift; - ke.pressed = true; - } else { - ke.pressed = false; - } - } else if (key == 0x3a || key == 0x3d) { - if (mod & NSEventModifierFlagOption) { - mod &= ~NSEventModifierFlagOption; - ke.pressed = true; - } else { - ke.pressed = false; - } - } else if (key == 0x3b || key == 0x3e) { - if (mod & NSEventModifierFlagControl) { - mod &= ~NSEventModifierFlagControl; - ke.pressed = true; - } else { - ke.pressed = false; - } - } else { - return; - } - - ke.osx_state = mod; - ke.keycode = remapKey(key, mod); - ke.physical_keycode = translateKey(key); - ke.unicode = 0; - - push_to_key_event_buffer(ke); - } -} - -- (void)keyUp:(NSEvent *)event { - - // Ignore all input if IME input is in progress - if (!imeInputEventInProgress) { - NSString *characters = [event characters]; - NSUInteger length = [characters length]; - - // Fallback unicode character handler used if IME is not active - if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) { - for (NSUInteger i = 0; i < length; i++) { - OS_OSX::KeyEvent ke; - - ke.osx_state = [event modifierFlags]; - ke.pressed = false; - ke.echo = [event isARepeat]; - ke.keycode = remapKey([event keyCode], [event modifierFlags]); - ke.physical_keycode = translateKey([event keyCode]); - ke.raw = true; - ke.unicode = [characters characterAtIndex:i]; - - push_to_key_event_buffer(ke); - } - } else { - OS_OSX::KeyEvent ke; - - ke.osx_state = [event modifierFlags]; - ke.pressed = false; - ke.echo = [event isARepeat]; - ke.keycode = remapKey([event keyCode], [event modifierFlags]); - ke.physical_keycode = translateKey([event keyCode]); - ke.raw = true; - ke.unicode = 0; - - push_to_key_event_buffer(ke); - } - } -} - -inline void sendScrollEvent(int button, double factor, int modifierFlags) { - - unsigned int mask = 1 << (button - 1); - Vector2 mouse_pos = Vector2(mouse_x, mouse_y); - - Ref<InputEventMouseButton> sc; - sc.instance(); - - get_key_modifier_state(modifierFlags, sc); - sc->set_button_index(button); - sc->set_factor(factor); - sc->set_pressed(true); - sc->set_position(mouse_pos); - sc->set_global_position(mouse_pos); - button_mask |= mask; - sc->set_button_mask(button_mask); - OS_OSX::singleton->push_input(sc); - - sc.instance(); - sc->set_button_index(button); - sc->set_factor(factor); - sc->set_pressed(false); - sc->set_position(mouse_pos); - sc->set_global_position(mouse_pos); - button_mask &= ~mask; - sc->set_button_mask(button_mask); - OS_OSX::singleton->push_input(sc); -} - -inline void sendPanEvent(double dx, double dy, int modifierFlags) { - - Ref<InputEventPanGesture> pg; - pg.instance(); - - get_key_modifier_state(modifierFlags, pg); - Vector2 mouse_pos = Vector2(mouse_x, mouse_y); - pg->set_position(mouse_pos); - pg->set_delta(Vector2(-dx, -dy)); - OS_OSX::singleton->push_input(pg); -} - -- (void)scrollWheel:(NSEvent *)event { - double deltaX, deltaY; - - get_mouse_pos([event locationInWindow], [[event window] backingScaleFactor]); - - deltaX = [event scrollingDeltaX]; - deltaY = [event scrollingDeltaY]; - - if ([event hasPreciseScrollingDeltas]) { - deltaX *= 0.03; - deltaY *= 0.03; - } - - if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) { - sendPanEvent(deltaX, deltaY, [event modifierFlags]); - } else { - if (fabs(deltaX)) { - sendScrollEvent(0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]); - } - if (fabs(deltaY)) { - sendScrollEvent(0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]); - } - } -} - -@end - -@interface GodotWindow : NSWindow { -} -@end - -@implementation GodotWindow - -- (BOOL)canBecomeKeyWindow { - // Required for NSBorderlessWindowMask windows - return YES; -} - -@end - -void OS_OSX::_update_global_menu() { - - NSMenu *main_menu = [NSApp mainMenu]; - - for (int i = 1; i < [main_menu numberOfItems]; i++) { - [main_menu removeItemAtIndex:i]; - } - for (Map<String, Vector<GlobalMenuItem>>::Element *E = global_menus.front(); E; E = E->next()) { - if (E->key() != "_dock") { - NSMenu *menu = [[[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:E->key().utf8().get_data()]] autorelease]; - for (int i = 0; i < E->get().size(); i++) { - if (E->get()[i].label == String()) { - [menu addItem:[NSMenuItem separatorItem]]; - } else { - NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:E->get()[i].label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:@""]; - [menu_item setRepresentedObject:[NSValue valueWithPointer:&(E->get()[i])]]; - } - } - NSMenuItem *menu_item = [main_menu addItemWithTitle:[NSString stringWithUTF8String:E->key().utf8().get_data()] action:nil keyEquivalent:@""]; - [main_menu setSubmenu:menu forItem:menu_item]; - } - } -} - -void OS_OSX::global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta) { - - global_menus[p_menu].push_back(GlobalMenuItem(p_label, p_signal, p_meta)); - _update_global_menu(); -} - -void OS_OSX::global_menu_add_separator(const String &p_menu) { - - global_menus[p_menu].push_back(GlobalMenuItem()); - _update_global_menu(); -} - -void OS_OSX::global_menu_remove_item(const String &p_menu, int p_idx) { - - ERR_FAIL_INDEX(p_idx, global_menus[p_menu].size()); - - global_menus[p_menu].remove(p_idx); - _update_global_menu(); -} - -void OS_OSX::global_menu_clear(const String &p_menu) { - - global_menus[p_menu].clear(); - _update_global_menu(); -} - -Point2 OS_OSX::get_ime_selection() const { - - return im_selection; -} - -String OS_OSX::get_ime_text() const { - - return im_text; -} - -String OS_OSX::get_unique_id() const { - - static String serial_number; - - if (serial_number.empty()) { - io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); - CFStringRef serialNumberAsCFString = NULL; - if (platformExpert) { - serialNumberAsCFString = (CFStringRef)IORegistryEntryCreateCFProperty(platformExpert, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0); - IOObjectRelease(platformExpert); - } - - NSString *serialNumberAsNSString = nil; - if (serialNumberAsCFString) { - serialNumberAsNSString = [NSString stringWithString:(NSString *)serialNumberAsCFString]; - CFRelease(serialNumberAsCFString); - } - - serial_number = [serialNumberAsNSString UTF8String]; - } - - return serial_number; -} - -void OS_OSX::set_ime_active(const bool p_active) { - - im_active = p_active; - if (!im_active) - [window_view cancelComposition]; -} - -void OS_OSX::set_ime_position(const Point2 &p_pos) { - - im_position = p_pos; -} - -void OS_OSX::initialize_core() { - - crash_handler.initialize(); - - OS_Unix::initialize_core(); - - DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_RESOURCES); - DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_USERDATA); - DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_FILESYSTEM); -} - -static bool keyboard_layout_dirty = true; -static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) { - keyboard_layout_dirty = true; -} - -static bool displays_arrangement_dirty = true; -static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) { - displays_arrangement_dirty = true; -} - -int OS_OSX::get_current_video_driver() const { - return video_driver_index; -} - -Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { - - /*** OSX INITIALIZATION ***/ - /*** OSX INITIALIZATION ***/ - /*** OSX INITIALIZATION ***/ - - keyboard_layout_dirty = true; - displays_arrangement_dirty = true; - - // Register to be notified on keyboard layout changes - CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), - NULL, keyboard_layout_changed, - kTISNotifySelectedKeyboardInputSourceChanged, NULL, - CFNotificationSuspensionBehaviorDeliverImmediately); - - // Register to be notified on displays arrangement changes - CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL); - - //!!!!!!!!!!!!!!!!!!!!!!!!!! - //TODO - do Vulkan and GLES2 support checks, driver selection and fallback - video_driver_index = p_video_driver; - print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]"); - //!!!!!!!!!!!!!!!!!!!!!!!!!! - - //Create window - - window_delegate = [[GodotWindowDelegate alloc] init]; - - // Don't use accumulation buffer support; it's not accelerated - // Aux buffers probably aren't accelerated either - - unsigned int styleMask; - - if (p_desired.borderless_window) { - styleMask = NSWindowStyleMaskBorderless; - } else { - resizable = p_desired.resizable; - styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (p_desired.resizable ? NSWindowStyleMaskResizable : 0); - } - - window_object = [[GodotWindow alloc] - initWithContentRect:NSMakeRect(0, 0, p_desired.width, p_desired.height) - styleMask:styleMask - backing:NSBackingStoreBuffered - defer:NO]; - - ERR_FAIL_COND_V(window_object == nil, ERR_UNAVAILABLE); - - window_view = [[GodotContentView alloc] init]; - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_14) { - [window_view setWantsLayer:TRUE]; - } - - float displayScale = 1.0; - if (is_hidpi_allowed()) { - // note that mainScreen is not screen #0 but the one with the keyboard focus. - NSScreen *screen = [NSScreen mainScreen]; - if ([screen respondsToSelector:@selector(backingScaleFactor)]) { - displayScale = fmax(displayScale, [screen backingScaleFactor]); - } - } - - window_size.width = p_desired.width * displayScale; - window_size.height = p_desired.height * displayScale; - - if (displayScale > 1.0) { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - [window_view setWantsBestResolutionOpenGLSurface:YES]; - } -#endif - [window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; - } else { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - [window_view setWantsBestResolutionOpenGLSurface:NO]; - } -#endif - } - - [window_object setContentView:window_view]; - [window_object setDelegate:window_delegate]; - [window_object setAcceptsMouseMovedEvents:YES]; - [(NSWindow *)window_object center]; - - [window_object setRestorable:NO]; - - // Init context and rendering device -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - context_gles2 = memnew(ContextGL_OSX(window_view, false)); - - if (context_gles2->initialize() != OK) { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - context_gles2->set_use_vsync(p_desired.use_vsync); - - if (RasterizerGLES2::is_viable() == OK) { - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); - } else { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - context_vulkan = memnew(VulkanContextOSX); - if (context_vulkan->initialize() != OK) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - if (context_vulkan->window_create(window_view, get_video_mode().width, get_video_mode().height) == -1) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - rendering_device_vulkan = memnew(RenderingDeviceVulkan); - rendering_device_vulkan->initialize(context_vulkan); - - RasterizerRD::make_current(); - } -#endif - - [NSApp activateIgnoringOtherApps:YES]; - - _update_window(); - - [window_object makeKeyAndOrderFront:nil]; - - if (p_desired.fullscreen) - zoomed = true; - - visual_server = memnew(VisualServerRaster); - if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); - } - - visual_server->init(); - AudioDriverManager::initialize(p_audio_driver); - - input = memnew(InputDefault); - joypad_osx = memnew(JoypadOSX); - - _ensure_user_data_dir(); - - restore_rect = Rect2(get_window_position(), get_window_size()); - - if (p_desired.layered) { - set_window_per_pixel_transparency_enabled(true); - } - - update_real_mouse_position(); - - return OK; -} - -void OS_OSX::finalize() { - -#ifdef COREMIDI_ENABLED - midi_driver.close(); -#endif - -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - if (context_gles2) - memdelete(context_gles2); - } -#endif - - CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); - CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL); - - delete_main_loop(); - - memdelete(joypad_osx); - memdelete(input); - - cursors_cache.clear(); - visual_server->finish(); - memdelete(visual_server); -} - -void OS_OSX::set_main_loop(MainLoop *p_main_loop) { - - main_loop = p_main_loop; - input->set_main_loop(p_main_loop); -} - -void OS_OSX::delete_main_loop() { - - if (!main_loop) - return; - memdelete(main_loop); - main_loop = NULL; -} - -String OS_OSX::get_name() const { +#include <mach-o/dyld.h> +#include <os/log.h> - return "OSX"; -} +/*************************************************************************/ +/* OSXTerminalLogger */ +/*************************************************************************/ -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 class OSXTerminalLogger : public StdLogger { public: virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR) { @@ -1747,333 +100,101 @@ public: } }; -#else - -typedef UnixTerminalLogger OSXTerminalLogger; -#endif - -void OS_OSX::alert(const String &p_alert, const String &p_title) { - // Set OS X-compliant variables - NSAlert *window = [[NSAlert alloc] init]; - NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()]; - NSString *ns_alert = [NSString stringWithUTF8String:p_alert.utf8().get_data()]; - - [window addButtonWithTitle:@"OK"]; - [window setMessageText:ns_title]; - [window setInformativeText:ns_alert]; - [window setAlertStyle:NSAlertStyleWarning]; - - // Display it, then release - [window runModal]; - [window release]; -} +/*************************************************************************/ +/* OS_OSX */ +/*************************************************************************/ -Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { +String OS_OSX::get_unique_id() const { + static String serial_number; - String path = p_path; + if (serial_number.empty()) { + io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); + CFStringRef serialNumberAsCFString = NULL; + if (platformExpert) { + serialNumberAsCFString = (CFStringRef)IORegistryEntryCreateCFProperty(platformExpert, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0); + IOObjectRelease(platformExpert); + } - if (!FileAccess::exists(path)) { - //this code exists so gdnative can load .dylib files from within the executable path - path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); - } + NSString *serialNumberAsNSString = nil; + if (serialNumberAsCFString) { + serialNumberAsNSString = [NSString stringWithString:(NSString *)serialNumberAsCFString]; + CFRelease(serialNumberAsCFString); + } - if (!FileAccess::exists(path)) { - //this code exists so gdnative can load .dylib files from a standard macOS location - path = get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file()); + serial_number = [serialNumberAsNSString UTF8String]; } - p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); - ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + "."); - return OK; + return serial_number; } -void OS_OSX::set_cursor_shape(CursorShape p_shape) { - - if (cursor_shape == p_shape) - return; - - if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { - cursor_shape = p_shape; - return; - } - - if (cursors[p_shape] != NULL) { - [cursors[p_shape] set]; - } else { - switch (p_shape) { - case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break; - case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break; - case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break; - case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break; - case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break; - case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break; - case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break; - case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break; - case CURSOR_FORBIDDEN: [[NSCursor operationNotAllowedCursor] set]; break; - case CURSOR_VSIZE: [cursorFromSelector(@selector(_windowResizeNorthSouthCursor), @selector(resizeUpDownCursor)) set]; break; - case CURSOR_HSIZE: [cursorFromSelector(@selector(_windowResizeEastWestCursor), @selector(resizeLeftRightCursor)) set]; break; - case CURSOR_BDIAGSIZE: [cursorFromSelector(@selector(_windowResizeNorthEastSouthWestCursor)) set]; break; - case CURSOR_FDIAGSIZE: [cursorFromSelector(@selector(_windowResizeNorthWestSouthEastCursor)) set]; break; - case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break; - case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break; - case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break; - case CURSOR_HELP: [cursorFromSelector(@selector(_helpCursor)) set]; break; - default: { - }; - } - } +void OS_OSX::initialize_core() { + OS_Unix::initialize_core(); - cursor_shape = p_shape; + DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_USERDATA); + DirAccess::make_default<DirAccessOSX>(DirAccess::ACCESS_FILESYSTEM); } -OS::CursorShape OS_OSX::get_cursor_shape() const { - - return cursor_shape; +void OS_OSX::initialize_joypads() { + joypad_osx = memnew(JoypadOSX(InputFilter::get_singleton())); } -void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { - - if (p_cursor.is_valid()) { - - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); - - if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { - set_cursor_shape(p_shape); - return; - } - - cursors_cache.erase(p_shape); - } - - Ref<Texture2D> texture = p_cursor; - Ref<AtlasTexture> atlas_texture = p_cursor; - Ref<Image> image; - Size2 texture_size; - Rect2 atlas_rect; - - if (texture.is_valid()) { - image = texture->get_data(); - } - - if (!image.is_valid() && atlas_texture.is_valid()) { - texture = atlas_texture->get_atlas(); - - atlas_rect.size.width = texture->get_width(); - atlas_rect.size.height = texture->get_height(); - atlas_rect.position.x = atlas_texture->get_region().position.x; - atlas_rect.position.y = atlas_texture->get_region().position.y; - - texture_size.width = atlas_texture->get_region().size.x; - texture_size.height = atlas_texture->get_region().size.y; - } else if (image.is_valid()) { - texture_size.width = texture->get_width(); - texture_size.height = texture->get_height(); - } - - ERR_FAIL_COND(!texture.is_valid()); - ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); - ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); - ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - - image = texture->get_data(); - - ERR_FAIL_COND(!image.is_valid()); - - NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:NULL - pixelsWide:int(texture_size.width) - pixelsHigh:int(texture_size.height) - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:int(texture_size.width) * 4 - bitsPerPixel:32]; - - ERR_FAIL_COND(imgrep == nil); - uint8_t *pixels = [imgrep bitmapData]; - - int len = int(texture_size.width * texture_size.height); - - for (int i = 0; i < len; i++) { - int row_index = floor(i / texture_size.width) + atlas_rect.position.y; - int column_index = (i % int(texture_size.width)) + atlas_rect.position.x; - - if (atlas_texture.is_valid()) { - column_index = MIN(column_index, atlas_rect.size.width - 1); - row_index = MIN(row_index, atlas_rect.size.height - 1); - } - - uint32_t color = image->get_pixel(column_index, row_index).to_argb32(); - - uint8_t alpha = (color >> 24) & 0xFF; - pixels[i * 4 + 0] = ((color >> 16) & 0xFF) * alpha / 255; - pixels[i * 4 + 1] = ((color >> 8) & 0xFF) * alpha / 255; - pixels[i * 4 + 2] = ((color)&0xFF) * alpha / 255; - pixels[i * 4 + 3] = alpha; - } - - NSImage *nsimage = [[NSImage alloc] initWithSize:NSMakeSize(texture_size.width, texture_size.height)]; - [nsimage addRepresentation:imgrep]; - - NSCursor *cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(p_hotspot.x, p_hotspot.y)]; - - [cursors[p_shape] release]; - cursors[p_shape] = cursor; - - Vector<Variant> params; - params.push_back(p_cursor); - params.push_back(p_hotspot); - cursors_cache.insert(p_shape, params); - - if (p_shape == cursor_shape) { - if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { - [cursor set]; - } - } - - [imgrep release]; - [nsimage release]; - } else { - // Reset to default system cursor - if (cursors[p_shape] != NULL) { - [cursors[p_shape] release]; - cursors[p_shape] = NULL; - } - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - - cursors_cache.erase(p_shape); - } -} - -void OS_OSX::set_mouse_show(bool p_show) { -} +void OS_OSX::initialize() { + crash_handler.initialize(); -void OS_OSX::set_mouse_grab(bool p_grab) { + initialize_core(); + //ensure_user_data_dir(); } -bool OS_OSX::is_mouse_grab_enabled() const { - - return mouse_grab; -} +void OS_OSX::finalize() { -void OS_OSX::warp_mouse_position(const Point2 &p_to) { - - //copied from windows impl with osx native calls - if (mouse_mode == MOUSE_MODE_CAPTURED) { - mouse_x = p_to.x; - mouse_y = p_to.y; - } else { //set OS position - - //local point in window coords - const NSRect contentRect = [window_view frame]; - float displayScale = _display_scale(); - NSRect pointInWindowRect = NSMakeRect(p_to.x / displayScale, contentRect.size.height - (p_to.y / displayScale) - 1, 0, 0); - NSPoint pointOnScreen = [[window_view window] convertRectToScreen:pointInWindowRect].origin; - - //point in scren coords - CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y }; - - //do the warping - CGEventSourceRef lEventRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); - CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0); - CGAssociateMouseAndMouseCursorPosition(false); - CGWarpMouseCursorPosition(lMouseWarpPos); - CGAssociateMouseAndMouseCursorPosition(true); - } -} +#ifdef COREMIDI_ENABLED + midi_driver.close(); +#endif -void OS_OSX::update_real_mouse_position() { + delete_main_loop(); - get_mouse_pos([window_object mouseLocationOutsideOfEventStream], [window_view backingScaleFactor]); - input->set_mouse_position(Point2(mouse_x, mouse_y)); + memdelete(joypad_osx); } -Point2 OS_OSX::get_mouse_position() const { - - return Vector2(mouse_x, mouse_y); +void OS_OSX::set_main_loop(MainLoop *p_main_loop) { + main_loop = p_main_loop; } -int OS_OSX::get_mouse_button_state() const { - return button_mask; +void OS_OSX::delete_main_loop() { + if (!main_loop) + return; + memdelete(main_loop); + main_loop = NULL; } -void OS_OSX::set_window_title(const String &p_title) { - title = p_title; - - [window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]]; +String OS_OSX::get_name() const { + return "macOS"; } -void OS_OSX::set_native_icon(const String &p_filename) { - - FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); - ERR_FAIL_COND(!f); - - Vector<uint8_t> data; - uint32_t len = f->get_len(); - data.resize(len); - f->get_buffer((uint8_t *)&data.write[0], len); - memdelete(f); - - NSData *icon_data = [[[NSData alloc] initWithBytes:&data.write[0] length:len] autorelease]; - ERR_FAIL_COND_MSG(!icon_data, "Error reading icon data."); - - NSImage *icon = [[[NSImage alloc] initWithData:icon_data] autorelease]; - ERR_FAIL_COND_MSG(!icon, "Error loading icon."); - - [NSApp setApplicationIconImage:icon]; -} +Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { + String path = p_path; -void OS_OSX::set_icon(const Ref<Image> &p_icon) { - - Ref<Image> img = p_icon; - img = img->duplicate(); - img->convert(Image::FORMAT_RGBA8); - NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:NULL - pixelsWide:img->get_width() - pixelsHigh:img->get_height() - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:img->get_width() * 4 - bitsPerPixel:32] autorelease]; - ERR_FAIL_COND(imgrep == nil); - uint8_t *pixels = [imgrep bitmapData]; - - int len = img->get_width() * img->get_height(); - const uint8_t *r = img->get_data().ptr(); - - /* Premultiply the alpha channel */ - for (int i = 0; i < len; i++) { - uint8_t alpha = r[i * 4 + 3]; - pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255); - pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255); - pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255); - pixels[i * 4 + 3] = alpha; + if (!FileAccess::exists(path)) { + //this code exists so gdnative can load .dylib files from within the executable path + path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); } - NSImage *nsimg = [[[NSImage alloc] initWithSize:NSMakeSize(img->get_width(), img->get_height())] autorelease]; - ERR_FAIL_COND(nsimg == nil); - [nsimg addRepresentation:imgrep]; + if (!FileAccess::exists(path)) { + //this code exists so gdnative can load .dylib files from a standard macOS location + path = get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file()); + } - [NSApp setApplicationIconImage:nsimg]; + p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); + ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + "."); + return OK; } MainLoop *OS_OSX::get_main_loop() const { - return main_loop; } String OS_OSX::get_config_path() const { - if (has_environment("XDG_CONFIG_HOME")) { return get_environment("XDG_CONFIG_HOME"); } else if (has_environment("HOME")) { @@ -2084,7 +205,6 @@ String OS_OSX::get_config_path() const { } String OS_OSX::get_data_path() const { - if (has_environment("XDG_DATA_HOME")) { return get_environment("XDG_DATA_HOME"); } else { @@ -2093,7 +213,6 @@ String OS_OSX::get_data_path() const { } String OS_OSX::get_cache_path() const { - if (has_environment("XDG_CACHE_HOME")) { return get_environment("XDG_CACHE_HOME"); } else if (has_environment("HOME")) { @@ -2104,7 +223,6 @@ String OS_OSX::get_cache_path() const { } String OS_OSX::get_bundle_resource_dir() const { - NSBundle *main = [NSBundle mainBundle]; NSString *resourcePath = [main resourcePath]; @@ -2118,12 +236,10 @@ String OS_OSX::get_bundle_resource_dir() const { // Get properly capitalized engine name for system paths String OS_OSX::get_godot_dir_name() const { - return String(VERSION_SHORT_NAME).capitalize(); } String OS_OSX::get_system_dir(SystemDir p_dir) const { - NSSearchPathDirectory id; bool found = true; @@ -2166,62 +282,7 @@ String OS_OSX::get_system_dir(SystemDir p_dir) const { return ret; } -bool OS_OSX::can_draw() const { - - return true; -} - -void OS_OSX::set_clipboard(const String &p_text) { - - NSString *copiedString = [NSString stringWithUTF8String:p_text.utf8().get_data()]; - NSArray *copiedStringArray = [NSArray arrayWithObject:copiedString]; - - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - [pasteboard clearContents]; - [pasteboard writeObjects:copiedStringArray]; -} - -String OS_OSX::get_clipboard() const { - - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; - NSDictionary *options = [NSDictionary dictionary]; - - BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; - - if (!ok) { - return ""; - } - - NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; - NSString *string = [objectsToPaste objectAtIndex:0]; - - char *utfs = strdup([string UTF8String]); - String ret; - ret.parse_utf8(utfs); - free(utfs); - - return ret; -} - -void OS_OSX::release_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->release_current(); - } -#endif -} - -void OS_OSX::make_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->make_current(); - } -#endif -} - Error OS_OSX::shell_open(String p_uri) { - [[NSWorkspace sharedWorkspace] openURL:[[NSURL alloc] initWithString:[[NSString stringWithUTF8String:p_uri.utf8().get_data()] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]]]; return OK; } @@ -2231,491 +292,7 @@ String OS_OSX::get_locale() const { return [locale_code UTF8String]; } -void OS_OSX::swap_buffers() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->swap_buffers(); - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->swap_buffers(); - } -#endif -} - -void OS_OSX::wm_minimized(bool p_minimized) { - - minimized = p_minimized; -}; - -void OS_OSX::set_video_mode(const VideoMode &p_video_mode, int p_screen) { -} - -OS::VideoMode OS_OSX::get_video_mode(int p_screen) const { - - VideoMode vm; - vm.width = window_size.width; - vm.height = window_size.height; - - return vm; -} - -void OS_OSX::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { -} - -int OS_OSX::get_screen_count() const { - NSArray *screenArray = [NSScreen screens]; - return [screenArray count]; -}; - -// Returns the native top-left screen coordinate of the smallest rectangle -// that encompasses all screens. Needed in get_screen_position(), -// get_window_position, and set_window_position() -// to convert between OS X native screen coordinates and the ones expected by Godot -Point2 OS_OSX::get_screens_origin() const { - static Point2 origin; - - if (displays_arrangement_dirty) { - origin = Point2(); - - for (int i = 0; i < get_screen_count(); i++) { - Point2 position = get_native_screen_position(i); - if (position.x < origin.x) { - origin.x = position.x; - } - if (position.y > origin.y) { - origin.y = position.y; - } - } - - displays_arrangement_dirty = false; - } - - return origin; -} - -static int get_screen_index(NSScreen *screen) { - const NSUInteger index = [[NSScreen screens] indexOfObject:screen]; - return index == NSNotFound ? 0 : index; -} - -int OS_OSX::get_current_screen() const { - if (window_object) { - return get_screen_index([window_object screen]); - } else { - return get_screen_index([NSScreen mainScreen]); - } -}; - -void OS_OSX::set_current_screen(int p_screen) { - Vector2 wpos = get_window_position() - get_screen_position(get_current_screen()); - set_window_position(wpos + get_screen_position(p_screen)); -}; - -Point2 OS_OSX::get_native_screen_position(int p_screen) const { - if (p_screen < 0) { - p_screen = get_current_screen(); - } - - NSArray *screenArray = [NSScreen screens]; - if ((NSUInteger)p_screen < [screenArray count]) { - float display_scale = _display_scale([screenArray objectAtIndex:p_screen]); - NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; - // Return the top-left corner of the screen, for OS X the y starts at the bottom - return Point2(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * display_scale; - } - - return Point2(); -} - -Point2 OS_OSX::get_screen_position(int p_screen) const { - Point2 position = get_native_screen_position(p_screen) - get_screens_origin(); - // OS X native y-coordinate relative to get_screens_origin() is negative, - // Godot expects a positive value - position.y *= -1; - return position; -} - -int OS_OSX::get_screen_dpi(int p_screen) const { - if (p_screen < 0) { - p_screen = get_current_screen(); - } - - NSArray *screenArray = [NSScreen screens]; - if ((NSUInteger)p_screen < [screenArray count]) { - float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); - NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription]; - NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue]; - CGSize displayPhysicalSize = CGDisplayScreenSize( - [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]); - - return (displayPixelSize.width * 25.4f / displayPhysicalSize.width) * displayScale; - } - - return 72; -} - -Size2 OS_OSX::get_screen_size(int p_screen) const { - if (p_screen < 0) { - p_screen = get_current_screen(); - } - - NSArray *screenArray = [NSScreen screens]; - if ((NSUInteger)p_screen < [screenArray count]) { - float displayScale = _display_scale([screenArray objectAtIndex:p_screen]); - // Note: Use frame to get the whole screen size - NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame]; - return Size2(nsrect.size.width, nsrect.size.height) * displayScale; - } - - return Size2(); -} - -void OS_OSX::_update_window() { - bool borderless_full = false; - - if (get_borderless_window()) { - NSRect frameRect = [window_object frame]; - NSRect screenRect = [[window_object screen] frame]; - - // Check if our window covers up the screen - if (frameRect.origin.x <= screenRect.origin.x && frameRect.origin.y <= frameRect.origin.y && - frameRect.size.width >= screenRect.size.width && frameRect.size.height >= screenRect.size.height) { - borderless_full = true; - } - } - - if (borderless_full) { - // If the window covers up the screen set the level to above the main menu and hide on deactivate - [window_object setLevel:NSMainMenuWindowLevel + 1]; - [window_object setHidesOnDeactivate:YES]; - } else { - // Reset these when our window is not a borderless window that covers up the screen - [window_object setLevel:NSNormalWindowLevel]; - [window_object setHidesOnDeactivate:NO]; - } -} - -float OS_OSX::_display_scale() const { - if (window_object) { - return _display_scale([window_object screen]); - } else { - return _display_scale([NSScreen mainScreen]); - } -} - -float OS_OSX::_display_scale(id screen) const { - if (is_hidpi_allowed()) { - if ([screen respondsToSelector:@selector(backingScaleFactor)]) { - return fmax(1.0, [screen backingScaleFactor]); - } - } - return 1.0; -} - -Point2 OS_OSX::get_native_window_position() const { - - NSRect nsrect = [window_object frame]; - Point2 pos; - float display_scale = _display_scale(); - - // Return the position of the top-left corner, for OS X the y starts at the bottom - pos.x = nsrect.origin.x * display_scale; - pos.y = (nsrect.origin.y + nsrect.size.height) * display_scale; - - return pos; -}; - -Point2 OS_OSX::get_window_position() const { - Point2 position = get_native_window_position() - get_screens_origin(); - // OS X native y-coordinate relative to get_screens_origin() is negative, - // Godot expects a positive value - position.y *= -1; - return position; -} - -void OS_OSX::set_native_window_position(const Point2 &p_position) { - - NSPoint pos; - float displayScale = _display_scale(); - - pos.x = p_position.x / displayScale; - pos.y = p_position.y / displayScale; - - [window_object setFrameTopLeftPoint:pos]; - - _update_window(); -}; - -void OS_OSX::set_window_position(const Point2 &p_position) { - Point2 position = p_position; - // OS X native y-coordinate relative to get_screens_origin() is negative, - // Godot passes a positive value - position.y *= -1; - set_native_window_position(get_screens_origin() + position); - - update_real_mouse_position(); -}; - -Size2 OS_OSX::get_window_size() const { - - return window_size; -}; - -Size2 OS_OSX::get_real_window_size() const { - - NSRect frame = [window_object frame]; - return Size2(frame.size.width, frame.size.height) * _display_scale(); -} - -Size2 OS_OSX::get_max_window_size() const { - return max_size; -} - -Size2 OS_OSX::get_min_window_size() const { - return min_size; -} - -void OS_OSX::set_min_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { - ERR_PRINT("Minimum window size can't be larger than maximum window size!"); - return; - } - min_size = p_size; - - if ((min_size != Size2()) && !zoomed) { - Size2 size = min_size / _display_scale(); - [window_object setContentMinSize:NSMakeSize(size.x, size.y)]; - } else { - [window_object setContentMinSize:NSMakeSize(0, 0)]; - } -} - -void OS_OSX::set_max_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { - ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); - return; - } - max_size = p_size; - - if ((max_size != Size2()) && !zoomed) { - Size2 size = max_size / _display_scale(); - [window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; - } else { - [window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; - } -} - -void OS_OSX::set_window_size(const Size2 p_size) { - - Size2 size = p_size / _display_scale(); - - if (get_borderless_window() == false) { - // NSRect used by setFrame includes the title bar, so add it to our size.y - CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; - if (menuBarHeight != 0.f) { - size.y += menuBarHeight; - } else { - if (floor(NSAppKitVersionNumber) < NSAppKitVersionNumber10_12) { - size.y += [[NSStatusBar systemStatusBar] thickness]; - } - } - } - - NSRect frame = [window_object frame]; - [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, size.x, size.y) display:YES]; - - _update_window(); -}; - -void OS_OSX::set_window_fullscreen(bool p_enabled) { - - if (zoomed != p_enabled) { - if (layered_window) - set_window_per_pixel_transparency_enabled(false); - if (!resizable) - [window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable]; - if (p_enabled) { - [window_object setContentMinSize:NSMakeSize(0, 0)]; - [window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; - } else { - if (min_size != Size2()) { - Size2 size = min_size / _display_scale(); - [window_object setContentMinSize:NSMakeSize(size.x, size.y)]; - } - if (max_size != Size2()) { - Size2 size = max_size / _display_scale(); - [window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; - } - } - [window_object toggleFullScreen:nil]; - } - zoomed = p_enabled; -}; - -bool OS_OSX::is_window_fullscreen() const { - - return zoomed; -}; - -void OS_OSX::set_window_resizable(bool p_enabled) { - - if (p_enabled) - [window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable]; - else if (!zoomed) - [window_object setStyleMask:[window_object styleMask] & ~NSWindowStyleMaskResizable]; - - resizable = p_enabled; -}; - -bool OS_OSX::is_window_resizable() const { - - return [window_object styleMask] & NSWindowStyleMaskResizable; -}; - -void OS_OSX::set_window_minimized(bool p_enabled) { - - if (p_enabled) - [window_object performMiniaturize:nil]; - else - [window_object deminiaturize:nil]; -}; - -bool OS_OSX::is_window_minimized() const { - - if ([window_object respondsToSelector:@selector(isMiniaturized)]) - return [window_object isMiniaturized]; - - return minimized; -}; - -void OS_OSX::set_window_maximized(bool p_enabled) { - - if (p_enabled) { - restore_rect = Rect2(get_window_position(), get_window_size()); - [window_object setFrame:[[[NSScreen screens] objectAtIndex:get_current_screen()] visibleFrame] display:YES]; - } else { - set_window_size(restore_rect.size); - set_window_position(restore_rect.position); - }; - maximized = p_enabled; -}; - -bool OS_OSX::is_window_maximized() const { - - // don't know - return maximized; -}; - -void OS_OSX::move_window_to_foreground() { - - [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; - [window_object makeKeyAndOrderFront:nil]; -} - -void OS_OSX::set_window_always_on_top(bool p_enabled) { - if (is_window_always_on_top() == p_enabled) - return; - - if (p_enabled) - [window_object setLevel:NSFloatingWindowLevel]; - else - [window_object setLevel:NSNormalWindowLevel]; -} - -bool OS_OSX::is_window_always_on_top() const { - return [window_object level] == NSFloatingWindowLevel; -} - -bool OS_OSX::is_window_focused() const { - return window_focused; -} - -void OS_OSX::request_attention() { - - [NSApp requestUserAttention:NSCriticalRequest]; -} - -bool OS_OSX::get_window_per_pixel_transparency_enabled() const { - - if (!is_layered_allowed()) return false; - return layered_window; -} - -void OS_OSX::set_window_per_pixel_transparency_enabled(bool p_enabled) { - - if (!is_layered_allowed()) return; - if (layered_window != p_enabled) { - if (p_enabled) { - set_borderless_window(true); - [window_object setBackgroundColor:[NSColor clearColor]]; - [window_object setOpaque:NO]; - [window_object setHasShadow:NO]; -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->set_opacity(0); - } -#endif - layered_window = true; - } else { - [window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]]; - [window_object setOpaque:YES]; - [window_object setHasShadow:YES]; -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->set_opacity(1); - } -#endif - layered_window = false; - } -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->update(); - } -#endif - NSRect frame = [window_object frame]; - [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES]; - [window_object setFrame:frame display:YES]; - } -} - -void OS_OSX::set_borderless_window(bool p_borderless) { - - // OrderOut prevents a lose focus bug with the window - [window_object orderOut:nil]; - - if (p_borderless) { - [window_object setStyleMask:NSWindowStyleMaskBorderless]; - } else { - if (layered_window) - set_window_per_pixel_transparency_enabled(false); - - [window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (resizable ? NSWindowStyleMaskResizable : 0)]; - - // Force update of the window styles - NSRect frameRect = [window_object frame]; - [window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO]; - [window_object setFrame:frameRect display:NO]; - - // Restore the window title - [window_object setTitle:[NSString stringWithUTF8String:title.utf8().get_data()]]; - } - - _update_window(); - - [window_object makeKeyAndOrderFront:nil]; -} - -bool OS_OSX::get_borderless_window() { - - return [window_object styleMask] == NSWindowStyleMaskBorderless; -} - String OS_OSX::get_executable_path() const { - int ret; pid_t pid; char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; @@ -2732,177 +309,7 @@ String OS_OSX::get_executable_path() const { } } -// Returns string representation of keys, if they are printable. -// -static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) { - - TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); - if (!currentKeyboard) - return nil; - - CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); - if (!layoutData) - return nil; - - const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); - - OSStatus err; - CFMutableStringRef output = CFStringCreateMutable(NULL, 0); - - for (int i = 0; i < length; ++i) { - - UInt32 keysDown = 0; - UniChar chars[4]; - UniCharCount realLength; - - err = UCKeyTranslate(keyboardLayout, - keyCode[i], - kUCKeyActionDisplay, - 0, - LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &keysDown, - sizeof(chars) / sizeof(chars[0]), - &realLength, - chars); - - if (err != noErr) { - CFRelease(output); - return nil; - } - - CFStringAppendCharacters(output, chars, 1); - } - - //CFStringUppercase(output, NULL); - - return (NSString *)output; -} - -OS::LatinKeyboardVariant OS_OSX::get_latin_keyboard_variant() const { - - static LatinKeyboardVariant layout = LATIN_KEYBOARD_QWERTY; - - if (keyboard_layout_dirty) { - - layout = LATIN_KEYBOARD_QWERTY; - - CGKeyCode keys[] = { kVK_ANSI_Q, kVK_ANSI_W, kVK_ANSI_E, kVK_ANSI_R, kVK_ANSI_T, kVK_ANSI_Y }; - NSString *test = createStringForKeys(keys, 6); - - if ([test isEqualToString:@"qwertz"]) { - layout = LATIN_KEYBOARD_QWERTZ; - } else if ([test isEqualToString:@"azerty"]) { - layout = LATIN_KEYBOARD_AZERTY; - } else if ([test isEqualToString:@"qzerty"]) { - layout = LATIN_KEYBOARD_QZERTY; - } else if ([test isEqualToString:@"',.pyf"]) { - layout = LATIN_KEYBOARD_DVORAK; - } else if ([test isEqualToString:@"xvlcwk"]) { - layout = LATIN_KEYBOARD_NEO; - } else if ([test isEqualToString:@"qwfpgj"]) { - layout = LATIN_KEYBOARD_COLEMAK; - } - - [test release]; - - keyboard_layout_dirty = false; - return layout; - } - - return layout; -} - -void OS_OSX::process_events() { - - while (true) { - NSEvent *event = [NSApp - nextEventMatchingMask:NSEventMaskAny - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - - if (event == nil) - break; - - [NSApp sendEvent:event]; - } - process_key_events(); - - [autoreleasePool drain]; - autoreleasePool = [[NSAutoreleasePool alloc] init]; - - input->flush_accumulated_events(); -} - -void OS_OSX::process_key_events() { - - Ref<InputEventKey> k; - for (int i = 0; i < key_event_pos; i++) { - - const KeyEvent &ke = key_event_buffer[i]; - - if (ke.raw) { - // Non IME input - no composite characters, pass events as is - k.instance(); - - get_key_modifier_state(ke.osx_state, k); - k->set_pressed(ke.pressed); - k->set_echo(ke.echo); - k->set_keycode(ke.keycode); - k->set_physical_keycode(ke.physical_keycode); - k->set_unicode(ke.unicode); - - push_input(k); - } else { - // IME input - if ((i == 0 && ke.keycode == 0) || (i > 0 && key_event_buffer[i - 1].keycode == 0)) { - k.instance(); - - get_key_modifier_state(ke.osx_state, k); - k->set_pressed(ke.pressed); - k->set_echo(ke.echo); - k->set_keycode(0); - k->set_physical_keycode(0); - k->set_unicode(ke.unicode); - - push_input(k); - } - if (ke.keycode != 0) { - k.instance(); - - get_key_modifier_state(ke.osx_state, k); - k->set_pressed(ke.pressed); - k->set_echo(ke.echo); - k->set_keycode(ke.keycode); - k->set_physical_keycode(ke.physical_keycode); - - if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == 0) { - k->set_unicode(key_event_buffer[i + 1].unicode); - } - - push_input(k); - } - } - } - - key_event_pos = 0; -} - -void OS_OSX::push_input(const Ref<InputEvent> &p_event) { - - Ref<InputEvent> ev = p_event; - input->accumulate_input_event(ev); -} - -void OS_OSX::force_process_input() { - - process_events(); // get rid of pending events - joypad_osx->process_joypads(); -} - void OS_OSX::run() { - force_quit = false; if (!main_loop) @@ -2910,23 +317,12 @@ void OS_OSX::run() { main_loop->init(); - if (zoomed) { - zoomed = false; - set_window_fullscreen(true); - } - - //uint64_t last_ticks=get_ticks_usec(); - - //int frames=0; - //uint64_t frame=0; - bool quit = false; - while (!force_quit && !quit) { - @try { - - process_events(); // get rid of pending events + if (DisplayServer::get_singleton()) { + DisplayServer::get_singleton()->process_events(); // get rid of pending events + } joypad_osx->process_joypads(); if (Main::iteration() == true) { @@ -2936,41 +332,9 @@ void OS_OSX::run() { ERR_PRINT("NSException: " + String([exception reason].UTF8String)); } }; - main_loop->finish(); } -void OS_OSX::set_mouse_mode(MouseMode p_mode) { - - if (p_mode == mouse_mode) - return; - - if (p_mode == MOUSE_MODE_CAPTURED) { - // Apple Docs state that the display parameter is not used. - // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." - // https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html - CGDisplayHideCursor(kCGDirectMainDisplay); - CGAssociateMouseAndMouseCursorPosition(false); - } else if (p_mode == MOUSE_MODE_HIDDEN) { - CGDisplayHideCursor(kCGDirectMainDisplay); - CGAssociateMouseAndMouseCursorPosition(true); - } else { - CGDisplayShowCursor(kCGDirectMainDisplay); - CGAssociateMouseAndMouseCursorPosition(true); - } - - mouse_mode = p_mode; -} - -OS::MouseMode OS_OSX::get_mouse_mode() const { - - return mouse_mode; -} - -String OS_OSX::get_joy_guid(int p_device) const { - return input->get_joy_guid_remapped(p_device); -} - Error OS_OSX::move_to_trash(const String &p_path) { NSFileManager *fm = [NSFileManager defaultManager]; NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())]; @@ -2984,123 +348,19 @@ Error OS_OSX::move_to_trash(const String &p_path) { return OK; } -void OS_OSX::_set_use_vsync(bool p_enable) { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - if (context_gles2) - context_gles2->set_use_vsync(p_enable); - } -#endif -} - -OS_OSX *OS_OSX::singleton = NULL; - OS_OSX::OS_OSX() { - - memset(cursors, 0, sizeof(cursors)); - key_event_pos = 0; - mouse_mode = OS::MOUSE_MODE_VISIBLE; main_loop = NULL; - singleton = this; - im_active = false; - im_position = Point2(); - layered_window = false; - autoreleasePool = [[NSAutoreleasePool alloc] init]; - - eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); - ERR_FAIL_COND(!eventSource); - - CGEventSourceSetLocalEventsSuppressionInterval(eventSource, 0.0); - - // Implicitly create shared NSApplication instance - [GodotApplication sharedApplication]; - - // In case we are unbundled, make us a proper UI application - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - - // Menu bar setup must go between sharedApplication above and - // finishLaunching below, in order to properly emulate the behavior - // of NSApplicationMain - NSMenuItem *menu_item; - NSString *title; - - NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; - if (nsappname == nil) - nsappname = [[NSProcessInfo processInfo] processName]; - - // Setup Apple menu - NSMenu *apple_menu = [[NSMenu alloc] initWithTitle:@""]; - title = [NSString stringWithFormat:NSLocalizedString(@"About %@", nil), nsappname]; - [apple_menu addItemWithTitle:title action:@selector(showAbout:) keyEquivalent:@""]; - - [apple_menu addItem:[NSMenuItem separatorItem]]; - - NSMenu *services = [[NSMenu alloc] initWithTitle:@""]; - menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Services", nil) action:nil keyEquivalent:@""]; - [apple_menu setSubmenu:services forItem:menu_item]; - [NSApp setServicesMenu:services]; - [services release]; - - [apple_menu addItem:[NSMenuItem separatorItem]]; - - title = [NSString stringWithFormat:NSLocalizedString(@"Hide %@", nil), nsappname]; - [apple_menu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Hide Others", nil) action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menu_item setKeyEquivalentModifierMask:(NSEventModifierFlagOption | NSEventModifierFlagCommand)]; - - [apple_menu addItemWithTitle:NSLocalizedString(@"Show all", nil) action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [apple_menu addItem:[NSMenuItem separatorItem]]; - - title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname]; - [apple_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - // Setup menu bar - NSMenu *main_menu = [[NSMenu alloc] initWithTitle:@""]; - menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""]; - [main_menu setSubmenu:apple_menu forItem:menu_item]; - [NSApp setMainMenu:main_menu]; - - [main_menu release]; - [apple_menu release]; - - [NSApp finishLaunching]; - - delegate = [[GodotApplicationDelegate alloc] init]; - ERR_FAIL_COND(!delegate); - [NSApp setDelegate:delegate]; - - cursor_shape = CURSOR_ARROW; - - maximized = false; - minimized = false; - window_size = Vector2(1024, 600); - zoomed = false; - resizable = false; - window_focused = true; + force_quit = false; Vector<Logger *> loggers; loggers.push_back(memnew(OSXTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); - //process application:openFile: event - while (true) { - NSEvent *event = [NSApp - nextEventMatchingMask:NSEventMaskAny - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - - if (event == nil) - break; - - [NSApp sendEvent:event]; - } - #ifdef COREAUDIO_ENABLED AudioDriverManager::add_driver(&audio_driver); #endif + + DisplayServerOSX::register_osx_driver(); } bool OS_OSX::_check_internal_feature_support(const String &p_feature) { diff --git a/platform/osx/vulkan_context_osx.h b/platform/osx/vulkan_context_osx.h index 619e91d1f6..09a5494ae8 100644 --- a/platform/osx/vulkan_context_osx.h +++ b/platform/osx/vulkan_context_osx.h @@ -39,7 +39,7 @@ class VulkanContextOSX : public VulkanContext { virtual const char *_get_platform_surface_extension() const; public: - int window_create(id p_window, int p_width, int p_height); + Error window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height); VulkanContextOSX(); ~VulkanContextOSX(); diff --git a/platform/osx/vulkan_context_osx.mm b/platform/osx/vulkan_context_osx.mm index c132bd334a..320401cdcb 100644 --- a/platform/osx/vulkan_context_osx.mm +++ b/platform/osx/vulkan_context_osx.mm @@ -35,7 +35,7 @@ const char *VulkanContextOSX::_get_platform_surface_extension() const { return VK_MVK_MACOS_SURFACE_EXTENSION_NAME; } -int VulkanContextOSX::window_create(id p_window, int p_width, int p_height) { +Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height) { VkMacOSSurfaceCreateInfoMVK createInfo; createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; @@ -45,8 +45,8 @@ int VulkanContextOSX::window_create(id p_window, int p_width, int p_height) { VkSurfaceKHR surface; VkResult err = vkCreateMacOSSurfaceMVK(_get_instance(), &createInfo, NULL, &surface); - ERR_FAIL_COND_V(err, -1); - return _window_create(surface, p_width, p_height); + ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + return _window_create(p_window_id, surface, p_width, p_height); } VulkanContextOSX::VulkanContextOSX() { diff --git a/platform/server/detect.py b/platform/server/detect.py index db9ba8d036..4ea4bddddd 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -16,7 +16,7 @@ def get_name(): def get_program_suffix(): if (sys.platform == "darwin"): return "osx" - return "x11" + return "linuxbsd" def can_build(): diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 7584293722..d40905718e 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -31,14 +31,14 @@ #ifndef OS_SERVER_H #define OS_SERVER_H +#include "core/input/input_filter.h" #include "drivers/dummy/texture_loader_dummy.h" #include "drivers/unix/os_unix.h" -#include "main/input_default.h" #ifdef __APPLE__ #include "platform/osx/crash_handler_osx.h" #include "platform/osx/semaphore_osx.h" #else -#include "platform/x11/crash_handler_x11.h" +#include "platform/x11/crash_handler_linuxbsd.h" #endif #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h index f2a721f3dd..054b67ddc8 100644 --- a/platform/uwp/joypad_uwp.h +++ b/platform/uwp/joypad_uwp.h @@ -31,7 +31,7 @@ #ifndef JOYPAD_UWP_H #define JOYPAD_UWP_H -#include "main/input_default.h" +#include "core/input/input_filter.h" ref class JoypadUWP sealed { diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index ac6e0f3dd5..cc4dfcc79f 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -32,13 +32,12 @@ #define OS_UWP_H #include "context_egl_uwp.h" +#include "core/input/input_filter.h" #include "core/math/transform_2d.h" -#include "core/os/input.h" #include "core/os/os.h" #include "core/ustring.h" #include "drivers/xaudio2/audio_driver_xaudio2.h" #include "joypad_uwp.h" -#include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" diff --git a/platform/windows/SCsub b/platform/windows/SCsub index 8e94c7b35d..89ee4dfa7a 100644 --- a/platform/windows/SCsub +++ b/platform/windows/SCsub @@ -10,6 +10,7 @@ common_win = [ "godot_windows.cpp", "crash_handler_windows.cpp", "os_windows.cpp", + "display_server_windows.cpp", "key_mapping_windows.cpp", "joypad_windows.cpp", "windows_terminal_logger.cpp", diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp new file mode 100644 index 0000000000..707337bc8d --- /dev/null +++ b/platform/windows/display_server_windows.cpp @@ -0,0 +1,2968 @@ +#include "display_server_windows.h" +#include "core/io/marshalls.h" +#include "main/main.h" +#include "os_windows.h" +#include "scene/resources/texture.h" + +#include <avrt.h> + +#ifndef WM_POINTERUPDATE +#define WM_POINTERUPDATE 0x0245 +#endif + +#ifdef DEBUG_ENABLED +static String format_error_message(DWORD id) { + + LPWSTR messageBuffer = NULL; + size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL); + + String msg = "Error " + itos(id) + ": " + String(messageBuffer, size); + + LocalFree(messageBuffer); + + return msg; +} +#endif // DEBUG_ENABLED + +bool DisplayServerWindows::has_feature(Feature p_feature) const { + switch (p_feature) { + case FEATURE_SUBWINDOWS: + case FEATURE_TOUCHSCREEN: + case FEATURE_MOUSE: + case FEATURE_MOUSE_WARP: + case FEATURE_CLIPBOARD: + case FEATURE_CURSOR_SHAPE: + case FEATURE_CUSTOM_CURSOR_SHAPE: + case FEATURE_CONSOLE_WINDOW: + case FEATURE_IME: + case FEATURE_WINDOW_TRANSPARENCY: + case FEATURE_HIDPI: + case FEATURE_ICON: + case FEATURE_NATIVE_ICON: + case FEATURE_SWAP_BUFFERS: + case FEATURE_KEEP_SCREEN_ON: + return true; + default: + return false; + } +} + +String DisplayServerWindows::get_name() const { + return "Windows"; +} + +void DisplayServerWindows::alert(const String &p_alert, const String &p_title) { + MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); +} + +void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { + + if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED) { + WindowData &wd = windows[MAIN_WINDOW_ID]; + + RECT clipRect; + GetClientRect(wd.hWnd, &clipRect); + ClientToScreen(wd.hWnd, (POINT *)&clipRect.left); + ClientToScreen(wd.hWnd, (POINT *)&clipRect.right); + ClipCursor(&clipRect); + if (p_mode == MOUSE_MODE_CAPTURED) { + + center = window_get_size() / 2; + POINT pos = { (int)center.x, (int)center.y }; + ClientToScreen(wd.hWnd, &pos); + SetCursorPos(pos.x, pos.y); + SetCapture(wd.hWnd); + } + } else { + ReleaseCapture(); + ClipCursor(NULL); + } + + if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { + hCursor = SetCursor(NULL); + } else { + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + cursor_set_shape(c); + } +} +void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) { + + _THREAD_SAFE_METHOD_ + + if (mouse_mode == p_mode) + return; + + _set_mouse_mode_impl(p_mode); + + mouse_mode = p_mode; +} +DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode() const { + return mouse_mode; +} + +void DisplayServerWindows::mouse_warp_to_position(const Point2i &p_to) { + + _THREAD_SAFE_METHOD_ + + if (!windows.has(last_focused_window)) { + return; //no window focused? + } + + if (mouse_mode == MOUSE_MODE_CAPTURED) { + + old_x = p_to.x; + old_y = p_to.y; + } else { + + POINT p; + p.x = p_to.x; + p.y = p_to.y; + ClientToScreen(windows[last_focused_window].hWnd, &p); + + SetCursorPos(p.x, p.y); + } +} +Point2i DisplayServerWindows::mouse_get_position() const { + POINT p; + GetCursorPos(&p); + return Point2i(p.x, p.y); + //return Point2(old_x, old_y); +} +int DisplayServerWindows::mouse_get_button_state() const { + return last_button_state; +} + +void DisplayServerWindows::clipboard_set(const String &p_text) { + + _THREAD_SAFE_METHOD_ + + if (!windows.has(last_focused_window)) { + return; //no window focused? + } + + // Convert LF line endings to CRLF in clipboard content + // Otherwise, line endings won't be visible when pasted in other software + String text = p_text.replace("\n", "\r\n"); + + if (!OpenClipboard(windows[last_focused_window].hWnd)) { + ERR_FAIL_MSG("Unable to open clipboard."); + } + EmptyClipboard(); + + HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType)); + ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); + + LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); + memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType)); + GlobalUnlock(mem); + + SetClipboardData(CF_UNICODETEXT, mem); + + // set the CF_TEXT version (not needed?) + CharString utf8 = text.utf8(); + mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1); + ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); + + LPTSTR ptr = (LPTSTR)GlobalLock(mem); + memcpy(ptr, utf8.get_data(), utf8.length()); + ptr[utf8.length()] = 0; + GlobalUnlock(mem); + + SetClipboardData(CF_TEXT, mem); + + CloseClipboard(); +} +String DisplayServerWindows::clipboard_get() const { + + _THREAD_SAFE_METHOD_ + + if (!windows.has(last_focused_window)) { + return String(); //no window focused? + } + + String ret; + if (!OpenClipboard(windows[last_focused_window].hWnd)) { + ERR_FAIL_V_MSG("", "Unable to open clipboard."); + }; + + if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { + + HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); + if (mem != NULL) { + + LPWSTR ptr = (LPWSTR)GlobalLock(mem); + if (ptr != NULL) { + + ret = String((CharType *)ptr); + GlobalUnlock(mem); + }; + }; + + } else if (IsClipboardFormatAvailable(CF_TEXT)) { + + HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); + if (mem != NULL) { + + LPTSTR ptr = (LPTSTR)GlobalLock(mem); + if (ptr != NULL) { + + ret.parse_utf8((const char *)ptr); + GlobalUnlock(mem); + }; + }; + }; + + CloseClipboard(); + + return ret; +} + +typedef struct { + int count; + int screen; + HMONITOR monitor; +} EnumScreenData; + +static BOOL CALLBACK _MonitorEnumProcScreen(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + EnumScreenData *data = (EnumScreenData *)dwData; + if (data->monitor == hMonitor) { + data->screen = data->count; + } + + data->count++; + return TRUE; +} + +static BOOL CALLBACK _MonitorEnumProcCount(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + int *data = (int *)dwData; + (*data)++; + return TRUE; +} + +int DisplayServerWindows::get_screen_count() const { + _THREAD_SAFE_METHOD_ + + int data = 0; + EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcCount, (LPARAM)&data); + return data; +} + +typedef struct { + int count; + int screen; + Point2 pos; +} EnumPosData; + +static BOOL CALLBACK _MonitorEnumProcPos(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + EnumPosData *data = (EnumPosData *)dwData; + if (data->count == data->screen) { + data->pos.x = lprcMonitor->left; + data->pos.y = lprcMonitor->top; + } + + data->count++; + return TRUE; +} +Point2i DisplayServerWindows::screen_get_position(int p_screen) const { + + _THREAD_SAFE_METHOD_ + + EnumPosData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Point2() }; + EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcPos, (LPARAM)&data); + return data.pos; +} + +typedef struct { + int count; + int screen; + Size2 size; +} EnumSizeData; + +typedef struct { + int count; + int screen; + Rect2i rect; +} EnumRectData; + +static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + EnumSizeData *data = (EnumSizeData *)dwData; + if (data->count == data->screen) { + data->size.x = lprcMonitor->right - lprcMonitor->left; + data->size.y = lprcMonitor->bottom - lprcMonitor->top; + } + + data->count++; + return TRUE; +} + +Size2i DisplayServerWindows::screen_get_size(int p_screen) const { + + _THREAD_SAFE_METHOD_ + + EnumSizeData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Size2() }; + EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data); + return data.size; +} + +static BOOL CALLBACK _MonitorEnumProcUsableSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + EnumRectData *data = (EnumRectData *)dwData; + if (data->count == data->screen) { + MONITORINFO minfo; + zeromem(&minfo, sizeof(MONITORINFO)); + minfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfoA(hMonitor, &minfo); + + data->rect.position.x = minfo.rcWork.left; + data->rect.position.y = minfo.rcWork.top; + data->rect.size.x = minfo.rcWork.right - minfo.rcWork.left; + data->rect.size.y = minfo.rcWork.bottom - minfo.rcWork.top; + } + + data->count++; + return TRUE; +} + +Rect2i DisplayServerWindows::screen_get_usable_rect(int p_screen) const { + + _THREAD_SAFE_METHOD_ + + EnumRectData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Rect2i() }; + EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcUsableSize, (LPARAM)&data); + return data.rect; +} + +typedef struct { + int count; + int screen; + int dpi; +} EnumDpiData; + +enum _MonitorDpiType { + MDT_Effective_DPI = 0, + MDT_Angular_DPI = 1, + MDT_Raw_DPI = 2, + MDT_Default = MDT_Effective_DPI +}; + +static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Default) { + + int dpiX = 96, dpiY = 96; + + static HMODULE Shcore = NULL; + typedef HRESULT(WINAPI * GetDPIForMonitor_t)(HMONITOR hmonitor, _MonitorDpiType dpiType, UINT * dpiX, UINT * dpiY); + static GetDPIForMonitor_t getDPIForMonitor = NULL; + + if (Shcore == NULL) { + Shcore = LoadLibraryW(L"Shcore.dll"); + getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)GetProcAddress(Shcore, "GetDpiForMonitor") : NULL; + + if ((Shcore == NULL) || (getDPIForMonitor == NULL)) { + if (Shcore) + FreeLibrary(Shcore); + Shcore = (HMODULE)INVALID_HANDLE_VALUE; + } + } + + UINT x = 0, y = 0; + HRESULT hr = E_FAIL; + if (hmon && (Shcore != (HMODULE)INVALID_HANDLE_VALUE)) { + hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y); + if (SUCCEEDED(hr) && (x > 0) && (y > 0)) { + + dpiX = (int)x; + dpiY = (int)y; + } + } else { + static int overallX = 0, overallY = 0; + if (overallX <= 0 || overallY <= 0) { + HDC hdc = GetDC(NULL); + if (hdc) { + overallX = GetDeviceCaps(hdc, LOGPIXELSX); + overallY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(NULL, hdc); + } + } + if (overallX > 0 && overallY > 0) { + dpiX = overallX; + dpiY = overallY; + } + } + + return (dpiX + dpiY) / 2; +} + +static BOOL CALLBACK _MonitorEnumProcDpi(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + EnumDpiData *data = (EnumDpiData *)dwData; + if (data->count == data->screen) { + data->dpi = QueryDpiForMonitor(hMonitor); + } + + data->count++; + return TRUE; +} + +int DisplayServerWindows::screen_get_dpi(int p_screen) const { + _THREAD_SAFE_METHOD_ + + EnumDpiData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, 72 }; + EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcDpi, (LPARAM)&data); + return data.dpi; +} +bool DisplayServerWindows::screen_is_touchscreen(int p_screen) const { +#ifndef _MSC_VER +#warning touchscreen not working +#endif + return false; +} + +void DisplayServerWindows::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) { +} +DisplayServer::ScreenOrientation DisplayServerWindows::screen_get_orientation(int p_screen) const { + return SCREEN_LANDSCAPE; +} + +void DisplayServerWindows::screen_set_keep_on(bool p_enable) { +} +bool DisplayServerWindows::screen_is_kept_on() const { + return false; +} + +Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const { + + _THREAD_SAFE_METHOD_ + + Vector<DisplayServer::WindowID> ret; + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + return ret; +} + +DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(const Point2i &p_position) const { + + POINT p; + p.x = p_position.x; + p.y = p_position.y; + HWND hwnd = WindowFromPoint(p); + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (E->get().hWnd == hwnd) { + return E->key(); + } + } + + return INVALID_WINDOW_ID; +} + +DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { + + _THREAD_SAFE_METHOD_ + + WindowID window_id = _create_window(p_mode, p_flags, p_rect); + + WindowData &wd = windows[window_id]; + + if (p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT) { + wd.resizable = false; + } + if (p_flags & WINDOW_FLAG_BORDERLESS_BIT) { + wd.borderless = true; + } + if (p_flags & WINDOW_FLAG_ALWAYS_ON_TOP_BIT && p_mode != WINDOW_MODE_FULLSCREEN) { + wd.always_on_top = true; + } + if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) { + wd.no_focus = true; + } + + _update_window_style(window_id); + + ShowWindow(wd.hWnd, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show The Window + if (!(p_flags & WINDOW_FLAG_NO_FOCUS_BIT)) { + SetForegroundWindow(wd.hWnd); // Slightly Higher Priority + SetFocus(wd.hWnd); // Sets Keyboard Focus To + } + + return window_id; +} +void DisplayServerWindows::delete_sub_window(WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + ERR_FAIL_COND_MSG(p_window == MAIN_WINDOW_ID, "Main window cannot be deleted."); + + WindowData &wd = windows[p_window]; + + while (wd.transient_children.size()) { + window_set_transient(wd.transient_children.front()->get(), INVALID_WINDOW_ID); + } + + if (wd.transient_parent != INVALID_WINDOW_ID) { + window_set_transient(p_window, INVALID_WINDOW_ID); + } + +#ifdef VULKAN_ENABLED + if (rendering_driver == "vulkan") { + context_vulkan->window_destroy(p_window); + } +#endif + + DestroyWindow(windows[p_window].hWnd); + windows.erase(p_window); +} + +void DisplayServerWindows::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].instance_id = p_instance; +} + +ObjectID DisplayServerWindows::window_get_attached_instance_id(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), ObjectID()); + return windows[p_window].instance_id; +} + +void DisplayServerWindows::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].rect_changed_callback = p_callable; +} + +void DisplayServerWindows::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].event_callback = p_callable; +} +void DisplayServerWindows::window_set_input_event_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].input_event_callback = p_callable; +} +void DisplayServerWindows::window_set_input_text_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].input_text_callback = p_callable; +} + +void DisplayServerWindows::window_set_drop_files_callback(const Callable &p_callable, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].drop_files_callback = p_callable; +} + +void DisplayServerWindows::window_set_title(const String &p_title, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + SetWindowTextW(windows[p_window].hWnd, p_title.c_str()); +} + +int DisplayServerWindows::window_get_current_screen(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), -1); + + EnumScreenData data = { 0, 0, MonitorFromWindow(windows[p_window].hWnd, MONITOR_DEFAULTTONEAREST) }; + EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcScreen, (LPARAM)&data); + return data.screen; +} +void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + ERR_FAIL_INDEX(p_screen, get_screen_count()); + + Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); + window_set_position(ofs + screen_get_position(p_screen), p_window); +} + +Point2i DisplayServerWindows::window_get_position(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Point2i()); + const WindowData &wd = windows[p_window]; + + if (wd.minimized) { + return wd.last_pos; + } + + POINT point; + point.x = 0; + point.y = 0; + + ClientToScreen(wd.hWnd, &point); + + return Point2i(point.x, point.y); + +#if 0 + //do not use this method, as it includes windows decorations + RECT r; + GetWindowRect(wd.hWnd, &r); + return Point2(r.left, r.top); +#endif +} +void DisplayServerWindows::_update_real_mouse_position(WindowID p_window) { + + POINT mouse_pos; + if (GetCursorPos(&mouse_pos) && ScreenToClient(windows[p_window].hWnd, &mouse_pos)) { + if (mouse_pos.x > 0 && mouse_pos.y > 0 && mouse_pos.x <= windows[p_window].width && mouse_pos.y <= windows[p_window].height) { + old_x = mouse_pos.x; + old_y = mouse_pos.y; + old_invalid = false; + InputFilter::get_singleton()->set_mouse_position(Point2i(mouse_pos.x, mouse_pos.y)); + } + } +} +void DisplayServerWindows::window_set_position(const Point2i &p_position, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if (wd.fullscreen) return; +#if 0 + //wrong needs to account properly for decorations + RECT r; + GetWindowRect(wd.hWnd, &r); + MoveWindow(wd.hWnd, p_position.x, p_position.y, r.right - r.left, r.bottom - r.top, TRUE); +#else + + RECT rc; + rc.left = p_position.x; + rc.right = p_position.x + wd.width; + rc.bottom = p_position.y + wd.height; + rc.top = p_position.y; + + const DWORD style = GetWindowLongPtr(wd.hWnd, GWL_STYLE); + const DWORD exStyle = GetWindowLongPtr(wd.hWnd, GWL_EXSTYLE); + + AdjustWindowRectEx(&rc, style, false, exStyle); + MoveWindow(wd.hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); +#endif + // Don't let the mouse leave the window when moved + if (mouse_mode == MOUSE_MODE_CONFINED) { + RECT rect; + GetClientRect(wd.hWnd, &rect); + ClientToScreen(wd.hWnd, (POINT *)&rect.left); + ClientToScreen(wd.hWnd, (POINT *)&rect.right); + ClipCursor(&rect); + } + + wd.last_pos = p_position; + _update_real_mouse_position(p_window); +} + +void DisplayServerWindows::window_set_transient(WindowID p_window, WindowID p_parent) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(p_window == p_parent); + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd_window = windows[p_window]; + + ERR_FAIL_COND(wd_window.transient_parent == p_parent); + + ERR_FAIL_COND_MSG(wd_window.always_on_top, "Windows with the 'on top' can't become transient."); + + if (p_parent == INVALID_WINDOW_ID) { + //remove transient + + ERR_FAIL_COND(wd_window.transient_parent == INVALID_WINDOW_ID); + ERR_FAIL_COND(!windows.has(wd_window.transient_parent)); + + WindowData &wd_parent = windows[wd_window.transient_parent]; + + wd_window.transient_parent = INVALID_WINDOW_ID; + wd_parent.transient_children.erase(p_window); + + SetWindowLongPtr(wd_window.hWnd, GWLP_HWNDPARENT, NULL); + } else { + ERR_FAIL_COND(!windows.has(p_parent)); + ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent"); + WindowData &wd_parent = windows[p_parent]; + + wd_window.transient_parent = p_parent; + wd_parent.transient_children.insert(p_window); + + SetWindowLongPtr(wd_window.hWnd, GWLP_HWNDPARENT, (LONG_PTR)wd_parent.hWnd); + } +} + +void DisplayServerWindows::window_set_max_size(const Size2i p_size, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if ((p_size != Size2()) && ((p_size.x < wd.min_size.x) || (p_size.y < wd.min_size.y))) { + ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); + return; + } + wd.max_size = p_size; +} +Size2i DisplayServerWindows::window_get_max_size(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + return wd.max_size; +} + +void DisplayServerWindows::window_set_min_size(const Size2i p_size, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if ((p_size != Size2()) && (wd.max_size != Size2()) && ((p_size.x > wd.max_size.x) || (p_size.y > wd.max_size.y))) { + ERR_PRINT("Minimum window size can't be larger than maximum window size!"); + return; + } + wd.min_size = p_size; +} +Size2i DisplayServerWindows::window_get_min_size(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + return wd.min_size; +} + +void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + int w = p_size.width; + int h = p_size.height; + + wd.width = w; + wd.height = h; + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + context_vulkan->window_resize(p_window, w, h); + } +#endif + + if (wd.fullscreen) { + return; + } + + RECT rect; + GetWindowRect(wd.hWnd, &rect); + + if (!wd.borderless) { + RECT crect; + GetClientRect(wd.hWnd, &crect); + + w += (rect.right - rect.left) - (crect.right - crect.left); + h += (rect.bottom - rect.top) - (crect.bottom - crect.top); + } + + MoveWindow(wd.hWnd, rect.left, rect.top, w, h, TRUE); + + // Don't let the mouse leave the window when resizing to a smaller resolution + if (mouse_mode == MOUSE_MODE_CONFINED) { + RECT crect; + GetClientRect(wd.hWnd, &crect); + ClientToScreen(wd.hWnd, (POINT *)&crect.left); + ClientToScreen(wd.hWnd, (POINT *)&crect.right); + ClipCursor(&crect); + } +} +Size2i DisplayServerWindows::window_get_size(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + + if (wd.minimized) { + return Size2(wd.width, wd.height); + } + + RECT r; + if (GetClientRect(wd.hWnd, &r)) { // Only area inside of window border + return Size2(r.right - r.left, r.bottom - r.top); + } + return Size2(); +} +Size2i DisplayServerWindows::window_get_real_size(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Size2i()); + const WindowData &wd = windows[p_window]; + + RECT r; + if (GetWindowRect(wd.hWnd, &r)) { // Includes area of the window border + return Size2(r.right - r.left, r.bottom - r.top); + } + return Size2(); +} + +void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) { + + r_style = 0; + r_style_ex = WS_EX_WINDOWEDGE; + if (p_main_window) { + r_style_ex |= WS_EX_APPWINDOW; + } + + if (p_fullscreen || p_borderless) { + r_style |= WS_POPUP; + //if (p_borderless) { + // r_style_ex |= WS_EX_TOOLWINDOW; + //} + } else { + + if (p_resizable) { + if (p_maximized) { + r_style = WS_OVERLAPPEDWINDOW | WS_MAXIMIZE; + } else { + r_style = WS_OVERLAPPEDWINDOW; + } + } else { + r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; + } + } + + if (p_no_activate_focus) { + r_style_ex |= WS_EX_TOPMOST | WS_EX_NOACTIVATE; + } + r_style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS; +} + +void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repaint, bool p_maximized) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + DWORD style = 0; + DWORD style_ex = 0; + + _get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.borderless, wd.resizable, wd.maximized, wd.no_focus, style, style_ex); + + SetWindowLongPtr(wd.hWnd, GWL_STYLE, style); + SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex); + + SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | (wd.no_focus ? SWP_NOACTIVATE : 0)); + + if (p_repaint) { + RECT rect; + GetWindowRect(wd.hWnd, &rect); + MoveWindow(wd.hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); + } +} + +void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if (wd.fullscreen && p_mode != WINDOW_MODE_FULLSCREEN) { + + RECT rect; + + wd.fullscreen = false; + + if (wd.pre_fs_valid) { + rect = wd.pre_fs_rect; + } else { + rect.left = 0; + rect.right = wd.width; + rect.top = 0; + rect.bottom = wd.height; + } + + _update_window_style(p_window, false, wd.was_maximized); + + MoveWindow(wd.hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); + + wd.pre_fs_valid = true; + } + + if (p_mode == WINDOW_MODE_MAXIMIZED) { + + ShowWindow(wd.hWnd, SW_MAXIMIZE); + wd.maximized = true; + wd.minimized = false; + } + + if (p_mode == WINDOW_MODE_WINDOWED) { + + ShowWindow(wd.hWnd, SW_RESTORE); + wd.maximized = false; + wd.minimized = false; + } + + if (p_mode == WINDOW_MODE_MINIMIZED) { + + ShowWindow(wd.hWnd, SW_MINIMIZE); + wd.maximized = false; + wd.minimized = true; + } + + if (p_mode == WINDOW_MODE_FULLSCREEN && !wd.fullscreen) { + if (wd.minimized) { + ShowWindow(wd.hWnd, SW_RESTORE); + } + wd.was_maximized = wd.maximized; + + if (wd.pre_fs_valid) { + GetWindowRect(wd.hWnd, &wd.pre_fs_rect); + } + + int cs = window_get_current_screen(p_window); + Point2 pos = screen_get_position(cs); + Size2 size = screen_get_size(cs); + + wd.fullscreen = true; + wd.maximized = false; + wd.minimized = false; + + _update_window_style(false); + + MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE); + } +} +DisplayServer::WindowMode DisplayServerWindows::window_get_mode(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), WINDOW_MODE_WINDOWED); + const WindowData &wd = windows[p_window]; + + if (wd.fullscreen) { + return WINDOW_MODE_FULLSCREEN; + } else if (wd.minimized) { + return WINDOW_MODE_MINIMIZED; + } else if (wd.maximized) { + return WINDOW_MODE_MAXIMIZED; + } else { + return WINDOW_MODE_WINDOWED; + } +} + +bool DisplayServerWindows::window_is_maximize_allowed(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; + + return true; //no idea +} + +void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + switch (p_flag) { + case WINDOW_FLAG_RESIZE_DISABLED: { + + wd.resizable = !p_enabled; + _update_window_style(p_window); + } break; + case WINDOW_FLAG_BORDERLESS: { + + wd.borderless = p_enabled; + _update_window_style(p_window); + } break; + case WINDOW_FLAG_ALWAYS_ON_TOP: { + + ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID && p_enabled, "Transient windows can't become on top"); + wd.always_on_top = p_enabled; + _update_window_style(p_window); + } break; + case WINDOW_FLAG_TRANSPARENT: { + + } break; + case WINDOW_FLAG_NO_FOCUS: { + + wd.no_focus = p_enabled; + _update_window_style(p_window); + } break; + } +} +bool DisplayServerWindows::window_get_flag(WindowFlags p_flag, WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; + switch (p_flag) { + case WINDOW_FLAG_RESIZE_DISABLED: { + + return !wd.resizable; + } break; + case WINDOW_FLAG_BORDERLESS: { + + return wd.borderless; + } break; + case WINDOW_FLAG_ALWAYS_ON_TOP: { + + return wd.always_on_top; + } break; + case WINDOW_FLAG_TRANSPARENT: { + + } break; + } + + return false; +} + +void DisplayServerWindows::window_request_attention(WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + FLASHWINFO info; + info.cbSize = sizeof(FLASHWINFO); + info.hwnd = wd.hWnd; + info.dwFlags = FLASHW_TRAY; + info.dwTimeout = 0; + info.uCount = 2; + FlashWindowEx(&info); +} +void DisplayServerWindows::window_move_to_foreground(WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + SetForegroundWindow(wd.hWnd); +} + +bool DisplayServerWindows::window_can_draw(WindowID p_window) const { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), false); + const WindowData &wd = windows[p_window]; + return wd.minimized; +} + +bool DisplayServerWindows::can_any_window_draw() const { + + _THREAD_SAFE_METHOD_ + + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (!E->get().minimized) { + return true; + } + } + + return false; +} + +void DisplayServerWindows::window_set_ime_active(const bool p_active, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + if (p_active) { + ImmAssociateContext(wd.hWnd, wd.im_himc); + + window_set_ime_position(wd.im_position, p_window); + } else { + ImmAssociateContext(wd.hWnd, (HIMC)0); + } +} +void DisplayServerWindows::window_set_ime_position(const Point2i &p_pos, WindowID p_window) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.im_position = p_pos; + + HIMC himc = ImmGetContext(wd.hWnd); + if (himc == (HIMC)0) + return; + + COMPOSITIONFORM cps; + cps.dwStyle = CFS_FORCE_POSITION; + cps.ptCurrentPos.x = wd.im_position.x; + cps.ptCurrentPos.y = wd.im_position.y; + ImmSetCompositionWindow(himc, &cps); + ImmReleaseContext(wd.hWnd, himc); +} + +void DisplayServerWindows::console_set_visible(bool p_enabled) { + + _THREAD_SAFE_METHOD_ + + if (console_visible == p_enabled) + return; + ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); + console_visible = p_enabled; +} +bool DisplayServerWindows::is_console_visible() const { + return console_visible; +} + +void DisplayServerWindows::cursor_set_shape(CursorShape p_shape) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_INDEX(p_shape, CURSOR_MAX); + + if (cursor_shape == p_shape) + return; + + if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { + cursor_shape = p_shape; + return; + } + + static const LPCTSTR win_cursors[CURSOR_MAX] = { + IDC_ARROW, + IDC_IBEAM, + IDC_HAND, //finger + IDC_CROSS, + IDC_WAIT, + IDC_APPSTARTING, + IDC_ARROW, + IDC_ARROW, + IDC_NO, + IDC_SIZENS, + IDC_SIZEWE, + IDC_SIZENESW, + IDC_SIZENWSE, + IDC_SIZEALL, + IDC_SIZENS, + IDC_SIZEWE, + IDC_HELP + }; + + if (cursors[p_shape] != NULL) { + SetCursor(cursors[p_shape]); + } else { + SetCursor(LoadCursor(hInstance, win_cursors[p_shape])); + } + + cursor_shape = p_shape; +} +DisplayServer::CursorShape DisplayServerWindows::cursor_get_shape() const { + return cursor_shape; +} + +void DisplayServerWindows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) { + + // Get the system display DC + HDC hDC = GetDC(NULL); + + // Create helper DC + HDC hMainDC = CreateCompatibleDC(hDC); + HDC hAndMaskDC = CreateCompatibleDC(hDC); + HDC hXorMaskDC = CreateCompatibleDC(hDC); + + // Get the dimensions of the source bitmap + BITMAP bm; + GetObject(hSourceBitmap, sizeof(BITMAP), &bm); + + // Create the mask bitmaps + hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color + hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color + + // Release the system display DC + ReleaseDC(NULL, hDC); + + // Select the bitmaps to helper DC + HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap); + HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap); + HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap); + + // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap + // with 'clrTransparent' will be white pixels of the monochrome bitmap + SetBkColor(hMainDC, clrTransparent); + BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY); + + // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap + // with 'clrTransparent' will be black and rest the pixels same as corresponding + // pixels of the source bitmap + SetBkColor(hXorMaskDC, RGB(0, 0, 0)); + SetTextColor(hXorMaskDC, RGB(255, 255, 255)); + BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY); + BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND); + + // Deselect bitmaps from the helper DC + SelectObject(hMainDC, hOldMainBitmap); + SelectObject(hAndMaskDC, hOldAndMaskBitmap); + SelectObject(hXorMaskDC, hOldXorMaskBitmap); + + // Delete the helper DC + DeleteDC(hXorMaskDC); + DeleteDC(hAndMaskDC); + DeleteDC(hMainDC); +} + +void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + + _THREAD_SAFE_METHOD_ + + if (p_cursor.is_valid()) { + + Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); + + if (cursor_c) { + if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { + cursor_set_shape(p_shape); + return; + } + + cursors_cache.erase(p_shape); + } + + Ref<Texture2D> texture = p_cursor; + Ref<AtlasTexture> atlas_texture = p_cursor; + Ref<Image> image; + Size2 texture_size; + Rect2 atlas_rect; + + if (texture.is_valid()) { + image = texture->get_data(); + } + + if (!image.is_valid() && atlas_texture.is_valid()) { + texture = atlas_texture->get_atlas(); + + atlas_rect.size.width = texture->get_width(); + atlas_rect.size.height = texture->get_height(); + atlas_rect.position.x = atlas_texture->get_region().position.x; + atlas_rect.position.y = atlas_texture->get_region().position.y; + + texture_size.width = atlas_texture->get_region().size.x; + texture_size.height = atlas_texture->get_region().size.y; + } else if (image.is_valid()) { + texture_size.width = texture->get_width(); + texture_size.height = texture->get_height(); + } + + ERR_FAIL_COND(!texture.is_valid()); + ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); + ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); + ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); + + image = texture->get_data(); + + ERR_FAIL_COND(!image.is_valid()); + + UINT image_size = texture_size.width * texture_size.height; + + // Create the BITMAP with alpha channel + COLORREF *buffer = (COLORREF *)memalloc(sizeof(COLORREF) * image_size); + + for (UINT index = 0; index < image_size; index++) { + int row_index = floor(index / texture_size.width) + atlas_rect.position.y; + int column_index = (index % int(texture_size.width)) + atlas_rect.position.x; + + if (atlas_texture.is_valid()) { + column_index = MIN(column_index, atlas_rect.size.width - 1); + row_index = MIN(row_index, atlas_rect.size.height - 1); + } + + *(buffer + index) = image->get_pixel(column_index, row_index).to_argb32(); + } + + // Using 4 channels, so 4 * 8 bits + HBITMAP bitmap = CreateBitmap(texture_size.width, texture_size.height, 1, 4 * 8, buffer); + COLORREF clrTransparent = -1; + + // Create the AND and XOR masks for the bitmap + HBITMAP hAndMask = NULL; + HBITMAP hXorMask = NULL; + + GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask); + + if (NULL == hAndMask || NULL == hXorMask) { + memfree(buffer); + DeleteObject(bitmap); + return; + } + + // Finally, create the icon + ICONINFO iconinfo; + iconinfo.fIcon = FALSE; + iconinfo.xHotspot = p_hotspot.x; + iconinfo.yHotspot = p_hotspot.y; + iconinfo.hbmMask = hAndMask; + iconinfo.hbmColor = hXorMask; + + if (cursors[p_shape]) + DestroyIcon(cursors[p_shape]); + + cursors[p_shape] = CreateIconIndirect(&iconinfo); + + Vector<Variant> params; + params.push_back(p_cursor); + params.push_back(p_hotspot); + cursors_cache.insert(p_shape, params); + + if (p_shape == cursor_shape) { + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + SetCursor(cursors[p_shape]); + } + } + + if (hAndMask != NULL) { + DeleteObject(hAndMask); + } + + if (hXorMask != NULL) { + DeleteObject(hXorMask); + } + + memfree(buffer); + DeleteObject(bitmap); + } else { + // Reset to default system cursor + if (cursors[p_shape]) { + DestroyIcon(cursors[p_shape]); + cursors[p_shape] = NULL; + } + + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + cursor_set_shape(c); + + cursors_cache.erase(p_shape); + } +} + +bool DisplayServerWindows::get_swap_ok_cancel() { + return true; +} + +void DisplayServerWindows::enable_for_stealing_focus(OS::ProcessID pid) { + _THREAD_SAFE_METHOD_ + + AllowSetForegroundWindow(pid); +} + +DisplayServer::LatinKeyboardVariant DisplayServerWindows::get_latin_keyboard_variant() const { + + _THREAD_SAFE_METHOD_ + + unsigned long azerty[] = { + 0x00020401, // Arabic (102) AZERTY + 0x0001080c, // Belgian (Comma) + 0x0000080c, // Belgian French + 0x0000040c, // French + 0 // <--- STOP MARK + }; + unsigned long qwertz[] = { + 0x0000041a, // Croation + 0x00000405, // Czech + 0x00000407, // German + 0x00010407, // German (IBM) + 0x0000040e, // Hungarian + 0x0000046e, // Luxembourgish + 0x00010415, // Polish (214) + 0x00000418, // Romanian (Legacy) + 0x0000081a, // Serbian (Latin) + 0x0000041b, // Slovak + 0x00000424, // Slovenian + 0x0001042e, // Sorbian Extended + 0x0002042e, // Sorbian Standard + 0x0000042e, // Sorbian Standard (Legacy) + 0x0000100c, // Swiss French + 0x00000807, // Swiss German + 0 // <--- STOP MARK + }; + unsigned long dvorak[] = { + 0x00010409, // US-Dvorak + 0x00030409, // US-Dvorak for left hand + 0x00040409, // US-Dvorak for right hand + 0 // <--- STOP MARK + }; + + char name[KL_NAMELENGTH + 1]; + name[0] = 0; + GetKeyboardLayoutNameA(name); + + unsigned long hex = strtoul(name, NULL, 16); + + int i = 0; + while (azerty[i] != 0) { + if (azerty[i] == hex) return LATIN_KEYBOARD_AZERTY; + i++; + } + + i = 0; + while (qwertz[i] != 0) { + if (qwertz[i] == hex) return LATIN_KEYBOARD_QWERTZ; + i++; + } + + i = 0; + while (dvorak[i] != 0) { + if (dvorak[i] == hex) return LATIN_KEYBOARD_DVORAK; + i++; + } + + return LATIN_KEYBOARD_QWERTY; +} + +void DisplayServerWindows::process_events() { + + _THREAD_SAFE_METHOD_ + + MSG msg; + + if (!drop_events) { + joypad->process_joypads(); + } + + while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { + + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + if (!drop_events) { + _process_key_events(); + InputFilter::get_singleton()->flush_accumulated_events(); + } +} + +void DisplayServerWindows::force_process_and_drop_events() { + + _THREAD_SAFE_METHOD_ + + drop_events = true; + process_events(); + drop_events = false; +} + +void DisplayServerWindows::release_rendering_thread() { +} +void DisplayServerWindows::make_rendering_thread() { +} +void DisplayServerWindows::swap_buffers() { +} + +void DisplayServerWindows::set_native_icon(const String &p_filename) { + + _THREAD_SAFE_METHOD_ + + FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); + ERR_FAIL_COND_MSG(!f, "Cannot open file with icon '" + p_filename + "'."); + + ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR)); + int pos = 0; + + icon_dir->idReserved = f->get_32(); + pos += sizeof(WORD); + f->seek(pos); + + icon_dir->idType = f->get_32(); + pos += sizeof(WORD); + f->seek(pos); + + ERR_FAIL_COND_MSG(icon_dir->idType != 1, "Invalid icon file format!"); + + icon_dir->idCount = f->get_32(); + pos += sizeof(WORD); + f->seek(pos); + + icon_dir = (ICONDIR *)memrealloc(icon_dir, 3 * sizeof(WORD) + icon_dir->idCount * sizeof(ICONDIRENTRY)); + f->get_buffer((uint8_t *)&icon_dir->idEntries[0], icon_dir->idCount * sizeof(ICONDIRENTRY)); + + int small_icon_index = -1; // Select 16x16 with largest color count + int small_icon_cc = 0; + int big_icon_index = -1; // Select largest + int big_icon_width = 16; + int big_icon_cc = 0; + + for (int i = 0; i < icon_dir->idCount; i++) { + int colors = (icon_dir->idEntries[i].bColorCount == 0) ? 32768 : icon_dir->idEntries[i].bColorCount; + int width = (icon_dir->idEntries[i].bWidth == 0) ? 256 : icon_dir->idEntries[i].bWidth; + if (width == 16) { + if (colors >= small_icon_cc) { + small_icon_index = i; + small_icon_cc = colors; + } + } + if (width >= big_icon_width) { + if (colors >= big_icon_cc) { + big_icon_index = i; + big_icon_width = width; + big_icon_cc = colors; + } + } + } + + ERR_FAIL_COND_MSG(big_icon_index == -1, "No valid icons found!"); + + if (small_icon_index == -1) { + WARN_PRINT("No small icon found, reusing " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon!"); + small_icon_index = big_icon_index; + small_icon_cc = big_icon_cc; + } + + // Read the big icon + DWORD bytecount_big = icon_dir->idEntries[big_icon_index].dwBytesInRes; + Vector<uint8_t> data_big; + data_big.resize(bytecount_big); + pos = icon_dir->idEntries[big_icon_index].dwImageOffset; + f->seek(pos); + f->get_buffer((uint8_t *)&data_big.write[0], bytecount_big); + HICON icon_big = CreateIconFromResource((PBYTE)&data_big.write[0], bytecount_big, TRUE, 0x00030000); + ERR_FAIL_COND_MSG(!icon_big, "Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); + + // Read the small icon + DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes; + Vector<uint8_t> data_small; + data_small.resize(bytecount_small); + pos = icon_dir->idEntries[small_icon_index].dwImageOffset; + f->seek(pos); + f->get_buffer((uint8_t *)&data_small.write[0], bytecount_small); + HICON icon_small = CreateIconFromResource((PBYTE)&data_small.write[0], bytecount_small, TRUE, 0x00030000); + ERR_FAIL_COND_MSG(!icon_small, "Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); + + // Online tradition says to be sure last error is cleared and set the small icon first + int err = 0; + SetLastError(err); + + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon_small); + err = GetLastError(); + ERR_FAIL_COND_MSG(err, "Error setting ICON_SMALL: " + format_error_message(err) + "."); + + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon_big); + err = GetLastError(); + ERR_FAIL_COND_MSG(err, "Error setting ICON_BIG: " + format_error_message(err) + "."); + + memdelete(f); + memdelete(icon_dir); +} +void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) { + + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!p_icon.is_valid()); + Ref<Image> icon = p_icon->duplicate(); + if (icon->get_format() != Image::FORMAT_RGBA8) + icon->convert(Image::FORMAT_RGBA8); + int w = icon->get_width(); + int h = icon->get_height(); + + /* Create temporary bitmap buffer */ + int icon_len = 40 + h * w * 4; + Vector<BYTE> v; + v.resize(icon_len); + BYTE *icon_bmp = v.ptrw(); + + encode_uint32(40, &icon_bmp[0]); + encode_uint32(w, &icon_bmp[4]); + encode_uint32(h * 2, &icon_bmp[8]); + encode_uint16(1, &icon_bmp[12]); + encode_uint16(32, &icon_bmp[14]); + encode_uint32(BI_RGB, &icon_bmp[16]); + encode_uint32(w * h * 4, &icon_bmp[20]); + encode_uint32(0, &icon_bmp[24]); + encode_uint32(0, &icon_bmp[28]); + encode_uint32(0, &icon_bmp[32]); + encode_uint32(0, &icon_bmp[36]); + + uint8_t *wr = &icon_bmp[40]; + const uint8_t *r = icon->get_data().ptr(); + + for (int i = 0; i < h; i++) { + + for (int j = 0; j < w; j++) { + + const uint8_t *rpx = &r[((h - i - 1) * w + j) * 4]; + uint8_t *wpx = &wr[(i * w + j) * 4]; + wpx[0] = rpx[2]; + wpx[1] = rpx[1]; + wpx[2] = rpx[0]; + wpx[3] = rpx[3]; + } + } + + HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000); + + /* Set the icon for the window */ + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); + + /* Set the icon in the task manager (should we do this?) */ + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); +} + +void DisplayServerWindows::vsync_set_use_via_compositor(bool p_enable) { +} +bool DisplayServerWindows::vsync_is_using_via_compositor() const { + return false; +} + +void DisplayServerWindows::set_context(Context p_context) { +} + +#define MI_WP_SIGNATURE 0xFF515700 +#define SIGNATURE_MASK 0xFFFFFF00 +// Keeping the name suggested by Microsoft, but this macro really answers: +// Is this mouse event emulated from touch or pen input? +#define IsPenEvent(dw) (((dw)&SIGNATURE_MASK) == MI_WP_SIGNATURE) +// This one tells whether the event comes from touchscreen (and not from pen) +#define IsTouchEvent(dw) (IsPenEvent(dw) && ((dw)&0x80)) + +void DisplayServerWindows::_touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx) { + + // Defensive + if (touch_state.has(idx) == p_pressed) + return; + + if (p_pressed) { + touch_state.insert(idx, Vector2(p_x, p_y)); + } else { + touch_state.erase(idx); + } + + Ref<InputEventScreenTouch> event; + event.instance(); + event->set_index(idx); + event->set_window_id(p_window); + event->set_pressed(p_pressed); + event->set_position(Vector2(p_x, p_y)); + + InputFilter::get_singleton()->accumulate_input_event(event); +} + +void DisplayServerWindows::_drag_event(WindowID p_window, float p_x, float p_y, int idx) { + + Map<int, Vector2>::Element *curr = touch_state.find(idx); + // Defensive + if (!curr) + return; + + if (curr->get() == Vector2(p_x, p_y)) + return; + + Ref<InputEventScreenDrag> event; + event.instance(); + event->set_window_id(p_window); + event->set_index(idx); + event->set_position(Vector2(p_x, p_y)); + event->set_relative(Vector2(p_x, p_y) - curr->get()); + + InputFilter::get_singleton()->accumulate_input_event(event); + + curr->get() = Vector2(p_x, p_y); +} + +void DisplayServerWindows::_send_window_event(const WindowData &wd, WindowEvent p_event) { + + if (!wd.event_callback.is_null()) { + Variant event = int(p_event); + Variant *eventp = &event; + Variant ret; + Callable::CallError ce; + wd.event_callback.call((const Variant **)&eventp, 1, ret, ce); + } +} + +void DisplayServerWindows::_dispatch_input_events(const Ref<InputEvent> &p_event) { + ((DisplayServerWindows *)(get_singleton()))->_dispatch_input_event(p_event); +} + +void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) { + + Variant ev = p_event; + Variant *evp = &ev; + Variant ret; + Callable::CallError ce; + + Ref<InputEventFromWindow> event_from_window = p_event; + if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) { + //send to a window + ERR_FAIL_COND(!windows.has(event_from_window->get_window_id())); + Callable callable = windows[event_from_window->get_window_id()].input_event_callback; + if (callable.is_null()) { + return; + } + callable.call((const Variant **)&evp, 1, ret, ce); + } else { + //send to all windows + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + Callable callable = E->get().input_event_callback; + if (callable.is_null()) { + continue; + } + callable.call((const Variant **)&evp, 1, ret, ce); + } + } +} + +LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + if (drop_events) { + + if (user_proc) { + + return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); + } else { + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + }; + + WindowID window_id = INVALID_WINDOW_ID; + + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (E->get().hWnd == hWnd) { + window_id = E->key(); + break; + } + } + + switch (uMsg) // Check For Windows Messages + { + case WM_SETFOCUS: { + + windows[window_id].window_has_focus = true; + last_focused_window = window_id; + + // Restore mouse mode + _set_mouse_mode_impl(mouse_mode); + + break; + } + case WM_KILLFOCUS: { + windows[window_id].window_has_focus = false; + last_focused_window = window_id; + + // Release capture unconditionally because it can be set due to dragging, in addition to captured mode + ReleaseCapture(); + + // Release every touch to avoid sticky points + for (Map<int, Vector2>::Element *E = touch_state.front(); E; E = E->next()) { + _touch_event(window_id, false, E->get().x, E->get().y, E->key()); + } + touch_state.clear(); + + break; + } + case WM_ACTIVATE: // Watch For Window Activate Message + { + windows[window_id].minimized = HIWORD(wParam) != 0; + + if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { + + _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN); + windows[window_id].window_focused = true; + alt_mem = false; + control_mem = false; + shift_mem = false; + } else { // WM_INACTIVE + InputFilter::get_singleton()->release_pressed_events(); + _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT); + windows[window_id].window_focused = false; + alt_mem = false; + }; + + return 0; // Return To The Message Loop + } + case WM_GETMINMAXINFO: { + if (windows[window_id].resizable && !windows[window_id].fullscreen) { + Size2 decor = window_get_size(window_id) - window_get_real_size(window_id); // Size of window decorations + MINMAXINFO *min_max_info = (MINMAXINFO *)lParam; + if (windows[window_id].min_size != Size2()) { + min_max_info->ptMinTrackSize.x = windows[window_id].min_size.x + decor.x; + min_max_info->ptMinTrackSize.y = windows[window_id].min_size.y + decor.y; + } + if (windows[window_id].max_size != Size2()) { + min_max_info->ptMaxTrackSize.x = windows[window_id].max_size.x + decor.x; + min_max_info->ptMaxTrackSize.y = windows[window_id].max_size.y + decor.y; + } + return 0; + } else { + break; + } + } + case WM_PAINT: + + Main::force_redraw(); + break; + + case WM_SYSCOMMAND: // Intercept System Commands + { + switch (wParam) // Check System Calls + { + case SC_SCREENSAVE: // Screensaver Trying To Start? + case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? + return 0; // Prevent From Happening + case SC_KEYMENU: + if ((lParam >> 16) <= 0) + return 0; + } + break; // Exit + } + + case WM_CLOSE: // Did We Receive A Close Message? + { + + _send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST); + + //force_quit=true; + return 0; // Jump Back + } + case WM_MOUSELEAVE: { + + old_invalid = true; + outside = true; + + _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_EXIT); + + } break; + case WM_INPUT: { + if (mouse_mode != MOUSE_MODE_CAPTURED || !use_raw_input) { + break; + } + + UINT dwSize; + + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + LPBYTE lpb = new BYTE[dwSize]; + if (lpb == NULL) { + return 0; + } + + if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) + OutputDebugString(TEXT("GetRawInputData does not return correct size !\n")); + + RAWINPUT *raw = (RAWINPUT *)lpb; + + if (raw->header.dwType == RIM_TYPEMOUSE) { + Ref<InputEventMouseMotion> mm; + mm.instance(); + + mm->set_window_id(window_id); + mm->set_control(control_mem); + mm->set_shift(shift_mem); + mm->set_alt(alt_mem); + + mm->set_button_mask(last_button_state); + + Point2i c(windows[window_id].width / 2, windows[window_id].height / 2); + + // centering just so it works as before + POINT pos = { (int)c.x, (int)c.y }; + ClientToScreen(windows[window_id].hWnd, &pos); + SetCursorPos(pos.x, pos.y); + + mm->set_position(c); + mm->set_global_position(c); + InputFilter::get_singleton()->set_mouse_position(c); + mm->set_speed(Vector2(0, 0)); + + if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE) { + mm->set_relative(Vector2(raw->data.mouse.lLastX, raw->data.mouse.lLastY)); + + } else if (raw->data.mouse.usFlags == MOUSE_MOVE_ABSOLUTE) { + + int nScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); + int nScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); + int nScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN); + int nScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN); + + Vector2 abs_pos( + (double(raw->data.mouse.lLastX) - 65536.0 / (nScreenWidth)) * nScreenWidth / 65536.0 + nScreenLeft, + (double(raw->data.mouse.lLastY) - 65536.0 / (nScreenHeight)) * nScreenHeight / 65536.0 + nScreenTop); + + POINT coords; //client coords + coords.x = abs_pos.x; + coords.y = abs_pos.y; + + ScreenToClient(hWnd, &coords); + + mm->set_relative(Vector2(coords.x - old_x, coords.y - old_y)); + old_x = coords.x; + old_y = coords.y; + + /*Input.mi.dx = (int)((((double)(pos.x)-nScreenLeft) * 65536) / nScreenWidth + 65536 / (nScreenWidth)); + Input.mi.dy = (int)((((double)(pos.y)-nScreenTop) * 65536) / nScreenHeight + 65536 / (nScreenHeight)); + */ + } + + if (windows[window_id].window_has_focus && mm->get_relative() != Vector2()) + InputFilter::get_singleton()->accumulate_input_event(mm); + } + delete[] lpb; + } break; + case WM_POINTERUPDATE: { + if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { + break; + } + + if (!win8p_GetPointerType || !win8p_GetPointerPenInfo) { + break; + } + + uint32_t pointer_id = LOWORD(wParam); + POINTER_INPUT_TYPE pointer_type = PT_POINTER; + if (!win8p_GetPointerType(pointer_id, &pointer_type)) { + break; + } + + if (pointer_type != PT_PEN) { + break; + } + + POINTER_PEN_INFO pen_info; + if (!win8p_GetPointerPenInfo(pointer_id, &pen_info)) { + break; + } + + if (InputFilter::get_singleton()->is_emulating_mouse_from_touch()) { + // Universal translation enabled; ignore OS translation + LPARAM extra = GetMessageExtraInfo(); + if (IsTouchEvent(extra)) { + break; + } + } + + if (outside) { + //mouse enter + + if (mouse_mode != MOUSE_MODE_CAPTURED) { + _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER); + } + + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + cursor_set_shape(c); + outside = false; + + //Once-Off notification, must call again.... + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + } + + // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. + if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) + break; + + Ref<InputEventMouseMotion> mm; + mm.instance(); + + mm->set_window_id(window_id); + mm->set_pressure(pen_info.pressure ? (float)pen_info.pressure / 1024 : 0); + mm->set_tilt(Vector2(pen_info.tiltX ? (float)pen_info.tiltX / 90 : 0, pen_info.tiltY ? (float)pen_info.tiltY / 90 : 0)); + + mm->set_control((wParam & MK_CONTROL) != 0); + mm->set_shift((wParam & MK_SHIFT) != 0); + mm->set_alt(alt_mem); + + mm->set_button_mask(last_button_state); + + POINT coords; //client coords + coords.x = GET_X_LPARAM(lParam); + coords.y = GET_Y_LPARAM(lParam); + + ScreenToClient(windows[window_id].hWnd, &coords); + + mm->set_position(Vector2(coords.x, coords.y)); + mm->set_global_position(Vector2(coords.x, coords.y)); + + if (mouse_mode == MOUSE_MODE_CAPTURED) { + + Point2i c(windows[window_id].width / 2, windows[window_id].height / 2); + old_x = c.x; + old_y = c.y; + + if (mm->get_position() == c) { + center = c; + return 0; + } + + Point2i ncenter = mm->get_position(); + center = ncenter; + POINT pos = { (int)c.x, (int)c.y }; + ClientToScreen(hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } + + InputFilter::get_singleton()->set_mouse_position(mm->get_position()); + mm->set_speed(InputFilter::get_singleton()->get_last_mouse_speed()); + + if (old_invalid) { + + old_x = mm->get_position().x; + old_y = mm->get_position().y; + old_invalid = false; + } + + mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); + old_x = mm->get_position().x; + old_y = mm->get_position().y; + if (windows[window_id].window_has_focus) { + InputFilter::get_singleton()->parse_input_event(mm); + } + + return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event + } break; + case WM_MOUSEMOVE: { + if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { + break; + } + + if (InputFilter::get_singleton()->is_emulating_mouse_from_touch()) { + // Universal translation enabled; ignore OS translation + LPARAM extra = GetMessageExtraInfo(); + if (IsTouchEvent(extra)) { + break; + } + } + + if (outside) { + //mouse enter + + if (mouse_mode != MOUSE_MODE_CAPTURED) { + _send_window_event(windows[window_id], WINDOW_EVENT_MOUSE_ENTER); + } + + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + cursor_set_shape(c); + outside = false; + + //Once-Off notification, must call again.... + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + } + + // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. + if (!windows[window_id].window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) + break; + + Ref<InputEventMouseMotion> mm; + mm.instance(); + mm->set_window_id(window_id); + mm->set_control((wParam & MK_CONTROL) != 0); + mm->set_shift((wParam & MK_SHIFT) != 0); + mm->set_alt(alt_mem); + + mm->set_button_mask(last_button_state); + + mm->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); + mm->set_global_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); + + if (mouse_mode == MOUSE_MODE_CAPTURED) { + + Point2i c(windows[window_id].width / 2, windows[window_id].height / 2); + old_x = c.x; + old_y = c.y; + + if (mm->get_position() == c) { + center = c; + return 0; + } + + Point2i ncenter = mm->get_position(); + center = ncenter; + POINT pos = { (int)c.x, (int)c.y }; + ClientToScreen(windows[window_id].hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } + + InputFilter::get_singleton()->set_mouse_position(mm->get_position()); + mm->set_speed(InputFilter::get_singleton()->get_last_mouse_speed()); + + if (old_invalid) { + + old_x = mm->get_position().x; + old_y = mm->get_position().y; + old_invalid = false; + } + + mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); + old_x = mm->get_position().x; + old_y = mm->get_position().y; + if (windows[window_id].window_has_focus) + InputFilter::get_singleton()->accumulate_input_event(mm); + + } break; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + if (InputFilter::get_singleton()->is_emulating_mouse_from_touch()) { + // Universal translation enabled; ignore OS translations for left button + LPARAM extra = GetMessageExtraInfo(); + if (IsTouchEvent(extra)) { + break; + } + } + [[fallthrough]]; + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_XBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: { + + Ref<InputEventMouseButton> mb; + mb.instance(); + mb->set_window_id(window_id); + + switch (uMsg) { + case WM_LBUTTONDOWN: { + mb->set_pressed(true); + mb->set_button_index(1); + } break; + case WM_LBUTTONUP: { + mb->set_pressed(false); + mb->set_button_index(1); + } break; + case WM_MBUTTONDOWN: { + mb->set_pressed(true); + mb->set_button_index(3); + } break; + case WM_MBUTTONUP: { + mb->set_pressed(false); + mb->set_button_index(3); + } break; + case WM_RBUTTONDOWN: { + mb->set_pressed(true); + mb->set_button_index(2); + } break; + case WM_RBUTTONUP: { + mb->set_pressed(false); + mb->set_button_index(2); + } break; + case WM_LBUTTONDBLCLK: { + mb->set_pressed(true); + mb->set_button_index(1); + mb->set_doubleclick(true); + } break; + case WM_RBUTTONDBLCLK: { + mb->set_pressed(true); + mb->set_button_index(2); + mb->set_doubleclick(true); + } break; + case WM_MBUTTONDBLCLK: { + mb->set_pressed(true); + mb->set_button_index(3); + mb->set_doubleclick(true); + } break; + case WM_MOUSEWHEEL: { + + mb->set_pressed(true); + int motion = (short)HIWORD(wParam); + if (!motion) + return 0; + + if (motion > 0) + mb->set_button_index(BUTTON_WHEEL_UP); + else + mb->set_button_index(BUTTON_WHEEL_DOWN); + + } break; + case WM_MOUSEHWHEEL: { + + mb->set_pressed(true); + int motion = (short)HIWORD(wParam); + if (!motion) + return 0; + + if (motion < 0) { + mb->set_button_index(BUTTON_WHEEL_LEFT); + mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); + } else { + mb->set_button_index(BUTTON_WHEEL_RIGHT); + mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); + } + } break; + case WM_XBUTTONDOWN: { + + mb->set_pressed(true); + if (HIWORD(wParam) == XBUTTON1) + mb->set_button_index(BUTTON_XBUTTON1); + else + mb->set_button_index(BUTTON_XBUTTON2); + } break; + case WM_XBUTTONUP: { + + mb->set_pressed(false); + if (HIWORD(wParam) == XBUTTON1) + mb->set_button_index(BUTTON_XBUTTON1); + else + mb->set_button_index(BUTTON_XBUTTON2); + } break; + case WM_XBUTTONDBLCLK: { + + mb->set_pressed(true); + if (HIWORD(wParam) == XBUTTON1) + mb->set_button_index(BUTTON_XBUTTON1); + else + mb->set_button_index(BUTTON_XBUTTON2); + mb->set_doubleclick(true); + } break; + default: { + return 0; + } + } + + mb->set_control((wParam & MK_CONTROL) != 0); + mb->set_shift((wParam & MK_SHIFT) != 0); + mb->set_alt(alt_mem); + //mb->get_alt()=(wParam&MK_MENU)!=0; + if (mb->is_pressed()) + last_button_state |= (1 << (mb->get_button_index() - 1)); + else + last_button_state &= ~(1 << (mb->get_button_index() - 1)); + mb->set_button_mask(last_button_state); + + mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); + + if (mouse_mode == MOUSE_MODE_CAPTURED && !use_raw_input) { + + mb->set_position(Vector2(old_x, old_y)); + } + + if (uMsg != WM_MOUSEWHEEL && uMsg != WM_MOUSEHWHEEL) { + if (mb->is_pressed()) { + + if (++pressrc > 0 && mouse_mode != MOUSE_MODE_CAPTURED) + SetCapture(hWnd); + } else { + + if (--pressrc <= 0) { + if (mouse_mode != MOUSE_MODE_CAPTURED) { + ReleaseCapture(); + } + pressrc = 0; + } + } + } else { + // for reasons unknown to mankind, wheel comes in screen coordinates + POINT coords; + coords.x = mb->get_position().x; + coords.y = mb->get_position().y; + + ScreenToClient(hWnd, &coords); + + mb->set_position(Vector2(coords.x, coords.y)); + } + + mb->set_global_position(mb->get_position()); + + InputFilter::get_singleton()->accumulate_input_event(mb); + if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { + //send release for mouse wheel + Ref<InputEventMouseButton> mbd = mb->duplicate(); + mbd->set_window_id(window_id); + last_button_state &= ~(1 << (mbd->get_button_index() - 1)); + mbd->set_button_mask(last_button_state); + mbd->set_pressed(false); + InputFilter::get_singleton()->accumulate_input_event(mbd); + } + + } break; + + case WM_MOVE: { + if (!IsIconic(windows[window_id].hWnd)) { + int x = int16_t(LOWORD(lParam)); + int y = int16_t(HIWORD(lParam)); + windows[window_id].last_pos = Point2(x, y); + + if (!windows[window_id].rect_changed_callback.is_null()) { + + Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height); + Variant *sizep = &size; + Variant ret; + Callable::CallError ce; + windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); + } + } + } break; + + case WM_SIZE: { + // Ignore size when a SIZE_MINIMIZED event is triggered + if (wParam != SIZE_MINIMIZED) { + int window_w = LOWORD(lParam); + int window_h = HIWORD(lParam); + if (window_w > 0 && window_h > 0 && !windows[window_id].preserve_window_size) { + windows[window_id].width = window_w; + windows[window_id].height = window_h; + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + context_vulkan->window_resize(window_id, windows[window_id].width, windows[window_id].height); + } +#endif + + } else { + windows[window_id].preserve_window_size = false; + window_set_size(Size2(windows[window_id].width, windows[window_id].height), window_id); + } + } + + if (!windows[window_id].rect_changed_callback.is_null()) { + + Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height); + Variant *sizep = &size; + Variant ret; + Callable::CallError ce; + windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); + } + + if (wParam == SIZE_MAXIMIZED) { + windows[window_id].maximized = true; + windows[window_id].minimized = false; + } else if (wParam == SIZE_MINIMIZED) { + windows[window_id].maximized = false; + windows[window_id].minimized = true; + } else if (wParam == SIZE_RESTORED) { + windows[window_id].maximized = false; + windows[window_id].minimized = false; + } +#if 0 + if (is_layered_allowed() && layered_window) { + DeleteObject(hBitmap); + + RECT r; + GetWindowRect(hWnd, &r); + dib_size = Size2i(r.right - r.left, r.bottom - r.top); + + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = dib_size.x; + bmi.bmiHeader.biHeight = dib_size.y; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; + hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); + SelectObject(hDC_dib, hBitmap); + + ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); + } +#endif + //return 0; // Jump Back + } break; + + case WM_ENTERSIZEMOVE: { + InputFilter::get_singleton()->release_pressed_events(); + move_timer_id = SetTimer(windows[window_id].hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC)NULL); + } break; + case WM_EXITSIZEMOVE: { + KillTimer(windows[window_id].hWnd, move_timer_id); + } break; + case WM_TIMER: { + if (wParam == move_timer_id) { + _process_key_events(); + if (!Main::is_iterating()) { + Main::iteration(); + } + } + } break; + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYUP: + case WM_KEYDOWN: { + + if (wParam == VK_SHIFT) + shift_mem = uMsg == WM_KEYDOWN; + if (wParam == VK_CONTROL) + control_mem = uMsg == WM_KEYDOWN; + if (wParam == VK_MENU) { + alt_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); + if (lParam & (1 << 24)) + gr_mem = alt_mem; + } + + if (mouse_mode == MOUSE_MODE_CAPTURED) { + // When SetCapture is used, ALT+F4 hotkey is ignored by Windows, so handle it ourselves + if (wParam == VK_F4 && alt_mem && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)) { + _send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST); + } + } + /* + if (wParam==VK_WIN) TODO wtf is this? + meta_mem=uMsg==WM_KEYDOWN; + */ + [[fallthrough]]; + } + case WM_CHAR: { + + ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); + + // Make sure we don't include modifiers for the modifier key itself. + KeyEvent ke; + ke.shift = (wParam != VK_SHIFT) ? shift_mem : false; + ke.alt = (!(wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false; + ke.control = (wParam != VK_CONTROL) ? control_mem : false; + ke.meta = meta_mem; + ke.uMsg = uMsg; + ke.window_id = window_id; + + if (ke.uMsg == WM_SYSKEYDOWN) + ke.uMsg = WM_KEYDOWN; + if (ke.uMsg == WM_SYSKEYUP) + ke.uMsg = WM_KEYUP; + + ke.wParam = wParam; + ke.lParam = lParam; + key_event_buffer[key_event_pos++] = ke; + + } break; + case WM_INPUTLANGCHANGEREQUEST: { + + // FIXME: Do something? + } break; + + case WM_TOUCH: { + + BOOL bHandled = FALSE; + UINT cInputs = LOWORD(wParam); + PTOUCHINPUT pInputs = memnew_arr(TOUCHINPUT, cInputs); + if (pInputs) { + if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) { + for (UINT i = 0; i < cInputs; i++) { + TOUCHINPUT ti = pInputs[i]; + POINT touch_pos = { + TOUCH_COORD_TO_PIXEL(ti.x), + TOUCH_COORD_TO_PIXEL(ti.y), + }; + ScreenToClient(hWnd, &touch_pos); + //do something with each touch input entry + if (ti.dwFlags & TOUCHEVENTF_MOVE) { + + _drag_event(window_id, touch_pos.x, touch_pos.y, ti.dwID); + } else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) { + + _touch_event(window_id, ti.dwFlags & TOUCHEVENTF_DOWN, touch_pos.x, touch_pos.y, ti.dwID); + }; + } + bHandled = TRUE; + } else { + /* handle the error here */ + } + memdelete_arr(pInputs); + } else { + /* handle the error here, probably out of memory */ + } + if (bHandled) { + CloseTouchInputHandle((HTOUCHINPUT)lParam); + return 0; + }; + + } break; + + case WM_DEVICECHANGE: { + + joypad->probe_joypads(); + } break; + case WM_SETCURSOR: { + if (LOWORD(lParam) == HTCLIENT) { + if (windows[window_id].window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) { + //Hide the cursor + if (hCursor == NULL) + hCursor = SetCursor(NULL); + else + SetCursor(NULL); + } else { + if (hCursor != NULL) { + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + cursor_set_shape(c); + hCursor = NULL; + } + } + } + + } break; + case WM_DROPFILES: { + + HDROP hDropInfo = (HDROP)wParam; + const int buffsize = 4096; + wchar_t buf[buffsize]; + + int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, NULL, 0); + + Vector<String> files; + + for (int i = 0; i < fcount; i++) { + + DragQueryFileW(hDropInfo, i, buf, buffsize); + String file = buf; + files.push_back(file); + } + + if (files.size() && !windows[window_id].drop_files_callback.is_null()) { + Variant v = files; + Variant *vp = &v; + Variant ret; + Callable::CallError ce; + windows[window_id].drop_files_callback.call((const Variant **)&vp, 1, ret, ce); + } + + } break; + + default: { + + if (user_proc) { + + return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); + }; + }; + } + + return DefWindowProcW(hWnd, uMsg, wParam, lParam); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + DisplayServerWindows *ds_win = static_cast<DisplayServerWindows *>(DisplayServer::get_singleton()); + if (ds_win) + return ds_win->WndProc(hWnd, uMsg, wParam, lParam); + else + return DefWindowProcW(hWnd, uMsg, wParam, lParam); +} + +void DisplayServerWindows::_process_key_events() { + + for (int i = 0; i < key_event_pos; i++) { + + KeyEvent &ke = key_event_buffer[i]; + switch (ke.uMsg) { + + case WM_CHAR: { + if ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR)) { + Ref<InputEventKey> k; + k.instance(); + + k->set_window_id(ke.window_id); + k->set_shift(ke.shift); + k->set_alt(ke.alt); + k->set_control(ke.control); + k->set_metakey(ke.meta); + k->set_pressed(true); + k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); + k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); + k->set_unicode(ke.wParam); + if (k->get_unicode() && gr_mem) { + k->set_alt(false); + k->set_control(false); + } + + if (k->get_unicode() < 32) + k->set_unicode(0); + + InputFilter::get_singleton()->accumulate_input_event(k); + } + + //do nothing + } break; + case WM_KEYUP: + case WM_KEYDOWN: { + + Ref<InputEventKey> k; + k.instance(); + + k->set_window_id(ke.window_id); + k->set_shift(ke.shift); + k->set_alt(ke.alt); + k->set_control(ke.control); + k->set_metakey(ke.meta); + + k->set_pressed(ke.uMsg == WM_KEYDOWN); + + if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) { + // Special case for Numpad Enter key + k->set_keycode(KEY_KP_ENTER); + } else { + k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); + } + + k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); + + if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) { + k->set_unicode(key_event_buffer[i + 1].wParam); + } + if (k->get_unicode() && gr_mem) { + k->set_alt(false); + k->set_control(false); + } + + if (k->get_unicode() < 32) + k->set_unicode(0); + + k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)))); + + InputFilter::get_singleton()->accumulate_input_event(k); + + } break; + } + } + + key_event_pos = 0; +} + +DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { + + DWORD dwExStyle; + DWORD dwStyle; + + _get_window_style(window_id_counter == MAIN_WINDOW_ID, p_mode == WINDOW_MODE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT), dwStyle, dwExStyle); + + RECT WindowRect; + + WindowRect.left = p_rect.position.x; + WindowRect.right = p_rect.position.x + p_rect.size.x; + WindowRect.top = p_rect.position.y; + WindowRect.bottom = p_rect.position.y + p_rect.size.y; + + AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); + + WindowID id = window_id_counter; + { + WindowData wd; + + wd.hWnd = CreateWindowExW( + dwExStyle, + L"Engine", L"", + dwStyle, + // (GetSystemMetrics(SM_CXSCREEN) - WindowRect.right) / 2, + // (GetSystemMetrics(SM_CYSCREEN) - WindowRect.bottom) / 2, + WindowRect.left, + WindowRect.top, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, NULL, hInstance, NULL); + if (!wd.hWnd) { + MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + return INVALID_WINDOW_ID; + } +#ifdef VULKAN_ENABLED + + if (rendering_driver == "vulkan") { + if (context_vulkan->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) { + memdelete(context_vulkan); + context_vulkan = NULL; + ERR_FAIL_V(INVALID_WINDOW_ID); + } + } +#endif + + RegisterTouchWindow(wd.hWnd, 0); + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = wd.hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + + DragAcceptFiles(wd.hWnd, true); + + // IME + wd.im_himc = ImmGetContext(wd.hWnd); + ImmReleaseContext(wd.hWnd, wd.im_himc); + + wd.im_position = Vector2(); + wd.last_pos = p_rect.position; + wd.width = p_rect.size.width; + wd.height = p_rect.size.height; + + windows[id] = wd; + + window_id_counter++; + } + + return id; +} + +GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr; +GetPointerPenInfoPtr DisplayServerWindows::win8p_GetPointerPenInfo = nullptr; + +typedef enum _SHC_PROCESS_DPI_AWARENESS { + SHC_PROCESS_DPI_UNAWARE = 0, + SHC_PROCESS_SYSTEM_DPI_AWARE = 1, + SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2 +} SHC_PROCESS_DPI_AWARENESS; + +DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + + //Note: Functions for pen input, available on Windows 8+ + HMODULE user32_lib = LoadLibraryW(L"user32.dll"); + if (user32_lib) { + win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); + win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); + } + + drop_events = false; + key_event_pos = 0; + + alt_mem = false; + gr_mem = false; + shift_mem = false; + control_mem = false; + meta_mem = false; + console_visible = IsWindowVisible(GetConsoleWindow()); + hInstance = ((OS_Windows *)OS::get_singleton())->get_hinstance(); + + pressrc = 0; + old_invalid = true; + mouse_mode = MOUSE_MODE_VISIBLE; + + outside = true; + + if (OS::get_singleton()->is_hidpi_allowed()) { + HMODULE Shcore = LoadLibraryW(L"Shcore.dll"); + + if (Shcore != NULL) { + typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS); + + SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)GetProcAddress(Shcore, "SetProcessDpiAwareness"); + + if (SetProcessDpiAwareness) { + SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE); + } + } + } + + memset(&wc, 0, sizeof(WNDCLASSEXW)); + wc.cbSize = sizeof(WNDCLASSEXW); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC)::WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + //wc.hInstance = hInstance; + wc.hInstance = hInstance ? hInstance : GetModuleHandle(NULL); + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = L"Engine"; + + if (!RegisterClassExW(&wc)) { + MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); + r_error = ERR_UNAVAILABLE; + return; + } + + use_raw_input = true; + + RAWINPUTDEVICE Rid[1]; + + Rid[0].usUsagePage = 0x01; + Rid[0].usUsage = 0x02; + Rid[0].dwFlags = 0; + Rid[0].hwndTarget = 0; + + if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) { + //registration failed. + use_raw_input = false; + } + + rendering_driver = "vulkan"; + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + + context_vulkan = memnew(VulkanContextWindows); + if (context_vulkan->initialize() != OK) { + memdelete(context_vulkan); + context_vulkan = NULL; + r_error = ERR_UNAVAILABLE; + return; + } + } +#endif +#if defined(OPENGL_ENABLED) + if (rendering_driver_index == VIDEO_DRIVER_GLES2) { + + context_gles2 = memnew(ContextGL_Windows(hWnd, false)); + + if (context_gles2->initialize() != OK) { + memdelete(context_gles2); + context_gles2 = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } + + context_gles2->set_use_vsync(video_mode.use_vsync); + set_vsync_via_compositor(video_mode.vsync_via_compositor); + + if (RasterizerGLES2::is_viable() == OK) { + RasterizerGLES2::register_config(); + RasterizerGLES2::make_current(); + } else { + memdelete(context_gles2); + context_gles2 = NULL; + ERR_FAIL_V(ERR_UNAVAILABLE); + } + } +#endif + WindowID main_window = _create_window(p_mode, 0, Rect2i(Point2i(), p_resolution)); + for (int i = 0; i < WINDOW_FLAG_MAX; i++) { + if (p_flags & (1 << i)) { + window_set_flag(WindowFlags(i), true, main_window); + } + } + + ShowWindow(windows[MAIN_WINDOW_ID].hWnd, SW_SHOW); // Show The Window + SetForegroundWindow(windows[MAIN_WINDOW_ID].hWnd); // Slightly Higher Priority + SetFocus(windows[MAIN_WINDOW_ID].hWnd); // Sets Keyboard Focus To + +#if defined(VULKAN_ENABLED) + + if (rendering_driver == "vulkan") { + + rendering_device_vulkan = memnew(RenderingDeviceVulkan); + rendering_device_vulkan->initialize(context_vulkan); + + RasterizerRD::make_current(); + } +#endif + + move_timer_id = 1; + + //set_ime_active(false); + + if (!OS::get_singleton()->is_in_low_processor_usage_mode()) { + //SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); + SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); + DWORD index = 0; + HANDLE handle = AvSetMmThreadCharacteristics("Games", &index); + if (handle) + AvSetMmThreadPriority(handle, AVRT_PRIORITY_CRITICAL); + + // This is needed to make sure that background work does not starve the main thread. + // This is only setting priority of this thread, not the whole process. + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + } + + cursor_shape = CURSOR_ARROW; + + _update_real_mouse_position(MAIN_WINDOW_ID); + + joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd); + + r_error = OK; + + ((OS_Windows *)OS::get_singleton())->set_main_window(windows[MAIN_WINDOW_ID].hWnd); + InputFilter::get_singleton()->set_event_dispatch_function(_dispatch_input_events); +} + +Vector<String> DisplayServerWindows::get_rendering_drivers_func() { + Vector<String> drivers; + +#ifdef VULKAN_ENABLED + drivers.push_back("vulkan"); +#endif +#ifdef OPENGL_ENABLED + drivers.push_back("opengl"); +#endif + + return drivers; +} + +DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + + return memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_flags, p_resolution, r_error)); +} + +void DisplayServerWindows::register_windows_driver() { + + register_create_function("windows", create_func, get_rendering_drivers_func); +} + +DisplayServerWindows::~DisplayServerWindows() { + + delete joypad; + touch_state.clear(); + + cursors_cache.clear(); + +#if defined(VULKAN_ENABLED) + if (rendering_driver == "vulkan") { + + if (rendering_device_vulkan) { + rendering_device_vulkan->finalize(); + memdelete(rendering_device_vulkan); + } + + if (context_vulkan) + memdelete(context_vulkan); + } +#endif + + if (user_proc) { + SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); + }; + + if (windows.has(MAIN_WINDOW_ID)) { +#ifdef VULKAN_ENABLED + if (rendering_driver == "vulkan") { + context_vulkan->window_destroy(MAIN_WINDOW_ID); + } +#endif + + DestroyWindow(windows[MAIN_WINDOW_ID].hWnd); + } +} diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h new file mode 100644 index 0000000000..47bb3f59a6 --- /dev/null +++ b/platform/windows/display_server_windows.h @@ -0,0 +1,389 @@ +#ifndef DISPLAY_SERVER_WINDOWS_H +#define DISPLAY_SERVER_WINDOWS_H + +#include "servers/display_server.h" + +#include "core/input/input_filter.h" +#include "core/os/os.h" +#include "core/project_settings.h" +#include "crash_handler_windows.h" +#include "drivers/unix/ip_unix.h" +#include "drivers/wasapi/audio_driver_wasapi.h" +#include "drivers/winmidi/midi_driver_winmidi.h" +#include "joypad_windows.h" +#include "key_mapping_windows.h" +#include "servers/audio_server.h" +#include "servers/visual/rasterizer.h" +#include "servers/visual/rasterizer_rd/rasterizer_rd.h" +#include "servers/visual_server.h" + +#ifdef XAUDIO2_ENABLED +#include "drivers/xaudio2/audio_driver_xaudio2.h" +#endif + +#if defined(OPENGL_ENABLED) +#include "context_gl_windows.h" +#endif + +#if defined(VULKAN_ENABLED) +#include "drivers/vulkan/rendering_device_vulkan.h" +#include "platform/windows/vulkan_context_win.h" +#endif + +#include <fcntl.h> +#include <io.h> +#include <stdio.h> +#include <windows.h> +#include <windowsx.h> + +#ifndef POINTER_STRUCTURES + +#define POINTER_STRUCTURES + +typedef DWORD POINTER_INPUT_TYPE; +typedef UINT32 POINTER_FLAGS; +typedef UINT32 PEN_FLAGS; +typedef UINT32 PEN_MASK; + +enum tagPOINTER_INPUT_TYPE { + PT_POINTER = 0x00000001, + PT_TOUCH = 0x00000002, + PT_PEN = 0x00000003, + PT_MOUSE = 0x00000004, + PT_TOUCHPAD = 0x00000005 +}; + +typedef enum tagPOINTER_BUTTON_CHANGE_TYPE { + POINTER_CHANGE_NONE, + POINTER_CHANGE_FIRSTBUTTON_DOWN, + POINTER_CHANGE_FIRSTBUTTON_UP, + POINTER_CHANGE_SECONDBUTTON_DOWN, + POINTER_CHANGE_SECONDBUTTON_UP, + POINTER_CHANGE_THIRDBUTTON_DOWN, + POINTER_CHANGE_THIRDBUTTON_UP, + POINTER_CHANGE_FOURTHBUTTON_DOWN, + POINTER_CHANGE_FOURTHBUTTON_UP, + POINTER_CHANGE_FIFTHBUTTON_DOWN, + POINTER_CHANGE_FIFTHBUTTON_UP, +} POINTER_BUTTON_CHANGE_TYPE; + +typedef struct tagPOINTER_INFO { + POINTER_INPUT_TYPE pointerType; + UINT32 pointerId; + UINT32 frameId; + POINTER_FLAGS pointerFlags; + HANDLE sourceDevice; + HWND hwndTarget; + POINT ptPixelLocation; + POINT ptHimetricLocation; + POINT ptPixelLocationRaw; + POINT ptHimetricLocationRaw; + DWORD dwTime; + UINT32 historyCount; + INT32 InputData; + DWORD dwKeyStates; + UINT64 PerformanceCount; + POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; +} POINTER_INFO; + +typedef struct tagPOINTER_PEN_INFO { + POINTER_INFO pointerInfo; + PEN_FLAGS penFlags; + PEN_MASK penMask; + UINT32 pressure; + UINT32 rotation; + INT32 tiltX; + INT32 tiltY; +} POINTER_PEN_INFO; + +#endif //POINTER_STRUCTURES + +typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type); +typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info); + +typedef struct { + BYTE bWidth; // Width, in pixels, of the image + BYTE bHeight; // Height, in pixels, of the image + BYTE bColorCount; // Number of colors in image (0 if >=8bpp) + BYTE bReserved; // Reserved ( must be 0) + WORD wPlanes; // Color Planes + WORD wBitCount; // Bits per pixel + DWORD dwBytesInRes; // How many bytes in this resource? + DWORD dwImageOffset; // Where in the file is this image? +} ICONDIRENTRY, *LPICONDIRENTRY; + +typedef struct { + WORD idReserved; // Reserved (must be 0) + WORD idType; // Resource Type (1 for icons) + WORD idCount; // How many images? + ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) +} ICONDIR, *LPICONDIR; + +class DisplayServerWindows : public DisplayServer { + //No need to register, it's platform-specific and nothing is added + //GDCLASS(DisplayServerWindows, DisplayServer) + + _THREAD_SAFE_CLASS_ + + static GetPointerTypePtr win8p_GetPointerType; + static GetPointerPenInfoPtr win8p_GetPointerPenInfo; + + void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap); + + enum { + KEY_EVENT_BUFFER_SIZE = 512 + }; + + struct KeyEvent { + + WindowID window_id; + bool alt, shift, control, meta; + UINT uMsg; + WPARAM wParam; + LPARAM lParam; + }; + + KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE]; + int key_event_pos; + + bool old_invalid; + bool outside; + int old_x, old_y; + Point2i center; + +#if defined(OPENGL_ENABLED) + ContextGL_Windows *context_gles2; +#endif + +#if defined(VULKAN_ENABLED) + VulkanContextWindows *context_vulkan; + RenderingDeviceVulkan *rendering_device_vulkan; +#endif + + Map<int, Vector2> touch_state; + + int pressrc; + HINSTANCE hInstance; // Holds The Instance Of The Application + String rendering_driver; + + struct WindowData { + HWND hWnd; + //layered window + + bool preserve_window_size = false; + bool pre_fs_valid = false; + RECT pre_fs_rect; + bool maximized = false; + bool minimized = false; + bool fullscreen = false; + bool borderless = false; + bool resizable = true; + bool window_focused = false; + bool was_maximized = false; + bool always_on_top = false; + bool no_focus = false; + bool window_has_focus = false; + + HBITMAP hBitmap; //DIB section for layered window + uint8_t *dib_data = nullptr; + Size2 dib_size; + HDC hDC_dib; + Size2 min_size; + Size2 max_size; + int width = 0, height = 0; + + Size2 window_rect; + Point2 last_pos; + + ObjectID instance_id; + + // IME + HIMC im_himc; + Vector2 im_position; + + bool layered_window = false; + + Callable rect_changed_callback; + Callable event_callback; + Callable input_event_callback; + Callable input_text_callback; + Callable drop_files_callback; + + WindowID transient_parent = INVALID_WINDOW_ID; + Set<WindowID> transient_children; + }; + + JoypadWindows *joypad; + + WindowID _create_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect); + WindowID window_id_counter = MAIN_WINDOW_ID; + Map<WindowID, WindowData> windows; + + WindowID last_focused_window = INVALID_WINDOW_ID; + + uint32_t move_timer_id; + + HCURSOR hCursor; + + WNDPROC user_proc = nullptr; + + void _send_window_event(const WindowData &wd, WindowEvent p_event); + void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_borderless, bool p_resizable, bool p_maximized, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex); + + MouseMode mouse_mode; + bool alt_mem = false; + bool gr_mem = false; + bool shift_mem = false; + bool control_mem = false; + bool meta_mem = false; + bool force_quit = false; + uint32_t last_button_state = 0; + bool use_raw_input = false; + bool drop_events = false; + bool console_visible = false; + + WNDCLASSEXW wc; + + HCURSOR cursors[CURSOR_MAX] = { NULL }; + CursorShape cursor_shape; + Map<CursorShape, Vector<Variant>> cursors_cache; + + void _drag_event(WindowID p_window, float p_x, float p_y, int idx); + void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx); + + void _update_window_style(WindowID p_window, bool p_repaint = true, bool p_maximized = false); + + void _update_real_mouse_position(WindowID p_window); + + void _set_mouse_mode_impl(MouseMode p_mode); + + void _process_key_events(); + + static void _dispatch_input_events(const Ref<InputEvent> &p_event); + void _dispatch_input_event(const Ref<InputEvent> &p_event); + +public: + LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + virtual bool has_feature(Feature p_feature) const; + virtual String get_name() const; + + virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); + + virtual void mouse_set_mode(MouseMode p_mode); + virtual MouseMode mouse_get_mode() const; + + virtual void mouse_warp_to_position(const Point2i &p_to); + virtual Point2i mouse_get_position() const; + virtual int mouse_get_button_state() const; + + virtual void clipboard_set(const String &p_text); + virtual String clipboard_get() const; + + virtual int get_screen_count() const; + virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + + virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW); + ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + + virtual void screen_set_keep_on(bool p_enable); //disable screensaver + virtual bool screen_is_kept_on() const; + + virtual Vector<DisplayServer::WindowID> get_window_list() const; + + virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); + virtual void delete_sub_window(WindowID p_window); + + virtual WindowID get_window_at_screen_position(const Point2i &p_position) const; + + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID); + virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID); + + virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const; + virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID); + + virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const; + virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID); + + virtual void window_set_transient(WindowID p_window, WindowID p_parent); + + virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID); + virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const; + virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; //wtf is this? should probable use proper name + + virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID); + virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID); + virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const; + + virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID); + virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID); + + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const; + + virtual bool can_any_window_draw() const; + + virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); + + virtual void console_set_visible(bool p_enabled); + virtual bool is_console_visible() const; + + virtual void cursor_set_shape(CursorShape p_shape); + virtual CursorShape cursor_get_shape() const; + virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); + + virtual bool get_swap_ok_cancel(); + + virtual void enable_for_stealing_focus(OS::ProcessID pid); + + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + + virtual void process_events(); + + virtual void force_process_and_drop_events(); + + virtual void release_rendering_thread(); + virtual void make_rendering_thread(); + virtual void swap_buffers(); + + virtual void set_native_icon(const String &p_filename); + virtual void set_icon(const Ref<Image> &p_icon); + + virtual void vsync_set_use_via_compositor(bool p_enable); + virtual bool vsync_is_using_via_compositor() const; + + virtual void set_context(Context p_context); + + static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + static Vector<String> get_rendering_drivers_func(); + static void register_windows_driver(); + + DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + ~DisplayServerWindows(); +}; + +#endif // DISPLAY_SERVER_WINDOWS_H diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index 49432435b9..9de1b7b194 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -52,9 +52,9 @@ DWORD WINAPI _xinput_set_state(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration) JoypadWindows::JoypadWindows() { } -JoypadWindows::JoypadWindows(InputDefault *_input, HWND *hwnd) { +JoypadWindows::JoypadWindows(HWND *hwnd) { - input = _input; + input = InputFilter::get_singleton(); hWnd = hwnd; joypad_count = 0; dinput = NULL; @@ -436,46 +436,46 @@ void JoypadWindows::post_hat(int p_device, DWORD p_dpad) { // BOOL POVCentered = (LOWORD(dwPOV) == 0xFFFF);" // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee416628(v%3Dvs.85)#remarks if (LOWORD(p_dpad) == 0xFFFF) { - dpad_val = InputDefault::HAT_MASK_CENTER; + dpad_val = InputFilter::HAT_MASK_CENTER; } if (p_dpad == 0) { - dpad_val = InputDefault::HAT_MASK_UP; + dpad_val = InputFilter::HAT_MASK_UP; } else if (p_dpad == 4500) { - dpad_val = (InputDefault::HAT_MASK_UP | InputDefault::HAT_MASK_RIGHT); + dpad_val = (InputFilter::HAT_MASK_UP | InputFilter::HAT_MASK_RIGHT); } else if (p_dpad == 9000) { - dpad_val = InputDefault::HAT_MASK_RIGHT; + dpad_val = InputFilter::HAT_MASK_RIGHT; } else if (p_dpad == 13500) { - dpad_val = (InputDefault::HAT_MASK_RIGHT | InputDefault::HAT_MASK_DOWN); + dpad_val = (InputFilter::HAT_MASK_RIGHT | InputFilter::HAT_MASK_DOWN); } else if (p_dpad == 18000) { - dpad_val = InputDefault::HAT_MASK_DOWN; + dpad_val = InputFilter::HAT_MASK_DOWN; } else if (p_dpad == 22500) { - dpad_val = (InputDefault::HAT_MASK_DOWN | InputDefault::HAT_MASK_LEFT); + dpad_val = (InputFilter::HAT_MASK_DOWN | InputFilter::HAT_MASK_LEFT); } else if (p_dpad == 27000) { - dpad_val = InputDefault::HAT_MASK_LEFT; + dpad_val = InputFilter::HAT_MASK_LEFT; } else if (p_dpad == 31500) { - dpad_val = (InputDefault::HAT_MASK_LEFT | InputDefault::HAT_MASK_UP); + dpad_val = (InputFilter::HAT_MASK_LEFT | InputFilter::HAT_MASK_UP); } input->joy_hat(p_device, dpad_val); }; -InputDefault::JoyAxis JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const { +InputFilter::JoyAxis JoypadWindows::axis_correct(int p_val, bool p_xinput, bool p_trigger, bool p_negate) const { - InputDefault::JoyAxis jx; + InputFilter::JoyAxis jx; if (Math::abs(p_val) < MIN_JOY_AXIS) { jx.min = p_trigger ? 0 : -1; jx.value = 0.0f; diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h index ab85bc60ac..f010fd08ff 100644 --- a/platform/windows/joypad_windows.h +++ b/platform/windows/joypad_windows.h @@ -52,7 +52,7 @@ class JoypadWindows { public: JoypadWindows(); - JoypadWindows(InputDefault *_input, HWND *hwnd); + JoypadWindows(HWND *hwnd); ~JoypadWindows(); void probe_joypads(); @@ -117,7 +117,7 @@ private: HWND *hWnd; HANDLE xinput_dll; LPDIRECTINPUT8 dinput; - InputDefault *input; + InputFilter *input; int id_to_change; int joypad_count; @@ -141,7 +141,7 @@ private: void joypad_vibration_start_xinput(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp); void joypad_vibration_stop_xinput(int p_device, uint64_t p_timestamp); - InputDefault::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const; + InputFilter::JoyAxis axis_correct(int p_val, bool p_xinput = false, bool p_trigger = false, bool p_negate = false) const; XInputGetState_t xinput_get_state; XInputSetState_t xinput_set_state; }; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 041a5bffa6..f78c87be93 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -37,15 +37,6 @@ #include "core/debugger/script_debugger.h" #include "core/io/marshalls.h" #include "core/version_generated.gen.h" - -#if defined(OPENGL_ENABLED) -#include "drivers/gles2/rasterizer_gles2.h" -#endif - -#if defined(VULKAN_ENABLED) -#include "servers/visual/rasterizer_rd/rasterizer_rd.h" -#endif - #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" #include "drivers/windows/rw_lock_windows.h" @@ -53,6 +44,7 @@ #include "joypad_windows.h" #include "lang_table.h" #include "main/main.h" +#include "platform/windows/display_server_windows.h" #include "servers/audio_server.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" @@ -86,30 +78,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; #define GetProcAddress (void *)GetProcAddress #endif -typedef struct { - int count; - int screen; - Size2 size; -} EnumSizeData; - -typedef struct { - int count; - int screen; - Point2 pos; -} EnumPosData; - -static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumSizeData *data = (EnumSizeData *)dwData; - if (data->count == data->screen) { - data->size.x = lprcMonitor->right - lprcMonitor->left; - data->size.y = lprcMonitor->bottom - lprcMonitor->top; - } - - data->count++; - return TRUE; -} - #ifdef DEBUG_ENABLED static String format_error_message(DWORD id) { @@ -125,8 +93,6 @@ static String format_error_message(DWORD id) { } #endif // DEBUG_ENABLED -extern HINSTANCE godot_hinstance; - void RedirectIOToConsole() { int hConHandle; @@ -208,24 +174,16 @@ BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) { } } -GetPointerTypePtr OS_Windows::win8p_GetPointerType = NULL; -GetPointerPenInfoPtr OS_Windows::win8p_GetPointerPenInfo = NULL; - void OS_Windows::initialize_debugging() { SetConsoleCtrlHandler(HandlerRoutine, TRUE); } -void OS_Windows::initialize_core() { +void OS_Windows::initialize() { crash_handler.initialize(); - last_button_state = 0; - //RedirectIOToConsole(); - maximized = false; - minimized = false; - borderless = false; ThreadWindows::make_default(); RWLockWindows::make_default(); @@ -255,1371 +213,9 @@ void OS_Windows::initialize_core() { process_map = memnew((Map<ProcessID, ProcessInfo>)); IP_Unix::make_default(); - - cursor_shape = CURSOR_ARROW; -} - -bool OS_Windows::can_draw() const { - - return !minimized; -}; - -#define MI_WP_SIGNATURE 0xFF515700 -#define SIGNATURE_MASK 0xFFFFFF00 -// Keeping the name suggested by Microsoft, but this macro really answers: -// Is this mouse event emulated from touch or pen input? -#define IsPenEvent(dw) (((dw)&SIGNATURE_MASK) == MI_WP_SIGNATURE) -// This one tells whether the event comes from touchscreen (and not from pen) -#define IsTouchEvent(dw) (IsPenEvent(dw) && ((dw)&0x80)) - -void OS_Windows::_touch_event(bool p_pressed, float p_x, float p_y, int idx) { - - // Defensive - if (touch_state.has(idx) == p_pressed) - return; - - if (p_pressed) { - touch_state.insert(idx, Vector2(p_x, p_y)); - } else { - touch_state.erase(idx); - } - - Ref<InputEventScreenTouch> event; - event.instance(); - event->set_index(idx); - event->set_pressed(p_pressed); - event->set_position(Vector2(p_x, p_y)); - - if (main_loop) { - input->accumulate_input_event(event); - } -}; - -void OS_Windows::_drag_event(float p_x, float p_y, int idx) { - - Map<int, Vector2>::Element *curr = touch_state.find(idx); - // Defensive - if (!curr) - return; - - if (curr->get() == Vector2(p_x, p_y)) - return; - - Ref<InputEventScreenDrag> event; - event.instance(); - event->set_index(idx); - event->set_position(Vector2(p_x, p_y)); - event->set_relative(Vector2(p_x, p_y) - curr->get()); - - if (main_loop) - input->accumulate_input_event(event); - - curr->get() = Vector2(p_x, p_y); -}; - -LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - - if (drop_events) { - - if (user_proc) { - - return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); - } else { - return DefWindowProcW(hWnd, uMsg, wParam, lParam); - } - }; - - switch (uMsg) // Check For Windows Messages - { - case WM_SETFOCUS: { - window_has_focus = true; - - // Restore mouse mode - _set_mouse_mode_impl(mouse_mode); - - break; - } - case WM_KILLFOCUS: { - window_has_focus = false; - - // Release capture unconditionally because it can be set due to dragging, in addition to captured mode - ReleaseCapture(); - - // Release every touch to avoid sticky points - for (Map<int, Vector2>::Element *E = touch_state.front(); E; E = E->next()) { - _touch_event(false, E->get().x, E->get().y, E->key()); - } - touch_state.clear(); - - break; - } - case WM_ACTIVATE: // Watch For Window Activate Message - { - minimized = HIWORD(wParam) != 0; - if (!main_loop) { - return 0; - }; - if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { - - main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); - window_focused = true; - alt_mem = false; - control_mem = false; - shift_mem = false; - } else { // WM_INACTIVE - input->release_pressed_events(); - main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); - window_focused = false; - alt_mem = false; - }; - - return 0; // Return To The Message Loop - } - case WM_GETMINMAXINFO: { - if (video_mode.resizable && !video_mode.fullscreen) { - Size2 decor = get_real_window_size() - get_window_size(); // Size of window decorations - MINMAXINFO *min_max_info = (MINMAXINFO *)lParam; - if (min_size != Size2()) { - min_max_info->ptMinTrackSize.x = min_size.x + decor.x; - min_max_info->ptMinTrackSize.y = min_size.y + decor.y; - } - if (max_size != Size2()) { - min_max_info->ptMaxTrackSize.x = max_size.x + decor.x; - min_max_info->ptMaxTrackSize.y = max_size.y + decor.y; - } - return 0; - } else { - break; - } - } - case WM_PAINT: - - Main::force_redraw(); - break; - - case WM_SYSCOMMAND: // Intercept System Commands - { - switch (wParam) // Check System Calls - { - case SC_SCREENSAVE: // Screensaver Trying To Start? - case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? - return 0; // Prevent From Happening - case SC_KEYMENU: - if ((lParam >> 16) <= 0) - return 0; - } - break; // Exit - } - - case WM_CLOSE: // Did We Receive A Close Message? - { - if (main_loop) - main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); - //force_quit=true; - return 0; // Jump Back - } - case WM_MOUSELEAVE: { - - old_invalid = true; - outside = true; - if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) - main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT); - - } break; - case WM_INPUT: { - if (mouse_mode != MOUSE_MODE_CAPTURED || !use_raw_input) { - break; - } - - UINT dwSize; - - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); - LPBYTE lpb = new BYTE[dwSize]; - if (lpb == NULL) { - return 0; - } - - if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) - OutputDebugString(TEXT("GetRawInputData does not return correct size !\n")); - - RAWINPUT *raw = (RAWINPUT *)lpb; - - if (raw->header.dwType == RIM_TYPEMOUSE) { - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_control(control_mem); - mm->set_shift(shift_mem); - mm->set_alt(alt_mem); - - mm->set_button_mask(last_button_state); - - Point2i c(video_mode.width / 2, video_mode.height / 2); - - // centering just so it works as before - POINT pos = { (int)c.x, (int)c.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - - mm->set_position(c); - mm->set_global_position(c); - input->set_mouse_position(c); - mm->set_speed(Vector2(0, 0)); - - if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE) { - mm->set_relative(Vector2(raw->data.mouse.lLastX, raw->data.mouse.lLastY)); - - } else if (raw->data.mouse.usFlags == MOUSE_MOVE_ABSOLUTE) { - - int nScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); - int nScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); - int nScreenLeft = GetSystemMetrics(SM_XVIRTUALSCREEN); - int nScreenTop = GetSystemMetrics(SM_YVIRTUALSCREEN); - - Vector2 abs_pos( - (double(raw->data.mouse.lLastX) - 65536.0 / (nScreenWidth)) * nScreenWidth / 65536.0 + nScreenLeft, - (double(raw->data.mouse.lLastY) - 65536.0 / (nScreenHeight)) * nScreenHeight / 65536.0 + nScreenTop); - - POINT coords; //client coords - coords.x = abs_pos.x; - coords.y = abs_pos.y; - - ScreenToClient(hWnd, &coords); - - mm->set_relative(Vector2(coords.x - old_x, coords.y - old_y)); - old_x = coords.x; - old_y = coords.y; - - /*Input.mi.dx = (int)((((double)(pos.x)-nScreenLeft) * 65536) / nScreenWidth + 65536 / (nScreenWidth)); - Input.mi.dy = (int)((((double)(pos.y)-nScreenTop) * 65536) / nScreenHeight + 65536 / (nScreenHeight)); - */ - } - - if (window_has_focus && main_loop && mm->get_relative() != Vector2()) - input->accumulate_input_event(mm); - } - delete[] lpb; - } break; - case WM_POINTERUPDATE: { - if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { - break; - } - - if (!win8p_GetPointerType || !win8p_GetPointerPenInfo) { - break; - } - - uint32_t pointer_id = LOWORD(wParam); - POINTER_INPUT_TYPE pointer_type = PT_POINTER; - if (!win8p_GetPointerType(pointer_id, &pointer_type)) { - break; - } - - if (pointer_type != PT_PEN) { - break; - } - - POINTER_PEN_INFO pen_info; - if (!win8p_GetPointerPenInfo(pointer_id, &pen_info)) { - break; - } - - if (input->is_emulating_mouse_from_touch()) { - // Universal translation enabled; ignore OS translation - LPARAM extra = GetMessageExtraInfo(); - if (IsTouchEvent(extra)) { - break; - } - } - - if (outside) { - //mouse enter - - if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) - main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - outside = false; - - //Once-Off notification, must call again.... - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&tme); - } - - // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. - if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) - break; - - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_pressure(pen_info.pressure ? (float)pen_info.pressure / 1024 : 0); - mm->set_tilt(Vector2(pen_info.tiltX ? (float)pen_info.tiltX / 90 : 0, pen_info.tiltY ? (float)pen_info.tiltY / 90 : 0)); - - mm->set_control((wParam & MK_CONTROL) != 0); - mm->set_shift((wParam & MK_SHIFT) != 0); - mm->set_alt(alt_mem); - - mm->set_button_mask(last_button_state); - - POINT coords; //client coords - coords.x = GET_X_LPARAM(lParam); - coords.y = GET_Y_LPARAM(lParam); - - ScreenToClient(hWnd, &coords); - - mm->set_position(Vector2(coords.x, coords.y)); - mm->set_global_position(Vector2(coords.x, coords.y)); - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - - Point2i c(video_mode.width / 2, video_mode.height / 2); - old_x = c.x; - old_y = c.y; - - if (mm->get_position() == c) { - center = c; - return 0; - } - - Point2i ncenter = mm->get_position(); - center = ncenter; - POINT pos = { (int)c.x, (int)c.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - } - - input->set_mouse_position(mm->get_position()); - mm->set_speed(input->get_last_mouse_speed()); - - if (old_invalid) { - - old_x = mm->get_position().x; - old_y = mm->get_position().y; - old_invalid = false; - } - - mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); - old_x = mm->get_position().x; - old_y = mm->get_position().y; - if (window_has_focus && main_loop) - input->parse_input_event(mm); - - return 0; //Pointer event handled return 0 to avoid duplicate WM_MOUSEMOVE event - } break; - case WM_MOUSEMOVE: { - if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) { - break; - } - - if (input->is_emulating_mouse_from_touch()) { - // Universal translation enabled; ignore OS translation - LPARAM extra = GetMessageExtraInfo(); - if (IsTouchEvent(extra)) { - break; - } - } - - if (outside) { - //mouse enter - - if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED) - main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - outside = false; - - //Once-Off notification, must call again.... - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&tme); - } - - // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. - if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) - break; - - Ref<InputEventMouseMotion> mm; - mm.instance(); - - mm->set_control((wParam & MK_CONTROL) != 0); - mm->set_shift((wParam & MK_SHIFT) != 0); - mm->set_alt(alt_mem); - - mm->set_button_mask(last_button_state); - - mm->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - mm->set_global_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - - Point2i c(video_mode.width / 2, video_mode.height / 2); - old_x = c.x; - old_y = c.y; - - if (mm->get_position() == c) { - center = c; - return 0; - } - - Point2i ncenter = mm->get_position(); - center = ncenter; - POINT pos = { (int)c.x, (int)c.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - } - - input->set_mouse_position(mm->get_position()); - mm->set_speed(input->get_last_mouse_speed()); - - if (old_invalid) { - - old_x = mm->get_position().x; - old_y = mm->get_position().y; - old_invalid = false; - } - - mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); - old_x = mm->get_position().x; - old_y = mm->get_position().y; - if (window_has_focus && main_loop) - input->accumulate_input_event(mm); - - } break; - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - if (input->is_emulating_mouse_from_touch()) { - // Universal translation enabled; ignore OS translations for left button - LPARAM extra = GetMessageExtraInfo(); - if (IsTouchEvent(extra)) { - break; - } - } - [[fallthrough]]; - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: - case WM_XBUTTONDOWN: - case WM_XBUTTONUP: { - - Ref<InputEventMouseButton> mb; - mb.instance(); - - switch (uMsg) { - case WM_LBUTTONDOWN: { - mb->set_pressed(true); - mb->set_button_index(1); - } break; - case WM_LBUTTONUP: { - mb->set_pressed(false); - mb->set_button_index(1); - } break; - case WM_MBUTTONDOWN: { - mb->set_pressed(true); - mb->set_button_index(3); - } break; - case WM_MBUTTONUP: { - mb->set_pressed(false); - mb->set_button_index(3); - } break; - case WM_RBUTTONDOWN: { - mb->set_pressed(true); - mb->set_button_index(2); - } break; - case WM_RBUTTONUP: { - mb->set_pressed(false); - mb->set_button_index(2); - } break; - case WM_LBUTTONDBLCLK: { - mb->set_pressed(true); - mb->set_button_index(1); - mb->set_doubleclick(true); - } break; - case WM_RBUTTONDBLCLK: { - mb->set_pressed(true); - mb->set_button_index(2); - mb->set_doubleclick(true); - } break; - case WM_MBUTTONDBLCLK: { - mb->set_pressed(true); - mb->set_button_index(3); - mb->set_doubleclick(true); - } break; - case WM_MOUSEWHEEL: { - - mb->set_pressed(true); - int motion = (short)HIWORD(wParam); - if (!motion) - return 0; - - if (motion > 0) - mb->set_button_index(BUTTON_WHEEL_UP); - else - mb->set_button_index(BUTTON_WHEEL_DOWN); - - } break; - case WM_MOUSEHWHEEL: { - - mb->set_pressed(true); - int motion = (short)HIWORD(wParam); - if (!motion) - return 0; - - if (motion < 0) { - mb->set_button_index(BUTTON_WHEEL_LEFT); - mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); - } else { - mb->set_button_index(BUTTON_WHEEL_RIGHT); - mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); - } - } break; - case WM_XBUTTONDOWN: { - - mb->set_pressed(true); - if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); - else - mb->set_button_index(BUTTON_XBUTTON2); - } break; - case WM_XBUTTONUP: { - - mb->set_pressed(false); - if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); - else - mb->set_button_index(BUTTON_XBUTTON2); - } break; - case WM_XBUTTONDBLCLK: { - - mb->set_pressed(true); - if (HIWORD(wParam) == XBUTTON1) - mb->set_button_index(BUTTON_XBUTTON1); - else - mb->set_button_index(BUTTON_XBUTTON2); - mb->set_doubleclick(true); - } break; - default: { - return 0; - } - } - - mb->set_control((wParam & MK_CONTROL) != 0); - mb->set_shift((wParam & MK_SHIFT) != 0); - mb->set_alt(alt_mem); - //mb->get_alt()=(wParam&MK_MENU)!=0; - if (mb->is_pressed()) - last_button_state |= (1 << (mb->get_button_index() - 1)); - else - last_button_state &= ~(1 << (mb->get_button_index() - 1)); - mb->set_button_mask(last_button_state); - - mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - - if (mouse_mode == MOUSE_MODE_CAPTURED && !use_raw_input) { - - mb->set_position(Vector2(old_x, old_y)); - } - - if (uMsg != WM_MOUSEWHEEL && uMsg != WM_MOUSEHWHEEL) { - if (mb->is_pressed()) { - - if (++pressrc > 0 && mouse_mode != MOUSE_MODE_CAPTURED) - SetCapture(hWnd); - } else { - - if (--pressrc <= 0) { - if (mouse_mode != MOUSE_MODE_CAPTURED) { - ReleaseCapture(); - } - pressrc = 0; - } - } - } else { - // for reasons unknown to mankind, wheel comes in screen coordinates - POINT coords; - coords.x = mb->get_position().x; - coords.y = mb->get_position().y; - - ScreenToClient(hWnd, &coords); - - mb->set_position(Vector2(coords.x, coords.y)); - } - - mb->set_global_position(mb->get_position()); - - if (main_loop) { - input->accumulate_input_event(mb); - if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { - //send release for mouse wheel - Ref<InputEventMouseButton> mbd = mb->duplicate(); - last_button_state &= ~(1 << (mbd->get_button_index() - 1)); - mbd->set_button_mask(last_button_state); - mbd->set_pressed(false); - input->accumulate_input_event(mbd); - } - } - } break; - - case WM_MOVE: { - if (!IsIconic(hWnd)) { - int x = LOWORD(lParam); - int y = HIWORD(lParam); - last_pos = Point2(x, y); - } - } break; - - case WM_SIZE: { - // Ignore size when a SIZE_MINIMIZED event is triggered - if (wParam != SIZE_MINIMIZED) { - int window_w = LOWORD(lParam); - int window_h = HIWORD(lParam); - if (window_w > 0 && window_h > 0 && !preserve_window_size) { - video_mode.width = window_w; - video_mode.height = window_h; - } else { - preserve_window_size = false; - set_window_size(Size2(video_mode.width, video_mode.height)); - } -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->window_resize(0, video_mode.width, video_mode.height); - } -#endif - } - - if (wParam == SIZE_MAXIMIZED) { - maximized = true; - minimized = false; - } else if (wParam == SIZE_MINIMIZED) { - maximized = false; - minimized = true; - } else if (wParam == SIZE_RESTORED) { - maximized = false; - minimized = false; - } - if (is_layered_allowed() && layered_window) { - DeleteObject(hBitmap); - - RECT r; - GetWindowRect(hWnd, &r); - dib_size = Size2i(r.right - r.left, r.bottom - r.top); - - BITMAPINFO bmi; - ZeroMemory(&bmi, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = dib_size.x; - bmi.bmiHeader.biHeight = dib_size.y; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; - hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); - SelectObject(hDC_dib, hBitmap); - - ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); - } - //return 0; // Jump Back - } break; - - case WM_ENTERSIZEMOVE: { - input->release_pressed_events(); - move_timer_id = SetTimer(hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC)NULL); - } break; - case WM_EXITSIZEMOVE: { - KillTimer(hWnd, move_timer_id); - } break; - case WM_TIMER: { - if (wParam == move_timer_id) { - process_key_events(); - if (!Main::is_iterating()) { - Main::iteration(); - } - } - } break; - - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - case WM_KEYUP: - case WM_KEYDOWN: { - - if (wParam == VK_SHIFT) - shift_mem = uMsg == WM_KEYDOWN; - if (wParam == VK_CONTROL) - control_mem = uMsg == WM_KEYDOWN; - if (wParam == VK_MENU) { - alt_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); - if (lParam & (1 << 24)) - gr_mem = alt_mem; - } - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - // When SetCapture is used, ALT+F4 hotkey is ignored by Windows, so handle it ourselves - if (wParam == VK_F4 && alt_mem && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)) { - if (main_loop) - main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); - } - } - /* - if (wParam==VK_WIN) TODO wtf is this? - meta_mem=uMsg==WM_KEYDOWN; - */ - [[fallthrough]]; - } - case WM_CHAR: { - - ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); - - // Make sure we don't include modifiers for the modifier key itself. - KeyEvent ke; - ke.shift = (wParam != VK_SHIFT) ? shift_mem : false; - ke.alt = (!(wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false; - ke.control = (wParam != VK_CONTROL) ? control_mem : false; - ke.meta = meta_mem; - ke.uMsg = uMsg; - - if (ke.uMsg == WM_SYSKEYDOWN) - ke.uMsg = WM_KEYDOWN; - if (ke.uMsg == WM_SYSKEYUP) - ke.uMsg = WM_KEYUP; - - ke.wParam = wParam; - ke.lParam = lParam; - key_event_buffer[key_event_pos++] = ke; - - } break; - case WM_INPUTLANGCHANGEREQUEST: { - - // FIXME: Do something? - } break; - - case WM_TOUCH: { - - BOOL bHandled = FALSE; - UINT cInputs = LOWORD(wParam); - PTOUCHINPUT pInputs = memnew_arr(TOUCHINPUT, cInputs); - if (pInputs) { - if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) { - for (UINT i = 0; i < cInputs; i++) { - TOUCHINPUT ti = pInputs[i]; - POINT touch_pos = { - TOUCH_COORD_TO_PIXEL(ti.x), - TOUCH_COORD_TO_PIXEL(ti.y), - }; - ScreenToClient(hWnd, &touch_pos); - //do something with each touch input entry - if (ti.dwFlags & TOUCHEVENTF_MOVE) { - - _drag_event(touch_pos.x, touch_pos.y, ti.dwID); - } else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) { - - _touch_event(ti.dwFlags & TOUCHEVENTF_DOWN, touch_pos.x, touch_pos.y, ti.dwID); - }; - } - bHandled = TRUE; - } else { - /* handle the error here */ - } - memdelete_arr(pInputs); - } else { - /* handle the error here, probably out of memory */ - } - if (bHandled) { - CloseTouchInputHandle((HTOUCHINPUT)lParam); - return 0; - }; - - } break; - - case WM_DEVICECHANGE: { - - joypad->probe_joypads(); - } break; - case WM_SETCURSOR: { - if (LOWORD(lParam) == HTCLIENT) { - if (window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) { - //Hide the cursor - if (hCursor == NULL) - hCursor = SetCursor(NULL); - else - SetCursor(NULL); - } else { - if (hCursor != NULL) { - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - hCursor = NULL; - } - } - } - - } break; - case WM_DROPFILES: { - - HDROP hDropInfo = (HDROP)wParam; - const int buffsize = 4096; - wchar_t buf[buffsize]; - - int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, NULL, 0); - - Vector<String> files; - - for (int i = 0; i < fcount; i++) { - - DragQueryFileW(hDropInfo, i, buf, buffsize); - String file = buf; - files.push_back(file); - } - - if (files.size() && main_loop) { - main_loop->drop_files(files, 0); - } - - } break; - - default: { - - if (user_proc) { - - return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); - }; - }; - } - - return DefWindowProcW(hWnd, uMsg, wParam, lParam); -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - - OS_Windows *os_win = static_cast<OS_Windows *>(OS::get_singleton()); - if (os_win) - return os_win->WndProc(hWnd, uMsg, wParam, lParam); - else - return DefWindowProcW(hWnd, uMsg, wParam, lParam); -} - -void OS_Windows::process_key_events() { - - for (int i = 0; i < key_event_pos; i++) { - - KeyEvent &ke = key_event_buffer[i]; - switch (ke.uMsg) { - - case WM_CHAR: { - if ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR)) { - Ref<InputEventKey> k; - k.instance(); - - k->set_shift(ke.shift); - k->set_alt(ke.alt); - k->set_control(ke.control); - k->set_metakey(ke.meta); - k->set_pressed(true); - k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); - k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); - k->set_unicode(ke.wParam); - if (k->get_unicode() && gr_mem) { - k->set_alt(false); - k->set_control(false); - } - - if (k->get_unicode() < 32) - k->set_unicode(0); - - input->accumulate_input_event(k); - } - - //do nothing - } break; - case WM_KEYUP: - case WM_KEYDOWN: { - - Ref<InputEventKey> k; - k.instance(); - - k->set_shift(ke.shift); - k->set_alt(ke.alt); - k->set_control(ke.control); - k->set_metakey(ke.meta); - - k->set_pressed(ke.uMsg == WM_KEYDOWN); - - if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) { - // Special case for Numpad Enter key - k->set_keycode(KEY_KP_ENTER); - } else { - k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); - } - - k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); - - if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) { - k->set_unicode(key_event_buffer[i + 1].wParam); - } - if (k->get_unicode() && gr_mem) { - k->set_alt(false); - k->set_control(false); - } - - if (k->get_unicode() < 32) - k->set_unicode(0); - - k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)))); - - input->accumulate_input_event(k); - - } break; - } - } - - key_event_pos = 0; -} - -enum _MonitorDpiType { - MDT_Effective_DPI = 0, - MDT_Angular_DPI = 1, - MDT_Raw_DPI = 2, - MDT_Default = MDT_Effective_DPI -}; - -static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Default) { - - int dpiX = 96, dpiY = 96; - - static HMODULE Shcore = NULL; - typedef HRESULT(WINAPI * GetDPIForMonitor_t)(HMONITOR hmonitor, _MonitorDpiType dpiType, UINT * dpiX, UINT * dpiY); - static GetDPIForMonitor_t getDPIForMonitor = NULL; - - if (Shcore == NULL) { - Shcore = LoadLibraryW(L"Shcore.dll"); - getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)GetProcAddress(Shcore, "GetDpiForMonitor") : NULL; - - if ((Shcore == NULL) || (getDPIForMonitor == NULL)) { - if (Shcore) - FreeLibrary(Shcore); - Shcore = (HMODULE)INVALID_HANDLE_VALUE; - } - } - - UINT x = 0, y = 0; - HRESULT hr = E_FAIL; - if (hmon && (Shcore != (HMODULE)INVALID_HANDLE_VALUE)) { - hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y); - if (SUCCEEDED(hr) && (x > 0) && (y > 0)) { - - dpiX = (int)x; - dpiY = (int)y; - } - } else { - static int overallX = 0, overallY = 0; - if (overallX <= 0 || overallY <= 0) { - HDC hdc = GetDC(NULL); - if (hdc) { - overallX = GetDeviceCaps(hdc, LOGPIXELSX); - overallY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(NULL, hdc); - } - } - if (overallX > 0 && overallY > 0) { - dpiX = overallX; - dpiY = overallY; - } - } - - return (dpiX + dpiY) / 2; -} - -typedef enum _SHC_PROCESS_DPI_AWARENESS { - SHC_PROCESS_DPI_UNAWARE = 0, - SHC_PROCESS_SYSTEM_DPI_AWARE = 1, - SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2 -} SHC_PROCESS_DPI_AWARENESS; - -int OS_Windows::get_current_video_driver() const { - return video_driver_index; -} - -Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { - main_loop = NULL; - outside = true; - window_has_focus = true; - WNDCLASSEXW wc; - - if (is_hidpi_allowed()) { - HMODULE Shcore = LoadLibraryW(L"Shcore.dll"); - - if (Shcore != NULL) { - typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS); - - SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)GetProcAddress(Shcore, "SetProcessDpiAwareness"); - - if (SetProcessDpiAwareness) { - SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE); - } - } - } - - video_mode = p_desired; - //printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false"); - RECT WindowRect; - - WindowRect.left = 0; - WindowRect.right = video_mode.width; - WindowRect.top = 0; - WindowRect.bottom = video_mode.height; - - memset(&wc, 0, sizeof(WNDCLASSEXW)); - wc.cbSize = sizeof(WNDCLASSEXW); - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; - wc.lpfnWndProc = (WNDPROC)::WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - //wc.hInstance = hInstance; - wc.hInstance = godot_hinstance ? godot_hinstance : GetModuleHandle(NULL); - wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); - wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = L"Engine"; - - if (!RegisterClassExW(&wc)) { - MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); - return ERR_UNAVAILABLE; - } - - use_raw_input = true; - - RAWINPUTDEVICE Rid[1]; - - Rid[0].usUsagePage = 0x01; - Rid[0].usUsage = 0x02; - Rid[0].dwFlags = 0; - Rid[0].hwndTarget = 0; - - if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) { - //registration failed. - use_raw_input = false; - } - - pre_fs_valid = true; - if (video_mode.fullscreen) { - - /* this returns DPI unaware size, commenting - DEVMODE current; - memset(¤t, 0, sizeof(current)); - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t); - - WindowRect.right = current.dmPelsWidth; - WindowRect.bottom = current.dmPelsHeight; - - */ - - EnumSizeData data = { 0, 0, Size2() }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data); - - WindowRect.right = data.size.width; - WindowRect.bottom = data.size.height; - - /* DEVMODE dmScreenSettings; - memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); - dmScreenSettings.dmSize=sizeof(dmScreenSettings); - dmScreenSettings.dmPelsWidth = video_mode.width; - dmScreenSettings.dmPelsHeight = video_mode.height; - dmScreenSettings.dmBitsPerPel = current.dmBitsPerPel; - dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - - LONG err = ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN); - if (err!=DISP_CHANGE_SUCCESSFUL) { - - video_mode.fullscreen=false; - }*/ - pre_fs_valid = false; - } - - DWORD dwExStyle; - DWORD dwStyle; - - if (video_mode.fullscreen || video_mode.borderless_window) { - - dwExStyle = WS_EX_APPWINDOW; - dwStyle = WS_POPUP; - - } else { - dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dwStyle = WS_OVERLAPPEDWINDOW; - if (!video_mode.resizable) { - dwStyle &= ~WS_THICKFRAME; - dwStyle &= ~WS_MAXIMIZEBOX; - } - } - - AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); - - char *windowid; -#ifdef MINGW_ENABLED - windowid = getenv("GODOT_WINDOWID"); -#else - size_t len; - _dupenv_s(&windowid, &len, "GODOT_WINDOWID"); -#endif - - if (windowid) { - -// strtoull on mingw -#ifdef MINGW_ENABLED - hWnd = (HWND)strtoull(windowid, NULL, 0); -#else - hWnd = (HWND)_strtoui64(windowid, NULL, 0); -#endif - free(windowid); - SetLastError(0); - user_proc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC); - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)::WndProc); - DWORD le = GetLastError(); - if (user_proc == 0 && le != 0) { - - printf("Error setting WNDPROC: %li\n", le); - }; - GetWindowLongPtr(hWnd, GWLP_WNDPROC); - - RECT rect; - if (!GetClientRect(hWnd, &rect)) { - MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); - return ERR_UNAVAILABLE; - }; - video_mode.width = rect.right; - video_mode.height = rect.bottom; - video_mode.fullscreen = false; - } else { - - hWnd = CreateWindowExW( - dwExStyle, - L"Engine", L"", - dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - (GetSystemMetrics(SM_CXSCREEN) - WindowRect.right) / 2, - (GetSystemMetrics(SM_CYSCREEN) - WindowRect.bottom) / 2, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, NULL, hInstance, NULL); - if (!hWnd) { - MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); - return ERR_UNAVAILABLE; - } - }; - - if (video_mode.always_on_top) { - SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - } - - //!!!!!!!!!!!!!!!!!!!!!!!!!! - //TODO - do Vulkan and GLES2 support checks, driver selection and fallback - video_driver_index = p_video_driver; - print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]"); - //!!!!!!!!!!!!!!!!!!!!!!!!!! - - // Init context and rendering device -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - context_gles2 = memnew(ContextGL_Windows(hWnd, false)); - - if (context_gles2->initialize() != OK) { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - context_gles2->set_use_vsync(video_mode.use_vsync); - set_vsync_via_compositor(video_mode.vsync_via_compositor); - - if (RasterizerGLES2::is_viable() == OK) { - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); - } else { - memdelete(context_gles2); - context_gles2 = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - context_vulkan = memnew(VulkanContextWindows); - if (context_vulkan->initialize() != OK) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - if (context_vulkan->window_create(hWnd, hInstance, get_video_mode().width, get_video_mode().height) == -1) { - memdelete(context_vulkan); - context_vulkan = NULL; - ERR_FAIL_V(ERR_UNAVAILABLE); - } - - //temporary - rendering_device_vulkan = memnew(RenderingDeviceVulkan); - rendering_device_vulkan->initialize(context_vulkan); - - RasterizerRD::make_current(); - } -#endif - - visual_server = memnew(VisualServerRaster); - if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); - } - - visual_server->init(); - - input = memnew(InputDefault); - joypad = memnew(JoypadWindows(input, &hWnd)); - - AudioDriverManager::initialize(p_audio_driver); - - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - TrackMouseEvent(&tme); - - RegisterTouchWindow(hWnd, 0); - - _ensure_user_data_dir(); - - DragAcceptFiles(hWnd, true); - - move_timer_id = 1; - - if (!is_no_window_mode_enabled()) { - ShowWindow(hWnd, SW_SHOW); // Show The Window - SetForegroundWindow(hWnd); // Slightly Higher Priority - SetFocus(hWnd); // Sets Keyboard Focus To - } - - if (p_desired.layered) { - set_window_per_pixel_transparency_enabled(true); - } - - // IME - im_himc = ImmGetContext(hWnd); - ImmReleaseContext(hWnd, im_himc); - - im_position = Vector2(); - - set_ime_active(false); - - if (!OS::get_singleton()->is_in_low_processor_usage_mode()) { - //SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); - SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); - DWORD index = 0; - HANDLE handle = AvSetMmThreadCharacteristics("Games", &index); - if (handle) - AvSetMmThreadPriority(handle, AVRT_PRIORITY_CRITICAL); - - // This is needed to make sure that background work does not starve the main thread. - // This is only setting priority of this thread, not the whole process. - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - } - - update_real_mouse_position(); - - return OK; } -void OS_Windows::set_clipboard(const String &p_text) { - - // Convert LF line endings to CRLF in clipboard content - // Otherwise, line endings won't be visible when pasted in other software - String text = p_text.replace("\n", "\r\n"); - - if (!OpenClipboard(hWnd)) { - ERR_FAIL_MSG("Unable to open clipboard."); - } - EmptyClipboard(); - - HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType)); - ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); - - LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); - memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType)); - GlobalUnlock(mem); - - SetClipboardData(CF_UNICODETEXT, mem); - - // set the CF_TEXT version (not needed?) - CharString utf8 = text.utf8(); - mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1); - ERR_FAIL_COND_MSG(mem == NULL, "Unable to allocate memory for clipboard contents."); - - LPTSTR ptr = (LPTSTR)GlobalLock(mem); - memcpy(ptr, utf8.get_data(), utf8.length()); - ptr[utf8.length()] = 0; - GlobalUnlock(mem); - - SetClipboardData(CF_TEXT, mem); - - CloseClipboard(); -}; - -String OS_Windows::get_clipboard() const { - - String ret; - if (!OpenClipboard(hWnd)) { - ERR_FAIL_V_MSG("", "Unable to open clipboard."); - }; - - if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { - - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem != NULL) { - - LPWSTR ptr = (LPWSTR)GlobalLock(mem); - if (ptr != NULL) { - - ret = String((CharType *)ptr); - GlobalUnlock(mem); - }; - }; - - } else if (IsClipboardFormatAvailable(CF_TEXT)) { - - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem != NULL) { - - LPTSTR ptr = (LPTSTR)GlobalLock(mem); - if (ptr != NULL) { - - ret.parse_utf8((const char *)ptr); - GlobalUnlock(mem); - }; - }; - }; - - CloseClipboard(); - - return ret; -}; - void OS_Windows::delete_main_loop() { if (main_loop) @@ -1629,7 +225,6 @@ void OS_Windows::delete_main_loop() { void OS_Windows::set_main_loop(MainLoop *p_main_loop) { - input->set_main_loop(p_main_loop); main_loop = p_main_loop; } @@ -1643,38 +238,6 @@ void OS_Windows::finalize() { memdelete(main_loop); main_loop = NULL; - - memdelete(joypad); - memdelete(input); - touch_state.clear(); - - cursors_cache.clear(); - visual_server->finish(); - memdelete(visual_server); - -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - - if (context_gles2) - memdelete(context_gles2); - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - - if (rendering_device_vulkan) { - rendering_device_vulkan->finalize(); - memdelete(rendering_device_vulkan); - } - - if (context_vulkan) - memdelete(context_vulkan); - } -#endif - - if (user_proc) { - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); - }; } void OS_Windows::finalize_core() { @@ -1685,576 +248,6 @@ void OS_Windows::finalize_core() { NetSocketPosix::cleanup(); } -void OS_Windows::alert(const String &p_alert, const String &p_title) { - - if (!is_no_window_mode_enabled()) - MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); - else - print_line("ALERT: " + p_alert); -} - -void OS_Windows::set_mouse_mode(MouseMode p_mode) { - - if (mouse_mode == p_mode) - return; - - _set_mouse_mode_impl(p_mode); - - mouse_mode = p_mode; -} - -void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) { - - if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED) { - RECT clipRect; - GetClientRect(hWnd, &clipRect); - ClientToScreen(hWnd, (POINT *)&clipRect.left); - ClientToScreen(hWnd, (POINT *)&clipRect.right); - ClipCursor(&clipRect); - if (p_mode == MOUSE_MODE_CAPTURED) { - center = Point2i(video_mode.width / 2, video_mode.height / 2); - POINT pos = { (int)center.x, (int)center.y }; - ClientToScreen(hWnd, &pos); - SetCursorPos(pos.x, pos.y); - SetCapture(hWnd); - } - } else { - ReleaseCapture(); - ClipCursor(NULL); - } - - if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { - hCursor = SetCursor(NULL); - } else { - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - } -} -OS_Windows::MouseMode OS_Windows::get_mouse_mode() const { - - return mouse_mode; -} - -void OS_Windows::warp_mouse_position(const Point2 &p_to) { - - if (mouse_mode == MOUSE_MODE_CAPTURED) { - - old_x = p_to.x; - old_y = p_to.y; - } else { - - POINT p; - p.x = p_to.x; - p.y = p_to.y; - ClientToScreen(hWnd, &p); - - SetCursorPos(p.x, p.y); - } -} - -Point2 OS_Windows::get_mouse_position() const { - - return Point2(old_x, old_y); -} - -void OS_Windows::update_real_mouse_position() { - - POINT mouse_pos; - if (GetCursorPos(&mouse_pos) && ScreenToClient(hWnd, &mouse_pos)) { - if (mouse_pos.x > 0 && mouse_pos.y > 0 && mouse_pos.x <= video_mode.width && mouse_pos.y <= video_mode.height) { - old_x = mouse_pos.x; - old_y = mouse_pos.y; - old_invalid = false; - input->set_mouse_position(Point2i(mouse_pos.x, mouse_pos.y)); - } - } -} - -int OS_Windows::get_mouse_button_state() const { - - return last_button_state; -} - -void OS_Windows::set_window_title(const String &p_title) { - - SetWindowTextW(hWnd, p_title.c_str()); -} - -void OS_Windows::set_video_mode(const VideoMode &p_video_mode, int p_screen) { -} - -OS::VideoMode OS_Windows::get_video_mode(int p_screen) const { - - return video_mode; -} -void OS_Windows::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { -} - -static BOOL CALLBACK _MonitorEnumProcCount(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - int *data = (int *)dwData; - (*data)++; - return TRUE; -} - -int OS_Windows::get_screen_count() const { - - int data = 0; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcCount, (LPARAM)&data); - return data; -} - -typedef struct { - int count; - int screen; - HMONITOR monitor; -} EnumScreenData; - -static BOOL CALLBACK _MonitorEnumProcScreen(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumScreenData *data = (EnumScreenData *)dwData; - if (data->monitor == hMonitor) { - data->screen = data->count; - } - - data->count++; - return TRUE; -} - -int OS_Windows::get_current_screen() const { - - EnumScreenData data = { 0, 0, MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST) }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcScreen, (LPARAM)&data); - return data.screen; -} - -void OS_Windows::set_current_screen(int p_screen) { - - Vector2 ofs = get_window_position() - get_screen_position(get_current_screen()); - set_window_position(ofs + get_screen_position(p_screen)); -} - -static BOOL CALLBACK _MonitorEnumProcPos(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumPosData *data = (EnumPosData *)dwData; - if (data->count == data->screen) { - data->pos.x = lprcMonitor->left; - data->pos.y = lprcMonitor->top; - } - - data->count++; - return TRUE; -} - -Point2 OS_Windows::get_screen_position(int p_screen) const { - - EnumPosData data = { 0, p_screen == -1 ? get_current_screen() : p_screen, Point2() }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcPos, (LPARAM)&data); - return data.pos; -} - -Size2 OS_Windows::get_screen_size(int p_screen) const { - - EnumSizeData data = { 0, p_screen == -1 ? get_current_screen() : p_screen, Size2() }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data); - return data.size; -} - -typedef struct { - int count; - int screen; - int dpi; -} EnumDpiData; - -static BOOL CALLBACK _MonitorEnumProcDpi(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - - EnumDpiData *data = (EnumDpiData *)dwData; - if (data->count == data->screen) { - data->dpi = QueryDpiForMonitor(hMonitor); - } - - data->count++; - return TRUE; -} - -int OS_Windows::get_screen_dpi(int p_screen) const { - - EnumDpiData data = { 0, p_screen == -1 ? get_current_screen() : p_screen, 72 }; - EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcDpi, (LPARAM)&data); - return data.dpi; -} - -Point2 OS_Windows::get_window_position() const { - - if (minimized) { - return last_pos; - } - - RECT r; - GetWindowRect(hWnd, &r); - return Point2(r.left, r.top); -} - -void OS_Windows::set_window_position(const Point2 &p_position) { - - if (video_mode.fullscreen) return; - RECT r; - GetWindowRect(hWnd, &r); - MoveWindow(hWnd, p_position.x, p_position.y, r.right - r.left, r.bottom - r.top, TRUE); - - // Don't let the mouse leave the window when moved - if (mouse_mode == MOUSE_MODE_CONFINED) { - RECT rect; - GetClientRect(hWnd, &rect); - ClientToScreen(hWnd, (POINT *)&rect.left); - ClientToScreen(hWnd, (POINT *)&rect.right); - ClipCursor(&rect); - } - - last_pos = p_position; - update_real_mouse_position(); -} - -Size2 OS_Windows::get_window_size() const { - - if (minimized) { - return Size2(video_mode.width, video_mode.height); - } - - RECT r; - if (GetClientRect(hWnd, &r)) { // Only area inside of window border - return Size2(r.right - r.left, r.bottom - r.top); - } - return Size2(); -} - -Size2 OS_Windows::get_max_window_size() const { - return max_size; -} - -Size2 OS_Windows::get_min_window_size() const { - return min_size; -} - -void OS_Windows::set_min_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && (max_size != Size2()) && ((p_size.x > max_size.x) || (p_size.y > max_size.y))) { - ERR_PRINT("Minimum window size can't be larger than maximum window size!"); - return; - } - min_size = p_size; -} - -void OS_Windows::set_max_window_size(const Size2 p_size) { - - if ((p_size != Size2()) && ((p_size.x < min_size.x) || (p_size.y < min_size.y))) { - ERR_PRINT("Maximum window size can't be smaller than minimum window size!"); - return; - } - max_size = p_size; -} - -Size2 OS_Windows::get_real_window_size() const { - - RECT r; - if (GetWindowRect(hWnd, &r)) { // Includes area of the window border - return Size2(r.right - r.left, r.bottom - r.top); - } - return Size2(); -} - -void OS_Windows::set_window_size(const Size2 p_size) { - - int w = p_size.width; - int h = p_size.height; - - video_mode.width = w; - video_mode.height = h; -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->window_resize(0, video_mode.width, video_mode.height); - } -#endif - - if (video_mode.fullscreen) { - return; - } - - RECT rect; - GetWindowRect(hWnd, &rect); - - if (!video_mode.borderless_window) { - RECT crect; - GetClientRect(hWnd, &crect); - - w += (rect.right - rect.left) - (crect.right - crect.left); - h += (rect.bottom - rect.top) - (crect.bottom - crect.top); - } - - MoveWindow(hWnd, rect.left, rect.top, w, h, TRUE); - - // Don't let the mouse leave the window when resizing to a smaller resolution - if (mouse_mode == MOUSE_MODE_CONFINED) { - RECT crect; - GetClientRect(hWnd, &crect); - ClientToScreen(hWnd, (POINT *)&crect.left); - ClientToScreen(hWnd, (POINT *)&crect.right); - ClipCursor(&crect); - } -} -void OS_Windows::set_window_fullscreen(bool p_enabled) { - - if (video_mode.fullscreen == p_enabled) - return; - - if (layered_window) - set_window_per_pixel_transparency_enabled(false); - - if (p_enabled) { - - was_maximized = maximized; - - if (pre_fs_valid) { - GetWindowRect(hWnd, &pre_fs_rect); - } - - int cs = get_current_screen(); - Point2 pos = get_screen_position(cs); - Size2 size = get_screen_size(cs); - - video_mode.fullscreen = true; - - _update_window_style(false); - - MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE); - - } else { - - RECT rect; - - video_mode.fullscreen = false; - - if (pre_fs_valid) { - rect = pre_fs_rect; - } else { - rect.left = 0; - rect.right = video_mode.width; - rect.top = 0; - rect.bottom = video_mode.height; - } - - _update_window_style(false, was_maximized); - - MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); - - pre_fs_valid = true; - } -} -bool OS_Windows::is_window_fullscreen() const { - - return video_mode.fullscreen; -} -void OS_Windows::set_window_resizable(bool p_enabled) { - - if (video_mode.resizable == p_enabled) - return; - - video_mode.resizable = p_enabled; - - _update_window_style(); -} -bool OS_Windows::is_window_resizable() const { - - return video_mode.resizable; -} -void OS_Windows::set_window_minimized(bool p_enabled) { - - if (p_enabled) { - maximized = false; - minimized = true; - ShowWindow(hWnd, SW_MINIMIZE); - } else { - ShowWindow(hWnd, SW_RESTORE); - maximized = false; - minimized = false; - } -} -bool OS_Windows::is_window_minimized() const { - - return minimized; -} -void OS_Windows::set_window_maximized(bool p_enabled) { - - if (p_enabled) { - maximized = true; - minimized = false; - ShowWindow(hWnd, SW_MAXIMIZE); - } else { - ShowWindow(hWnd, SW_RESTORE); - maximized = false; - minimized = false; - } -} -bool OS_Windows::is_window_maximized() const { - - return maximized; -} - -void OS_Windows::set_window_always_on_top(bool p_enabled) { - if (video_mode.always_on_top == p_enabled) - return; - - video_mode.always_on_top = p_enabled; - - _update_window_style(); -} - -bool OS_Windows::is_window_always_on_top() const { - return video_mode.always_on_top; -} - -bool OS_Windows::is_window_focused() const { - - return window_focused; -} - -void OS_Windows::set_console_visible(bool p_enabled) { - if (console_visible == p_enabled) - return; - ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); - console_visible = p_enabled; -} - -bool OS_Windows::is_console_visible() const { - return console_visible; -} - -bool OS_Windows::get_window_per_pixel_transparency_enabled() const { - - if (!is_layered_allowed()) return false; - return layered_window; -} - -void OS_Windows::set_window_per_pixel_transparency_enabled(bool p_enabled) { - - if (!is_layered_allowed()) return; - if (layered_window != p_enabled) { - if (p_enabled) { - set_borderless_window(true); - //enable per-pixel alpha - hDC_dib = CreateCompatibleDC(GetDC(hWnd)); - - SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); - - RECT r; - GetWindowRect(hWnd, &r); - dib_size = Size2(r.right - r.left, r.bottom - r.top); - - BITMAPINFO bmi; - ZeroMemory(&bmi, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = dib_size.x; - bmi.bmiHeader.biHeight = dib_size.y; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; - hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0); - SelectObject(hDC_dib, hBitmap); - - ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); - - layered_window = true; - } else { - //disable per-pixel alpha - layered_window = false; - - SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); - - //cleanup - DeleteObject(hBitmap); - DeleteDC(hDC_dib); - } - } -} - -uint8_t *OS_Windows::get_layered_buffer_data() { - - return (is_layered_allowed() && layered_window) ? dib_data : NULL; -} - -Size2 OS_Windows::get_layered_buffer_size() { - - return (is_layered_allowed() && layered_window) ? dib_size : Size2(); -} - -void OS_Windows::swap_layered_buffer() { - - if (is_layered_allowed() && layered_window) { - - //premultiply alpha - for (int y = 0; y < dib_size.y; y++) { - for (int x = 0; x < dib_size.x; x++) { - float alpha = (float)dib_data[y * (int)dib_size.x * 4 + x * 4 + 3] / (float)0xFF; - dib_data[y * (int)dib_size.x * 4 + x * 4 + 0] *= alpha; - dib_data[y * (int)dib_size.x * 4 + x * 4 + 1] *= alpha; - dib_data[y * (int)dib_size.x * 4 + x * 4 + 2] *= alpha; - } - } - //swap layered window buffer - POINT ptSrc = { 0, 0 }; - SIZE sizeWnd = { (long)dib_size.x, (long)dib_size.y }; - BLENDFUNCTION bf; - bf.BlendOp = AC_SRC_OVER; - bf.BlendFlags = 0; - bf.AlphaFormat = AC_SRC_ALPHA; - bf.SourceConstantAlpha = 0xFF; - UpdateLayeredWindow(hWnd, NULL, NULL, &sizeWnd, hDC_dib, &ptSrc, 0, &bf, ULW_ALPHA); - } -} - -void OS_Windows::set_borderless_window(bool p_borderless) { - if (video_mode.borderless_window == p_borderless) - return; - - if (!p_borderless && layered_window) - set_window_per_pixel_transparency_enabled(false); - - video_mode.borderless_window = p_borderless; - - preserve_window_size = true; - _update_window_style(); -} - -bool OS_Windows::get_borderless_window() { - return video_mode.borderless_window; -} - -void OS_Windows::_update_window_style(bool p_repaint, bool p_maximized) { - if (video_mode.fullscreen || video_mode.borderless_window) { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE); - } else { - if (video_mode.resizable) { - if (p_maximized) { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE); - } else { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); - } - } else { - SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE); - } - } - - SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); - - if (p_repaint) { - RECT rect; - GetWindowRect(hWnd, &rect); - MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE); - } -} - Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { String path = p_path; @@ -2306,17 +299,6 @@ Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, cons return OK; } -void OS_Windows::request_attention() { - - FLASHWINFO info; - info.cbSize = sizeof(FLASHWINFO); - info.hwnd = hWnd; - info.dwFlags = FLASHW_TRAY; - info.dwTimeout = 0; - info.uCount = 2; - FlashWindowEx(&info); -} - String OS_Windows::get_name() const { return "Windows"; @@ -2448,253 +430,6 @@ uint64_t OS_Windows::get_ticks_usec() const { return time; } -void OS_Windows::process_events() { - - MSG msg; - - if (!drop_events) { - joypad->process_joypads(); - } - - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - - if (!drop_events) { - process_key_events(); - input->flush_accumulated_events(); - } -} - -void OS_Windows::set_cursor_shape(CursorShape p_shape) { - - ERR_FAIL_INDEX(p_shape, CURSOR_MAX); - - if (cursor_shape == p_shape) - return; - - if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { - cursor_shape = p_shape; - return; - } - - static const LPCTSTR win_cursors[CURSOR_MAX] = { - IDC_ARROW, - IDC_IBEAM, - IDC_HAND, //finger - IDC_CROSS, - IDC_WAIT, - IDC_APPSTARTING, - IDC_ARROW, - IDC_ARROW, - IDC_NO, - IDC_SIZENS, - IDC_SIZEWE, - IDC_SIZENESW, - IDC_SIZENWSE, - IDC_SIZEALL, - IDC_SIZENS, - IDC_SIZEWE, - IDC_HELP - }; - - if (cursors[p_shape] != NULL) { - SetCursor(cursors[p_shape]); - } else { - SetCursor(LoadCursor(hInstance, win_cursors[p_shape])); - } - - cursor_shape = p_shape; -} - -OS::CursorShape OS_Windows::get_cursor_shape() const { - - return cursor_shape; -} - -void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { - - if (p_cursor.is_valid()) { - - Map<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape); - - if (cursor_c) { - if (cursor_c->get()[0] == p_cursor && cursor_c->get()[1] == p_hotspot) { - set_cursor_shape(p_shape); - return; - } - - cursors_cache.erase(p_shape); - } - - Ref<Texture2D> texture = p_cursor; - Ref<AtlasTexture> atlas_texture = p_cursor; - Ref<Image> image; - Size2 texture_size; - Rect2 atlas_rect; - - if (texture.is_valid()) { - image = texture->get_data(); - } - - if (!image.is_valid() && atlas_texture.is_valid()) { - texture = atlas_texture->get_atlas(); - - atlas_rect.size.width = texture->get_width(); - atlas_rect.size.height = texture->get_height(); - atlas_rect.position.x = atlas_texture->get_region().position.x; - atlas_rect.position.y = atlas_texture->get_region().position.y; - - texture_size.width = atlas_texture->get_region().size.x; - texture_size.height = atlas_texture->get_region().size.y; - } else if (image.is_valid()) { - texture_size.width = texture->get_width(); - texture_size.height = texture->get_height(); - } - - ERR_FAIL_COND(!texture.is_valid()); - ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); - ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); - ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); - - image = texture->get_data(); - - ERR_FAIL_COND(!image.is_valid()); - - UINT image_size = texture_size.width * texture_size.height; - - // Create the BITMAP with alpha channel - COLORREF *buffer = (COLORREF *)memalloc(sizeof(COLORREF) * image_size); - - for (UINT index = 0; index < image_size; index++) { - int row_index = floor(index / texture_size.width) + atlas_rect.position.y; - int column_index = (index % int(texture_size.width)) + atlas_rect.position.x; - - if (atlas_texture.is_valid()) { - column_index = MIN(column_index, atlas_rect.size.width - 1); - row_index = MIN(row_index, atlas_rect.size.height - 1); - } - - *(buffer + index) = image->get_pixel(column_index, row_index).to_argb32(); - } - - // Using 4 channels, so 4 * 8 bits - HBITMAP bitmap = CreateBitmap(texture_size.width, texture_size.height, 1, 4 * 8, buffer); - COLORREF clrTransparent = -1; - - // Create the AND and XOR masks for the bitmap - HBITMAP hAndMask = NULL; - HBITMAP hXorMask = NULL; - - GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask); - - if (NULL == hAndMask || NULL == hXorMask) { - memfree(buffer); - DeleteObject(bitmap); - return; - } - - // Finally, create the icon - ICONINFO iconinfo; - iconinfo.fIcon = FALSE; - iconinfo.xHotspot = p_hotspot.x; - iconinfo.yHotspot = p_hotspot.y; - iconinfo.hbmMask = hAndMask; - iconinfo.hbmColor = hXorMask; - - if (cursors[p_shape]) - DestroyIcon(cursors[p_shape]); - - cursors[p_shape] = CreateIconIndirect(&iconinfo); - - Vector<Variant> params; - params.push_back(p_cursor); - params.push_back(p_hotspot); - cursors_cache.insert(p_shape, params); - - if (p_shape == cursor_shape) { - if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { - SetCursor(cursors[p_shape]); - } - } - - if (hAndMask != NULL) { - DeleteObject(hAndMask); - } - - if (hXorMask != NULL) { - DeleteObject(hXorMask); - } - - memfree(buffer); - DeleteObject(bitmap); - } else { - // Reset to default system cursor - if (cursors[p_shape]) { - DestroyIcon(cursors[p_shape]); - cursors[p_shape] = NULL; - } - - CursorShape c = cursor_shape; - cursor_shape = CURSOR_MAX; - set_cursor_shape(c); - - cursors_cache.erase(p_shape); - } -} - -void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) { - - // Get the system display DC - HDC hDC = GetDC(NULL); - - // Create helper DC - HDC hMainDC = CreateCompatibleDC(hDC); - HDC hAndMaskDC = CreateCompatibleDC(hDC); - HDC hXorMaskDC = CreateCompatibleDC(hDC); - - // Get the dimensions of the source bitmap - BITMAP bm; - GetObject(hSourceBitmap, sizeof(BITMAP), &bm); - - // Create the mask bitmaps - hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color - hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color - - // Release the system display DC - ReleaseDC(NULL, hDC); - - // Select the bitmaps to helper DC - HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap); - HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap); - HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap); - - // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap - // with 'clrTransparent' will be white pixels of the monochrome bitmap - SetBkColor(hMainDC, clrTransparent); - BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY); - - // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap - // with 'clrTransparent' will be black and rest the pixels same as corresponding - // pixels of the source bitmap - SetBkColor(hXorMaskDC, RGB(0, 0, 0)); - SetTextColor(hXorMaskDC, RGB(255, 255, 255)); - BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY); - BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND); - - // Deselect bitmaps from the helper DC - SelectObject(hMainDC, hOldMainBitmap); - SelectObject(hAndMaskDC, hOldAndMaskBitmap); - SelectObject(hXorMaskDC, hOldXorMaskBitmap); - - // Delete the helper DC - DeleteDC(hXorMaskDC); - DeleteDC(hAndMaskDC); - DeleteDC(hMainDC); -} - Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) { if (p_blocking && r_pipe) { @@ -2812,151 +547,6 @@ String OS_Windows::get_executable_path() const { return s; } -void OS_Windows::set_native_icon(const String &p_filename) { - - FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); - ERR_FAIL_COND_MSG(!f, "Cannot open file with icon '" + p_filename + "'."); - - ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR)); - int pos = 0; - - icon_dir->idReserved = f->get_32(); - pos += sizeof(WORD); - f->seek(pos); - - icon_dir->idType = f->get_32(); - pos += sizeof(WORD); - f->seek(pos); - - ERR_FAIL_COND_MSG(icon_dir->idType != 1, "Invalid icon file format!"); - - icon_dir->idCount = f->get_32(); - pos += sizeof(WORD); - f->seek(pos); - - icon_dir = (ICONDIR *)memrealloc(icon_dir, 3 * sizeof(WORD) + icon_dir->idCount * sizeof(ICONDIRENTRY)); - f->get_buffer((uint8_t *)&icon_dir->idEntries[0], icon_dir->idCount * sizeof(ICONDIRENTRY)); - - int small_icon_index = -1; // Select 16x16 with largest color count - int small_icon_cc = 0; - int big_icon_index = -1; // Select largest - int big_icon_width = 16; - int big_icon_cc = 0; - - for (int i = 0; i < icon_dir->idCount; i++) { - int colors = (icon_dir->idEntries[i].bColorCount == 0) ? 32768 : icon_dir->idEntries[i].bColorCount; - int width = (icon_dir->idEntries[i].bWidth == 0) ? 256 : icon_dir->idEntries[i].bWidth; - if (width == 16) { - if (colors >= small_icon_cc) { - small_icon_index = i; - small_icon_cc = colors; - } - } - if (width >= big_icon_width) { - if (colors >= big_icon_cc) { - big_icon_index = i; - big_icon_width = width; - big_icon_cc = colors; - } - } - } - - ERR_FAIL_COND_MSG(big_icon_index == -1, "No valid icons found!"); - - if (small_icon_index == -1) { - WARN_PRINT("No small icon found, reusing " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon!"); - small_icon_index = big_icon_index; - small_icon_cc = big_icon_cc; - } - - // Read the big icon - DWORD bytecount_big = icon_dir->idEntries[big_icon_index].dwBytesInRes; - Vector<uint8_t> data_big; - data_big.resize(bytecount_big); - pos = icon_dir->idEntries[big_icon_index].dwImageOffset; - f->seek(pos); - f->get_buffer((uint8_t *)&data_big.write[0], bytecount_big); - HICON icon_big = CreateIconFromResource((PBYTE)&data_big.write[0], bytecount_big, TRUE, 0x00030000); - ERR_FAIL_COND_MSG(!icon_big, "Could not create " + itos(big_icon_width) + "x" + itos(big_icon_width) + " @" + itos(big_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); - - // Read the small icon - DWORD bytecount_small = icon_dir->idEntries[small_icon_index].dwBytesInRes; - Vector<uint8_t> data_small; - data_small.resize(bytecount_small); - pos = icon_dir->idEntries[small_icon_index].dwImageOffset; - f->seek(pos); - f->get_buffer((uint8_t *)&data_small.write[0], bytecount_small); - HICON icon_small = CreateIconFromResource((PBYTE)&data_small.write[0], bytecount_small, TRUE, 0x00030000); - ERR_FAIL_COND_MSG(!icon_small, "Could not create 16x16 @" + itos(small_icon_cc) + " icon, error: " + format_error_message(GetLastError()) + "."); - - // Online tradition says to be sure last error is cleared and set the small icon first - int err = 0; - SetLastError(err); - - SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon_small); - err = GetLastError(); - ERR_FAIL_COND_MSG(err, "Error setting ICON_SMALL: " + format_error_message(err) + "."); - - SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)icon_big); - err = GetLastError(); - ERR_FAIL_COND_MSG(err, "Error setting ICON_BIG: " + format_error_message(err) + "."); - - memdelete(f); - memdelete(icon_dir); -} - -void OS_Windows::set_icon(const Ref<Image> &p_icon) { - - ERR_FAIL_COND(!p_icon.is_valid()); - Ref<Image> icon = p_icon->duplicate(); - if (icon->get_format() != Image::FORMAT_RGBA8) - icon->convert(Image::FORMAT_RGBA8); - int w = icon->get_width(); - int h = icon->get_height(); - - /* Create temporary bitmap buffer */ - int icon_len = 40 + h * w * 4; - Vector<BYTE> v; - v.resize(icon_len); - BYTE *icon_bmp = v.ptrw(); - - encode_uint32(40, &icon_bmp[0]); - encode_uint32(w, &icon_bmp[4]); - encode_uint32(h * 2, &icon_bmp[8]); - encode_uint16(1, &icon_bmp[12]); - encode_uint16(32, &icon_bmp[14]); - encode_uint32(BI_RGB, &icon_bmp[16]); - encode_uint32(w * h * 4, &icon_bmp[20]); - encode_uint32(0, &icon_bmp[24]); - encode_uint32(0, &icon_bmp[28]); - encode_uint32(0, &icon_bmp[32]); - encode_uint32(0, &icon_bmp[36]); - - uint8_t *wr = &icon_bmp[40]; - const uint8_t *r = icon->get_data().ptr(); - - for (int i = 0; i < h; i++) { - - for (int j = 0; j < w; j++) { - - const uint8_t *rpx = &r[((h - i - 1) * w + j) * 4]; - uint8_t *wpx = &wr[(i * w + j) * 4]; - wpx[0] = rpx[2]; - wpx[1] = rpx[1]; - wpx[2] = rpx[0]; - wpx[3] = rpx[3]; - } - } - - HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000); - - /* Set the icon for the window */ - SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); - - /* Set the icon in the task manager (should we do this?) */ - SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); -} - bool OS_Windows::has_environment(const String &p_var) const { #ifdef MINGW_ENABLED @@ -2996,16 +586,6 @@ String OS_Windows::get_stdin_string(bool p_block) { return String(); } -void OS_Windows::enable_for_stealing_focus(ProcessID pid) { - - AllowSetForegroundWindow(pid); -} - -void OS_Windows::move_window_to_foreground() { - - SetForegroundWindow(hWnd); -} - Error OS_Windows::shell_open(String p_uri) { ShellExecuteW(NULL, NULL, p_uri.c_str(), NULL, NULL, SW_SHOWNORMAL); @@ -3068,101 +648,6 @@ int OS_Windows::get_processor_count() const { return sysinfo.dwNumberOfProcessors; } -OS::LatinKeyboardVariant OS_Windows::get_latin_keyboard_variant() const { - - unsigned long azerty[] = { - 0x00020401, // Arabic (102) AZERTY - 0x0001080c, // Belgian (Comma) - 0x0000080c, // Belgian French - 0x0000040c, // French - 0 // <--- STOP MARK - }; - unsigned long qwertz[] = { - 0x0000041a, // Croation - 0x00000405, // Czech - 0x00000407, // German - 0x00010407, // German (IBM) - 0x0000040e, // Hungarian - 0x0000046e, // Luxembourgish - 0x00010415, // Polish (214) - 0x00000418, // Romanian (Legacy) - 0x0000081a, // Serbian (Latin) - 0x0000041b, // Slovak - 0x00000424, // Slovenian - 0x0001042e, // Sorbian Extended - 0x0002042e, // Sorbian Standard - 0x0000042e, // Sorbian Standard (Legacy) - 0x0000100c, // Swiss French - 0x00000807, // Swiss German - 0 // <--- STOP MARK - }; - unsigned long dvorak[] = { - 0x00010409, // US-Dvorak - 0x00030409, // US-Dvorak for left hand - 0x00040409, // US-Dvorak for right hand - 0 // <--- STOP MARK - }; - - char name[KL_NAMELENGTH + 1]; - name[0] = 0; - GetKeyboardLayoutNameA(name); - - unsigned long hex = strtoul(name, NULL, 16); - - int i = 0; - while (azerty[i] != 0) { - if (azerty[i] == hex) return LATIN_KEYBOARD_AZERTY; - i++; - } - - i = 0; - while (qwertz[i] != 0) { - if (qwertz[i] == hex) return LATIN_KEYBOARD_QWERTZ; - i++; - } - - i = 0; - while (dvorak[i] != 0) { - if (dvorak[i] == hex) return LATIN_KEYBOARD_DVORAK; - i++; - } - - return LATIN_KEYBOARD_QWERTY; -} - -void OS_Windows::release_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->release_current(); - } -#endif -} - -void OS_Windows::make_rendering_thread() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->make_current(); - } -#endif -} - -void OS_Windows::swap_buffers() { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2->swap_buffers(); - } -#endif -#if defined(VULKAN_ENABLED) - if (video_driver_index == VIDEO_DRIVER_VULKAN) { - context_vulkan->swap_buffers(); - } -#endif -} - -void OS_Windows::force_process_input() { - process_events(); // get rid of pending events -} - void OS_Windows::run() { if (!main_loop) @@ -3172,7 +657,7 @@ void OS_Windows::run() { while (!force_quit) { - process_events(); // get rid of pending events + DisplayServer::get_singleton()->process_events(); // get rid of pending events if (Main::iteration()) break; }; @@ -3287,50 +772,6 @@ String OS_Windows::get_unique_id() const { return String(HwProfInfo.szHwProfileGuid); } -void OS_Windows::set_ime_active(const bool p_active) { - - if (p_active) { - ImmAssociateContext(hWnd, im_himc); - - set_ime_position(im_position); - } else { - ImmAssociateContext(hWnd, (HIMC)0); - } -} - -void OS_Windows::set_ime_position(const Point2 &p_pos) { - - im_position = p_pos; - - HIMC himc = ImmGetContext(hWnd); - if (himc == (HIMC)0) - return; - - COMPOSITIONFORM cps; - cps.dwStyle = CFS_FORCE_POSITION; - cps.ptCurrentPos.x = im_position.x; - cps.ptCurrentPos.y = im_position.y; - ImmSetCompositionWindow(himc, &cps); - ImmReleaseContext(hWnd, himc); -} - -bool OS_Windows::is_joy_known(int p_device) { - return input->is_joy_mapped(p_device); -} - -String OS_Windows::get_joy_guid(int p_device) const { - return input->get_joy_guid_remapped(p_device); -} - -void OS_Windows::_set_use_vsync(bool p_enable) { -#if defined(OPENGL_ENABLED) - if (video_driver_index == VIDEO_DRIVER_GLES2) { - if (context_gles2) - context_gles2->set_use_vsync(p_enable); - } -#endif -} - bool OS_Windows::_check_internal_feature_support(const String &p_feature) { return p_feature == "pc"; @@ -3344,20 +785,13 @@ bool OS_Windows::is_disable_crash_handler() const { return crash_handler.is_disabled(); } -void OS_Windows::process_and_drop_events() { - - drop_events = true; - process_events(); - drop_events = false; -} - Error OS_Windows::move_to_trash(const String &p_path) { SHFILEOPSTRUCTW sf; WCHAR *from = new WCHAR[p_path.length() + 2]; wcscpy_s(from, p_path.length() + 1, p_path.c_str()); from[p_path.length() + 1] = 0; - sf.hwnd = hWnd; + sf.hwnd = main_window; sf.wFunc = FO_DELETE; sf.pFrom = from; sf.pTo = NULL; @@ -3379,36 +813,12 @@ Error OS_Windows::move_to_trash(const String &p_path) { OS_Windows::OS_Windows(HINSTANCE _hInstance) { - drop_events = false; - key_event_pos = 0; - layered_window = false; - hBitmap = NULL; force_quit = false; - alt_mem = false; - gr_mem = false; - shift_mem = false; - control_mem = false; - meta_mem = false; - minimized = false; - was_maximized = false; - window_focused = true; - console_visible = IsWindowVisible(GetConsoleWindow()); - - //Note: Functions for pen input, available on Windows 8+ - HMODULE user32_lib = LoadLibraryW(L"user32.dll"); - if (user32_lib) { - win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType"); - win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo"); - } hInstance = _hInstance; - pressrc = 0; - old_invalid = true; - mouse_mode = MOUSE_MODE_VISIBLE; #ifdef STDOUT_FILE stdo = fopen("stdout.txt", "wb"); #endif - user_proc = NULL; #ifdef WASAPI_ENABLED AudioDriverManager::add_driver(&driver_wasapi); @@ -3417,16 +827,14 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { AudioDriverManager::add_driver(&driver_xaudio2); #endif + DisplayServerWindows::register_windows_driver(); + Vector<Logger *> loggers; loggers.push_back(memnew(WindowsTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); } OS_Windows::~OS_Windows() { - if (is_layered_allowed() && layered_window) { - DeleteObject(hBitmap); - DeleteDC(hDC_dib); - } #ifdef STDOUT_FILE fclose(stdo); #endif diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 8506aa7b20..040951668d 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -31,7 +31,7 @@ #ifndef OS_WINDOWS_H #define OS_WINDOWS_H -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/os.h" #include "core/project_settings.h" #include "crash_handler_windows.h" @@ -39,7 +39,6 @@ #include "drivers/wasapi/audio_driver_wasapi.h" #include "drivers/winmidi/midi_driver_winmidi.h" #include "key_mapping_windows.h" -#include "main/input_default.h" #include "servers/audio_server.h" #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" @@ -62,183 +61,19 @@ #include <windows.h> #include <windowsx.h> -#ifndef POINTER_STRUCTURES - -#define POINTER_STRUCTURES - -typedef DWORD POINTER_INPUT_TYPE; -typedef UINT32 POINTER_FLAGS; -typedef UINT32 PEN_FLAGS; -typedef UINT32 PEN_MASK; - -enum tagPOINTER_INPUT_TYPE { - PT_POINTER = 0x00000001, - PT_TOUCH = 0x00000002, - PT_PEN = 0x00000003, - PT_MOUSE = 0x00000004, - PT_TOUCHPAD = 0x00000005 -}; - -typedef enum tagPOINTER_BUTTON_CHANGE_TYPE { - POINTER_CHANGE_NONE, - POINTER_CHANGE_FIRSTBUTTON_DOWN, - POINTER_CHANGE_FIRSTBUTTON_UP, - POINTER_CHANGE_SECONDBUTTON_DOWN, - POINTER_CHANGE_SECONDBUTTON_UP, - POINTER_CHANGE_THIRDBUTTON_DOWN, - POINTER_CHANGE_THIRDBUTTON_UP, - POINTER_CHANGE_FOURTHBUTTON_DOWN, - POINTER_CHANGE_FOURTHBUTTON_UP, - POINTER_CHANGE_FIFTHBUTTON_DOWN, - POINTER_CHANGE_FIFTHBUTTON_UP, -} POINTER_BUTTON_CHANGE_TYPE; - -typedef struct tagPOINTER_INFO { - POINTER_INPUT_TYPE pointerType; - UINT32 pointerId; - UINT32 frameId; - POINTER_FLAGS pointerFlags; - HANDLE sourceDevice; - HWND hwndTarget; - POINT ptPixelLocation; - POINT ptHimetricLocation; - POINT ptPixelLocationRaw; - POINT ptHimetricLocationRaw; - DWORD dwTime; - UINT32 historyCount; - INT32 InputData; - DWORD dwKeyStates; - UINT64 PerformanceCount; - POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; -} POINTER_INFO; - -typedef struct tagPOINTER_PEN_INFO { - POINTER_INFO pointerInfo; - PEN_FLAGS penFlags; - PEN_MASK penMask; - UINT32 pressure; - UINT32 rotation; - INT32 tiltX; - INT32 tiltY; -} POINTER_PEN_INFO; - -#endif - -typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type); -typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info); - -typedef struct { - BYTE bWidth; // Width, in pixels, of the image - BYTE bHeight; // Height, in pixels, of the image - BYTE bColorCount; // Number of colors in image (0 if >=8bpp) - BYTE bReserved; // Reserved ( must be 0) - WORD wPlanes; // Color Planes - WORD wBitCount; // Bits per pixel - DWORD dwBytesInRes; // How many bytes in this resource? - DWORD dwImageOffset; // Where in the file is this image? -} ICONDIRENTRY, *LPICONDIRENTRY; - -typedef struct { - WORD idReserved; // Reserved (must be 0) - WORD idType; // Resource Type (1 for icons) - WORD idCount; // How many images? - ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) -} ICONDIR, *LPICONDIR; - class JoypadWindows; class OS_Windows : public OS { - static GetPointerTypePtr win8p_GetPointerType; - static GetPointerPenInfoPtr win8p_GetPointerPenInfo; - - enum { - KEY_EVENT_BUFFER_SIZE = 512 - }; - #ifdef STDOUT_FILE FILE *stdo; #endif - struct KeyEvent { - - bool alt, shift, control, meta; - UINT uMsg; - WPARAM wParam; - LPARAM lParam; - }; - - KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE]; - int key_event_pos; - uint64_t ticks_start; uint64_t ticks_per_second; - bool old_invalid; - bool outside; - int old_x, old_y; - Point2i center; - -#if defined(OPENGL_ENABLED) - ContextGL_Windows *context_gles2; -#endif - -#if defined(VULKAN_ENABLED) - VulkanContextWindows *context_vulkan; - RenderingDeviceVulkan *rendering_device_vulkan; -#endif - - VisualServer *visual_server; - int pressrc; - HINSTANCE hInstance; // Holds The Instance Of The Application - HWND hWnd; - Point2 last_pos; - - HBITMAP hBitmap; //DIB section for layered window - uint8_t *dib_data; - Size2 dib_size; - HDC hDC_dib; - bool layered_window; - - uint32_t move_timer_id; - - HCURSOR hCursor; - - Size2 min_size; - Size2 max_size; - - Size2 window_rect; - VideoMode video_mode; - bool preserve_window_size = false; - + HINSTANCE hInstance; MainLoop *main_loop; - WNDPROC user_proc; - - // IME - HIMC im_himc; - Vector2 im_position; - - MouseMode mouse_mode; - bool alt_mem; - bool gr_mem; - bool shift_mem; - bool control_mem; - bool meta_mem; - bool force_quit; - bool window_has_focus; - uint32_t last_button_state; - bool use_raw_input; - bool drop_events; - - HCURSOR cursors[CURSOR_MAX] = { NULL }; - CursorShape cursor_shape; - Map<CursorShape, Vector<Variant>> cursors_cache; - - InputDefault *input; - JoypadWindows *joypad; - Map<int, Vector2> touch_state; - - int video_driver_index; #ifdef WASAPI_ENABLED AudioDriverWASAPI driver_wasapi; #endif @@ -251,28 +86,19 @@ class OS_Windows : public OS { CrashHandler crash_handler; - void _drag_event(float p_x, float p_y, int idx); - void _touch_event(bool p_pressed, float p_x, float p_y, int idx); - - void _update_window_style(bool p_repaint = true, bool p_maximized = false); - - void _set_mouse_mode_impl(MouseMode p_mode); + bool force_quit; + HWND main_window; // functions used by main to initialize/deinitialize the OS protected: - virtual int get_current_video_driver() const; - - virtual void initialize_core(); - virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual void initialize(); virtual void set_main_loop(MainLoop *p_main_loop); virtual void delete_main_loop(); virtual void finalize(); virtual void finalize_core(); - - void process_events(); - void process_key_events(); + virtual String get_stdin_string(bool p_block); struct ProcessInfo { @@ -281,75 +107,7 @@ protected: }; Map<ProcessID, ProcessInfo> *process_map; - bool pre_fs_valid; - RECT pre_fs_rect; - bool maximized; - bool minimized; - bool borderless; - bool window_focused; - bool console_visible; - bool was_maximized; - public: - LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - - virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); - String get_stdin_string(bool p_block); - - void set_mouse_mode(MouseMode p_mode); - MouseMode get_mouse_mode() const; - - virtual void warp_mouse_position(const Point2 &p_to); - virtual Point2 get_mouse_position() const; - void update_real_mouse_position(); - virtual int get_mouse_button_state() const; - virtual void set_window_title(const String &p_title); - - virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0); - virtual VideoMode get_video_mode(int p_screen = 0) const; - virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; - - virtual int get_screen_count() const; - virtual int get_current_screen() const; - virtual void set_current_screen(int p_screen); - virtual Point2 get_screen_position(int p_screen = -1) const; - virtual Size2 get_screen_size(int p_screen = -1) const; - virtual int get_screen_dpi(int p_screen = -1) const; - - virtual Point2 get_window_position() const; - virtual void set_window_position(const Point2 &p_position); - virtual Size2 get_window_size() const; - virtual Size2 get_real_window_size() const; - virtual Size2 get_max_window_size() const; - virtual Size2 get_min_window_size() const; - virtual void set_min_window_size(const Size2 p_size); - virtual void set_max_window_size(const Size2 p_size); - virtual void set_window_size(const Size2 p_size); - virtual void set_window_fullscreen(bool p_enabled); - virtual bool is_window_fullscreen() const; - virtual void set_window_resizable(bool p_enabled); - virtual bool is_window_resizable() const; - virtual void set_window_minimized(bool p_enabled); - virtual bool is_window_minimized() const; - virtual void set_window_maximized(bool p_enabled); - virtual bool is_window_maximized() const; - virtual void set_window_always_on_top(bool p_enabled); - virtual bool is_window_always_on_top() const; - virtual bool is_window_focused() const; - virtual void set_console_visible(bool p_enabled); - virtual bool is_console_visible() const; - virtual void request_attention(); - - virtual void set_borderless_window(bool p_borderless); - virtual bool get_borderless_window(); - - virtual bool get_window_per_pixel_transparency_enabled() const; - virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); - - virtual uint8_t *get_layered_buffer_data(); - virtual Size2 get_layered_buffer_size(); - virtual void swap_layered_buffer(); - virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false); virtual Error close_dynamic_library(void *p_library_handle); virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false); @@ -358,6 +116,8 @@ public: virtual String get_name() const; + virtual void initialize_joypads() {} + virtual Date get_date(bool utc) const; virtual Time get_time(bool utc) const; virtual TimeZoneInfo get_time_zone_info() const; @@ -365,7 +125,6 @@ public: virtual uint64_t get_system_time_secs() const; virtual uint64_t get_system_time_msecs() const; - virtual bool can_draw() const; virtual Error set_cwd(const String &p_cwd); virtual void delay_usec(uint32_t p_usec) const; @@ -379,28 +138,12 @@ public: virtual String get_environment(const String &p_var) const; virtual bool set_environment(const String &p_var, const String &p_value) const; - virtual void set_clipboard(const String &p_text); - virtual String get_clipboard() const; - - void set_cursor_shape(CursorShape p_shape); - CursorShape get_cursor_shape() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); - void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap); - - void set_native_icon(const String &p_filename); - void set_icon(const Ref<Image> &p_icon); - virtual String get_executable_path() const; virtual String get_locale() const; virtual int get_processor_count() const; - virtual LatinKeyboardVariant get_latin_keyboard_variant() const; - - virtual void enable_for_stealing_focus(ProcessID pid); - virtual void move_window_to_foreground(); - virtual String get_config_path() const; virtual String get_data_path() const; virtual String get_cache_path() const; @@ -411,37 +154,21 @@ public: virtual String get_unique_id() const; - virtual void set_ime_active(const bool p_active); - virtual void set_ime_position(const Point2 &p_pos); - - virtual void release_rendering_thread(); - virtual void make_rendering_thread(); - virtual void swap_buffers(); - virtual Error shell_open(String p_uri); void run(); - virtual bool get_swap_ok_cancel() { return true; } - - virtual bool is_joy_known(int p_device); - virtual String get_joy_guid(int p_device) const; - - virtual void _set_use_vsync(bool p_enable); - //virtual bool is_vsync_enabled() const; - virtual bool _check_internal_feature_support(const String &p_feature); void disable_crash_handler(); bool is_disable_crash_handler() const; virtual void initialize_debugging(); - void force_process_input(); - virtual Error move_to_trash(const String &p_path); - virtual void process_and_drop_events(); + void set_main_window(HWND p_main_window) { main_window = p_main_window; } + HINSTANCE get_hinstance() { return hInstance; } OS_Windows(HINSTANCE _hInstance); ~OS_Windows(); }; diff --git a/platform/windows/vulkan_context_win.cpp b/platform/windows/vulkan_context_win.cpp index 20e1b46682..66b5cf8113 100644 --- a/platform/windows/vulkan_context_win.cpp +++ b/platform/windows/vulkan_context_win.cpp @@ -35,7 +35,7 @@ const char *VulkanContextWindows::_get_platform_surface_extension() const { return VK_KHR_WIN32_SURFACE_EXTENSION_NAME; } -int VulkanContextWindows::window_create(HWND p_window, HINSTANCE p_instance, int p_width, int p_height) { +int VulkanContextWindows::window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height) { VkWin32SurfaceCreateInfoKHR createInfo; createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; @@ -47,7 +47,7 @@ int VulkanContextWindows::window_create(HWND p_window, HINSTANCE p_instance, int VkSurfaceKHR surface; VkResult err = vkCreateWin32SurfaceKHR(_get_instance(), &createInfo, NULL, &surface); ERR_FAIL_COND_V(err, -1); - return _window_create(surface, p_width, p_height); + return _window_create(p_window_id, surface, p_width, p_height); } VulkanContextWindows::VulkanContextWindows() { diff --git a/platform/windows/vulkan_context_win.h b/platform/windows/vulkan_context_win.h index 1289f2a299..c9fea9369b 100644 --- a/platform/windows/vulkan_context_win.h +++ b/platform/windows/vulkan_context_win.h @@ -39,7 +39,7 @@ class VulkanContextWindows : public VulkanContext { virtual const char *_get_platform_surface_extension() const; public: - int window_create(HWND p_window, HINSTANCE p_instance, int p_width, int p_height); + int window_create(DisplayServer::WindowID p_window_id, HWND p_window, HINSTANCE p_instance, int p_width, int p_height); VulkanContextWindows(); ~VulkanContextWindows(); diff --git a/platform/x11/SCsub b/platform/x11/SCsub deleted file mode 100644 index 2268e4cc3d..0000000000 --- a/platform/x11/SCsub +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -from platform_methods import run_in_subprocess -import platform_x11_builders - -common_x11 = [ - "context_gl_x11.cpp", - "vulkan_context_x11.cpp", - "crash_handler_x11.cpp", - "os_x11.cpp", - "key_mapping_x11.cpp", - "joypad_linux.cpp", - "detect_prime.cpp" -] - -prog = env.add_program('#bin/godot', ['godot_x11.cpp'] + common_x11) - -if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]: - env.AddPostAction(prog, run_in_subprocess(platform_x11_builders.make_debug_x11)) diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h deleted file mode 100644 index 997a6cc053..0000000000 --- a/platform/x11/os_x11.h +++ /dev/null @@ -1,339 +0,0 @@ -/*************************************************************************/ -/* os_x11.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef OS_X11_H -#define OS_X11_H - -#include "core/os/input.h" -#include "crash_handler_x11.h" -#include "drivers/alsa/audio_driver_alsa.h" -#include "drivers/alsamidi/midi_driver_alsamidi.h" -#include "drivers/pulseaudio/audio_driver_pulseaudio.h" -#include "drivers/unix/os_unix.h" -#include "joypad_linux.h" -#include "main/input_default.h" -#include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" - -#if defined(OPENGL_ENABLED) -#include "context_gl_x11.h" -#endif - -#if defined(VULKAN_ENABLED) -#include "drivers/vulkan/rendering_device_vulkan.h" -#include "platform/x11/vulkan_context_x11.h" -#endif - -#include <X11/Xcursor/Xcursor.h> -#include <X11/Xlib.h> -#include <X11/extensions/XInput2.h> -#include <X11/extensions/Xrandr.h> -#include <X11/keysym.h> - -// Hints for X11 fullscreen -typedef struct { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long inputMode; - unsigned long status; -} Hints; - -typedef struct _xrr_monitor_info { - Atom name; - Bool primary; - Bool automatic; - int noutput; - int x; - int y; - int width; - int height; - int mwidth; - int mheight; - RROutput *outputs; -} xrr_monitor_info; - -#undef CursorShape - -class OS_X11 : public OS_Unix { - - Atom wm_delete; - Atom xdnd_enter; - Atom xdnd_position; - Atom xdnd_status; - Atom xdnd_action_copy; - Atom xdnd_drop; - Atom xdnd_finished; - Atom xdnd_selection; - Atom requested; - - int xdnd_version; - -#if defined(OPENGL_ENABLED) - ContextGL_X11 *context_gles2; -#endif -#if defined(VULKAN_ENABLED) - VulkanContextX11 *context_vulkan; - RenderingDeviceVulkan *rendering_device_vulkan; -#endif - - //Rasterizer *rasterizer; - VisualServer *visual_server; - VideoMode current_videomode; - List<String> args; - Window x11_window; - Window xdnd_source_window; - MainLoop *main_loop; - ::Display *x11_display; - char *xmbstring; - int xmblen; - unsigned long last_timestamp; - ::Time last_keyrelease_time; - ::XIC xic; - ::XIM xim; - ::XIMStyle xim_style; - static void xim_destroy_callback(::XIM im, ::XPointer client_data, - ::XPointer call_data); - - // IME - bool im_active; - Vector2 im_position; - Vector2 last_position_before_fs; - - Size2 min_size; - Size2 max_size; - - Point2 last_mouse_pos; - bool last_mouse_pos_valid; - Point2i last_click_pos; - uint64_t last_click_ms; - int last_click_button_index; - uint32_t last_button_state; - - struct { - int opcode; - Vector<int> touch_devices; - Map<int, Vector2> absolute_devices; - Map<int, Vector3> pen_devices; - XIEventMask all_event_mask; - XIEventMask all_master_event_mask; - Map<int, Vector2> state; - double pressure; - Vector2 tilt; - Vector2 mouse_pos_to_filter; - Vector2 relative_motion; - Vector2 raw_pos; - Vector2 old_raw_pos; - ::Time last_relative_time; - } xi; - - bool refresh_device_info(); - - unsigned int get_mouse_button_state(unsigned int p_x11_button, int p_x11_type); - void get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state); - void flush_mouse_motion(); - - MouseMode mouse_mode; - Point2i center; - - void handle_key_event(XKeyEvent *p_event, bool p_echo = false); - void process_xevents(); - virtual void delete_main_loop(); - - bool force_quit; - bool minimized; - bool window_has_focus; - bool do_mouse_warp; - - const char *cursor_theme; - int cursor_size; - XcursorImage *img[CURSOR_MAX]; - Cursor cursors[CURSOR_MAX]; - Cursor null_cursor; - CursorShape current_cursor; - Map<CursorShape, Vector<Variant>> cursors_cache; - - InputDefault *input; - -#ifdef JOYDEV_ENABLED - JoypadLinux *joypad; -#endif - -#ifdef ALSA_ENABLED - AudioDriverALSA driver_alsa; -#endif - -#ifdef ALSAMIDI_ENABLED - MIDIDriverALSAMidi driver_alsamidi; -#endif - -#ifdef PULSEAUDIO_ENABLED - AudioDriverPulseAudio driver_pulseaudio; -#endif - - bool layered_window; - - CrashHandler crash_handler; - - int video_driver_index; - bool maximized; - bool window_focused; - //void set_wm_border(bool p_enabled); - void set_wm_fullscreen(bool p_enabled); - void set_wm_above(bool p_enabled); - - typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors); - typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors); - xrr_get_monitors_t xrr_get_monitors; - xrr_free_monitors_t xrr_free_monitors; - void *xrandr_handle; - Bool xrandr_ext_ok; - -protected: - virtual int get_current_video_driver() const; - - virtual void initialize_core(); - virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); - virtual void finalize(); - - virtual void set_main_loop(MainLoop *p_main_loop); - - void _window_changed(XEvent *event); - - bool is_window_maximize_allowed(); - -public: - virtual String get_name() const; - - virtual void set_cursor_shape(CursorShape p_shape); - virtual CursorShape get_cursor_shape() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); - - void set_mouse_mode(MouseMode p_mode); - MouseMode get_mouse_mode() const; - - virtual void warp_mouse_position(const Point2 &p_to); - virtual Point2 get_mouse_position() const; - virtual int get_mouse_button_state() const; - virtual void set_window_title(const String &p_title); - - virtual void set_icon(const Ref<Image> &p_icon); - - virtual MainLoop *get_main_loop() const; - - virtual bool can_draw() const; - - virtual void set_clipboard(const String &p_text); - virtual String get_clipboard() const; - - virtual void release_rendering_thread(); - virtual void make_rendering_thread(); - virtual void swap_buffers(); - - virtual String get_config_path() const; - virtual String get_data_path() const; - virtual String get_cache_path() const; - - virtual String get_system_dir(SystemDir p_dir) const; - - virtual Error shell_open(String p_uri); - - virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0); - virtual VideoMode get_video_mode(int p_screen = 0) const; - virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; - - virtual int get_screen_count() const; - virtual int get_current_screen() const; - virtual void set_current_screen(int p_screen); - virtual Point2 get_screen_position(int p_screen = -1) const; - virtual Size2 get_screen_size(int p_screen = -1) const; - virtual int get_screen_dpi(int p_screen = -1) const; - virtual Point2 get_window_position() const; - virtual void set_window_position(const Point2 &p_position); - virtual Size2 get_window_size() const; - virtual Size2 get_real_window_size() const; - virtual Size2 get_max_window_size() const; - virtual Size2 get_min_window_size() const; - virtual void set_min_window_size(const Size2 p_size); - virtual void set_max_window_size(const Size2 p_size); - virtual void set_window_size(const Size2 p_size); - virtual void set_window_fullscreen(bool p_enabled); - virtual bool is_window_fullscreen() const; - virtual void set_window_resizable(bool p_enabled); - virtual bool is_window_resizable() const; - virtual void set_window_minimized(bool p_enabled); - virtual bool is_window_minimized() const; - virtual void set_window_maximized(bool p_enabled); - virtual bool is_window_maximized() const; - virtual void set_window_always_on_top(bool p_enabled); - virtual bool is_window_always_on_top() const; - virtual bool is_window_focused() const; - virtual void request_attention(); - - virtual void set_borderless_window(bool p_borderless); - virtual bool get_borderless_window(); - - virtual bool get_window_per_pixel_transparency_enabled() const; - virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); - - virtual void set_ime_active(const bool p_active); - virtual void set_ime_position(const Point2 &p_pos); - - virtual String get_unique_id() const; - - virtual void move_window_to_foreground(); - virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); - - virtual bool is_joy_known(int p_device); - virtual String get_joy_guid(int p_device) const; - - virtual void set_context(int p_context); - - virtual void _set_use_vsync(bool p_enable); - //virtual bool is_vsync_enabled() const; - - virtual bool _check_internal_feature_support(const String &p_feature); - - virtual void force_process_input(); - void run(); - - void disable_crash_handler(); - bool is_disable_crash_handler() const; - - virtual Error move_to_trash(const String &p_path); - - virtual LatinKeyboardVariant get_latin_keyboard_variant() const; - - void update_real_mouse_position(); - OS_X11(); -}; - -#endif diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 3ef4dfe5f1..df0b17800f 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "scene/2d/area_2d.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void AudioStreamPlayer2D::_mix_audio() { diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 04b5260444..7a106ef79a 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -32,7 +32,7 @@ #define CAMERA_2D_H #include "scene/2d/node_2d.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" class Camera2D : public Node2D { diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index ef7aa9ba01..7a0fc3352b 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -29,11 +29,13 @@ /*************************************************************************/ #include "canvas_item.h" + +#include "core/input/input_filter.h" #include "core/message_queue.h" #include "core/method_bind_ext.gen.inc" -#include "core/os/input.h" #include "scene/main/canvas_layer.h" #include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/font.h" #include "scene/resources/style_box.h" #include "scene/resources/texture.h" @@ -347,6 +349,9 @@ bool CanvasItem::is_visible_in_tree() const { while (p) { if (!p->visible) return false; + if (p->window && !p->window->is_visible()) { + return false; + } p = p->get_parent_item(); } @@ -450,6 +455,21 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const { return get_global_transform(); } +Transform2D CanvasItem::get_screen_transform() const { + ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); + Transform2D xform = get_global_transform_with_canvas(); + + Window *w = Object::cast_to<Window>(get_viewport()); + if (w && !w->is_embedding_subwindows()) { + Transform2D s; + s.set_origin(w->get_position()); + + xform = s * xform; + } + + return xform; +} + Transform2D CanvasItem::get_global_transform() const { #ifdef DEBUG_ENABLED ERR_FAIL_COND_V(!is_inside_tree(), get_transform()); @@ -548,10 +568,30 @@ void CanvasItem::_notification(int p_what) { _update_texture_repeat_changed(false); first_draw = true; - if (get_parent()) { - CanvasItem *ci = Object::cast_to<CanvasItem>(get_parent()); + Node *parent = get_parent(); + if (parent) { + CanvasItem *ci = Object::cast_to<CanvasItem>(parent); if (ci) C = ci->children_items.push_back(this); + if (!ci) { + //look for a window + Viewport *viewport = nullptr; + + while (parent) { + viewport = Object::cast_to<Viewport>(parent); + if (viewport) { + break; + } + parent = parent->get_parent(); + } + + ERR_FAIL_COND(!viewport); + + window = Object::cast_to<Window>(viewport); + if (window) { + window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + } + } } _enter_canvas(); if (!block_transform_notify && !xform_change.in_list()) { @@ -580,6 +620,9 @@ void CanvasItem::_notification(int p_what) { Object::cast_to<CanvasItem>(get_parent())->children_items.erase(C); C = NULL; } + if (window) { + window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + } global_invalid = true; } break; case NOTIFICATION_DRAW: @@ -600,6 +643,14 @@ void CanvasItem::set_visible(bool p_visible) { else hide(); } + +void CanvasItem::_window_visibility_changed() { + + if (visible) { + _propagate_visibility_changed(window->is_visible()); + } +} + bool CanvasItem::is_visible() const { return visible; @@ -1408,6 +1459,7 @@ CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const { CanvasItem::CanvasItem() : xform_change(this) { + window = nullptr; canvas_item = VisualServer::get_singleton()->canvas_item_create(); visible = true; pending_update = false; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index c7f9500ea1..3f176e5f60 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -201,6 +201,7 @@ private: int light_mask; + Window *window; bool first_draw; bool visible; bool pending_update; @@ -232,6 +233,8 @@ private: void _enter_canvas(); void _exit_canvas(); + void _window_visibility_changed(); + void _notify_transform(CanvasItem *p_node); void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); } @@ -364,6 +367,7 @@ public: virtual Transform2D get_global_transform() const; virtual Transform2D get_global_transform_with_canvas() const; + virtual Transform2D get_screen_transform() const; CanvasItem *get_toplevel() const; _FORCE_INLINE_ RID get_canvas_item() const { diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index df21538609..0b0b9820d3 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -32,7 +32,7 @@ #include "core/message_queue.h" #include "scene/gui/control.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "servers/visual_server.h" #ifdef TOOLS_ENABLED diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 2ba2fd8f79..e5c17fe9a4 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -228,7 +228,7 @@ bool Particles2D::get_fractional_delta() const { String Particles2D::get_configuration_warning() const { - if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { + if (VisualServer::get_singleton()->is_low_end()) { return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); } diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 7eaafe5348..a6fb6f7435 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -32,7 +32,7 @@ #include "core/core_string_names.h" #include "core/os/os.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" #ifdef TOOLS_ENABLED diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index 1cca45b422..2cb979a0e0 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -30,10 +30,11 @@ #include "touch_screen_button.h" -#include "core/input_map.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" +#include "core/input/input_map.h" #include "core/os/os.h" - +#include "scene/main/window.h" +# void TouchScreenButton::set_texture(const Ref<Texture2D> &p_texture) { texture = p_texture; @@ -114,7 +115,7 @@ void TouchScreenButton::_notification(int p_what) { if (!is_inside_tree()) return; - if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility == VISIBILITY_TOUCHSCREEN_ONLY) + if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY) return; if (finger_pressed != -1) { @@ -145,7 +146,7 @@ void TouchScreenButton::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { - if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility == VISIBILITY_TOUCHSCREEN_ONLY) + if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY) return; update(); @@ -289,12 +290,12 @@ void TouchScreenButton::_press(int p_finger_pressed) { if (action != StringName()) { - Input::get_singleton()->action_press(action); + InputFilter::get_singleton()->action_press(action); Ref<InputEventAction> iea; iea.instance(); iea->set_action(action); iea->set_pressed(true); - get_tree()->input_event(iea); + get_viewport()->input(iea, true); } emit_signal("pressed"); @@ -307,14 +308,14 @@ void TouchScreenButton::_release(bool p_exiting_tree) { if (action != StringName()) { - Input::get_singleton()->action_release(action); + InputFilter::get_singleton()->action_release(action); if (!p_exiting_tree) { Ref<InputEventAction> iea; iea.instance(); iea->set_action(action); iea->set_pressed(false); - get_tree()->input_event(iea); + get_viewport()->input(iea, true); } } diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 54511bbe1b..65dabb92b1 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -35,7 +35,7 @@ #include "scene/2d/animated_sprite.h" #include "scene/2d/physics_body_2d.h" #include "scene/animation/animation_player.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" #ifdef TOOLS_ENABLED diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index d23e5ffa08..bea717b354 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "arvr_nodes.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "servers/arvr/arvr_interface.h" #include "servers/arvr_server.h" @@ -206,7 +206,7 @@ void ARVRController::_notification(int p_what) { // check button states for (int i = 0; i < 16; i++) { bool was_pressed = (button_states & mask) == mask; - bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i); + bool is_pressed = InputFilter::get_singleton()->is_joy_button_pressed(joy_id, i); if (!was_pressed && is_pressed) { emit_signal("button_pressed", i); @@ -306,7 +306,7 @@ bool ARVRController::is_button_pressed(int p_button) const { return false; }; - return Input::get_singleton()->is_joy_button_pressed(joy_id, p_button); + return InputFilter::get_singleton()->is_joy_button_pressed(joy_id, p_button); }; float ARVRController::get_joystick_axis(int p_axis) const { @@ -315,7 +315,7 @@ float ARVRController::get_joystick_axis(int p_axis) const { return 0.0; }; - return Input::get_singleton()->get_joy_axis(joy_id, p_axis); + return InputFilter::get_singleton()->get_joy_axis(joy_id, p_axis); }; real_t ARVRController::get_rumble() const { diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index f0a61a905c..f3020d4044 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -33,7 +33,7 @@ #include "scene/3d/area.h" #include "scene/3d/camera.h" #include "scene/3d/listener.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" // Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004) // Speaker-Placement Correction Amplitude Panning (SPCAP) diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 6ac3ece798..feb7b39b1e 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -33,7 +33,7 @@ #include "scene/3d/spatial.h" #include "scene/3d/spatial_velocity_tracker.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/environment.h" class Camera : public Spatial { diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index c3f039ae85..76549f7e51 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -526,7 +526,7 @@ Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const { String GIProbe::get_configuration_warning() const { - if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { + if (VisualServer::get_singleton()->is_low_end()) { return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); } return String(); diff --git a/scene/3d/listener.h b/scene/3d/listener.h index 287e67f31e..17ff1d9397 100644 --- a/scene/3d/listener.h +++ b/scene/3d/listener.h @@ -32,7 +32,7 @@ #define LISTENER_H #include "scene/3d/spatial.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" class Listener : public Spatial { diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index e502b0c037..7a1eeb105a 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -240,7 +240,7 @@ bool Particles::get_fractional_delta() const { String Particles::get_configuration_warning() const { - if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { + if (VisualServer::get_singleton()->is_low_end()) { return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); } diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index f1911348ce..c6225dd291 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -33,7 +33,7 @@ #include "core/engine.h" #include "core/message_queue.h" #include "scene/main/scene_tree.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" /* diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 83a7243906..9276432ba9 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "world_environment.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void WorldEnvironment::_notification(int p_what) { diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 7a184adc55..359f936793 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -34,7 +34,7 @@ #include "core/io/marshalls.h" #include "core/script_language.h" #include "scene/main/scene_tree.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" void SceneDebugger::initialize() { diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index b2020d44e8..a05ac08e9d 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -31,7 +31,7 @@ #include "base_button.h" #include "core/os/keyboard.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" void BaseButton::_unpress_group() { @@ -357,9 +357,6 @@ void BaseButton::_unhandled_input(Ref<InputEvent> p_event) { if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { - if (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)) - return; //ignore because of modal window - on_action_event(p_event); } } diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index e0bfeac9f7..0da6e0fdfa 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -45,7 +45,7 @@ void BoxContainer::_resort() { Size2i new_size = get_size(); - int sep = get_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer"); + int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer"); bool first = true; int children_count = 0; @@ -206,7 +206,7 @@ Size2 BoxContainer::get_minimum_size() const { /* Calculate MINIMUM SIZE */ Size2i minimum; - int sep = get_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer"); + int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer"); bool first = true; @@ -310,7 +310,7 @@ MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control l->set_text(p_label); add_child(l); MarginContainer *mc = memnew(MarginContainer); - mc->add_constant_override("margin_left", 0); + mc->add_theme_constant_override("margin_left", 0); mc->add_child(p_control); add_child(mc); if (p_expand) diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 784d298bff..f71d322412 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -35,14 +35,14 @@ Size2 Button::get_minimum_size() const { - Size2 minsize = get_font("font")->get_string_size(xl_text); + Size2 minsize = get_theme_font("font")->get_string_size(xl_text); if (clip_text) minsize.width = 0; if (!expand_icon) { Ref<Texture2D> _icon; - if (icon.is_null() && has_icon("icon")) - _icon = Control::get_icon("icon"); + if (icon.is_null() && has_theme_icon("icon")) + _icon = Control::get_theme_icon("icon"); else _icon = icon; @@ -51,11 +51,11 @@ Size2 Button::get_minimum_size() const { minsize.height = MAX(minsize.height, _icon->get_height()); minsize.width += _icon->get_width(); if (xl_text != "") - minsize.width += get_constant("hseparation"); + minsize.width += get_theme_constant("hseparation"); } } - return get_stylebox("normal")->get_minimum_size() + minsize; + return get_theme_stylebox("normal")->get_minimum_size() + minsize; } void Button::_set_internal_margin(Margin p_margin, float p_value) { @@ -79,30 +79,30 @@ void Button::_notification(int p_what) { Color color; Color color_icon(1, 1, 1, 1); - Ref<StyleBox> style = get_stylebox("normal"); + Ref<StyleBox> style = get_theme_stylebox("normal"); switch (get_draw_mode()) { case DRAW_NORMAL: { - style = get_stylebox("normal"); + style = get_theme_stylebox("normal"); if (!flat) style->draw(ci, Rect2(Point2(0, 0), size)); - color = get_color("font_color"); - if (has_color("icon_color_normal")) - color_icon = get_color("icon_color_normal"); + color = get_theme_color("font_color"); + if (has_theme_color("icon_color_normal")) + color_icon = get_theme_color("icon_color_normal"); } break; case DRAW_HOVER_PRESSED: { - if (has_stylebox("hover_pressed") && has_stylebox_override("hover_pressed")) { - style = get_stylebox("hover_pressed"); + if (has_theme_stylebox("hover_pressed") && has_theme_stylebox_override("hover_pressed")) { + style = get_theme_stylebox("hover_pressed"); if (!flat) style->draw(ci, Rect2(Point2(0, 0), size)); - if (has_color("font_color_hover_pressed")) - color = get_color("font_color_hover_pressed"); + if (has_theme_color("font_color_hover_pressed")) + color = get_theme_color("font_color_hover_pressed"); else - color = get_color("font_color"); - if (has_color("icon_color_hover_pressed")) - color_icon = get_color("icon_color_hover_pressed"); + color = get_theme_color("font_color"); + if (has_theme_color("icon_color_hover_pressed")) + color_icon = get_theme_color("icon_color_hover_pressed"); break; } @@ -110,49 +110,49 @@ void Button::_notification(int p_what) { } case DRAW_PRESSED: { - style = get_stylebox("pressed"); + style = get_theme_stylebox("pressed"); if (!flat) style->draw(ci, Rect2(Point2(0, 0), size)); - if (has_color("font_color_pressed")) - color = get_color("font_color_pressed"); + if (has_theme_color("font_color_pressed")) + color = get_theme_color("font_color_pressed"); else - color = get_color("font_color"); - if (has_color("icon_color_pressed")) - color_icon = get_color("icon_color_pressed"); + color = get_theme_color("font_color"); + if (has_theme_color("icon_color_pressed")) + color_icon = get_theme_color("icon_color_pressed"); } break; case DRAW_HOVER: { - style = get_stylebox("hover"); + style = get_theme_stylebox("hover"); if (!flat) style->draw(ci, Rect2(Point2(0, 0), size)); - color = get_color("font_color_hover"); - if (has_color("icon_color_hover")) - color_icon = get_color("icon_color_hover"); + color = get_theme_color("font_color_hover"); + if (has_theme_color("icon_color_hover")) + color_icon = get_theme_color("icon_color_hover"); } break; case DRAW_DISABLED: { - style = get_stylebox("disabled"); + style = get_theme_stylebox("disabled"); if (!flat) style->draw(ci, Rect2(Point2(0, 0), size)); - color = get_color("font_color_disabled"); - if (has_color("icon_color_disabled")) - color_icon = get_color("icon_color_disabled"); + color = get_theme_color("font_color_disabled"); + if (has_theme_color("icon_color_disabled")) + color_icon = get_theme_color("icon_color_disabled"); } break; } if (has_focus()) { - Ref<StyleBox> style2 = get_stylebox("focus"); + Ref<StyleBox> style2 = get_theme_stylebox("focus"); style2->draw(ci, Rect2(Point2(), size)); } - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); Ref<Texture2D> _icon; - if (icon.is_null() && has_icon("icon")) - _icon = Control::get_icon("icon"); + if (icon.is_null() && has_theme_icon("icon")) + _icon = Control::get_theme_icon("icon"); else _icon = icon; @@ -166,14 +166,14 @@ void Button::_notification(int p_what) { float icon_ofs_region = 0; if (_internal_margin[MARGIN_LEFT] > 0) { - icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_constant("hseparation"); + icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation"); } if (expand_icon) { Size2 _size = get_size() - style->get_offset() * 2; - _size.width -= get_constant("hseparation") + icon_ofs_region; + _size.width -= get_theme_constant("hseparation") + icon_ofs_region; if (!clip_text) - _size.width -= get_font("font")->get_string_size(xl_text).width; + _size.width -= get_theme_font("font")->get_string_size(xl_text).width; float icon_width = _icon->get_width() * _size.height / _icon->get_height(); float icon_height = _size.height; @@ -188,13 +188,13 @@ void Button::_notification(int p_what) { } } - Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_constant("hseparation"), 0) : Point2(); + Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant("hseparation"), 0) : Point2(); int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width; if (_internal_margin[MARGIN_LEFT] > 0) { - text_clip -= _internal_margin[MARGIN_LEFT] + get_constant("hseparation"); + text_clip -= _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation"); } if (_internal_margin[MARGIN_RIGHT] > 0) { - text_clip -= _internal_margin[MARGIN_RIGHT] + get_constant("hseparation"); + text_clip -= _internal_margin[MARGIN_RIGHT] + get_theme_constant("hseparation"); } Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text) - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0; @@ -202,7 +202,7 @@ void Button::_notification(int p_what) { switch (align) { case ALIGN_LEFT: { if (_internal_margin[MARGIN_LEFT] > 0) { - text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_constant("hseparation"); + text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation"); } else { text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x; } @@ -216,7 +216,7 @@ void Button::_notification(int p_what) { } break; case ALIGN_RIGHT: { if (_internal_margin[MARGIN_RIGHT] > 0) { - text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_constant("hseparation"); + text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_theme_constant("hseparation"); } else { text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x; } diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 89bd8ab0dd..d68bd4fe4e 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -33,10 +33,10 @@ #include "servers/visual_server.h" Size2 CheckBox::get_icon_size() const { - Ref<Texture2D> checked = Control::get_icon("checked"); - Ref<Texture2D> unchecked = Control::get_icon("unchecked"); - Ref<Texture2D> radio_checked = Control::get_icon("radio_checked"); - Ref<Texture2D> radio_unchecked = Control::get_icon("radio_unchecked"); + Ref<Texture2D> checked = Control::get_theme_icon("checked"); + Ref<Texture2D> unchecked = Control::get_theme_icon("unchecked"); + Ref<Texture2D> radio_checked = Control::get_theme_icon("radio_checked"); + Ref<Texture2D> radio_unchecked = Control::get_theme_icon("radio_unchecked"); Size2 tex_size = Size2(0, 0); if (!checked.is_null()) @@ -56,9 +56,9 @@ Size2 CheckBox::get_minimum_size() const { Size2 tex_size = get_icon_size(); minsize.width += tex_size.width; if (get_text().length() > 0) { - minsize.width += get_constant("hseparation"); + minsize.width += get_theme_constant("hseparation"); } - Ref<StyleBox> sb = get_stylebox("normal"); + Ref<StyleBox> sb = get_theme_stylebox("normal"); minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM)); return minsize; @@ -73,13 +73,13 @@ void CheckBox::_notification(int p_what) { RID ci = get_canvas_item(); - Ref<Texture2D> on = Control::get_icon(is_radio() ? "radio_checked" : "checked"); - Ref<Texture2D> off = Control::get_icon(is_radio() ? "radio_unchecked" : "unchecked"); - Ref<StyleBox> sb = get_stylebox("normal"); + Ref<Texture2D> on = Control::get_theme_icon(is_radio() ? "radio_checked" : "checked"); + Ref<Texture2D> off = Control::get_theme_icon(is_radio() ? "radio_unchecked" : "unchecked"); + Ref<StyleBox> sb = get_theme_stylebox("normal"); Vector2 ofs; ofs.x = sb->get_margin(MARGIN_LEFT); - ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_constant("check_vadjust"); + ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant("check_vadjust"); if (is_pressed()) on->draw(ci, ofs); diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index 0b093ce850..ac967a128c 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -35,8 +35,8 @@ Size2 CheckButton::get_icon_size() const { - Ref<Texture2D> on = Control::get_icon(is_disabled() ? "on_disabled" : "on"); - Ref<Texture2D> off = Control::get_icon(is_disabled() ? "off_disabled" : "off"); + Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on"); + Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off"); Size2 tex_size = Size2(0, 0); if (!on.is_null()) tex_size = Size2(on->get_width(), on->get_height()); @@ -52,8 +52,8 @@ Size2 CheckButton::get_minimum_size() const { Size2 tex_size = get_icon_size(); minsize.width += tex_size.width; if (get_text().length() > 0) - minsize.width += get_constant("hseparation"); - Ref<StyleBox> sb = get_stylebox("normal"); + minsize.width += get_theme_constant("hseparation"); + Ref<StyleBox> sb = get_theme_stylebox("normal"); minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM)); return minsize; @@ -68,15 +68,15 @@ void CheckButton::_notification(int p_what) { RID ci = get_canvas_item(); - Ref<Texture2D> on = Control::get_icon(is_disabled() ? "on_disabled" : "on"); - Ref<Texture2D> off = Control::get_icon(is_disabled() ? "off_disabled" : "off"); + Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on"); + Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off"); - Ref<StyleBox> sb = get_stylebox("normal"); + Ref<StyleBox> sb = get_theme_stylebox("normal"); Vector2 ofs; Size2 tex_size = get_icon_size(); ofs.x = get_size().width - (tex_size.width + sb->get_margin(MARGIN_RIGHT)); - ofs.y = (get_size().height - tex_size.height) / 2 + get_constant("check_vadjust"); + ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant("check_vadjust"); if (is_pressed()) on->draw(ci, ofs); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index a8b5ac6909..2ec9bb2292 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -30,7 +30,7 @@ #include "color_picker.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "core/os/os.h" @@ -38,22 +38,22 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #endif -#include "scene/main/viewport.h" +#include "scene/main/window.h" void ColorPicker::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - btn_pick->set_icon(get_icon("screen_picker", "ColorPicker")); - bt_add_preset->set_icon(get_icon("add_preset")); + btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker")); + bt_add_preset->set_icon(get_theme_icon("add_preset")); _update_controls(); } break; case NOTIFICATION_ENTER_TREE: { - btn_pick->set_icon(get_icon("screen_picker", "ColorPicker")); - bt_add_preset->set_icon(get_icon("add_preset")); + btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker")); + bt_add_preset->set_icon(get_theme_icon("add_preset")); _update_color(); @@ -70,15 +70,15 @@ void ColorPicker::_notification(int p_what) { case NOTIFICATION_PARENTED: { for (int i = 0; i < 4; i++) - set_margin((Margin)i, get_constant("margin")); + set_margin((Margin)i, get_theme_constant("margin")); } break; case NOTIFICATION_VISIBILITY_CHANGED: { Popup *p = Object::cast_to<Popup>(get_parent()); if (p) - p->set_size(Size2(get_combined_minimum_size().width + get_constant("margin") * 2, get_combined_minimum_size().height + get_constant("margin") * 2)); + p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant("margin") * 2, get_combined_minimum_size().height + get_theme_constant("margin") * 2)); } break; - case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { + case NOTIFICATION_WM_CLOSE_REQUEST: { if (screen != NULL && screen->is_visible()) screen->hide(); @@ -247,6 +247,9 @@ void ColorPicker::_update_color(bool p_update_sliders) { } void ColorPicker::_update_presets() { + return; + //presets should be shown using buttons or something else, this method is not a good idea + presets_per_row = 10; Size2 size = bt_add_preset->get_size(); Size2 preset_size = Size2(MIN(size.width * presets.size(), presets_per_row * size.width), size.height * (Math::ceil((float)presets.size() / presets_per_row))); @@ -267,7 +270,7 @@ void ColorPicker::_text_type_toggled() { text_is_constructor = !text_is_constructor; if (text_is_constructor) { text_type->set_text(""); - text_type->set_icon(get_icon("Script", "EditorIcons")); + text_type->set_icon(get_theme_icon("Script", "EditorIcons")); c_text->set_editable(false); } else { @@ -399,14 +402,14 @@ void ColorPicker::_sample_draw() { const Rect2 r = Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95)); if (color.a < 1.0) { - sample->draw_texture_rect(get_icon("preset_bg", "ColorPicker"), r, true); + sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), r, true); } sample->draw_rect(r, color); if (color.r > 1 || color.g > 1 || color.b > 1) { // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - sample->draw_texture(get_icon("overbright_indicator", "ColorPicker"), Point2()); + sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2()); } } @@ -445,7 +448,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted()); c->draw_line(Point2(x, y), Point2(x, y), Color(1, 1, 1), 2); } else if (p_which == 1) { - Ref<Texture2D> hue = get_icon("color_hue", "ColorPicker"); + Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker"); c->draw_texture_rect(hue, Rect2(Point2(), c->get_size())); int y = c->get_size().y - c->get_size().y * (1.0 - h); Color col = Color(); @@ -620,7 +623,10 @@ void ColorPicker::_screen_pick_pressed() { screen->call_deferred("connect", "hide", Callable(btn_pick, "set_pressed"), varray(false)); } screen->raise(); - screen->show_modal(); +#ifndef _MSC_VER +#warning show modal no longer works, needs to be converted to a popup +#endif + //screen->show_modal(); } void ColorPicker::_focus_enter() { @@ -738,12 +744,12 @@ ColorPicker::ColorPicker() : uv_edit->set_mouse_filter(MOUSE_FILTER_PASS); uv_edit->set_h_size_flags(SIZE_EXPAND_FILL); uv_edit->set_v_size_flags(SIZE_EXPAND_FILL); - uv_edit->set_custom_minimum_size(Size2(get_constant("sv_width"), get_constant("sv_height"))); + uv_edit->set_custom_minimum_size(Size2(get_theme_constant("sv_width"), get_theme_constant("sv_height"))); uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit)); w_edit = memnew(Control); hb_edit->add_child(w_edit); - w_edit->set_custom_minimum_size(Size2(get_constant("h_width"), 0)); + w_edit->set_custom_minimum_size(Size2(get_theme_constant("h_width"), 0)); w_edit->set_h_size_flags(SIZE_FILL); w_edit->set_v_size_flags(SIZE_EXPAND_FILL); w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input)); @@ -777,7 +783,7 @@ ColorPicker::ColorPicker() : HBoxContainer *hbc = memnew(HBoxContainer); labels[i] = memnew(Label()); - labels[i]->set_custom_minimum_size(Size2(get_constant("label_width"), 0)); + labels[i]->set_custom_minimum_size(Size2(get_theme_constant("label_width"), 0)); labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER); hbc->add_child(labels[i]); @@ -881,8 +887,32 @@ void ColorPickerButton::_modal_closed() { void ColorPickerButton::pressed() { _update_picker(); - popup->set_position(get_global_position() - picker->get_combined_minimum_size() * get_global_transform().get_scale()); - popup->set_scale(get_global_transform().get_scale()); + + popup->set_as_minsize(); + + Rect2i usable_rect = popup->get_usable_parent_rect(); + //let's try different positions to see which one we can use + + Rect2i cp_rect(Point2i(), popup->get_size()); + for (int i = 0; i < 4; i++) { + if (i > 1) { + cp_rect.position.y = get_screen_position().y - cp_rect.size.y; + } else { + cp_rect.position.y = get_screen_position().y + get_size().height; + } + + if (i & 1) { + cp_rect.position.x = get_screen_position().x; + } else { + + cp_rect.position.x = get_screen_position().x - MAX(0, (cp_rect.size.x - get_size().x)); + } + + if (usable_rect.encloses(cp_rect)) { + break; + } + } + popup->set_position(cp_rect.position); popup->popup(); picker->set_focus_on_line_edit(); } @@ -892,17 +922,17 @@ void ColorPickerButton::_notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { - const Ref<StyleBox> normal = get_stylebox("normal"); + const Ref<StyleBox> normal = get_theme_stylebox("normal"); const Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size()); - draw_texture_rect(Control::get_icon("bg", "ColorPickerButton"), r, true); + draw_texture_rect(Control::get_theme_icon("bg", "ColorPickerButton"), r, true); draw_rect(r, color); if (color.r > 1 || color.g > 1 || color.b > 1) { // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - draw_texture(Control::get_icon("overbright_indicator", "ColorPicker"), normal->get_offset()); + draw_texture(Control::get_theme_icon("overbright_indicator", "ColorPicker"), normal->get_offset()); } } break; - case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: { + case NOTIFICATION_WM_CLOSE_REQUEST: { if (popup) popup->hide(); @@ -958,12 +988,14 @@ PopupPanel *ColorPickerButton::get_popup() { void ColorPickerButton::_update_picker() { if (!picker) { popup = memnew(PopupPanel); + popup->set_wrap_controls(true); picker = memnew(ColorPicker); + picker->set_anchors_and_margins_preset(PRESET_WIDE); popup->add_child(picker); add_child(popup); picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed)); popup->connect("modal_closed", callable_mp(this, &ColorPickerButton::_modal_closed)); - popup->connect("about_to_show", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); + popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false)); picker->set_pick_color(color); picker->set_edit_alpha(edit_alpha); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 1a231e368b..14bca0e2c8 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -38,7 +38,7 @@ #include "scene/gui/label.h" #include "scene/gui/panel.h" #include "scene/main/canvas_layer.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/scene_string_names.h" #include "servers/visual_server.h" @@ -260,22 +260,22 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { } else { if (name.begins_with("custom_icons/")) { String dname = name.get_slicec('/', 1); - add_icon_override(dname, p_value); + add_theme_icon_override(dname, p_value); } else if (name.begins_with("custom_shaders/")) { String dname = name.get_slicec('/', 1); - add_shader_override(dname, p_value); + add_theme_shader_override(dname, p_value); } else if (name.begins_with("custom_styles/")) { String dname = name.get_slicec('/', 1); - add_style_override(dname, p_value); + add_theme_style_override(dname, p_value); } else if (name.begins_with("custom_fonts/")) { String dname = name.get_slicec('/', 1); - add_font_override(dname, p_value); + add_theme_font_override(dname, p_value); } else if (name.begins_with("custom_colors/")) { String dname = name.get_slicec('/', 1); - add_color_override(dname, p_value); + add_theme_color_override(dname, p_value); } else if (name.begins_with("custom_constants/")) { String dname = name.get_slicec('/', 1); - add_constant_override(dname, p_value); + add_theme_constant_override(dname, p_value); } else return false; } @@ -438,22 +438,30 @@ void Control::_resize(const Size2 &p_size) { void Control::add_child_notify(Node *p_child) { Control *child_c = Object::cast_to<Control>(p_child); - if (!child_c) - return; - if (child_c->data.theme.is_null() && data.theme_owner) { - _propagate_theme_changed(child_c, data.theme_owner); //need to propagate here, since many controls may require setting up stuff + if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) { + _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) { + _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff } } void Control::remove_child_notify(Node *p_child) { Control *child_c = Object::cast_to<Control>(p_child); - if (!child_c) - return; - if (child_c->data.theme_owner && child_c->data.theme.is_null()) { - _propagate_theme_changed(child_c, NULL); + if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { + _propagate_theme_changed(child_c, NULL, NULL); + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { + _propagate_theme_changed(child_w, NULL, NULL); } } @@ -486,76 +494,54 @@ void Control::_notification(int p_notification) { data.parent = Object::cast_to<Control>(get_parent()); - if (is_set_as_toplevel()) { - data.SI = get_viewport()->_gui_add_subwindow_control(this); - - if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { - data.theme_owner = data.parent->data.theme_owner; - notification(NOTIFICATION_THEME_CHANGED); - } - - } else { - - Node *parent = this; //meh - Control *parent_control = NULL; - bool subwindow = false; + Node *parent = this; //meh + Control *parent_control = NULL; + bool subwindow = false; - while (parent) { - - parent = parent->get_parent(); - - if (!parent) - break; - - CanvasItem *ci = Object::cast_to<CanvasItem>(parent); - if (ci && ci->is_set_as_toplevel()) { - subwindow = true; - break; - } + while (parent) { - parent_control = Object::cast_to<Control>(parent); + parent = parent->get_parent(); - if (parent_control) { - break; - } else if (ci) { + if (!parent) + break; - } else { - break; - } + CanvasItem *ci = Object::cast_to<CanvasItem>(parent); + if (ci && ci->is_set_as_toplevel()) { + subwindow = true; + break; } - if (parent_control) { - //do nothing, has a parent control - if (data.theme.is_null() && parent_control->data.theme_owner) { - data.theme_owner = parent_control->data.theme_owner; - notification(NOTIFICATION_THEME_CHANGED); - } - } else if (subwindow) { - //is a subwindow (process input before other controls for that canvas) - data.SI = get_viewport()->_gui_add_subwindow_control(this); - } else { - //is a regular root control - data.RI = get_viewport()->_gui_add_root_control(this); - } + parent_control = Object::cast_to<Control>(parent); - data.parent_canvas_item = get_parent_item(); - - if (data.parent_canvas_item) { + if (parent_control) { + break; + } else if (ci) { - data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed)); } else { - //connect viewport - get_viewport()->connect("size_changed", callable_mp(this, &Control::_size_changed)); + break; } } - /* - if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { - data.theme_owner=data.parent->data.theme_owner; - notification(NOTIFICATION_THEME_CHANGED); + if (parent_control && !subwindow) { + //do nothing, has a parent control and not toplevel + if (data.theme.is_null() && parent_control->data.theme_owner) { + data.theme_owner = parent_control->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } + } else { + //is a regular root control or toplevel + data.RI = get_viewport()->_gui_add_root_control(this); } - */ + data.parent_canvas_item = get_parent_item(); + + if (data.parent_canvas_item) { + + data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed)); + } else { + //connect viewport + get_viewport()->connect("size_changed", callable_mp(this, &Control::_size_changed)); + } } break; case NOTIFICATION_EXIT_CANVAS: { @@ -568,16 +554,6 @@ void Control::_notification(int p_notification) { get_viewport()->disconnect("size_changed", callable_mp(this, &Control::_size_changed)); } - if (data.MI) { - get_viewport()->_gui_remove_modal_control(data.MI); - data.MI = NULL; - } - - if (data.SI) { - get_viewport()->_gui_remove_subwindow_control(data.SI); - data.SI = NULL; - } - if (data.RI) { get_viewport()->_gui_remove_root_control(data.RI); data.RI = NULL; @@ -600,9 +576,6 @@ void Control::_notification(int p_notification) { data.parent->update(); update(); - if (data.SI) { - get_viewport()->_gui_set_subwindow_order_dirty(); - } if (data.RI) { get_viewport()->_gui_set_root_order_dirty(); } @@ -644,10 +617,6 @@ void Control::_notification(int p_notification) { minimum_size_changed(); update(); } break; - case NOTIFICATION_MODAL_CLOSE: { - - emit_signal("modal_closed"); - } break; case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible_in_tree()) { @@ -655,23 +624,14 @@ void Control::_notification(int p_notification) { if (get_viewport() != NULL) get_viewport()->_gui_hid_control(this); - if (is_inside_tree()) { - _modal_stack_remove(); - } - //remove key focus - //remove modalness + } else { data.minimum_size_valid = false; _size_changed(); } } break; - case SceneTree::NOTIFICATION_WM_UNFOCUS_REQUEST: { - - get_viewport()->_gui_unfocus_control(this); - - } break; } } @@ -787,19 +747,6 @@ void Control::set_drag_preview(Control *p_control) { get_viewport()->_gui_set_drag_preview(this, p_control); } -bool Control::is_window_modal_on_top() const { - - if (!is_inside_tree()) - return false; - - return get_viewport()->_gui_is_modal_on_top(this); -} - -uint64_t Control::get_modal_frame() const { - - return data.modal_frame; -} - Size2 Control::get_minimum_size() const { ScriptInstance *si = const_cast<Control *>(this)->get_script_instance(); @@ -813,50 +760,130 @@ Size2 Control::get_minimum_size() const { return Size2(); } -Ref<Texture2D> Control::get_icon(const StringName &p_name, const StringName &p_type) const { +template <class T> +bool Control::_find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &r_ret, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) { - if (p_type == StringName() || p_type == get_class_name()) { + // try with custom themes + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; - const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); - if (tex) - return *tex; + while (theme_owner || theme_owner_window) { + + StringName class_name = p_type; + + while (class_name != StringName()) { + if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) { + r_ret = (theme_owner->data.theme.operator->()->*get_func)(p_name, class_name); + return true; + } + + if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) { + r_ret = (theme_owner_window->theme.operator->()->*get_func)(p_name, class_name); + return true; + } + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } + + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + + theme_owner = NULL; + theme_owner_window = NULL; + } + } } + return false; +} - StringName type = p_type ? p_type : get_class_name(); +bool Control::_has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) { // try with custom themes - Control *theme_owner = data.theme_owner; + Control *theme_owner = p_theme_owner; + Window *theme_owner_window = p_theme_owner_window; - while (theme_owner) { + while (theme_owner || theme_owner_window) { - StringName class_name = type; + StringName class_name = p_type; while (class_name != StringName()) { - if (theme_owner->data.theme->has_icon(p_name, class_name)) { - return theme_owner->data.theme->get_icon(p_name, class_name); + if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) { + return true; + } + + if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) { + return true; } class_name = ClassDB::get_parent_class_nocheck(class_name); } - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); + + Control *parent_c = Object::cast_to<Control>(parent); + + if (parent_c) { + theme_owner = parent_c->data.theme_owner; + theme_owner_window = parent_c->data.theme_owner_window; + } else { + Window *parent_w = Object::cast_to<Window>(parent); + if (parent_w) { + theme_owner = parent_w->theme_owner; + theme_owner_window = parent_w->theme_owner_window; + } else { + + theme_owner = NULL; + theme_owner_window = NULL; + } + } + } + return false; +} + +Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_type) const { + + if (p_type == StringName() || p_type == get_class_name()) { + + const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); + if (tex) + return *tex; + } + + StringName type = p_type ? p_type : get_class_name(); - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + return get_icons(data.theme_owner, data.theme_owner_window, p_name, type); +} + +Ref<Texture2D> Control::get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { + + Ref<Texture2D> icon; + + if (_find_theme_item(p_theme_owner, p_theme_owner_window, icon, &Theme::get_icon, &Theme::has_icon, p_name, p_type)) { + return icon; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_icon(p_name, type)) { - return Theme::get_project_default()->get_icon(p_name, type); + if (Theme::get_project_default()->has_icon(p_name, p_type)) { + return Theme::get_project_default()->get_icon(p_name, p_type); } } - return Theme::get_default()->get_icon(p_name, type); + return Theme::get_default()->get_icon(p_name, p_type); } -Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_type) const { +Ref<Shader> Control::get_theme_shader(const StringName &p_name, const StringName &p_type) const { + if (p_type == StringName() || p_type == get_class_name()) { const Ref<Shader> *sdr = data.shader_override.getptr(p_name); @@ -866,39 +893,27 @@ Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_ty StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_shader(p_name, class_name)) { - return theme_owner->data.theme->get_shader(p_name, class_name); - } + return get_shaders(data.theme_owner, data.theme_owner_window, p_name, type); +} - class_name = ClassDB::get_parent_class_nocheck(class_name); - } +Ref<Shader> Control::get_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + Ref<Shader> shader; - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(p_theme_owner, p_theme_owner_window, shader, &Theme::get_shader, &Theme::has_shader, p_name, p_type)) { + return shader; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_shader(p_name, type)) { - return Theme::get_project_default()->get_shader(p_name, type); + if (Theme::get_project_default()->has_shader(p_name, p_type)) { + return Theme::get_project_default()->get_shader(p_name, p_type); } } - return Theme::get_default()->get_shader(p_name, type); + return Theme::get_default()->get_shader(p_name, p_type); } -Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &p_type) const { +Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { const Ref<StyleBox> *style = data.style_override.getptr(p_name); @@ -908,43 +923,27 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName & StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; + return get_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type); +} - StringName class_name = type; +Ref<StyleBox> Control::get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - while (theme_owner) { + Ref<StyleBox> stylebox; - while (class_name != StringName()) { - if (theme_owner->data.theme->has_stylebox(p_name, class_name)) { - return theme_owner->data.theme->get_stylebox(p_name, class_name); - } + if (_find_theme_item(p_theme_owner, p_theme_owner_window, stylebox, &Theme::get_stylebox, &Theme::has_stylebox, p_name, p_type)) { + return stylebox; + } - class_name = ClassDB::get_parent_class_nocheck(class_name); + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_stylebox(p_name, p_type)) { + return Theme::get_project_default()->get_stylebox(p_name, p_type); } - - class_name = type; - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; } - while (class_name != StringName()) { - if (Theme::get_project_default().is_valid() && Theme::get_project_default()->has_stylebox(p_name, type)) - return Theme::get_project_default()->get_stylebox(p_name, type); - - if (Theme::get_default()->has_stylebox(p_name, class_name)) - return Theme::get_default()->get_stylebox(p_name, class_name); - - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - return Theme::get_default()->get_stylebox(p_name, type); + return Theme::get_default()->get_stylebox(p_name, p_type); } -Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const { + +Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { const Ref<Font> *font = data.font_override.getptr(p_name); @@ -954,34 +953,27 @@ Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; + return get_fonts(data.theme_owner, data.theme_owner_window, p_name, type); +} - while (theme_owner) { +Ref<Font> Control::get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - StringName class_name = type; + Ref<Font> font; - while (class_name != StringName()) { - if (theme_owner->data.theme->has_font(p_name, class_name)) { - return theme_owner->data.theme->get_font(p_name, class_name); - } + if (_find_theme_item(p_theme_owner, p_theme_owner_window, font, &Theme::get_font, &Theme::has_font, p_name, p_type)) { + return font; + } - class_name = ClassDB::get_parent_class_nocheck(class_name); + if (Theme::get_project_default().is_valid()) { + if (Theme::get_project_default()->has_font(p_name, p_type)) { + return Theme::get_project_default()->get_font(p_name, p_type); } - - if (theme_owner->data.theme->get_default_theme_font().is_valid()) - return theme_owner->data.theme->get_default_theme_font(); - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; } - return Theme::get_default()->get_font(p_name, type); + return Theme::get_default()->get_font(p_name, p_type); } -Color Control::get_color(const StringName &p_name, const StringName &p_type) const { + +Color Control::get_theme_color(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { const Color *color = data.color_override.getptr(p_name); @@ -990,38 +982,27 @@ Color Control::get_color(const StringName &p_name, const StringName &p_type) con } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - StringName class_name = type; + return get_colors(data.theme_owner, data.theme_owner_window, p_name, type); +} - while (class_name != StringName()) { - if (theme_owner->data.theme->has_color(p_name, class_name)) { - return theme_owner->data.theme->get_color(p_name, class_name); - } +Color Control::get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - class_name = ClassDB::get_parent_class_nocheck(class_name); - } + Color color; - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); - - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(p_theme_owner, p_theme_owner_window, color, &Theme::get_color, &Theme::has_color, p_name, p_type)) { + return color; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_color(p_name, type)) { - return Theme::get_project_default()->get_color(p_name, type); + if (Theme::get_project_default()->has_color(p_name, p_type)) { + return Theme::get_project_default()->get_color(p_name, p_type); } } - return Theme::get_default()->get_color(p_name, type); + return Theme::get_default()->get_color(p_name, p_type); } -int Control::get_constant(const StringName &p_name, const StringName &p_type) const { +int Control::get_theme_constant(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { const int *constant = data.constant_override.getptr(p_name); @@ -1030,303 +1011,213 @@ int Control::get_constant(const StringName &p_name, const StringName &p_type) co } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - while (class_name != StringName()) { - if (theme_owner->data.theme->has_constant(p_name, class_name)) { - return theme_owner->data.theme->get_constant(p_name, class_name); - } + return get_constants(data.theme_owner, data.theme_owner_window, p_name, type); +} - class_name = ClassDB::get_parent_class_nocheck(class_name); - } +int Control::get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + int constant; - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_find_theme_item(p_theme_owner, p_theme_owner_window, constant, &Theme::get_constant, &Theme::has_constant, p_name, p_type)) { + return constant; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_constant(p_name, type)) { - return Theme::get_project_default()->get_constant(p_name, type); + if (Theme::get_project_default()->has_constant(p_name, p_type)) { + return Theme::get_project_default()->get_constant(p_name, p_type); } } - return Theme::get_default()->get_constant(p_name, type); + return Theme::get_default()->get_constant(p_name, p_type); } -bool Control::has_icon_override(const StringName &p_name) const { +bool Control::has_theme_icon_override(const StringName &p_name) const { const Ref<Texture2D> *tex = data.icon_override.getptr(p_name); return tex != NULL; } -bool Control::has_shader_override(const StringName &p_name) const { +bool Control::has_theme_shader_override(const StringName &p_name) const { const Ref<Shader> *sdr = data.shader_override.getptr(p_name); return sdr != NULL; } -bool Control::has_stylebox_override(const StringName &p_name) const { +bool Control::has_theme_stylebox_override(const StringName &p_name) const { const Ref<StyleBox> *style = data.style_override.getptr(p_name); return style != NULL; } -bool Control::has_font_override(const StringName &p_name) const { +bool Control::has_theme_font_override(const StringName &p_name) const { const Ref<Font> *font = data.font_override.getptr(p_name); return font != NULL; } -bool Control::has_color_override(const StringName &p_name) const { +bool Control::has_theme_color_override(const StringName &p_name) const { const Color *color = data.color_override.getptr(p_name); return color != NULL; } -bool Control::has_constant_override(const StringName &p_name) const { +bool Control::has_theme_constant_override(const StringName &p_name) const { const int *constant = data.constant_override.getptr(p_name); return constant != NULL; } -bool Control::has_icon(const StringName &p_name, const StringName &p_type) const { +bool Control::has_theme_icon(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { - if (has_icon_override(p_name)) + if (has_theme_icon_override(p_name)) return true; } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_icon(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } + return has_icons(data.theme_owner, data.theme_owner_window, p_name, type); +} - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); +bool Control::has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_icon, p_name, p_type)) { + return true; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_color(p_name, type)) { + if (Theme::get_project_default()->has_color(p_name, p_type)) { return true; } } - return Theme::get_default()->has_icon(p_name, type); + return Theme::get_default()->has_icon(p_name, p_type); } -bool Control::has_shader(const StringName &p_name, const StringName &p_type) const { +bool Control::has_theme_shader(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { - if (has_shader_override(p_name)) + if (has_theme_shader_override(p_name)) return true; } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_shader(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + return has_shaders(data.theme_owner, data.theme_owner_window, p_name, type); +} +bool Control::has_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_shader, p_name, p_type)) { + return true; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_shader(p_name, type)) { + if (Theme::get_project_default()->has_shader(p_name, p_type)) { return true; } } - return Theme::get_default()->has_shader(p_name, type); + return Theme::get_default()->has_shader(p_name, p_type); } -bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) const { + +bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { - if (has_stylebox_override(p_name)) + if (has_theme_stylebox_override(p_name)) return true; } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_stylebox(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } + return has_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type); +} - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); +bool Control::has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_stylebox, p_name, p_type)) { + return true; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_stylebox(p_name, type)) { + if (Theme::get_project_default()->has_stylebox(p_name, p_type)) { return true; } } - return Theme::get_default()->has_stylebox(p_name, type); + return Theme::get_default()->has_stylebox(p_name, p_type); } -bool Control::has_font(const StringName &p_name, const StringName &p_type) const { + +bool Control::has_theme_font(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { - if (has_font_override(p_name)) + if (has_theme_font_override(p_name)) return true; } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_font(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + return has_fonts(data.theme_owner, data.theme_owner_window, p_name, type); +} +bool Control::has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font, p_name, p_type)) { + return true; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_font(p_name, type)) { + if (Theme::get_project_default()->has_font(p_name, p_type)) { return true; } } - return Theme::get_default()->has_font(p_name, type); + return Theme::get_default()->has_font(p_name, p_type); } -bool Control::has_color(const StringName &p_name, const StringName &p_type) const { +bool Control::has_theme_color(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { - if (has_color_override(p_name)) + if (has_theme_color_override(p_name)) return true; } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_color(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } - - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); + return has_colors(data.theme_owner, data.theme_owner_window, p_name, type); +} +bool Control::has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_color, p_name, p_type)) { + return true; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_color(p_name, type)) { + if (Theme::get_project_default()->has_color(p_name, p_type)) { return true; } } - return Theme::get_default()->has_color(p_name, type); + return Theme::get_default()->has_color(p_name, p_type); } -bool Control::has_constant(const StringName &p_name, const StringName &p_type) const { +bool Control::has_theme_constant(const StringName &p_name, const StringName &p_type) const { if (p_type == StringName() || p_type == get_class_name()) { - if (has_constant_override(p_name)) + if (has_theme_constant_override(p_name)) return true; } StringName type = p_type ? p_type : get_class_name(); - // try with custom themes - Control *theme_owner = data.theme_owner; - - while (theme_owner) { - - StringName class_name = type; - - while (class_name != StringName()) { - if (theme_owner->data.theme->has_constant(p_name, class_name)) { - return true; - } - class_name = ClassDB::get_parent_class_nocheck(class_name); - } + return has_constants(data.theme_owner, data.theme_owner_window, p_name, p_type); +} - Control *parent = Object::cast_to<Control>(theme_owner->get_parent()); +bool Control::has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) { - if (parent) - theme_owner = parent->data.theme_owner; - else - theme_owner = NULL; + if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_constant, p_name, p_type)) { + return true; } if (Theme::get_project_default().is_valid()) { - if (Theme::get_project_default()->has_constant(p_name, type)) { + if (Theme::get_project_default()->has_constant(p_name, p_type)) { return true; } } - return Theme::get_default()->has_constant(p_name, type); + return Theme::get_default()->has_constant(p_name, p_type); } Rect2 Control::get_parent_anchorable_rect() const { @@ -1769,6 +1660,17 @@ Point2 Control::get_global_position() const { return get_global_transform().get_origin(); } +Point2 Control::get_screen_position() const { + ERR_FAIL_COND_V(!is_inside_tree(), Point2()); + Point2 global_pos = get_global_position(); + Window *w = Object::cast_to<Window>(get_viewport()); + if (w && !w->is_embedding_subwindows()) { + global_pos += w->get_position(); + } + + return global_pos; +} + void Control::_set_global_position(const Point2 &p_point) { set_global_position(p_point); } @@ -1863,6 +1765,20 @@ Rect2 Control::get_global_rect() const { return Rect2(get_global_position(), get_size()); } +Rect2 Control::get_screen_rect() const { + + ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); + + Rect2 r(get_global_position(), get_size()); + + Window *w = Object::cast_to<Window>(get_viewport()); + if (w && !w->is_embedding_subwindows()) { + r.position += w->get_position(); + } + + return r; +} + Rect2 Control::get_window_rect() const { ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); Rect2 gr = get_global_rect(); @@ -1880,7 +1796,7 @@ Rect2 Control::get_anchorable_rect() const { return Rect2(Point2(), get_size()); } -void Control::add_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) { +void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) { if (data.icon_override.has(p_name)) { data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); @@ -1898,7 +1814,7 @@ void Control::add_icon_override(const StringName &p_name, const Ref<Texture2D> & notification(NOTIFICATION_THEME_CHANGED); } -void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) { +void Control::add_theme_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) { if (data.shader_override.has(p_name)) { data.shader_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); @@ -1915,7 +1831,7 @@ void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p } notification(NOTIFICATION_THEME_CHANGED); } -void Control::add_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { +void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { if (data.style_override.has(p_name)) { data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); @@ -1933,7 +1849,7 @@ void Control::add_style_override(const StringName &p_name, const Ref<StyleBox> & notification(NOTIFICATION_THEME_CHANGED); } -void Control::add_font_override(const StringName &p_name, const Ref<Font> &p_font) { +void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { if (data.font_override.has(p_name)) { data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); @@ -1950,12 +1866,12 @@ void Control::add_font_override(const StringName &p_name, const Ref<Font> &p_fon } notification(NOTIFICATION_THEME_CHANGED); } -void Control::add_color_override(const StringName &p_name, const Color &p_color) { +void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) { data.color_override[p_name] = p_color; notification(NOTIFICATION_THEME_CHANGED); } -void Control::add_constant_override(const StringName &p_name, int p_constant) { +void Control::add_theme_constant_override(const StringName &p_name, int p_constant) { data.constant_override[p_name] = p_constant; notification(NOTIFICATION_THEME_CHANGED); @@ -2049,7 +1965,7 @@ Control *Control::find_next_valid_focus() const { next_child = const_cast<Control *>(this); while (next_child) { - if (next_child->data.SI || next_child->data.RI) + if (next_child->data.RI) break; next_child = next_child->get_parent_control(); } @@ -2192,53 +2108,29 @@ bool Control::is_toplevel_control() const { return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_toplevel()); } -void Control::show_modal(bool p_exclusive) { - - ERR_FAIL_COND(!is_inside_tree()); - ERR_FAIL_COND(!data.SI); - - if (is_visible_in_tree()) - hide(); - - ERR_FAIL_COND(data.MI != NULL); - show(); - raise(); - data.modal_exclusive = p_exclusive; - data.MI = get_viewport()->_gui_show_modal(this); - data.modal_frame = Engine::get_singleton()->get_frames_drawn(); -} +void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) { -void Control::_modal_set_prev_focus_owner(ObjectID p_prev) { - data.modal_prev_focus_owner = p_prev; -} - -void Control::_modal_stack_remove() { - - ERR_FAIL_COND(!is_inside_tree()); + Control *c = Object::cast_to<Control>(p_at); - if (!data.MI) + if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated return; - List<Control *>::Element *element = data.MI; - data.MI = NULL; - - get_viewport()->_gui_remove_from_modal_stack(element, data.modal_prev_focus_owner); - - data.modal_prev_focus_owner = ObjectID(); -} + Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr; -void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign) { - - Control *c = Object::cast_to<Control>(p_at); - - if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated + if (w && w != p_owner_window && w->theme.is_valid()) // has a theme, this can't be propagated return; for (int i = 0; i < p_at->get_child_count(); i++) { CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i)); if (child) { - _propagate_theme_changed(child, p_owner, p_assign); + _propagate_theme_changed(child, p_owner, p_owner_window, p_assign); + } else { + + Window *window = Object::cast_to<Window>(p_at->get_child(i)); + if (window) { + _propagate_theme_changed(window, p_owner, p_owner_window, p_assign); + } } } @@ -2246,14 +2138,26 @@ void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool if (p_assign) { c->data.theme_owner = p_owner; + c->data.theme_owner_window = p_owner_window; + } + c->notification(Control::NOTIFICATION_THEME_CHANGED); + c->emit_signal(SceneStringNames::get_singleton()->theme_changed); + } + + if (w) { + + if (p_assign) { + w->theme_owner = p_owner; + w->theme_owner_window = p_owner_window; } - c->notification(NOTIFICATION_THEME_CHANGED); + w->notification(Window::NOTIFICATION_THEME_CHANGED); + w->emit_signal(SceneStringNames::get_singleton()->theme_changed); } } void Control::_theme_changed() { - _propagate_theme_changed(this, this, false); + _propagate_theme_changed(this, this, nullptr, false); } void Control::set_theme(const Ref<Theme> &p_theme) { @@ -2269,15 +2173,21 @@ void Control::set_theme(const Ref<Theme> &p_theme) { if (!p_theme.is_null()) { data.theme_owner = this; - _propagate_theme_changed(this, this); + data.theme_owner_window = nullptr; + _propagate_theme_changed(this, this, nullptr); } else { - Control *parent = cast_to<Control>(get_parent()); - if (parent && parent->data.theme_owner) { - _propagate_theme_changed(this, parent->data.theme_owner); - } else { + Control *parent_c = Object::cast_to<Control>(get_parent()); - _propagate_theme_changed(this, NULL); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); + } else { + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); + } else { + Control::_propagate_theme_changed(this, nullptr, nullptr); + } } } @@ -2440,8 +2350,6 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) { Control *c = Object::cast_to<Control>(base); if (c) { - if (c->data.SI) - break; if (c->data.RI) break; } @@ -2511,7 +2419,7 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con Node *child = p_at->get_child(i); Control *childc = Object::cast_to<Control>(child); - if (childc && childc->data.SI) + if (childc && childc->data.RI) continue; //subwindow, ignore _window_find_focus_neighbour(p_dir, p_at->get_child(i), p_points, p_min, r_closest_dist, r_closest); } @@ -2569,6 +2477,12 @@ void Control::minimum_size_changed() { invalidate->data.minimum_size_valid = false; if (invalidate->is_set_as_toplevel()) break; // do not go further up + if (!invalidate->data.parent && get_parent()) { + Window *parent_window = Object::cast_to<Window>(get_parent()); + if (parent_window && parent_window->is_wrapping_controls()) { + parent_window->child_controls_changed(); + } + } invalidate = invalidate->data.parent; } @@ -2599,16 +2513,6 @@ Control::MouseFilter Control::get_mouse_filter() const { return data.mouse_filter; } -void Control::set_pass_on_modal_close_click(bool p_pass_on) { - - data.pass_on_modal_close_click = p_pass_on; -} - -bool Control::pass_on_modal_close_click() const { - - return data.pass_on_modal_close_click; -} - Control *Control::get_focus_owner() const { ERR_FAIL_COND_V(!is_inside_tree(), NULL); @@ -2658,6 +2562,7 @@ float Control::get_rotation_degrees() const { void Control::_override_changed() { notification(NOTIFICATION_THEME_CHANGED); + emit_signal(SceneStringNames::get_singleton()->theme_changed); minimum_size_changed(); // overrides are likely to affect minimum size } @@ -2701,7 +2606,7 @@ Control *Control::get_root_parent_control() const { if (c) { root = c; - if (c->data.RI || c->data.MI || c->is_toplevel_control()) + if (c->data.RI || c->is_toplevel_control()) break; } @@ -2853,7 +2758,6 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position); ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect); ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect); - ClassDB::bind_method(D_METHOD("show_modal", "exclusive"), &Control::show_modal, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode); ClassDB::bind_method(D_METHOD("get_focus_mode"), &Control::get_focus_mode); ClassDB::bind_method(D_METHOD("has_focus"), &Control::has_focus); @@ -2873,31 +2777,31 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme); - ClassDB::bind_method(D_METHOD("add_icon_override", "name", "texture"), &Control::add_icon_override); - ClassDB::bind_method(D_METHOD("add_shader_override", "name", "shader"), &Control::add_shader_override); - ClassDB::bind_method(D_METHOD("add_stylebox_override", "name", "stylebox"), &Control::add_style_override); - ClassDB::bind_method(D_METHOD("add_font_override", "name", "font"), &Control::add_font_override); - ClassDB::bind_method(D_METHOD("add_color_override", "name", "color"), &Control::add_color_override); - ClassDB::bind_method(D_METHOD("add_constant_override", "name", "constant"), &Control::add_constant_override); - - ClassDB::bind_method(D_METHOD("get_icon", "name", "type"), &Control::get_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_stylebox", "name", "type"), &Control::get_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_font", "name", "type"), &Control::get_font, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_color", "name", "type"), &Control::get_color, DEFVAL("")); - ClassDB::bind_method(D_METHOD("get_constant", "name", "type"), &Control::get_constant, DEFVAL("")); - - ClassDB::bind_method(D_METHOD("has_icon_override", "name"), &Control::has_icon_override); - ClassDB::bind_method(D_METHOD("has_shader_override", "name"), &Control::has_shader_override); - ClassDB::bind_method(D_METHOD("has_stylebox_override", "name"), &Control::has_stylebox_override); - ClassDB::bind_method(D_METHOD("has_font_override", "name"), &Control::has_font_override); - ClassDB::bind_method(D_METHOD("has_color_override", "name"), &Control::has_color_override); - ClassDB::bind_method(D_METHOD("has_constant_override", "name"), &Control::has_constant_override); - - ClassDB::bind_method(D_METHOD("has_icon", "name", "type"), &Control::has_icon, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_font", "name", "type"), &Control::has_font, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_color", "name", "type"), &Control::has_color, DEFVAL("")); - ClassDB::bind_method(D_METHOD("has_constant", "name", "type"), &Control::has_constant, DEFVAL("")); + ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Control::add_theme_icon_override); + ClassDB::bind_method(D_METHOD("add_theme_shader_override", "name", "shader"), &Control::add_theme_shader_override); + ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override); + ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Control::add_theme_font_override); + ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Control::add_theme_color_override); + ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Control::add_theme_constant_override); + + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Control::get_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Control::get_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Control::get_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Control::get_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Control::get_theme_constant, DEFVAL("")); + + ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Control::has_theme_icon_override); + ClassDB::bind_method(D_METHOD("has_theme_shader_override", "name"), &Control::has_theme_shader_override); + ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Control::has_theme_stylebox_override); + ClassDB::bind_method(D_METHOD("has_theme_font_override", "name"), &Control::has_theme_font_override); + ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Control::has_theme_color_override); + ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Control::has_theme_constant_override); + + ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Control::has_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Control::has_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Control::has_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Control::has_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Control::has_theme_constant, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control); @@ -3013,7 +2917,6 @@ void Control::_bind_methods() { BIND_CONSTANT(NOTIFICATION_FOCUS_ENTER); BIND_CONSTANT(NOTIFICATION_FOCUS_EXIT); BIND_CONSTANT(NOTIFICATION_THEME_CHANGED); - BIND_CONSTANT(NOTIFICATION_MODAL_CLOSE); BIND_CONSTANT(NOTIFICATION_SCROLL_BEGIN); BIND_CONSTANT(NOTIFICATION_SCROLL_END); @@ -3082,7 +2985,7 @@ void Control::_bind_methods() { ADD_SIGNAL(MethodInfo("focus_exited")); ADD_SIGNAL(MethodInfo("size_flags_changed")); ADD_SIGNAL(MethodInfo("minimum_size_changed")); - ADD_SIGNAL(MethodInfo("modal_closed")); + ADD_SIGNAL(MethodInfo("theme_changed")); BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_point", PropertyInfo(Variant::VECTOR2, "point"))); } @@ -3091,13 +2994,10 @@ Control::Control() { data.parent = NULL; data.mouse_filter = MOUSE_FILTER_STOP; - data.pass_on_modal_close_click = true; - data.SI = NULL; - data.MI = NULL; data.RI = NULL; data.theme_owner = NULL; - data.modal_exclusive = false; + data.theme_owner_window = NULL; data.default_cursor = CURSOR_ARROW; data.h_size_flags = SIZE_FILL; data.v_size_flags = SIZE_FILL; @@ -3106,7 +3006,6 @@ Control::Control() { data.parent_canvas_item = NULL; data.scale = Vector2(1, 1); - data.modal_frame = 0; data.block_minimum_size_adjust = false; data.disable_visibility_clip = false; data.h_grow = GROW_DIRECTION_END; diff --git a/scene/gui/control.h b/scene/gui/control.h index 15a32b8f67..c52e80fa70 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -168,8 +168,6 @@ private: float expand; Point2 custom_minimum_size; - bool pass_on_modal_close_click; - MouseFilter mouse_filter; bool clip_contents; @@ -179,21 +177,16 @@ private: Control *parent; ObjectID drag_owner; - bool modal_exclusive; - uint64_t modal_frame; //frame used to put something as modal Ref<Theme> theme; Control *theme_owner; + Window *theme_owner_window; String tooltip; CursorShape default_cursor; - List<Control *>::Element *MI; //modal item - List<Control *>::Element *SI; List<Control *>::Element *RI; CanvasItem *parent_canvas_item; - ObjectID modal_prev_focus_owner; - NodePath focus_neighbour[4]; NodePath focus_next; NodePath focus_prev; @@ -218,7 +211,6 @@ private: void _set_global_position(const Point2 &p_point); void _set_size(const Size2 &p_size); - void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true); void _theme_changed(); void _change_notify_margins(); @@ -240,10 +232,29 @@ private: Transform2D _get_internal_transform() const; friend class Viewport; - void _modal_stack_remove(); - void _modal_set_prev_focus_owner(ObjectID p_prev); void _update_minimum_size_cache(); + friend class Window; + static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true); + + template <class T> + _FORCE_INLINE_ static bool _find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type); + + _FORCE_INLINE_ static bool _has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type); + + static Ref<Texture2D> get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static Ref<Shader> get_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static Ref<StyleBox> get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static Ref<Font> get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static Color get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static int get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + + static bool has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static bool has_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static bool has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static bool has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static bool has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); + static bool has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName()); protected: virtual void add_child_notify(Node *p_child); @@ -272,7 +283,6 @@ public: NOTIFICATION_FOCUS_ENTER = 43, NOTIFICATION_FOCUS_EXIT = 44, NOTIFICATION_THEME_CHANGED = 45, - NOTIFICATION_MODAL_CLOSE = 46, NOTIFICATION_SCROLL_BEGIN = 47, NOTIFICATION_SCROLL_END = 48, @@ -320,9 +330,6 @@ public: void set_custom_minimum_size(const Size2 &p_custom); Size2 get_custom_minimum_size() const; - bool is_window_modal_on_top() const; - uint64_t get_modal_frame() const; //frame in which this was made modal - Control *get_parent_control() const; /* POSITIONING */ @@ -349,12 +356,14 @@ public: void set_global_position(const Point2 &p_point, bool p_keep_margins = false); Point2 get_position() const; Point2 get_global_position() const; + Point2 get_screen_position() const; void set_size(const Size2 &p_size, bool p_keep_margins = false); Size2 get_size() const; Rect2 get_rect() const; Rect2 get_global_rect() const; + Rect2 get_screen_rect() const; Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server Rect2 get_anchorable_rect() const; @@ -375,8 +384,6 @@ public: void set_scale(const Vector2 &p_scale); Vector2 get_scale() const; - void show_modal(bool p_exclusive = false); - void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; @@ -415,38 +422,35 @@ public: void set_mouse_filter(MouseFilter p_filter); MouseFilter get_mouse_filter() const; - void set_pass_on_modal_close_click(bool p_pass_on); - bool pass_on_modal_close_click() const; - /* SKINNING */ - void add_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon); - void add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader); - void add_style_override(const StringName &p_name, const Ref<StyleBox> &p_style); - void add_font_override(const StringName &p_name, const Ref<Font> &p_font); - void add_color_override(const StringName &p_name, const Color &p_color); - void add_constant_override(const StringName &p_name, int p_constant); - - Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_type = StringName()) const; - Ref<Shader> get_shader(const StringName &p_name, const StringName &p_type = StringName()) const; - Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; - Ref<Font> get_font(const StringName &p_name, const StringName &p_type = StringName()) const; - Color get_color(const StringName &p_name, const StringName &p_type = StringName()) const; - int get_constant(const StringName &p_name, const StringName &p_type = StringName()) const; - - bool has_icon_override(const StringName &p_name) const; - bool has_shader_override(const StringName &p_name) const; - bool has_stylebox_override(const StringName &p_name) const; - bool has_font_override(const StringName &p_name) const; - bool has_color_override(const StringName &p_name) const; - bool has_constant_override(const StringName &p_name) const; - - bool has_icon(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_shader(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_font(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_color(const StringName &p_name, const StringName &p_type = StringName()) const; - bool has_constant(const StringName &p_name, const StringName &p_type = StringName()) const; + void add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon); + void add_theme_shader_override(const StringName &p_name, const Ref<Shader> &p_shader); + void add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style); + void add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font); + void add_theme_color_override(const StringName &p_name, const Color &p_color); + void add_theme_constant_override(const StringName &p_name, int p_constant); + + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<Shader> get_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const; + Color get_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const; + int get_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const; + + bool has_theme_icon_override(const StringName &p_name) const; + bool has_theme_shader_override(const StringName &p_name) const; + bool has_theme_stylebox_override(const StringName &p_name) const; + bool has_theme_font_override(const StringName &p_name) const; + bool has_theme_color_override(const StringName &p_name) const; + bool has_theme_constant_override(const StringName &p_name) const; + + bool has_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const; /* TOOLTIP */ diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 6cadd0a63e..2e87a92969 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "dialogs.h" + +#include "core/os/keyboard.h" #include "core/print_string.h" #include "core/translation.h" #include "line_edit.h" @@ -36,362 +38,61 @@ #ifdef TOOLS_ENABLED #include "editor/editor_node.h" #include "editor/editor_scale.h" -#include "scene/main/viewport.h" // Only used to check for more modals when dimming the editor. +#include "scene/main/window.h" // Only used to check for more modals when dimming the editor. #endif -// WindowDialog - -void WindowDialog::_post_popup() { - - drag_type = DRAG_NONE; // just in case -} - -void WindowDialog::_fix_size() { - - // Perhaps this should be called when the viewport resizes as well or windows go out of bounds... - - // Ensure the whole window is visible. - Point2i pos = get_global_position(); - Size2i size = get_size(); - Size2i viewport_size = get_viewport_rect().size; - - // Windows require additional padding to keep the window chrome visible. - Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog"); - float top = 0; - float left = 0; - float bottom = 0; - float right = 0; - // Check validity, because the theme could contain a different type of StyleBox. - if (panel->get_class() == "StyleBoxTexture") { - Ref<StyleBoxTexture> panel_texture = Object::cast_to<StyleBoxTexture>(*panel); - top = panel_texture->get_expand_margin_size(MARGIN_TOP); - left = panel_texture->get_expand_margin_size(MARGIN_LEFT); - bottom = panel_texture->get_expand_margin_size(MARGIN_BOTTOM); - right = panel_texture->get_expand_margin_size(MARGIN_RIGHT); - } else if (panel->get_class() == "StyleBoxFlat") { - Ref<StyleBoxFlat> panel_flat = Object::cast_to<StyleBoxFlat>(*panel); - top = panel_flat->get_expand_margin_size(MARGIN_TOP); - left = panel_flat->get_expand_margin_size(MARGIN_LEFT); - bottom = panel_flat->get_expand_margin_size(MARGIN_BOTTOM); - right = panel_flat->get_expand_margin_size(MARGIN_RIGHT); - } - - pos.x = MAX(left, MIN(pos.x, viewport_size.x - size.x - right)); - pos.y = MAX(top, MIN(pos.y, viewport_size.y - size.y - bottom)); - set_global_position(pos); +// AcceptDialog - if (resizable) { - size.x = MIN(size.x, viewport_size.x - left - right); - size.y = MIN(size.y, viewport_size.y - top - bottom); - set_size(size); +void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> key = p_event; + if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) { + _cancel_pressed(); } } -bool WindowDialog::has_point(const Point2 &p_point) const { - - Rect2 r(Point2(), get_size()); - - // Enlarge upwards for title bar. - int title_height = get_constant("title_height", "WindowDialog"); - r.position.y -= title_height; - r.size.y += title_height; - - // Inflate by the resizable border thickness. - if (resizable) { - int scaleborder_size = get_constant("scaleborder_size", "WindowDialog"); - r.position.x -= scaleborder_size; - r.size.width += scaleborder_size * 2; - r.position.y -= scaleborder_size; - r.size.height += scaleborder_size * 2; - } - - return r.has_point(p_point); +void AcceptDialog::_parent_focused() { + _cancel_pressed(); } -void WindowDialog::_gui_input(const Ref<InputEvent> &p_event) { - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { - - if (mb->is_pressed()) { - // Begin a possible dragging operation. - drag_type = _drag_hit_test(Point2(mb->get_position().x, mb->get_position().y)); - if (drag_type != DRAG_NONE) - drag_offset = get_global_mouse_position() - get_position(); - drag_offset_far = get_position() + get_size() - get_global_mouse_position(); - } else if (drag_type != DRAG_NONE && !mb->is_pressed()) { - // End a dragging operation. - drag_type = DRAG_NONE; - } - } +void AcceptDialog::_notification(int p_what) { - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (drag_type == DRAG_NONE) { - // Update the cursor while moving along the borders. - CursorShape cursor = CURSOR_ARROW; - if (resizable) { - int preview_drag_type = _drag_hit_test(Point2(mm->get_position().x, mm->get_position().y)); - switch (preview_drag_type) { - case DRAG_RESIZE_TOP: - case DRAG_RESIZE_BOTTOM: - cursor = CURSOR_VSIZE; - break; - case DRAG_RESIZE_LEFT: - case DRAG_RESIZE_RIGHT: - cursor = CURSOR_HSIZE; - break; - case DRAG_RESIZE_TOP + DRAG_RESIZE_LEFT: - case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_RIGHT: - cursor = CURSOR_FDIAGSIZE; - break; - case DRAG_RESIZE_TOP + DRAG_RESIZE_RIGHT: - case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_LEFT: - cursor = CURSOR_BDIAGSIZE; - break; + switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (is_visible()) { + + get_ok()->grab_focus(); + _update_child_rects(); + parent_visible = get_parent_visible_window(); + if (parent_visible) { + parent_visible->connect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); } - } - if (get_cursor_shape() != cursor) - set_default_cursor_shape(cursor); - } else { - // Update while in a dragging operation. - Point2 global_pos = get_global_mouse_position(); - global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible. - - Rect2 rect = get_rect(); - Size2 min_size = get_combined_minimum_size(); - - if (drag_type == DRAG_MOVE) { - rect.position = global_pos - drag_offset; } else { - if (drag_type & DRAG_RESIZE_TOP) { - int bottom = rect.position.y + rect.size.height; - int max_y = bottom - min_size.height; - rect.position.y = MIN(global_pos.y - drag_offset.y, max_y); - rect.size.height = bottom - rect.position.y; - } else if (drag_type & DRAG_RESIZE_BOTTOM) { - rect.size.height = global_pos.y - rect.position.y + drag_offset_far.y; - } - if (drag_type & DRAG_RESIZE_LEFT) { - int right = rect.position.x + rect.size.width; - int max_x = right - min_size.width; - rect.position.x = MIN(global_pos.x - drag_offset.x, max_x); - rect.size.width = right - rect.position.x; - } else if (drag_type & DRAG_RESIZE_RIGHT) { - rect.size.width = global_pos.x - rect.position.x + drag_offset_far.x; + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); + parent_visible = nullptr; } } - set_size(rect.size); - set_position(rect.position); - } - } -} - -void WindowDialog::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_DRAW: { - RID canvas = get_canvas_item(); - - // Draw the background. - Ref<StyleBox> panel = get_stylebox("panel"); - Size2 size = get_size(); - panel->draw(canvas, Rect2(0, 0, size.x, size.y)); - - // Draw the title bar text. - Ref<Font> title_font = get_font("title_font", "WindowDialog"); - Color title_color = get_color("title_color", "WindowDialog"); - int title_height = get_constant("title_height", "WindowDialog"); - int font_height = title_font->get_height() - title_font->get_descent() * 2; - int x = (size.x - title_font->get_string_size(xl_title).x) / 2; - int y = (-title_height + font_height) / 2; - title_font->draw(canvas, Point2(x, y), xl_title, title_color, size.x - panel->get_minimum_size().x); } break; - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { - close_button->set_normal_texture(get_icon("close", "WindowDialog")); - close_button->set_pressed_texture(get_icon("close", "WindowDialog")); - close_button->set_hover_texture(get_icon("close_highlight", "WindowDialog")); - close_button->set_anchor(MARGIN_LEFT, ANCHOR_END); - close_button->set_begin(Point2(-get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog"))); - } break; - - case NOTIFICATION_TRANSLATION_CHANGED: { - String new_title = tr(title); - if (new_title != xl_title) { - xl_title = new_title; - minimum_size_changed(); - update(); - } + case NOTIFICATION_THEME_CHANGED: { + bg->add_theme_style_override("panel", bg->get_theme_stylebox("panel", "AcceptDialog")); } break; - case NOTIFICATION_MOUSE_EXIT: { - // Reset the mouse cursor when leaving the resizable window border. - if (resizable && !drag_type) { - if (get_default_cursor_shape() != CURSOR_ARROW) - set_default_cursor_shape(CURSOR_ARROW); + case NOTIFICATION_EXIT_TREE: { + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); + parent_visible = nullptr; } } break; - -#ifdef TOOLS_ENABLED - case NOTIFICATION_POST_POPUP: { - if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton()) { - was_editor_dimmed = EditorNode::get_singleton()->is_editor_dimmed(); - EditorNode::get_singleton()->dim_editor(true); - } - } break; - - case NOTIFICATION_POPUP_HIDE: { - if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton() && !was_editor_dimmed) { - EditorNode::get_singleton()->dim_editor(false); - set_pass_on_modal_close_click(false); + case NOTIFICATION_READY: + case NOTIFICATION_WM_SIZE_CHANGED: { + if (is_visible()) { + _update_child_rects(); } } break; -#endif - } -} - -void WindowDialog::_closed() { - - _close_pressed(); - hide(); -} - -int WindowDialog::_drag_hit_test(const Point2 &pos) const { - int drag_type = DRAG_NONE; - - if (resizable) { - int title_height = get_constant("title_height", "WindowDialog"); - int scaleborder_size = get_constant("scaleborder_size", "WindowDialog"); - - Rect2 rect = get_rect(); - - if (pos.y < (-title_height + scaleborder_size)) - drag_type = DRAG_RESIZE_TOP; - else if (pos.y >= (rect.size.height - scaleborder_size)) - drag_type = DRAG_RESIZE_BOTTOM; - if (pos.x < scaleborder_size) - drag_type |= DRAG_RESIZE_LEFT; - else if (pos.x >= (rect.size.width - scaleborder_size)) - drag_type |= DRAG_RESIZE_RIGHT; - } - - if (drag_type == DRAG_NONE && pos.y < 0) - drag_type = DRAG_MOVE; - - return drag_type; -} - -void WindowDialog::set_title(const String &p_title) { - - if (title != p_title) { - title = p_title; - xl_title = tr(p_title); - minimum_size_changed(); - update(); - } -} -String WindowDialog::get_title() const { - - return title; -} - -void WindowDialog::set_resizable(bool p_resizable) { - resizable = p_resizable; -} -bool WindowDialog::get_resizable() const { - return resizable; -} - -Size2 WindowDialog::get_minimum_size() const { - - Ref<Font> font = get_font("title_font", "WindowDialog"); - - const int button_width = close_button->get_combined_minimum_size().x; - const int title_width = font->get_string_size(xl_title).x; - const int padding = button_width / 2; - const int button_area = button_width + padding; - - // As the title gets centered, title_width + close_button_width is not enough. - // We want a width w, such that w / 2 - title_width / 2 >= button_area, i.e. - // w >= 2 * button_area + title_width - - return Size2(2 * button_area + title_width, 1); -} - -TextureButton *WindowDialog::get_close_button() { - - return close_button; -} - -void WindowDialog::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_gui_input"), &WindowDialog::_gui_input); - ClassDB::bind_method(D_METHOD("set_title", "title"), &WindowDialog::set_title); - ClassDB::bind_method(D_METHOD("get_title"), &WindowDialog::get_title); - ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &WindowDialog::set_resizable); - ClassDB::bind_method(D_METHOD("get_resizable"), &WindowDialog::get_resizable); - ClassDB::bind_method(D_METHOD("get_close_button"), &WindowDialog::get_close_button); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "window_title", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_title", "get_title"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_resizable", "get_resizable"); -} - -WindowDialog::WindowDialog() { - - drag_type = DRAG_NONE; - resizable = false; - close_button = memnew(TextureButton); - add_child(close_button); - close_button->connect("pressed", callable_mp(this, &WindowDialog::_closed)); - -#ifdef TOOLS_ENABLED - was_editor_dimmed = false; -#endif -} - -WindowDialog::~WindowDialog() { -} - -// PopupDialog - -void PopupDialog::_notification(int p_what) { - - if (p_what == NOTIFICATION_DRAW) { - RID ci = get_canvas_item(); - get_stylebox("panel")->draw(ci, Rect2(Point2(), get_size())); - } -} - -PopupDialog::PopupDialog() { -} - -PopupDialog::~PopupDialog() { -} - -// AcceptDialog - -void AcceptDialog::_post_popup() { - - WindowDialog::_post_popup(); - get_ok()->grab_focus(); -} - -void AcceptDialog::_notification(int p_what) { - - switch (p_what) { - case NOTIFICATION_MODAL_CLOSE: { - cancel_pressed(); - } break; - - case NOTIFICATION_READY: - case NOTIFICATION_RESIZED: { - _update_child_rects(); + case NOTIFICATION_WM_CLOSE_REQUEST: { + _cancel_pressed(); } break; } } @@ -404,20 +105,28 @@ void AcceptDialog::_text_entered(const String &p_text) { void AcceptDialog::_ok_pressed() { if (hide_on_ok) - hide(); + set_visible(false); ok_pressed(); emit_signal("confirmed"); } -void AcceptDialog::_close_pressed() { +void AcceptDialog::_cancel_pressed() { + + Window *parent_window = parent_visible; + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused)); + parent_visible = nullptr; + } + + call_deferred("hide"); + + emit_signal("cancelled"); cancel_pressed(); -} -// FIXME: This is redundant with _closed_pressed, but there's a slight behavior -// change (WindowDialog's _closed() also calls hide()) which should be assessed. -void AcceptDialog::_on_close_pressed() { - _closed(); // From WindowDialog. + if (parent_window) { + //parent_window->grab_focus(); + } } String AcceptDialog::get_text() const { @@ -427,8 +136,10 @@ String AcceptDialog::get_text() const { void AcceptDialog::set_text(String p_text) { label->set_text(p_text); - minimum_size_changed(); - _update_child_rects(); + child_controls_changed(); + if (is_visible()) { + _update_child_rects(); + } } void AcceptDialog::set_hide_on_ok(bool p_hide) { @@ -463,7 +174,7 @@ void AcceptDialog::_update_child_rects() { if (label->get_text().empty()) { label_size.height = 0; } - int margin = get_constant("margin", "Dialogs"); + int margin = hbc->get_theme_constant("margin", "Dialogs"); Size2 size = get_size(); Size2 hminsize = hbc->get_combined_minimum_size(); @@ -475,7 +186,7 @@ void AcceptDialog::_update_child_rects() { if (!c) continue; - if (c == hbc || c == label || c == get_close_button() || c->is_set_as_toplevel()) + if (c == hbc || c == label || c == bg || c->is_set_as_toplevel()) continue; c->set_position(cpos); @@ -487,11 +198,14 @@ void AcceptDialog::_update_child_rects() { hbc->set_position(cpos); hbc->set_size(csize); + + bg->set_position(Point2()); + bg->set_size(size); } -Size2 AcceptDialog::get_minimum_size() const { +Size2 AcceptDialog::_get_contents_minimum_size() const { - int margin = get_constant("margin", "Dialogs"); + int margin = hbc->get_theme_constant("margin", "Dialogs"); Size2 minsize = label->get_combined_minimum_size(); for (int i = 0; i < get_child_count(); i++) { @@ -499,7 +213,7 @@ Size2 AcceptDialog::get_minimum_size() const { if (!c) continue; - if (c == hbc || c == label || c == const_cast<AcceptDialog *>(this)->get_close_button() || c->is_set_as_toplevel()) + if (c == hbc || c == label || c->is_set_as_toplevel()) continue; Size2 cminsize = c->get_combined_minimum_size(); @@ -513,7 +227,7 @@ Size2 AcceptDialog::get_minimum_size() const { minsize.x += margin * 2; minsize.y += margin * 3; //one as separation between hbc and child - Size2 wmsize = WindowDialog::get_minimum_size(); + Size2 wmsize = get_min_size(); minsize.x = MAX(wmsize.x, minsize.x); return minsize; } @@ -551,7 +265,7 @@ Button *AcceptDialog::add_cancel(const String &p_cancel) { if (p_cancel == "") c = RTR("Cancel"); Button *b = swap_ok_cancel ? add_button(c, true) : add_button(c); - b->connect("pressed", callable_mp(this, &AcceptDialog::_on_close_pressed)); + b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed)); return b; } @@ -570,6 +284,7 @@ void AcceptDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("has_autowrap"), &AcceptDialog::has_autowrap); ADD_SIGNAL(MethodInfo("confirmed")); + ADD_SIGNAL(MethodInfo("cancelled")); ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action"))); ADD_GROUP("Dialog", "dialog"); @@ -586,12 +301,23 @@ void AcceptDialog::set_swap_ok_cancel(bool p_swap) { AcceptDialog::AcceptDialog() { - int margin = get_constant("margin", "Dialogs"); - int button_margin = get_constant("button_margin", "Dialogs"); + parent_visible = nullptr; + + set_wrap_controls(true); + set_visible(false); + set_transient(true); + + bg = memnew(Panel); + add_child(bg); + + hbc = memnew(HBoxContainer); + + int margin = hbc->get_theme_constant("margin", "Dialogs"); + int button_margin = hbc->get_theme_constant("button_margin", "Dialogs"); label = memnew(Label); - label->set_anchor(MARGIN_RIGHT, ANCHOR_END); - label->set_anchor(MARGIN_BOTTOM, ANCHOR_END); + label->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END); + label->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END); label->set_begin(Point2(margin, margin)); label->set_end(Point2(-margin, -button_margin - 10)); add_child(label); @@ -606,10 +332,11 @@ AcceptDialog::AcceptDialog() { hbc->add_spacer(); ok->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed)); - set_as_toplevel(true); hide_on_ok = true; set_title(RTR("Alert!")); + + connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window)); } AcceptDialog::~AcceptDialog() { @@ -631,7 +358,7 @@ ConfirmationDialog::ConfirmationDialog() { set_title(RTR("Please Confirm...")); #ifdef TOOLS_ENABLED - set_custom_minimum_size(Size2(200, 70) * EDSCALE); + set_min_size(Size2(200, 70) * EDSCALE); #endif cancel = add_cancel(); } diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index c474f7849d..b68b4297d7 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -37,91 +37,32 @@ #include "scene/gui/panel.h" #include "scene/gui/popup.h" #include "scene/gui/texture_button.h" - -class WindowDialog : public Popup { - - GDCLASS(WindowDialog, Popup); - - enum DRAG_TYPE { - DRAG_NONE = 0, - DRAG_MOVE = 1, - DRAG_RESIZE_TOP = 1 << 1, - DRAG_RESIZE_RIGHT = 1 << 2, - DRAG_RESIZE_BOTTOM = 1 << 3, - DRAG_RESIZE_LEFT = 1 << 4 - }; - - TextureButton *close_button; - String title; - String xl_title; - int drag_type; - Point2 drag_offset; - Point2 drag_offset_far; - bool resizable; - -#ifdef TOOLS_ENABLED - bool was_editor_dimmed; -#endif - - void _gui_input(const Ref<InputEvent> &p_event); - int _drag_hit_test(const Point2 &pos) const; - -protected: - virtual void _post_popup(); - virtual void _fix_size(); - virtual void _close_pressed() {} - virtual bool has_point(const Point2 &p_point) const; - void _notification(int p_what); - static void _bind_methods(); - - // Not private since used by derived classes signal. - void _closed(); - -public: - TextureButton *get_close_button(); - - void set_title(const String &p_title); - String get_title() const; - void set_resizable(bool p_resizable); - bool get_resizable() const; - - Size2 get_minimum_size() const; - - WindowDialog(); - ~WindowDialog(); -}; - -class PopupDialog : public Popup { - - GDCLASS(PopupDialog, Popup); - -protected: - void _notification(int p_what); - -public: - PopupDialog(); - ~PopupDialog(); -}; +#include "scene/main/window.h" class LineEdit; -class AcceptDialog : public WindowDialog { +class AcceptDialog : public Window { - GDCLASS(AcceptDialog, WindowDialog); + GDCLASS(AcceptDialog, Window); + Window *parent_visible; + Panel *bg; HBoxContainer *hbc; Label *label; Button *ok; bool hide_on_ok; void _custom_action(const String &p_action); - void _close_pressed(); void _update_child_rects(); static bool swap_ok_cancel; + void _input_from_window(const Ref<InputEvent> &p_event); + void _parent_focused(); + protected: - virtual void _post_popup(); + virtual Size2 _get_contents_minimum_size() const; + void _notification(int p_what); static void _bind_methods(); virtual void ok_pressed() {} @@ -131,11 +72,9 @@ protected: // Not private since used by derived classes signal. void _text_entered(const String &p_text); void _ok_pressed(); - void _on_close_pressed(); + void _cancel_pressed(); public: - Size2 get_minimum_size() const; - Label *get_label() { return label; } static void set_swap_ok_cancel(bool p_swap); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 3be77ff4b3..a4f0338f00 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -44,42 +44,46 @@ VBoxContainer *FileDialog::get_vbox() { return vbox; } -void FileDialog::_notification(int p_what) { +void FileDialog::_theme_changed() { - if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + Color font_color = vbc->get_theme_color("font_color", "ToolButton"); + Color font_color_hover = vbc->get_theme_color("font_color_hover", "ToolButton"); + Color font_color_pressed = vbc->get_theme_color("font_color_pressed", "ToolButton"); - if (p_what == NOTIFICATION_ENTER_TREE) { - dir_up->set_icon(get_icon("parent_folder")); - refresh->set_icon(get_icon("reload")); - show_hidden->set_icon(get_icon("toggle_hidden")); - } + dir_up->add_theme_color_override("icon_color_normal", font_color); + dir_up->add_theme_color_override("icon_color_hover", font_color_hover); + dir_up->add_theme_color_override("icon_color_pressed", font_color_pressed); - Color font_color = get_color("font_color", "ToolButton"); - Color font_color_hover = get_color("font_color_hover", "ToolButton"); - Color font_color_pressed = get_color("font_color_pressed", "ToolButton"); + refresh->add_theme_color_override("icon_color_normal", font_color); + refresh->add_theme_color_override("icon_color_hover", font_color_hover); + refresh->add_theme_color_override("icon_color_pressed", font_color_pressed); - dir_up->add_color_override("icon_color_normal", font_color); - dir_up->add_color_override("icon_color_hover", font_color_hover); - dir_up->add_color_override("icon_color_pressed", font_color_pressed); + show_hidden->add_theme_color_override("icon_color_normal", font_color); + show_hidden->add_theme_color_override("icon_color_hover", font_color_hover); + show_hidden->add_theme_color_override("icon_color_pressed", font_color_pressed); +} - refresh->add_color_override("icon_color_normal", font_color); - refresh->add_color_override("icon_color_hover", font_color_hover); - refresh->add_color_override("icon_color_pressed", font_color_pressed); +void FileDialog::_notification(int p_what) { - show_hidden->add_color_override("icon_color_normal", font_color); - show_hidden->add_color_override("icon_color_hover", font_color_hover); - show_hidden->add_color_override("icon_color_pressed", font_color_pressed); + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (!is_visible()) { - } else if (p_what == NOTIFICATION_POPUP_HIDE) { + set_process_unhandled_input(false); + } + } + if (p_what == NOTIFICATION_ENTER_TREE) { - set_process_unhandled_input(false); + dir_up->set_icon(vbc->get_theme_icon("parent_folder")); + refresh->set_icon(vbc->get_theme_icon("reload")); + show_hidden->set_icon(vbc->get_theme_icon("toggle_hidden")); + _theme_changed(); } } void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; - if (k.is_valid() && is_window_modal_on_top()) { + if (k.is_valid() && has_focus()) { if (k->is_pressed()) { @@ -110,7 +114,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { } if (handled) - accept_event(); + set_input_as_handled(); } } } @@ -171,7 +175,7 @@ void FileDialog::_post_popup() { update_file_list(); invalidated = false; } - if (mode == MODE_SAVE_FILE) + if (mode == FILE_MODE_SAVE_FILE) file->grab_focus(); else tree->grab_focus(); @@ -179,7 +183,7 @@ void FileDialog::_post_popup() { set_process_unhandled_input(true); // For open dir mode, deselect all items on file dialog open. - if (mode == MODE_OPEN_DIR) { + if (mode == FILE_MODE_OPEN_DIR) { deselect_items(); file_box->set_visible(false); } else { @@ -189,7 +193,7 @@ void FileDialog::_post_popup() { void FileDialog::_action_pressed() { - if (mode == MODE_OPEN_FILES) { + if (mode == FILE_MODE_OPEN_FILES) { TreeItem *ti = tree->get_next_selected(NULL); String fbase = dir_access->get_current_dir(); @@ -211,10 +215,10 @@ void FileDialog::_action_pressed() { String f = dir_access->get_current_dir().plus_file(file->get_text()); - if ((mode == MODE_OPEN_ANY || mode == MODE_OPEN_FILE) && dir_access->file_exists(f)) { + if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) { emit_signal("file_selected", f); hide(); - } else if (mode == MODE_OPEN_ANY || mode == MODE_OPEN_DIR) { + } else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) { String path = dir_access->get_current_dir(); @@ -231,7 +235,7 @@ void FileDialog::_action_pressed() { hide(); } - if (mode == MODE_SAVE_FILE) { + if (mode == FILE_MODE_SAVE_FILE) { bool valid = false; @@ -283,7 +287,7 @@ void FileDialog::_action_pressed() { if (!valid) { - exterr->popup_centered_minsize(Size2(250, 80)); + exterr->popup_centered(Size2(250, 80)); return; } @@ -307,7 +311,7 @@ void FileDialog::_cancel_pressed() { bool FileDialog::_is_open_should_be_disabled() { - if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE) + if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_SAVE_FILE) return false; TreeItem *ti = tree->get_next_selected(tree->get_root()); @@ -319,13 +323,13 @@ bool FileDialog::_is_open_should_be_disabled() { } // We have something that we can't select? if (!ti) - return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. + return mode != FILE_MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder. Dictionary d = ti->get_metadata(0); // Opening a file, but selected a folder? Forbidden. - return ((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden. - (mode == MODE_OPEN_DIR && !d["dir"]); + return ((mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden. + (mode == FILE_MODE_OPEN_DIR && !d["dir"]); } void FileDialog::_go_up() { @@ -346,15 +350,15 @@ void FileDialog::deselect_items() { switch (mode) { - case MODE_OPEN_FILE: - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_text(RTR("Select Current Folder")); break; - case MODE_OPEN_ANY: - case MODE_SAVE_FILE: + case FILE_MODE_OPEN_ANY: + case FILE_MODE_SAVE_FILE: // FIXME: Implement, or refactor to avoid duplication with set_mode break; } @@ -375,7 +379,7 @@ void FileDialog::_tree_selected() { if (!d["dir"]) { file->set_text(d["name"]); - } else if (mode == MODE_OPEN_DIR) { + } else if (mode == FILE_MODE_OPEN_DIR) { get_ok()->set_text(RTR("Select This Folder")); } @@ -393,7 +397,7 @@ void FileDialog::_tree_item_activated() { if (d["dir"]) { dir_access->change_dir(d["name"]); - if (mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES || mode == MODE_OPEN_DIR || mode == MODE_OPEN_ANY) + if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY) file->set_text(""); call_deferred("_update_file_list"); call_deferred("_update_dir"); @@ -425,8 +429,8 @@ void FileDialog::update_file_list() { dir_access->list_dir_begin(); TreeItem *root = tree->create_item(); - Ref<Texture2D> folder = get_icon("folder"); - const Color folder_color = get_color("folder_icon_modulate"); + Ref<Texture2D> folder = vbc->get_theme_icon("folder"); + const Color folder_color = vbc->get_theme_color("folder_icon_modulate"); List<String> files; List<String> dirs; @@ -523,8 +527,8 @@ void FileDialog::update_file_list() { ti->set_icon(0, icon); } - if (mode == MODE_OPEN_DIR) { - ti->set_custom_color(0, get_color("files_disabled")); + if (mode == FILE_MODE_OPEN_DIR) { + ti->set_custom_color(0, vbc->get_theme_color("files_disabled")); ti->set_selectable(0, false); } Dictionary d; @@ -661,38 +665,38 @@ bool FileDialog::is_mode_overriding_title() const { return mode_overrides_title; } -void FileDialog::set_mode(Mode p_mode) { +void FileDialog::set_file_mode(FileMode p_mode) { ERR_FAIL_INDEX((int)p_mode, 5); mode = p_mode; switch (mode) { - case MODE_OPEN_FILE: + case FILE_MODE_OPEN_FILE: get_ok()->set_text(RTR("Open")); if (mode_overrides_title) set_title(RTR("Open a File")); makedir->hide(); break; - case MODE_OPEN_FILES: + case FILE_MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); if (mode_overrides_title) set_title(RTR("Open File(s)")); makedir->hide(); break; - case MODE_OPEN_DIR: + case FILE_MODE_OPEN_DIR: get_ok()->set_text(RTR("Select Current Folder")); if (mode_overrides_title) set_title(RTR("Open a Directory")); makedir->show(); break; - case MODE_OPEN_ANY: + case FILE_MODE_OPEN_ANY: get_ok()->set_text(RTR("Open")); if (mode_overrides_title) set_title(RTR("Open a File or Directory")); makedir->show(); break; - case MODE_SAVE_FILE: + case FILE_MODE_SAVE_FILE: get_ok()->set_text(RTR("Save")); if (mode_overrides_title) set_title(RTR("Save a File")); @@ -700,14 +704,14 @@ void FileDialog::set_mode(Mode p_mode) { break; } - if (mode == MODE_OPEN_FILES) { + if (mode == FILE_MODE_OPEN_FILES) { tree->set_select_mode(Tree::SELECT_MULTI); } else { tree->set_select_mode(Tree::SELECT_SINGLE); } } -FileDialog::Mode FileDialog::get_mode() const { +FileDialog::FileMode FileDialog::get_file_mode() const { return mode; } @@ -741,7 +745,7 @@ void FileDialog::set_access(Access p_access) { void FileDialog::invalidate() { - if (is_visible_in_tree()) { + if (is_visible()) { update_file_list(); invalidated = false; } else { @@ -763,14 +767,14 @@ void FileDialog::_make_dir_confirm() { update_filters(); update_dir(); } else { - mkdirerr->popup_centered_minsize(Size2(250, 50)); + mkdirerr->popup_centered(Size2(250, 50)); } makedirname->set_text(""); // reset label } void FileDialog::_make_dir() { - makedialog->popup_centered_minsize(Size2(250, 80)); + makedialog->popup_centered(Size2(250, 80)); makedirname->grab_focus(); } @@ -826,8 +830,8 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path); ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title); ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title); - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode); - ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode); + ClassDB::bind_method(D_METHOD("set_file_mode", "mode"), &FileDialog::set_file_mode); + ClassDB::bind_method(D_METHOD("get_file_mode"), &FileDialog::get_file_mode); ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox); ClassDB::bind_method(D_METHOD("get_line_edit"), &FileDialog::get_line_edit); ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access); @@ -842,7 +846,7 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_mode", "get_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_file_mode", "get_file_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files"); @@ -854,11 +858,11 @@ void FileDialog::_bind_methods() { ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"))); ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir"))); - BIND_ENUM_CONSTANT(MODE_OPEN_FILE); - BIND_ENUM_CONSTANT(MODE_OPEN_FILES); - BIND_ENUM_CONSTANT(MODE_OPEN_DIR); - BIND_ENUM_CONSTANT(MODE_OPEN_ANY); - BIND_ENUM_CONSTANT(MODE_SAVE_FILE); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILE); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILES); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_DIR); + BIND_ENUM_CONSTANT(FILE_MODE_OPEN_ANY); + BIND_ENUM_CONSTANT(FILE_MODE_SAVE_FILE); BIND_ENUM_CONSTANT(ACCESS_RESOURCES); BIND_ENUM_CONSTANT(ACCESS_USERDATA); @@ -884,10 +888,11 @@ FileDialog::FileDialog() { mode_overrides_title = true; - VBoxContainer *vbc = memnew(VBoxContainer); + vbc = memnew(VBoxContainer); add_child(vbc); + vbc->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed)); - mode = MODE_SAVE_FILE; + mode = FILE_MODE_SAVE_FILE; set_title(RTR("Save a File")); HBoxContainer *hbc = memnew(HBoxContainer); @@ -907,7 +912,7 @@ FileDialog::FileDialog() { dir = memnew(LineEdit); hbc->add_child(dir); - dir->set_h_size_flags(SIZE_EXPAND_FILL); + dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); refresh = memnew(ToolButton); refresh->set_tooltip(RTR("Refresh files.")); @@ -938,11 +943,11 @@ FileDialog::FileDialog() { file_box->add_child(memnew(Label(RTR("File:")))); file = memnew(LineEdit); file->set_stretch_ratio(4); - file->set_h_size_flags(SIZE_EXPAND_FILL); + file->set_h_size_flags(Control::SIZE_EXPAND_FILL); file_box->add_child(file); filter = memnew(OptionButton); filter->set_stretch_ratio(3); - filter->set_h_size_flags(SIZE_EXPAND_FILL); + filter->set_h_size_flags(Control::SIZE_EXPAND_FILL); filter->set_clip_text(true); // too many extensions overflows it file_box->add_child(filter); vbc->add_child(file_box); @@ -961,7 +966,7 @@ FileDialog::FileDialog() { filter->connect("item_selected", callable_mp(this, &FileDialog::_filter_selected)); confirm_save = memnew(ConfirmationDialog); - confirm_save->set_as_toplevel(true); + // confirm_save->set_as_toplevel(true); add_child(confirm_save); confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed)); @@ -1024,7 +1029,7 @@ LineEditFileChooser::LineEditFileChooser() { line_edit = memnew(LineEdit); add_child(line_edit); - line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); button = memnew(Button); button->set_text(" .. "); add_child(button); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index a7dc101d12..295ae023d1 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -50,12 +50,12 @@ public: ACCESS_FILESYSTEM }; - enum Mode { - MODE_OPEN_FILE, - MODE_OPEN_FILES, - MODE_OPEN_DIR, - MODE_OPEN_ANY, - MODE_SAVE_FILE + enum FileMode { + FILE_MODE_OPEN_FILE, + FILE_MODE_OPEN_FILES, + FILE_MODE_OPEN_DIR, + FILE_MODE_OPEN_ANY, + FILE_MODE_SAVE_FILE }; typedef Ref<Texture2D> (*GetIconFunc)(const String &); @@ -70,11 +70,12 @@ private: ConfirmationDialog *makedialog; LineEdit *makedirname; + VBoxContainer *vbc; Button *makedir; Access access; //Button *action; VBoxContainer *vbox; - Mode mode; + FileMode mode; LineEdit *dir; HBoxContainer *drives_container; HBoxContainer *shortcuts_container; @@ -131,6 +132,8 @@ private: virtual void _post_popup(); protected: + void _theme_changed(); + void _notification(int p_what); static void _bind_methods(); //bind helpers @@ -153,8 +156,8 @@ public: void set_mode_overrides_title(bool p_override); bool is_mode_overriding_title() const; - void set_mode(Mode p_mode); - Mode get_mode() const; + void set_file_mode(FileMode p_mode); + FileMode get_file_mode() const; VBoxContainer *get_vbox(); LineEdit *get_line_edit() { return file; } @@ -196,7 +199,7 @@ public: LineEditFileChooser(); }; -VARIANT_ENUM_CAST(FileDialog::Mode); +VARIANT_ENUM_CAST(FileDialog::FileMode); VARIANT_ENUM_CAST(FileDialog::Access); #endif diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 6345bfe562..88107f754c 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -76,15 +76,15 @@ void GradientEdit::_show_color_picker() { if (grabbed == -1) return; picker->set_pick_color(points[grabbed].color); - Size2 minsize = popup->get_combined_minimum_size(); + Size2 minsize = popup->get_contents_minimum_size(); bool show_above = false; if (get_global_position().y + get_size().y + minsize.y > get_viewport_rect().size.y) { show_above = true; } if (show_above) { - popup->set_position(get_global_position() - Vector2(0, minsize.y)); + popup->set_position(get_screen_position() - Vector2(0, minsize.y)); } else { - popup->set_position(get_global_position() + Vector2(0, get_size().y)); + popup->set_position(get_screen_position() + Vector2(0, get_size().y)); } popup->popup(); } diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 4bc33b220e..fd7935b376 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -30,7 +30,7 @@ #include "graph_edit.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "scene/gui/box_container.h" @@ -281,13 +281,13 @@ void GraphEdit::remove_child_notify(Node *p_child) { void GraphEdit::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - port_grab_distance_horizontal = get_constant("port_grab_distance_horizontal"); - port_grab_distance_vertical = get_constant("port_grab_distance_vertical"); + port_grab_distance_horizontal = get_theme_constant("port_grab_distance_horizontal"); + port_grab_distance_vertical = get_theme_constant("port_grab_distance_vertical"); - zoom_minus->set_icon(get_icon("minus")); - zoom_reset->set_icon(get_icon("reset")); - zoom_plus->set_icon(get_icon("more")); - snap_button->set_icon(get_icon("snap")); + zoom_minus->set_icon(get_theme_icon("minus")); + zoom_reset->set_icon(get_theme_icon("reset")); + zoom_plus->set_icon(get_theme_icon("more")); + snap_button->set_icon(get_theme_icon("snap")); } if (p_what == NOTIFICATION_READY) { Size2 hmin = h_scroll->get_combined_minimum_size(); @@ -305,7 +305,7 @@ void GraphEdit::_notification(int p_what) { } if (p_what == NOTIFICATION_DRAW) { - draw_style_box(get_stylebox("bg"), Rect2(Point2(), get_size())); + draw_style_box(get_theme_stylebox("bg"), Rect2(Point2(), get_size())); if (is_using_snap()) { //draw grid @@ -318,8 +318,8 @@ void GraphEdit::_notification(int p_what) { Point2i from = (offset / float(snap)).floor(); Point2i len = (size / float(snap)).floor() + Vector2(1, 1); - Color grid_minor = get_color("grid_minor"); - Color grid_major = get_color("grid_major"); + Color grid_minor = get_theme_color("grid_minor"); + Color grid_major = get_theme_color("grid_major"); for (int i = from.x; i < from.x + len.x; i++) { @@ -357,7 +357,7 @@ void GraphEdit::_notification(int p_what) { bool GraphEdit::_filter_input(const Point2 &p_point) { - Ref<Texture2D> port = get_icon("port", "GraphNode"); + Ref<Texture2D> port = get_theme_icon("port", "GraphNode"); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -389,7 +389,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseButton> mb = p_ev; if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { - Ref<Texture2D> port = get_icon("port", "GraphNode"); + Ref<Texture2D> port = get_theme_icon("port", "GraphNode"); Vector2 mpos(mb->get_position().x, mb->get_position().y); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -501,7 +501,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_target = false; top_layer->update(); - Ref<Texture2D> port = get_icon("port", "GraphNode"); + Ref<Texture2D> port = get_theme_icon("port", "GraphNode"); Vector2 mpos = mm->get_position(); for (int i = get_child_count() - 1; i >= 0; i--) { @@ -666,8 +666,8 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const //cubic bezier code float diff = p_to.x - p_from.x; float cp_offset; - int cp_len = get_constant("bezier_len_pos"); - int cp_neg_len = get_constant("bezier_len_neg"); + int cp_len = get_theme_constant("bezier_len_pos"); + int cp_neg_len = get_theme_constant("bezier_len_neg"); if (diff > 0) { cp_offset = MIN(cp_len, diff * 0.5); @@ -697,7 +697,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const void GraphEdit::_connections_layer_draw() { - Color activity_color = get_color("activity"); + Color activity_color = get_theme_color("activity"); //draw connections List<List<Connection>::Element *> to_erase; for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { @@ -784,8 +784,8 @@ void GraphEdit::_top_layer_draw() { } if (box_selecting) { - top_layer->draw_rect(box_selecting_rect, get_color("selection_fill")); - top_layer->draw_rect(box_selecting_rect, get_color("selection_stroke"), false); + top_layer->draw_rect(box_selecting_rect, get_theme_color("selection_fill")); + top_layer->draw_rect(box_selecting_rect, get_theme_color("selection_stroke"), false); } } @@ -804,7 +804,7 @@ void GraphEdit::set_selected(Node *p_child) { void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { Ref<InputEventMouseMotion> mm = p_ev; - if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) { + if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && InputFilter::get_singleton()->is_key_pressed(KEY_SPACE)))) { h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x); v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y); } @@ -823,7 +823,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { // Snapping can be toggled temporarily by holding down Ctrl. // This is done here as to not toggle the grid when holding down Ctrl. - if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (is_using_snap() ^ InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) { const int snap = get_snap(); pos = pos.snapped(Vector2(snap, snap)); } @@ -886,7 +886,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && dragging) { - if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (!just_selected && drag_accum == Vector2() && InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) { //deselect current node for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); @@ -948,7 +948,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { drag_accum = Vector2(); drag_origin = get_local_mouse_position(); just_selected = !gn->is_selected(); - if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + if (!gn->is_selected() && !InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) { for (int i = 0; i < get_child_count(); i++) { GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i)); if (o_gn) @@ -968,7 +968,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { } else { if (_filter_input(b->get_position())) return; - if (Input::get_singleton()->is_key_pressed(KEY_SPACE)) + if (InputFilter::get_singleton()->is_key_pressed(KEY_SPACE)) return; box_selecting = true; @@ -1025,16 +1025,16 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { //too difficult to get right //set_zoom(zoom/ZOOM_SCALE); } - if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (b->get_button_index() == BUTTON_WHEEL_UP && !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); } - if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (b->get_button_index() == BUTTON_WHEEL_DOWN && !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); } - if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8); } - if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8); } } diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 82e890395a..c28a60ff87 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -117,8 +117,8 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const { void GraphNode::_resort() { - int sep = get_constant("separation"); - Ref<StyleBox> sb = get_stylebox("frame"); + int sep = get_theme_constant("separation"); + Ref<StyleBox> sb = get_theme_stylebox("frame"); bool first = true; Size2 minsize; @@ -169,8 +169,8 @@ void GraphNode::_resort() { bool GraphNode::has_point(const Point2 &p_point) const { if (comment) { - Ref<StyleBox> comment = get_stylebox("comment"); - Ref<Texture2D> resizer = get_icon("resizer"); + Ref<StyleBox> comment = get_theme_stylebox("comment"); + Ref<Texture2D> resizer = get_theme_icon("resizer"); if (Rect2(get_size() - resizer->get_size(), resizer->get_size()).has_point(p_point)) { return true; @@ -195,28 +195,28 @@ void GraphNode::_notification(int p_what) { Ref<StyleBox> sb; if (comment) { - sb = get_stylebox(selected ? "commentfocus" : "comment"); + sb = get_theme_stylebox(selected ? "commentfocus" : "comment"); } else { - sb = get_stylebox(selected ? "selectedframe" : "frame"); + sb = get_theme_stylebox(selected ? "selectedframe" : "frame"); } //sb=sb->duplicate(); //sb->call("set_modulate",modulate); - Ref<Texture2D> port = get_icon("port"); - Ref<Texture2D> close = get_icon("close"); - Ref<Texture2D> resizer = get_icon("resizer"); - int close_offset = get_constant("close_offset"); - int close_h_offset = get_constant("close_h_offset"); - Color close_color = get_color("close_color"); - Color resizer_color = get_color("resizer_color"); - Ref<Font> title_font = get_font("title_font"); - int title_offset = get_constant("title_offset"); - int title_h_offset = get_constant("title_h_offset"); - Color title_color = get_color("title_color"); + Ref<Texture2D> port = get_theme_icon("port"); + Ref<Texture2D> close = get_theme_icon("close"); + Ref<Texture2D> resizer = get_theme_icon("resizer"); + int close_offset = get_theme_constant("close_offset"); + int close_h_offset = get_theme_constant("close_h_offset"); + Color close_color = get_theme_color("close_color"); + Color resizer_color = get_theme_color("resizer_color"); + Ref<Font> title_font = get_theme_font("title_font"); + int title_offset = get_theme_constant("title_offset"); + int title_h_offset = get_theme_constant("title_h_offset"); + Color title_color = get_theme_color("title_color"); Point2i icofs = -port->get_size() * 0.5; - int edgeofs = get_constant("port_offset"); + int edgeofs = get_theme_constant("port_offset"); icofs.y += sb->get_margin(MARGIN_TOP); draw_style_box(sb, Rect2(Point2(), get_size())); @@ -227,10 +227,10 @@ void GraphNode::_notification(int p_what) { } break; case OVERLAY_BREAKPOINT: { - draw_style_box(get_stylebox("breakpoint"), Rect2(Point2(), get_size())); + draw_style_box(get_theme_stylebox("breakpoint"), Rect2(Point2(), get_size())); } break; case OVERLAY_POSITION: { - draw_style_box(get_stylebox("position"), Rect2(Point2(), get_size())); + draw_style_box(get_theme_stylebox("position"), Rect2(Point2(), get_size())); } break; } @@ -370,16 +370,16 @@ Color GraphNode::get_slot_color_right(int p_idx) const { Size2 GraphNode::get_minimum_size() const { - Ref<Font> title_font = get_font("title_font"); + Ref<Font> title_font = get_theme_font("title_font"); - int sep = get_constant("separation"); - Ref<StyleBox> sb = get_stylebox("frame"); + int sep = get_theme_constant("separation"); + Ref<StyleBox> sb = get_theme_stylebox("frame"); bool first = true; Size2 minsize; minsize.x = title_font->get_string_size(title).x; if (show_close) { - Ref<Texture2D> close = get_icon("close"); + Ref<Texture2D> close = get_theme_icon("close"); minsize.x += sep + close->get_width(); } @@ -464,10 +464,10 @@ bool GraphNode::is_close_button_visible() const { void GraphNode::_connpos_update() { - int edgeofs = get_constant("port_offset"); - int sep = get_constant("separation"); + int edgeofs = get_theme_constant("port_offset"); + int sep = get_theme_constant("separation"); - Ref<StyleBox> sb = get_stylebox("frame"); + Ref<StyleBox> sb = get_theme_stylebox("frame"); conn_input_cache.clear(); conn_output_cache.clear(); int vofs = 0; @@ -606,7 +606,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) { return; } - Ref<Texture2D> resizer = get_icon("resizer"); + Ref<Texture2D> resizer = get_theme_icon("resizer"); if (resizable && mpos.x > get_size().x - resizer->get_width() && mpos.y > get_size().y - resizer->get_height()) { diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index 0028093a95..16f6fd0111 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -41,8 +41,8 @@ void GridContainer::_notification(int p_what) { Set<int> col_expanded; // Columns which have the SIZE_EXPAND flag set. Set<int> row_expanded; // Rows which have the SIZE_EXPAND flag set. - int hsep = get_constant("hseparation"); - int vsep = get_constant("vseparation"); + int hsep = get_theme_constant("hseparation"); + int vsep = get_theme_constant("vseparation"); int max_col = MIN(get_child_count(), columns); int max_row = ceil((float)get_child_count() / (float)columns); @@ -200,8 +200,8 @@ Size2 GridContainer::get_minimum_size() const { Map<int, int> col_minw; Map<int, int> row_minh; - int hsep = get_constant("hseparation"); - int vsep = get_constant("vseparation"); + int hsep = get_theme_constant("hseparation"); + int vsep = get_theme_constant("vseparation"); int max_row = 0; int max_col = 0; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 5e662b8df0..2db44d0b66 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -495,7 +495,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { search_string = ""; //any mousepress cancels Vector2 pos = mb->get_position(); - Ref<StyleBox> bg = get_stylebox("bg"); + Ref<StyleBox> bg = get_theme_stylebox("bg"); pos -= bg->get_offset(); pos.y += scroll_bar->get_value(); @@ -820,7 +820,7 @@ void ItemList::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<StyleBox> bg = get_stylebox("bg"); + Ref<StyleBox> bg = get_theme_stylebox("bg"); int mw = scroll_bar->get_minimum_size().x; scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw); @@ -837,18 +837,18 @@ void ItemList::_notification(int p_what) { draw_style_box(bg, Rect2(Point2(), size)); - int hseparation = get_constant("hseparation"); - int vseparation = get_constant("vseparation"); - int icon_margin = get_constant("icon_margin"); - int line_separation = get_constant("line_separation"); + int hseparation = get_theme_constant("hseparation"); + int vseparation = get_theme_constant("vseparation"); + int icon_margin = get_theme_constant("icon_margin"); + int line_separation = get_theme_constant("line_separation"); - Ref<StyleBox> sbsel = has_focus() ? get_stylebox("selected_focus") : get_stylebox("selected"); - Ref<StyleBox> cursor = has_focus() ? get_stylebox("cursor") : get_stylebox("cursor_unfocused"); + Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox("selected_focus") : get_theme_stylebox("selected"); + Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox("cursor") : get_theme_stylebox("cursor_unfocused"); - Ref<Font> font = get_font("font"); - Color guide_color = get_color("guide_color"); - Color font_color = get_color("font_color"); - Color font_color_selected = get_color("font_color_selected"); + Ref<Font> font = get_theme_font("font"); + Color guide_color = get_theme_color("guide_color"); + Color font_color = get_theme_color("font_color"); + Color font_color_selected = get_theme_color("font_color_selected"); int font_height = font->get_height(); Vector<int> line_size_cache; Vector<int> line_limit_cache; @@ -860,7 +860,7 @@ void ItemList::_notification(int p_what) { if (has_focus()) { VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true); - draw_style_box(get_stylebox("bg_focus"), Rect2(Point2(), size)); + draw_style_box(get_theme_stylebox("bg_focus"), Rect2(Point2(), size)); VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false); } @@ -1251,7 +1251,7 @@ void ItemList::_scroll_changed(double) { int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const { Vector2 pos = p_pos; - Ref<StyleBox> bg = get_stylebox("bg"); + Ref<StyleBox> bg = get_theme_stylebox("bg"); pos -= bg->get_offset(); pos.y += scroll_bar->get_value(); @@ -1286,7 +1286,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const { return true; Vector2 pos = p_pos; - Ref<StyleBox> bg = get_stylebox("bg"); + Ref<StyleBox> bg = get_theme_stylebox("bg"); pos -= bg->get_offset(); pos.y += scroll_bar->get_value(); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index c900b35d65..ef1bb958f6 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -65,7 +65,7 @@ bool Label::is_uppercase() const { int Label::get_line_height() const { - return get_font("font")->get_height(); + return get_theme_font("font")->get_height(); } void Label::_notification(int p_what) { @@ -94,14 +94,14 @@ void Label::_notification(int p_what) { Size2 string_size; Size2 size = get_size(); - Ref<StyleBox> style = get_stylebox("normal"); - Ref<Font> font = get_font("font"); - Color font_color = get_color("font_color"); - Color font_color_shadow = get_color("font_color_shadow"); - bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); - int line_spacing = get_constant("line_spacing"); - Color font_outline_modulate = get_color("font_outline_modulate"); + Ref<StyleBox> style = get_theme_stylebox("normal"); + Ref<Font> font = get_theme_font("font"); + Color font_color = get_theme_color("font_color"); + Color font_color_shadow = get_theme_color("font_color_shadow"); + bool use_outline = get_theme_constant("shadow_as_outline"); + Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y")); + int line_spacing = get_theme_constant("line_spacing"); + Color font_outline_modulate = get_theme_color("font_outline_modulate"); style->draw(ci, Rect2(Point2(0, 0), get_size())); @@ -300,7 +300,7 @@ void Label::_notification(int p_what) { Size2 Label::get_minimum_size() const { - Size2 min_style = get_stylebox("normal")->get_minimum_size(); + Size2 min_style = get_theme_stylebox("normal")->get_minimum_size(); // don't want to mutable everything if (word_cache_dirty) { @@ -319,7 +319,7 @@ Size2 Label::get_minimum_size() const { int Label::get_longest_line_width() const { - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); real_t max_line_width = 0; real_t line_width = 0; @@ -363,9 +363,9 @@ int Label::get_line_count() const { int Label::get_visible_line_count() const { - int line_spacing = get_constant("line_spacing"); - int font_h = get_font("font")->get_height() + line_spacing; - int lines_visible = (get_size().height - get_stylebox("normal")->get_minimum_size().height + line_spacing) / font_h; + int line_spacing = get_theme_constant("line_spacing"); + int font_h = get_theme_font("font")->get_height() + line_spacing; + int lines_visible = (get_size().height - get_theme_stylebox("normal")->get_minimum_size().height + line_spacing) / font_h; if (lines_visible > line_count) lines_visible = line_count; @@ -387,20 +387,20 @@ void Label::regenerate_word_cache() { int width; if (autowrap) { - Ref<StyleBox> style = get_stylebox("normal"); + Ref<StyleBox> style = get_theme_stylebox("normal"); width = MAX(get_size().width, get_custom_minimum_size().width) - style->get_minimum_size().width; } else { width = get_longest_line_width(); } - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); real_t current_word_size = 0; int word_pos = 0; real_t line_width = 0; int space_count = 0; real_t space_width = font->get_char_size(' ').width; - int line_spacing = get_constant("line_spacing"); + int line_spacing = get_theme_constant("line_spacing"); line_count = 1; total_char_cache = 0; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 7ee4dab3c9..734e27b1b6 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -36,12 +36,12 @@ #include "core/print_string.h" #include "core/translation.h" #include "label.h" - +#include "servers/display_server.h" #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" #include "editor/editor_settings.h" #endif - +#include "scene/main/window.h" static bool _is_text_char(CharType c) { return !is_symbol(c); @@ -56,7 +56,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { menu->set_position(get_global_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); - menu->set_scale(get_global_transform().get_scale()); + //menu->set_scale(get_global_transform().get_scale()); menu->popup(); grab_focus(); accept_event(); @@ -127,8 +127,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { selection.creating = false; selection.doubleclick = false; - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) + DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length); } update(); @@ -304,8 +304,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { case KEY_ENTER: { emit_signal("text_entered", text); - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->hide_virtual_keyboard(); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) + DisplayServer::get_singleton()->virtual_keyboard_hide(); } break; @@ -552,10 +552,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { } break; case KEY_MENU: { if (context_menu_enabled) { - Point2 pos = Point2(get_cursor_pixel_pos(), (get_size().y + get_font("font")->get_height()) / 2); + Point2 pos = Point2(get_cursor_pixel_pos(), (get_size().y + get_theme_font("font")->get_height()) / 2); menu->set_position(get_global_transform().xform(pos)); menu->set_size(Vector2(1, 1)); - menu->set_scale(get_global_transform().get_scale()); + // menu->set_scale(get_global_transform().get_scale()); menu->popup(); menu->grab_focus(); } @@ -629,7 +629,7 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { set_cursor_at_pixel_pos(p_point.x); int selected = selection.end - selection.begin; - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); if (font != NULL) { for (int i = selection.begin; i < selection.end; i++) cached_width -= font->get_char_size(pass ? secret_character[0] : text[i]).width; @@ -654,8 +654,8 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const { if (!clear_button_enabled || !has_point(p_pos)) { return false; } - Ref<Texture2D> icon = Control::get_icon("clear"); - int x_ofs = get_stylebox("normal")->get_offset().x; + Ref<Texture2D> icon = Control::get_theme_icon("clear"); + int x_ofs = get_theme_stylebox("normal")->get_offset().x; return p_pos.x > get_size().width - icon->get_width() - x_ofs; } @@ -685,12 +685,12 @@ void LineEdit::_notification(int p_what) { update_placeholder_width(); update(); } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_FOCUS_IN: { window_has_focus = true; draw_caret = true; update(); } break; - case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_FOCUS_OUT: { window_has_focus = false; draw_caret = false; update(); @@ -709,19 +709,19 @@ void LineEdit::_notification(int p_what) { RID ci = get_canvas_item(); - Ref<StyleBox> style = get_stylebox("normal"); + Ref<StyleBox> style = get_theme_stylebox("normal"); if (!is_editable()) { - style = get_stylebox("read_only"); + style = get_theme_stylebox("read_only"); draw_caret = false; } - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); style->draw(ci, Rect2(Point2(), size)); if (has_focus()) { - get_stylebox("focus")->draw(ci, Rect2(Point2(), size)); + get_theme_stylebox("focus")->draw(ci, Rect2(Point2(), size)); } int x_ofs = 0; @@ -756,10 +756,10 @@ void LineEdit::_notification(int p_what) { int font_ascent = font->get_ascent(); - Color selection_color = get_color("selection_color"); - Color font_color = is_editable() ? get_color("font_color") : get_color("font_color_uneditable"); - Color font_color_selected = get_color("font_color_selected"); - Color cursor_color = get_color("cursor_color"); + Color selection_color = get_theme_color("selection_color"); + Color font_color = is_editable() ? get_theme_color("font_color") : get_theme_color("font_color_uneditable"); + Color font_color_selected = get_theme_color("font_color_selected"); + Color cursor_color = get_theme_color("cursor_color"); const String &t = using_placeholder ? placeholder_translated : text; // Draw placeholder color. @@ -768,13 +768,13 @@ void LineEdit::_notification(int p_what) { bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled; if (right_icon.is_valid() || display_clear_icon) { - Ref<Texture2D> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon; + Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon; Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9); if (display_clear_icon) { if (clear_button_status.press_attempt && clear_button_status.pressing_inside) { - color_icon = get_color("clear_button_color_pressed"); + color_icon = get_theme_color("clear_button_color_pressed"); } else { - color_icon = get_color("clear_button_color"); + color_icon = get_theme_color("clear_button_color"); } } @@ -913,9 +913,10 @@ void LineEdit::_notification(int p_what) { } if (has_focus()) { - - OS::get_singleton()->set_ime_active(true); - OS::get_singleton()->set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height)); + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); + DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height), get_viewport()->get_window_id()); + } } } break; case NOTIFICATION_FOCUS_ENTER: { @@ -926,12 +927,14 @@ void LineEdit::_notification(int p_what) { draw_caret = true; } - OS::get_singleton()->set_ime_active(true); - Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height; - OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); + Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height; + DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id()); + } - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) + DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length); } break; case NOTIFICATION_FOCUS_EXIT: { @@ -940,20 +943,22 @@ void LineEdit::_notification(int p_what) { caret_blink_timer->stop(); } - OS::get_singleton()->set_ime_position(Point2()); - OS::get_singleton()->set_ime_active(false); + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); + DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id()); + } ime_text = ""; ime_selection = Point2(); - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->hide_virtual_keyboard(); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) + DisplayServer::get_singleton()->virtual_keyboard_hide(); } break; case MainLoop::NOTIFICATION_OS_IME_UPDATE: { if (has_focus()) { - ime_text = OS::get_singleton()->get_ime_text(); - ime_selection = OS::get_singleton()->get_ime_selection(); + ime_text = DisplayServer::get_singleton()->ime_get_text(); + ime_selection = DisplayServer::get_singleton()->ime_get_selection(); update(); } } break; @@ -963,14 +968,14 @@ void LineEdit::_notification(int p_what) { void LineEdit::copy_text() { if (selection.enabled && !pass) { - OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin)); + DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin)); } } void LineEdit::cut_text() { if (selection.enabled && !pass) { - OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin)); + DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin)); selection_delete(); } } @@ -978,7 +983,7 @@ void LineEdit::cut_text() { void LineEdit::paste_text() { // Strip escape characters like \n and \t as they can't be displayed on LineEdit. - String paste_buffer = OS::get_singleton()->get_clipboard().strip_escapes(); + String paste_buffer = DisplayServer::get_singleton()->clipboard_get().strip_escapes(); if (paste_buffer != "") { @@ -1054,13 +1059,13 @@ void LineEdit::shift_selection_check_post(bool p_shift) { void LineEdit::set_cursor_at_pixel_pos(int p_x) { - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); int ofs = window_pos; - Ref<StyleBox> style = get_stylebox("normal"); + Ref<StyleBox> style = get_theme_stylebox("normal"); int pixel_ofs = 0; Size2 size = get_size(); bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled; - int r_icon_width = Control::get_icon("clear")->get_width(); + int r_icon_width = Control::get_theme_icon("clear")->get_width(); switch (align) { @@ -1108,13 +1113,13 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { int LineEdit::get_cursor_pixel_pos() { - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); int ofs = window_pos; - Ref<StyleBox> style = get_stylebox("normal"); + Ref<StyleBox> style = get_theme_stylebox("normal"); int pixel_ofs = 0; Size2 size = get_size(); bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled; - int r_icon_width = Control::get_icon("clear")->get_width(); + int r_icon_width = Control::get_theme_icon("clear")->get_width(); switch (align) { @@ -1201,7 +1206,7 @@ void LineEdit::delete_char() { if ((text.length() <= 0) || (cursor_pos == 0)) return; - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); if (font != NULL) { cached_width -= font->get_char_size(pass ? secret_character[0] : text[cursor_pos - 1]).width; } @@ -1220,7 +1225,7 @@ void LineEdit::delete_char() { void LineEdit::delete_text(int p_from_column, int p_to_column) { if (text.size() > 0) { - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); if (font != NULL) { for (int i = p_from_column; i < p_to_column; i++) cached_width -= font->get_char_size(pass ? secret_character[0] : text[i]).width; @@ -1318,8 +1323,8 @@ void LineEdit::set_cursor_position(int p_pos) { return; } - Ref<StyleBox> style = get_stylebox("normal"); - Ref<Font> font = get_font("font"); + Ref<StyleBox> style = get_theme_stylebox("normal"); + Ref<Font> font = get_theme_font("font"); if (cursor_pos <= window_pos) { // Adjust window if cursor goes too much to the left. @@ -1329,7 +1334,7 @@ void LineEdit::set_cursor_position(int p_pos) { int window_width = get_size().width - style->get_minimum_size().width; bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled; if (right_icon.is_valid() || display_clear_icon) { - Ref<Texture2D> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon; + Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon; window_width -= r_icon->get_width(); } @@ -1404,14 +1409,14 @@ void LineEdit::clear_internal() { Size2 LineEdit::get_minimum_size() const { - Ref<StyleBox> style = get_stylebox("normal"); - Ref<Font> font = get_font("font"); + Ref<StyleBox> style = get_theme_stylebox("normal"); + Ref<Font> font = get_theme_font("font"); Size2 min_size; // Minimum size of text. int space_size = font->get_char_size(' ').x; - min_size.width = get_constant("minimum_spaces") * space_size; + min_size.width = get_theme_constant("minimum_spaces") * space_size; if (expand_to_text_length) { // Add a space because some fonts are too exact, and because cursor needs a bit more when at the end. @@ -1422,8 +1427,8 @@ Size2 LineEdit::get_minimum_size() const { // Take icons into account. if (!text.empty() && is_editable() && clear_button_enabled) { - min_size.width = MAX(min_size.width, Control::get_icon("clear")->get_width()); - min_size.height = MAX(min_size.height, Control::get_icon("clear")->get_height()); + min_size.width = MAX(min_size.width, Control::get_theme_icon("clear")->get_width()); + min_size.height = MAX(min_size.height, Control::get_theme_icon("clear")->get_height()); } if (right_icon.is_valid()) { min_size.width = MAX(min_size.width, right_icon->get_width()); @@ -1702,7 +1707,7 @@ void LineEdit::_emit_text_change() { } void LineEdit::update_cached_width() { - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); cached_width = 0; if (font != NULL) { String text = get_text(); @@ -1713,7 +1718,7 @@ void LineEdit::update_cached_width() { } void LineEdit::update_placeholder_width() { - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); cached_placeholder_width = 0; if (font != NULL) { for (int i = 0; i < placeholder_translated.length(); i++) { diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp index 4b8054bac6..3dffa06b49 100644 --- a/scene/gui/link_button.cpp +++ b/scene/gui/link_button.cpp @@ -54,7 +54,7 @@ LinkButton::UnderlineMode LinkButton::get_underline_mode() const { Size2 LinkButton::get_minimum_size() const { - return get_font("font")->get_string_size(text); + return get_theme_font("font")->get_string_size(text); } void LinkButton::_notification(int p_what) { @@ -72,29 +72,29 @@ void LinkButton::_notification(int p_what) { case DRAW_NORMAL: { - color = get_color("font_color"); + color = get_theme_color("font_color"); do_underline = underline_mode == UNDERLINE_MODE_ALWAYS; } break; case DRAW_HOVER_PRESSED: case DRAW_PRESSED: { - if (has_color("font_color_pressed")) - color = get_color("font_color_pressed"); + if (has_theme_color("font_color_pressed")) + color = get_theme_color("font_color_pressed"); else - color = get_color("font_color"); + color = get_theme_color("font_color"); do_underline = underline_mode != UNDERLINE_MODE_NEVER; } break; case DRAW_HOVER: { - color = get_color("font_color_hover"); + color = get_theme_color("font_color_hover"); do_underline = underline_mode != UNDERLINE_MODE_NEVER; } break; case DRAW_DISABLED: { - color = get_color("font_color_disabled"); + color = get_theme_color("font_color_disabled"); do_underline = underline_mode == UNDERLINE_MODE_ALWAYS; } break; @@ -102,16 +102,16 @@ void LinkButton::_notification(int p_what) { if (has_focus()) { - Ref<StyleBox> style = get_stylebox("focus"); + Ref<StyleBox> style = get_theme_stylebox("focus"); style->draw(ci, Rect2(Point2(), size)); } - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); draw_string(font, Vector2(0, font->get_ascent()), text, color); if (do_underline) { - int underline_spacing = get_constant("underline_spacing"); + int underline_spacing = get_theme_constant("underline_spacing"); int width = font->get_string_size(text).width; int y = font->get_ascent() + underline_spacing; diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index 53373fc297..1cd4ff4ff8 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -32,10 +32,10 @@ Size2 MarginContainer::get_minimum_size() const { - int margin_left = get_constant("margin_left"); - int margin_top = get_constant("margin_top"); - int margin_right = get_constant("margin_right"); - int margin_bottom = get_constant("margin_bottom"); + int margin_left = get_theme_constant("margin_left"); + int margin_top = get_theme_constant("margin_top"); + int margin_right = get_theme_constant("margin_right"); + int margin_bottom = get_theme_constant("margin_bottom"); Size2 max; @@ -67,10 +67,10 @@ void MarginContainer::_notification(int p_what) { switch (p_what) { case NOTIFICATION_SORT_CHILDREN: { - int margin_left = get_constant("margin_left"); - int margin_top = get_constant("margin_top"); - int margin_right = get_constant("margin_right"); - int margin_bottom = get_constant("margin_bottom"); + int margin_left = get_theme_constant("margin_left"); + int margin_top = get_theme_constant("margin_top"); + int margin_right = get_theme_constant("margin_right"); + int margin_bottom = get_theme_constant("margin_bottom"); Size2 s = get_size(); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 2b163187c5..a7d1f64e93 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -31,7 +31,7 @@ #include "menu_button.h" #include "core/os/keyboard.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { @@ -43,23 +43,34 @@ void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { if (!get_parent() || !is_visible_in_tree() || is_disabled()) return; - bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)); - - if (popup->activate_item_by_event(p_event, global_only)) + //bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)); + //if (popup->activate_item_by_event(p_event, global_only)) + // accept_event(); + if (popup->activate_item_by_event(p_event, false)) accept_event(); } } void MenuButton::pressed() { - emit_signal("about_to_show"); + { + Window *w = Object::cast_to<Window>(get_viewport()); + if (w && !w->is_embedding_subwindows()) { + print_line("windowpos: " + w->get_position()); + } + } Size2 size = get_size(); - Point2 gp = get_global_position(); - popup->set_global_position(gp + Size2(0, size.height * get_global_transform().get_scale().y)); + Point2 gp = get_screen_position(); + + print_line("screenpos: " + gp); + gp.y += get_size().y; + + popup->set_position(gp); + popup->set_size(Size2(size.width, 0)); - popup->set_scale(get_global_transform().get_scale()); - popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size())); + popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size())); + popup->take_mouse_focus(); popup->popup(); } @@ -116,7 +127,7 @@ void MenuButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover"); - ADD_SIGNAL(MethodInfo("about_to_show")); + ADD_SIGNAL(MethodInfo("about_to_popup")); } void MenuButton::set_disable_shortcuts(bool p_disabled) { @@ -137,8 +148,7 @@ MenuButton::MenuButton() { popup = memnew(PopupMenu); popup->hide(); add_child(popup); - popup->set_pass_on_modal_close_click(false); - popup->connect("about_to_show", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); // For when switching from another MenuButton. + popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); // For when switching from another MenuButton. popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false)); } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index c185761beb..30ecd651b1 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -36,12 +36,12 @@ Size2 OptionButton::get_minimum_size() const { Size2 minsize = Button::get_minimum_size(); - if (has_icon("arrow")) { - const Size2 padding = get_stylebox("normal")->get_minimum_size(); - const Size2 arrow_size = Control::get_icon("arrow")->get_size(); + if (has_theme_icon("arrow")) { + const Size2 padding = get_theme_stylebox("normal")->get_minimum_size(); + const Size2 arrow_size = Control::get_theme_icon("arrow")->get_size(); Size2 content_size = minsize - padding; - content_size.width += arrow_size.width + get_constant("hseparation"); + content_size.width += arrow_size.width + get_theme_constant("hseparation"); content_size.height = MAX(content_size.height, arrow_size.height); minsize = content_size + padding; @@ -55,37 +55,37 @@ void OptionButton::_notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { - if (!has_icon("arrow")) + if (!has_theme_icon("arrow")) return; RID ci = get_canvas_item(); - Ref<Texture2D> arrow = Control::get_icon("arrow"); + Ref<Texture2D> arrow = Control::get_theme_icon("arrow"); Color clr = Color(1, 1, 1); - if (get_constant("modulate_arrow")) { + if (get_theme_constant("modulate_arrow")) { switch (get_draw_mode()) { case DRAW_PRESSED: - clr = get_color("font_color_pressed"); + clr = get_theme_color("font_color_pressed"); break; case DRAW_HOVER: - clr = get_color("font_color_hover"); + clr = get_theme_color("font_color_hover"); break; case DRAW_DISABLED: - clr = get_color("font_color_disabled"); + clr = get_theme_color("font_color_disabled"); break; default: - clr = get_color("font_color"); + clr = get_theme_color("font_color"); } } Size2 size = get_size(); - Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2))); + Point2 ofs(size.width - arrow->get_width() - get_theme_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2))); arrow->draw(ci, ofs, clr); } break; case NOTIFICATION_THEME_CHANGED: { - if (has_icon("arrow")) { - _set_internal_margin(MARGIN_RIGHT, Control::get_icon("arrow")->get_width()); + if (has_theme_icon("arrow")) { + _set_internal_margin(MARGIN_RIGHT, Control::get_theme_icon("arrow")->get_width()); } } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -109,9 +109,8 @@ void OptionButton::_selected(int p_which) { void OptionButton::pressed() { Size2 size = get_size(); - popup->set_global_position(get_global_position() + Size2(0, size.height * get_global_transform().get_scale().y)); + popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); popup->set_size(Size2(size.width, 0)); - popup->set_scale(get_global_transform().get_scale()); popup->popup(); } @@ -351,15 +350,15 @@ OptionButton::OptionButton() { set_toggle_mode(true); set_text_align(ALIGN_LEFT); set_action_mode(ACTION_MODE_BUTTON_PRESS); - if (has_icon("arrow")) { - _set_internal_margin(MARGIN_RIGHT, Control::get_icon("arrow")->get_width()); + if (has_theme_icon("arrow")) { + _set_internal_margin(MARGIN_RIGHT, Control::get_theme_icon("arrow")->get_width()); } popup = memnew(PopupMenu); popup->hide(); add_child(popup); - popup->set_pass_on_modal_close_click(false); - popup->set_notify_transform(true); + // popup->set_pass_on_modal_close_click(false); + // popup->set_notify_transform(true); popup->set_allow_search(true); popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected)); popup->connect("id_focused", callable_mp(this, &OptionButton::_focused)); diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp index 0356607071..ae51463a15 100644 --- a/scene/gui/panel.cpp +++ b/scene/gui/panel.cpp @@ -36,11 +36,25 @@ void Panel::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { RID ci = get_canvas_item(); - Ref<StyleBox> style = get_stylebox("panel"); + Ref<StyleBox> style = mode == MODE_BACKGROUND ? get_theme_stylebox("panel") : get_theme_stylebox("panel_fg"); style->draw(ci, Rect2(Point2(), get_size())); } } +void Panel::set_mode(Mode p_mode) { + mode = p_mode; + update(); +} +Panel::Mode Panel::get_mode() const { + return mode; +} + +void Panel::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Panel::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"), &Panel::get_mode); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Background,Foreground"), "set_mode", "get_mode"); +} Panel::Panel() { // Has visible stylebox, so stop by default. set_mouse_filter(MOUSE_FILTER_STOP); diff --git a/scene/gui/panel.h b/scene/gui/panel.h index 3538126d22..739c64c0a6 100644 --- a/scene/gui/panel.h +++ b/scene/gui/panel.h @@ -37,12 +37,26 @@ class Panel : public Control { GDCLASS(Panel, Control); +public: + enum Mode { + MODE_BACKGROUND, + MODE_FOREGROUND + }; + +private: + Mode mode = MODE_BACKGROUND; + protected: void _notification(int p_what); + static void _bind_methods(); public: + void set_mode(Mode p_mode); + Mode get_mode() const; + Panel(); ~Panel(); }; +VARIANT_ENUM_CAST(Panel::Mode) #endif diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp index 6cf23b8a32..62b9296409 100644 --- a/scene/gui/panel_container.cpp +++ b/scene/gui/panel_container.cpp @@ -34,16 +34,16 @@ Size2 PanelContainer::get_minimum_size() const { Ref<StyleBox> style; - if (has_stylebox("panel")) - style = get_stylebox("panel"); + if (has_theme_stylebox("panel")) + style = get_theme_stylebox("panel"); else - style = get_stylebox("panel", "PanelContainer"); + style = get_theme_stylebox("panel", "PanelContainer"); Size2 ms; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c || !c->is_visible_in_tree()) + if (!c || !c->is_visible()) continue; if (c->is_set_as_toplevel()) continue; @@ -65,10 +65,10 @@ void PanelContainer::_notification(int p_what) { RID ci = get_canvas_item(); Ref<StyleBox> style; - if (has_stylebox("panel")) - style = get_stylebox("panel"); + if (has_theme_stylebox("panel")) + style = get_theme_stylebox("panel"); else - style = get_stylebox("panel", "PanelContainer"); + style = get_theme_stylebox("panel", "PanelContainer"); style->draw(ci, Rect2(Point2(), get_size())); } @@ -77,10 +77,10 @@ void PanelContainer::_notification(int p_what) { Ref<StyleBox> style; - if (has_stylebox("panel")) - style = get_stylebox("panel"); + if (has_theme_stylebox("panel")) + style = get_theme_stylebox("panel"); else - style = get_stylebox("panel", "PanelContainer"); + style = get_theme_stylebox("panel", "PanelContainer"); Size2 size = get_size(); Point2 ofs; diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 64ef4a01f6..6edafc65a0 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -32,227 +32,131 @@ #include "core/engine.h" #include "core/os/keyboard.h" +#include "scene/gui/panel.h" -void Popup::_gui_input(Ref<InputEvent> p_event) { -} - -void Popup::_notification(int p_what) { - - if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - if (popped_up && !is_visible_in_tree()) { - popped_up = false; - notification(NOTIFICATION_POPUP_HIDE); - emit_signal("popup_hide"); - } - - update_configuration_warning(); - } - - if (p_what == NOTIFICATION_EXIT_TREE) { - if (popped_up) { - popped_up = false; - notification(NOTIFICATION_POPUP_HIDE); - emit_signal("popup_hide"); - } - } - - if (p_what == NOTIFICATION_ENTER_TREE) { -//small helper to make editing of these easier in editor -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { - //edited on editor - set_as_toplevel(false); - } else -#endif - if (is_visible()) { - hide(); - } +void Popup::_input_from_window(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> key = p_event; + if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) { + _close_pressed(); } } -void Popup::_fix_size() { - - Point2 pos = get_global_position(); - Size2 size = get_size() * get_scale(); - Point2 window_size = get_viewport_rect().size - get_viewport_transform().get_origin(); - - if (pos.x + size.width > window_size.width) - pos.x = window_size.width - size.width; - if (pos.x < 0) - pos.x = 0; +void Popup::_parent_focused() { - if (pos.y + size.height > window_size.height) - pos.y = window_size.height - size.height; - if (pos.y < 0) - pos.y = 0; - if (pos != get_position()) - set_global_position(pos); + _close_pressed(); } +void Popup::_notification(int p_what) { -void Popup::set_as_minsize() { - - Size2 total_minsize; - - for (int i = 0; i < get_child_count(); i++) { - - Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) - continue; - if (!c->is_visible()) - continue; - - Size2 minsize = c->get_combined_minimum_size(); - - for (int j = 0; j < 2; j++) { - - Margin m_beg = Margin(0 + j); - Margin m_end = Margin(2 + j); - - float margin_begin = c->get_margin(m_beg); - float margin_end = c->get_margin(m_end); - float anchor_begin = c->get_anchor(m_beg); - float anchor_end = c->get_anchor(m_end); - - minsize[j] += margin_begin * (ANCHOR_END - anchor_begin) + margin_end * anchor_end; - } - - total_minsize.width = MAX(total_minsize.width, minsize.width); - total_minsize.height = MAX(total_minsize.height, minsize.height); + switch (p_what) { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (is_visible()) { + + parent_visible = get_parent_visible_window(); + if (parent_visible) { + parent_visible->connect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + } + } else { + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + parent_visible = nullptr; + } + + emit_signal("popup_hide"); + } + + } break; + case NOTIFICATION_EXIT_TREE: { + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + parent_visible = nullptr; + } + } break; + case NOTIFICATION_WM_CLOSE_REQUEST: { + _close_pressed(); + + } break; } - - set_size(total_minsize); } -void Popup::popup_centered_clamped(const Size2 &p_size, float p_fallback_ratio) { - - Size2 popup_size = p_size; - Size2 window_size = get_viewport_rect().size; - - // clamp popup size in each dimension if window size is too small (using fallback ratio) - popup_size.x = MIN(window_size.x * p_fallback_ratio, popup_size.x); - popup_size.y = MIN(window_size.y * p_fallback_ratio, popup_size.y); - - popup_centered(popup_size); -} +void Popup::_close_pressed() { -void Popup::popup_centered_minsize(const Size2 &p_minsize) { - - set_custom_minimum_size(p_minsize); - _fix_size(); - popup_centered(); -} + Window *parent_window = parent_visible; + if (parent_visible) { + parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + parent_visible = nullptr; + } -void Popup::popup_centered(const Size2 &p_size) { + call_deferred("hide"); - Rect2 rect; - Size2 window_size = get_viewport_rect().size; - rect.size = p_size == Size2() ? get_size() : p_size; - rect.position = ((window_size - rect.size) / 2.0).floor(); + emit_signal("cancelled"); - _popup(rect, true); + if (parent_window) { + //parent_window->grab_focus(); + } } -void Popup::popup_centered_ratio(float p_screen_ratio) { - - Rect2 rect; - Size2 window_size = get_viewport_rect().size; - rect.size = (window_size * p_screen_ratio).floor(); - rect.position = ((window_size - rect.size) / 2.0).floor(); - - _popup(rect, true); +void Popup::set_as_minsize() { + set_size(get_contents_minimum_size()); } +void Popup::_bind_methods() { -void Popup::popup(const Rect2 &p_bounds) { - - _popup(p_bounds); + ADD_SIGNAL(MethodInfo("popup_hide")); } -void Popup::_popup(const Rect2 &p_bounds, const bool p_centered) { - - emit_signal("about_to_show"); - show_modal(exclusive); - - // Fit the popup into the optionally provided bounds. - if (!p_bounds.has_no_area()) { - set_size(p_bounds.size); +Rect2i Popup::_popup_adjust_rect() const { + ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); + Rect2i parent = get_usable_parent_rect(); - // check if p_bounds.size was using an outdated cached values - if (p_centered && p_bounds.size != get_size()) { - set_position(p_bounds.position - ((get_size() - p_bounds.size) / 2.0).floor()); - } else { - set_position(p_bounds.position); - } + if (parent == Rect2i()) { + return Rect2i(); } - _fix_size(); - - Control *focusable = find_next_valid_focus(); - - if (focusable) - focusable->grab_focus(); - - _post_popup(); - notification(NOTIFICATION_POST_POPUP); - popped_up = true; -} -void Popup::set_exclusive(bool p_exclusive) { + Rect2i current(get_position(), get_size()); - exclusive = p_exclusive; -} - -bool Popup::is_exclusive() const { + if (current.position.x + current.size.x > parent.position.x + parent.size.x) { + current.position.x = parent.position.x + parent.size.x - current.size.x; + } - return exclusive; -} + if (current.position.x < parent.position.x) { + current.position.x = parent.position.x; + } -void Popup::_bind_methods() { + if (current.position.y + current.size.y > parent.position.y + parent.size.y) { + current.position.y = parent.position.y + parent.size.y - current.size.y; + } - ClassDB::bind_method(D_METHOD("set_as_minsize"), &Popup::set_as_minsize); - ClassDB::bind_method(D_METHOD("popup_centered", "size"), &Popup::popup_centered, DEFVAL(Size2())); - ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Popup::popup_centered_ratio, DEFVAL(0.75)); - ClassDB::bind_method(D_METHOD("popup_centered_minsize", "minsize"), &Popup::popup_centered_minsize, DEFVAL(Size2())); - ClassDB::bind_method(D_METHOD("popup_centered_clamped", "size", "fallback_ratio"), &Popup::popup_centered_clamped, DEFVAL(Size2()), DEFVAL(0.75)); - ClassDB::bind_method(D_METHOD("popup", "bounds"), &Popup::popup, DEFVAL(Rect2())); - ClassDB::bind_method(D_METHOD("set_exclusive", "enable"), &Popup::set_exclusive); - ClassDB::bind_method(D_METHOD("is_exclusive"), &Popup::is_exclusive); - ADD_SIGNAL(MethodInfo("about_to_show")); - ADD_SIGNAL(MethodInfo("popup_hide")); - ADD_GROUP("Popup", "popup_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "popup_exclusive"), "set_exclusive", "is_exclusive"); + if (current.position.y < parent.position.y) { + current.position.y = parent.position.y; + } - BIND_CONSTANT(NOTIFICATION_POST_POPUP); - BIND_CONSTANT(NOTIFICATION_POPUP_HIDE); + return current; } Popup::Popup() { - set_as_toplevel(true); - exclusive = false; - popped_up = false; - hide(); -} - -String Popup::get_configuration_warning() const { + parent_visible = nullptr; - if (is_visible_in_tree()) { - return TTR("Popups will hide by default unless you call popup() or any of the popup*() functions. Making them visible for editing is fine, but they will hide upon running."); - } + set_wrap_controls(true); + set_visible(false); + set_transient(true); + set_flag(FLAG_BORDERLESS, true); + set_flag(FLAG_RESIZE_DISABLED, true); - return String(); + connect("window_input", callable_mp(this, &Popup::_input_from_window)); } Popup::~Popup() { } -Size2 PopupPanel::get_minimum_size() const { +Size2 PopupPanel::_get_contents_minimum_size() const { - Ref<StyleBox> p = get_stylebox("panel"); + Ref<StyleBox> p = get_theme_stylebox("panel", get_class_name()); Size2 ms; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) + if (!c || c == panel) continue; if (c->is_set_as_toplevel()) @@ -268,7 +172,7 @@ Size2 PopupPanel::get_minimum_size() const { void PopupPanel::_update_child_rects() { - Ref<StyleBox> p = get_stylebox("panel"); + Ref<StyleBox> p = get_theme_stylebox("panel", get_class_name()); Vector2 cpos(p->get_offset()); Vector2 csize(get_size() - p->get_minimum_size()); @@ -281,24 +185,32 @@ void PopupPanel::_update_child_rects() { if (c->is_set_as_toplevel()) continue; - c->set_position(cpos); - c->set_size(csize); + if (c == panel) { + c->set_position(Vector2()); + c->set_size(get_size()); + } else { + c->set_position(cpos); + c->set_size(csize); + } } } void PopupPanel::_notification(int p_what) { - if (p_what == NOTIFICATION_DRAW) { - - get_stylebox("panel")->draw(get_canvas_item(), Rect2(Point2(), get_size())); - } else if (p_what == NOTIFICATION_READY) { + if (p_what == NOTIFICATION_THEME_CHANGED) { + panel->add_theme_style_override("panel", get_theme_stylebox("panel", get_class_name())); + } else if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_ENTER_TREE) { + panel->add_theme_style_override("panel", get_theme_stylebox("panel", get_class_name())); _update_child_rects(); - } else if (p_what == NOTIFICATION_RESIZED) { + } else if (p_what == NOTIFICATION_WM_SIZE_CHANGED) { _update_child_rects(); } } PopupPanel::PopupPanel() { + + panel = memnew(Panel); + add_child(panel); } diff --git a/scene/gui/popup.h b/scene/gui/popup.h index ff472170b3..6cd2b4028f 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -31,44 +31,26 @@ #ifndef POPUP_H #define POPUP_H -#include "scene/gui/control.h" +#include "scene/main/window.h" -class Popup : public Control { +class Popup : public Window { - GDCLASS(Popup, Control); + GDCLASS(Popup, Window); - bool exclusive; - bool popped_up; + Window *parent_visible; -private: - void _popup(const Rect2 &p_bounds = Rect2(), const bool p_centered = false); + void _input_from_window(const Ref<InputEvent> &p_event); + void _parent_focused(); protected: - virtual void _post_popup() {} + void _close_pressed(); + virtual Rect2i _popup_adjust_rect() const; - void _gui_input(Ref<InputEvent> p_event); void _notification(int p_what); - virtual void _fix_size(); static void _bind_methods(); public: - enum { - NOTIFICATION_POST_POPUP = 80, - NOTIFICATION_POPUP_HIDE = 81 - }; - - void set_exclusive(bool p_exclusive); - bool is_exclusive() const; - - void popup_centered_ratio(float p_screen_ratio = 0.75); - void popup_centered(const Size2 &p_size = Size2()); - void popup_centered_minsize(const Size2 &p_minsize = Size2()); void set_as_minsize(); - void popup_centered_clamped(const Size2 &p_size = Size2(), float p_fallback_ratio = 0.75); - virtual void popup(const Rect2 &p_bounds = Rect2()); - - virtual String get_configuration_warning() const; - Popup(); ~Popup(); }; @@ -77,13 +59,16 @@ class PopupPanel : public Popup { GDCLASS(PopupPanel, Popup); + Panel *panel; + protected: void _update_child_rects(); void _notification(int p_what); + virtual Size2 _get_contents_minimum_size() const; + public: void set_child_rect(Control *p_child); - virtual Size2 get_minimum_size() const; PopupPanel(); }; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index e75dadd5e0..c096dc94cb 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -30,11 +30,12 @@ #include "popup_menu.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/print_string.h" #include "core/translation.h" +#include "scene/gui/control.h" String PopupMenu::_get_accel_text(int p_item) const { @@ -47,18 +48,18 @@ String PopupMenu::_get_accel_text(int p_item) const { return String(); } -Size2 PopupMenu::get_minimum_size() const { +Size2 PopupMenu::_get_contents_minimum_size() const { - int vseparation = get_constant("vseparation"); - int hseparation = get_constant("hseparation"); + int vseparation = get_theme_constant("vseparation"); + int hseparation = get_theme_constant("hseparation"); - Size2 minsize = get_stylebox("panel")->get_minimum_size(); - Ref<Font> font = get_font("font"); + Size2 minsize = get_theme_stylebox("panel")->get_minimum_size(); + Ref<Font> font = get_theme_font("font"); float max_w = 0; float icon_w = 0; int font_h = font->get_height(); - int check_w = MAX(get_icon("checked")->get_width(), get_icon("radio_checked")->get_width()) + hseparation; + int check_w = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation; int accel_max_w = 0; bool has_check = false; @@ -93,7 +94,7 @@ Size2 PopupMenu::get_minimum_size() const { } if (items[i].submenu != "") - size.width += get_icon("submenu")->get_width(); + size.width += get_theme_icon("submenu")->get_width(); max_w = MAX(max_w, size.width); @@ -112,15 +113,15 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { if (p_over.x < 0 || p_over.x >= get_size().width) return -1; - Ref<StyleBox> style = get_stylebox("panel"); + Ref<StyleBox> style = get_theme_stylebox("panel"); Point2 ofs = style->get_offset(); if (ofs.y > p_over.y) return -1; - Ref<Font> font = get_font("font"); - int vseparation = get_constant("vseparation"); + Ref<Font> font = get_theme_font("font"); + int vseparation = get_theme_constant("vseparation"); float font_h = font->get_height(); for (int i = 0; i < items.size(); i++) { @@ -152,27 +153,27 @@ void PopupMenu::_activate_submenu(int over) { ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[over].submenu + "."); Popup *pm = Object::cast_to<Popup>(n); ERR_FAIL_COND_MSG(!pm, "Item subnode is not a Popup: " + items[over].submenu + "."); - if (pm->is_visible_in_tree()) + if (pm->is_visible()) return; //already visible! - Point2 p = get_global_position(); + Point2 p = get_position(); Rect2 pr(p, get_size()); - Ref<StyleBox> style = get_stylebox("panel"); + Ref<StyleBox> style = get_theme_stylebox("panel"); - Point2 pos = p + Point2(get_size().width, items[over]._ofs_cache - style->get_offset().y) * get_global_transform().get_scale(); + Point2 pos = p + Point2(get_size().width, items[over]._ofs_cache - style->get_offset().y); Size2 size = pm->get_size(); // fix pos - if (pos.x + size.width > get_viewport_rect().size.width) + if (pos.x + size.width > get_parent_rect().size.width) pos.x = p.x - size.width; pm->set_position(pos); - pm->set_scale(get_global_transform().get_scale()); + // pm->set_scale(get_global_transform().get_scale()); pm->popup(); PopupMenu *pum = Object::cast_to<PopupMenu>(pm); if (pum) { - pr.position -= pum->get_global_position(); + pr.position -= pum->get_position(); pum->clear_autohide_areas(); pum->add_autohide_area(Rect2(pr.position.x, pr.position.y, pr.size.x, items[over]._ofs_cache)); if (over < items.size() - 1) { @@ -184,6 +185,9 @@ void PopupMenu::_activate_submenu(int over) { void PopupMenu::_submenu_timeout() { + //if (!has_focus()) { + // return; //do not activate if not has focus + //} if (mouse_over == submenu_over) _activate_submenu(mouse_over); @@ -192,20 +196,27 @@ void PopupMenu::_submenu_timeout() { void PopupMenu::_scroll(float p_factor, const Point2 &p_over) { - int vseparation = get_constant("vseparation"); - Ref<Font> font = get_font("font"); + int vseparation = get_theme_constant("vseparation"); + Ref<Font> font = get_theme_font("font"); - float dy = (vseparation + font->get_height()) * 3 * p_factor * get_global_transform().get_scale().y; + Rect2 visible_rect = get_usable_parent_rect(); + + int dy = (vseparation + font->get_height()) * 3 * p_factor; if (dy > 0) { - const float global_top = get_global_position().y; - const float limit = global_top < 0 ? -global_top : 0; + const float global_top = get_position().y; + const float limit = global_top < visible_rect.position.y ? visible_rect.position.y - global_top : 0; dy = MIN(dy, limit); } else if (dy < 0) { - const float global_bottom = get_global_position().y + get_size().y * get_global_transform().get_scale().y; - const float viewport_height = get_viewport_rect().size.y; + const float global_bottom = get_position().y + get_size().y; + const float viewport_height = visible_rect.position.y + visible_rect.size.y; const float limit = global_bottom > viewport_height ? global_bottom - viewport_height : 0; dy = -MIN(-dy, limit); } + + if (dy == 0) { + return; + } + set_position(get_position() + Vector2(0, dy)); Ref<InputEventMouseMotion> ie; @@ -231,8 +242,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { mouse_over = i; emit_signal("id_focused", i); - update(); - accept_event(); + control->update(); + set_input_as_handled(); break; } } @@ -251,8 +262,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { mouse_over = i; emit_signal("id_focused", i); - update(); - accept_event(); + control->update(); + set_input_as_handled(); break; } } @@ -261,13 +272,13 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { Node *n = get_parent(); if (n && Object::cast_to<PopupMenu>(n)) { hide(); - accept_event(); + set_input_as_handled(); } } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) { _activate_submenu(mouse_over); - accept_event(); + set_input_as_handled(); } } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { @@ -278,7 +289,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { } else { activate_item(mouse_over); } - accept_event(); + set_input_as_handled(); } } @@ -294,15 +305,11 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { case BUTTON_WHEEL_DOWN: { - if (get_global_position().y + get_size().y * get_global_transform().get_scale().y > get_viewport_rect().size.y) { - _scroll(-b->get_factor(), b->get_position()); - } + _scroll(-b->get_factor(), b->get_position()); } break; case BUTTON_WHEEL_UP: { - if (get_global_position().y < 0) { - _scroll(b->get_factor(), b->get_position()); - } + _scroll(b->get_factor(), b->get_position()); } break; default: { // Allow activating item by releasing the LMB or any that was down when the popup appeared @@ -338,7 +345,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { } } - //update(); + //control->update(); } Ref<InputEventMouseMotion> m = p_event; @@ -354,7 +361,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) { if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) { - call_deferred("hide"); + + _close_pressed(); return; } } @@ -364,7 +372,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { if (id < 0) { mouse_over = -1; - update(); + control->update(); return; } @@ -375,15 +383,13 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { if (over != mouse_over) { mouse_over = over; - update(); + control->update(); } } Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { - if (get_global_position().y + get_size().y > get_viewport_rect().size.y || get_global_position().y < 0) { - _scroll(-pan_gesture->get_delta().y, pan_gesture->get_position()); - } + _scroll(-pan_gesture->get_delta().y, pan_gesture->get_position()); } Ref<InputEventKey> k = p_event; @@ -416,218 +422,227 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { if (items[i].text.findn(search_string) == 0) { mouse_over = i; emit_signal("id_focused", i); - update(); - accept_event(); + control->update(); + set_input_as_handled(); break; } } } } -bool PopupMenu::has_point(const Point2 &p_point) const { +void PopupMenu::_draw() { - if (parent_rect.has_point(p_point)) - return true; - for (const List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) { + RID ci = control->get_canvas_item(); + Size2 size = get_size(); - if (E->get().has_point(p_point)) - return true; - } + Ref<StyleBox> style = get_theme_stylebox("panel"); + Ref<StyleBox> hover = get_theme_stylebox("hover"); + Ref<Font> font = get_theme_font("font"); + // In Item::checkable_type enum order (less the non-checkable member) + Ref<Texture2D> check[] = { get_theme_icon("checked"), get_theme_icon("radio_checked") }; + Ref<Texture2D> uncheck[] = { get_theme_icon("unchecked"), get_theme_icon("radio_unchecked") }; + Ref<Texture2D> submenu = get_theme_icon("submenu"); + Ref<StyleBox> separator = get_theme_stylebox("separator"); + Ref<StyleBox> labeled_separator_left = get_theme_stylebox("labeled_separator_left"); + Ref<StyleBox> labeled_separator_right = get_theme_stylebox("labeled_separator_right"); - return Control::has_point(p_point); -} - -void PopupMenu::_notification(int p_what) { + style->draw(ci, Rect2(Point2(), get_size())); + Point2 ofs = style->get_offset(); + int vseparation = get_theme_constant("vseparation"); + int hseparation = get_theme_constant("hseparation"); + Color font_color = get_theme_color("font_color"); + Color font_color_disabled = get_theme_color("font_color_disabled"); + Color font_color_accel = get_theme_color("font_color_accel"); + Color font_color_hover = get_theme_color("font_color_hover"); + float font_h = font->get_height(); - switch (p_what) { + // Add the check and the wider icon to the offset of all items. + float icon_ofs = 0.0; + bool has_check = false; + for (int i = 0; i < items.size(); i++) { - case NOTIFICATION_ENTER_TREE: { + if (!items[i].icon.is_null()) + icon_ofs = MAX(items[i].icon->get_size().width, icon_ofs); - PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent()); - if (pm) { - // Inherit submenu's popup delay time from parent menu - float pm_delay = pm->get_submenu_popup_delay(); - set_submenu_popup_delay(pm_delay); - } - } break; - case NOTIFICATION_TRANSLATION_CHANGED: { + if (items[i].checkable_type) + has_check = true; + } + if (icon_ofs > 0.0) + icon_ofs += hseparation; - for (int i = 0; i < items.size(); i++) { - items.write[i].xl_text = tr(items[i].text); - } + float check_ofs = 0.0; + if (has_check) + check_ofs = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation; - minimum_size_changed(); - update(); - } break; - case NOTIFICATION_DRAW: { - - RID ci = get_canvas_item(); - Size2 size = get_size(); - - Ref<StyleBox> style = get_stylebox("panel"); - Ref<StyleBox> hover = get_stylebox("hover"); - Ref<Font> font = get_font("font"); - // In Item::checkable_type enum order (less the non-checkable member) - Ref<Texture2D> check[] = { get_icon("checked"), get_icon("radio_checked") }; - Ref<Texture2D> uncheck[] = { get_icon("unchecked"), get_icon("radio_unchecked") }; - Ref<Texture2D> submenu = get_icon("submenu"); - Ref<StyleBox> separator = get_stylebox("separator"); - Ref<StyleBox> labeled_separator_left = get_stylebox("labeled_separator_left"); - Ref<StyleBox> labeled_separator_right = get_stylebox("labeled_separator_right"); - - style->draw(ci, Rect2(Point2(), get_size())); - Point2 ofs = style->get_offset(); - int vseparation = get_constant("vseparation"); - int hseparation = get_constant("hseparation"); - Color font_color = get_color("font_color"); - Color font_color_disabled = get_color("font_color_disabled"); - Color font_color_accel = get_color("font_color_accel"); - Color font_color_hover = get_color("font_color_hover"); - float font_h = font->get_height(); - - // Add the check and the wider icon to the offset of all items. - float icon_ofs = 0.0; - bool has_check = false; - for (int i = 0; i < items.size(); i++) { + for (int i = 0; i < items.size(); i++) { - if (!items[i].icon.is_null()) - icon_ofs = MAX(items[i].icon->get_size().width, icon_ofs); + if (i > 0) + ofs.y += vseparation; + Point2 item_ofs = ofs; + Size2 icon_size; + float h; - if (items[i].checkable_type) - has_check = true; - } - if (icon_ofs > 0.0) - icon_ofs += hseparation; + if (!items[i].icon.is_null()) { - float check_ofs = 0.0; - if (has_check) - check_ofs = MAX(get_icon("checked")->get_width(), get_icon("radio_checked")->get_width()) + hseparation; + icon_size = items[i].icon->get_size(); + h = MAX(icon_size.height, font_h); + } else { - for (int i = 0; i < items.size(); i++) { + h = font_h; + } - if (i > 0) - ofs.y += vseparation; - Point2 item_ofs = ofs; - Size2 icon_size; - float h; + if (i == mouse_over) { - if (!items[i].icon.is_null()) { + hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation))); + } - icon_size = items[i].icon->get_size(); - h = MAX(icon_size.height, font_h); - } else { + String text = items[i].xl_text; - h = font_h; + item_ofs.x += items[i].h_ofs; + if (items[i].separator) { + + int sep_h = separator->get_center_size().height + separator->get_minimum_size().height; + if (text != String()) { + int ss = font->get_string_size(text).width; + int center = (get_size().width) / 2; + int l = center - ss / 2; + int r = center + ss / 2; + if (l > item_ofs.x) { + labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, l - item_ofs.x), sep_h))); } - - if (i == mouse_over) { - - hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation))); + if (r < get_size().width - style->get_margin(MARGIN_RIGHT)) { + labeled_separator_right->draw(ci, Rect2(Point2(r, item_ofs.y + Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, get_size().width - style->get_margin(MARGIN_RIGHT) - r), sep_h))); } + } else { + separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(get_size().width - style->get_minimum_size().width, sep_h))); + } + } - String text = items[i].xl_text; + Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1); - item_ofs.x += items[i].h_ofs; - if (items[i].separator) { + if (items[i].checkable_type) { + Texture2D *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr(); + icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)), icon_color); + } - int sep_h = separator->get_center_size().height + separator->get_minimum_size().height; - if (text != String()) { - int ss = font->get_string_size(text).width; - int center = (get_size().width) / 2; - int l = center - ss / 2; - int r = center + ss / 2; - if (l > item_ofs.x) { - labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, l - item_ofs.x), sep_h))); - } - if (r < get_size().width - style->get_margin(MARGIN_RIGHT)) { - labeled_separator_right->draw(ci, Rect2(Point2(r, item_ofs.y + Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, get_size().width - style->get_margin(MARGIN_RIGHT) - r), sep_h))); - } - } else { - separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(get_size().width - style->get_minimum_size().width, sep_h))); - } - } + if (!items[i].icon.is_null()) { + items[i].icon->draw(ci, item_ofs + Size2(check_ofs, 0) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color); + } - Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1); + if (items[i].submenu != "") { + submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color); + } - if (items[i].checkable_type) { - Texture2D *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr(); - icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)), icon_color); - } + item_ofs.y += font->get_ascent(); + if (items[i].separator) { - if (!items[i].icon.is_null()) { - items[i].icon->draw(ci, item_ofs + Size2(check_ofs, 0) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color); - } + if (text != String()) { + int center = (get_size().width - font->get_string_size(text).width) / 2; + font->draw(ci, Point2(center, item_ofs.y + Math::floor((h - font_h) / 2.0)), text, font_color_disabled); + } + } else { - if (items[i].submenu != "") { - submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color); - } + item_ofs.x += icon_ofs + check_ofs; + font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, items[i].disabled ? font_color_disabled : (i == mouse_over ? font_color_hover : font_color)); + } - item_ofs.y += font->get_ascent(); - if (items[i].separator) { + if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { + //accelerator + String text2 = _get_accel_text(i); + item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text2).width; + font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text2, i == mouse_over ? font_color_hover : font_color_accel); + } - if (text != String()) { - int center = (get_size().width - font->get_string_size(text).width) / 2; - font->draw(ci, Point2(center, item_ofs.y + Math::floor((h - font_h) / 2.0)), text, font_color_disabled); - } - } else { + items.write[i]._ofs_cache = ofs.y; - item_ofs.x += icon_ofs + check_ofs; - font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, items[i].disabled ? font_color_disabled : (i == mouse_over ? font_color_hover : font_color)); - } + ofs.y += h; + } +} - if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) { - //accelerator - String text2 = _get_accel_text(i); - item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text2).width; - font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text2, i == mouse_over ? font_color_hover : font_color_accel); - } +void PopupMenu::_notification(int p_what) { + + switch (p_what) { - items.write[i]._ofs_cache = ofs.y; + case NOTIFICATION_ENTER_TREE: { - ofs.y += h; + PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent()); + if (pm) { + // Inherit submenu's popup delay time from parent menu + float pm_delay = pm->get_submenu_popup_delay(); + set_submenu_popup_delay(pm_delay); } } break; - case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_TRANSLATION_CHANGED: { - if (hide_on_window_lose_focus) - hide(); + for (int i = 0; i < items.size(); i++) { + items.write[i].xl_text = tr(items[i].text); + } + + child_controls_changed(); + control->update(); } break; - case NOTIFICATION_MOUSE_ENTER: { + case NOTIFICATION_WM_MOUSE_ENTER: { - grab_focus(); + //grab_focus(); } break; - case NOTIFICATION_MOUSE_EXIT: { + case NOTIFICATION_WM_MOUSE_EXIT: { if (mouse_over >= 0 && (items[mouse_over].submenu == "" || submenu_over != -1)) { mouse_over = -1; - update(); + control->update(); } } break; case NOTIFICATION_POST_POPUP: { - initial_button_mask = Input::get_singleton()->get_mouse_button_mask(); + initial_button_mask = InputFilter::get_singleton()->get_mouse_button_mask(); during_grabbed_click = (bool)initial_button_mask; } break; - case NOTIFICATION_POPUP_HIDE: { + case NOTIFICATION_WM_SIZE_CHANGED: { - if (mouse_over >= 0) { - mouse_over = -1; - update(); + } break; + case NOTIFICATION_INTERNAL_PROCESS: { + //only used when using operating system windows + if (get_window_id() != DisplayServer::INVALID_WINDOW_ID && autohide_areas.size()) { + Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position(); + mouse_pos -= get_position(); + + for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) { + + if (!Rect2(Point2(), get_size()).has_point(mouse_pos) && E->get().has_point(mouse_pos)) { + _close_pressed(); + return; + } + } } + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { - for (int i = 0; i < items.size(); i++) { - if (items[i].submenu == "") - continue; + if (!is_visible()) { + if (mouse_over >= 0) { + mouse_over = -1; + control->update(); + } + + for (int i = 0; i < items.size(); i++) { + if (items[i].submenu == "") + continue; - Node *n = get_node(items[i].submenu); - if (!n) - continue; + Node *n = get_node(items[i].submenu); + if (!n) + continue; - PopupMenu *pm = Object::cast_to<PopupMenu>(n); - if (!pm || !pm->is_visible()) - continue; + PopupMenu *pm = Object::cast_to<PopupMenu>(n); + if (!pm || !pm->is_visible()) + continue; - pm->hide(); + pm->hide(); + } + + set_process_internal(false); + } else { + if (get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + set_process_internal(true); + } } } break; } @@ -648,8 +663,8 @@ void PopupMenu::add_item(const String &p_label, int p_id, uint32_t p_accel) { Item item; ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { @@ -658,8 +673,8 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.icon = p_icon; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel) { @@ -668,8 +683,8 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { @@ -679,8 +694,8 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String & item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p_accel) { @@ -689,8 +704,8 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel); item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) { @@ -700,8 +715,8 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id, uint32_t p_accel) { @@ -711,8 +726,8 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int item.max_states = p_max_states; item.state = p_default_state; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } #define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \ @@ -729,8 +744,8 @@ void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_g Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { @@ -739,8 +754,8 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortC ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.icon = p_icon; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { @@ -749,8 +764,8 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bo ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { @@ -760,8 +775,8 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref< item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { @@ -770,8 +785,8 @@ void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { @@ -781,8 +796,8 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons item.icon = p_icon; item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_id) { @@ -793,8 +808,8 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, item.id = p_id == -1 ? items.size() : p_id; item.submenu = p_submenu; items.push_back(item); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } #undef ITEM_SETUP_WITH_ACCEL @@ -808,16 +823,16 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) { items.write[p_idx].text = p_text; items.write[p_idx].xl_text = tr(p_text); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].icon = p_icon; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_checked(int p_idx, bool p_checked) { @@ -825,16 +840,16 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) { items.write[p_idx].checked = p_checked; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_id(int p_idx, int p_id) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].id = p_id; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { @@ -842,40 +857,40 @@ void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].accel = p_accel; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].metadata = p_meta; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].disabled = p_disabled; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].submenu = p_submenu; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::toggle_item_checked(int p_idx) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].checked = !items[p_idx].checked; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } String PopupMenu::get_item_text(int p_idx) const { @@ -968,7 +983,7 @@ void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].separator = p_separator; - update(); + control->update(); } bool PopupMenu::is_item_separator(int p_idx) const { @@ -980,21 +995,21 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE; - update(); + control->update(); } void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE; - update(); + control->update(); } void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].tooltip = p_tooltip; - update(); + control->update(); } void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global) { @@ -1009,29 +1024,29 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bo _ref_shortcut(items[p_idx].shortcut); } - update(); + control->update(); } void PopupMenu::set_item_h_offset(int p_idx, int p_offset) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].h_ofs = p_offset; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::set_item_multistate(int p_idx, int p_state) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].state = p_state; - update(); + control->update(); } void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, items.size()); items.write[p_idx].shortcut_is_disabled = p_disabled; - update(); + control->update(); } void PopupMenu::toggle_item_multistate(int p_idx) { @@ -1045,7 +1060,7 @@ void PopupMenu::toggle_item_multistate(int p_idx) { if (items.write[p_idx].max_states <= items[p_idx].state) items.write[p_idx].state = 0; - update(); + control->update(); } bool PopupMenu::is_item_checkable(int p_idx) const { @@ -1177,8 +1192,8 @@ void PopupMenu::remove_item(int p_idx) { } items.remove(p_idx); - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } void PopupMenu::add_separator(const String &p_text) { @@ -1191,7 +1206,7 @@ void PopupMenu::add_separator(const String &p_text) { sep.xl_text = tr(p_text); } items.push_back(sep); - update(); + control->update(); } void PopupMenu::clear() { @@ -1203,8 +1218,8 @@ void PopupMenu::clear() { } items.clear(); mouse_over = -1; - update(); - minimum_size_changed(); + control->update(); + child_controls_changed(); } Array PopupMenu::_get_items() const { @@ -1345,16 +1360,6 @@ bool PopupMenu::get_allow_search() const { return allow_search; } -void PopupMenu::set_hide_on_window_lose_focus(bool p_enabled) { - - hide_on_window_lose_focus = p_enabled; -} - -bool PopupMenu::is_hide_on_window_lose_focus() const { - - return hide_on_window_lose_focus; -} - String PopupMenu::get_tooltip(const Point2 &p_pos) const { int over = _get_mouse_over(p_pos); @@ -1387,6 +1392,14 @@ void PopupMenu::clear_autohide_areas() { autohide_areas.clear(); } +void PopupMenu::take_mouse_focus() { + ERR_FAIL_COND(!is_inside_tree()); + + if (get_parent()) { + get_parent()->get_viewport()->pass_mouse_focus_to(this, control); + } +} + void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input); @@ -1466,9 +1479,6 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_submenu_popup_delay", "seconds"), &PopupMenu::set_submenu_popup_delay); ClassDB::bind_method(D_METHOD("get_submenu_popup_delay"), &PopupMenu::get_submenu_popup_delay); - ClassDB::bind_method(D_METHOD("set_hide_on_window_lose_focus", "enable"), &PopupMenu::set_hide_on_window_lose_focus); - ClassDB::bind_method(D_METHOD("is_hide_on_window_lose_focus"), &PopupMenu::is_hide_on_window_lose_focus); - ClassDB::bind_method(D_METHOD("set_allow_search", "allow"), &PopupMenu::set_allow_search); ClassDB::bind_method(D_METHOD("get_allow_search"), &PopupMenu::get_allow_search); @@ -1486,7 +1496,6 @@ void PopupMenu::_bind_methods() { void PopupMenu::popup(const Rect2 &p_bounds) { - grab_click_focus(); moved = Vector2(); invalidated_click = true; Popup::popup(p_bounds); @@ -1494,6 +1503,13 @@ void PopupMenu::popup(const Rect2 &p_bounds) { PopupMenu::PopupMenu() { + control = memnew(Control); + add_child(control); + + control->set_anchors_and_margins_preset(Control::PRESET_WIDE); + connect("window_input", callable_mp(this, &PopupMenu::_gui_input)); + control->connect("draw", callable_mp(this, &PopupMenu::_draw)); + mouse_over = -1; submenu_over = -1; initial_button_mask = 0; @@ -1503,12 +1519,9 @@ PopupMenu::PopupMenu() { search_time_msec = 0; search_string = ""; - set_focus_mode(FOCUS_ALL); - set_as_toplevel(true); set_hide_on_item_selection(true); set_hide_on_checkable_item_selection(true); set_hide_on_multistate_item_selection(false); - set_hide_on_window_lose_focus(true); submenu_timer = memnew(Timer); submenu_timer->set_wait_time(0.3); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index a3a858cfde..2eef1f009d 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -32,6 +32,7 @@ #define POPUP_MENU_H #include "scene/gui/popup.h" +#include "scene/gui/shortcut.h" class PopupMenu : public Popup { @@ -87,7 +88,7 @@ class PopupMenu : public Popup { Rect2 parent_rect; String _get_accel_text(int p_item) const; int _get_mouse_over(const Point2 &p_over) const; - virtual Size2 get_minimum_size() const; + virtual Size2 _get_contents_minimum_size() const; void _scroll(float p_factor, const Point2 &p_over); void _gui_input(const Ref<InputEvent> &p_event); void _activate_submenu(int over); @@ -97,7 +98,6 @@ class PopupMenu : public Popup { bool hide_on_item_selection; bool hide_on_checkable_item_selection; bool hide_on_multistate_item_selection; - bool hide_on_window_lose_focus; Vector2 moved; Array _get_items() const; @@ -112,9 +112,11 @@ class PopupMenu : public Popup { uint64_t search_time_msec; String search_string; -protected: - virtual bool has_point(const Point2 &p_point) const; + Control *control; + + void _draw(); +protected: friend class MenuButton; void _notification(int p_what); static void _bind_methods(); @@ -213,8 +215,7 @@ public: virtual void popup(const Rect2 &p_bounds = Rect2()); - void set_hide_on_window_lose_focus(bool p_enabled); - bool is_hide_on_window_lose_focus() const; + void take_mouse_focus(); PopupMenu(); ~PopupMenu(); diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp index e11295d7e7..362c45453d 100644 --- a/scene/gui/progress_bar.cpp +++ b/scene/gui/progress_bar.cpp @@ -32,9 +32,9 @@ Size2 ProgressBar::get_minimum_size() const { - Ref<StyleBox> bg = get_stylebox("bg"); - Ref<StyleBox> fg = get_stylebox("fg"); - Ref<Font> font = get_font("font"); + Ref<StyleBox> bg = get_theme_stylebox("bg"); + Ref<StyleBox> fg = get_theme_stylebox("fg"); + Ref<Font> font = get_theme_font("font"); Size2 minimum_size = bg->get_minimum_size(); minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height); @@ -52,10 +52,10 @@ void ProgressBar::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<StyleBox> bg = get_stylebox("bg"); - Ref<StyleBox> fg = get_stylebox("fg"); - Ref<Font> font = get_font("font"); - Color font_color = get_color("font_color"); + Ref<StyleBox> bg = get_theme_stylebox("bg"); + Ref<StyleBox> fg = get_theme_stylebox("fg"); + Ref<Font> font = get_theme_font("font"); + Color font_color = get_theme_color("font_color"); draw_style_box(bg, Rect2(Point2(), get_size())); float r = get_as_ratio(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index e4651ef473..df28a4c12f 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -34,6 +34,7 @@ #include "core/os/keyboard.h" #include "core/os/os.h" #include "scene/scene_string_names.h" +#include "servers/display_server.h" #include "modules/modules_enabled.gen.h" #ifdef MODULE_REGEX_ENABLED @@ -142,7 +143,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) { } Rect2 RichTextLabel::_get_text_rect() { - Ref<StyleBox> style = get_stylebox("normal"); + Ref<StyleBox> style = get_theme_stylebox("normal"); return Rect2(style->get_offset(), get_size() - style->get_minimum_size()); } @@ -240,7 +241,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & l.space_caches.push_back(spaces); \ } \ line_wrapped = false; \ - y += line_height + get_constant(SceneStringNames::get_singleton()->line_separation); \ + y += line_height + get_theme_constant(SceneStringNames::get_singleton()->line_separation); \ line_height = 0; \ line_ascent = 0; \ line_descent = 0; \ @@ -305,8 +306,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & Color selection_bg; if (p_mode == PROCESS_DRAW) { - selection_fg = get_color("font_color_selected"); - selection_bg = get_color("selection_color"); + selection_fg = get_theme_color("font_color_selected"); + selection_bg = get_theme_color("selection_color"); } int rchar = 0; @@ -667,13 +668,13 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & lh = 0; ItemTable *table = static_cast<ItemTable *>(it); - int hseparation = get_constant("table_hseparation"); - int vseparation = get_constant("table_vseparation"); + int hseparation = get_theme_constant("table_hseparation"); + int vseparation = get_theme_constant("table_vseparation"); Color ccolor = _find_color(table, p_base_color); Vector2 draw_ofs = Point2(wofs, y); - Color font_color_shadow = get_color("font_color_shadow"); - bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs2(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); + Color font_color_shadow = get_theme_color("font_color_shadow"); + bool use_outline = get_theme_constant("shadow_as_outline"); + Point2 shadow_ofs2(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y")); if (p_mode == PROCESS_CACHE) { @@ -987,11 +988,11 @@ void RichTextLabel::_notification(int p_what) { Size2 size = get_size(); Rect2 text_rect = _get_text_rect(); - draw_style_box(get_stylebox("normal"), Rect2(Point2(), size)); + draw_style_box(get_theme_stylebox("normal"), Rect2(Point2(), size)); if (has_focus()) { VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); - draw_style_box(get_stylebox("focus"), Rect2(Point2(), size)); + draw_style_box(get_theme_stylebox("focus"), Rect2(Point2(), size)); VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); } @@ -1012,11 +1013,11 @@ void RichTextLabel::_notification(int p_what) { if (from_line >= main->lines.size()) break; //nothing to draw int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs; - Ref<Font> base_font = get_font("normal_font"); - Color base_color = get_color("default_color"); - Color font_color_shadow = get_color("font_color_shadow"); - bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); + Ref<Font> base_font = get_theme_font("normal_font"); + Color base_color = get_theme_color("default_color"); + Color font_color_shadow = get_theme_color("font_color_shadow"); + bool use_outline = get_theme_constant("shadow_as_outline"); + Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y")); visible_line_count = 0; while (y < size.height && from_line < main->lines.size()) { @@ -1043,9 +1044,9 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item Rect2 text_rect = _get_text_rect(); int ofs = vscroll->get_value(); - Color font_color_shadow = get_color("font_color_shadow"); - bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); + Color font_color_shadow = get_theme_color("font_color_shadow"); + bool use_outline = get_theme_constant("shadow_as_outline"); + Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y")); //todo, change to binary search int from_line = 0; @@ -1061,8 +1062,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item return; int y = (p_frame->lines[from_line].height_accum_cache - p_frame->lines[from_line].height_cache) - ofs; - Ref<Font> base_font = get_font("normal_font"); - Color base_color = get_color("default_color"); + Ref<Font> base_font = get_theme_font("normal_font"); + Color base_color = get_theme_color("default_color"); while (y < text_rect.get_size().height && from_line < p_frame->lines.size()) { @@ -1227,14 +1228,14 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { case KEY_UP: { if (vscroll->is_visible_in_tree()) { - vscroll->set_value(vscroll->get_value() - get_font("normal_font")->get_height()); + vscroll->set_value(vscroll->get_value() - get_theme_font("normal_font")->get_height()); handled = true; } } break; case KEY_DOWN: { if (vscroll->is_visible_in_tree()) { - vscroll->set_value(vscroll->get_value() + get_font("normal_font")->get_height()); + vscroll->set_value(vscroll->get_value() + get_theme_font("normal_font")->get_height()); handled = true; } } break; @@ -1525,11 +1526,11 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { size.width = fixed_width; } Rect2 text_rect = _get_text_rect(); - Color font_color_shadow = get_color("font_color_shadow"); - bool use_outline = get_constant("shadow_as_outline"); - Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y")); + Color font_color_shadow = get_theme_color("font_color_shadow"); + bool use_outline = get_theme_constant("shadow_as_outline"); + Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y")); - Ref<Font> base_font = get_font("normal_font"); + Ref<Font> base_font = get_theme_font("normal_font"); for (int i = p_frame->first_invalid_line; i < p_frame->lines.size(); i++) { @@ -1544,7 +1545,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { int total_height = 0; if (p_frame->lines.size()) - total_height = p_frame->lines[p_frame->lines.size() - 1].height_accum_cache + get_stylebox("normal")->get_minimum_size().height; + total_height = p_frame->lines[p_frame->lines.size() - 1].height_accum_cache + get_theme_stylebox("normal")->get_minimum_size().height; main->first_invalid_line = p_frame->lines.size(); @@ -1646,6 +1647,10 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline) p_item->line = current_frame->lines.size() - 1; _invalidate_current_line(current_frame); + + if (fixed_width != -1) { + minimum_size_changed(); + } } void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_subitem_line) { @@ -1758,35 +1763,35 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) { } void RichTextLabel::push_normal() { - Ref<Font> normal_font = get_font("normal_font"); + Ref<Font> normal_font = get_theme_font("normal_font"); ERR_FAIL_COND(normal_font.is_null()); push_font(normal_font); } void RichTextLabel::push_bold() { - Ref<Font> bold_font = get_font("bold_font"); + Ref<Font> bold_font = get_theme_font("bold_font"); ERR_FAIL_COND(bold_font.is_null()); push_font(bold_font); } void RichTextLabel::push_bold_italics() { - Ref<Font> bold_italics_font = get_font("bold_italics_font"); + Ref<Font> bold_italics_font = get_theme_font("bold_italics_font"); ERR_FAIL_COND(bold_italics_font.is_null()); push_font(bold_italics_font); } void RichTextLabel::push_italics() { - Ref<Font> italics_font = get_font("italics_font"); + Ref<Font> italics_font = get_theme_font("italics_font"); ERR_FAIL_COND(italics_font.is_null()); push_font(italics_font); } void RichTextLabel::push_mono() { - Ref<Font> mono_font = get_font("mono_font"); + Ref<Font> mono_font = get_theme_font("mono_font"); ERR_FAIL_COND(mono_font.is_null()); push_font(mono_font); @@ -1967,6 +1972,10 @@ void RichTextLabel::clear() { selection.click = NULL; selection.active = false; current_idx = 1; + + if (fixed_width != -1) { + minimum_size_changed(); + } } void RichTextLabel::set_tab_size(int p_spaces) { @@ -2044,13 +2053,13 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) { int pos = 0; List<String> tag_stack; - Ref<Font> normal_font = get_font("normal_font"); - Ref<Font> bold_font = get_font("bold_font"); - Ref<Font> italics_font = get_font("italics_font"); - Ref<Font> bold_italics_font = get_font("bold_italics_font"); - Ref<Font> mono_font = get_font("mono_font"); + Ref<Font> normal_font = get_theme_font("normal_font"); + Ref<Font> bold_font = get_theme_font("bold_font"); + Ref<Font> italics_font = get_theme_font("italics_font"); + Ref<Font> bold_italics_font = get_theme_font("bold_italics_font"); + Ref<Font> mono_font = get_theme_font("mono_font"); - Color base_color = get_color("default_color"); + Color base_color = get_theme_color("default_color"); int indent_level = 0; @@ -2518,7 +2527,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p _validate_line_caches(main); - int fh = _find_font(t).is_valid() ? _find_font(t)->get_height() : get_font("normal_font")->get_height(); + int fh = _find_font(t).is_valid() ? _find_font(t)->get_height() : get_theme_font("normal_font")->get_height(); float offset = 0; @@ -2584,7 +2593,7 @@ void RichTextLabel::selection_copy() { } if (text != "") { - OS::get_singleton()->set_clipboard(text); + DisplayServer::get_singleton()->clipboard_set(text); } } @@ -2692,7 +2701,7 @@ void RichTextLabel::install_effect(const Variant effect) { int RichTextLabel::get_content_height() { int total_height = 0; if (main->lines.size()) - total_height = main->lines[main->lines.size() - 1].height_accum_cache + get_stylebox("normal")->get_minimum_size().height; + total_height = main->lines[main->lines.size() - 1].height_accum_cache + get_theme_stylebox("normal")->get_minimum_size().height; return total_height; } diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index fef5e00984..5e9541730e 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -33,6 +33,7 @@ #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/print_string.h" +#include "scene/main/window.h" bool ScrollBar::focus_by_default = false; @@ -71,8 +72,8 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { if (b->is_pressed()) { double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x; - Ref<Texture2D> decr = get_icon("decrement"); - Ref<Texture2D> incr = get_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); + Ref<Texture2D> incr = get_theme_icon("increment"); double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width(); @@ -148,7 +149,7 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { if (drag.active) { double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x; - Ref<Texture2D> decr = get_icon("decrement"); + Ref<Texture2D> decr = get_theme_icon("decrement"); double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); ofs -= decr_size; @@ -159,8 +160,8 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { } else { double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x; - Ref<Texture2D> decr = get_icon("decrement"); - Ref<Texture2D> incr = get_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); + Ref<Texture2D> incr = get_theme_icon("increment"); double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width(); double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width(); @@ -233,17 +234,17 @@ void ScrollBar::_notification(int p_what) { RID ci = get_canvas_item(); - Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_icon("decrement_highlight") : get_icon("decrement"); - Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_icon("increment_highlight") : get_icon("increment"); - Ref<StyleBox> bg = has_focus() ? get_stylebox("scroll_focus") : get_stylebox("scroll"); + Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_theme_icon("decrement_highlight") : get_theme_icon("decrement"); + Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_theme_icon("increment_highlight") : get_theme_icon("increment"); + Ref<StyleBox> bg = has_focus() ? get_theme_stylebox("scroll_focus") : get_theme_stylebox("scroll"); Ref<StyleBox> grabber; if (drag.active) - grabber = get_stylebox("grabber_pressed"); + grabber = get_theme_stylebox("grabber_pressed"); else if (highlight == HIGHLIGHT_RANGE) - grabber = get_stylebox("grabber_highlight"); + grabber = get_theme_stylebox("grabber_highlight"); else - grabber = get_stylebox("grabber"); + grabber = get_theme_stylebox("grabber"); Point2 ofs; @@ -416,7 +417,7 @@ void ScrollBar::_notification(int p_what) { double ScrollBar::get_grabber_min_size() const { - Ref<StyleBox> grabber = get_stylebox("grabber"); + Ref<StyleBox> grabber = get_theme_stylebox("grabber"); Size2 gminsize = grabber->get_minimum_size() + grabber->get_center_size(); return (orientation == VERTICAL) ? gminsize.height : gminsize.width; } @@ -442,17 +443,17 @@ double ScrollBar::get_area_size() const { switch (orientation) { case VERTICAL: { double area = get_size().height; - area -= get_stylebox("scroll")->get_minimum_size().height; - area -= get_icon("increment")->get_height(); - area -= get_icon("decrement")->get_height(); + area -= get_theme_stylebox("scroll")->get_minimum_size().height; + area -= get_theme_icon("increment")->get_height(); + area -= get_theme_icon("decrement")->get_height(); area -= get_grabber_min_size(); return area; } break; case HORIZONTAL: { double area = get_size().width; - area -= get_stylebox("scroll")->get_minimum_size().width; - area -= get_icon("increment")->get_width(); - area -= get_icon("decrement")->get_width(); + area -= get_theme_stylebox("scroll")->get_minimum_size().width; + area -= get_theme_icon("increment")->get_width(); + area -= get_theme_icon("decrement")->get_width(); area -= get_grabber_min_size(); return area; } break; @@ -468,14 +469,14 @@ double ScrollBar::get_area_offset() const { if (orientation == VERTICAL) { - ofs += get_stylebox("hscroll")->get_margin(MARGIN_TOP); - ofs += get_icon("decrement")->get_height(); + ofs += get_theme_stylebox("hscroll")->get_margin(MARGIN_TOP); + ofs += get_theme_icon("decrement")->get_height(); } if (orientation == HORIZONTAL) { - ofs += get_stylebox("hscroll")->get_margin(MARGIN_LEFT); - ofs += get_icon("decrement")->get_width(); + ofs += get_theme_stylebox("hscroll")->get_margin(MARGIN_LEFT); + ofs += get_theme_icon("decrement")->get_width(); } return ofs; @@ -500,9 +501,9 @@ double ScrollBar::get_grabber_offset() const { Size2 ScrollBar::get_minimum_size() const { - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); - Ref<StyleBox> bg = get_stylebox("scroll"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); + Ref<StyleBox> bg = get_theme_stylebox("scroll"); Size2 minsize; if (orientation == VERTICAL) { @@ -559,8 +560,7 @@ void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) { drag_node_accum = Vector2(); last_drag_node_accum = Vector2(); drag_node_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0); - - drag_node_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_node_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())); drag_node_touching_deaccel = false; time_since_motion = 0; diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index c25a6d5a0c..fb17adf96e 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -30,7 +30,7 @@ #include "scroll_container.h" #include "core/os/os.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" bool ScrollContainer::clips_input() const { @@ -39,7 +39,7 @@ bool ScrollContainer::clips_input() const { Size2 ScrollContainer::get_minimum_size() const { - Ref<StyleBox> sb = get_stylebox("bg"); + Ref<StyleBox> sb = get_theme_stylebox("bg"); Size2 min_size; for (int i = 0; i < get_child_count(); i++) { @@ -129,7 +129,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) accept_event(); //accept event if scroll changed - if (!OS::get_singleton()->has_touchscreen_ui_hint()) + if (!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()))) return; if (mb->get_button_index() != BUTTON_LEFT) @@ -145,7 +145,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) { drag_accum = Vector2(); last_drag_accum = Vector2(); drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value()); - drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())); drag_touching_deaccel = false; beyond_deadzone = false; time_since_motion = 0; @@ -276,7 +276,7 @@ void ScrollContainer::_notification(int p_what) { Size2 size = get_size(); Point2 ofs; - Ref<StyleBox> sb = get_stylebox("bg"); + Ref<StyleBox> sb = get_theme_stylebox("bg"); size -= sb->get_minimum_size(); ofs += sb->get_offset(); @@ -323,7 +323,7 @@ void ScrollContainer::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<StyleBox> sb = get_stylebox("bg"); + Ref<StyleBox> sb = get_theme_stylebox("bg"); draw_style_box(sb, Rect2(Vector2(), get_size())); update_scrollbars(); @@ -404,7 +404,7 @@ void ScrollContainer::_notification(int p_what) { void ScrollContainer::update_scrollbars() { Size2 size = get_size(); - Ref<StyleBox> sb = get_stylebox("bg"); + Ref<StyleBox> sb = get_theme_stylebox("bg"); size -= sb->get_minimum_size(); Size2 hmin; diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp index 4635efb233..75c4b7cce9 100644 --- a/scene/gui/separator.cpp +++ b/scene/gui/separator.cpp @@ -34,9 +34,9 @@ Size2 Separator::get_minimum_size() const { Size2 ms(3, 3); if (orientation == VERTICAL) { - ms.x = get_constant("separation"); + ms.x = get_theme_constant("separation"); } else { // HORIZONTAL - ms.y = get_constant("separation"); + ms.y = get_theme_constant("separation"); } return ms; } @@ -48,7 +48,7 @@ void Separator::_notification(int p_what) { case NOTIFICATION_DRAW: { Size2i size = get_size(); - Ref<StyleBox> style = get_stylebox("separator"); + Ref<StyleBox> style = get_theme_stylebox("separator"); Size2i ssize = style->get_minimum_size() + style->get_center_size(); if (orientation == VERTICAL) { diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h index 59d3245db5..b22c3441c5 100644 --- a/scene/gui/shortcut.h +++ b/scene/gui/shortcut.h @@ -31,7 +31,7 @@ #ifndef SHORTCUT_H #define SHORTCUT_H -#include "core/os/input_event.h" +#include "core/input/input_event.h" #include "core/resource.h" class ShortCut : public Resource { diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 85887ef7b1..e47e2b869d 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -33,10 +33,10 @@ Size2 Slider::get_minimum_size() const { - Ref<StyleBox> style = get_stylebox("slider"); + Ref<StyleBox> style = get_theme_stylebox("slider"); Size2i ss = style->get_minimum_size() + style->get_center_size(); - Ref<Texture2D> grabber = get_icon("grabber"); + Ref<Texture2D> grabber = get_theme_icon("grabber"); Size2i rs = grabber->get_size(); if (orientation == HORIZONTAL) @@ -57,7 +57,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { if (mb->get_button_index() == BUTTON_LEFT) { if (mb->is_pressed()) { - Ref<Texture2D> grabber = get_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber"); + Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber"); grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x; double grab_width = (double)grabber->get_size().width; @@ -87,7 +87,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { if (grab.active) { Size2i size = get_size(); - Ref<Texture2D> grabber = get_icon("grabber"); + Ref<Texture2D> grabber = get_theme_icon("grabber"); float motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos; if (orientation == VERTICAL) motion = -motion; @@ -165,10 +165,10 @@ void Slider::_notification(int p_what) { case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Size2i size = get_size(); - Ref<StyleBox> style = get_stylebox("slider"); - Ref<StyleBox> grabber_area = get_stylebox("grabber_area"); - Ref<Texture2D> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled"); - Ref<Texture2D> tick = get_icon("tick"); + Ref<StyleBox> style = get_theme_stylebox("slider"); + Ref<StyleBox> grabber_area = get_theme_stylebox("grabber_area"); + Ref<Texture2D> grabber = get_theme_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled"); + Ref<Texture2D> tick = get_theme_icon("tick"); double ratio = Math::is_nan(get_as_ratio()) ? 0 : get_as_ratio(); if (orientation == VERTICAL) { diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 576de98a4f..ccfa8ebf63 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -29,8 +29,9 @@ /*************************************************************************/ #include "spin_box.h" + +#include "core/input/input_filter.h" #include "core/math/expression.h" -#include "core/os/input.h" Size2 SpinBox::get_minimum_size() const { @@ -76,7 +77,7 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) { void SpinBox::_range_click_timeout() { - if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (!drag.enabled && InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { bool up = get_local_mouse_position().y < (get_size().height / 2); set_value(get_value() + (up ? get_step() : -get_step())); @@ -148,7 +149,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { if (drag.enabled) { drag.enabled = false; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); warp_mouse(drag.capture_pos); } drag.allowed = false; @@ -165,7 +166,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) { set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max())); } else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) { - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_CAPTURED); drag.enabled = true; drag.base_val = get_value(); drag.diff_y = 0; @@ -195,7 +196,7 @@ void SpinBox::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { - Ref<Texture2D> updown = get_icon("updown"); + Ref<Texture2D> updown = get_theme_icon("updown"); _adjust_width_for_icon(updown); @@ -209,7 +210,7 @@ void SpinBox::_notification(int p_what) { //_value_changed(0); } else if (p_what == NOTIFICATION_ENTER_TREE) { - _adjust_width_for_icon(get_icon("updown")); + _adjust_width_for_icon(get_theme_icon("updown")); _value_changed(0); } else if (p_what == NOTIFICATION_THEME_CHANGED) { diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 255278be2b..4eb614a9ac 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -74,8 +74,8 @@ void SplitContainer::_resort() { bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND; // Determine the separation between items - Ref<Texture2D> g = get_icon("grabber"); - int sep = get_constant("separation"); + Ref<Texture2D> g = get_theme_icon("grabber"); + int sep = get_theme_constant("separation"); sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0; // Compute the minimum size @@ -123,8 +123,8 @@ Size2 SplitContainer::get_minimum_size() const { /* Calculate MINIMUM SIZE */ Size2i minimum; - Ref<Texture2D> g = get_icon("grabber"); - int sep = get_constant("separation"); + Ref<Texture2D> g = get_theme_icon("grabber"); + int sep = get_theme_constant("separation"); sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0; for (int i = 0; i < 2; i++) { @@ -167,7 +167,7 @@ void SplitContainer::_notification(int p_what) { case NOTIFICATION_MOUSE_EXIT: { mouse_inside = false; - if (get_constant("autohide")) + if (get_theme_constant("autohide")) update(); } break; case NOTIFICATION_DRAW: { @@ -175,14 +175,14 @@ void SplitContainer::_notification(int p_what) { if (!_getch(0) || !_getch(1)) return; - if (collapsed || (!dragging && !mouse_inside && get_constant("autohide"))) + if (collapsed || (!dragging && !mouse_inside && get_theme_constant("autohide"))) return; if (dragger_visibility != DRAGGER_VISIBLE) return; - int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_constant("separation") : 0; - Ref<Texture2D> tex = get_icon("grabber"); + int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant("separation") : 0; + Ref<Texture2D> tex = get_theme_icon("grabber"); Size2 size = get_size(); if (vertical) @@ -210,7 +210,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { if (mb->is_pressed()) { - int sep = get_constant("separation"); + int sep = get_theme_constant("separation"); if (vertical) { @@ -242,14 +242,14 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) { bool mouse_inside_state = false; if (vertical) - mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_constant("separation"); + mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant("separation"); else - mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_constant("separation"); + mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant("separation"); if (mouse_inside != mouse_inside_state) { mouse_inside = mouse_inside_state; - if (get_constant("autohide")) + if (get_theme_constant("autohide")) update(); } @@ -270,7 +270,7 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) { - int sep = get_constant("separation"); + int sep = get_theme_constant("separation"); if (vertical) { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 6290d364fc..7cecbf7fa2 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -41,14 +41,14 @@ int TabContainer::_get_top_margin() const { return 0; // Respect the minimum tab height. - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); int tab_height = MAX(MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height), tab_disabled->get_minimum_size().height); // Font height or higher icon wins. - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); int content_height = font->get_height(); Vector<Control *> tabs = _get_tabs(); @@ -81,15 +81,15 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { return; // Handle menu button. - Ref<Texture2D> menu = get_icon("menu"); + Ref<Texture2D> menu = get_theme_icon("menu"); if (popup && pos.x > size.width - menu->get_width()) { emit_signal("pre_popup_pressed"); - Vector2 popup_pos = get_global_position(); - popup_pos.x += size.width * get_global_transform().get_scale().x - popup->get_size().width * popup->get_global_transform().get_scale().x; - popup_pos.y += menu->get_height() * get_global_transform().get_scale().y; + Vector2 popup_pos = get_screen_position(); + popup_pos.x += size.width - popup->get_size().width; + popup_pos.y += menu->get_height(); - popup->set_global_position(popup_pos); + popup->set_position(popup_pos); popup->popup(); return; } @@ -107,8 +107,8 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { popup_ofs = menu->get_width(); } - Ref<Texture2D> increment = get_icon("increment"); - Ref<Texture2D> decrement = get_icon("decrement"); + Ref<Texture2D> increment = get_theme_icon("increment"); + Ref<Texture2D> decrement = get_theme_icon("decrement"); if (pos.x > size.width - increment->get_width() - popup_ofs) { if (last_tab_cache < tabs.size() - 1) { first_tab_cache += 1; @@ -159,7 +159,7 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { return; } - Ref<Texture2D> menu = get_icon("menu"); + Ref<Texture2D> menu = get_theme_icon("menu"); if (popup) { if (pos.x >= size.width - menu->get_width()) { @@ -191,8 +191,8 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { popup_ofs = menu->get_width(); } - Ref<Texture2D> increment = get_icon("increment"); - Ref<Texture2D> decrement = get_icon("decrement"); + Ref<Texture2D> increment = get_theme_icon("increment"); + Ref<Texture2D> decrement = get_theme_icon("decrement"); if (pos.x >= size.width - increment->get_width() - popup_ofs) { if (highlight_arrow != 1) { @@ -224,10 +224,10 @@ void TabContainer::_notification(int p_what) { case NOTIFICATION_RESIZED: { Vector<Control *> tabs = _get_tabs(); - int side_margin = get_constant("side_margin"); - Ref<Texture2D> menu = get_icon("menu"); - Ref<Texture2D> increment = get_icon("increment"); - Ref<Texture2D> decrement = get_icon("decrement"); + int side_margin = get_theme_constant("side_margin"); + Ref<Texture2D> menu = get_theme_icon("menu"); + Ref<Texture2D> increment = get_theme_icon("increment"); + Ref<Texture2D> decrement = get_theme_icon("decrement"); int header_width = get_size().width - side_margin * 2; // Find the width of the header area. @@ -262,28 +262,28 @@ void TabContainer::_notification(int p_what) { Size2 size = get_size(); // Draw only the tab area if the header is hidden. - Ref<StyleBox> panel = get_stylebox("panel"); + Ref<StyleBox> panel = get_theme_stylebox("panel"); if (!tabs_visible) { panel->draw(canvas, Rect2(0, 0, size.width, size.height)); return; } Vector<Control *> tabs = _get_tabs(); - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); - Ref<Texture2D> increment = get_icon("increment"); - Ref<Texture2D> increment_hl = get_icon("increment_highlight"); - Ref<Texture2D> decrement = get_icon("decrement"); - Ref<Texture2D> decrement_hl = get_icon("decrement_highlight"); - Ref<Texture2D> menu = get_icon("menu"); - Ref<Texture2D> menu_hl = get_icon("menu_highlight"); - Ref<Font> font = get_font("font"); - Color font_color_fg = get_color("font_color_fg"); - Color font_color_bg = get_color("font_color_bg"); - Color font_color_disabled = get_color("font_color_disabled"); - int side_margin = get_constant("side_margin"); - int icon_text_distance = get_constant("hseparation"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); + Ref<Texture2D> increment = get_theme_icon("increment"); + Ref<Texture2D> increment_hl = get_theme_icon("increment_highlight"); + Ref<Texture2D> decrement = get_theme_icon("decrement"); + Ref<Texture2D> decrement_hl = get_theme_icon("decrement_highlight"); + Ref<Texture2D> menu = get_theme_icon("menu"); + Ref<Texture2D> menu_hl = get_theme_icon("menu_highlight"); + Ref<Font> font = get_theme_font("font"); + Color font_color_fg = get_theme_color("font_color_fg"); + Color font_color_bg = get_theme_color("font_color_bg"); + Color font_color_disabled = get_theme_color("font_color_disabled"); + int side_margin = get_theme_constant("side_margin"); + int icon_text_distance = get_theme_constant("hseparation"); // Find out start and width of the header area. int header_x = side_margin; @@ -458,7 +458,7 @@ int TabContainer::_get_tab_width(int p_index) const { return 0; // Get the width of the text displayed on the tab. - Ref<Font> font = get_font("font"); + Ref<Font> font = get_theme_font("font"); String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(control->get_name()); int width = font->get_string_size(text).width; @@ -468,14 +468,14 @@ int TabContainer::_get_tab_width(int p_index) const { if (icon.is_valid()) { width += icon->get_width(); if (text != "") - width += get_constant("hseparation"); + width += get_theme_constant("hseparation"); } } // Respect a minimum size. - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); if (get_tab_disabled(p_index)) { width += tab_disabled->get_minimum_size().width; } else if (p_index == current) { @@ -530,7 +530,7 @@ void TabContainer::add_child_notify(Node *p_child) { c->set_anchors_and_margins_preset(Control::PRESET_WIDE); if (tabs_visible) c->set_margin(MARGIN_TOP, _get_top_margin()); - Ref<StyleBox> sb = get_stylebox("panel"); + Ref<StyleBox> sb = get_theme_stylebox("panel"); c->set_margin(Margin(MARGIN_TOP), c->get_margin(Margin(MARGIN_TOP)) + sb->get_margin(Margin(MARGIN_TOP))); c->set_margin(Margin(MARGIN_LEFT), c->get_margin(Margin(MARGIN_LEFT)) + sb->get_margin(Margin(MARGIN_LEFT))); c->set_margin(Margin(MARGIN_RIGHT), c->get_margin(Margin(MARGIN_RIGHT)) - sb->get_margin(Margin(MARGIN_RIGHT))); @@ -554,7 +554,7 @@ void TabContainer::set_current_tab(int p_current) { int pending_previous = current; current = p_current; - Ref<StyleBox> sb = get_stylebox("panel"); + Ref<StyleBox> sb = get_theme_stylebox("panel"); Vector<Control *> tabs = _get_tabs(); for (int i = 0; i < tabs.size(); i++) { @@ -745,12 +745,12 @@ int TabContainer::get_tab_idx_at_point(const Point2 &p_point) const { int right_ofs = 0; if (popup) { - Ref<Texture2D> menu = get_icon("menu"); + Ref<Texture2D> menu = get_theme_icon("menu"); right_ofs += menu->get_width(); } if (buttons_visible_cache) { - Ref<Texture2D> increment = get_icon("increment"); - Ref<Texture2D> decrement = get_icon("decrement"); + Ref<Texture2D> increment = get_theme_icon("increment"); + Ref<Texture2D> decrement = get_theme_icon("decrement"); right_ofs += increment->get_width() + decrement->get_width(); } if (p_point.x > size.width - right_ofs) { @@ -933,17 +933,17 @@ Size2 TabContainer::get_minimum_size() const { ms.y = MAX(ms.y, cms.y); } - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); - Ref<Font> font = get_font("font"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); + Ref<Font> font = get_theme_font("font"); if (tabs_visible) { ms.y += MAX(MAX(tab_bg->get_minimum_size().y, tab_fg->get_minimum_size().y), tab_disabled->get_minimum_size().y); ms.y += font->get_height(); } - Ref<StyleBox> sb = get_stylebox("panel"); + Ref<StyleBox> sb = get_theme_stylebox("panel"); ms += sb->get_minimum_size(); return ms; diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 901408919a..ea6d44e3a7 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -37,10 +37,10 @@ Size2 Tabs::get_minimum_size() const { - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); - Ref<Font> font = get_font("font"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); + Ref<Font> font = get_theme_font("font"); Size2 ms(0, MAX(MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height), tab_disabled->get_minimum_size().height) + font->get_height()); @@ -50,7 +50,7 @@ Size2 Tabs::get_minimum_size() const { if (tex.is_valid()) { ms.height = MAX(ms.height, tex->get_size().height); if (tabs[i].text != "") - ms.width += get_constant("hseparation"); + ms.width += get_theme_constant("hseparation"); } ms.width += Math::ceil(font->get_string_size(tabs[i].xl_text).width); @@ -65,15 +65,15 @@ Size2 Tabs::get_minimum_size() const { if (tabs[i].right_button.is_valid()) { Ref<Texture2D> rb = tabs[i].right_button; Size2 bms = rb->get_size(); - bms.width += get_constant("hseparation"); + bms.width += get_theme_constant("hseparation"); ms.width += bms.width; ms.height = MAX(bms.height + tab_bg->get_minimum_size().height, ms.height); } if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { - Ref<Texture2D> cb = get_icon("close"); + Ref<Texture2D> cb = get_theme_icon("close"); Size2 bms = cb->get_size(); - bms.width += get_constant("hseparation"); + bms.width += get_theme_constant("hseparation"); ms.width += bms.width; ms.height = MAX(bms.height + tab_bg->get_minimum_size().height, ms.height); } @@ -94,8 +94,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { highlight_arrow = -1; if (buttons_visible) { - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); @@ -163,8 +163,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { if (buttons_visible) { - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); @@ -238,14 +238,14 @@ void Tabs::_notification(int p_what) { _update_cache(); RID ci = get_canvas_item(); - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); - Ref<Font> font = get_font("font"); - Color color_fg = get_color("font_color_fg"); - Color color_bg = get_color("font_color_bg"); - Color color_disabled = get_color("font_color_disabled"); - Ref<Texture2D> close = get_icon("close"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); + Ref<Font> font = get_theme_font("font"); + Color color_fg = get_theme_color("font_color_fg"); + Color color_bg = get_theme_color("font_color_bg"); + Color color_disabled = get_theme_color("font_color_disabled"); + Ref<Texture2D> close = get_theme_icon("close"); int h = get_size().height; int w = 0; @@ -267,10 +267,10 @@ void Tabs::_notification(int p_what) { w = 0; } - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); - Ref<Texture2D> incr_hl = get_icon("increment_highlight"); - Ref<Texture2D> decr_hl = get_icon("decrement_highlight"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); + Ref<Texture2D> incr_hl = get_theme_icon("increment_highlight"); + Ref<Texture2D> decr_hl = get_theme_icon("decrement_highlight"); int limit = get_size().width - incr->get_size().width - decr->get_size().width; @@ -318,7 +318,7 @@ void Tabs::_notification(int p_what) { icon->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2)); if (tabs[i].text != "") - w += icon->get_width() + get_constant("hseparation"); + w += icon->get_width() + get_theme_constant("hseparation"); } font->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - font->get_height()) / 2 + font->get_ascent()), tabs[i].xl_text, col, tabs[i].size_text); @@ -327,10 +327,10 @@ void Tabs::_notification(int p_what) { if (tabs[i].right_button.is_valid()) { - Ref<StyleBox> style = get_stylebox("button"); + Ref<StyleBox> style = get_theme_stylebox("button"); Ref<Texture2D> rb = tabs[i].right_button; - w += get_constant("hseparation"); + w += get_theme_constant("hseparation"); Rect2 rb_rect; rb_rect.size = style->get_minimum_size() + rb->get_size(); @@ -339,7 +339,7 @@ void Tabs::_notification(int p_what) { if (rb_hover == i) { if (rb_pressing) - get_stylebox("button_pressed")->draw(ci, rb_rect); + get_theme_stylebox("button_pressed")->draw(ci, rb_rect); else style->draw(ci, rb_rect); } @@ -351,10 +351,10 @@ void Tabs::_notification(int p_what) { if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { - Ref<StyleBox> style = get_stylebox("button"); + Ref<StyleBox> style = get_theme_stylebox("button"); Ref<Texture2D> cb = close; - w += get_constant("hseparation"); + w += get_theme_constant("hseparation"); Rect2 cb_rect; cb_rect.size = style->get_minimum_size() + cb->get_size(); @@ -363,7 +363,7 @@ void Tabs::_notification(int p_what) { if (!tabs[i].disabled && cb_hover == i) { if (cb_pressing) - get_stylebox("button_pressed")->draw(ci, cb_rect); + get_theme_stylebox("button_pressed")->draw(ci, cb_rect); else style->draw(ci, cb_rect); } @@ -532,12 +532,12 @@ void Tabs::_update_hover() { } void Tabs::_update_cache() { - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<Font> font = get_font("font"); - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<Font> font = get_theme_font("font"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); int w = 0; @@ -577,12 +577,12 @@ void Tabs::_update_cache() { slen = m_width - (sb->get_margin(MARGIN_LEFT) + sb->get_margin(MARGIN_RIGHT)); if (tabs[i].icon.is_valid()) { slen -= tabs[i].icon->get_width(); - slen -= get_constant("hseparation"); + slen -= get_theme_constant("hseparation"); } if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { - Ref<Texture2D> cb = get_icon("close"); + Ref<Texture2D> cb = get_theme_icon("close"); slen -= cb->get_width(); - slen -= get_constant("hseparation"); + slen -= get_theme_constant("hseparation"); } slen = MAX(slen, 1); lsize = m_width; @@ -799,10 +799,10 @@ int Tabs::get_tab_width(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0); - Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); - Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); - Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); - Ref<Font> font = get_font("font"); + Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg"); + Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg"); + Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled"); + Ref<Font> font = get_theme_font("font"); int x = 0; @@ -810,7 +810,7 @@ int Tabs::get_tab_width(int p_idx) const { if (tex.is_valid()) { x += tex->get_width(); if (tabs[p_idx].text != "") - x += get_constant("hseparation"); + x += get_theme_constant("hseparation"); } x += Math::ceil(font->get_string_size(tabs[p_idx].xl_text).width); @@ -825,13 +825,13 @@ int Tabs::get_tab_width(int p_idx) const { if (tabs[p_idx].right_button.is_valid()) { Ref<Texture2D> rb = tabs[p_idx].right_button; x += rb->get_width(); - x += get_constant("hseparation"); + x += get_theme_constant("hseparation"); } if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current)) { - Ref<Texture2D> cb = get_icon("close"); + Ref<Texture2D> cb = get_theme_icon("close"); x += cb->get_width(); - x += get_constant("hseparation"); + x += get_theme_constant("hseparation"); } return x; @@ -842,8 +842,8 @@ void Tabs::_ensure_no_over_offset() { if (!is_inside_tree()) return; - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); @@ -885,8 +885,8 @@ void Tabs::ensure_tab_visible(int p_idx) { } int prev_offset = offset; - Ref<Texture2D> incr = get_icon("increment"); - Ref<Texture2D> decr = get_icon("decrement"); + Ref<Texture2D> incr = get_theme_icon("increment"); + Ref<Texture2D> decr = get_theme_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); for (int i = offset; i <= p_idx; i++) { if (tabs[i].ofs_cache + tabs[i].size_cache > limit) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index cdc2430eb5..fb477ee3b4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -30,13 +30,13 @@ #include "text_edit.h" +#include "core/input/input_filter.h" #include "core/message_queue.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/project_settings.h" #include "core/script_language.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" @@ -446,7 +446,7 @@ void TextEdit::_click_selection_held() { // Warning: is_mouse_button_pressed(BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD // and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem. // I'm unsure if there's an actual fix that doesn't have a ton of side effects. - if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) { + if (InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) { switch (selection.selecting_mode) { case Selection::MODE_POINTER: { _update_selection_mode_pointer(); @@ -639,12 +639,12 @@ void TextEdit::_notification(int p_what) { _update_wrap_at(); syntax_highlighting_cache.clear(); } break; - case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_FOCUS_IN: { window_has_focus = true; draw_caret = true; update(); } break; - case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_FOCUS_OUT: { window_has_focus = false; draw_caret = false; update(); @@ -1584,11 +1584,11 @@ void TextEdit::_notification(int p_what) { bool completion_below = false; if (completion_active && completion_options.size() > 0) { // Code completion box. - Ref<StyleBox> csb = get_stylebox("completion"); - int maxlines = get_constant("completion_lines"); - int cmax_width = get_constant("completion_max_width") * cache.font->get_char_size('x').x; - int scrollw = get_constant("completion_scroll_width"); - Color scrollc = get_color("completion_scroll_color"); + Ref<StyleBox> csb = get_theme_stylebox("completion"); + int maxlines = get_theme_constant("completion_lines"); + int cmax_width = get_theme_constant("completion_max_width") * cache.font->get_char_size('x').x; + int scrollw = get_theme_constant("completion_scroll_width"); + Color scrollc = get_theme_color("completion_scroll_color"); const int completion_options_size = completion_options.size(); int lines = MIN(completion_options_size, maxlines); @@ -1607,7 +1607,7 @@ void TextEdit::_notification(int p_what) { } // Add space for completion icons. - const int icon_hsep = get_constant("hseparation", "ItemList"); + const int icon_hsep = get_theme_constant("hseparation", "ItemList"); Size2 icon_area_size(get_row_height(), get_row_height()); w += icon_area_size.width + icon_hsep; @@ -1694,9 +1694,9 @@ void TextEdit::_notification(int p_what) { if (show_hint) { - Ref<StyleBox> sb = get_stylebox("panel", "TooltipPanel"); + Ref<StyleBox> sb = get_theme_stylebox("panel", "TooltipPanel"); Ref<Font> font = cache.font; - Color font_color = get_color("font_color", "TooltipLabel"); + Color font_color = get_theme_color("font_color", "TooltipLabel"); int max_w = 0; int sc = completion_hint.get_slice_count("\n"); @@ -1754,8 +1754,10 @@ void TextEdit::_notification(int p_what) { } if (has_focus()) { - OS::get_singleton()->set_ime_active(true); - OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height())); + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); + DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()), get_viewport()->get_window_id()); + } } } break; case NOTIFICATION_FOCUS_ENTER: { @@ -1766,12 +1768,14 @@ void TextEdit::_notification(int p_what) { draw_caret = true; } - OS::get_singleton()->set_ime_active(true); - Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height(); - OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id()); + Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height(); + DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id()); + } - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect()); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) + DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect()); } break; case NOTIFICATION_FOCUS_EXIT: { @@ -1779,19 +1783,21 @@ void TextEdit::_notification(int p_what) { caret_blink_timer->stop(); } - OS::get_singleton()->set_ime_position(Point2()); - OS::get_singleton()->set_ime_active(false); + if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); + DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id()); + } ime_text = ""; ime_selection = Point2(); - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->hide_virtual_keyboard(); + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) + DisplayServer::get_singleton()->virtual_keyboard_hide(); } break; case MainLoop::NOTIFICATION_OS_IME_UPDATE: { if (has_focus()) { - ime_text = OS::get_singleton()->get_ime_text(); - ime_selection = OS::get_singleton()->get_ime_selection(); + ime_text = DisplayServer::get_singleton()->ime_get_text(); + ime_selection = DisplayServer::get_singleton()->ime_get_selection(); update(); } } break; @@ -2477,9 +2483,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - menu->set_position(get_global_transform().xform(get_local_mouse_position())); + menu->set_position(get_screen_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); - menu->set_scale(get_global_transform().get_scale()); + // menu->set_scale(get_global_transform().get_scale()); menu->popup(); grab_focus(); } @@ -2634,7 +2640,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_keycode() == KEY_PAGEUP) { - completion_index -= get_constant("completion_lines"); + completion_index -= get_theme_constant("completion_lines"); if (completion_index < 0) completion_index = 0; completion_current = completion_options[completion_index]; @@ -2645,7 +2651,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_keycode() == KEY_PAGEDOWN) { - completion_index += get_constant("completion_lines"); + completion_index += get_theme_constant("completion_lines"); if (completion_index >= completion_options.size()) completion_index = completion_options.size() - 1; completion_current = completion_options[completion_index]; @@ -3735,7 +3741,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (context_menu_enabled) { menu->set_position(get_global_transform().xform(_get_cursor_pixel_pos())); menu->set_size(Vector2(1, 1)); - menu->set_scale(get_global_transform().get_scale()); + // menu->set_scale(get_global_transform().get_scale()); menu->popup(); menu->grab_focus(); } @@ -5026,51 +5032,51 @@ void TextEdit::_toggle_draw_caret() { void TextEdit::_update_caches() { - cache.style_normal = get_stylebox("normal"); - cache.style_focus = get_stylebox("focus"); - cache.style_readonly = get_stylebox("read_only"); - cache.completion_background_color = get_color("completion_background_color"); - cache.completion_selected_color = get_color("completion_selected_color"); - cache.completion_existing_color = get_color("completion_existing_color"); - cache.completion_font_color = get_color("completion_font_color"); - cache.font = get_font("font"); - cache.caret_color = get_color("caret_color"); - cache.caret_background_color = get_color("caret_background_color"); - cache.line_number_color = get_color("line_number_color"); - cache.safe_line_number_color = get_color("safe_line_number_color"); - cache.font_color = get_color("font_color"); - cache.font_color_selected = get_color("font_color_selected"); - cache.font_color_readonly = get_color("font_color_readonly"); - cache.keyword_color = get_color("keyword_color"); - cache.function_color = get_color("function_color"); - cache.member_variable_color = get_color("member_variable_color"); - cache.number_color = get_color("number_color"); - cache.selection_color = get_color("selection_color"); - cache.mark_color = get_color("mark_color"); - cache.current_line_color = get_color("current_line_color"); - cache.line_length_guideline_color = get_color("line_length_guideline_color"); - cache.bookmark_color = get_color("bookmark_color"); - cache.breakpoint_color = get_color("breakpoint_color"); - cache.executing_line_color = get_color("executing_line_color"); - cache.code_folding_color = get_color("code_folding_color"); - cache.brace_mismatch_color = get_color("brace_mismatch_color"); - cache.word_highlighted_color = get_color("word_highlighted_color"); - cache.search_result_color = get_color("search_result_color"); - cache.search_result_border_color = get_color("search_result_border_color"); - cache.symbol_color = get_color("symbol_color"); - cache.background_color = get_color("background_color"); + cache.style_normal = get_theme_stylebox("normal"); + cache.style_focus = get_theme_stylebox("focus"); + cache.style_readonly = get_theme_stylebox("read_only"); + cache.completion_background_color = get_theme_color("completion_background_color"); + cache.completion_selected_color = get_theme_color("completion_selected_color"); + cache.completion_existing_color = get_theme_color("completion_existing_color"); + cache.completion_font_color = get_theme_color("completion_font_color"); + cache.font = get_theme_font("font"); + cache.caret_color = get_theme_color("caret_color"); + cache.caret_background_color = get_theme_color("caret_background_color"); + cache.line_number_color = get_theme_color("line_number_color"); + cache.safe_line_number_color = get_theme_color("safe_line_number_color"); + cache.font_color = get_theme_color("font_color"); + cache.font_color_selected = get_theme_color("font_color_selected"); + cache.font_color_readonly = get_theme_color("font_color_readonly"); + cache.keyword_color = get_theme_color("keyword_color"); + cache.function_color = get_theme_color("function_color"); + cache.member_variable_color = get_theme_color("member_variable_color"); + cache.number_color = get_theme_color("number_color"); + cache.selection_color = get_theme_color("selection_color"); + cache.mark_color = get_theme_color("mark_color"); + cache.current_line_color = get_theme_color("current_line_color"); + cache.line_length_guideline_color = get_theme_color("line_length_guideline_color"); + cache.bookmark_color = get_theme_color("bookmark_color"); + cache.breakpoint_color = get_theme_color("breakpoint_color"); + cache.executing_line_color = get_theme_color("executing_line_color"); + cache.code_folding_color = get_theme_color("code_folding_color"); + cache.brace_mismatch_color = get_theme_color("brace_mismatch_color"); + cache.word_highlighted_color = get_theme_color("word_highlighted_color"); + cache.search_result_color = get_theme_color("search_result_color"); + cache.search_result_border_color = get_theme_color("search_result_border_color"); + cache.symbol_color = get_theme_color("symbol_color"); + cache.background_color = get_theme_color("background_color"); #ifdef TOOLS_ENABLED - cache.line_spacing = get_constant("line_spacing") * EDSCALE; + cache.line_spacing = get_theme_constant("line_spacing") * EDSCALE; #else - cache.line_spacing = get_constant("line_spacing"); + cache.line_spacing = get_theme_constant("line_spacing"); #endif cache.row_height = cache.font->get_height() + cache.line_spacing; - cache.tab_icon = get_icon("tab"); - cache.space_icon = get_icon("space"); - cache.folded_icon = get_icon("folded"); - cache.can_fold_icon = get_icon("fold"); - cache.folded_eol_icon = get_icon("GuiEllipsis", "EditorIcons"); - cache.executing_icon = get_icon("MainPlay", "EditorIcons"); + cache.tab_icon = get_theme_icon("tab"); + cache.space_icon = get_theme_icon("space"); + cache.folded_icon = get_theme_icon("folded"); + cache.can_fold_icon = get_theme_icon("fold"); + cache.folded_eol_icon = get_theme_icon("GuiEllipsis", "EditorIcons"); + cache.executing_icon = get_theme_icon("MainPlay", "EditorIcons"); text.set_font(cache.font); if (syntax_highlighter) { @@ -5226,7 +5232,7 @@ void TextEdit::cut() { if (!selection.active) { String clipboard = text[cursor.line]; - OS::get_singleton()->set_clipboard(clipboard); + DisplayServer::get_singleton()->clipboard_set(clipboard); cursor_set_line(cursor.line); cursor_set_column(0); @@ -5244,7 +5250,7 @@ void TextEdit::cut() { } else { String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); + DisplayServer::get_singleton()->clipboard_set(clipboard); _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); cursor_set_line(selection.from_line); // Set afterwards else it causes the view to be offset. @@ -5264,19 +5270,19 @@ void TextEdit::copy() { if (text[cursor.line].length() != 0) { String clipboard = _base_get_text(cursor.line, 0, cursor.line, text[cursor.line].length()); - OS::get_singleton()->set_clipboard(clipboard); + DisplayServer::get_singleton()->clipboard_set(clipboard); cut_copy_line = clipboard; } } else { String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); + DisplayServer::get_singleton()->clipboard_set(clipboard); cut_copy_line = ""; } } void TextEdit::paste() { - String clipboard = OS::get_singleton()->get_clipboard(); + String clipboard = DisplayServer::get_singleton()->clipboard_get(); begin_complex_operation(); if (selection.active) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 12b3d56938..653ac74164 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -30,13 +30,15 @@ #include "tree.h" +#include "core/input/input_filter.h" #include "core/math/math_funcs.h" -#include "core/os/input.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/print_string.h" #include "core/project_settings.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" + +#include "box_container.h" #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" @@ -952,45 +954,45 @@ TreeItem::~TreeItem() { void Tree::update_cache() { - cache.font = get_font("font"); - cache.tb_font = get_font("title_button_font"); - cache.bg = get_stylebox("bg"); - cache.selected = get_stylebox("selected"); - cache.selected_focus = get_stylebox("selected_focus"); - cache.cursor = get_stylebox("cursor"); - cache.cursor_unfocus = get_stylebox("cursor_unfocused"); - cache.button_pressed = get_stylebox("button_pressed"); - - cache.checked = get_icon("checked"); - cache.unchecked = get_icon("unchecked"); - cache.arrow_collapsed = get_icon("arrow_collapsed"); - cache.arrow = get_icon("arrow"); - cache.select_arrow = get_icon("select_arrow"); - cache.updown = get_icon("updown"); - - cache.custom_button = get_stylebox("custom_button"); - cache.custom_button_hover = get_stylebox("custom_button_hover"); - cache.custom_button_pressed = get_stylebox("custom_button_pressed"); - cache.custom_button_font_highlight = get_color("custom_button_font_highlight"); - - cache.font_color = get_color("font_color"); - cache.font_color_selected = get_color("font_color_selected"); - cache.guide_color = get_color("guide_color"); - cache.drop_position_color = get_color("drop_position_color"); - cache.hseparation = get_constant("hseparation"); - cache.vseparation = get_constant("vseparation"); - cache.item_margin = get_constant("item_margin"); - cache.button_margin = get_constant("button_margin"); - cache.draw_guides = get_constant("draw_guides"); - cache.draw_relationship_lines = get_constant("draw_relationship_lines"); - cache.relationship_line_color = get_color("relationship_line_color"); - cache.scroll_border = get_constant("scroll_border"); - cache.scroll_speed = get_constant("scroll_speed"); - - cache.title_button = get_stylebox("title_button_normal"); - cache.title_button_pressed = get_stylebox("title_button_pressed"); - cache.title_button_hover = get_stylebox("title_button_hover"); - cache.title_button_color = get_color("title_button_color"); + cache.font = get_theme_font("font"); + cache.tb_font = get_theme_font("title_button_font"); + cache.bg = get_theme_stylebox("bg"); + cache.selected = get_theme_stylebox("selected"); + cache.selected_focus = get_theme_stylebox("selected_focus"); + cache.cursor = get_theme_stylebox("cursor"); + cache.cursor_unfocus = get_theme_stylebox("cursor_unfocused"); + cache.button_pressed = get_theme_stylebox("button_pressed"); + + cache.checked = get_theme_icon("checked"); + cache.unchecked = get_theme_icon("unchecked"); + cache.arrow_collapsed = get_theme_icon("arrow_collapsed"); + cache.arrow = get_theme_icon("arrow"); + cache.select_arrow = get_theme_icon("select_arrow"); + cache.updown = get_theme_icon("updown"); + + cache.custom_button = get_theme_stylebox("custom_button"); + cache.custom_button_hover = get_theme_stylebox("custom_button_hover"); + cache.custom_button_pressed = get_theme_stylebox("custom_button_pressed"); + cache.custom_button_font_highlight = get_theme_color("custom_button_font_highlight"); + + cache.font_color = get_theme_color("font_color"); + cache.font_color_selected = get_theme_color("font_color_selected"); + cache.guide_color = get_theme_color("guide_color"); + cache.drop_position_color = get_theme_color("drop_position_color"); + cache.hseparation = get_theme_constant("hseparation"); + cache.vseparation = get_theme_constant("vseparation"); + cache.item_margin = get_theme_constant("item_margin"); + cache.button_margin = get_theme_constant("button_margin"); + cache.draw_guides = get_theme_constant("draw_guides"); + cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines"); + cache.relationship_line_color = get_theme_color("relationship_line_color"); + cache.scroll_border = get_theme_constant("scroll_border"); + cache.scroll_speed = get_theme_constant("scroll_speed"); + + cache.title_button = get_theme_stylebox("title_button_normal"); + cache.title_button_pressed = get_theme_stylebox("title_button_pressed"); + cache.title_button_hover = get_theme_stylebox("title_button_hover"); + cache.title_button_color = get_theme_color("title_button_color"); v_scroll->set_custom_step(cache.font->get_height()); } @@ -1291,7 +1293,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } } - Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_color(p_item->cells[i].selected ? "font_color_selected" : "font_color"); + Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_color_selected" : "font_color"); Color icon_col = p_item->cells[i].icon_color; Point2i text_pos = item_rect.position; @@ -1423,7 +1425,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 if (p_item->cells[i].custom_button) { if (cache.hover_item == p_item && cache.hover_cell == i) { - if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { draw_style_box(cache.custom_button_pressed, ir); } else { draw_style_box(cache.custom_button_hover, ir); @@ -1659,7 +1661,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) { void Tree::_range_click_timeout() { - if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { + if (range_item_last && !range_drag_enabled && InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) { Point2 pos = get_local_mouse_position() - cache.bg->get_offset(); if (show_column_titles) { @@ -2046,9 +2048,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool void Tree::_text_editor_modal_close() { - if (Input::get_singleton()->is_key_pressed(KEY_ESCAPE) || - Input::get_singleton()->is_key_pressed(KEY_KP_ENTER) || - Input::get_singleton()->is_key_pressed(KEY_ENTER)) { + if (InputFilter::get_singleton()->is_key_pressed(KEY_ESCAPE) || + InputFilter::get_singleton()->is_key_pressed(KEY_KP_ENTER) || + InputFilter::get_singleton()->is_key_pressed(KEY_ENTER)) { return; } @@ -2056,13 +2058,12 @@ void Tree::_text_editor_modal_close() { if (value_editor->has_point(value_editor->get_local_mouse_position())) return; - text_editor_enter(text_editor->get_text()); + _text_editor_enter(text_editor->get_text()); } -void Tree::text_editor_enter(String p_text) { +void Tree::_text_editor_enter(String p_text) { - text_editor->hide(); - value_editor->hide(); + popup_editor->hide(); if (!popup_edited_item) return; @@ -2531,7 +2532,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { range_drag_enabled = true; range_drag_capture_pos = cpos; range_drag_base = popup_edited_item->get_range(popup_edited_item_col); - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_CAPTURED); } } else { @@ -2593,7 +2594,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (range_drag_enabled) { range_drag_enabled = false; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); warp_mouse(range_drag_capture_pos); } else { Rect2 rect = get_selected()->get_meta("__focus_rect"); @@ -2703,7 +2704,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { drag_accum = 0; //last_drag_accum=0; drag_from = v_scroll->get_value(); - drag_touching = OS::get_singleton()->has_touchscreen_ui_hint(); + drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())); drag_touching_deaccel = false; if (drag_touching) { set_physics_process_internal(true); @@ -2806,20 +2807,23 @@ bool Tree::edit_selected() { } else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) { + Rect2 popup_rect; + Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2); - Point2i textedpos = get_global_position() + rect.position - ofs; + + Point2i textedpos = get_screen_position() + rect.position - ofs; cache.text_editor_position = textedpos; - text_editor->set_position(textedpos); - text_editor->set_size(rect.size); + popup_rect.position = textedpos; + popup_rect.size = rect.size; text_editor->clear(); text_editor->set_text(c.mode == TreeItem::CELL_MODE_STRING ? c.text : String::num(c.val, Math::range_step_decimals(c.step))); text_editor->select_all(); if (c.mode == TreeItem::CELL_MODE_RANGE) { - value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height)); - value_editor->set_size(Size2(rect.size.width, 1)); - value_editor->show_modal(); + popup_rect.size.y += value_editor->get_minimum_size().height; + + value_editor->show(); updating_value_editor = true; value_editor->set_min(c.min); value_editor->set_max(c.max); @@ -2827,10 +2831,17 @@ bool Tree::edit_selected() { value_editor->set_value(c.val); value_editor->set_exp_ratio(c.expr); updating_value_editor = false; + } else { + value_editor->hide(); } - text_editor->show_modal(); + popup_editor->set_position(popup_rect.position); + popup_editor->set_size(popup_rect.size); + popup_editor->popup(); + popup_editor->child_controls_changed(); + text_editor->grab_focus(); + return true; } @@ -3011,7 +3022,7 @@ void Tree::_notification(int p_what) { RID ci = get_canvas_item(); Ref<StyleBox> bg = cache.bg; - Ref<StyleBox> bg_focus = get_stylebox("bg_focus"); + Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus"); Point2 draw_ofs; draw_ofs += bg->get_offset(); @@ -3234,7 +3245,7 @@ void Tree::clear() { if (pressing_for_editor) { if (range_drag_enabled) { range_drag_enabled = false; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); warp_mouse(range_drag_capture_pos); } pressing_for_editor = false; @@ -4020,14 +4031,23 @@ Tree::Tree() { popup_menu = memnew(PopupMenu); popup_menu->hide(); add_child(popup_menu); - popup_menu->set_as_toplevel(true); + // popup_menu->set_as_toplevel(true); + + popup_editor = memnew(PopupPanel); + popup_editor->set_wrap_controls(true); + add_child(popup_editor); + popup_editor_vb = memnew(VBoxContainer); + popup_editor->add_child(popup_editor_vb); + popup_editor_vb->add_theme_constant_override("separation", 0); + popup_editor_vb->set_anchors_and_margins_preset(PRESET_WIDE); text_editor = memnew(LineEdit); - add_child(text_editor); - text_editor->set_as_toplevel(true); - text_editor->hide(); + popup_editor_vb->add_child(text_editor); + text_editor->set_v_size_flags(SIZE_EXPAND_FILL); + text_editor->set_h_size_flags(SIZE_EXPAND_FILL); value_editor = memnew(HSlider); - add_child(value_editor); - value_editor->set_as_toplevel(true); + value_editor->set_v_size_flags(SIZE_EXPAND_FILL); + value_editor->set_h_size_flags(SIZE_EXPAND_FILL); + popup_editor_vb->add_child(value_editor); value_editor->hide(); h_scroll = memnew(HScrollBar); @@ -4042,13 +4062,11 @@ Tree::Tree() { h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved)); v_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved)); - text_editor->connect("text_entered", callable_mp(this, &Tree::text_editor_enter)); - text_editor->connect("modal_closed", callable_mp(this, &Tree::_text_editor_modal_close)); + text_editor->connect("text_entered", callable_mp(this, &Tree::_text_editor_enter)); + popup_editor->connect("popup_hide", callable_mp(this, &Tree::_text_editor_modal_close)); popup_menu->connect("id_pressed", callable_mp(this, &Tree::popup_select)); value_editor->connect("value_changed", callable_mp(this, &Tree::value_editor_changed)); - value_editor->set_as_toplevel(true); - text_editor->set_as_toplevel(true); set_notify_transform(true); updating_value_editor = false; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index b179c5bcba..becbe76598 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -290,6 +290,8 @@ public: VARIANT_ENUM_CAST(TreeItem::TreeCellMode); VARIANT_ENUM_CAST(TreeItem::TextAlign); +class VBoxContainer; + class Tree : public Control { GDCLASS(Tree, Control); @@ -359,6 +361,10 @@ private: }; bool show_column_titles; + + VBoxContainer *popup_editor_vb; + + PopupPanel *popup_editor; LineEdit *text_editor; HSlider *value_editor; bool updating_value_editor; @@ -379,7 +385,7 @@ private: int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item); void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = NULL, bool *r_in_range = NULL, bool p_force_deselect = false); int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod); - void text_editor_enter(String p_text); + void _text_editor_enter(String p_text); void _text_editor_modal_close(); void value_editor_changed(double p_value); diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp index a76f2924d3..7ce1d9e551 100644 --- a/scene/gui/viewport_container.cpp +++ b/scene/gui/viewport_container.cpp @@ -40,7 +40,7 @@ Size2 ViewportContainer::get_minimum_size() const { Size2 ms; for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c) continue; @@ -77,7 +77,7 @@ void ViewportContainer::set_stretch_shrink(int p_shrink) { for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c) continue; @@ -101,7 +101,7 @@ void ViewportContainer::_notification(int p_what) { for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c) continue; @@ -113,14 +113,14 @@ void ViewportContainer::_notification(int p_what) { for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c) continue; if (is_visible_in_tree()) - c->set_update_mode(Viewport::UPDATE_ALWAYS); + c->set_update_mode(SubViewport::UPDATE_ALWAYS); else - c->set_update_mode(Viewport::UPDATE_DISABLED); + c->set_update_mode(SubViewport::UPDATE_DISABLED); c->set_handle_input_locally(false); //do not handle input locally here } @@ -130,7 +130,7 @@ void ViewportContainer::_notification(int p_what) { for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c) continue; @@ -159,7 +159,7 @@ void ViewportContainer::_input(const Ref<InputEvent> &p_event) { for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c || c->is_input_disabled()) continue; @@ -184,7 +184,7 @@ void ViewportContainer::_unhandled_input(const Ref<InputEvent> &p_event) { for (int i = 0; i < get_child_count(); i++) { - Viewport *c = Object::cast_to<Viewport>(get_child(i)); + SubViewport *c = Object::cast_to<SubViewport>(get_child(i)); if (!c || c->is_input_disabled()) continue; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 973dff07d2..b882b9ead6 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2950,9 +2950,9 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT); BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); - BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST); + BIND_CONSTANT(NOTIFICATION_WM_CLOSE_REQUEST); BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST); - BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST); + BIND_CONSTANT(NOTIFICATION_WM_SIZE_CHANGED); BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING); BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED); BIND_CONSTANT(NOTIFICATION_WM_ABOUT); diff --git a/scene/main/node.h b/scene/main/node.h index d1f75b71ec..cf25a92be6 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -244,13 +244,16 @@ public: NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26, NOTIFICATION_POST_ENTER_TREE = 27, //keep these linked to node - NOTIFICATION_WM_MOUSE_ENTER = MainLoop::NOTIFICATION_WM_MOUSE_ENTER, - NOTIFICATION_WM_MOUSE_EXIT = MainLoop::NOTIFICATION_WM_MOUSE_EXIT, - NOTIFICATION_WM_FOCUS_IN = MainLoop::NOTIFICATION_WM_FOCUS_IN, - NOTIFICATION_WM_FOCUS_OUT = MainLoop::NOTIFICATION_WM_FOCUS_OUT, - NOTIFICATION_WM_QUIT_REQUEST = MainLoop::NOTIFICATION_WM_QUIT_REQUEST, - NOTIFICATION_WM_GO_BACK_REQUEST = MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST, - NOTIFICATION_WM_UNFOCUS_REQUEST = MainLoop::NOTIFICATION_WM_UNFOCUS_REQUEST, + + NOTIFICATION_WM_MOUSE_ENTER = 1002, + NOTIFICATION_WM_MOUSE_EXIT = 1003, + NOTIFICATION_WM_FOCUS_IN = 1004, + NOTIFICATION_WM_FOCUS_OUT = 1005, + NOTIFICATION_WM_CLOSE_REQUEST = 1006, + NOTIFICATION_WM_GO_BACK_REQUEST = 1007, + NOTIFICATION_WM_SIZE_CHANGED = 1008, + NOTIFICATION_WM_DPI_CHANGE = 1009, + NOTIFICATION_OS_MEMORY_WARNING = MainLoop::NOTIFICATION_OS_MEMORY_WARNING, NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED, NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT, diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index f472de220b..fad10524b9 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -31,6 +31,7 @@ #include "scene_tree.h" #include "core/debugger/engine_debugger.h" +#include "core/input/input_filter.h" #include "core/io/marshalls.h" #include "core/io/resource_loader.h" #include "core/message_queue.h" @@ -39,7 +40,6 @@ #include "core/os/os.h" #include "core/print_string.h" #include "core/project_settings.h" -#include "main/input_default.h" #include "node.h" #include "scene/debugger/scene_debugger.h" #include "scene/resources/dynamic_font.h" @@ -47,10 +47,11 @@ #include "scene/resources/mesh.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" +#include "servers/display_server.h" #include "servers/navigation_server.h" #include "servers/physics_2d_server.h" #include "servers/physics_server.h" -#include "viewport.h" +#include "window.h" #include <stdio.h> @@ -397,69 +398,6 @@ void SceneTree::set_group(const StringName &p_group, const String &p_name, const set_group_flags(0, p_group, p_name, p_value); } -void SceneTree::set_input_as_handled() { - - input_handled = true; -} - -void SceneTree::input_text(const String &p_text) { - - root_lock++; - - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input_text", p_text); //special one for GUI, as controls use their own process check - - root_lock--; -} - -bool SceneTree::is_input_handled() { - return input_handled; -} - -void SceneTree::input_event(const Ref<InputEvent> &p_event) { - - if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_event))) - return; //avoid joy input on editor - - current_event++; - root_lock++; - - input_handled = false; - - // Don't make const ref unless you can find and fix what caused GH-34691. - Ref<InputEvent> ev = p_event; - - MainLoop::input_event(ev); - - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input", ev); //special one for GUI, as controls use their own process check - - if (EngineDebugger::is_active()) { - //quit from game window using F8 - Ref<InputEventKey> k = ev; - if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_F8) { - EngineDebugger::get_singleton()->send_message("request_quit", Array()); - } - } - - _flush_ugc(); - root_lock--; - //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness - - root_lock++; - - if (!input_handled) { - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_unhandled_input", ev); //special one for GUI, as controls use their own process check - _flush_ugc(); - // input_handled = true; - no reason to set this as handled - root_lock--; - //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness - } else { - // input_handled = true; - no reason to set this as handled - root_lock--; - } - - _call_idle_callbacks(); -} - void SceneTree::init() { initialized = true; root->_set_tree(this); @@ -493,14 +431,6 @@ bool SceneTree::iteration(float p_time) { return _quit; } -void SceneTree::_update_font_oversampling(float p_ratio) { - - if (use_font_oversampling) { - DynamicFontAtSize::font_oversampling = p_ratio; - DynamicFont::update_oversampling(); - } -} - bool SceneTree::idle(float p_time) { //print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage())); @@ -526,15 +456,6 @@ bool SceneTree::idle(float p_time) { _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); _notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS); - Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - - if (win_size != last_screen_size) { - - last_screen_size = win_size; - _update_root_rect(); - emit_signal("screen_resized"); - } - _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications @@ -642,59 +563,36 @@ void SceneTree::quit(int p_exit_code) { _quit = true; } -void SceneTree::_notification(int p_notification) { - - switch (p_notification) { - - case NOTIFICATION_WM_QUIT_REQUEST: { - - get_root()->propagate_notification(p_notification); - - if (accept_quit) { - _quit = true; - break; - } - } break; - - case NOTIFICATION_WM_GO_BACK_REQUEST: { - - get_root()->propagate_notification(p_notification); +void SceneTree::_main_window_close() { - if (quit_on_go_back) { - _quit = true; - break; - } - } break; + if (accept_quit) { + _quit = true; + } +} +void SceneTree::_main_window_go_back() { + if (quit_on_go_back) { + _quit = true; + } +} - case NOTIFICATION_WM_FOCUS_IN: { +void SceneTree::_main_window_focus_in() { + InputFilter *id = InputFilter::get_singleton(); + if (id) { + id->ensure_touch_mouse_raised(); + } +} - InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); - if (id) { - id->ensure_touch_mouse_raised(); - } +void SceneTree::_notification(int p_notification) { - get_root()->propagate_notification(p_notification); - } break; + switch (p_notification) { case NOTIFICATION_TRANSLATION_CHANGED: { if (!Engine::get_singleton()->is_editor_hint()) { get_root()->propagate_notification(p_notification); } } break; - - case NOTIFICATION_WM_UNFOCUS_REQUEST: { - - notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST); - - get_root()->propagate_notification(p_notification); - - } break; - case NOTIFICATION_OS_MEMORY_WARNING: case NOTIFICATION_OS_IME_UPDATE: - case NOTIFICATION_WM_MOUSE_ENTER: - case NOTIFICATION_WM_MOUSE_EXIT: - case NOTIFICATION_WM_FOCUS_OUT: case NOTIFICATION_WM_ABOUT: case NOTIFICATION_CRASH: case NOTIFICATION_APP_RESUMED: @@ -910,7 +808,7 @@ bool SceneTree::is_paused() const { return pause; } -void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input) { +void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) { Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) @@ -919,7 +817,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p if (g.nodes.empty()) return; - _update_group_order(g); + _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); //copy, so copy on write happens in case something is removed from process while being called //performance is not lost because only if something is added/removed the vector is copied. @@ -928,15 +826,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p int node_count = nodes_copy.size(); Node **nodes = nodes_copy.ptrw(); - Variant arg = p_input; - const Variant *v[1] = { &arg }; - call_lock++; - for (int i = node_count - 1; i >= 0; i--) { - - if (input_handled) - break; + for (int i = 0; i < node_count; i++) { Node *n = nodes[i]; if (call_lock && call_skip.has(n)) @@ -944,8 +836,10 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p if (!n->can_process()) continue; + if (!n->can_process_notification(p_notification)) + continue; - n->call_multilevel(p_method, (const Variant **)v, 1); + n->notification(p_notification); //ERR_FAIL_COND(node_count != g.nodes.size()); } @@ -954,7 +848,18 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p call_skip.clear(); } -void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) { +/* +void SceneMainLoop::_update_listener_2d() { + + if (listener_2d.is_valid()) { + + SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() ); + } + +} +*/ + +void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport) { Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) @@ -963,7 +868,7 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio if (g.nodes.empty()) return; - _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS); + _update_group_order(g); //copy, so copy on write happens in case something is removed from process while being called //performance is not lost because only if something is added/removed the vector is copied. @@ -972,9 +877,15 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio int node_count = nodes_copy.size(); Node **nodes = nodes_copy.ptrw(); + Variant arg = p_input; + const Variant *v[1] = { &arg }; + call_lock++; - for (int i = 0; i < node_count; i++) { + for (int i = node_count - 1; i >= 0; i--) { + + if (p_viewport->is_input_handled()) + break; Node *n = nodes[i]; if (call_lock && call_skip.has(n)) @@ -982,10 +893,8 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio if (!n->can_process()) continue; - if (!n->can_process_notification(p_notification)) - continue; - n->notification(p_notification); + n->call_multilevel(p_method, (const Variant **)v, 1); //ERR_FAIL_COND(node_count != g.nodes.size()); } @@ -993,18 +902,6 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio if (call_lock == 0) call_skip.clear(); } - -/* -void SceneMainLoop::_update_listener_2d() { - - if (listener_2d.is_valid()) { - - SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() ); - } - -} -*/ - Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { r_error.error = Callable::CallError::CALL_OK; @@ -1129,129 +1026,6 @@ int SceneTree::get_node_count() const { return node_count; } -void SceneTree::_update_root_rect() { - - if (stretch_mode == STRETCH_MODE_DISABLED) { - - _update_font_oversampling(1.0); - root->set_size((last_screen_size / stretch_shrink).floor()); - root->set_attach_to_screen_rect(Rect2(Point2(), last_screen_size)); - root->set_size_override_stretch(false); - root->set_size_override(false, Size2()); - root->update_canvas_items(); - return; //user will take care - } - - //actual screen video mode - Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - Size2 desired_res = stretch_min; - - Size2 viewport_size; - Size2 screen_size; - - float viewport_aspect = desired_res.aspect(); - float video_mode_aspect = video_mode.aspect(); - - if (use_font_oversampling && stretch_aspect == STRETCH_ASPECT_IGNORE) { - WARN_PRINT("Font oversampling only works with the resize modes 'Keep Width', 'Keep Height', and 'Expand'."); - } - - if (stretch_aspect == STRETCH_ASPECT_IGNORE || Math::is_equal_approx(viewport_aspect, video_mode_aspect)) { - //same aspect or ignore aspect - viewport_size = desired_res; - screen_size = video_mode; - } else if (viewport_aspect < video_mode_aspect) { - // screen ratio is smaller vertically - - if (stretch_aspect == STRETCH_ASPECT_KEEP_HEIGHT || stretch_aspect == STRETCH_ASPECT_EXPAND) { - - //will stretch horizontally - viewport_size.x = desired_res.y * video_mode_aspect; - viewport_size.y = desired_res.y; - screen_size = video_mode; - - } else { - //will need black bars - viewport_size = desired_res; - screen_size.x = video_mode.y * viewport_aspect; - screen_size.y = video_mode.y; - } - } else { - //screen ratio is smaller horizontally - if (stretch_aspect == STRETCH_ASPECT_KEEP_WIDTH || stretch_aspect == STRETCH_ASPECT_EXPAND) { - - //will stretch horizontally - viewport_size.x = desired_res.x; - viewport_size.y = desired_res.x / video_mode_aspect; - screen_size = video_mode; - - } else { - //will need black bars - viewport_size = desired_res; - screen_size.x = video_mode.x; - screen_size.y = video_mode.x / viewport_aspect; - } - } - - screen_size = screen_size.floor(); - viewport_size = viewport_size.floor(); - - Size2 margin; - Size2 offset; - //black bars and margin - if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.x < video_mode.x) { - margin.x = Math::round((video_mode.x - screen_size.x) / 2.0); - VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); - offset.x = Math::round(margin.x * viewport_size.y / screen_size.y); - } else if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.y < video_mode.y) { - margin.y = Math::round((video_mode.y - screen_size.y) / 2.0); - VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); - offset.y = Math::round(margin.y * viewport_size.x / screen_size.x); - } else { - VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0); - } - - switch (stretch_mode) { - case STRETCH_MODE_DISABLED: { - // Already handled above - _update_font_oversampling(1.0); - } break; - case STRETCH_MODE_2D: { - - _update_font_oversampling(screen_size.x / viewport_size.x); //screen / viewport radio drives oversampling - root->set_size((screen_size / stretch_shrink).floor()); - root->set_attach_to_screen_rect(Rect2(margin, screen_size)); - root->set_size_override_stretch(true); - root->set_size_override(true, (viewport_size / stretch_shrink).floor()); - root->update_canvas_items(); //force them to update just in case - - } break; - case STRETCH_MODE_VIEWPORT: { - - _update_font_oversampling(1.0); - root->set_size((viewport_size / stretch_shrink).floor()); - root->set_attach_to_screen_rect(Rect2(margin, screen_size)); - root->set_size_override_stretch(false); - root->set_size_override(false, Size2()); - root->update_canvas_items(); //force them to update just in case - - if (use_font_oversampling) { - WARN_PRINT("Font oversampling does not work in 'Viewport' stretch mode, only '2D'."); - } - - } break; - } -} - -void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_shrink) { - - stretch_mode = p_mode; - stretch_aspect = p_aspect; - stretch_min = p_minsize; - stretch_shrink = p_shrink; - _update_root_rect(); -} - void SceneTree::set_edited_scene_root(Node *p_node) { #ifdef TOOLS_ENABLED edited_scene_root = p_node; @@ -1330,18 +1104,6 @@ void SceneTree::add_current_scene(Node *p_current) { root->add_child(p_current); } -void SceneTree::drop_files(const Vector<String> &p_files, int p_from_screen) { - - emit_signal("files_dropped", p_files, p_from_screen); - MainLoop::drop_files(p_files, p_from_screen); -} - -void SceneTree::global_menu_action(const Variant &p_id, const Variant &p_meta) { - - emit_signal("global_menu_action", p_id, p_meta); - MainLoop::global_menu_action(p_id, p_meta); -} - Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) { Ref<SceneTreeTimer> stt; @@ -1469,8 +1231,6 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause); ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); - ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled); - ClassDB::bind_method(D_METHOD("is_input_handled"), &SceneTree::is_input_handled); ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true)); @@ -1478,8 +1238,6 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1)); - ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete); MethodInfo mi; @@ -1529,15 +1287,11 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections); ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections); - ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &SceneTree::set_use_font_oversampling); - ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &SceneTree::is_using_font_oversampling); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); @@ -1549,14 +1303,12 @@ void SceneTree::_bind_methods() { ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("screen_resized")); ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("idle_frame")); ADD_SIGNAL(MethodInfo("physics_frame")); ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen"))); - ADD_SIGNAL(MethodInfo("global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta"))); ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("connected_to_server")); @@ -1567,16 +1319,6 @@ void SceneTree::_bind_methods() { BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE); BIND_ENUM_CONSTANT(GROUP_CALL_REALTIME); BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE); - - BIND_ENUM_CONSTANT(STRETCH_MODE_DISABLED); - BIND_ENUM_CONSTANT(STRETCH_MODE_2D); - BIND_ENUM_CONSTANT(STRETCH_MODE_VIEWPORT); - - BIND_ENUM_CONSTANT(STRETCH_ASPECT_IGNORE); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_WIDTH); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_HEIGHT); - BIND_ENUM_CONSTANT(STRETCH_ASPECT_EXPAND); } SceneTree *SceneTree::singleton = NULL; @@ -1596,19 +1338,6 @@ void SceneTree::add_idle_callback(IdleCallback p_callback) { idle_callbacks[idle_callback_count++] = p_callback; } -void SceneTree::set_use_font_oversampling(bool p_oversampling) { - - if (use_font_oversampling == p_oversampling) - return; - - use_font_oversampling = p_oversampling; - _update_root_rect(); -} - -bool SceneTree::is_using_font_oversampling() const { - return use_font_oversampling; -} - void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { if (p_function == "change_scene") { @@ -1648,7 +1377,6 @@ SceneTree::SceneTree() { accept_quit = true; quit_on_go_back = true; initialized = false; - use_font_oversampling = false; #ifdef DEBUG_ENABLED debug_collisions_hint = false; debug_navigation_hint = false; @@ -1665,7 +1393,6 @@ SceneTree::SceneTree() { idle_process_time = 1; root = NULL; - input_handled = false; pause = false; current_frame = 0; current_event = 0; @@ -1680,9 +1407,8 @@ SceneTree::SceneTree() { //create with mainloop - root = memnew(Viewport); + root = memnew(Window); root->set_name("root"); - root->set_handle_input_locally(false); if (!root->get_world().is_valid()) root->set_world(Ref<World>(memnew(World))); @@ -1730,15 +1456,12 @@ SceneTree::SceneTree() { } } - stretch_mode = STRETCH_MODE_DISABLED; - stretch_aspect = STRETCH_ASPECT_IGNORE; - stretch_shrink = 1; - - last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height); - _update_root_rect(); - root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true)); + root->connect("close_requested", callable_mp(this, &SceneTree::_main_window_close)); + root->connect("go_back_requested", callable_mp(this, &SceneTree::_main_window_go_back)); + root->connect("focus_entered", callable_mp(this, &SceneTree::_main_window_focus_in)); + #ifdef TOOLS_ENABLED edited_scene_root = NULL; #endif diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 2f805d074f..e6b2575f98 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -39,9 +39,11 @@ #include "scene/resources/world.h" #include "scene/resources/world_2d.h" +#undef Window + class PackedScene; class Node; -class Viewport; +class Window; class Material; class Mesh; class SceneDebugger; @@ -76,22 +78,6 @@ class SceneTree : public MainLoop { public: typedef void (*IdleCallback)(); - enum StretchMode { - - STRETCH_MODE_DISABLED, - STRETCH_MODE_2D, - STRETCH_MODE_VIEWPORT, - }; - - enum StretchAspect { - - STRETCH_ASPECT_IGNORE, - STRETCH_ASPECT_KEEP, - STRETCH_ASPECT_KEEP_WIDTH, - STRETCH_ASPECT_KEEP_HEIGHT, - STRETCH_ASPECT_EXPAND, - }; - private: struct Group { @@ -101,7 +87,7 @@ private: Group() { changed = false; }; }; - Viewport *root; + Window *root; uint64_t tree_version; float physics_process_time; @@ -119,15 +105,12 @@ private: Map<StringName, Group> group_map; bool _quit; bool initialized; - bool input_handled; - Size2 last_screen_size; StringName tree_changed_name; StringName node_added_name; StringName node_removed_name; StringName node_renamed_name; - bool use_font_oversampling; int64_t current_frame; int64_t current_event; int node_count; @@ -147,14 +130,6 @@ private: int call_lock; Set<Node *> call_skip; //skip erased nodes - StretchMode stretch_mode; - StretchAspect stretch_aspect; - Size2i stretch_min; - real_t stretch_shrink; - - void _update_font_oversampling(float p_ratio); - void _update_root_rect(); - List<ObjectID> delete_queue; Map<UGCall, Vector<Variant>> unique_group_calls; @@ -208,7 +183,6 @@ private: void make_group_changed(const StringName &p_group); void _notify_group_pause(const StringName &p_group, int p_notification); - void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input); Variant _call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Variant _call_group(const Variant **p_args, int p_argcount, Callable::CallError &r_error); @@ -232,6 +206,13 @@ private: static int idle_callback_count; void _call_idle_callbacks(); + void _main_window_focus_in(); + void _main_window_close(); + void _main_window_go_back(); + + //used by viewport + void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport); + protected: void _notification(int p_notification); static void _bind_methods(); @@ -249,7 +230,7 @@ public: GROUP_CALL_MULTILEVEL = 8, }; - _FORCE_INLINE_ Viewport *get_root() const { return root; } + _FORCE_INLINE_ Window *get_root() const { return root; } void call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST); void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification); @@ -261,8 +242,6 @@ public: void flush_transform_notifications(); - virtual void input_text(const String &p_text); - virtual void input_event(const Ref<InputEvent> &p_event); virtual void init(); virtual bool iteration(float p_time); @@ -275,8 +254,6 @@ public: void quit(int p_exit_code = -1); - void set_input_as_handled(); - bool is_input_handled(); _FORCE_INLINE_ float get_physics_process_time() const { return physics_process_time; } _FORCE_INLINE_ float get_idle_process_time() const { return idle_process_time; } @@ -335,11 +312,6 @@ public: void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list); bool has_group(const StringName &p_identifier) const; - void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_shrink = 1); - - void set_use_font_oversampling(bool p_oversampling); - bool is_using_font_oversampling() const; - //void change_scene(const String& p_path); //Node *get_loaded_scene(); @@ -359,8 +331,6 @@ public: static SceneTree *get_singleton() { return singleton; } - void drop_files(const Vector<String> &p_files, int p_from_screen = 0); - void global_menu_action(const Variant &p_id, const Variant &p_meta); void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; //network API @@ -388,8 +358,6 @@ public: ~SceneTree(); }; -VARIANT_ENUM_CAST(SceneTree::StretchMode); -VARIANT_ENUM_CAST(SceneTree::StretchAspect); VARIANT_ENUM_CAST(SceneTree::GroupCallFlags); #endif diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 8ef3bdd04e..e49674663a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -32,7 +32,7 @@ #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" #include "core/os/os.h" #include "core/project_settings.h" #include "scene/2d/collision_object_2d.h" @@ -49,8 +49,10 @@ #include "scene/gui/popup_menu.h" #include "scene/main/canvas_layer.h" #include "scene/main/timer.h" +#include "scene/main/window.h" #include "scene/resources/mesh.h" #include "scene/scene_string_names.h" +#include "servers/display_server.h" #include "servers/physics_2d_server.h" void ViewportTexture::setup_local_to_scene() { @@ -141,7 +143,7 @@ void ViewportTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene); ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SubViewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene"); } ViewportTexture::ViewportTexture() { @@ -166,9 +168,9 @@ ViewportTexture::~ViewportTexture() { ///////////////////////////////////// -class TooltipPanel : public PanelContainer { +class TooltipPanel : public PopupPanel { - GDCLASS(TooltipPanel, PanelContainer); + GDCLASS(TooltipPanel, PopupPanel); public: TooltipPanel(){}; @@ -184,39 +186,25 @@ public: Viewport::GUI::GUI() { + embed_subwindows_hint = false; + embedding_subwindows = false; + dragging = false; mouse_focus = NULL; + forced_mouse_focus = false; mouse_click_grabber = NULL; mouse_focus_mask = 0; key_focus = NULL; mouse_over = NULL; + drag_mouse_over = NULL; tooltip = NULL; tooltip_popup = NULL; tooltip_label = NULL; - subwindow_visibility_dirty = false; - subwindow_order_dirty = false; } ///////////////////////////////////// -void Viewport::_update_stretch_transform() { - - if (size_override_stretch && size_override) { - - stretch_transform = Transform2D(); - Size2 scale = size / (size_override_size + size_override_margin * 2); - stretch_transform.scale(scale); - stretch_transform.elements[2] = size_override_margin * scale; - - } else { - - stretch_transform = Transform2D(); - } - - _update_global_transform(); -} - void Viewport::update_worlds() { if (!is_inside_tree()) @@ -249,6 +237,191 @@ void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera * physics_last_id = id; } +void Viewport::_sub_window_update_order() { + + for (int i = 0; i < gui.sub_windows.size(); i++) { + VS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i); + } +} + +void Viewport::_sub_window_register(Window *p_window) { + + ERR_FAIL_COND(!is_inside_tree()); + for (int i = 0; i < gui.sub_windows.size(); i++) { + ERR_FAIL_COND(gui.sub_windows[i].window == p_window); + } + + if (gui.sub_windows.size() == 0) { + subwindow_canvas = VS::get_singleton()->canvas_create(); + VS::get_singleton()->viewport_attach_canvas(viewport, subwindow_canvas); + VS::get_singleton()->viewport_set_canvas_stacking(viewport, subwindow_canvas, SUBWINDOW_CANVAS_LAYER, 0); + } + SubWindow sw; + sw.canvas_item = VS::get_singleton()->canvas_item_create(); + VS::get_singleton()->canvas_item_set_parent(sw.canvas_item, subwindow_canvas); + sw.window = p_window; + gui.sub_windows.push_back(sw); + + _sub_window_grab_focus(p_window); + + VisualServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, viewport); +} + +void Viewport::_sub_window_update(Window *p_window) { + + int index = -1; + for (int i = 0; i < gui.sub_windows.size(); i++) { + if (gui.sub_windows[i].window == p_window) { + index = i; + break; + } + } + + ERR_FAIL_COND(index == -1); + + const SubWindow &sw = gui.sub_windows[index]; + + Transform2D pos; + pos.set_origin(p_window->get_position()); + VS::get_singleton()->canvas_item_clear(sw.canvas_item); + Rect2i r = Rect2i(p_window->get_position(), sw.window->get_size()); + + if (!p_window->get_flag(Window::FLAG_BORDERLESS)) { + Ref<StyleBox> panel = p_window->get_theme_stylebox("panel_window"); + panel->draw(sw.canvas_item, r); + + // Draw the title bar text. + Ref<Font> title_font = p_window->get_theme_font("title_font"); + Color title_color = p_window->get_theme_color("title_color"); + int title_height = p_window->get_theme_constant("title_height"); + int font_height = title_font->get_height() - title_font->get_descent() * 2; + int x = (r.size.width - title_font->get_string_size(p_window->get_title()).x) / 2; + int y = (-title_height + font_height) / 2; + + int close_h_ofs = p_window->get_theme_constant("close_h_ofs"); + int close_v_ofs = p_window->get_theme_constant("close_v_ofs"); + + title_font->draw(sw.canvas_item, r.position + Point2(x, y), p_window->get_title(), title_color, r.size.width - panel->get_minimum_size().x - close_h_ofs); + + bool hl = gui.subwindow_focused == sw.window && gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE && gui.subwindow_drag_close_inside; + + Ref<Texture2D> close_icon = p_window->get_theme_icon(hl ? "close_highlight" : "close"); + close_icon->draw(sw.canvas_item, r.position + Vector2(r.size.width - close_h_ofs, -close_v_ofs)); + } + + VS::get_singleton()->canvas_item_add_texture_rect(sw.canvas_item, r, sw.window->get_texture()->get_rid()); +} + +void Viewport::_sub_window_grab_focus(Window *p_window) { + + if (p_window == nullptr) { + //release current focus + if (gui.subwindow_focused) { + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + gui.subwindow_focused = nullptr; + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; + } + + Window *this_window = Object::cast_to<Window>(this); + if (this_window) { + this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN); + } + + return; + } + + int index = -1; + for (int i = 0; i < gui.sub_windows.size(); i++) { + if (gui.sub_windows[i].window == p_window) { + index = i; + break; + } + } + + ERR_FAIL_COND(index == -1); + + if (p_window->get_flag(Window::FLAG_NO_FOCUS)) { + //can only move to foreground, but no focus granted + SubWindow sw = gui.sub_windows[index]; + gui.sub_windows.remove(index); + gui.sub_windows.push_back(sw); + index = gui.sub_windows.size() - 1; + _sub_window_update_order(); + return; //i guess not... + } + + if (gui.subwindow_focused) { + if (gui.subwindow_focused == p_window) { + return; //nothing to do + } + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; + } else { + Window *this_window = Object::cast_to<Window>(this); + if (this_window) { + this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + } + } + + Window *old_focus = gui.subwindow_focused; + + gui.subwindow_focused = p_window; + + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN); + + { //move to foreground + SubWindow sw = gui.sub_windows[index]; + gui.sub_windows.remove(index); + gui.sub_windows.push_back(sw); + index = gui.sub_windows.size() - 1; + _sub_window_update_order(); + } + + if (old_focus) { + _sub_window_update(old_focus); + } + + _sub_window_update(p_window); +} + +void Viewport::_sub_window_remove(Window *p_window) { + + for (int i = 0; i < gui.sub_windows.size(); i++) { + if (gui.sub_windows[i].window == p_window) { + VS::get_singleton()->free(gui.sub_windows[i].canvas_item); + gui.sub_windows.remove(i); + break; + } + } + + if (gui.sub_windows.size() == 0) { + VS::get_singleton()->free(subwindow_canvas); + subwindow_canvas = RID(); + } + + if (gui.subwindow_focused == p_window) { + Window *parent_visible = p_window->get_parent_visible_window(); + + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; + + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + + if (parent_visible && parent_visible != this) { + + gui.subwindow_focused = parent_visible; + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN); + } else { + gui.subwindow_focused = nullptr; + Window *this_window = Object::cast_to<Window>(this); + if (this_window) { + this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN); + } + } + } + + VisualServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID()); +} + void Viewport::_own_world_changed() { ERR_FAIL_COND(world.is_null()); ERR_FAIL_COND(own_world.is_null()); @@ -276,6 +449,8 @@ void Viewport::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { + gui.embedding_subwindows = gui.embed_subwindows_hint; + if (get_parent()) { parent = get_parent()->get_viewport(); VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, parent->get_viewport_rid()); @@ -310,7 +485,6 @@ void Viewport::_notification(int p_what) { //VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true); } - VS::get_singleton()->viewport_set_active(viewport, true); } break; case NOTIFICATION_READY: { #ifndef _3D_DISABLED @@ -371,6 +545,7 @@ void Viewport::_notification(int p_what) { remove_from_group("_viewports"); VS::get_singleton()->viewport_set_active(viewport, false); + VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, RID()); } break; case NOTIFICATION_INTERNAL_PROCESS: { @@ -408,7 +583,7 @@ void Viewport::_notification(int p_what) { VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count); } - if (physics_object_picking && (to_screen_rect == Rect2() || Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED)) { + if (physics_object_picking && (to_screen_rect == Rect2i() || InputFilter::get_singleton()->get_mouse_mode() != InputFilter::MOUSE_MODE_CAPTURED)) { #ifndef _3D_DISABLED Vector2 last_pos(1e20, 1e20); @@ -433,6 +608,7 @@ void Viewport::_notification(int p_what) { if (!has_mouse_event) { Ref<InputEventMouseMotion> mm; mm.instance(); + mm->set_device(InputEvent::DEVICE_ID_INTERNAL); mm->set_global_position(physics_last_mousepos); mm->set_position(physics_last_mousepos); @@ -680,13 +856,12 @@ void Viewport::_notification(int p_what) { } } break; - case SceneTree::NOTIFICATION_WM_MOUSE_EXIT: - case SceneTree::NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_MOUSE_EXIT: + case NOTIFICATION_WM_FOCUS_OUT: { _drop_physics_mouseover(); - if (gui.mouse_focus) { - //if mouse is being pressed, send a release event + if (gui.mouse_focus && !gui.forced_mouse_focus) { _drop_mouse_focus(); } } break; @@ -698,16 +873,6 @@ RID Viewport::get_viewport_rid() const { return viewport; } -void Viewport::set_use_arvr(bool p_use_arvr) { - arvr = p_use_arvr; - - VS::get_singleton()->viewport_set_use_arvr(viewport, arvr); -} - -bool Viewport::use_arvr() { - return arvr; -} - void Viewport::update_canvas_items() { if (!is_inside_tree()) return; @@ -715,40 +880,52 @@ void Viewport::update_canvas_items() { _update_canvas_items(this); } -void Viewport::set_size(const Size2 &p_size) { +void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated) { - if (size == p_size.floor()) + if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_override == size_override && to_screen_rect != p_to_screen_rect) return; - size = p_size.floor(); - VS::get_singleton()->viewport_set_size(viewport, size.width, size.height); + size = p_size; + size_allocated = p_allocated; + size_override = p_size_override; + stretch_transform = p_stretch_transform; + to_screen_rect = p_to_screen_rect; + + if (p_allocated) { + VS::get_singleton()->viewport_set_size(viewport, size.width, size.height); + } else { + VS::get_singleton()->viewport_set_size(viewport, 0, 0); + } + _update_global_transform(); - _update_stretch_transform(); + update_canvas_items(); emit_signal("size_changed"); } +Size2i Viewport::_get_size() const { + return size; +} +bool Viewport::_is_size_allocated() const { + return size_allocated; +} + Rect2 Viewport::get_visible_rect() const { Rect2 r; if (size == Size2()) { - r = Rect2(Point2(), OS::get_singleton()->get_window_size()); + r = Rect2(Point2(), DisplayServer::get_singleton()->window_get_size()); } else { r = Rect2(Point2(), size); } - if (size_override) { - r.size = size_override_size; + if (size_override != Size2i()) { + r.size = size_override; } return r; } -Size2 Viewport::get_size() const { - - return size; -} - void Viewport::_update_listener() { /* if (is_inside_tree() && audio_listener && (camera || listener) && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree()))) { @@ -943,7 +1120,9 @@ void Viewport::_camera_set(Camera *p_camera) { if (camera) { camera->notification(Camera::NOTIFICATION_LOST_CURRENT); } + camera = p_camera; + if (!camera_override) { if (camera) VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); @@ -1278,70 +1457,11 @@ void Viewport::_update_canvas_items(Node *p_node) { } } -void Viewport::set_size_override(bool p_enable, const Size2 &p_size, const Vector2 &p_margin) { - - if (size_override == p_enable && p_size == size_override_size) - return; - - size_override = p_enable; - if (p_size.x >= 0 || p_size.y >= 0) { - size_override_size = p_size; - } - size_override_margin = p_margin; - - _update_stretch_transform(); - emit_signal("size_changed"); -} - -Size2 Viewport::get_size_override() const { - - return size_override_size; -} -bool Viewport::is_size_override_enabled() const { - - return size_override; -} -void Viewport::set_size_override_stretch(bool p_enable) { - - if (p_enable == size_override_stretch) - return; - - size_override_stretch = p_enable; - - _update_stretch_transform(); -} - -bool Viewport::is_size_override_stretch_enabled() const { - - return size_override_stretch; -} - -void Viewport::set_update_mode(UpdateMode p_mode) { - - update_mode = p_mode; - VS::get_singleton()->viewport_set_update_mode(viewport, VS::ViewportUpdateMode(p_mode)); -} -Viewport::UpdateMode Viewport::get_update_mode() const { - - return update_mode; -} - Ref<ViewportTexture> Viewport::get_texture() const { return default_texture; } -void Viewport::set_clear_mode(ClearMode p_mode) { - - clear_mode = p_mode; - VS::get_singleton()->viewport_set_clear_mode(viewport, VS::ViewportClearMode(p_mode)); -} - -Viewport::ClearMode Viewport::get_clear_mode() const { - - return clear_mode; -} - void Viewport::set_shadow_atlas_size(int p_size) { if (shadow_atlas_size == p_size) @@ -1379,7 +1499,7 @@ Transform2D Viewport::_get_input_pre_xform() const { Transform2D pre_xf; - if (to_screen_rect != Rect2()) { + if (to_screen_rect.size.x != 0 && to_screen_rect.size.y != 0) { pre_xf.elements[2] = -to_screen_rect.position; pre_xf.scale(size / to_screen_rect.size); @@ -1388,118 +1508,22 @@ Transform2D Viewport::_get_input_pre_xform() const { return pre_xf; } -Vector2 Viewport::_get_window_offset() const { - - if (get_parent() && get_parent()->has_method("get_global_position")) { - return get_parent()->call("get_global_position"); - } - return Vector2(); -} - Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) { - Vector2 vp_ofs = _get_window_offset(); Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform(); - return ev->xformed_by(ai, -vp_ofs); -} - -void Viewport::_vp_input_text(const String &p_text) { - - if (gui.key_focus) { - gui.key_focus->call("set_text", p_text); - } -} - -void Viewport::_vp_input(const Ref<InputEvent> &p_ev) { - - if (disable_input) - return; - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { - return; - } -#endif - - if (to_screen_rect == Rect2()) - return; //if render target, can't get input events - - //this one handles system input, p_ev are in system coordinates - //they are converted to viewport coordinates - - Ref<InputEvent> ev = _make_input_local(p_ev); - input(ev); -} - -void Viewport::_vp_unhandled_input(const Ref<InputEvent> &p_ev) { - - if (disable_input) - return; -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { - return; - } -#endif - - /* - if (parent_control && !parent_control->is_visible_in_tree()) - return; - */ - - if (to_screen_rect == Rect2()) - return; //if render target, can't get input events - - //this one handles system input, p_ev are in system coordinates - //they are converted to viewport coordinates - - Ref<InputEvent> ev = _make_input_local(p_ev); - unhandled_input(ev); + return ev->xformed_by(ai); } Vector2 Viewport::get_mouse_position() const { - return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_position() - _get_window_offset()); + return gui.last_mouse_pos; } void Viewport::warp_mouse(const Vector2 &p_pos) { Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos); - Input::get_singleton()->warp_mouse_position(gpos); -} - -void Viewport::_gui_prepare_subwindows() { - - if (gui.subwindow_visibility_dirty) { - - gui.subwindows.clear(); - for (List<Control *>::Element *E = gui.all_known_subwindows.front(); E; E = E->next()) { - if (E->get()->is_visible_in_tree()) { - gui.subwindows.push_back(E->get()); - } - } - - gui.subwindow_visibility_dirty = false; - gui.subwindow_order_dirty = true; - } - - _gui_sort_subwindows(); -} - -void Viewport::_gui_sort_subwindows() { - - if (!gui.subwindow_order_dirty) - return; - - gui.modal_stack.sort_custom<Control::CComparator>(); - gui.subwindows.sort_custom<Control::CComparator>(); - - gui.subwindow_order_dirty = false; -} - -void Viewport::_gui_sort_modal_stack() { - - gui.modal_stack.sort_custom<Control::CComparator>(); + InputFilter::get_singleton()->warp_mouse_position(gpos); } void Viewport::_gui_sort_roots() { @@ -1575,47 +1599,49 @@ void Viewport::_gui_show_tooltip() { Control *rp = which; - gui.tooltip_popup = which->make_custom_tooltip(tooltip); - - if (!gui.tooltip_popup) { - gui.tooltip_popup = memnew(TooltipPanel); + Control *base_tooltip = which->make_custom_tooltip(tooltip); + if (!base_tooltip) { gui.tooltip_label = memnew(TooltipLabel); - gui.tooltip_popup->add_child(gui.tooltip_label); - - Ref<StyleBox> ttp = gui.tooltip_label->get_stylebox("panel", "TooltipPanel"); - - gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_LEFT)); - gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP)); - gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT)); - gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM)); gui.tooltip_label->set_text(tooltip); + base_tooltip = gui.tooltip_label; } + base_tooltip->set_anchors_and_margins_preset(Control::PRESET_WIDE); + + TooltipPanel *panel = memnew(TooltipPanel); + panel->set_transient(false); + panel->set_flag(Window::FLAG_NO_FOCUS, true); + panel->set_wrap_controls(true); + panel->add_child(base_tooltip); + + gui.tooltip_popup = panel; + rp->add_child(gui.tooltip_popup); - gui.tooltip_popup->force_parent_owned(); - gui.tooltip_popup->set_as_toplevel(true); - if (gui.tooltip) // Avoids crash when rapidly switching controls. - gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale()); + + //if (gui.tooltip) // Avoids crash when rapidly switching controls. + // gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale()); Point2 tooltip_offset = ProjectSettings::get_singleton()->get("display/mouse_cursor/tooltip_position_offset"); - Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_minimum_size()); - Rect2 vr = gui.tooltip_popup->get_viewport_rect(); - if (r.size.x * gui.tooltip_popup->get_scale().x + r.position.x > vr.size.x) - r.position.x = vr.size.x - r.size.x * gui.tooltip_popup->get_scale().x; - else if (r.position.x < 0) - r.position.x = 0; - - if (r.size.y * gui.tooltip_popup->get_scale().y + r.position.y > vr.size.y) - r.position.y = vr.size.y - r.size.y * gui.tooltip_popup->get_scale().y; - else if (r.position.y < 0) - r.position.y = 0; - - gui.tooltip_popup->set_global_position(r.position); + Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_contents_minimum_size()); + + Rect2i vr = gui.tooltip_popup->get_parent_visible_window()->get_usable_parent_rect(); + + if (r.size.x + r.position.x > vr.size.x + vr.position.x) + r.position.x = vr.position.x + vr.size.x - r.size.x; + else if (r.position.x < vr.position.x) + r.position.x = vr.position.x; + + if (r.size.y + r.position.y > vr.size.y + vr.position.y) + r.position.y = vr.position.y + vr.size.y - r.size.y; + else if (r.position.y < vr.position.y) + r.position.y = vr.position.y; + + gui.tooltip_popup->set_position(r.position); gui.tooltip_popup->set_size(r.size); - gui.tooltip_popup->raise(); gui.tooltip_popup->show(); + gui.tooltip_popup->child_controls_changed(); } void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_input) { @@ -1704,26 +1730,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) { } Control *Viewport::_gui_find_control(const Point2 &p_global) { - _gui_prepare_subwindows(); - - for (List<Control *>::Element *E = gui.subwindows.back(); E; E = E->prev()) { - - Control *sw = E->get(); - if (!sw->is_visible_in_tree()) - continue; - - Transform2D xform; - CanvasItem *pci = sw->get_parent_item(); - if (pci) - xform = pci->get_global_transform_with_canvas(); - else - xform = sw->get_canvas_transform(); - - Control *ret = _gui_find_control_at_pos(sw, p_global, xform, gui.focus_inv_xform); - if (ret) - return ret; - } - + //aca va subwindows _gui_sort_roots(); for (List<Control *>::Element *E = gui.roots.back(); E; E = E->prev()) { @@ -1752,8 +1759,6 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_ if (Object::cast_to<Viewport>(p_node)) return NULL; - //subwindows first!! - if (!p_node->is_visible()) { //return _find_next_visible_control_at_pos(p_node,p_global,r_inv_xform); return NULL; //canvas item hidden, discard @@ -1770,9 +1775,6 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_ for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (p_node == gui.tooltip_popup) - continue; - CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i)); if (!ci || ci->is_set_as_toplevel()) continue; @@ -1858,39 +1860,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { bool is_handled = false; - _gui_sort_modal_stack(); - while (!gui.modal_stack.empty()) { - - Control *top = gui.modal_stack.back()->get(); - Vector2 pos2 = top->get_global_transform_with_canvas().affine_inverse().xform(mpos); - if (!top->has_point(pos2)) { - - if (top->data.modal_exclusive || top->data.modal_frame == Engine::get_singleton()->get_frames_drawn()) { - //cancel event, sorry, modal exclusive EATS UP ALL - //alternative, you can't pop out a window the same frame it was made modal (fixes many issues) - set_input_as_handled(); - - return; // no one gets the event if exclusive NO ONE - } - - if (mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_DOWN || mb->get_button_index() == BUTTON_WHEEL_LEFT || mb->get_button_index() == BUTTON_WHEEL_RIGHT) { - //cancel scroll wheel events, only clicks should trigger focus changes. - set_input_as_handled(); - return; - } - - top->notification(Control::NOTIFICATION_MODAL_CLOSE); - top->_modal_stack_remove(); - top->hide(); - - if (!top->pass_on_modal_close_click()) { - is_handled = true; - } - } else { - break; - } - } - if (is_handled) { set_input_as_handled(); return; @@ -1992,11 +1961,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) { - if (gui.mouse_over) { - Size2 pos = mpos; - pos = gui.focus_inv_xform.xform(pos); - - _gui_drop(gui.mouse_over, pos, false); + if (gui.drag_mouse_over) { + _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); } if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) { @@ -2006,6 +1972,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.drag_data = Variant(); gui.dragging = false; + gui.drag_mouse_over = nullptr; _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); //change mouse accordingly } @@ -2029,6 +1996,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { //disable mouse focus if needed before calling input, this makes popups on mouse press event work better, as the release will never be received otherwise if (gui.mouse_focus_mask == 0) { gui.mouse_focus = NULL; + gui.forced_mouse_focus = false; } if (mouse_focus && mouse_focus->can_process()) { @@ -2074,6 +2042,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL) { gui.mouse_focus = NULL; + gui.forced_mouse_focus = false; gui.mouse_focus_mask = 0; break; } else { @@ -2113,45 +2082,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { over = _gui_find_control(mpos); } - if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) { - - Control *top = gui.modal_stack.back()->get(); - - if (over != top && !top->is_a_parent_of(over)) { - - PopupMenu *popup_menu = Object::cast_to<PopupMenu>(top); - MenuButton *popup_menu_parent = NULL; - MenuButton *menu_button = Object::cast_to<MenuButton>(over); - - if (popup_menu) { - popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent()); - if (!popup_menu_parent) { - // Go through the parents to see if there's a MenuButton at the end. - while (Object::cast_to<PopupMenu>(popup_menu->get_parent())) { - popup_menu = Object::cast_to<PopupMenu>(popup_menu->get_parent()); - } - popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent()); - } - } - - // If the mouse is over a menu button, this menu will open automatically - // if there is already a pop-up menu open at the same hierarchical level. - if (popup_menu_parent && menu_button && popup_menu_parent->is_switch_on_hover() && - !menu_button->is_disabled() && menu_button->is_switch_on_hover() && - (popup_menu_parent->get_parent()->is_a_parent_of(menu_button) || - menu_button->get_parent()->is_a_parent_of(popup_menu))) { - - popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE); - popup_menu->_modal_stack_remove(); - popup_menu->hide(); - - menu_button->pressed(); - } else { - over = NULL; //nothing can be found outside the modal stack - } - } - } - if (over != gui.mouse_over) { if (gui.mouse_over) { @@ -2167,103 +2097,195 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.mouse_over = over; - if (gui.drag_preview) { - gui.drag_preview->set_position(mpos); - } + DisplayServer::CursorShape ds_cursor_shape = (DisplayServer::CursorShape)InputFilter::get_singleton()->get_default_cursor_shape(); - if (!over) { - OS::get_singleton()->set_cursor_shape((OS::CursorShape)Input::get_singleton()->get_default_cursor_shape()); - return; - } + if (over) { - Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse(); - Size2 pos = localizer.xform(mpos); - Vector2 speed = localizer.basis_xform(mm->get_speed()); - Vector2 rel = localizer.basis_xform(mm->get_relative()); + Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse(); + Size2 pos = localizer.xform(mpos); + Vector2 speed = localizer.basis_xform(mm->get_speed()); + Vector2 rel = localizer.basis_xform(mm->get_relative()); - mm = mm->xformed_by(Transform2D()); //make a copy + mm = mm->xformed_by(Transform2D()); //make a copy - mm->set_global_position(mpos); - mm->set_speed(speed); - mm->set_relative(rel); + mm->set_global_position(mpos); + mm->set_speed(speed); + mm->set_relative(rel); - if (mm->get_button_mask() == 0) { - //nothing pressed + if (mm->get_button_mask() == 0) { + //nothing pressed - bool can_tooltip = true; + bool can_tooltip = true; - if (!gui.modal_stack.empty()) { - if (gui.modal_stack.back()->get() != over && !gui.modal_stack.back()->get()->is_a_parent_of(over)) - can_tooltip = false; - } + bool is_tooltip_shown = false; + + if (gui.tooltip_popup) { + if (can_tooltip && gui.tooltip) { + String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos)); - bool is_tooltip_shown = false; + if (tooltip.length() == 0) + _gui_cancel_tooltip(); + else if (gui.tooltip_label) { + if (tooltip == gui.tooltip_label->get_text()) { + is_tooltip_shown = true; + } + } else { - if (gui.tooltip_popup) { - if (can_tooltip && gui.tooltip) { - String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos)); + Variant t = gui.tooltip_popup->call("get_tooltip_text"); - if (tooltip.length() == 0) - _gui_cancel_tooltip(); - else if (gui.tooltip_label) { - if (tooltip == gui.tooltip_label->get_text()) { - is_tooltip_shown = true; + if (t.get_type() == Variant::STRING) { + if (tooltip == String(t)) { + is_tooltip_shown = true; + } + } else { + is_tooltip_shown = true; //well, nothing to compare against, likely using custom control, so if it changes there is nothing we can do + } } - } else if (tooltip == String(gui.tooltip_popup->call("get_tooltip_text"))) { - is_tooltip_shown = true; - } - } else - _gui_cancel_tooltip(); + } else + _gui_cancel_tooltip(); + } + + if (can_tooltip && !is_tooltip_shown) { + + gui.tooltip = over; + gui.tooltip_pos = over->get_screen_transform().xform(pos); //(parent_xform * get_transform()).affine_inverse().xform(pos); + gui.tooltip_timer = gui.tooltip_delay; + } } - if (can_tooltip && !is_tooltip_shown) { + //pos = gui.focus_inv_xform.xform(pos); - gui.tooltip = over; - gui.tooltip_pos = mpos; //(parent_xform * get_transform()).affine_inverse().xform(pos); - gui.tooltip_timer = gui.tooltip_delay; + mm->set_position(pos); + + Control::CursorShape cursor_shape = Control::CURSOR_ARROW; + { + Control *c = over; + Vector2 cpos = pos; + while (c) { + cursor_shape = c->get_cursor_shape(cpos); + cpos = c->get_transform().xform(cpos); + if (cursor_shape != Control::CURSOR_ARROW) + break; + if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP) + break; + if (c->is_set_as_toplevel()) + break; + c = c->get_parent_control(); + } } + + ds_cursor_shape = (DisplayServer::CursorShape)cursor_shape; + + if (over && over->can_process()) { + _gui_call_input(over, mm); + } + + set_input_as_handled(); } - //pos = gui.focus_inv_xform.xform(pos); + if (gui.drag_data.get_type() != Variant::NIL) { + //handle dragandrop - mm->set_position(pos); + if (gui.drag_preview) { + gui.drag_preview->set_position(mpos); + } - Control::CursorShape cursor_shape = Control::CURSOR_ARROW; - { - Control *c = over; - Vector2 cpos = pos; - while (c) { - cursor_shape = c->get_cursor_shape(cpos); - cpos = c->get_transform().xform(cpos); - if (cursor_shape != Control::CURSOR_ARROW) - break; - if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP) - break; - if (c->is_set_as_toplevel()) - break; - c = c->get_parent_control(); + gui.drag_mouse_over = over; + gui.drag_mouse_over_pos = Vector2(); + + //find the window this is above of + + //see if there is an embedder + Viewport *embedder = nullptr; + Vector2 viewport_pos; + + if (is_embedding_subwindows()) { + embedder = this; + viewport_pos = mpos; + } else { + //not an embeder, but may be a subwindow of an embedder + Window *w = Object::cast_to<Window>(this); + if (w) { + if (w->is_embedded()) { + embedder = w->_get_embedder(); + + Transform2D ai = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse(); + + viewport_pos = ai.xform(mpos) + w->get_position(); //to parent coords + } + } } - } - OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape); + Viewport *viewport_under = nullptr; - if (over && over->can_process()) { - _gui_call_input(over, mm); - } + if (embedder) { + //use embedder logic - set_input_as_handled(); + for (int i = embedder->gui.sub_windows.size() - 1; i >= 0; i--) { + Window *sw = embedder->gui.sub_windows[i].window; + Rect2 swrect = Rect2i(sw->get_position(), sw->get_size()); + if (!sw->get_flag(Window::FLAG_BORDERLESS)) { + int title_height = sw->get_theme_constant("title_height"); + swrect.position.y -= title_height; + swrect.size.y += title_height; + } - if (gui.drag_data.get_type() != Variant::NIL && mm->get_button_mask() & BUTTON_MASK_LEFT) { + if (swrect.has_point(viewport_pos)) { + viewport_under = sw; + viewport_pos -= sw->get_position(); + } + } - bool can_drop = _gui_drop(over, pos, true); + if (!viewport_under) { + //not in a subwindow, likely in embedder + viewport_under = embedder; + } + } else { + //use displayserver logic + Vector2i screen_mouse_pos = DisplayServer::get_singleton()->mouse_get_position(); + + DisplayServer::WindowID window_id = DisplayServer::get_singleton()->get_window_at_screen_position(screen_mouse_pos); + + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + ObjectID object_under = DisplayServer::get_singleton()->window_get_attached_instance_id(window_id); + + if (object_under != ObjectID()) { //fetch window + Window *w = Object::cast_to<Window>(ObjectDB::get_instance(object_under)); + if (w) { + viewport_under = w; + viewport_pos = screen_mouse_pos - w->get_position(); + } + } + } + } + + if (viewport_under) { + Transform2D ai = (viewport_under->get_final_transform().affine_inverse() * viewport_under->_get_input_pre_xform()); + viewport_pos = ai.xform(viewport_pos); + //find control under at pos + gui.drag_mouse_over = viewport_under->_gui_find_control(viewport_pos); + if (gui.drag_mouse_over) { + Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse(); + gui.drag_mouse_over_pos = localizer.xform(viewport_pos); + + if (mm->get_button_mask() & BUTTON_MASK_LEFT) { + + bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true); + + if (!can_drop) { + ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN; + } else { + ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP; + } + } + } - if (!can_drop) { - OS::get_singleton()->set_cursor_shape(OS::CURSOR_FORBIDDEN); } else { - OS::get_singleton()->set_cursor_shape(OS::CURSOR_CAN_DROP); + gui.drag_mouse_over = nullptr; } - //change mouse accordingly i guess } + + DisplayServer::get_singleton()->cursor_set_shape(ds_cursor_shape); } Ref<InputEventScreenTouch> touch_event = p_event; @@ -2275,14 +2297,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *over = _gui_find_control(pos); if (over) { - if (!gui.modal_stack.empty()) { - - Control *top = gui.modal_stack.back()->get(); - if (over != top && !top->is_a_parent_of(over)) { - - return; - } - } if (over->can_process()) { touch_event = touch_event->xformed_by(Transform2D()); //make a copy @@ -2348,14 +2362,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } if (over) { - if (!gui.modal_stack.empty()) { - - Control *top = gui.modal_stack.back()->get(); - if (over != top && !top->is_a_parent_of(over)) { - - return; - } - } if (over->can_process()) { Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse(); @@ -2399,21 +2405,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } } - if (p_event->is_pressed() && p_event->is_action("ui_cancel") && !gui.modal_stack.empty()) { - - _gui_sort_modal_stack(); - Control *top = gui.modal_stack.back()->get(); - if (!top->data.modal_exclusive) { - - top->notification(Control::NOTIFICATION_MODAL_CLOSE); - top->_modal_stack_remove(); - top->hide(); - // Close modal, set input as handled - set_input_as_handled(); - return; - } - } - Control *from = gui.key_focus ? gui.key_focus : NULL; //hmm //keyboard focus @@ -2426,7 +2417,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (from && p_event->is_pressed()) { Control *next = NULL; - Input *input = Input::get_singleton(); + InputFilter *input = InputFilter::get_singleton(); if (p_event->is_action_pressed("ui_focus_next") && input->is_action_just_pressed("ui_focus_next")) { @@ -2472,61 +2463,10 @@ List<Control *>::Element *Viewport::_gui_add_root_control(Control *p_control) { return gui.roots.push_back(p_control); } -List<Control *>::Element *Viewport::_gui_add_subwindow_control(Control *p_control) { - - p_control->connect("visibility_changed", callable_mp(this, &Viewport::_subwindow_visibility_changed)); - - if (p_control->is_visible_in_tree()) { - gui.subwindow_order_dirty = true; - gui.subwindows.push_back(p_control); - } - - return gui.all_known_subwindows.push_back(p_control); -} - -void Viewport::_gui_set_subwindow_order_dirty() { - gui.subwindow_order_dirty = true; -} - void Viewport::_gui_set_root_order_dirty() { gui.roots_order_dirty = true; } -void Viewport::_gui_remove_modal_control(List<Control *>::Element *MI) { - - gui.modal_stack.erase(MI); -} - -void Viewport::_gui_remove_from_modal_stack(List<Control *>::Element *MI, ObjectID p_prev_focus_owner) { - - //transfer the focus stack to the next - - List<Control *>::Element *next = MI->next(); - - gui.modal_stack.erase(MI); - - if (p_prev_focus_owner.is_valid()) { - - // for previous window in stack, pass the focus so it feels more - // natural - - if (!next) { //top of stack - - Object *pfo = ObjectDB::get_instance(p_prev_focus_owner); - Control *pfoc = Object::cast_to<Control>(pfo); - if (!pfoc) - return; - - if (!pfoc->is_inside_tree() || !pfoc->is_visible_in_tree()) - return; - pfoc->grab_focus(); - } else { - - next->get()->_modal_set_prev_focus_owner(p_prev_focus_owner); - } - } -} - void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control) { ERR_FAIL_COND_MSG(p_data.get_type() == Variant::NIL, "Drag data must be a value."); @@ -2563,21 +2503,6 @@ void Viewport::_gui_remove_root_control(List<Control *>::Element *RI) { gui.roots.erase(RI); } -void Viewport::_gui_remove_subwindow_control(List<Control *>::Element *SI) { - - ERR_FAIL_COND(!SI); - - Control *control = SI->get(); - - control->disconnect("visibility_changed", callable_mp(this, &Viewport::_subwindow_visibility_changed)); - - List<Control *>::Element *E = gui.subwindows.find(control); - if (E) - gui.subwindows.erase(E); - - gui.all_known_subwindows.erase(SI); -} - void Viewport::_gui_unfocus_control(Control *p_control) { if (gui.key_focus == p_control) { @@ -2605,6 +2530,8 @@ void Viewport::_gui_hid_control(Control *p_control) { _gui_remove_focus(); if (gui.mouse_over == p_control) gui.mouse_over = NULL; + if (gui.drag_mouse_over == p_control) + gui.drag_mouse_over = NULL; if (gui.tooltip == p_control) _gui_cancel_tooltip(); } @@ -2613,6 +2540,7 @@ void Viewport::_gui_remove_control(Control *p_control) { if (gui.mouse_focus == p_control) { gui.mouse_focus = NULL; + gui.forced_mouse_focus = false; gui.mouse_focus_mask = 0; } if (gui.last_mouse_focus == p_control) { @@ -2622,11 +2550,10 @@ void Viewport::_gui_remove_control(Control *p_control) { gui.key_focus = NULL; if (gui.mouse_over == p_control) gui.mouse_over = NULL; + if (gui.drag_mouse_over == p_control) + gui.drag_mouse_over = NULL; if (gui.tooltip == p_control) gui.tooltip = NULL; - if (gui.tooltip_popup == p_control) { - _gui_cancel_tooltip(); - } } void Viewport::_gui_remove_focus() { @@ -2638,11 +2565,6 @@ void Viewport::_gui_remove_focus() { } } -bool Viewport::_gui_is_modal_on_top(const Control *p_control) { - - return (gui.modal_stack.size() && gui.modal_stack.back()->get() == p_control); -} - bool Viewport::_gui_control_has_focus(const Control *p_control) { return gui.key_focus == p_control; @@ -2672,6 +2594,7 @@ void Viewport::_drop_mouse_focus() { Control *c = gui.mouse_focus; int mask = gui.mouse_focus_mask; gui.mouse_focus = NULL; + gui.forced_mouse_focus = false; gui.mouse_focus_mask = 0; for (int i = 0; i < 3; i++) { @@ -2714,22 +2637,6 @@ void Viewport::_drop_physics_mouseover() { #endif } -List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) { - - List<Control *>::Element *node = gui.modal_stack.push_back(p_control); - if (gui.key_focus) - p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_id()); - else - p_control->_modal_set_prev_focus_owner(ObjectID()); - - if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus) && !gui.mouse_click_grabber) { - - _drop_mouse_focus(); - } - - return node; -} - Control *Viewport::_gui_get_focus_owner() { return gui.key_focus; @@ -2798,44 +2705,390 @@ void Viewport::_post_gui_grab_click_focus() { /////////////////////////////// -void Viewport::input(const Ref<InputEvent> &p_event) { +void Viewport::input_text(const String &p_text) { + + if (gui.subwindow_focused) { + gui.subwindow_focused->input_text(p_text); + return; + } + + if (gui.key_focus) { + gui.key_focus->call("set_text", p_text); + } +} +Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point) { + + if (p_subwindow->get_flag(Window::FLAG_BORDERLESS)) { + return SUB_WINDOW_RESIZE_DISABLED; + } + + Rect2i r = Rect2i(p_subwindow->get_position(), p_subwindow->get_size()); + + int title_height = p_subwindow->get_theme_constant("title_height"); + + r.position.y -= title_height; + r.size.y += title_height; + + if (r.has_point(p_point)) { + return SUB_WINDOW_RESIZE_DISABLED; //it's inside, so no resize + } + + int dist_x = p_point.x < r.position.x ? (p_point.x - r.position.x) : (p_point.x > (r.position.x + r.size.x) ? (p_point.x - (r.position.x + r.size.x)) : 0); + int dist_y = p_point.y < r.position.y ? (p_point.y - r.position.y) : (p_point.y > (r.position.y + r.size.y) ? (p_point.y - (r.position.y + r.size.y)) : 0); + + int limit = p_subwindow->get_theme_constant("resize_margin"); + + if (ABS(dist_x) > limit) { + return SUB_WINDOW_RESIZE_DISABLED; + } + + if (ABS(dist_y) > limit) { + return SUB_WINDOW_RESIZE_DISABLED; + } + + if (dist_x < 0 && dist_y < 0) { + return SUB_WINDOW_RESIZE_TOP_LEFT; + } + + if (dist_x == 0 && dist_y < 0) { + return SUB_WINDOW_RESIZE_TOP; + } + + if (dist_x > 0 && dist_y < 0) { + return SUB_WINDOW_RESIZE_TOP_RIGHT; + } + + if (dist_x < 0 && dist_y == 0) { + return SUB_WINDOW_RESIZE_LEFT; + } + + if (dist_x > 0 && dist_y == 0) { + return SUB_WINDOW_RESIZE_RIGHT; + } + + if (dist_x < 0 && dist_y > 0) { + return SUB_WINDOW_RESIZE_BOTTOM_LEFT; + } + + if (dist_x == 0 && dist_y > 0) { + return SUB_WINDOW_RESIZE_BOTTOM; + } + + if (dist_x > 0 && dist_y > 0) { + return SUB_WINDOW_RESIZE_BOTTOM_RIGHT; + } + + return SUB_WINDOW_RESIZE_DISABLED; +} +bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { + + if (gui.subwindow_drag != SUB_WINDOW_DRAG_DISABLED) { + + ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false); + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + + if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) { + if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) { + //close window + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST); + } + } + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; + if (gui.subwindow_focused != nullptr) { //may have been erased + _sub_window_update(gui.subwindow_focused); + } + } + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + + if (gui.subwindow_drag == SUB_WINDOW_DRAG_MOVE) { + Vector2 diff = mm->get_position() - gui.subwindow_drag_from; + Rect2i new_rect(gui.subwindow_drag_pos + diff, gui.subwindow_focused->get_size()); + gui.subwindow_focused->_rect_changed_callback(new_rect); + } + if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) { + gui.subwindow_drag_close_inside = gui.subwindow_drag_close_rect.has_point(mm->get_position()); + } + if (gui.subwindow_drag == SUB_WINDOW_DRAG_RESIZE) { + Vector2i diff = mm->get_position() - gui.subwindow_drag_from; + Size2i min_size = gui.subwindow_focused->get_min_size(); + if (gui.subwindow_focused->is_wrapping_controls()) { + Size2i cms = gui.subwindow_focused->get_contents_minimum_size(); + min_size.x = MAX(cms.x, min_size.x); + min_size.y = MAX(cms.y, min_size.y); + } + min_size.x = MAX(min_size.x, 1); + min_size.y = MAX(min_size.y, 1); + + Rect2i r = gui.subwindow_resize_from_rect; + + Size2i limit = r.size - min_size; + + switch (gui.subwindow_resize_mode) { + case SUB_WINDOW_RESIZE_TOP_LEFT: { + + diff.x = MIN(diff.x, limit.x); + diff.y = MIN(diff.y, limit.y); + r.position += diff; + r.size -= diff; + } break; + case SUB_WINDOW_RESIZE_TOP: { + diff.x = 0; + diff.y = MIN(diff.y, limit.y); + r.position += diff; + r.size -= diff; + } break; + case SUB_WINDOW_RESIZE_TOP_RIGHT: { + diff.x = MAX(diff.x, -limit.x); + diff.y = MIN(diff.y, limit.y); + r.position.y += diff.y; + r.size.y -= diff.y; + r.size.x += diff.x; + } break; + case SUB_WINDOW_RESIZE_LEFT: { + diff.x = MIN(diff.x, limit.x); + diff.y = 0; + r.position += diff; + r.size -= diff; + + } break; + case SUB_WINDOW_RESIZE_RIGHT: { + diff.x = MAX(diff.x, -limit.x); + r.size.x += diff.x; + } break; + case SUB_WINDOW_RESIZE_BOTTOM_LEFT: { + diff.x = MIN(diff.x, limit.x); + diff.y = MAX(diff.y, -limit.y); + r.position.x += diff.x; + r.size.x -= diff.x; + r.size.y += diff.y; + + } break; + case SUB_WINDOW_RESIZE_BOTTOM: { + diff.y = MAX(diff.y, -limit.y); + r.size.y += diff.y; + } break; + case SUB_WINDOW_RESIZE_BOTTOM_RIGHT: { + diff.x = MAX(diff.x, -limit.x); + diff.y = MAX(diff.y, -limit.y); + r.size += diff; + + } break; + default: { + } + } + + gui.subwindow_focused->_rect_changed_callback(r); + } + + if (gui.subwindow_focused) { //may have been erased + _sub_window_update(gui.subwindow_focused); + } + } + + return true; //handled + } + Ref<InputEventMouseButton> mb = p_event; + //if the event is a mouse button, we need to check whether another window was clicked + + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + + bool click_on_window = false; + for (int i = gui.sub_windows.size() - 1; i >= 0; i--) { + SubWindow &sw = gui.sub_windows.write[i]; + + //clicked inside window? + + Rect2i r = Rect2i(sw.window->get_position(), sw.window->get_size()); + + if (!sw.window->get_flag(Window::FLAG_BORDERLESS)) { + //check top bar + int title_height = sw.window->get_theme_constant("title_height"); + Rect2i title_bar = r; + title_bar.position.y -= title_height; + title_bar.size.y = title_height; + + if (title_bar.has_point(mb->get_position())) { + + click_on_window = true; + + int close_h_ofs = sw.window->get_theme_constant("close_h_ofs"); + int close_v_ofs = sw.window->get_theme_constant("close_v_ofs"); + Ref<Texture2D> close_icon = sw.window->get_theme_icon("close"); + + Rect2 close_rect; + close_rect.position = Vector2(r.position.x + r.size.x - close_v_ofs, r.position.y - close_h_ofs); + close_rect.size = close_icon->get_size(); + + if (gui.subwindow_focused != sw.window) { + //refocus + _sub_window_grab_focus(sw.window); + } + + if (close_rect.has_point(mb->get_position())) { + + gui.subwindow_drag = SUB_WINDOW_DRAG_CLOSE; + gui.subwindow_drag_close_inside = true; //starts inside + gui.subwindow_drag_close_rect = close_rect; + } else { + + gui.subwindow_drag = SUB_WINDOW_DRAG_MOVE; + } + + gui.subwindow_drag_from = mb->get_position(); + gui.subwindow_drag_pos = sw.window->get_position(); + + _sub_window_update(sw.window); + } else { + gui.subwindow_resize_mode = _sub_window_get_resize_margin(sw.window, mb->get_position()); + if (gui.subwindow_resize_mode != SUB_WINDOW_RESIZE_DISABLED) { + gui.subwindow_resize_from_rect = r; + gui.subwindow_drag_from = mb->get_position(); + gui.subwindow_drag = SUB_WINDOW_DRAG_RESIZE; + click_on_window = true; + } + } + } + if (!click_on_window && r.has_point(mb->get_position())) { + //clicked, see if it needs to fetch focus + if (gui.subwindow_focused != sw.window) { + //refocus + _sub_window_grab_focus(sw.window); + } + + click_on_window = true; + } + + if (click_on_window) { + break; + } + } + + if (!click_on_window && gui.subwindow_focused) { + //no window found and clicked, remove focus + _sub_window_grab_focus(nullptr); + } + } + + if (gui.subwindow_focused) { + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + + SubWindowResize resize = _sub_window_get_resize_margin(gui.subwindow_focused, mm->get_position()); + if (resize != SUB_WINDOW_RESIZE_DISABLED) { + + DisplayServer::CursorShape shapes[SUB_WINDOW_RESIZE_MAX] = { + DisplayServer::CURSOR_ARROW, + DisplayServer::CURSOR_FDIAGSIZE, + DisplayServer::CURSOR_VSIZE, + DisplayServer::CURSOR_BDIAGSIZE, + DisplayServer::CURSOR_HSIZE, + DisplayServer::CURSOR_HSIZE, + DisplayServer::CURSOR_BDIAGSIZE, + DisplayServer::CURSOR_VSIZE, + DisplayServer::CURSOR_FDIAGSIZE + }; + + DisplayServer::get_singleton()->cursor_set_shape(shapes[resize]); + + return true; //reserved for showing the resize cursor + } + } + } + + if (gui.subwindow_drag != SUB_WINDOW_DRAG_DISABLED) { + return true; // dragging, don't pass the event + } + + if (!gui.subwindow_focused) { + return false; + } + + Transform2D window_ofs; + window_ofs.set_origin(-gui.subwindow_focused->get_position()); + + Ref<InputEvent> ev = p_event->xformed_by(window_ofs); + + gui.subwindow_focused->_window_input(ev); + + return true; +} + +void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) { ERR_FAIL_COND(!is_inside_tree()); + if (disable_input) + return; + + if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + return; + } + local_input_handled = false; + Ref<InputEvent> ev; + if (!p_local_coords) { + ev = _make_input_local(p_event); + } else { + ev = p_event; + } + + if (is_embedding_subwindows() && _sub_windows_forward_input(p_event)) { + set_input_as_handled(); + return; + } + if (!is_input_handled()) { - get_tree()->_call_input_pause(input_group, "_input", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input + get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input } if (!is_input_handled()) { - _gui_input_event(p_event); + _gui_input_event(ev); } - //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check + //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",ev); //special one for GUI, as controls use their own process check } -void Viewport::unhandled_input(const Ref<InputEvent> &p_event) { +void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) { ERR_FAIL_COND(!is_inside_tree()); - get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", p_event); + if (disable_input) + return; + + if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + return; + } + + Ref<InputEvent> ev; + if (!p_local_coords) { + ev = _make_input_local(p_event); + } else { + ev = p_event; + } + + get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev); - if (!get_tree()->input_handled && Object::cast_to<InputEventKey>(*p_event) != NULL) { - get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", p_event); + if (!is_input_handled() && Object::cast_to<InputEventKey>(*ev) != NULL) { + get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this); //call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev); } - if (physics_object_picking && !get_tree()->input_handled) { + if (physics_object_picking && !is_input_handled()) { - if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED && - (Object::cast_to<InputEventMouseButton>(*p_event) || - Object::cast_to<InputEventMouseMotion>(*p_event) || - Object::cast_to<InputEventScreenDrag>(*p_event) || - Object::cast_to<InputEventScreenTouch>(*p_event) || - Object::cast_to<InputEventKey>(*p_event) //to remember state + if (InputFilter::get_singleton()->get_mouse_mode() != InputFilter::MOUSE_MODE_CAPTURED && + (Object::cast_to<InputEventMouseButton>(*ev) || + Object::cast_to<InputEventMouseMotion>(*ev) || + Object::cast_to<InputEventScreenDrag>(*ev) || + Object::cast_to<InputEventScreenTouch>(*ev) || + Object::cast_to<InputEventKey>(*ev) //to remember state )) { - physics_picking_events.push_back(p_event); + physics_picking_events.push_back(ev); } } } @@ -2877,30 +3130,6 @@ bool Viewport::is_using_own_world() const { return own_world.is_valid(); } -void Viewport::set_attach_to_screen_rect(const Rect2 &p_rect) { - - VS::get_singleton()->viewport_attach_to_screen(viewport, p_rect); - to_screen_rect = p_rect; -} - -Rect2 Viewport::get_attach_to_screen_rect() const { - - return to_screen_rect; -} - -void Viewport::set_use_render_direct_to_screen(bool p_render_direct_to_screen) { - - if (p_render_direct_to_screen == render_direct_to_screen) - return; - - render_direct_to_screen = p_render_direct_to_screen; - VS::get_singleton()->viewport_set_render_direct_to_screen(viewport, p_render_direct_to_screen); -} - -bool Viewport::is_using_render_direct_to_screen() const { - return render_direct_to_screen; -} - void Viewport::set_physics_object_picking(bool p_enable) { physics_object_picking = p_enable; @@ -2925,11 +3154,6 @@ Vector2 Viewport::get_camera_rect_size() const { return size; } -bool Viewport::gui_has_modal_stack() const { - - return gui.modal_stack.size(); -} - void Viewport::set_disable_input(bool p_disable) { disable_input = p_disable; } @@ -2943,10 +3167,6 @@ Variant Viewport::gui_get_drag_data() const { return gui.drag_data; } -Control *Viewport::get_modal_stack_top() const { - return gui.modal_stack.size() ? gui.modal_stack.back()->get() : NULL; -} - String Viewport::get_configuration_warning() const { /*if (get_parent() && !Object::cast_to<Control>(get_parent()) && !render_target) { @@ -3017,7 +3237,17 @@ void Viewport::set_input_as_handled() { local_input_handled = true; } else { ERR_FAIL_COND(!is_inside_tree()); - get_tree()->set_input_as_handled(); + Viewport *vp = this; + while (true) { + if (Object::cast_to<Window>(vp)) { + break; + } + if (!vp->get_parent()) { + break; + } + vp = vp->get_parent()->get_viewport(); + } + vp->set_input_as_handled(); } } @@ -3025,8 +3255,17 @@ bool Viewport::is_input_handled() const { if (handle_input_locally) { return local_input_handled; } else { - ERR_FAIL_COND_V(!is_inside_tree(), false); - return get_tree()->is_input_handled(); + const Viewport *vp = this; + while (true) { + if (Object::cast_to<Window>(vp)) { + break; + } + if (!vp->get_parent()) { + break; + } + vp = vp->get_parent()->get_viewport(); + } + return vp->is_input_handled(); } } @@ -3086,13 +3325,47 @@ void Viewport::_propagate_update_default_repeat(Node *p_node) { } } -void Viewport::_bind_methods() { +DisplayServer::WindowID Viewport::get_window_id() const { + return DisplayServer::MAIN_WINDOW_ID; +} - ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr); - ClassDB::bind_method(D_METHOD("use_arvr"), &Viewport::use_arvr); +Viewport *Viewport::get_parent_viewport() const { + ERR_FAIL_COND_V(!is_inside_tree(), nullptr); + if (!get_parent()) { + return nullptr; //root viewport + } + + return get_parent()->get_viewport(); +} + +void Viewport::set_embed_subwindows_hint(bool p_embed) { + gui.embed_subwindows_hint = p_embed; +} +bool Viewport::get_embed_subwindows_hint() const { + return gui.embed_subwindows_hint; +} +bool Viewport::is_embedding_subwindows() const { + return gui.embed_subwindows_hint; +} + +void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) { + ERR_FAIL_NULL(p_viewport); + ERR_FAIL_NULL(p_control); + + if (gui.mouse_focus) { + p_viewport->gui.mouse_focus = p_control; + p_viewport->gui.mouse_focus_mask = gui.mouse_focus_mask; + p_viewport->gui.key_focus = p_control; + p_viewport->gui.forced_mouse_focus = true; + + gui.mouse_focus = nullptr; + gui.forced_mouse_focus = false; + gui.mouse_focus_mask = 0; + } +} + +void Viewport::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size); - ClassDB::bind_method(D_METHOD("get_size"), &Viewport::get_size); ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d); ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d); ClassDB::bind_method(D_METHOD("find_world_2d"), &Viewport::find_world_2d); @@ -3111,22 +3384,6 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_transparent_background", "enable"), &Viewport::set_transparent_background); ClassDB::bind_method(D_METHOD("has_transparent_background"), &Viewport::has_transparent_background); - ClassDB::bind_method(D_METHOD("_vp_input"), &Viewport::_vp_input); - ClassDB::bind_method(D_METHOD("_vp_input_text", "text"), &Viewport::_vp_input_text); - ClassDB::bind_method(D_METHOD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input); - - ClassDB::bind_method(D_METHOD("set_size_override", "enable", "size", "margin"), &Viewport::set_size_override, DEFVAL(Size2(-1, -1)), DEFVAL(Size2(0, 0))); - ClassDB::bind_method(D_METHOD("get_size_override"), &Viewport::get_size_override); - ClassDB::bind_method(D_METHOD("is_size_override_enabled"), &Viewport::is_size_override_enabled); - ClassDB::bind_method(D_METHOD("set_size_override_stretch", "enabled"), &Viewport::set_size_override_stretch); - ClassDB::bind_method(D_METHOD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled); - - ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &Viewport::set_clear_mode); - ClassDB::bind_method(D_METHOD("get_clear_mode"), &Viewport::get_clear_mode); - - ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &Viewport::set_update_mode); - ClassDB::bind_method(D_METHOD("get_update_mode"), &Viewport::get_update_mode); - ClassDB::bind_method(D_METHOD("set_msaa", "msaa"), &Viewport::set_msaa); ClassDB::bind_method(D_METHOD("get_msaa"), &Viewport::get_msaa); @@ -3141,8 +3398,9 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking); ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid); - ClassDB::bind_method(D_METHOD("input", "local_event"), &Viewport::input); - ClassDB::bind_method(D_METHOD("unhandled_input", "local_event"), &Viewport::unhandled_input); + ClassDB::bind_method(D_METHOD("input_text", "text"), &Viewport::input_text); + ClassDB::bind_method(D_METHOD("input", "event", "in_local_coords"), &Viewport::input, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("unhandled_input", "event", "in_local_coords"), &Viewport::unhandled_input, DEFVAL(false)); ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds); @@ -3156,19 +3414,13 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d); ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d); - ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect); - ClassDB::bind_method(D_METHOD("set_use_render_direct_to_screen", "enable"), &Viewport::set_use_render_direct_to_screen); - ClassDB::bind_method(D_METHOD("is_using_render_direct_to_screen"), &Viewport::is_using_render_direct_to_screen); ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position); ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse); - ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack); ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data); ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging); - ClassDB::bind_method(D_METHOD("get_modal_stack_top"), &Viewport::get_modal_stack_top); - ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input); ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); @@ -3194,13 +3446,13 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_filter", "mode"), &Viewport::set_default_canvas_item_texture_filter); ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_filter"), &Viewport::get_default_canvas_item_texture_filter); + ClassDB::bind_method(D_METHOD("set_embed_subwindows_hint", "enable"), &Viewport::set_embed_subwindows_hint); + ClassDB::bind_method(D_METHOD("get_embed_subwindows_hint"), &Viewport::get_embed_subwindows_hint); + ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows); + ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat); ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr"); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_override_stretch"), "set_size_override_stretch", "is_size_override_stretch_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world"), "set_use_own_world", "is_using_own_world"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World"), "set_world", "get_world"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d"); @@ -3208,11 +3460,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally"); ADD_GROUP("Rendering", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_direct_to_screen"), "set_use_render_direct_to_screen", "is_using_render_direct_to_screen"); ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw"); - ADD_GROUP("Render Target", "render_target_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode"); ADD_GROUP("Canvas Items", "canvas_item_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat"); @@ -3224,6 +3472,7 @@ void Viewport::_bind_methods() { ADD_GROUP("GUI", "gui_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint"); ADD_GROUP("Shadow Atlas", "shadow_atlas_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size"); ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0); @@ -3236,11 +3485,6 @@ void Viewport::_bind_methods() { ADD_SIGNAL(MethodInfo("size_changed")); ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); - BIND_ENUM_CONSTANT(UPDATE_DISABLED); - BIND_ENUM_CONSTANT(UPDATE_ONCE); - BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE); - BIND_ENUM_CONSTANT(UPDATE_ALWAYS); - BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED); BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1); BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_4); @@ -3277,10 +3521,6 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(MSAA_8X); BIND_ENUM_CONSTANT(MSAA_16X); - BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS); - BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER); - BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME); - BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST); BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR); BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); @@ -3293,13 +3533,6 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX); } -void Viewport::_subwindow_visibility_changed() { - - // unfortunately, we don't know the sender, i.e. which subwindow changed; - // so we have to check them all. - gui.subwindow_visibility_dirty = true; -} - Viewport::Viewport() { world_2d = Ref<World2D>(memnew(World2D)); @@ -3307,8 +3540,6 @@ Viewport::Viewport() { viewport = VisualServer::get_singleton()->viewport_create(); texture_rid = VisualServer::get_singleton()->viewport_get_texture(viewport); - render_direct_to_screen = false; - default_texture.instance(); default_texture->vp = const_cast<Viewport *>(this); viewport_textures.insert(default_texture.ptr()); @@ -3324,14 +3555,10 @@ Viewport::Viewport() { camera = NULL; override_canvas_transform = false; canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport) - arvr = false; - size_override = false; - size_override_stretch = false; - size_override_size = Size2(1, 1); + gen_mipmaps = false; //clear=true; - update_mode = UPDATE_WHEN_VISIBLE; physics_object_picking = false; physics_has_last_mousepos = false; @@ -3368,12 +3595,14 @@ Viewport::Viewport() { gui.canvas_sort_index = 0; gui.roots_order_dirty = false; gui.mouse_focus = NULL; + gui.forced_mouse_focus = false; gui.last_mouse_focus = NULL; + gui.subwindow_focused = nullptr; + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; msaa = MSAA_DISABLED; debug_draw = DEBUG_DRAW_DISABLED; - clear_mode = CLEAR_MODE_ALWAYS; snap_controls_to_pixels = true; physics_last_mouse_state.alt = false; @@ -3384,6 +3613,8 @@ Viewport::Viewport() { local_input_handled = false; handle_input_locally = true; + size_allocated = false; + default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR; default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; } @@ -3398,3 +3629,95 @@ Viewport::~Viewport() { //SpatialSoundServer::get_singleton()->free(internal_listener); //SpatialSound2DServer::get_singleton()->free(internal_listener_2d); } + +///////////////////////////////// + +void SubViewport::set_use_arvr(bool p_use_arvr) { + arvr = p_use_arvr; + + VS::get_singleton()->viewport_set_use_arvr(get_viewport_rid(), arvr); +} + +bool SubViewport::is_using_arvr() { + return arvr; +} + +void SubViewport::set_size(const Size2i &p_size) { + _set_size(p_size, Size2i(), Rect2i(), Transform2D(), true); +} +Size2i SubViewport::get_size() const { + return _get_size(); +} + +void SubViewport::set_update_mode(UpdateMode p_mode) { + + update_mode = p_mode; + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::ViewportUpdateMode(p_mode)); +} +SubViewport::UpdateMode SubViewport::get_update_mode() const { + + return update_mode; +} + +void SubViewport::set_clear_mode(ClearMode p_mode) { + + clear_mode = p_mode; + VS::get_singleton()->viewport_set_clear_mode(get_viewport_rid(), VS::ViewportClearMode(p_mode)); +} + +SubViewport::ClearMode SubViewport::get_clear_mode() const { + + return clear_mode; +} + +DisplayServer::WindowID SubViewport::get_window_id() const { + return DisplayServer::INVALID_WINDOW_ID; +} + +void SubViewport::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + VS::get_singleton()->viewport_set_active(get_viewport_rid(), true); + } + if (p_what == NOTIFICATION_EXIT_TREE) { + VS::get_singleton()->viewport_set_active(get_viewport_rid(), false); + } +} + +void SubViewport::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &SubViewport::set_use_arvr); + ClassDB::bind_method(D_METHOD("is_using_arvr"), &SubViewport::is_using_arvr); + + ClassDB::bind_method(D_METHOD("set_size", "size"), &SubViewport::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &SubViewport::get_size); + + ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &SubViewport::set_update_mode); + ClassDB::bind_method(D_METHOD("get_update_mode"), &SubViewport::get_update_mode); + + ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &SubViewport::set_clear_mode); + ClassDB::bind_method(D_METHOD("get_clear_mode"), &SubViewport::get_clear_mode); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "is_using_arvr"); + ADD_GROUP("Render Target", "render_target_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode"); + + BIND_ENUM_CONSTANT(UPDATE_DISABLED); + BIND_ENUM_CONSTANT(UPDATE_ONCE); + BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE); + BIND_ENUM_CONSTANT(UPDATE_WHEN_PARENT_VISIBLE); + BIND_ENUM_CONSTANT(UPDATE_ALWAYS); + + BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS); + BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER); + BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME); +} + +SubViewport::SubViewport() { + arvr = false; + update_mode = UPDATE_WHEN_VISIBLE; + clear_mode = CLEAR_MODE_ALWAYS; +} + +SubViewport::~SubViewport() { +} diff --git a/scene/main/viewport.h b/scene/main/viewport.h index e511ce1b17..6b68bc0c94 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -35,6 +35,7 @@ #include "scene/main/node.h" #include "scene/resources/texture.h" #include "scene/resources/world_2d.h" +#include "servers/display_server.h" #include "servers/visual_server.h" class Camera; @@ -88,13 +89,6 @@ class Viewport : public Node { GDCLASS(Viewport, Node); public: - enum UpdateMode { - UPDATE_DISABLED, - UPDATE_ONCE, //then goes to disabled - UPDATE_WHEN_VISIBLE, // default - UPDATE_ALWAYS - }; - enum ShadowAtlasQuadrantSubdiv { SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED, SHADOW_ATLAS_QUADRANT_SUBDIV_1, @@ -142,13 +136,6 @@ public: DEBUG_DRAW_ROUGHNESS_LIMITER }; - enum ClearMode { - - CLEAR_MODE_ALWAYS, - CLEAR_MODE_NEVER, - CLEAR_MODE_ONLY_NEXT_FRAME - }; - enum DefaultCanvasItemTextureFilter { DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST, DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR, @@ -164,6 +151,10 @@ public: DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX, }; + enum { + SUBWINDOW_CANVAS_LAYER = 1024 + }; + private: friend class ViewportTexture; @@ -172,8 +163,6 @@ private: Listener *listener; Set<Listener *> listeners; - bool arvr; - struct CameraOverrideData { Transform transform; enum Projection { @@ -198,6 +187,7 @@ private: RID viewport; RID current_canvas; + RID subwindow_canvas; bool audio_listener; RID internal_listener; @@ -212,23 +202,17 @@ private: Transform2D global_canvas_transform; Transform2D stretch_transform; - Size2 size; - Rect2 to_screen_rect; - bool render_direct_to_screen; + Size2i size; + Size2i size_override; + bool size_allocated; RID contact_2d_debug; RID contact_3d_debug_multimesh; RID contact_3d_debug_instance; - bool size_override; - bool size_override_stretch; - Size2 size_override_size; - Size2 size_override_margin; - Rect2 last_vp_rect; bool transparent_bg; - ClearMode clear_mode; bool filter; bool gen_mipmaps; @@ -264,6 +248,7 @@ private: Ref<World> world; Ref<World> own_world; + Rect2i to_screen_rect; StringName input_group; StringName gui_input_group; StringName unhandled_input_group; @@ -276,10 +261,8 @@ private: void _propagate_exit_world(Node *p_node); void _propagate_viewport_notification(Node *p_node, int p_what); - void _update_stretch_transform(); void _update_global_transform(); - UpdateMode update_mode; RID texture_rid; DebugDraw debug_draw; @@ -291,9 +274,35 @@ private: Ref<ViewportTexture> default_texture; Set<ViewportTexture *> viewport_textures; + enum SubWindowDrag { + SUB_WINDOW_DRAG_DISABLED, + SUB_WINDOW_DRAG_MOVE, + SUB_WINDOW_DRAG_CLOSE, + SUB_WINDOW_DRAG_RESIZE, + }; + + enum SubWindowResize { + SUB_WINDOW_RESIZE_DISABLED, + SUB_WINDOW_RESIZE_TOP_LEFT, + SUB_WINDOW_RESIZE_TOP, + SUB_WINDOW_RESIZE_TOP_RIGHT, + SUB_WINDOW_RESIZE_LEFT, + SUB_WINDOW_RESIZE_RIGHT, + SUB_WINDOW_RESIZE_BOTTOM_LEFT, + SUB_WINDOW_RESIZE_BOTTOM, + SUB_WINDOW_RESIZE_BOTTOM_RIGHT, + SUB_WINDOW_RESIZE_MAX + }; + + struct SubWindow { + Window *window; + RID canvas_item; + }; + struct GUI { // info used when this is a window + bool forced_mouse_focus; //used for menu buttons bool key_event_accepted; Control *mouse_focus; Control *last_mouse_focus; @@ -301,8 +310,10 @@ private: int mouse_focus_mask; Control *key_focus; Control *mouse_over; + Control *drag_mouse_over; + Vector2 drag_mouse_over_pos; Control *tooltip; - Control *tooltip_popup; + Window *tooltip_popup; Label *tooltip_label; Point2 tooltip_pos; Point2 last_mouse_pos; @@ -312,16 +323,24 @@ private: Control *drag_preview; float tooltip_timer; float tooltip_delay; - List<Control *> modal_stack; Transform2D focus_inv_xform; - bool subwindow_order_dirty; - bool subwindow_visibility_dirty; - List<Control *> subwindows; // visible subwindows - List<Control *> all_known_subwindows; bool roots_order_dirty; List<Control *> roots; int canvas_sort_index; //for sorting items with canvas as root bool dragging; + bool embed_subwindows_hint; + bool embedding_subwindows; + + Window *subwindow_focused; + SubWindowDrag subwindow_drag; + Vector2 subwindow_drag_from; + Vector2 subwindow_drag_pos; + Rect2i subwindow_drag_close_rect; + bool subwindow_drag_close_inside; + SubWindowResize subwindow_resize_mode; + Rect2i subwindow_resize_from_rect; + + Vector<SubWindow> sub_windows; GUI(); } gui; @@ -337,10 +356,7 @@ private: void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input); void _gui_call_notification(Control *p_control, int p_what); - void _gui_prepare_subwindows(); - void _gui_sort_subwindows(); void _gui_sort_roots(); - void _gui_sort_modal_stack(); Control *_gui_find_control(const Point2 &p_global); Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform); @@ -350,23 +366,13 @@ private: _FORCE_INLINE_ Transform2D _get_input_pre_xform() const; - void _vp_input(const Ref<InputEvent> &p_ev); - void _vp_input_text(const String &p_text); - void _vp_unhandled_input(const Ref<InputEvent> &p_ev); Ref<InputEvent> _make_input_local(const Ref<InputEvent> &ev); friend class Control; List<Control *>::Element *_gui_add_root_control(Control *p_control); - List<Control *>::Element *_gui_add_subwindow_control(Control *p_control); - - void _gui_set_subwindow_order_dirty(); - void _gui_set_root_order_dirty(); - void _gui_remove_modal_control(List<Control *>::Element *MI); - void _gui_remove_from_modal_stack(List<Control *>::Element *MI, ObjectID p_prev_focus_owner); void _gui_remove_root_control(List<Control *>::Element *RI); - void _gui_remove_subwindow_control(List<Control *>::Element *SI); String _gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which = NULL); void _gui_cancel_tooltip(); @@ -378,9 +384,6 @@ private: void _gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control); void _gui_set_drag_preview(Control *p_base, Control *p_control); - bool _gui_is_modal_on_top(const Control *p_control); - List<Control *>::Element *_gui_show_modal(Control *p_control); - void _gui_remove_focus(); void _gui_unfocus_control(Control *p_control); bool _gui_control_has_focus(const Control *p_control); @@ -391,8 +394,6 @@ private: Control *_gui_get_focus_owner(); - Vector2 _get_window_offset() const; - bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check); friend class Listener; @@ -418,9 +419,26 @@ private: void _update_canvas_items(Node *p_node); + void _gui_set_root_order_dirty(); + void _own_world_changed(); + friend class Window; + + void _sub_window_update_order(); + void _sub_window_register(Window *p_window); + void _sub_window_update(Window *p_window); + void _sub_window_grab_focus(Window *p_window); + void _sub_window_remove(Window *p_window); + bool _sub_windows_forward_input(const Ref<InputEvent> &p_event); + SubWindowResize _sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point); + protected: + void _set_size(const Size2i &p_size, const Size2i &p_size_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated); + + Size2i _get_size() const; + bool _is_size_allocated() const; + void _notification(int p_what); static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const; @@ -438,19 +456,14 @@ public: void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far); void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far); - void set_use_arvr(bool p_use_arvr); - bool use_arvr(); - void set_as_audio_listener(bool p_enable); bool is_audio_listener() const; void set_as_audio_listener_2d(bool p_enable); bool is_audio_listener_2d() const; - void set_size(const Size2 &p_size); void update_canvas_items(); - Size2 get_size() const; Rect2 get_visible_rect() const; RID get_viewport_rid() const; @@ -479,18 +492,6 @@ public: void set_transparent_background(bool p_enable); bool has_transparent_background() const; - void set_size_override(bool p_enable, const Size2 &p_size = Size2(-1, -1), const Vector2 &p_margin = Vector2()); - Size2 get_size_override() const; - - bool is_size_override_enabled() const; - void set_size_override_stretch(bool p_enable); - bool is_size_override_stretch_enabled() const; - - void set_clear_mode(ClearMode p_mode); - ClearMode get_clear_mode() const; - - void set_update_mode(UpdateMode p_mode); - UpdateMode get_update_mode() const; Ref<ViewportTexture> get_texture() const; void set_shadow_atlas_size(int p_size); @@ -508,28 +509,20 @@ public: void set_use_own_world(bool p_world); bool is_using_own_world() const; - void input(const Ref<InputEvent> &p_event); - void unhandled_input(const Ref<InputEvent> &p_event); + void input_text(const String &p_text); + void input(const Ref<InputEvent> &p_event, bool p_local_coords = false); + void unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false); void set_disable_input(bool p_disable); bool is_input_disabled() const; - void set_attach_to_screen_rect(const Rect2 &p_rect); - Rect2 get_attach_to_screen_rect() const; - - void set_use_render_direct_to_screen(bool p_render_direct_to_screen); - bool is_using_render_direct_to_screen() const; - Vector2 get_mouse_position() const; void warp_mouse(const Vector2 &p_pos); void set_physics_object_picking(bool p_enable); bool get_physics_object_picking(); - bool gui_has_modal_stack() const; - Variant gui_get_drag_data() const; - Control *get_modal_stack_top() const; void gui_reset_canvas_sort_index(); int gui_get_canvas_sort_index(); @@ -544,8 +537,6 @@ public: void set_snap_controls_to_pixels(bool p_enable); bool is_snap_controls_to_pixels_enabled() const; - void _subwindow_visibility_changed(); - void set_input_as_handled(); bool is_input_handled() const; @@ -560,15 +551,71 @@ public: void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat); DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const; + virtual DisplayServer::WindowID get_window_id() const = 0; + + void set_embed_subwindows_hint(bool p_embed); + bool get_embed_subwindows_hint() const; + bool is_embedding_subwindows() const; + + Viewport *get_parent_viewport() const; + + void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control); + Viewport(); ~Viewport(); }; -VARIANT_ENUM_CAST(Viewport::UpdateMode); +class SubViewport : public Viewport { + + GDCLASS(SubViewport, Viewport); + +public: + enum ClearMode { + + CLEAR_MODE_ALWAYS, + CLEAR_MODE_NEVER, + CLEAR_MODE_ONLY_NEXT_FRAME + }; + + enum UpdateMode { + UPDATE_DISABLED, + UPDATE_ONCE, //then goes to disabled + UPDATE_WHEN_VISIBLE, // default + UPDATE_WHEN_PARENT_VISIBLE, + UPDATE_ALWAYS + }; + +private: + UpdateMode update_mode; + ClearMode clear_mode; + bool arvr; + +protected: + static void _bind_methods(); + virtual DisplayServer::WindowID get_window_id() const; + void _notification(int p_what); + +public: + void set_size(const Size2i &p_size); + Size2i get_size() const; + + void set_use_arvr(bool p_use_arvr); + bool is_using_arvr(); + + void set_update_mode(UpdateMode p_mode); + UpdateMode get_update_mode() const; + + void set_clear_mode(ClearMode p_mode); + ClearMode get_clear_mode() const; + + SubViewport(); + ~SubViewport(); +}; +VARIANT_ENUM_CAST(SubViewport::UpdateMode); VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv); VARIANT_ENUM_CAST(Viewport::MSAA); VARIANT_ENUM_CAST(Viewport::DebugDraw); -VARIANT_ENUM_CAST(Viewport::ClearMode); +VARIANT_ENUM_CAST(SubViewport::ClearMode); VARIANT_ENUM_CAST(Viewport::RenderInfo); VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter); VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureRepeat); diff --git a/scene/main/window.cpp b/scene/main/window.cpp new file mode 100644 index 0000000000..a2a49aea75 --- /dev/null +++ b/scene/main/window.cpp @@ -0,0 +1,1406 @@ +/*************************************************************************/ +/* window.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "window.h" + +#include "core/debugger/engine_debugger.h" +#include "core/os/keyboard.h" +#include "scene/gui/control.h" +#include "scene/resources/dynamic_font.h" +#include "scene/scene_string_names.h" + +void Window::set_title(const String &p_title) { + title = p_title; + + if (embedder) { + embedder->_sub_window_update(this); + + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + + DisplayServer::get_singleton()->window_set_title(p_title, window_id); + } +} +String Window::get_title() const { + return title; +} + +void Window::set_current_screen(int p_screen) { + current_screen = p_screen; + if (window_id == DisplayServer::INVALID_WINDOW_ID) + return; + DisplayServer::get_singleton()->window_set_current_screen(p_screen, window_id); +} +int Window::get_current_screen() const { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + current_screen = DisplayServer::get_singleton()->window_get_current_screen(window_id); + } + return current_screen; +} + +void Window::set_position(const Point2i &p_position) { + + position = p_position; + + if (embedder) { + embedder->_sub_window_update(this); + + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + + DisplayServer::get_singleton()->window_set_position(p_position, window_id); + } +} +Point2i Window::get_position() const { + return position; +} + +void Window::set_size(const Size2i &p_size) { + size = p_size; + _update_window_size(); +} +Size2i Window::get_size() const { + + return size; +} + +Size2i Window::get_real_size() const { + + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + return DisplayServer::get_singleton()->window_get_real_size(window_id); + } + return size; +} + +void Window::set_max_size(const Size2i &p_max_size) { + max_size = p_max_size; + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); + } + _update_window_size(); +} + +Size2i Window::get_max_size() const { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + max_size = DisplayServer::get_singleton()->window_get_max_size(window_id); + } + return max_size; +} + +void Window::set_min_size(const Size2i &p_min_size) { + min_size = p_min_size; + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_min_size(min_size, window_id); + } + _update_window_size(); +} + +Size2i Window::get_min_size() const { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + min_size = DisplayServer::get_singleton()->window_get_min_size(window_id); + } + return min_size; +} + +void Window::set_mode(Mode p_mode) { + + mode = p_mode; + + if (embedder) { + embedder->_sub_window_update(this); + + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + + DisplayServer::get_singleton()->window_set_mode(DisplayServer::WindowMode(p_mode), window_id); + } +} + +Window::Mode Window::get_mode() const { + + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + mode = (Mode)DisplayServer::get_singleton()->window_get_mode(window_id); + } + return mode; +} + +void Window::set_flag(Flags p_flag, bool p_enabled) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags[p_flag] = p_enabled; + + if (embedder) { + embedder->_sub_window_update(this); + + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + + DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id); + } +} + +bool Window::get_flag(Flags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + flags[p_flag] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(p_flag), window_id); + } + return flags[p_flag]; +} + +bool Window::is_maximize_allowed() const { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + return DisplayServer::get_singleton()->window_is_maximize_allowed(window_id); + } + return true; +} + +void Window::request_attention() { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_request_attention(window_id); + } +} +void Window::move_to_foreground() { + + if (embedder) { + embedder->_sub_window_grab_focus(this); + + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_move_to_foreground(window_id); + } +} + +bool Window::can_draw() const { + if (!is_inside_tree()) { + return false; + } + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + return DisplayServer::get_singleton()->window_can_draw(window_id); + } + + return visible; +} + +void Window::set_ime_active(bool p_active) { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_active(p_active, window_id); + } +} +void Window::set_ime_position(const Point2i &p_pos) { + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_ime_position(p_pos, window_id); + } +} + +bool Window::is_embedded() const { + ERR_FAIL_COND_V(!is_inside_tree(), false); + + return _get_embedder() != nullptr; +} + +void Window::_make_window() { + ERR_FAIL_COND(window_id != DisplayServer::INVALID_WINDOW_ID); + + uint32_t f = 0; + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + f |= (1 << i); + } + } + + window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), f, Rect2i(position, size)); + ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); + DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id); + DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); + DisplayServer::get_singleton()->window_set_min_size(min_size, window_id); + DisplayServer::get_singleton()->window_set_title(title, window_id); + DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); + + _update_window_size(); + + if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id); + } + + for (Set<Window *>::Element *E = transient_children.front(); E; E = E->next()) { + if (E->get()->window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_transient(E->get()->window_id, transient_parent->window_id); + } + } + + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_VISIBLE); +} +void Window::_update_from_window() { + + ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); + mode = (Mode)DisplayServer::get_singleton()->window_get_mode(window_id); + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(i), window_id); + } +} + +void Window::_clear_window() { + ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); + + if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID); + } + + for (Set<Window *>::Element *E = transient_children.front(); E; E = E->next()) { + if (E->get()->window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_transient(E->get()->window_id, DisplayServer::INVALID_WINDOW_ID); + } + } + + _update_from_window(); + + DisplayServer::get_singleton()->delete_sub_window(window_id); + window_id = DisplayServer::INVALID_WINDOW_ID; + + _update_viewport_size(); + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); +} + +void Window::_rect_changed_callback(const Rect2i &p_callback) { + + //we must always accept this as the truth + if (size == p_callback.size && position == p_callback.position) { + return; + } + position = p_callback.position; + + if (size != p_callback.size) { + size = p_callback.size; + _update_viewport_size(); + } +} + +void Window::_propagate_window_notification(Node *p_node, int p_notification) { + p_node->notification(p_notification); + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *child = p_node->get_child(i); + Window *window = Object::cast_to<Window>(child); + if (window) { + break; + } + _propagate_window_notification(child, p_notification); + } +} + +void Window::_event_callback(DisplayServer::WindowEvent p_event) { + + switch (p_event) { + case DisplayServer::WINDOW_EVENT_MOUSE_ENTER: { + _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER); + emit_signal("mouse_entered"); + } break; + case DisplayServer::WINDOW_EVENT_MOUSE_EXIT: { + _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT); + emit_signal("mouse_exited"); + } break; + case DisplayServer::WINDOW_EVENT_FOCUS_IN: { + focused = true; + _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN); + emit_signal("focus_entered"); + + } break; + case DisplayServer::WINDOW_EVENT_FOCUS_OUT: { + focused = false; + _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT); + emit_signal("focus_exited"); + } break; + case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: { + if (exclusive_child != nullptr) { + break; //has an exclusive child, can't get events until child is closed + } + _propagate_window_notification(this, NOTIFICATION_WM_CLOSE_REQUEST); + emit_signal("close_requested"); + } break; + case DisplayServer::WINDOW_EVENT_GO_BACK_REQUEST: { + _propagate_window_notification(this, NOTIFICATION_WM_GO_BACK_REQUEST); + emit_signal("go_back_requested"); + } break; + case DisplayServer::WINDOW_EVENT_DPI_CHANGE: { + _propagate_window_notification(this, NOTIFICATION_WM_DPI_CHANGE); + emit_signal("dpi_changed"); + } break; + } +} + +void Window::show() { + set_visible(true); +} +void Window::hide() { + set_visible(false); +} + +void Window::set_visible(bool p_visible) { + + if (visible == p_visible) { + return; + } + + visible = p_visible; + + if (!is_inside_tree()) { + return; + } + + if (updating_child_controls) { + _update_child_controls(); + } + + ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window."); + + Viewport *embedder_vp = _get_embedder(); + + if (!embedder_vp) { + if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) { + _clear_window(); + } + if (p_visible && window_id == DisplayServer::INVALID_WINDOW_ID) { + _make_window(); + _update_window_callbacks(); + } + } else { + if (visible) { + embedder = embedder_vp; + embedder->_sub_window_register(this); + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); + } else { + embedder->_sub_window_remove(this); + embedder = nullptr; + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + } + _update_window_size(); + } + + if (!visible) { + focused = false; + } + notification(NOTIFICATION_VISIBILITY_CHANGED); + emit_signal(SceneStringNames::get_singleton()->visibility_changed); + + VS::get_singleton()->viewport_set_active(get_viewport_rid(), visible); +} + +void Window::_clear_transient() { + if (transient_parent) { + if (transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID && window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID); + } + transient_parent->transient_children.erase(this); + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } + transient_parent = nullptr; + } +} + +void Window::_make_transient() { + if (!get_parent()) { + //main window, can't be transient + return; + } + //find transient parent + Viewport *vp = get_parent()->get_viewport(); + Window *window = nullptr; + while (vp) { + window = Object::cast_to<Window>(vp); + if (window) { + break; + } + if (!vp->get_parent()) { + break; + } + + vp = vp->get_parent()->get_viewport(); + } + + if (window) { + transient_parent = window; + window->transient_children.insert(this); + if (is_inside_tree() && is_visible() && exclusive) { + if (transient_parent->exclusive_child == nullptr) { + transient_parent->exclusive_child = this; + } else if (transient_parent->exclusive_child != this) { + ERR_PRINT("Making child transient exclusive, but parent has another exclusive child"); + } + } + } + + //see if we can make transient + if (transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID && window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id); + } +} + +void Window::set_transient(bool p_transient) { + if (transient == p_transient) { + return; + } + + transient = p_transient; + + if (!is_inside_tree()) { + return; + } + + if (transient) { + _make_transient(); + } else { + _clear_transient(); + } +} +bool Window::is_transient() const { + return transient; +} + +void Window::set_exclusive(bool p_exclusive) { + + if (exclusive == p_exclusive) { + return; + } + + exclusive = p_exclusive; + + if (transient_parent) { + if (p_exclusive && is_inside_tree() && is_visible()) { + ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); + transient_parent->exclusive_child = this; + } else { + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } + } + } +} + +bool Window::is_exclusive() const { + return exclusive; +} + +bool Window::is_visible() const { + return visible; +} + +void Window::_update_window_size() { + + Size2i size_limit; + if (wrap_controls) { + size_limit = get_contents_minimum_size(); + } + + size_limit.x = MAX(size_limit.x, min_size.x); + size_limit.y = MAX(size_limit.y, min_size.y); + + size.x = MAX(size_limit.x, size.x); + size.y = MAX(size_limit.y, size.y); + + if (max_size.x > 0 && max_size.x > min_size.x && max_size.x > size.x) { + size.x = max_size.x; + } + + if (max_size.y > 0 && max_size.y > min_size.y && max_size.y > size.y) { + size.y = max_size.y; + } + + if (embedder) { + embedder->_sub_window_update(this); + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_set_size(size, window_id); + } + + //update the viewport + _update_viewport_size(); +} +void Window::_update_viewport_size() { + //update the viewport part + + Size2i final_size; + Size2i final_size_override; + Rect2i attach_to_screen_rect(Point2i(), size); + Transform2D stretch_transform; + float font_oversampling = 1.0; + + if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) { + + stretch_transform = Transform2D(); + final_size = size; + + } else { + + //actual screen video mode + Size2 video_mode = size; + Size2 desired_res = content_scale_size; + + Size2 viewport_size; + Size2 screen_size; + + float viewport_aspect = desired_res.aspect(); + float video_mode_aspect = video_mode.aspect(); + + if (content_scale_aspect == CONTENT_SCALE_ASPECT_IGNORE || Math::is_equal_approx(viewport_aspect, video_mode_aspect)) { + //same aspect or ignore aspect + viewport_size = desired_res; + screen_size = video_mode; + } else if (viewport_aspect < video_mode_aspect) { + // screen ratio is smaller vertically + + if (content_scale_aspect == CONTENT_SCALE_ASPECT_KEEP_HEIGHT || content_scale_aspect == CONTENT_SCALE_ASPECT_EXPAND) { + + //will stretch horizontally + viewport_size.x = desired_res.y * video_mode_aspect; + viewport_size.y = desired_res.y; + screen_size = video_mode; + + } else { + //will need black bars + viewport_size = desired_res; + screen_size.x = video_mode.y * viewport_aspect; + screen_size.y = video_mode.y; + } + } else { + //screen ratio is smaller horizontally + if (content_scale_aspect == CONTENT_SCALE_ASPECT_KEEP_WIDTH || content_scale_aspect == CONTENT_SCALE_ASPECT_EXPAND) { + + //will stretch horizontally + viewport_size.x = desired_res.x; + viewport_size.y = desired_res.x / video_mode_aspect; + screen_size = video_mode; + + } else { + //will need black bars + viewport_size = desired_res; + screen_size.x = video_mode.x; + screen_size.y = video_mode.x / viewport_aspect; + } + } + + screen_size = screen_size.floor(); + viewport_size = viewport_size.floor(); + + Size2 margin; + Size2 offset; + //black bars and margin + if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.x < video_mode.x) { + margin.x = Math::round((video_mode.x - screen_size.x) / 2.0); + //VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); + offset.x = Math::round(margin.x * viewport_size.y / screen_size.y); + } else if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.y < video_mode.y) { + margin.y = Math::round((video_mode.y - screen_size.y) / 2.0); + //VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); + offset.y = Math::round(margin.y * viewport_size.x / screen_size.x); + } else { + //VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0); + } + + switch (content_scale_mode) { + case CONTENT_SCALE_MODE_DISABLED: { + // Already handled above + //_update_font_oversampling(1.0); + } break; + case CONTENT_SCALE_MODE_OBJECTS: { + + final_size = screen_size; + final_size_override = viewport_size; + attach_to_screen_rect = Rect2(margin, screen_size); + font_oversampling = screen_size.x / viewport_size.x; + } break; + case CONTENT_SCALE_MODE_PIXELS: { + + final_size = viewport_size; + attach_to_screen_rect = Rect2(margin, screen_size); + + } break; + } + + Size2 scale = size / (Vector2(final_size) + margin * 2); + stretch_transform.scale(scale); + stretch_transform.elements[2] = margin * scale; + } + + bool allocate = is_inside_tree() && visible && (window_id != DisplayServer::INVALID_WINDOW_ID || embedder != nullptr); + + _set_size(final_size, final_size_override, attach_to_screen_rect, stretch_transform, allocate); + + if (window_id != DisplayServer::INVALID_WINDOW_ID) { + VisualServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), attach_to_screen_rect, window_id); + } else { + VisualServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), Rect2i(), DisplayServer::INVALID_WINDOW_ID); + } + + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + + if (!use_font_oversampling) { + font_oversampling = 1.0; + } + if (DynamicFontAtSize::font_oversampling != font_oversampling) { + + DynamicFontAtSize::font_oversampling = font_oversampling; + DynamicFont::update_oversampling(); + } + } + + notification(NOTIFICATION_WM_SIZE_CHANGED); + + if (embedder) { + embedder->_sub_window_update(this); + } +} + +void Window::_update_window_callbacks() { + DisplayServer::get_singleton()->window_set_rect_changed_callback(callable_mp(this, &Window::_rect_changed_callback), window_id); + DisplayServer::get_singleton()->window_set_window_event_callback(callable_mp(this, &Window::_event_callback), window_id); + DisplayServer::get_singleton()->window_set_input_event_callback(callable_mp(this, &Window::_window_input), window_id); + DisplayServer::get_singleton()->window_set_input_text_callback(callable_mp(this, &Window::_window_input_text), window_id); + DisplayServer::get_singleton()->window_set_drop_files_callback(callable_mp(this, &Window::_window_drop_files), window_id); +} + +Viewport *Window::_get_embedder() const { + + Viewport *vp = get_parent_viewport(); + + while (vp) { + + if (vp->is_embedding_subwindows()) { + return vp; + } + + if (vp->get_parent()) { + vp = vp->get_parent()->get_viewport(); + } else { + vp = nullptr; + } + } + return nullptr; +} + +void Window::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE) { + + bool embedded = false; + { + + embedder = _get_embedder(); + + if (embedder) { + embedded = true; + + if (!visible) { + embedder = nullptr; //not yet since not visible + } + } + } + + if (embedded) { + //create as embedded + if (embedder) { + embedder->_sub_window_register(this); + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); + _update_window_size(); + } + + } else { + if (get_parent() == nullptr) { + //it's the root window! + visible = true; //always visible + window_id = DisplayServer::MAIN_WINDOW_ID; + DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); + _update_from_window(); + //since this window already exists (created on start), we must update pos and size from it + { + position = DisplayServer::get_singleton()->window_get_position(window_id); + size = DisplayServer::get_singleton()->window_get_size(window_id); + } + _update_viewport_size(); //then feed back to the viewport + _update_window_callbacks(); + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_VISIBLE); + } else { + //create + if (visible) { + _make_window(); + _update_window_callbacks(); + } + } + } + + if (transient) { + _make_transient(); + } + if (visible) { + notification(NOTIFICATION_VISIBILITY_CHANGED); + emit_signal(SceneStringNames::get_singleton()->visibility_changed); + VS::get_singleton()->viewport_set_active(get_viewport_rid(), true); + } + } + + if (p_what == NOTIFICATION_READY) { + + if (wrap_controls) { + _update_child_controls(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + + if (transient) { + _clear_transient(); + } + + if (!is_embedded() && window_id != DisplayServer::INVALID_WINDOW_ID) { + + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + _update_window_callbacks(); + } else { + _clear_window(); + } + } else { + + if (embedder) { + embedder->_sub_window_remove(this); + embedder = nullptr; + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + } + _update_viewport_size(); //called by clear and make, which does not happen here + } + + VS::get_singleton()->viewport_set_active(get_viewport_rid(), false); + } +} + +void Window::set_content_scale_size(const Size2i &p_size) { + ERR_FAIL_COND(p_size.x < 0); + ERR_FAIL_COND(p_size.y < 0); + content_scale_size = p_size; + _update_viewport_size(); +} + +Size2i Window::get_content_scale_size() const { + return content_scale_size; +} + +void Window::set_content_scale_mode(ContentScaleMode p_mode) { + content_scale_mode = p_mode; + _update_viewport_size(); +} +Window::ContentScaleMode Window::get_content_scale_mode() const { + return content_scale_mode; +} + +void Window::set_content_scale_aspect(ContentScaleAspect p_aspect) { + content_scale_aspect = p_aspect; + _update_viewport_size(); +} +Window::ContentScaleAspect Window::get_content_scale_aspect() const { + return content_scale_aspect; +} + +void Window::set_use_font_oversampling(bool p_oversampling) { + if (is_inside_tree() && window_id != DisplayServer::MAIN_WINDOW_ID) { + ERR_FAIL_MSG("Only the root window can set and use font oversampling."); + } + use_font_oversampling = p_oversampling; + _update_viewport_size(); +} +bool Window::is_using_font_oversampling() const { + return use_font_oversampling; +} + +DisplayServer::WindowID Window::get_window_id() const { + return window_id; +} + +void Window::set_wrap_controls(bool p_enable) { + wrap_controls = p_enable; + if (wrap_controls) { + child_controls_changed(); + } +} + +bool Window::is_wrapping_controls() const { + return wrap_controls; +} + +Size2 Window::_get_contents_minimum_size() const { + Size2 max; + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (c) { + Point2i pos = c->get_position(); + Size2i min = c->get_combined_minimum_size(); + + max.x = MAX(pos.x + min.x, max.x); + max.y = MAX(pos.y + min.y, max.y); + } + } + + return max; +} +void Window::_update_child_controls() { + + if (!updating_child_controls) { + return; + } + + _update_window_size(); + + updating_child_controls = false; +} +void Window::child_controls_changed() { + + if (!is_inside_tree() || !visible || updating_child_controls) { + return; + } + + updating_child_controls = true; + call_deferred("_update_child_controls"); +} + +void Window::_window_input(const Ref<InputEvent> &p_ev) { + if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev))) + return; //avoid joy input on editor + + if (EngineDebugger::is_active()) { + //quit from game window using F8 + Ref<InputEventKey> k = p_ev; + if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_F8) { + EngineDebugger::get_singleton()->send_message("request_quit", Array()); + } + } + + if (exclusive_child != nullptr) { + exclusive_child->grab_focus(); + + return; //has an exclusive child, can't get events until child is closed + } + + emit_signal(SceneStringNames::get_singleton()->window_input, p_ev); + input(p_ev); + if (!is_input_handled()) { + unhandled_input(p_ev); + } +} +void Window::_window_input_text(const String &p_text) { + input_text(p_text); +} +void Window::_window_drop_files(const Vector<String> &p_files) { + emit_signal("files_dropped", p_files); +} + +Viewport *Window::get_parent_viewport() const { + + if (get_parent()) { + return get_parent()->get_viewport(); + } else { + return nullptr; + } +} + +Window *Window::get_parent_visible_window() const { + + Viewport *vp = get_parent_viewport(); + Window *window = nullptr; + while (vp) { + window = Object::cast_to<Window>(vp); + if (window && window->visible) { + break; + } + if (!vp->get_parent()) { + break; + } + + vp = vp->get_parent()->get_viewport(); + } + return window; +} + +void Window::popup_on_parent(const Rect2i &p_parent_rect) { + + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + if (!is_embedded()) { + Window *window = get_parent_visible_window(); + + if (!window) { + popup(p_parent_rect); + } else { + popup(Rect2i(window->get_position() + p_parent_rect.position, p_parent_rect.size)); + } + } else { + popup(p_parent_rect); + } +} + +void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio) { + + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + Rect2 parent_rect; + + if (is_embedded()) { + parent_rect = get_parent_viewport()->get_visible_rect(); + } else { + DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); + int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); + parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen); + parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen); + } + + Vector2i size_ratio = parent_rect.size * p_fallback_ratio; + + Rect2i popup_rect; + popup_rect.size = Vector2i(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y)); + popup_rect.position = (parent_rect.size - popup_rect.size) / 2; + + popup(popup_rect); +} + +void Window::popup_centered(const Size2i &p_minsize) { + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + Rect2 parent_rect; + + if (is_embedded()) { + parent_rect = get_parent_viewport()->get_visible_rect(); + } else { + DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); + int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); + parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen); + parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen); + } + + Rect2i popup_rect; + if (p_minsize == Size2i()) { + popup_rect.size = _get_contents_minimum_size(); + } else { + popup_rect.size = p_minsize; + } + popup_rect.position = (parent_rect.size - popup_rect.size) / 2; + + popup(popup_rect); +} + +void Window::popup_centered_ratio(float p_ratio) { + + ERR_FAIL_COND(!is_inside_tree()); + ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window."); + + Rect2i parent_rect; + + if (is_embedded()) { + parent_rect = get_parent_viewport()->get_visible_rect(); + } else { + DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); + int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); + parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen); + parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen); + } + + Rect2i popup_rect; + popup_rect.size = parent_rect.size * p_ratio; + popup_rect.position = (parent_rect.size - popup_rect.size) / 2; + + popup(popup_rect); +} + +void Window::popup(const Rect2i &p_screen_rect) { + + emit_signal("about_to_popup"); + + if (p_screen_rect != Rect2i()) { + set_position(p_screen_rect.position); + set_size(p_screen_rect.size); + } + + Rect2i adjust = _popup_adjust_rect(); + if (adjust != Rect2i()) { + set_position(adjust.position); + set_size(adjust.size); + } + + set_transient(true); + set_visible(true); + _post_popup(); + notification(NOTIFICATION_POST_POPUP); +} + +Size2 Window::get_contents_minimum_size() const { + return _get_contents_minimum_size(); +} + +void Window::grab_focus() { + if (embedder) { + embedder->_sub_window_grab_focus(this); + } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { + DisplayServer::get_singleton()->window_move_to_foreground(window_id); + } +} + +bool Window::has_focus() const { + return focused; +} + +Rect2i Window::get_usable_parent_rect() const { + ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); + Rect2i parent; + if (is_embedded()) { + parent = _get_embedder()->get_visible_rect(); + } else { + + const Window *w = is_visible() ? this : get_parent_visible_window(); + //find a parent that can contain us + ERR_FAIL_COND_V(!w, Rect2()); + + parent = DisplayServer::get_singleton()->screen_get_usable_rect(DisplayServer::get_singleton()->window_get_current_screen(w->get_window_id())); + } + return parent; +} + +void Window::add_child_notify(Node *p_child) { + + Control *child_c = Object::cast_to<Control>(p_child); + + if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) { + Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) { + Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff + } + + if (is_inside_tree() && wrap_controls) { + child_controls_changed(); + } +} + +void Window::remove_child_notify(Node *p_child) { + + Control *child_c = Object::cast_to<Control>(p_child); + + if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { + Control::_propagate_theme_changed(child_c, NULL, NULL); + } + + Window *child_w = Object::cast_to<Window>(p_child); + + if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { + Control::_propagate_theme_changed(child_w, NULL, NULL); + } + + if (is_inside_tree() && wrap_controls) { + child_controls_changed(); + } +} + +void Window::set_theme(const Ref<Theme> &p_theme) { + + if (theme == p_theme) + return; + + theme = p_theme; + + if (!p_theme.is_null()) { + + theme_owner = nullptr; + theme_owner_window = this; + Control::_propagate_theme_changed(this, nullptr, this); + } else { + + Control *parent_c = cast_to<Control>(get_parent()); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); + } else { + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); + } else { + Control::_propagate_theme_changed(this, nullptr, nullptr); + } + } + } +} +Ref<Theme> Window::get_theme() const { + return theme; +} + +Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::get_icons(theme_owner, theme_owner_window, p_name, type); +} +Ref<Shader> Window::get_theme_shader(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::get_shaders(theme_owner, theme_owner_window, p_name, type); +} +Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::get_styleboxs(theme_owner, theme_owner_window, p_name, type); +} +Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::get_fonts(theme_owner, theme_owner_window, p_name, type); +} +Color Window::get_theme_color(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::get_colors(theme_owner, theme_owner_window, p_name, type); +} +int Window::get_theme_constant(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::get_constants(theme_owner, theme_owner_window, p_name, type); +} + +bool Window::has_theme_icon(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::has_icons(theme_owner, theme_owner_window, p_name, type); +} +bool Window::has_theme_shader(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::has_shaders(theme_owner, theme_owner_window, p_name, type); +} +bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::has_styleboxs(theme_owner, theme_owner_window, p_name, type); +} +bool Window::has_theme_font(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::has_fonts(theme_owner, theme_owner_window, p_name, type); +} +bool Window::has_theme_color(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::has_colors(theme_owner, theme_owner_window, p_name, type); +} +bool Window::has_theme_constant(const StringName &p_name, const StringName &p_type) const { + StringName type = p_type ? p_type : get_class_name(); + return Control::has_constants(theme_owner, theme_owner_window, p_name, type); +} + +Rect2i Window::get_parent_rect() const { + ERR_FAIL_COND_V(!is_inside_tree(), Rect2i()); + if (is_embedded()) { + //viewport + Node *n = get_parent(); + ERR_FAIL_COND_V(!n, Rect2i()); + Viewport *p = n->get_viewport(); + ERR_FAIL_COND_V(!p, Rect2i()); + + return p->get_visible_rect(); + } else { + int x = get_position().x; + int closest_dist = 0x7FFFFFFF; + Rect2i closest_rect; + for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) { + Rect2i s(DisplayServer::get_singleton()->screen_get_position(i), DisplayServer::get_singleton()->screen_get_size(i)); + int d; + if (x >= s.position.x && x < s.size.x) { + //contained + closest_rect = s; + break; + } else if (x < s.position.x) { + d = s.position.x - x; + } else { + d = x - (s.position.x + s.size.x); + } + + if (d < closest_dist) { + closest_dist = d; + closest_rect = s; + } + } + return closest_rect; + } +} + +void Window::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title); + ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title); + + ClassDB::bind_method(D_METHOD("set_current_screen", "index"), &Window::set_current_screen); + ClassDB::bind_method(D_METHOD("get_current_screen"), &Window::get_current_screen); + + ClassDB::bind_method(D_METHOD("set_position", "position"), &Window::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &Window::get_position); + + ClassDB::bind_method(D_METHOD("set_size", "size"), &Window::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &Window::get_size); + + ClassDB::bind_method(D_METHOD("get_real_size"), &Window::get_real_size); + + ClassDB::bind_method(D_METHOD("set_max_size", "max_size"), &Window::set_max_size); + ClassDB::bind_method(D_METHOD("get_max_size"), &Window::get_max_size); + + ClassDB::bind_method(D_METHOD("set_min_size", "min_size"), &Window::set_min_size); + ClassDB::bind_method(D_METHOD("get_min_size"), &Window::get_min_size); + + ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Window::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"), &Window::get_mode); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enabled"), &Window::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &Window::get_flag); + + ClassDB::bind_method(D_METHOD("is_maximize_allowed"), &Window::is_maximize_allowed); + + ClassDB::bind_method(D_METHOD("request_attention"), &Window::request_attention); + + ClassDB::bind_method(D_METHOD("move_to_foreground"), &Window::move_to_foreground); + + ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Window::set_visible); + ClassDB::bind_method(D_METHOD("is_visible"), &Window::is_visible); + + ClassDB::bind_method(D_METHOD("hide"), &Window::hide); + ClassDB::bind_method(D_METHOD("show"), &Window::show); + + ClassDB::bind_method(D_METHOD("set_transient", "transient"), &Window::set_transient); + ClassDB::bind_method(D_METHOD("is_transient"), &Window::is_transient); + + ClassDB::bind_method(D_METHOD("set_exclusive", "exclusive"), &Window::set_exclusive); + ClassDB::bind_method(D_METHOD("is_exclusive"), &Window::is_exclusive); + + ClassDB::bind_method(D_METHOD("can_draw"), &Window::is_transient); + ClassDB::bind_method(D_METHOD("has_focus"), &Window::has_focus); + ClassDB::bind_method(D_METHOD("grab_focus"), &Window::grab_focus); + + ClassDB::bind_method(D_METHOD("set_ime_active"), &Window::set_ime_active); + ClassDB::bind_method(D_METHOD("set_ime_position"), &Window::set_ime_position); + + ClassDB::bind_method(D_METHOD("is_embedded"), &Window::is_embedded); + + ClassDB::bind_method(D_METHOD("set_content_scale_size", "size"), &Window::set_content_scale_size); + ClassDB::bind_method(D_METHOD("get_content_scale_size"), &Window::get_content_scale_size); + + ClassDB::bind_method(D_METHOD("set_content_scale_mode", "mode"), &Window::set_content_scale_mode); + ClassDB::bind_method(D_METHOD("get_content_scale_mode"), &Window::get_content_scale_mode); + + ClassDB::bind_method(D_METHOD("set_content_scale_aspect", "aspect"), &Window::set_content_scale_aspect); + ClassDB::bind_method(D_METHOD("get_content_scale_aspect"), &Window::get_content_scale_aspect); + + ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &Window::set_use_font_oversampling); + ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &Window::is_using_font_oversampling); + + ClassDB::bind_method(D_METHOD("set_wrap_controls", "enable"), &Window::set_wrap_controls); + ClassDB::bind_method(D_METHOD("is_wrapping_controls"), &Window::is_wrapping_controls); + ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed); + + ClassDB::bind_method(D_METHOD("_update_child_controls"), &Window::_update_child_controls); + + ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme); + ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme); + + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Window::get_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Window::get_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Window::get_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Window::get_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Window::get_theme_constant, DEFVAL("")); + + ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Window::has_theme_icon, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Window::has_theme_stylebox, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Window::has_theme_font, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Window::has_theme_color, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Window::has_theme_constant, DEFVAL("")); + + ClassDB::bind_method(D_METHOD("popup", "rect"), &Window::popup, DEFVAL(Rect2i())); + ClassDB::bind_method(D_METHOD("popup_on_parent", "parent_rect"), &Window::popup_on_parent); + ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Window::popup_centered_ratio, DEFVAL(0.8)); + ClassDB::bind_method(D_METHOD("popup_centered", "minsize"), &Window::popup_centered, DEFVAL(Size2i())); + ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered, DEFVAL(Size2i()), DEFVAL(0.75)); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,FullScreen"), "set_mode", "get_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen"); + ADD_GROUP("Flags", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclusive"), "set_exclusive", "is_exclusive"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unresizable"), "set_flag", "get_flag", FLAG_RESIZE_DISABLED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "borderless"), "set_flag", "get_flag", FLAG_BORDERLESS); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "always_on_top"), "set_flag", "get_flag", FLAG_ALWAYS_ON_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_flag", "get_flag", FLAG_TRANSPARENT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unfocusable"), "set_flag", "get_flag", FLAG_NO_FOCUS); + ADD_GROUP("Limits", ""); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size"), "set_min_size", "get_min_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size"), "set_max_size", "get_max_size"); + ADD_GROUP("Content Scale", "content_scale_"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Object,Pixels"), "set_content_scale_mode", "get_content_scale_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect"); + ADD_GROUP("Theme", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); + + ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"))); + ADD_SIGNAL(MethodInfo("mouse_entered")); + ADD_SIGNAL(MethodInfo("mouse_exited")); + ADD_SIGNAL(MethodInfo("focus_entered")); + ADD_SIGNAL(MethodInfo("focus_exited")); + ADD_SIGNAL(MethodInfo("close_requested")); + ADD_SIGNAL(MethodInfo("go_back_requested")); + ADD_SIGNAL(MethodInfo("visibility_changed")); + ADD_SIGNAL(MethodInfo("about_to_popup")); + + BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); + + BIND_ENUM_CONSTANT(MODE_WINDOWED); + BIND_ENUM_CONSTANT(MODE_MINIMIZED); + BIND_ENUM_CONSTANT(MODE_MAXIMIZED); + BIND_ENUM_CONSTANT(MODE_FULLSCREEN); + + BIND_ENUM_CONSTANT(FLAG_RESIZE_DISABLED); + BIND_ENUM_CONSTANT(FLAG_BORDERLESS); + BIND_ENUM_CONSTANT(FLAG_ALWAYS_ON_TOP); + BIND_ENUM_CONSTANT(FLAG_TRANSPARENT); + BIND_ENUM_CONSTANT(FLAG_NO_FOCUS); + BIND_ENUM_CONSTANT(FLAG_MAX); + + BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED); + BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_OBJECTS); + BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_PIXELS); + + BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_IGNORE); + BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP); + BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP_WIDTH); + BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP_HEIGHT); + BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_EXPAND); +} + +Window::Window() { + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } + content_scale_mode = CONTENT_SCALE_MODE_DISABLED; + content_scale_aspect = CONTENT_SCALE_ASPECT_IGNORE; + VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); +} +Window::~Window() { +} diff --git a/scene/main/window.h b/scene/main/window.h new file mode 100644 index 0000000000..be07762f20 --- /dev/null +++ b/scene/main/window.h @@ -0,0 +1,266 @@ +/*************************************************************************/ +/* window.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include "scene/main/viewport.h" +#include "scene/resources/theme.h" +#include "servers/display_server.h" + +class Control; +class Window : public Viewport { + GDCLASS(Window, Viewport) +public: + enum Mode { + MODE_WINDOWED = DisplayServer::WINDOW_MODE_WINDOWED, + MODE_MINIMIZED = DisplayServer::WINDOW_MODE_MINIMIZED, + MODE_MAXIMIZED = DisplayServer::WINDOW_MODE_MAXIMIZED, + MODE_FULLSCREEN = DisplayServer::WINDOW_MODE_FULLSCREEN + }; + + enum Flags { + FLAG_RESIZE_DISABLED = DisplayServer::WINDOW_FLAG_RESIZE_DISABLED, + FLAG_BORDERLESS = DisplayServer::WINDOW_FLAG_BORDERLESS, + FLAG_ALWAYS_ON_TOP = DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, + FLAG_TRANSPARENT = DisplayServer::WINDOW_FLAG_TRANSPARENT, + FLAG_NO_FOCUS = DisplayServer::WINDOW_FLAG_NO_FOCUS, + FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX, + }; + + enum ContentScaleMode { + CONTENT_SCALE_MODE_DISABLED, + CONTENT_SCALE_MODE_OBJECTS, + CONTENT_SCALE_MODE_PIXELS, + + }; + + enum ContentScaleAspect { + CONTENT_SCALE_ASPECT_IGNORE, + CONTENT_SCALE_ASPECT_KEEP, + CONTENT_SCALE_ASPECT_KEEP_WIDTH, + CONTENT_SCALE_ASPECT_KEEP_HEIGHT, + CONTENT_SCALE_ASPECT_EXPAND, + + }; + enum { + DEFAULT_WINDOW_SIZE = 100 + }; + +private: + DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID; + + String title; + mutable int current_screen = 0; + mutable Vector2i position; + mutable Size2i size = Size2i(DEFAULT_WINDOW_SIZE, DEFAULT_WINDOW_SIZE); + mutable Size2i min_size; + mutable Size2i max_size; + mutable Mode mode = MODE_WINDOWED; + mutable bool flags[FLAG_MAX]; + bool visible = true; + bool focused = false; + + bool use_font_oversampling = false; + bool transient = false; + bool exclusive = false; + bool wrap_controls = false; + bool updating_child_controls = false; + + void _update_child_controls(); + + Size2i content_scale_size; + ContentScaleMode content_scale_mode; + ContentScaleAspect content_scale_aspect; + + void _make_window(); + void _clear_window(); + void _update_from_window(); + + void _update_viewport_size(); + void _update_window_size(); + + void _propagate_window_notification(Node *p_node, int p_notification); + + void _update_window_callbacks(); + + void _clear_transient(); + void _make_transient(); + Window *transient_parent = nullptr; + Window *exclusive_child = nullptr; + Set<Window *> transient_children; + + friend class Control; + Ref<Theme> theme; + Control *theme_owner = nullptr; + Window *theme_owner_window = nullptr; + + Viewport *embedder = nullptr; + + friend class Viewport; //friend back, can call the methods below + + void _window_input(const Ref<InputEvent> &p_ev); + void _window_input_text(const String &p_text); + void _window_drop_files(const Vector<String> &p_files); + void _rect_changed_callback(const Rect2i &p_callback); + void _event_callback(DisplayServer::WindowEvent p_event); + +protected: + Viewport *_get_embedder() const; + + virtual Rect2i _popup_adjust_rect() const { return Rect2i(); } + + virtual void _post_popup() {} + virtual Size2 _get_contents_minimum_size() const; + static void _bind_methods(); + void _notification(int p_what); + + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + +public: + enum { + + NOTIFICATION_VISIBILITY_CHANGED = 30, + NOTIFICATION_POST_POPUP = 31, + NOTIFICATION_THEME_CHANGED = 32, + }; + + void set_title(const String &p_title); + String get_title() const; + + void set_current_screen(int p_screen); + int get_current_screen() const; + + void set_position(const Point2i &p_position); + Point2i get_position() const; + + void set_size(const Size2i &p_size); + Size2i get_size() const; + + Size2i get_real_size() const; + + void set_max_size(const Size2i &p_max_size); + Size2i get_max_size() const; + + void set_min_size(const Size2i &p_min_size); + Size2i get_min_size() const; + + void set_mode(Mode p_mode); + Mode get_mode() const; + + void set_flag(Flags p_flag, bool p_enabled); + bool get_flag(Flags p_flag) const; + + bool is_maximize_allowed() const; + + void request_attention(); + void move_to_foreground(); + + void set_visible(bool p_visible); + bool is_visible() const; + + void show(); + void hide(); + + void set_transient(bool p_transient); + bool is_transient() const; + + void set_exclusive(bool p_exclusive); + bool is_exclusive() const; + + bool can_draw() const; + + void set_ime_active(bool p_active); + void set_ime_position(const Point2i &p_pos); + + bool is_embedded() const; + + void set_content_scale_size(const Size2i &p_size); + Size2i get_content_scale_size() const; + + void set_content_scale_mode(ContentScaleMode p_mode); + ContentScaleMode get_content_scale_mode() const; + + void set_content_scale_aspect(ContentScaleAspect p_aspect); + ContentScaleAspect get_content_scale_aspect() const; + + void set_use_font_oversampling(bool p_oversampling); + bool is_using_font_oversampling() const; + + void set_wrap_controls(bool p_enable); + bool is_wrapping_controls() const; + void child_controls_changed(); + + Window *get_parent_visible_window() const; + Viewport *get_parent_viewport() const; + void popup(const Rect2i &p_rect = Rect2i()); + void popup_on_parent(const Rect2i &p_parent_rect); + void popup_centered_ratio(float p_ratio = 0.8); + void popup_centered(const Size2i &p_minsize = Size2i()); + void popup_centered_clamped(const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75); + + void set_theme(const Ref<Theme> &p_theme); + Ref<Theme> get_theme() const; + + Size2 get_contents_minimum_size() const; + + void grab_focus(); + bool has_focus() const; + + Rect2i get_usable_parent_rect() const; + + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<Shader> get_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; + Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const; + Color get_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const; + int get_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const; + + bool has_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const; + bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const; + + Rect2i get_parent_rect() const; + virtual DisplayServer::WindowID get_window_id() const; + + Window(); + ~Window(); +}; + +VARIANT_ENUM_CAST(Window::Window::Mode); +VARIANT_ENUM_CAST(Window::Window::Flags); +VARIANT_ENUM_CAST(Window::ContentScaleMode); +VARIANT_ENUM_CAST(Window::ContentScaleAspect); + +#endif // WINDOW_H diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index f15911b0e2..41c43a586b 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -128,6 +128,7 @@ #include "scene/main/scene_tree.h" #include "scene/main/timer.h" #include "scene/main/viewport.h" +#include "scene/main/window.h" #include "scene/resources/audio_stream_sample.h" #include "scene/resources/bit_map.h" #include "scene/resources/box_shape.h" @@ -267,13 +268,14 @@ void register_scene_types() { ClassDB::register_class<Node>(); ClassDB::register_virtual_class<InstancePlaceholder>(); - ClassDB::register_class<Viewport>(); + ClassDB::register_virtual_class<Viewport>(); ClassDB::register_class<ViewportTexture>(); ClassDB::register_class<HTTPRequest>(); ClassDB::register_class<Timer>(); ClassDB::register_class<CanvasLayer>(); ClassDB::register_class<CanvasModulate>(); ClassDB::register_class<ResourcePreloader>(); + ClassDB::register_class<Window>(); /* REGISTER GUI */ ClassDB::register_class<ButtonGroup>(); @@ -348,8 +350,7 @@ void register_scene_types() { ClassDB::register_class<RichTextLabel>(); ClassDB::register_class<RichTextEffect>(); ClassDB::register_class<CharFXTransform>(); - ClassDB::register_class<PopupDialog>(); - ClassDB::register_class<WindowDialog>(); + ; ClassDB::register_class<AcceptDialog>(); ClassDB::register_class<ConfirmationDialog>(); ClassDB::register_class<MarginContainer>(); @@ -480,7 +481,7 @@ void register_scene_types() { #endif ClassDB::register_class<NavigationMesh>(); - AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel()))); + AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(DisplayServer::get_singleton()->get_swap_ok_cancel()))); ClassDB::register_class<Shader>(); ClassDB::register_class<VisualShader>(); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 9f5b49c4c3..0c45779307 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -188,6 +188,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Panel theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); + theme->set_stylebox("panel_fg", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); // Focus @@ -523,17 +524,19 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // WindowDialog - theme->set_stylebox("panel", "WindowDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); - theme->set_constant("scaleborder_size", "WindowDialog", 4 * scale); + theme->set_stylebox("panel", "Window", default_style); + theme->set_stylebox("window_panel", "Window", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); + theme->set_constant("scaleborder_size", "Window", 4 * scale); - theme->set_font("title_font", "WindowDialog", large_font); - theme->set_color("title_color", "WindowDialog", Color(0, 0, 0)); - theme->set_constant("title_height", "WindowDialog", 20 * scale); + theme->set_font("title_font", "Window", large_font); + theme->set_color("title_color", "Window", Color(0, 0, 0)); + theme->set_constant("title_height", "Window", 20 * scale); + theme->set_constant("resize_margin", "Window", 4 * scale); - theme->set_icon("close", "WindowDialog", make_icon(close_png)); - theme->set_icon("close_highlight", "WindowDialog", make_icon(close_hl_png)); - theme->set_constant("close_h_ofs", "WindowDialog", 18 * scale); - theme->set_constant("close_v_ofs", "WindowDialog", 18 * scale); + theme->set_icon("close", "Window", make_icon(close_png)); + theme->set_icon("close_highlight", "Window", make_icon(close_hl_png)); + theme->set_constant("close_h_ofs", "Window", 18 * scale); + theme->set_constant("close_v_ofs", "Window", 18 * scale); // File Dialog diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 6bdc4cf6f0..75bdeeac07 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -33,7 +33,7 @@ #include "core/project_settings.h" #include "scene/2d/camera_2d.h" #include "scene/2d/visibility_notifier_2d.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "servers/physics_2d_server.h" #include "servers/visual_server.h" diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index d3c5a87cae..1f0365dab9 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -193,6 +193,12 @@ SceneStringNames::SceneStringNames() { mesh_materials[i] = "material/" + itos(i); } + _window_group = StaticCString::create("_window_group"); + _window_input = StaticCString::create("_window_input"); + window_input = StaticCString::create("window_input"); + _window_unhandled_input = StaticCString::create("_window_unhandled_input"); + + theme_changed = StaticCString::create("theme_changed"); parameters_base_path = "parameters/"; tracks_changed = "tracks_changed"; diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 7976a2072c..e255ebb3cb 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -201,6 +201,13 @@ public: StringName tracks_changed; + StringName _window_group; + StringName _window_input; + StringName _window_unhandled_input; + StringName window_input; + + StringName theme_changed; + enum { MAX_MATERIALS = 32 }; diff --git a/servers/arvr/arvr_interface.h b/servers/arvr/arvr_interface.h index f33ddb2411..861061cbf5 100644 --- a/servers/arvr/arvr_interface.h +++ b/servers/arvr/arvr_interface.h @@ -33,7 +33,7 @@ #include "core/math/camera_matrix.h" #include "core/os/thread_safe.h" -#include "scene/main/viewport.h" +#include "scene/main/window.h" #include "servers/arvr_server.h" /** diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp index a64e36b6a2..dabeb7b86f 100644 --- a/servers/arvr/arvr_positional_tracker.cpp +++ b/servers/arvr/arvr_positional_tracker.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "arvr_positional_tracker.h" -#include "core/os/input.h" +#include "core/input/input_filter.h" void ARVRPositionalTracker::_bind_methods() { BIND_ENUM_CONSTANT(TRACKER_HAND_UNKNOWN); diff --git a/servers/display_server.cpp b/servers/display_server.cpp new file mode 100644 index 0000000000..1685328cbe --- /dev/null +++ b/servers/display_server.cpp @@ -0,0 +1,594 @@ +/*************************************************************************/ +/* display_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "display_server.h" +#include "core/input/input_filter.h" +#include "scene/resources/texture.h" + +DisplayServer *DisplayServer::singleton = nullptr; +DisplayServer::SwitchVSyncCallbackInThread DisplayServer::switch_vsync_function = nullptr; + +bool DisplayServer::hidpi_allowed = false; + +DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[DisplayServer::MAX_SERVERS]; +int DisplayServer::server_create_count = 0; + +void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_add_separator(const String &p_menu_root) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) { + WARN_PRINT("Global menus not supported by this display server."); +} + +bool DisplayServer::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return false; +} + +bool DisplayServer::global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return false; +} + +Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, int p_idx) { + WARN_PRINT("Global menus not supported by this display server."); + return Callable(); +} + +Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) { + WARN_PRINT("Global menus not supported by this display server."); + return Variant(); +} + +String DisplayServer::global_menu_get_item_text(const String &p_menu_root, int p_idx) { + WARN_PRINT("Global menus not supported by this display server."); + return String(); +} + +String DisplayServer::global_menu_get_item_submenu(const String &p_menu_root, int p_idx) { + WARN_PRINT("Global menus not supported by this display server."); + return String(); +} + +void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) { + WARN_PRINT("Global menus not supported by this display server."); +} + +int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const { + WARN_PRINT("Global menus not supported by this display server."); + return 0; +} + +void DisplayServer::global_menu_remove_item(const String &p_menu_root, int p_idx) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::global_menu_clear(const String &p_menu_root) { + WARN_PRINT("Global menus not supported by this display server."); +} + +void DisplayServer::mouse_set_mode(MouseMode p_mode) { + WARN_PRINT("Mouse is not supported by this display server."); +} +DisplayServer::MouseMode DisplayServer::mouse_get_mode() const { + return MOUSE_MODE_VISIBLE; +} + +void DisplayServer::mouse_warp_to_position(const Point2i &p_to) { + WARN_PRINT("Mouse warping is not supported by this display server."); +} +Point2i DisplayServer::mouse_get_absolute_position() const { + ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server."); +} +Point2i DisplayServer::mouse_get_position() const { + ERR_FAIL_V_MSG(Point2i(), "Mouse is not supported by this display server."); +} +int DisplayServer::mouse_get_button_state() const { + ERR_FAIL_V_MSG(0, "Mouse is not supported by this display server."); +} + +void DisplayServer::clipboard_set(const String &p_text) { + WARN_PRINT("Clipboard is not supported by this display server."); +} +String DisplayServer::clipboard_get() const { + ERR_FAIL_V_MSG(String(), "Clipboard is not supported by this display server."); +} + +void DisplayServer::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) { + WARN_PRINT("Orientation not supported by this display server."); +} +DisplayServer::ScreenOrientation DisplayServer::screen_get_orientation(int p_screen) const { + return SCREEN_LANDSCAPE; +} + +float DisplayServer::screen_get_scale(int p_screen) const { + return 1.0f; +}; + +bool DisplayServer::screen_is_touchscreen(int p_screen) const { + //return false; + return InputFilter::get_singleton() && InputFilter::get_singleton()->is_emulating_touch_from_mouse(); +} + +void DisplayServer::screen_set_keep_on(bool p_enable) { + WARN_PRINT("Keeping screen on not supported by this display server."); +} +bool DisplayServer::screen_is_kept_on() const { + return false; +} + +DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &) { + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server."); +} +void DisplayServer::delete_sub_window(WindowID p_id) { + ERR_FAIL_MSG("Sub-windows not supported by this display server."); +} + +void DisplayServer::window_set_ime_active(const bool p_active, WindowID p_window) { + WARN_PRINT("IME not supported by this display server."); +} +void DisplayServer::window_set_ime_position(const Point2i &p_pos, WindowID p_window) { + WARN_PRINT("IME not supported by this display server."); +} + +Point2i DisplayServer::ime_get_selection() const { + ERR_FAIL_V_MSG(Point2i(), "IME or NOTIFICATION_WM_IME_UPDATE not supported by this display server."); +} +String DisplayServer::ime_get_text() const { + ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server."); +} + +void DisplayServer::console_set_visible(bool p_enabled) { + WARN_PRINT("Console window not supported by this display server."); +} +bool DisplayServer::is_console_visible() const { + return false; +} + +void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_legth) { + WARN_PRINT("Virtual keyboard not supported by this display server."); +} +void DisplayServer::virtual_keyboard_hide() { + WARN_PRINT("Virtual keyboard not supported by this display server."); +} + +// returns height of the currently shown keyboard (0 if keyboard is hidden) +int DisplayServer::virtual_keyboard_get_height() const { + ERR_FAIL_V_MSG(0, "Virtual keyboad not supported by this display server."); +} + +void DisplayServer::cursor_set_shape(CursorShape p_shape) { + WARN_PRINT("Cursor shape not supported by this display server."); +} +DisplayServer::CursorShape DisplayServer::cursor_get_shape() const { + return CURSOR_ARROW; +} +void DisplayServer::cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + WARN_PRINT("Custom cursor shape not supported by this display server."); +} + +bool DisplayServer::get_swap_ok_cancel() { + return false; +} + +void DisplayServer::enable_for_stealing_focus(OS::ProcessID pid) { +} + +//plays video natively, in fullscreen, only implemented in mobile for now, likely not possible to implement on linux also. +Error DisplayServer::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track, int p_screen) { + ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Native video not supported by this display server."); +} +bool DisplayServer::native_video_is_playing() const { + return false; +} +void DisplayServer::native_video_pause() { + WARN_PRINT("Native video not supported by this display server."); +} +void DisplayServer::native_video_unpause() { + WARN_PRINT("Native video not supported by this display server."); +} +void DisplayServer::native_video_stop() { + WARN_PRINT("Native video not supported by this display server."); +} + +Error DisplayServer::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) { + WARN_PRINT("Native dialogs not supported by this display server."); + return OK; +} +Error DisplayServer::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) { + WARN_PRINT("Native dialogs not supported by this display server."); + return OK; +} + +DisplayServer::LatinKeyboardVariant DisplayServer::get_latin_keyboard_variant() const { + return LATIN_KEYBOARD_QWERTY; +} + +void DisplayServer::force_process_and_drop_events() { +} + +void DisplayServer::release_rendering_thread() { + WARN_PRINT("Rendering thread not supported by this display server."); +} +void DisplayServer::make_rendering_thread() { + WARN_PRINT("Rendering thread not supported by this display server."); +} +void DisplayServer::swap_buffers() { + WARN_PRINT("Swap buffers not supported by this display server."); +} + +void DisplayServer::set_native_icon(const String &p_filename) { + WARN_PRINT("Native icon not supported by this display server."); +} +void DisplayServer::set_icon(const Ref<Image> &p_icon) { + WARN_PRINT("Icon not supported by this display server."); +} + +void DisplayServer::_set_use_vsync(bool p_enable) { + WARN_PRINT("VSync not supported by this display server."); +} +void DisplayServer::vsync_set_enabled(bool p_enable) { + vsync_enabled = p_enable; + if (switch_vsync_function) { //if a function was set, use function + switch_vsync_function(p_enable); + } else { //otherwise just call here + _set_use_vsync(p_enable); + } +} +bool DisplayServer::vsync_is_enabled() const { + return vsync_enabled; +} + +void DisplayServer::vsync_set_use_via_compositor(bool p_enable) { + WARN_PRINT("VSync via compositor not supported by this display server."); +} +bool DisplayServer::vsync_is_using_via_compositor() const { + return false; +} + +void DisplayServer::set_context(Context p_context) { +} + +void DisplayServer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature); + ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name); + + ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag"), &DisplayServer::global_menu_add_item, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag"), &DisplayServer::global_menu_add_check_item, DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu"), &DisplayServer::global_menu_add_submenu_item); + ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root"), &DisplayServer::global_menu_add_separator); + + ClassDB::bind_method(D_METHOD("global_menu_is_item_checked", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checked); + ClassDB::bind_method(D_METHOD("global_menu_is_item_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checkable); + ClassDB::bind_method(D_METHOD("global_menu_get_item_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_callback); + ClassDB::bind_method(D_METHOD("global_menu_get_item_tag", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tag); + ClassDB::bind_method(D_METHOD("global_menu_get_item_text", "menu_root", "idx"), &DisplayServer::global_menu_get_item_text); + ClassDB::bind_method(D_METHOD("global_menu_get_item_submenu", "menu_root", "idx"), &DisplayServer::global_menu_get_item_submenu); + + ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked); + ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable); + ClassDB::bind_method(D_METHOD("global_menu_set_item_callback", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_callback); + ClassDB::bind_method(D_METHOD("global_menu_set_item_tag", "menu_root", "idx", "tag"), &DisplayServer::global_menu_set_item_tag); + ClassDB::bind_method(D_METHOD("global_menu_set_item_text", "menu_root", "idx", "text"), &DisplayServer::global_menu_set_item_text); + ClassDB::bind_method(D_METHOD("global_menu_set_item_submenu", "menu_root", "idx", "submenu"), &DisplayServer::global_menu_set_item_submenu); + + ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item); + ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear); + + ClassDB::bind_method(D_METHOD("alert", "text", "title"), &DisplayServer::alert, DEFVAL("Alert!")); + + ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode); + ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode); + + ClassDB::bind_method(D_METHOD("mouse_warp_to_position", "position"), &DisplayServer::mouse_warp_to_position); + ClassDB::bind_method(D_METHOD("mouse_get_position"), &DisplayServer::mouse_get_position); + ClassDB::bind_method(D_METHOD("mouse_get_absolute_position"), &DisplayServer::mouse_get_absolute_position); + ClassDB::bind_method(D_METHOD("mouse_get_button_state"), &DisplayServer::mouse_get_button_state); + + ClassDB::bind_method(D_METHOD("clipboard_set", "clipboard"), &DisplayServer::clipboard_set); + ClassDB::bind_method(D_METHOD("clipboard_get"), &DisplayServer::clipboard_get); + + ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count); + ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_get_size", "screen"), &DisplayServer::screen_get_size, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_get_usable_rect", "screen"), &DisplayServer::screen_get_usable_rect, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_get_dpi", "screen"), &DisplayServer::screen_get_dpi, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_get_scale", "screen"), &DisplayServer::screen_get_scale, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_is_touchscreen", "screen"), &DisplayServer::screen_is_touchscreen, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + + ClassDB::bind_method(D_METHOD("screen_set_orientation", "orientation", "screen"), &DisplayServer::screen_set_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + ClassDB::bind_method(D_METHOD("screen_get_orientation", "screen"), &DisplayServer::screen_get_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW)); + + ClassDB::bind_method(D_METHOD("screen_set_keep_on", "enable"), &DisplayServer::screen_set_keep_on); + ClassDB::bind_method(D_METHOD("screen_is_kept_on"), &DisplayServer::screen_is_kept_on); + + ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list); + ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position); + + ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i())); + ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window); + + ClassDB::bind_method(D_METHOD("window_set_title", "title", "window_id"), &DisplayServer::window_set_title, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_current_screen", "window_id"), &DisplayServer::window_get_current_screen, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_current_screen", "screen", "window_id"), &DisplayServer::window_set_current_screen, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_position", "window_id"), &DisplayServer::window_get_position, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_position", "position", "window_id"), &DisplayServer::window_set_position, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_size", "window_id"), &DisplayServer::window_get_size, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_size", "size", "window_id"), &DisplayServer::window_set_size, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_rect_changed_callback", "callback", "window_id"), &DisplayServer::window_set_rect_changed_callback, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_window_event_callback", "callback", "window_id"), &DisplayServer::window_set_window_event_callback, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_input_event_callback", "callback", "window_id"), &DisplayServer::window_set_input_event_callback, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_input_text_callback", "callback", "window_id"), &DisplayServer::window_set_input_text_callback, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_drop_files_callback", "callback", "window_id"), &DisplayServer::window_set_drop_files_callback, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_attach_instance_id", "instance_id", "window_id"), &DisplayServer::window_attach_instance_id, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_get_attached_instance_id", "window_id"), &DisplayServer::window_get_attached_instance_id, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_max_size", "window_id"), &DisplayServer::window_get_max_size, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_max_size", "max_size", "window_id"), &DisplayServer::window_set_max_size, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_min_size", "window_id"), &DisplayServer::window_get_min_size, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_min_size", "min_size", "window_id"), &DisplayServer::window_set_min_size, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_real_size", "window_id"), &DisplayServer::window_get_real_size, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_get_mode", "window_id"), &DisplayServer::window_get_mode, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_mode", "mode", "window_id"), &DisplayServer::window_set_mode, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_set_flag", "flag", "enabled", "window_id"), &DisplayServer::window_set_flag, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_get_flag", "flag", "window_id"), &DisplayServer::window_get_flag, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_request_attention", "window_id"), &DisplayServer::window_request_attention, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_move_to_foreground", "window_id"), &DisplayServer::window_move_to_foreground, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_can_draw", "window_id"), &DisplayServer::window_can_draw, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("window_set_transient", "window_id", "parent_window_id"), &DisplayServer::window_set_transient); + + ClassDB::bind_method(D_METHOD("window_set_ime_active", "active", "window_id"), &DisplayServer::window_set_ime_active, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_ime_position", "position", "window_id"), &DisplayServer::window_set_ime_position, DEFVAL(MAIN_WINDOW_ID)); + + ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection); + ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); + + ClassDB::bind_method(D_METHOD("console_set_visible", "console_visible"), &DisplayServer::console_set_visible); + ClassDB::bind_method(D_METHOD("is_console_visible"), &DisplayServer::is_console_visible); + + ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "max_length"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide); + + ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height); + + ClassDB::bind_method(D_METHOD("cursor_set_shape", "shape"), &DisplayServer::cursor_set_shape); + ClassDB::bind_method(D_METHOD("cursor_get_shape"), &DisplayServer::cursor_get_shape); + ClassDB::bind_method(D_METHOD("cursor_set_custom_image", "cursor", "shape", "hotspot"), &DisplayServer::cursor_set_custom_image, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); + + ClassDB::bind_method(D_METHOD("get_swap_ok_cancel"), &DisplayServer::get_swap_ok_cancel); + + ClassDB::bind_method(D_METHOD("enable_for_stealing_focus", "process_id"), &DisplayServer::enable_for_stealing_focus); + + ClassDB::bind_method(D_METHOD("native_video_play", "path", "volume", "audio_track", "subtitle_track"), &DisplayServer::native_video_play); + ClassDB::bind_method(D_METHOD("native_video_is_playing"), &DisplayServer::native_video_is_playing); + ClassDB::bind_method(D_METHOD("native_video_stop"), &DisplayServer::native_video_stop); + ClassDB::bind_method(D_METHOD("native_video_pause"), &DisplayServer::native_video_pause); + ClassDB::bind_method(D_METHOD("native_video_unpause"), &DisplayServer::native_video_unpause); + + ClassDB::bind_method(D_METHOD("dialog_show", "title", "description", "buttons", "callback"), &DisplayServer::dialog_show); + ClassDB::bind_method(D_METHOD("dialog_input_text", "title", "description", "existing_text", "callback"), &DisplayServer::dialog_show); + + ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &DisplayServer::get_latin_keyboard_variant); + + ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events); + ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events); + + ClassDB::bind_method(D_METHOD("vsync_set_enabled", "enabled"), &DisplayServer::vsync_set_enabled); + ClassDB::bind_method(D_METHOD("vsync_is_enabled"), &DisplayServer::vsync_is_enabled); + + ClassDB::bind_method(D_METHOD("vsync_set_use_via_compositor", "enabled"), &DisplayServer::vsync_set_use_via_compositor); + ClassDB::bind_method(D_METHOD("vsync_is_using_via_compositor"), &DisplayServer::vsync_is_using_via_compositor); + + ClassDB::bind_method(D_METHOD("set_native_icon", "filename"), &DisplayServer::set_native_icon); + ClassDB::bind_method(D_METHOD("set_icon", "image"), &DisplayServer::set_icon); + + BIND_ENUM_CONSTANT(FEATURE_GLOBAL_MENU); + BIND_ENUM_CONSTANT(FEATURE_SUBWINDOWS); + BIND_ENUM_CONSTANT(FEATURE_TOUCHSCREEN); + BIND_ENUM_CONSTANT(FEATURE_MOUSE); + BIND_ENUM_CONSTANT(FEATURE_MOUSE_WARP); + BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD); + BIND_ENUM_CONSTANT(FEATURE_VIRTUAL_KEYBOARD); + BIND_ENUM_CONSTANT(FEATURE_CURSOR_SHAPE); + BIND_ENUM_CONSTANT(FEATURE_CUSTOM_CURSOR_SHAPE); + BIND_ENUM_CONSTANT(FEATURE_NATIVE_VIDEO); + BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG); + BIND_ENUM_CONSTANT(FEATURE_CONSOLE_WINDOW); + BIND_ENUM_CONSTANT(FEATURE_IME); + BIND_ENUM_CONSTANT(FEATURE_WINDOW_TRANSPARENCY); + BIND_ENUM_CONSTANT(FEATURE_HIDPI); + BIND_ENUM_CONSTANT(FEATURE_ICON); + BIND_ENUM_CONSTANT(FEATURE_NATIVE_ICON); + BIND_ENUM_CONSTANT(FEATURE_ORIENTATION); + BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS); + + BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); + BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); + BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); + BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); + + BIND_CONSTANT(SCREEN_OF_MAIN_WINDOW); + BIND_CONSTANT(MAIN_WINDOW_ID); + BIND_CONSTANT(INVALID_WINDOW_ID); + + BIND_ENUM_CONSTANT(SCREEN_LANDSCAPE); + BIND_ENUM_CONSTANT(SCREEN_PORTRAIT); + BIND_ENUM_CONSTANT(SCREEN_REVERSE_LANDSCAPE); + BIND_ENUM_CONSTANT(SCREEN_REVERSE_PORTRAIT); + BIND_ENUM_CONSTANT(SCREEN_SENSOR_LANDSCAPE); + BIND_ENUM_CONSTANT(SCREEN_SENSOR_PORTRAIT); + BIND_ENUM_CONSTANT(SCREEN_SENSOR); + + BIND_ENUM_CONSTANT(CURSOR_ARROW); + BIND_ENUM_CONSTANT(CURSOR_IBEAM); + BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND); + BIND_ENUM_CONSTANT(CURSOR_CROSS); + BIND_ENUM_CONSTANT(CURSOR_WAIT); + BIND_ENUM_CONSTANT(CURSOR_BUSY); + BIND_ENUM_CONSTANT(CURSOR_DRAG); + BIND_ENUM_CONSTANT(CURSOR_CAN_DROP); + BIND_ENUM_CONSTANT(CURSOR_FORBIDDEN); + BIND_ENUM_CONSTANT(CURSOR_VSIZE); + BIND_ENUM_CONSTANT(CURSOR_HSIZE); + BIND_ENUM_CONSTANT(CURSOR_BDIAGSIZE); + BIND_ENUM_CONSTANT(CURSOR_FDIAGSIZE); + BIND_ENUM_CONSTANT(CURSOR_MOVE); + BIND_ENUM_CONSTANT(CURSOR_VSPLIT); + BIND_ENUM_CONSTANT(CURSOR_HSPLIT); + BIND_ENUM_CONSTANT(CURSOR_HELP); + BIND_ENUM_CONSTANT(CURSOR_MAX); + + BIND_ENUM_CONSTANT(WINDOW_MODE_WINDOWED); + BIND_ENUM_CONSTANT(WINDOW_MODE_MINIMIZED); + BIND_ENUM_CONSTANT(WINDOW_MODE_MAXIMIZED); + BIND_ENUM_CONSTANT(WINDOW_MODE_FULLSCREEN); + + BIND_ENUM_CONSTANT(WINDOW_FLAG_RESIZE_DISABLED); + BIND_ENUM_CONSTANT(WINDOW_FLAG_BORDERLESS); + BIND_ENUM_CONSTANT(WINDOW_FLAG_ALWAYS_ON_TOP); + BIND_ENUM_CONSTANT(WINDOW_FLAG_TRANSPARENT); + BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS); + BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX); + BIND_ENUM_CONSTANT(WINDOW_FLAG_RESIZE_DISABLED_BIT); + BIND_ENUM_CONSTANT(WINDOW_FLAG_BORDERLESS_BIT); + BIND_ENUM_CONSTANT(WINDOW_FLAG_ALWAYS_ON_TOP_BIT); + BIND_ENUM_CONSTANT(WINDOW_FLAG_TRANSPARENT_BIT); + BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS_BIT); + + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_QWERTY); + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_QWERTZ); + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_AZERTY); + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_QZERTY); + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_DVORAK); + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_NEO); + BIND_ENUM_CONSTANT(LATIN_KEYBOARD_COLEMAK); + + BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER); + BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_EXIT); + BIND_ENUM_CONSTANT(WINDOW_EVENT_FOCUS_IN); + BIND_ENUM_CONSTANT(WINDOW_EVENT_FOCUS_OUT); + BIND_ENUM_CONSTANT(WINDOW_EVENT_CLOSE_REQUEST); + BIND_ENUM_CONSTANT(WINDOW_EVENT_GO_BACK_REQUEST); + BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE); +} + +void DisplayServer::register_create_function(const char *p_name, CreateFunction p_function, GetVideoDriversFunction p_get_drivers) { + ERR_FAIL_COND(server_create_count == MAX_SERVERS); + server_create_functions[server_create_count].create_function = p_function; + server_create_functions[server_create_count].name = p_name; + server_create_count++; +} +int DisplayServer::get_create_function_count() { + return server_create_count; +} +const char *DisplayServer::get_create_function_name(int p_index) { + ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr); + return server_create_functions[p_index].name; +} + +Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index) { + ERR_FAIL_INDEX_V(p_index, server_create_count, Vector<String>()); + return server_create_functions[p_index].get_rendering_drivers_function(); +} + +DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { + ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr); + return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_flags, p_resolution, r_error); +} + +void DisplayServer::_input_set_mouse_mode(InputFilter::MouseMode p_mode) { + singleton->mouse_set_mode(MouseMode(p_mode)); +} +InputFilter::MouseMode DisplayServer::_input_get_mouse_mode() { + return InputFilter::MouseMode(singleton->mouse_get_mode()); +} + +void DisplayServer::_input_warp(const Vector2 &p_to_pos) { + singleton->mouse_warp_to_position(p_to_pos); +} + +InputFilter::CursorShape DisplayServer::_input_get_current_cursor_shape() { + return (InputFilter::CursorShape)singleton->cursor_get_shape(); +} +void DisplayServer::_input_set_custom_mouse_cursor_func(const RES &p_image, InputFilter::CursorShape p_shape, const Vector2 &p_hostspot) { + singleton->cursor_set_custom_image(p_image, (CursorShape)p_shape, p_hostspot); +} + +DisplayServer::DisplayServer() { + singleton = this; + InputFilter::set_mouse_mode_func = _input_set_mouse_mode; + InputFilter::get_mouse_mode_func = _input_get_mouse_mode; + InputFilter::warp_mouse_func = _input_warp; + InputFilter::get_current_cursor_shape_func = _input_get_current_cursor_shape; + InputFilter::set_custom_mouse_cursor_func = _input_set_custom_mouse_cursor_func; +} +DisplayServer::~DisplayServer() { +} diff --git a/servers/display_server.h b/servers/display_server.h new file mode 100644 index 0000000000..8ed0b11d03 --- /dev/null +++ b/servers/display_server.h @@ -0,0 +1,383 @@ +/*************************************************************************/ +/* display_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DISPLAY_SERVER_H +#define DISPLAY_SERVER_H + +#include "core/callable.h" +#include "core/input/input_filter.h" +#include "core/os/os.h" +#include "core/resource.h" + +class Texture2D; + +class DisplayServer : public Object { + GDCLASS(DisplayServer, Object) + + static DisplayServer *singleton; + bool vsync_enabled = true; + static bool hidpi_allowed; + +public: + _FORCE_INLINE_ static DisplayServer *get_singleton() { + return singleton; + } + + enum WindowMode { + WINDOW_MODE_WINDOWED, + WINDOW_MODE_MINIMIZED, + WINDOW_MODE_MAXIMIZED, + WINDOW_MODE_FULLSCREEN + }; + + typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, uint32_t, const Size2i &, Error &r_error); //video driver, window mode, resolution + typedef Vector<String> (*GetVideoDriversFunction)(); //video driver, window mode, resolution +private: + static void _input_set_mouse_mode(InputFilter::MouseMode p_mode); + static InputFilter::MouseMode _input_get_mouse_mode(); + static void _input_warp(const Vector2 &p_to_pos); + static InputFilter::CursorShape _input_get_current_cursor_shape(); + static void _input_set_custom_mouse_cursor_func(const RES &, InputFilter::CursorShape, const Vector2 &p_hostspot); + +protected: + static void _bind_methods(); + enum { + MAX_SERVERS = 64 + }; + + struct DisplayServerCreate { + const char *name; + GetVideoDriversFunction get_rendering_drivers_function; + CreateFunction create_function; + }; + + static DisplayServerCreate server_create_functions[MAX_SERVERS]; + static int server_create_count; + + friend class VisualServerRaster; + virtual void _set_use_vsync(bool p_enable); + +public: + enum Feature { + FEATURE_GLOBAL_MENU, + FEATURE_SUBWINDOWS, + FEATURE_TOUCHSCREEN, + FEATURE_MOUSE, + FEATURE_MOUSE_WARP, + FEATURE_CLIPBOARD, + FEATURE_VIRTUAL_KEYBOARD, + FEATURE_CURSOR_SHAPE, + FEATURE_CUSTOM_CURSOR_SHAPE, + FEATURE_NATIVE_VIDEO, + FEATURE_NATIVE_DIALOG, + FEATURE_CONSOLE_WINDOW, + FEATURE_IME, + FEATURE_WINDOW_TRANSPARENCY, + FEATURE_HIDPI, + FEATURE_ICON, + FEATURE_NATIVE_ICON, + FEATURE_ORIENTATION, + FEATURE_SWAP_BUFFERS, + FEATURE_KEEP_SCREEN_ON, + }; + + virtual bool has_feature(Feature p_feature) const = 0; + virtual String get_name() const = 0; + + virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()); + virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()); + virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu); + virtual void global_menu_add_separator(const String &p_menu_root); + + virtual bool global_menu_is_item_checked(const String &p_menu_root, int p_idx) const; + virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const; + virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx); + virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx); + virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx); + virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx); + + virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked); + virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); + virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback); + virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag); + virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text); + virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu); + + virtual int global_menu_get_item_count(const String &p_menu_root) const; + + virtual void global_menu_remove_item(const String &p_menu_root, int p_idx); + virtual void global_menu_clear(const String &p_menu_root); + + virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0; + + enum MouseMode { + MOUSE_MODE_VISIBLE, + MOUSE_MODE_HIDDEN, + MOUSE_MODE_CAPTURED, + MOUSE_MODE_CONFINED + }; + + virtual void mouse_set_mode(MouseMode p_mode); + virtual MouseMode mouse_get_mode() const; + + virtual void mouse_warp_to_position(const Point2i &p_to); + virtual Point2i mouse_get_position() const; + virtual Point2i mouse_get_absolute_position() const; + virtual int mouse_get_button_state() const; + + virtual void clipboard_set(const String &p_text); + virtual String clipboard_get() const; + + enum { + SCREEN_OF_MAIN_WINDOW = -1 + }; + + virtual int get_screen_count() const = 0; + virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; + virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; + virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; + virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0; + virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + enum ScreenOrientation { + + SCREEN_LANDSCAPE, + SCREEN_PORTRAIT, + SCREEN_REVERSE_LANDSCAPE, + SCREEN_REVERSE_PORTRAIT, + SCREEN_SENSOR_LANDSCAPE, + SCREEN_SENSOR_PORTRAIT, + SCREEN_SENSOR, + }; + + virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW); + ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const; + + virtual void screen_set_keep_on(bool p_enable); //disable screensaver + virtual bool screen_is_kept_on() const; + enum { + MAIN_WINDOW_ID = 0, + INVALID_WINDOW_ID = -1 + }; + + typedef int WindowID; + + virtual Vector<DisplayServer::WindowID> get_window_list() const = 0; + + enum WindowFlags { + WINDOW_FLAG_RESIZE_DISABLED, + WINDOW_FLAG_BORDERLESS, + WINDOW_FLAG_ALWAYS_ON_TOP, + WINDOW_FLAG_TRANSPARENT, + WINDOW_FLAG_NO_FOCUS, + WINDOW_FLAG_MAX, + WINDOW_FLAG_RESIZE_DISABLED_BIT = (1 << WINDOW_FLAG_RESIZE_DISABLED), + WINDOW_FLAG_BORDERLESS_BIT = (1 << WINDOW_FLAG_BORDERLESS), + WINDOW_FLAG_ALWAYS_ON_TOP_BIT = (1 << WINDOW_FLAG_ALWAYS_ON_TOP), + WINDOW_FLAG_TRANSPARENT_BIT = (1 << WINDOW_FLAG_TRANSPARENT), + WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS) + }; + + virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i()); + virtual void delete_sub_window(WindowID p_id); + + virtual WindowID get_window_at_screen_position(const Point2i &p_position) const = 0; + + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; + + enum WindowEvent { + WINDOW_EVENT_MOUSE_ENTER, + WINDOW_EVENT_MOUSE_EXIT, + WINDOW_EVENT_FOCUS_IN, + WINDOW_EVENT_FOCUS_OUT, + WINDOW_EVENT_CLOSE_REQUEST, + WINDOW_EVENT_GO_BACK_REQUEST, + WINDOW_EVENT_DPI_CHANGE, + }; + virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; + + virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; + + virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) = 0; + + virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const = 0; + virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) = 0; + + virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const = 0; + virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) = 0; + + virtual void window_set_transient(WindowID p_window, WindowID p_parent) = 0; + + virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const = 0; + virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const = 0; // FIXME: Find clearer name for this. + + virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0; + + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const = 0; + + virtual bool can_any_window_draw() const = 0; + + virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); + + virtual Point2i ime_get_selection() const; + virtual String ime_get_text() const; + + virtual void console_set_visible(bool p_enabled); + virtual bool is_console_visible() const; + + virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_legth = -1); + virtual void virtual_keyboard_hide(); + + // returns height of the currently shown virtual keyboard (0 if keyboard is hidden) + virtual int virtual_keyboard_get_height() const; + + enum CursorShape { + CURSOR_ARROW, + CURSOR_IBEAM, + CURSOR_POINTING_HAND, + CURSOR_CROSS, + CURSOR_WAIT, + CURSOR_BUSY, + CURSOR_DRAG, + CURSOR_CAN_DROP, + CURSOR_FORBIDDEN, + CURSOR_VSIZE, + CURSOR_HSIZE, + CURSOR_BDIAGSIZE, + CURSOR_FDIAGSIZE, + CURSOR_MOVE, + CURSOR_VSPLIT, + CURSOR_HSPLIT, + CURSOR_HELP, + CURSOR_MAX + }; + virtual void cursor_set_shape(CursorShape p_shape); + virtual CursorShape cursor_get_shape() const; + virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); + + virtual bool get_swap_ok_cancel(); + + virtual void enable_for_stealing_focus(OS::ProcessID pid); + + //plays video natively, in fullscreen, only implemented in mobile for now, likely not possible to implement on linux also. + virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track, int p_screen = SCREEN_OF_MAIN_WINDOW); + virtual bool native_video_is_playing() const; + virtual void native_video_pause(); + virtual void native_video_unpause(); + virtual void native_video_stop(); + + virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback); + virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback); + + enum LatinKeyboardVariant { + LATIN_KEYBOARD_QWERTY, + LATIN_KEYBOARD_QWERTZ, + LATIN_KEYBOARD_AZERTY, + LATIN_KEYBOARD_QZERTY, + LATIN_KEYBOARD_DVORAK, + LATIN_KEYBOARD_NEO, + LATIN_KEYBOARD_COLEMAK, + }; + + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + + virtual void process_events() = 0; + + virtual void force_process_and_drop_events(); + + virtual void release_rendering_thread(); + virtual void make_rendering_thread(); + virtual void swap_buffers(); + + virtual void set_native_icon(const String &p_filename); + virtual void set_icon(const Ref<Image> &p_icon); + + typedef void (*SwitchVSyncCallbackInThread)(bool); + + static SwitchVSyncCallbackInThread switch_vsync_function; + + void vsync_set_enabled(bool p_enable); + bool vsync_is_enabled() const; + + virtual void vsync_set_use_via_compositor(bool p_enable); + virtual bool vsync_is_using_via_compositor() const; + + //real, actual overridable function to switch vsync, which needs to be called from graphics thread if needed + + enum Context { + CONTEXT_EDITOR, + CONTEXT_PROJECTMAN, + CONTEXT_ENGINE, + }; + + virtual void set_context(Context p_context); + + static void register_create_function(const char *p_name, CreateFunction p_function, GetVideoDriversFunction p_get_drivers); + static int get_create_function_count(); + static const char *get_create_function_name(int p_index); + static Vector<String> get_create_function_rendering_drivers(int p_index); + static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error); + + DisplayServer(); + ~DisplayServer(); +}; + +VARIANT_ENUM_CAST(DisplayServer::WindowEvent) +VARIANT_ENUM_CAST(DisplayServer::Feature) +VARIANT_ENUM_CAST(DisplayServer::MouseMode) +VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation) +VARIANT_ENUM_CAST(DisplayServer::WindowMode) +VARIANT_ENUM_CAST(DisplayServer::WindowFlags) +VARIANT_ENUM_CAST(DisplayServer::CursorShape) +VARIANT_ENUM_CAST(DisplayServer::LatinKeyboardVariant) + +#endif // DISPLAY_SERVER_H diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index fd65f57380..574b373c30 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "register_server_types.h" + #include "core/engine.h" #include "core/project_settings.h" @@ -56,6 +57,7 @@ #include "audio_server.h" #include "camera/camera_feed.h" #include "camera_server.h" +#include "display_server.h" #include "navigation_2d_server.h" #include "navigation_server.h" #include "physics/physics_server_sw.h" @@ -95,6 +97,7 @@ void register_server_types() { OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback); + ClassDB::register_virtual_class<DisplayServer>(); ClassDB::register_virtual_class<VisualServer>(); ClassDB::register_class<AudioServer>(); ClassDB::register_virtual_class<PhysicsServer>(); diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 84eda2d80c..d5d32c8d47 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -1294,7 +1294,7 @@ public: }; virtual void prepare_for_blitting_render_targets() = 0; - virtual void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; + virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; virtual void end_frame(bool p_swap_buffers) = 0; virtual void finalize() = 0; diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp index 206320376b..9c54f0caae 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_rd.cpp @@ -34,7 +34,7 @@ void RasterizerRD::prepare_for_blitting_render_targets() { RD::get_singleton()->prepare_screen_for_drawing(); } -void RasterizerRD::blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount) { +void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen); diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.h b/servers/visual/rasterizer_rd/rasterizer_rd.h index d14e9fb36e..bbcf9bfefe 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_rd.h @@ -66,7 +66,7 @@ public: void initialize(); void begin_frame(double frame_step); void prepare_for_blitting_render_targets(); - void blit_render_targets_to_screen(int p_screen, const BlitToScreen *p_render_targets, int p_amount); + void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount); void end_frame(bool p_swap_buffers); void finalize(); diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h index ed55afd961..4705bcaa75 100644 --- a/servers/visual/rendering_device.h +++ b/servers/visual/rendering_device.h @@ -32,6 +32,7 @@ #define RENDERING_DEVICE_H #include "core/object.h" +#include "servers/display_server.h" class RenderingDevice : public Object { GDCLASS(RenderingDevice, Object) @@ -896,8 +897,8 @@ public: /**** SCREEN ****/ /****************/ - virtual int screen_get_width(int p_screen = 0) const = 0; - virtual int screen_get_height(int p_screen = 0) const = 0; + virtual int screen_get_width(DisplayServer::WindowID p_screen = 0) const = 0; + virtual int screen_get_height(DisplayServer::WindowID p_screen = 0) const = 0; virtual FramebufferFormatID screen_get_framebuffer_format() const = 0; /********************/ @@ -920,7 +921,7 @@ public: typedef int64_t DrawListID; - virtual DrawListID draw_list_begin_for_screen(int p_screen = 0, const Color &p_clear_color = Color()) = 0; + virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()) = 0; virtual DrawListID draw_list_begin(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<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 35ec52a5c0..1026972a62 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -234,7 +234,7 @@ void VisualServerRaster::set_debug_generate_wireframes(bool p_generate) { } void VisualServerRaster::call_set_use_vsync(bool p_enable) { - OS::get_singleton()->_set_use_vsync(p_enable); + DisplayServer::get_singleton()->_set_use_vsync(p_enable); } bool VisualServerRaster::is_low_end() const { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index b6afbbff93..1a40fc96a2 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -466,7 +466,6 @@ public: BIND3(viewport_attach_to_screen, RID, const Rect2 &, int) BIND2(viewport_set_render_direct_to_screen, RID, bool) - BIND1(viewport_detach, RID) BIND2(viewport_set_update_mode, RID, ViewportUpdateMode) BIND2(viewport_set_vflip, RID, bool) diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 43262042cc..555d5f99c7 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -312,11 +312,14 @@ void VisualServerViewport::draw_viewports() { //sort viewports active_viewports.sort_custom<ViewportSort>(); - Map<int, Vector<Rasterizer::BlitToScreen>> blit_to_screen_list; + Map<DisplayServer::WindowID, Vector<Rasterizer::BlitToScreen>> blit_to_screen_list; //draw viewports RENDER_TIMESTAMP(">Render Viewports"); - for (int i = 0; i < active_viewports.size(); i++) { + //determine what is visible + draw_viewports_pass++; + + for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order Viewport *vp = active_viewports[i]; @@ -328,11 +331,37 @@ void VisualServerViewport::draw_viewports() { } //ERR_CONTINUE(!vp->render_target.is_valid()); - bool visible = vp->viewport_to_screen_rect != Rect2() || vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE || (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target)); + bool visible = vp->viewport_to_screen_rect != Rect2(); + + if (vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE) { + visible = true; + } + + if (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target)) { + visible = true; + } + + if (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE) { + Viewport *parent = viewport_owner.getornull(vp->parent); + if (parent && parent->last_pass == draw_viewports_pass) { + visible = true; + } + } + visible = visible && vp->size.x > 1 && vp->size.y > 1; - if (!visible) - continue; + if (visible) { + vp->last_pass = draw_viewports_pass; + } + } + + for (int i = 0; i < active_viewports.size(); i++) { + + Viewport *vp = active_viewports[i]; + + if (vp->last_pass != draw_viewports_pass) { + continue; //should not draw + } RENDER_TIMESTAMP(">Rendering Viewport " + itos(i)); @@ -389,11 +418,16 @@ void VisualServerViewport::draw_viewports() { vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); - if (vp->viewport_to_screen_rect != Rect2() && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) { + if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) { //copy to screen if set as such Rasterizer::BlitToScreen blit; blit.render_target = vp->render_target; - blit.rect = vp->viewport_to_screen_rect; + if (vp->viewport_to_screen_rect != Rect2()) { + blit.rect = vp->viewport_to_screen_rect; + } else { + blit.rect.position = Vector2(); + blit.rect.size = vp->size; + } if (!blit_to_screen_list.has(vp->viewport_to_screen)) { blit_to_screen_list[vp->viewport_to_screen] = Vector<Rasterizer::BlitToScreen>(); @@ -450,13 +484,15 @@ void VisualServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_ Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); - // if (viewport->size.width == p_width && viewport->size.height == p_height) { - // return; //nothing to do - // } viewport->size = Size2(p_width, p_height); VSG::storage->render_target_set_size(viewport->render_target, p_width, p_height); if (viewport->render_buffers.is_valid()) { - VSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa); + if (p_width == 0 || p_height == 0) { + VSG::scene_render->free(viewport->render_buffers); + viewport->render_buffers = RID(); + } else { + VSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa); + } } } @@ -489,21 +525,34 @@ void VisualServerViewport::viewport_set_clear_mode(RID p_viewport, VS::ViewportC viewport->clear_mode = p_clear_mode; } -void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, int p_screen) { +void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); - // If using GLES2 we can optimize this operation by rendering directly to system_fbo - // instead of rendering to fbo and copying to system_fbo after - if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + if (p_screen != DisplayServer::INVALID_WINDOW_ID) { + // If using GLES2 we can optimize this operation by rendering directly to system_fbo + // instead of rendering to fbo and copying to system_fbo after + if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { - VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y); - VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y); - } + VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y); + VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y); + } + + viewport->viewport_to_screen_rect = p_rect; + viewport->viewport_to_screen = p_screen; + } else { - viewport->viewport_to_screen_rect = p_rect; - viewport->viewport_to_screen = p_screen; + // if render_direct_to_screen was used, reset size and position + if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + VSG::storage->render_target_set_position(viewport->render_target, 0, 0); + VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + + viewport->viewport_to_screen_rect = Rect2(); + viewport->viewport_to_screen = DisplayServer::INVALID_WINDOW_ID; + } } void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { @@ -531,22 +580,6 @@ void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, } } -void VisualServerViewport::viewport_detach(RID p_viewport) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - // if render_direct_to_screen was used, reset size and position - if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { - - VSG::storage->render_target_set_position(viewport->render_target, 0, 0); - VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); - } - - viewport->viewport_to_screen_rect = Rect2(); - viewport->viewport_to_screen = 0; -} - void VisualServerViewport::viewport_set_update_mode(RID p_viewport, VS::ViewportUpdateMode p_mode) { Viewport *viewport = viewport_owner.getornull(p_viewport); diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h index 30b53f3935..06372376f8 100644 --- a/servers/visual/visual_server_viewport.h +++ b/servers/visual/visual_server_viewport.h @@ -60,7 +60,7 @@ public: VS::ViewportMSAA msaa; - int viewport_to_screen; + DisplayServer::WindowID viewport_to_screen; Rect2 viewport_to_screen_rect; bool viewport_render_direct_to_screen; @@ -73,6 +73,8 @@ public: RID shadow_atlas; int shadow_atlas_size; + uint64_t last_pass = 0; + int render_info[VS::VIEWPORT_RENDER_INFO_MAX]; VS::ViewportDebugDraw debug_draw; @@ -117,7 +119,7 @@ public: clear_mode = VS::VIEWPORT_CLEAR_ALWAYS; transparent_bg = false; disable_environment = false; - viewport_to_screen = 0; + viewport_to_screen = DisplayServer::INVALID_WINDOW_ID; shadow_atlas_size = 0; keep_3d_linear = false; debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; @@ -129,6 +131,8 @@ public: } }; + uint64_t draw_viewports_pass = 0; + mutable RID_PtrOwner<Viewport> viewport_owner; struct ViewportSort { @@ -139,9 +143,9 @@ public: if (left_to_screen == right_to_screen) { - return p_left->parent == p_right->self; + return p_right->parent == p_left->self; } - return right_to_screen; + return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1); } }; @@ -158,9 +162,8 @@ public: void viewport_set_size(RID p_viewport, int p_width, int p_height); - void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0); + void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID); void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable); - void viewport_detach(RID p_viewport); void viewport_set_active(RID p_viewport, bool p_active); void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport); diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp index 90d301c0cd..4169144fc9 100644 --- a/servers/visual/visual_server_wrap_mt.cpp +++ b/servers/visual/visual_server_wrap_mt.cpp @@ -31,6 +31,7 @@ #include "visual_server_wrap_mt.h" #include "core/os/os.h" #include "core/project_settings.h" +#include "servers/display_server.h" void VisualServerWrapMT::thread_exit() { @@ -61,7 +62,7 @@ void VisualServerWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); - OS::get_singleton()->make_rendering_thread(); + DisplayServer::get_singleton()->make_rendering_thread(); visual_server->init(); @@ -108,7 +109,7 @@ void VisualServerWrapMT::init() { if (create_thread) { print_verbose("VisualServerWrapMT: Creating render thread"); - OS::get_singleton()->release_rendering_thread(); + DisplayServer::get_singleton()->release_rendering_thread(); if (create_thread) { thread = Thread::create(_thread_callback, this); print_verbose("VisualServerWrapMT: Starting render thread"); @@ -173,7 +174,7 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer *p_contained, bool p_create_ command_queue(p_create_thread) { singleton_mt = this; - OS::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly + DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly visual_server = p_contained; create_thread = p_create_thread; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 0d4683e43d..e043ac5214 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -379,9 +379,8 @@ public: FUNC2(viewport_set_clear_mode, RID, ViewportClearMode) - FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int) + FUNC3(viewport_attach_to_screen, RID, const Rect2 &, DisplayServer::WindowID) FUNC2(viewport_set_render_direct_to_screen, RID, bool) - FUNC1(viewport_detach, RID) FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index b50ad89b1e..1e4ee5cb50 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1769,9 +1769,9 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &VisualServer::viewport_set_size); ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active); ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport); - ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &VisualServer::viewport_set_render_direct_to_screen); - ClassDB::bind_method(D_METHOD("viewport_detach", "viewport"), &VisualServer::viewport_detach); + ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode); ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &VisualServer::viewport_set_clear_mode); ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &VisualServer::viewport_get_texture); @@ -2060,6 +2060,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS); diff --git a/servers/visual_server.h b/servers/visual_server.h index dfe5e7feed..506800cc7d 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -37,6 +37,7 @@ #include "core/object.h" #include "core/rid.h" #include "core/variant.h" +#include "servers/display_server.h" class VisualServer : public Object { @@ -584,14 +585,14 @@ public: virtual void viewport_set_active(RID p_viewport, bool p_active) = 0; virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; - virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), int p_screen = 0) = 0; + virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0; virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0; - virtual void viewport_detach(RID p_viewport) = 0; enum ViewportUpdateMode { VIEWPORT_UPDATE_DISABLED, VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated VIEWPORT_UPDATE_WHEN_VISIBLE, // default + VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE, VIEWPORT_UPDATE_ALWAYS }; |