summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/crypto/hashing_context.cpp2
-rw-r--r--core/io/file_access_encrypted.cpp16
-rw-r--r--core/io/file_access_encrypted.h3
-rw-r--r--core/io/file_access_zip.cpp2
-rw-r--r--core/math/disjoint_set.cpp31
-rw-r--r--core/math/disjoint_set.h155
-rw-r--r--core/math/geometry.cpp2
-rw-r--r--core/os/main_loop.h2
-rw-r--r--core/ustring.cpp4
-rw-r--r--core/variant.cpp10
-rw-r--r--core/variant_parser.cpp2
-rw-r--r--doc/classes/AnimatedTexture.xml2
-rw-r--r--doc/classes/AnimationNode.xml2
-rw-r--r--doc/classes/AnimationPlayer.xml4
-rw-r--r--doc/classes/AtlasTexture.xml3
-rw-r--r--doc/classes/Camera2D.xml2
-rw-r--r--doc/classes/Control.xml10
-rw-r--r--doc/classes/EditorVCSInterface.xml4
-rw-r--r--doc/classes/Image.xml5
-rw-r--r--doc/classes/Input.xml4
-rw-r--r--doc/classes/LineEdit.xml3
-rw-r--r--doc/classes/MainLoop.xml8
-rw-r--r--doc/classes/NinePatchRect.xml2
-rw-r--r--doc/classes/Node.xml9
-rw-r--r--doc/classes/Node2D.xml2
-rw-r--r--doc/classes/Physics2DServer.xml2
-rw-r--r--doc/classes/PopupMenu.xml2
-rw-r--r--doc/classes/ProjectSettings.xml2
-rw-r--r--doc/classes/Skeleton.xml2
-rw-r--r--doc/classes/Tree.xml2
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp4
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp12
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp28
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h9
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp7
-rw-r--r--drivers/gles2/shaders/canvas.glsl26
-rw-r--r--drivers/gles2/shaders/copy.glsl4
-rw-r--r--drivers/gles2/shaders/scene.glsl12
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp5
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp18
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h6
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp7
-rw-r--r--drivers/gles3/shaders/canvas.glsl26
-rw-r--r--drivers/gles3/shaders/scene.glsl10
-rw-r--r--editor/animation_bezier_editor.cpp7
-rw-r--r--editor/animation_track_editor.cpp47
-rw-r--r--editor/animation_track_editor.h4
-rw-r--r--editor/collada/collada.cpp6
-rw-r--r--editor/connections_dialog.cpp2
-rw-r--r--editor/editor_audio_buses.cpp7
-rw-r--r--editor/editor_help.cpp7
-rw-r--r--editor/editor_help_search.cpp17
-rw-r--r--editor/editor_inspector.cpp15
-rw-r--r--editor/editor_log.cpp6
-rw-r--r--editor/editor_log.h3
-rw-r--r--editor/editor_network_profiler.cpp35
-rw-r--r--editor/editor_node.cpp19
-rw-r--r--editor/editor_properties.cpp53
-rw-r--r--editor/editor_properties.h1
-rw-r--r--editor/editor_properties_array_dict.cpp4
-rw-r--r--editor/editor_resource_preview.cpp2
-rw-r--r--editor/editor_themes.cpp8
-rw-r--r--editor/editor_vcs_interface.cpp9
-rw-r--r--editor/export_template_manager.cpp89
-rw-r--r--editor/export_template_manager.h2
-rw-r--r--editor/icons/icon_GUI_tree_option.svg5
-rw-r--r--editor/icons/icon_arrow_down.svg1
-rw-r--r--editor/icons/icon_arrow_up.svg6
-rw-r--r--editor/icons/icon_bus_vu_db.svg12
-rw-r--r--editor/icons/icon_camera_texture.svg5
-rw-r--r--editor/icons/icon_clipped_camera.svg3
-rw-r--r--editor/icons/icon_height_map_shape.svg12
-rw-r--r--editor/icons/icon_interpolated_camera.svg2
-rw-r--r--editor/icons/icon_mesh_texture.svg3
-rw-r--r--editor/icons/icon_rich_text_effect.svg6
-rw-r--r--editor/icons/icon_skeleton_i_k.svg3
-rw-r--r--editor/icons/icon_soft_body.svg57
-rw-r--r--editor/icons/icon_spring_arm.svg6
-rw-r--r--editor/icons/icon_style_box_line.svg11
-rw-r--r--editor/import/editor_import_collada.cpp1
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp1740
-rw-r--r--editor/import/editor_scene_importer_gltf.h215
-rw-r--r--editor/import/resource_importer_scene.cpp2
-rw-r--r--editor/import_dock.cpp8
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp29
-rw-r--r--editor/plugins/animation_player_editor_plugin.h11
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp20
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h1
-rw-r--r--editor/plugins/script_editor_plugin.cpp45
-rw-r--r--editor/plugins/script_text_editor.cpp153
-rw-r--r--editor/plugins/script_text_editor.h2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp13
-rw-r--r--editor/plugins/shader_editor_plugin.h2
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp2
-rw-r--r--editor/plugins/spatial_editor_plugin.h3
-rw-r--r--editor/plugins/sprite_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp66
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h3
-rw-r--r--editor/plugins/text_editor.cpp15
-rw-r--r--editor/plugins/text_editor.h2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp7
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp108
-rw-r--r--editor/plugins/tile_map_editor_plugin.h2
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp26
-rw-r--r--editor/plugins/tile_set_editor_plugin.h1
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp52
-rw-r--r--editor/project_manager.cpp28
-rw-r--r--editor/project_settings_editor.cpp86
-rw-r--r--editor/project_settings_editor.h4
-rw-r--r--editor/scene_tree_dock.cpp55
-rw-r--r--editor/script_editor_debugger.cpp45
-rw-r--r--editor/script_editor_debugger.h1
-rw-r--r--editor/settings_config_dialog.cpp6
-rw-r--r--editor/spatial_editor_gizmos.cpp101
-rw-r--r--misc/dist/html/full-size.html2
-rwxr-xr-xmisc/hooks/pre-commit-clang-format2
-rw-r--r--misc/ide/jetbrains/AndroidManifest.xml44
-rw-r--r--misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.jarbin54329 -> 0 bytes
-rw-r--r--misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xmisc/ide/jetbrains/gradlew172
-rw-r--r--misc/ide/jetbrains/gradlew.bat84
-rwxr-xr-xmisc/travis/clang-format.sh2
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp109
-rw-r--r--modules/bmp/image_loader_bmp.cpp228
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/csg/csg_gizmos.cpp2
-rw-r--r--modules/cvtt/SCsub19
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp4
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp2
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript_compiler.cpp10
-rw-r--r--modules/gdscript/gdscript_function.cpp13
-rw-r--r--modules/gdscript/gdscript_parser.cpp159
-rw-r--r--modules/gdscript/gdscript_parser.h8
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp6
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp4
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp4
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp22
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h7
-rw-r--r--modules/mono/build_scripts/mono_configure.py2
-rw-r--r--modules/mono/editor/bindings_generator.cpp3
-rw-r--r--modules/mono/glue/Managed/Files/Rect2.cs8
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp12
-rw-r--r--modules/visual_script/visual_script.cpp15
-rw-r--r--modules/visual_script/visual_script.h3
-rw-r--r--modules/visual_script/visual_script_editor.cpp10
-rw-r--r--modules/visual_script/visual_script_editor.h1
-rw-r--r--platform/android/SCsub24
-rw-r--r--platform/android/export/export.cpp20
-rw-r--r--platform/android/java/app/AndroidManifest.xml (renamed from platform/android/java/AndroidManifest.xml)10
-rw-r--r--platform/android/java/app/build.gradle121
-rw-r--r--platform/android/java/app/config.gradle12
-rw-r--r--platform/android/java/app/src/com/godot/game/GodotApp.java10
-rw-r--r--platform/android/java/build.gradle158
-rw-r--r--platform/android/java/gradle/wrapper/gradle-wrapper.properties3
-rw-r--r--platform/android/java/lib/AndroidManifest.xml19
-rw-r--r--platform/android/java/lib/CMakeLists.txt (renamed from misc/ide/jetbrains/CMakeLists.txt)2
-rw-r--r--platform/android/java/lib/THIRDPARTY.md (renamed from platform/android/java/THIRDPARTY.md)0
-rw-r--r--platform/android/java/lib/aidl/com/android/vending/billing/IInAppBillingService.aidl (renamed from platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl)0
-rw-r--r--platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl (renamed from platform/android/java/aidl/com/android/vending/licensing/ILicenseResultListener.aidl)0
-rw-r--r--platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl (renamed from platform/android/java/aidl/com/android/vending/licensing/ILicensingService.aidl)0
-rw-r--r--platform/android/java/lib/build.gradle (renamed from misc/ide/jetbrains/build.gradle)51
-rw-r--r--platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch (renamed from platform/android/java/patches/com.google.android.vending.expansion.downloader.patch)4
-rw-r--r--platform/android/java/lib/patches/com.google.android.vending.licensing.patch (renamed from platform/android/java/patches/com.google.android.vending.licensing.patch)2
-rw-r--r--platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.png (renamed from platform/android/java/res/drawable-hdpi/notify_panel_notification_icon_bg.png)bin1843 -> 1843 bytes
-rw-r--r--platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.png (renamed from platform/android/java/res/drawable-mdpi/notify_panel_notification_icon_bg.png)bin718 -> 718 bytes
-rw-r--r--platform/android/java/lib/res/drawable-nodpi/icon.png (renamed from platform/android/java/res/drawable-nodpi/icon.png)bin7569 -> 7569 bytes
-rw-r--r--platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.png (renamed from platform/android/java/res/drawable-xhdpi/notify_panel_notification_icon_bg.png)bin462 -> 462 bytes
-rw-r--r--platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png (renamed from platform/android/java/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png)bin2830 -> 2830 bytes
-rw-r--r--platform/android/java/lib/res/layout/downloading_expansion.xml (renamed from platform/android/java/res/layout/downloading_expansion.xml)0
-rw-r--r--platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml (renamed from platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml)0
-rw-r--r--platform/android/java/lib/res/values-ar/strings.xml (renamed from platform/android/java/res/values-ar/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-bg/strings.xml (renamed from platform/android/java/res/values-bg/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-ca/strings.xml (renamed from platform/android/java/res/values-ca/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-cs/strings.xml (renamed from platform/android/java/res/values-cs/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-da/strings.xml (renamed from platform/android/java/res/values-da/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-de/strings.xml (renamed from platform/android/java/res/values-de/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-el/strings.xml (renamed from platform/android/java/res/values-el/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-en/strings.xml (renamed from platform/android/java/res/values-en/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-es-rES/strings.xml (renamed from platform/android/java/res/values-es-rES/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-es/strings.xml (renamed from platform/android/java/res/values-es/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-fa/strings.xml (renamed from platform/android/java/res/values-fa/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-fi/strings.xml (renamed from platform/android/java/res/values-fi/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-fr/strings.xml (renamed from platform/android/java/res/values-fr/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-hi/strings.xml (renamed from platform/android/java/res/values-hi/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-hr/strings.xml (renamed from platform/android/java/res/values-hr/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-hu/strings.xml (renamed from platform/android/java/res/values-hu/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-in/strings.xml (renamed from platform/android/java/res/values-in/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-it/strings.xml (renamed from platform/android/java/res/values-it/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-iw/strings.xml (renamed from platform/android/java/res/values-iw/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-ja/strings.xml (renamed from platform/android/java/res/values-ja/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-ko/strings.xml (renamed from platform/android/java/res/values-ko/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-lt/strings.xml (renamed from platform/android/java/res/values-lt/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-lv/strings.xml (renamed from platform/android/java/res/values-lv/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-nb/strings.xml (renamed from platform/android/java/res/values-nb/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-nl/strings.xml (renamed from platform/android/java/res/values-nl/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-pl/strings.xml (renamed from platform/android/java/res/values-pl/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-pt/strings.xml (renamed from platform/android/java/res/values-pt/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-ro/strings.xml (renamed from platform/android/java/res/values-ro/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-ru/strings.xml (renamed from platform/android/java/res/values-ru/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-sk/strings.xml (renamed from platform/android/java/res/values-sk/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-sl/strings.xml (renamed from platform/android/java/res/values-sl/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-sr/strings.xml (renamed from platform/android/java/res/values-sr/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-sv/strings.xml (renamed from platform/android/java/res/values-sv/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-th/strings.xml (renamed from platform/android/java/res/values-th/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-tl/strings.xml (renamed from platform/android/java/res/values-tl/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-tr/strings.xml (renamed from platform/android/java/res/values-tr/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-uk/strings.xml (renamed from platform/android/java/res/values-uk/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-vi/strings.xml (renamed from platform/android/java/res/values-vi/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-zh-rCN/strings.xml (renamed from platform/android/java/res/values-zh-rCN/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-zh-rHK/strings.xml (renamed from platform/android/java/res/values-zh-rHK/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values-zh-rTW/strings.xml (renamed from platform/android/java/res/values-zh-rTW/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values/strings.xml (renamed from platform/android/java/res/values/strings.xml)0
-rw-r--r--platform/android/java/lib/res/values/styles.xml (renamed from platform/android/java/res/values/styles.xml)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Constants.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/Constants.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Helpers.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java)2
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderService.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderService.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IStub.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/IStub.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/SystemFacade.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java)2
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java (renamed from platform/android/java/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/AESObfuscator.java (renamed from platform/android/java/src/com/google/android/vending/licensing/AESObfuscator.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/APKExpansionPolicy.java (renamed from platform/android/java/src/com/google/android/vending/licensing/APKExpansionPolicy.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/DeviceLimiter.java (renamed from platform/android/java/src/com/google/android/vending/licensing/DeviceLimiter.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/LicenseChecker.java (renamed from platform/android/java/src/com/google/android/vending/licensing/LicenseChecker.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/LicenseCheckerCallback.java (renamed from platform/android/java/src/com/google/android/vending/licensing/LicenseCheckerCallback.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/LicenseValidator.java (renamed from platform/android/java/src/com/google/android/vending/licensing/LicenseValidator.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/NullDeviceLimiter.java (renamed from platform/android/java/src/com/google/android/vending/licensing/NullDeviceLimiter.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java (renamed from platform/android/java/src/com/google/android/vending/licensing/Obfuscator.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/Policy.java (renamed from platform/android/java/src/com/google/android/vending/licensing/Policy.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/PreferenceObfuscator.java (renamed from platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/ResponseData.java (renamed from platform/android/java/src/com/google/android/vending/licensing/ResponseData.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/ServerManagedPolicy.java (renamed from platform/android/java/src/com/google/android/vending/licensing/ServerManagedPolicy.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/StrictPolicy.java (renamed from platform/android/java/src/com/google/android/vending/licensing/StrictPolicy.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/ValidationException.java (renamed from platform/android/java/src/com/google/android/vending/licensing/ValidationException.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64.java (renamed from platform/android/java/src/com/google/android/vending/licensing/util/Base64.java)2
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64DecoderException.java (renamed from platform/android/java/src/com/google/android/vending/licensing/util/Base64DecoderException.java)0
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/util/URIQueryDecoder.java (renamed from platform/android/java/src/com/google/android/vending/licensing/util/URIQueryDecoder.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Dictionary.java (renamed from platform/android/java/src/org/godotengine/godot/Dictionary.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java (renamed from platform/android/java/src/org/godotengine/godot/Godot.java)51
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java (renamed from platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotDownloaderService.java (renamed from platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java (renamed from platform/android/java/src/org/godotengine/godot/GodotIO.java)8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotInstrumentation.java (renamed from platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java (renamed from platform/android/java/src/org/godotengine/godot/GodotLib.java)12
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotPaymentV3.java (renamed from platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java (renamed from platform/android/java/src/org/godotengine/godot/GodotRenderer.java)17
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotView.java (renamed from platform/android/java/src/org/godotengine/godot/GodotView.java)32
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java (renamed from platform/android/java/src/org/godotengine/godot/input/GodotEditText.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java (renamed from platform/android/java/src/org/godotengine/godot/input/GodotInputHandler.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java (renamed from platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java)1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java (renamed from platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java (renamed from platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java (renamed from platform/android/java/src/org/godotengine/godot/input/Joystick.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/ConsumeTask.java (renamed from platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java)1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/HandlePurchaseTask.java (renamed from platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java)11
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/PaymentsCache.java (renamed from platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/PaymentsManager.java (renamed from platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java)1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/PurchaseTask.java (renamed from platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java)7
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java (renamed from platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/payments/ValidateTask.java (renamed from platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java)11
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java (renamed from platform/android/java/src/org/godotengine/godot/utils/Crypt.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java (renamed from platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java (renamed from platform/android/java/src/org/godotengine/godot/utils/GLUtils.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/HttpRequester.java (renamed from platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java)4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/RequestParams.java (renamed from platform/android/java/src/org/godotengine/godot/utils/RequestParams.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java (renamed from platform/android/java/src/org/godotengine/godot/xr/XRMode.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrConfigChooser.java (renamed from platform/android/java/src/org/godotengine/godot/xr/ovr/OvrConfigChooser.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrContextFactory.java (renamed from platform/android/java/src/org/godotengine/godot/xr/ovr/OvrContextFactory.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrWindowSurfaceFactory.java (renamed from platform/android/java/src/org/godotengine/godot/xr/ovr/OvrWindowSurfaceFactory.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java (renamed from platform/android/java/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java (renamed from platform/android/java/src/org/godotengine/godot/xr/regular/RegularContextFactory.java)0
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularFallbackConfigChooser.java (renamed from platform/android/java/src/org/godotengine/godot/xr/regular/RegularFallbackConfigChooser.java)0
-rw-r--r--platform/android/java/settings.gradle (renamed from misc/ide/jetbrains/settings.gradle)3
-rw-r--r--platform/android/java_godot_lib_jni.cpp18
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/iphone/export/export.cpp10
-rw-r--r--platform/osx/export/export.cpp2
-rw-r--r--platform/uwp/export/export.cpp8
-rw-r--r--platform/windows/camera_win.cpp12
-rw-r--r--platform/x11/os_x11.cpp13
-rw-r--r--scene/2d/canvas_item.cpp4
-rw-r--r--scene/2d/line_builder.cpp2
-rw-r--r--scene/2d/navigation_polygon.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp2
-rw-r--r--scene/3d/mesh_instance.cpp37
-rw-r--r--scene/3d/mesh_instance.h7
-rw-r--r--scene/3d/physics_body.cpp9
-rw-r--r--scene/3d/skeleton.cpp303
-rw-r--r--scene/3d/skeleton.h62
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/animation/animation_tree.cpp2
-rw-r--r--scene/animation/animation_tree_player.cpp6
-rw-r--r--scene/animation/skeleton_ik.cpp2
-rw-r--r--scene/animation/tween.cpp2
-rw-r--r--scene/gui/control.cpp24
-rw-r--r--scene/gui/dialogs.cpp5
-rw-r--r--scene/gui/line_edit.cpp224
-rw-r--r--scene/gui/line_edit.h16
-rw-r--r--scene/gui/option_button.cpp6
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/gui/text_edit.cpp146
-rw-r--r--scene/gui/text_edit.h12
-rw-r--r--scene/gui/tree.cpp4
-rw-r--r--scene/gui/tree.h2
-rw-r--r--scene/main/node.cpp2
-rw-r--r--scene/main/node.h4
-rw-r--r--scene/main/scene_tree.cpp30
-rw-r--r--scene/register_scene_types.cpp3
-rw-r--r--scene/resources/default_theme/default_theme.cpp1
-rw-r--r--scene/resources/resource_format_text.cpp1
-rw-r--r--scene/resources/skin.cpp102
-rw-r--r--scene/resources/skin.h54
-rw-r--r--scene/resources/style_box.cpp11
-rw-r--r--scene/resources/visual_shader_nodes.cpp119
-rw-r--r--servers/camera_server.h2
-rw-r--r--servers/visual/rasterizer.h1
-rw-r--r--servers/visual/shader_language.cpp40
-rw-r--r--servers/visual/shader_language.h4
-rw-r--r--servers/visual/shader_types.cpp1
-rw-r--r--servers/visual/visual_server_raster.h1
-rw-r--r--servers/visual/visual_server_viewport.cpp2
-rw-r--r--servers/visual/visual_server_wrap_mt.h1
-rw-r--r--servers/visual_server.h1
-rw-r--r--thirdparty/assimp/code/FBX/FBXConverter.cpp24
-rw-r--r--thirdparty/assimp/code/FBX/FBXConverter.h4
-rw-r--r--thirdparty/assimp/code/FBX/FBXImporter.cpp2
-rw-r--r--thirdparty/assimp/include/assimp/material.h46
340 files changed, 4378 insertions, 2407 deletions
diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp
index bdccb258dd..bd863f546b 100644
--- a/core/crypto/hashing_context.cpp
+++ b/core/crypto/hashing_context.cpp
@@ -103,7 +103,7 @@ void HashingContext::_create_ctx(HashType p_type) {
}
void HashingContext::_delete_ctx() {
- return;
+
switch (type) {
case HASH_MD5:
memdelete((CryptoCore::MD5Context *)ctx);
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 77decc107d..0eef0ee79f 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -176,6 +176,22 @@ bool FileAccessEncrypted::is_open() const {
return file != NULL;
}
+String FileAccessEncrypted::get_path() const {
+
+ if (file)
+ return file->get_path();
+ else
+ return "";
+}
+
+String FileAccessEncrypted::get_path_absolute() const {
+
+ if (file)
+ return file->get_path_absolute();
+ else
+ return "";
+}
+
void FileAccessEncrypted::seek(size_t p_position) {
if (p_position > (size_t)data.size())
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index d779a150ac..c3be0f7de8 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -60,6 +60,9 @@ public:
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
+ virtual String get_path() const; /// returns the path for the current open file
+ virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual size_t get_position() const; ///< get position in the file
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index be28c9a877..abc0bd064d 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -194,7 +194,7 @@ bool ZipArchive::try_open_pack(const String &p_path) {
packages.push_back(pkg);
int pkg_num = packages.size() - 1;
- for (unsigned int i = 0; i < gi.number_entry; i++) {
+ for (uint64_t i = 0; i < gi.number_entry; i++) {
char filename_inzip[256];
diff --git a/core/math/disjoint_set.cpp b/core/math/disjoint_set.cpp
new file mode 100644
index 0000000000..838939e1ba
--- /dev/null
+++ b/core/math/disjoint_set.cpp
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* disjoint_set.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 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 "disjoint_set.h"
diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h
new file mode 100644
index 0000000000..c9b3d0b65d
--- /dev/null
+++ b/core/math/disjoint_set.h
@@ -0,0 +1,155 @@
+/*************************************************************************/
+/* disjoint_set.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 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 DISJOINT_SET_H
+#define DISJOINT_SET_H
+
+#include "core/map.h"
+#include "core/vector.h"
+
+/**
+ @author Marios Staikopoulos <marios@staik.net>
+*/
+
+/* This DisjointSet class uses Find with path compression and Union by rank */
+template <typename T, class C = Comparator<T>, class AL = DefaultAllocator>
+class DisjointSet {
+
+ struct Element {
+ T object;
+ Element *parent = nullptr;
+ int rank = 0;
+ };
+
+ typedef Map<T, Element *, C, AL> MapT;
+
+ MapT elements;
+
+ Element *get_parent(Element *element);
+
+ _FORCE_INLINE_ Element *insert_or_get(T object);
+
+public:
+ ~DisjointSet();
+
+ _FORCE_INLINE_ void insert(T object) { (void)insert_or_get(object); }
+
+ void create_union(T a, T b);
+
+ void get_representatives(Vector<T> &out_roots);
+
+ void get_members(Vector<T> &out_members, T representative);
+};
+
+/* FUNCTIONS */
+
+template <typename T, class C, class AL>
+DisjointSet<T, C, AL>::~DisjointSet() {
+ for (typename MapT::Element *itr = elements.front(); itr != nullptr; itr = itr->next()) {
+ memdelete_allocator<Element, AL>(itr->value());
+ }
+}
+
+template <typename T, class C, class AL>
+typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::get_parent(Element *element) {
+ if (element->parent != element) {
+ element->parent = get_parent(element->parent);
+ }
+
+ return element->parent;
+}
+
+template <typename T, class C, class AL>
+typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::insert_or_get(T object) {
+ typename MapT::Element *itr = elements.find(object);
+ if (itr != nullptr) {
+ return itr->value();
+ }
+
+ Element *new_element = memnew_allocator(Element, AL);
+ new_element->object = object;
+ new_element->parent = new_element;
+ elements.insert(object, new_element);
+
+ return new_element;
+}
+
+template <typename T, class C, class AL>
+void DisjointSet<T, C, AL>::create_union(T a, T b) {
+
+ Element *x = insert_or_get(a);
+ Element *y = insert_or_get(b);
+
+ Element *x_root = get_parent(x);
+ Element *y_root = get_parent(y);
+
+ // Already in the same set
+ if (x_root == y_root)
+ return;
+
+ // Not in the same set, merge
+ if (x_root->rank < y_root->rank) {
+ SWAP(x_root, y_root);
+ }
+
+ // Merge y_root into x_root
+ y_root->parent = x_root;
+ if (x_root->rank == y_root->rank) {
+ ++x_root->rank;
+ }
+}
+
+template <typename T, class C, class AL>
+void DisjointSet<T, C, AL>::get_representatives(Vector<T> &out_representatives) {
+ for (typename MapT::Element *itr = elements.front(); itr != nullptr; itr = itr->next()) {
+ Element *element = itr->value();
+ if (element->parent == element) {
+ out_representatives.push_back(element->object);
+ }
+ }
+}
+
+template <typename T, class C, class AL>
+void DisjointSet<T, C, AL>::get_members(Vector<T> &out_members, T representative) {
+ typename MapT::Element *rep_itr = elements.find(representative);
+ ERR_FAIL_COND(rep_itr == nullptr);
+
+ Element *rep_element = rep_itr->value();
+ ERR_FAIL_COND(rep_element->parent != rep_element);
+
+ for (typename MapT::Element *itr = elements.front(); itr != nullptr; itr = itr->next()) {
+ Element *parent = get_parent(itr->value());
+ if (parent == rep_element) {
+ out_members.push_back(itr->key());
+ }
+ }
+}
+
+#endif
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index f37db90929..77383e2839 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -715,7 +715,7 @@ Vector<Vector<Vector2> > Geometry::decompose_polygon_in_convex(Vector<Point2> po
decomp.write[idx].resize(tp.GetNumPoints());
- for (int i = 0; i < tp.GetNumPoints(); i++) {
+ for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
decomp.write[idx].write[i] = tp.GetPoint(i);
}
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 54e61fd2fa..aca920efcb 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -60,6 +60,8 @@ public:
NOTIFICATION_WM_ABOUT = 1011,
NOTIFICATION_CRASH = 1012,
NOTIFICATION_OS_IME_UPDATE = 1013,
+ NOTIFICATION_APP_RESUMED = 1014,
+ NOTIFICATION_APP_PAUSED = 1015,
};
virtual void input_event(const Ref<InputEvent> &p_event);
diff --git a/core/ustring.cpp b/core/ustring.cpp
index fb4bd6d802..237e86aaf1 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -2147,13 +2147,13 @@ int64_t String::to_int(const CharType *p_str, int p_len) {
if (c >= '0' && c <= '9') {
- if (integer > INT32_MAX / 10) {
+ if (integer > INT64_MAX / 10) {
String number("");
str = p_str;
while (*str && str != limit) {
number += *(str++);
}
- ERR_FAIL_V_MSG(sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
+ ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small."));
}
integer *= 10;
integer += c - '0';
diff --git a/core/variant.cpp b/core/variant.cpp
index e7d0e58367..16bbf94c54 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -910,7 +910,15 @@ bool Variant::is_one() const {
void Variant::reference(const Variant &p_variant) {
- clear();
+ switch (type) {
+ case NIL:
+ case BOOL:
+ case INT:
+ case REAL:
+ break;
+ default:
+ clear();
+ }
type = p_variant.type;
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 07212ec669..fe2c981c3c 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1522,7 +1522,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
return err;
if (tk.type != TK_STRING) {
r_err_str = "Error reading quoted string";
- return err;
+ return ERR_INVALID_DATA;
}
what = tk.value;
diff --git a/doc/classes/AnimatedTexture.xml b/doc/classes/AnimatedTexture.xml
index 7e32db1bb8..2d3ebac78c 100644
--- a/doc/classes/AnimatedTexture.xml
+++ b/doc/classes/AnimatedTexture.xml
@@ -6,7 +6,7 @@
<description>
[AnimatedTexture] is a resource format for frame-based animations, where multiple textures can be chained automatically with a predefined delay for each frame. Unlike [AnimationPlayer] or [AnimatedSprite], it isn't a [Node], but has the advantage of being usable anywhere a [Texture] resource can be used, e.g. in a [TileSet].
The playback of the animation is controlled by the [member fps] property as well as each frame's optional delay (see [method set_frame_delay]). The animation loops, i.e. it will restart at frame 0 automatically after playing the last frame.
- [AnimatedTexture] currently requires all frame textures to have the same size, otherwise the bigger ones will be cropped to match the smallest one.
+ [AnimatedTexture] currently requires all frame textures to have the same size, otherwise the bigger ones will be cropped to match the smallest one. Also, it doesn't support [AtlasTexture]. Each frame needs to be separate image.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index 7d5d8a2db1..b4288bbfaa 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -73,7 +73,7 @@
<argument index="6" name="optimize" type="bool" default="true">
</argument>
<description>
- Blend another animaiton node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition.
+ Blend another animation node (in case this node contains children animation nodes). This function is only useful if you inherit from [AnimationRootNode] instead, else editors will not display your node for addition.
</description>
</method>
<method name="get_caption" qualifiers="virtual">
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index e510603281..5bb4a6e3c7 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -71,7 +71,7 @@
<argument index="0" name="animation" type="Animation">
</argument>
<description>
- Returns the name of [code]animation[/code] or empty string if not found.
+ Returns the name of [code]animation[/code] or an empty string if not found.
</description>
</method>
<method name="get_animation" qualifiers="const">
@@ -112,6 +112,7 @@
<return type="PoolStringArray">
</return>
<description>
+ Returns a list of the animation names that are currently queued to play.
</description>
</method>
<method name="has_animation" qualifiers="const">
@@ -284,6 +285,7 @@
</signal>
<signal name="caches_cleared">
<description>
+ Notifies when the caches have been cleared, either automatically, or manually via [method clear_caches].
</description>
</signal>
</signals>
diff --git a/doc/classes/AtlasTexture.xml b/doc/classes/AtlasTexture.xml
index 5b0a06a7fb..b270c7e279 100644
--- a/doc/classes/AtlasTexture.xml
+++ b/doc/classes/AtlasTexture.xml
@@ -4,8 +4,7 @@
Packs multiple small textures in a single, bigger one. Helps to optimize video memory costs and render calls.
</brief_description>
<description>
- [Texture] resource aimed at managing big textures files that pack multiple smaller textures. Consists of a [Texture], a margin that defines the border width,
- and a region that defines the actual area of the AtlasTexture.
+ [Texture] resource aimed at managing big textures files that pack multiple smaller textures. Consists of a [Texture], a margin that defines the border width, and a region that defines the actual area of the AtlasTexture.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index 16fb483249..aeeebdf00d 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -154,7 +154,7 @@
</member>
<member name="offset_h" type="float" setter="set_h_offset" getter="get_h_offset" default="0.0">
The horizontal offset of the camera, relative to the drag margins.
- [b]Note:[/b] Offset H is used only to force offset relative to margins. It's not updated in any way if drag margins are enabled and can be used to set inital offset.
+ [b]Note:[/b] Offset H is used only to force offset relative to margins. It's not updated in any way if drag margins are enabled and can be used to set initial offset.
</member>
<member name="offset_v" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The vertical offset of the camera, relative to the drag margins.
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 1eeef92ccc..05ffac803a 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -22,7 +22,7 @@
</return>
<description>
Virtual method to be implemented by the user. Returns whether [method _gui_input] should not be called for children controls outside this control's rectangle. Input will be clipped to the Rect of this [Control]. Similar to [member rect_clip_content], but doesn't affect visibility.
- If not overriden, defaults to [code]false[/code].
+ If not overridden, defaults to [code]false[/code].
</description>
</method>
<method name="_get_minimum_size" qualifiers="virtual">
@@ -30,7 +30,7 @@
</return>
<description>
Virtual method to be implemented by the user. Returns the minimum size for this control. Alternative to [member rect_min_size] for controlling minimum size via code. The actual minimum size will be the max value of these two (in each axis separately).
- If not overriden, defaults to [constant Vector2.ZERO].
+ If not overridden, defaults to [constant Vector2.ZERO].
</description>
</method>
<method name="_gui_input" qualifiers="virtual">
@@ -395,7 +395,7 @@
<return type="void">
</return>
<description>
- Creates an [InputEventMouseButton] that attempts to click the control. If the event is received, the control aquires focus.
+ Creates an [InputEventMouseButton] that attempts to click the control. If the event is received, the control acquires focus.
[codeblock]
func _process(delta):
grab_click_focus() #when clicking another Control node, this node will be clicked instead
@@ -503,7 +503,7 @@
</argument>
<description>
Virtual method to be implemented by the user. Returns whether the given [code]point[/code] is inside this control.
- If not overriden, default behavior is checking if the point is within control's Rect.
+ If not overridden, default behavior is checking if the point is within control's Rect.
[b]Node:[/b] If you want to check if a point is inside the control, you can use [code]get_rect().has_point(point)[/code].
</description>
</method>
@@ -564,7 +564,7 @@
<description>
Sets the anchor identified by [code]margin[/code] constant from [enum Margin] enum to value [code]anchor[/code]. A setter method for [member anchor_bottom], [member anchor_left], [member anchor_right] and [member anchor_top].
If [code]keep_margin[/code] is [code]true[/code], margins aren't updated after this operation.
- If [code]push_opposite_anchor[/code] is [code]true[/code] and the opposite anchor overlaps this anchor, the opposite one will have its value overriden. For example, when setting left anchor to 1 and the right anchor has value of 0.5, the right anchor will also get value of 1. If [code]push_opposite_anchor[/code] was [code]false[/code], the left anchor would get value 0.5.
+ If [code]push_opposite_anchor[/code] is [code]true[/code] and the opposite anchor overlaps this anchor, the opposite one will have its value overridden. For example, when setting left anchor to 1 and the right anchor has value of 0.5, the right anchor will also get value of 1. If [code]push_opposite_anchor[/code] was [code]false[/code], the left anchor would get value 0.5.
</description>
</method>
<method name="set_anchor_and_margin">
diff --git a/doc/classes/EditorVCSInterface.xml b/doc/classes/EditorVCSInterface.xml
index 2f58e6d54e..f67c1c9eb5 100644
--- a/doc/classes/EditorVCSInterface.xml
+++ b/doc/classes/EditorVCSInterface.xml
@@ -38,7 +38,7 @@
<return type="bool">
</return>
<description>
- Returns [code]true[/code] if the VCS addon has been intialized, else returns [code]false[/code].
+ Returns [code]true[/code] if the VCS addon has been initialized, else returns [code]false[/code].
</description>
</method>
<method name="get_modified_files_data">
@@ -65,7 +65,7 @@
<return type="String">
</return>
<description>
- Return the name of the VCS if the VCS has been intialized, else return an empty string.
+ Return the name of the VCS if the VCS has been initialized, else return an empty string.
</description>
</method>
<method name="initialize">
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 10be66feb8..d297bc98ae 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -252,7 +252,7 @@
<argument index="1" name="y" type="int">
</argument>
<description>
- Returns the color of the pixel at [code](x, y)[/code] if the image is locked. If the image is unlocked it always returns a [Color] with the value [code](0, 0, 0, 1.0)[/code].
+ Returns the color of the pixel at [code](x, y)[/code] if the image is locked. If the image is unlocked, it always returns a [Color] with the value [code](0, 0, 0, 1.0)[/code]. This is the same as [method get_pixelv], but two integer arguments instead of a Vector2 argument.
</description>
</method>
<method name="get_pixelv" qualifiers="const">
@@ -261,6 +261,7 @@
<argument index="0" name="src" type="Vector2">
</argument>
<description>
+ Returns the color of the pixel at [code]src[/code] if the image is locked. If the image is unlocked, it always returns a [Color] with the value [code](0, 0, 0, 1.0)[/code]. This is the same as [method get_pixel], but with a Vector2 argument instead of two integer arguments.
</description>
</method>
<method name="get_rect" qualifiers="const">
@@ -414,7 +415,7 @@
<argument index="1" name="grayscale" type="bool" default="false">
</argument>
<description>
- Saves the image as an EXR file to [code]path[/code]. If grayscale is true and the image has only one channel, it will be saved explicitely as monochrome rather than one red channel. This function will return [constant ERR_UNAVAILABLE] if Godot was compiled without the TinyEXR module.
+ Saves the image as an EXR file to [code]path[/code]. If grayscale is true and the image has only one channel, it will be saved explicitly as monochrome rather than one red channel. This function will return [constant ERR_UNAVAILABLE] if Godot was compiled without the TinyEXR module.
</description>
</method>
<method name="save_png" qualifiers="const">
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index 5fd5e8c3c0..afb3977849 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -223,7 +223,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns [code]true[/code] if you are pressing the action event. Note that if an action has multiple buttons asigned and more than one of them is pressed, releasing one button will release the action, even if some other button assigned to this action is still pressed.
+ Returns [code]true[/code] if you are pressing the action event. Note that if an action has multiple buttons assigned and more than one of them is pressed, releasing one button will release the action, even if some other button assigned to this action is still pressed.
</description>
</method>
<method name="is_joy_button_pressed" qualifiers="const">
@@ -316,6 +316,8 @@
Sets a custom mouse cursor image, which is only visible inside the game window. The hotspot can also be specified. Passing [code]null[/code] to the image parameter resets to the system cursor. See enum [code]CURSOR_*[/code] for the list of shapes.
[code]image[/code]'s size must be lower than 256×256.
[code]hotspot[/code] must be within [code]image[/code]'s size.
+ [b]Note:[/b] [AnimatedTexture]s aren't supported as custom mouse cursors. If using an [AnimatedTexture], only the first frame will be displayed.
+ [b]Note:[/b] Only images imported with the [b]Lossless[/b], [b]Lossy[/b] or [b]Uncompressed[/b] compression modes are supported. The [b]Video RAM[/b] compression mode can't be used for custom cursors.
</description>
</method>
<method name="set_default_cursor_shape">
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index d90a290fdc..c1dca9f95e 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -119,6 +119,9 @@
<member name="placeholder_text" type="String" setter="set_placeholder" getter="get_placeholder" default="&quot;&quot;">
Text shown when the [LineEdit] is empty. It is [b]not[/b] the [LineEdit]'s default value (see [member text]).
</member>
+ <member name="right_icon" type="Texture" setter="set_right_icon" getter="get_right_icon">
+ Sets the icon that will appear in the right end of the [LineEdit] if there's no [member text], or always, if [member clear_button_enabled] is set to [code]false[/code].
+ </member>
<member name="secret" type="bool" setter="set_secret" getter="is_secret" default="false">
If [code]true[/code], every character is replaced with the secret character (see [member secret_character]).
</member>
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index 181a99590a..23ce20a434 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -215,5 +215,13 @@
Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string).
Specific to the macOS platform.
</constant>
+ <constant name="NOTIFICATION_APP_RESUMED" value="1014">
+ Notification received from the OS when the app is resumed.
+ Specific to the Android platform.
+ </constant>
+ <constant name="NOTIFICATION_APP_PAUSED" value="1015">
+ Notification received from the OS when the app is paused.
+ Specific to the Android platform.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml
index f191b08d96..ce7a6ef54c 100644
--- a/doc/classes/NinePatchRect.xml
+++ b/doc/classes/NinePatchRect.xml
@@ -51,7 +51,7 @@
The height of the 9-slice's top row.
</member>
<member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect" default="Rect2( 0, 0, 0, 0 )">
- Rectangular region of the texture to sample from. If you're working with an atlas, use this property to define the area the 9-slice should use. All other properties are relative to this one.
+ Rectangular region of the texture to sample from. If you're working with an atlas, use this property to define the area the 9-slice should use. All other properties are relative to this one. If the rect is empty, NinePatchRect will use the whole texture.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The node's texture resource.
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 097fa1f6e5..b206d4a4d2 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -171,6 +171,7 @@
<description>
Duplicates the node, returning a new node.
You can fine-tune the behavior using the [code]flags[/code] (see [enum DuplicateFlags]).
+ [b]Note:[/b] It will not work properly if the node contains a script with constructor arguments (i.e. needs to supply arguments to [method Object._init] method). In that case, the node will be duplicated without a script.
</description>
</method>
<method name="find_node" qualifiers="const">
@@ -962,6 +963,14 @@
Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string).
Specific to the macOS platform.
</constant>
+ <constant name="NOTIFICATION_APP_RESUMED" value="1014">
+ Notification received from the OS when the app is resumed.
+ Specific to the Android platform.
+ </constant>
+ <constant name="NOTIFICATION_APP_PAUSED" value="1015">
+ Notification received from the OS when the app is paused.
+ Specific to the Android platform.
+ </constant>
<constant name="PAUSE_MODE_INHERIT" value="0" enum="PauseMode">
Inherits pause mode from the node's parent. For the root node, it is equivalent to [constant PAUSE_MODE_STOP]. Default.
</constant>
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index abdbfa09f7..29c4680685 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -52,7 +52,7 @@
<argument index="0" name="point" type="Vector2">
</argument>
<description>
- Rotates the node so it points towards the [code]point[/code].
+ Rotates the node so it points towards the [code]point[/code], which is expected to use global coordinates.
</description>
</method>
<method name="move_local_x">
diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml
index ba00438ea1..a139fa4664 100644
--- a/doc/classes/Physics2DServer.xml
+++ b/doc/classes/Physics2DServer.xml
@@ -822,7 +822,7 @@
<argument index="5" name="result" type="Physics2DTestMotionResult" default="null">
</argument>
<description>
- Returns whether a body can move from a given point in a given direction. Apart from the boolean return value, a [Physics2DTestMotionResult] can be passed to return additional information in.
+ Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [Physics2DTestMotionResult] can be passed to return additional information in.
</description>
</method>
<method name="capsule_shape_create">
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 3d6693da15..d917f7d7f8 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -233,7 +233,7 @@
<argument index="0" name="id" type="int">
</argument>
<description>
- Returns the index of the item containing the specified [code]id[/code]. Index is automatically assigned to each item by the engine. Index can not be set manualy.
+ Returns the index of the item containing the specified [code]id[/code]. Index is automatically assigned to each item by the engine. Index can not be set manually.
</description>
</method>
<method name="get_item_metadata" qualifiers="const">
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 86b874d8ee..b42a10b13b 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -722,7 +722,7 @@
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
</member>
<member name="rendering/environment/default_clear_color" type="Color" setter="" getter="" default="Color( 0.3, 0.3, 0.3, 1 )">
- Default background clear color. Overriddable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method VisualServer.set_default_clear_color].
+ Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method VisualServer.set_default_clear_color].
</member>
<member name="rendering/limits/buffers/blend_shape_max_buffer_size_kb" type="int" setter="" getter="" default="4096">
Max buffer size for blend shapes. Any blend shape bigger than this will not work.
diff --git a/doc/classes/Skeleton.xml b/doc/classes/Skeleton.xml
index b1e71ee924..8b17928f90 100644
--- a/doc/classes/Skeleton.xml
+++ b/doc/classes/Skeleton.xml
@@ -4,7 +4,7 @@
Skeleton for characters and animated objects.
</brief_description>
<description>
- Skeleton provides a hierarchical interface for managing bones, including pose, rest and animation (see [Animation]). Skeleton will support rag doll dynamics in the future.
+ Skeleton provides a hierarchical interface for managing bones, including pose, rest and animation (see [Animation]). It can also use ragdoll physics.
The overall transform of a bone with respect to the skeleton is determined by the following hierarchical order: rest pose, custom pose and pose.
Note that "global pose" below refers to the overall transform of the bone with respect to skeleton, so it not the actual global/world transform of the bone.
</description>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 51d56c758e..82f948c54d 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -403,8 +403,6 @@
</theme_item>
<theme_item name="guide_color" type="Color" default="Color( 0, 0, 0, 0.1 )">
</theme_item>
- <theme_item name="guide_width" type="int" default="2">
- </theme_item>
<theme_item name="hseparation" type="int" default="4">
</theme_item>
<theme_item name="item_margin" type="int" default="12">
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 0611d7d4e0..42899c0f76 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -171,14 +171,14 @@ void AudioDriverALSA::thread_func(void *p_udata) {
ad->start_counting_ticks();
if (!ad->active) {
- for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) {
+ for (uint64_t i = 0; i < ad->period_size * ad->channels; i++) {
ad->samples_out.write[i] = 0;
}
} else {
ad->audio_server_process(ad->period_size, ad->samples_in.ptrw());
- for (unsigned int i = 0; i < ad->period_size * ad->channels; i++) {
+ for (uint64_t i = 0; i < ad->period_size * ad->channels; i++) {
ad->samples_out.write[i] = ad->samples_in[i] >> 16;
}
}
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index cc414c26af..a8fa30c709 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -1432,11 +1432,11 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste
}
}
- bool clear_skeleton_buffer = !storage->config.float_texture_supported;
+ bool clear_skeleton_buffer = storage->config.use_skeleton_software;
if (p_skeleton) {
- if (storage->config.float_texture_supported) {
+ if (!storage->config.use_skeleton_software) {
//use float texture workflow
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 1);
glBindTexture(GL_TEXTURE_2D, p_skeleton->tex_id);
@@ -2452,7 +2452,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
if (skeleton) {
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, true);
- state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, !storage->config.float_texture_supported);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, storage->config.use_skeleton_software);
} else {
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_SKELETON_SOFTWARE, false);
@@ -2570,12 +2570,6 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
- if (skeleton) {
- state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_IN_WORLD_COORDS, skeleton->use_world_transform);
- state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TRANSFORM, skeleton->world_transform);
- state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TRANSFORM_INVERSE, skeleton->world_transform_inverse);
- }
-
if (use_lightmap_capture) { //this is per instance, must be set always if present
glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr());
state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false);
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 5c02d8096d..9f511cd787 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -2432,7 +2432,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
// from surface->data.
// if USE_SKELETON_SOFTWARE is active
- if (!config.float_texture_supported) {
+ if (config.use_skeleton_software) {
// if this geometry is used specifically for skinning
if (p_format & (VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS))
surface->data = array;
@@ -3514,7 +3514,7 @@ void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool
skeleton->size = p_bones;
skeleton->use_2d = p_2d_skeleton;
- if (config.float_texture_supported) {
+ if (!config.use_skeleton_software) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, skeleton->tex_id);
@@ -3663,23 +3663,6 @@ void RasterizerStorageGLES2::skeleton_set_base_transform_2d(RID p_skeleton, cons
skeleton->base_transform_2d = p_base_transform;
}
-void RasterizerStorageGLES2::skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND(skeleton->use_2d);
-
- skeleton->world_transform = p_world_transform;
- skeleton->use_world_transform = p_enable;
- if (p_enable) {
- skeleton->world_transform_inverse = skeleton->world_transform.affine_inverse();
- }
-
- if (!skeleton->update_list.in_list()) {
- skeleton_update_list.add(&skeleton->update_list);
- }
-}
-
void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size) {
glBindBuffer(GL_ARRAY_BUFFER, resources.skeleton_transform_buffer);
@@ -3699,7 +3682,7 @@ void RasterizerStorageGLES2::_update_skeleton_transform_buffer(const PoolVector<
void RasterizerStorageGLES2::update_dirty_skeletons() {
- if (!config.float_texture_supported)
+ if (config.use_skeleton_software)
return;
glActiveTexture(GL_TEXTURE0);
@@ -5751,9 +5734,14 @@ void RasterizerStorageGLES2::initialize() {
frame.current_rt = NULL;
frame.clear_request = false;
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &config.max_vertex_texture_image_units);
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
+ // the use skeleton software path should be used if either float texture is not supported,
+ // OR max_vertex_texture_image_units is zero
+ config.use_skeleton_software = (config.float_texture_supported == false) || (config.max_vertex_texture_image_units == 0);
+
shaders.copy.init();
shaders.cubemap_filter.init();
bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index d139697b86..ba9274b576 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -60,7 +60,9 @@ public:
bool shrink_textures_x2;
bool use_fast_texture_filter;
+ bool use_skeleton_software;
+ int max_vertex_texture_image_units;
int max_texture_image_units;
int max_texture_size;
@@ -868,16 +870,12 @@ public:
Set<RasterizerScene::InstanceBase *> instances;
Transform2D base_transform_2d;
- Transform world_transform;
- Transform world_transform_inverse;
- bool use_world_transform;
Skeleton() :
use_2d(false),
size(0),
tex_id(0),
- update_list(this),
- use_world_transform(false) {
+ update_list(this) {
}
};
@@ -895,7 +893,6 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
- virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform);
void _update_skeleton_transform_buffer(const PoolVector<float> &p_data, size_t p_size);
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index 640d45ae65..1db8a870a2 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -353,6 +353,11 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
varying_code += _typestr(E->get().type);
varying_code += " ";
varying_code += _mkid(E->key());
+ if (E->get().array_size > 0) {
+ varying_code += "[";
+ varying_code += itos(E->get().array_size);
+ varying_code += "]";
+ }
varying_code += ";\n";
String final_code = varying_code.as_string();
@@ -943,6 +948,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv";
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light";
actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
@@ -952,6 +958,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n";
// Ported from GLES3
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index fa0b315e29..08548ded17 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -331,6 +331,7 @@ void light_compute(
inout vec4 light_color,
vec2 light_uv,
inout vec4 shadow_color,
+ inout vec2 shadow_vec,
vec3 normal,
vec2 uv,
#if defined(SCREEN_UV_USED)
@@ -407,6 +408,7 @@ FRAGMENT_SHADER_CODE
#ifdef USE_LIGHTING
vec2 light_vec = transformed_light_uv;
+ vec2 shadow_vec = transformed_light_uv;
if (normal_used) {
normal.xy = mat2(local_rot.xy, local_rot.zw) * normal.xy;
@@ -434,6 +436,7 @@ FRAGMENT_SHADER_CODE
real_light_color,
light_uv,
real_light_shadow_color,
+ shadow_vec,
normal,
uv,
#if defined(SCREEN_UV_USED)
@@ -452,11 +455,18 @@ FRAGMENT_SHADER_CODE
color *= light;
#ifdef USE_SHADOWS
- // Reset light_vec to compute shadows, the shadow map is created from the light origin, so it only
- // makes sense to compute shadows from there.
- light_vec = light_uv_interp.zw;
- float angle_to_light = -atan(light_vec.x, light_vec.y);
+#ifdef SHADOW_VEC_USED
+ mat3 inverse_light_matrix = mat3(light_matrix);
+ inverse_light_matrix[0] = normalize(inverse_light_matrix[0]);
+ inverse_light_matrix[1] = normalize(inverse_light_matrix[1]);
+ inverse_light_matrix[2] = normalize(inverse_light_matrix[2]);
+ shadow_vec = (inverse_light_matrix * vec3(shadow_vec, 0.0)).xy;
+#else
+ shadow_vec = light_uv_interp.zw;
+#endif
+
+ float angle_to_light = -atan(shadow_vec.x, shadow_vec.y);
float PI = 3.14159265358979323846264;
/*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
float ang*/
@@ -467,18 +477,18 @@ FRAGMENT_SHADER_CODE
vec2 point;
float sh;
if (abs_angle < 45.0 * PI / 180.0) {
- point = light_vec;
+ point = shadow_vec;
sh = 0.0 + (1.0 / 8.0);
} else if (abs_angle > 135.0 * PI / 180.0) {
- point = -light_vec;
+ point = -shadow_vec;
sh = 0.5 + (1.0 / 8.0);
} else if (angle_to_light > 0.0) {
- point = vec2(light_vec.y, -light_vec.x);
+ point = vec2(shadow_vec.y, -shadow_vec.x);
sh = 0.25 + (1.0 / 8.0);
} else {
- point = vec2(-light_vec.y, light_vec.x);
+ point = vec2(-shadow_vec.y, shadow_vec.x);
sh = 0.75 + (1.0 / 8.0);
}
diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl
index 195db7c45f..aa967115da 100644
--- a/drivers/gles2/shaders/copy.glsl
+++ b/drivers/gles2/shaders/copy.glsl
@@ -144,11 +144,11 @@ void main() {
#elif defined(USE_ASYM_PANO)
// When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result.
- // Note that we're ignoring the x-offset for IPD, with Z sufficiently in the distance it becomes neglectible, as a result we could probably just set cube_normal.z to -1.
+ // Asymmetrical projection means the center of projection is no longer in the center of the screen but shifted.
// The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image.
vec3 cube_normal;
- cube_normal.z = -1000000.0;
+ cube_normal.z = -1.0;
cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y;
cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a;
cube_normal = mat3(sky_transform) * mat3(pano_transform) * cube_normal;
diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl
index 8a9387f0b3..51447dc00f 100644
--- a/drivers/gles2/shaders/scene.glsl
+++ b/drivers/gles2/shaders/scene.glsl
@@ -61,9 +61,6 @@ uniform ivec2 skeleton_texture_size;
#endif
-uniform highp mat4 skeleton_transform;
-uniform highp mat4 skeleton_transform_inverse;
-uniform bool skeleton_in_world_coords;
#endif
@@ -410,12 +407,9 @@ void main() {
#endif
- if (skeleton_in_world_coords) {
- bone_transform = skeleton_transform * (bone_transform * skeleton_transform_inverse);
- world_matrix = bone_transform * world_matrix;
- } else {
- world_matrix = world_matrix * bone_transform;
- }
+
+ world_matrix = world_matrix * bone_transform;
+
#endif
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 1472954ebc..1cab3d89aa 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -2260,11 +2260,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
_set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, e->sort_key & RenderList::SORT_KEY_CULL_DISABLED_FLAG, p_reverse_cull);
- if (skeleton) {
- state.scene_shader.set_uniform(SceneShaderGLES3::SKELETON_TRANSFORM, skeleton->world_transform);
- state.scene_shader.set_uniform(SceneShaderGLES3::SKELETON_IN_WORLD_COORDS, skeleton->use_world_transform);
- }
-
state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform);
_render_geometry(e);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 5f4acbc2de..a29831e3f5 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -2955,7 +2955,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
case ShaderLanguage::TYPE_BVEC3:
case ShaderLanguage::TYPE_IVEC3:
case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_VEC3:
+ case ShaderLanguage::TYPE_VEC3: {
+ zeromem(data, 12);
+ } break;
case ShaderLanguage::TYPE_BVEC4:
case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC4:
@@ -5160,20 +5162,6 @@ void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, cons
skeleton->base_transform_2d = p_base_transform;
}
-void RasterizerStorageGLES3::skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) {
-
- Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
-
- ERR_FAIL_COND(skeleton->use_2d);
-
- skeleton->world_transform = p_world_transform;
- skeleton->use_world_transform = p_enable;
-
- if (!skeleton->update_list.in_list()) {
- skeleton_update_list.add(&skeleton->update_list);
- }
-}
-
void RasterizerStorageGLES3::update_dirty_skeletons() {
glActiveTexture(GL_TEXTURE0);
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 0a7e47e304..84632308b4 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -892,15 +892,12 @@ public:
SelfList<Skeleton> update_list;
Set<RasterizerScene::InstanceBase *> instances; //instances using skeleton
Transform2D base_transform_2d;
- bool use_world_transform;
- Transform world_transform;
Skeleton() :
use_2d(false),
size(0),
texture(0),
- update_list(this),
- use_world_transform(false) {
+ update_list(this) {
}
};
@@ -918,7 +915,6 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
- virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform);
/* Light API */
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 0121d88f4d..7499962da3 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -467,6 +467,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
vcode += _prestr(E->get().precision);
vcode += _typestr(E->get().type);
vcode += " " + _mkid(E->key());
+ if (E->get().array_size > 0) {
+ vcode += "[";
+ vcode += itos(E->get().array_size);
+ vcode += "]";
+ }
vcode += ";\n";
r_gen_code.vertex_global += interp_mode + "out " + vcode;
r_gen_code.fragment_global += interp_mode + "in " + vcode;
@@ -936,6 +941,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv";
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light";
actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color";
+ actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
@@ -944,6 +950,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
+ actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n";
actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
/** SPATIAL SHADER **/
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 10c8764b8e..e83f53d648 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -345,6 +345,7 @@ void light_compute(
inout vec4 light_color,
vec2 light_uv,
inout vec4 shadow_color,
+ inout vec2 shadow_vec,
vec3 normal,
vec2 uv,
#if defined(SCREEN_UV_USED)
@@ -512,6 +513,7 @@ FRAGMENT_SHADER_CODE
#ifdef USE_LIGHTING
vec2 light_vec = transformed_light_uv;
+ vec2 shadow_vec = transformed_light_uv;
if (normal_used) {
normal.xy = mat2(local_rot.xy, local_rot.zw) * normal.xy;
@@ -539,6 +541,7 @@ FRAGMENT_SHADER_CODE
real_light_color,
light_uv,
real_light_shadow_color,
+ shadow_vec,
normal,
uv,
#if defined(SCREEN_UV_USED)
@@ -557,11 +560,16 @@ FRAGMENT_SHADER_CODE
color *= light;
#ifdef USE_SHADOWS
- // Reset light_vec to compute shadows, the shadow map is created from the light origin, so it only
- // makes sense to compute shadows from there.
- light_vec = light_uv_interp.zw;
-
- float angle_to_light = -atan(light_vec.x, light_vec.y);
+#ifdef SHADOW_VEC_USED
+ mat3 inverse_light_matrix = mat3(light_matrix);
+ inverse_light_matrix[0] = normalize(inverse_light_matrix[0]);
+ inverse_light_matrix[1] = normalize(inverse_light_matrix[1]);
+ inverse_light_matrix[2] = normalize(inverse_light_matrix[2]);
+ shadow_vec = (mat3(inverse_light_matrix) * vec3(shadow_vec, 0.0)).xy;
+#else
+ shadow_vec = light_uv_interp.zw;
+#endif
+ float angle_to_light = -atan(shadow_vec.x, shadow_vec.y);
float PI = 3.14159265358979323846264;
/*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays
float ang*/
@@ -572,18 +580,18 @@ FRAGMENT_SHADER_CODE
vec2 point;
float sh;
if (abs_angle < 45.0 * PI / 180.0) {
- point = light_vec;
+ point = shadow_vec;
sh = 0.0 + (1.0 / 8.0);
} else if (abs_angle > 135.0 * PI / 180.0) {
- point = -light_vec;
+ point = -shadow_vec;
sh = 0.5 + (1.0 / 8.0);
} else if (angle_to_light > 0.0) {
- point = vec2(light_vec.y, -light_vec.x);
+ point = vec2(shadow_vec.y, -shadow_vec.x);
sh = 0.25 + (1.0 / 8.0);
} else {
- point = vec2(-light_vec.y, light_vec.x);
+ point = vec2(-shadow_vec.y, shadow_vec.x);
sh = 0.75 + (1.0 / 8.0);
}
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index f08d3f4d23..20e0c282e3 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -302,8 +302,6 @@ out highp float dp_clip;
#ifdef USE_SKELETON
uniform highp sampler2D skeleton_texture; // texunit:-1
-uniform highp mat4 skeleton_transform;
-uniform bool skeleton_in_world_coords;
#endif
out highp vec4 position_interp;
@@ -432,14 +430,8 @@ void main() {
vec4(0.0, 0.0, 0.0, 1.0)) *
bone_weights.w;
- if (skeleton_in_world_coords) {
- highp mat4 bone_matrix = skeleton_transform * (transpose(m) * inverse(skeleton_transform));
- world_matrix = bone_matrix * world_matrix;
-
- } else {
+ world_matrix = world_matrix * transpose(m);
- world_matrix = world_matrix * transpose(m);
- }
}
#endif
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 6728f60e06..9194da654c 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -929,13 +929,6 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, 1);
}
- // 6-(undo) reinsert overlapped keys
- for (List<AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
-
- AnimMoveRestore &amr = E->get();
- undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, 1);
- }
-
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index a163490cfb..285cea7d0a 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -2466,6 +2466,7 @@ void AnimationTrackEdit::update_play_position() {
void AnimationTrackEdit::set_root(Node *p_root) {
root = p_root;
}
+
void AnimationTrackEdit::_zoom_changed() {
update();
play_position->update();
@@ -3305,6 +3306,7 @@ Ref<Animation> AnimationTrackEditor::get_current_animation() const {
return animation;
}
+
void AnimationTrackEditor::_root_removed(Node *p_root) {
root = NULL;
}
@@ -3400,15 +3402,14 @@ void AnimationTrackEditor::_track_remove_request(int p_track) {
int idx = p_track;
if (idx >= 0 && idx < animation->get_track_count()) {
- selection.clear();
- _clear_key_edit();
- //all will be updated after remove anyway, and triggering update here raises error on tracks already removed
undo_redo->create_action(TTR("Remove Anim Track"));
+ undo_redo->add_do_method(this, "_clear_selection", false);
undo_redo->add_do_method(animation.ptr(), "remove_track", idx);
undo_redo->add_undo_method(animation.ptr(), "add_track", animation->track_get_type(idx), idx);
undo_redo->add_undo_method(animation.ptr(), "track_set_path", idx, animation->track_get_path(idx));
- //todo interpolation
+
+ // TODO interpolation.
for (int i = 0; i < animation->track_get_key_count(idx); i++) {
Variant v = animation->track_get_key_value(idx, i);
@@ -3491,7 +3492,7 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
case Variant::QUAT:
case Variant::PLANE:
case Variant::COLOR: {
- //good
+ // Valid.
} break;
default: {
all_bezier = false;
@@ -3954,7 +3955,9 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
bool created = false;
if (p_id.track_idx < 0) {
- if (p_create_beziers && (p_id.value.get_type() == Variant::VECTOR2 ||
+ if (p_create_beziers && (p_id.value.get_type() == Variant::INT ||
+ p_id.value.get_type() == Variant::REAL ||
+ p_id.value.get_type() == Variant::VECTOR2 ||
p_id.value.get_type() == Variant::VECTOR3 ||
p_id.value.get_type() == Variant::QUAT ||
p_id.value.get_type() == Variant::COLOR ||
@@ -3977,10 +3980,10 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
if (p_id.type == Animation::TYPE_VALUE || p_id.type == Animation::TYPE_BEZIER) {
- //wants a new tack
+ // Wants a new track.
{
- //hack
+ // Hack.
NodePath np;
animation->add_track(p_id.type);
animation->track_set_path(animation->get_track_count() - 1, p_id.path);
@@ -4034,7 +4037,7 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
Dictionary d;
d["location"] = tr.origin;
d["scale"] = tr.basis.get_scale();
- d["rotation"] = Quat(tr.basis); //.orthonormalized();
+ d["rotation"] = Quat(tr.basis);
value = d;
} break;
case Animation::TYPE_BEZIER: {
@@ -4059,7 +4062,8 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
if (created) {
- //just remove the track
+ // Just remove the track.
+ undo_redo->add_undo_method(this, "_clear_selection", false);
undo_redo->add_undo_method(animation.ptr(), "remove_track", p_last_track);
p_last_track++;
} else {
@@ -4079,6 +4083,8 @@ int AnimationTrackEditor::_confirm_insert(InsertData p_id, int p_last_track, boo
}
void AnimationTrackEditor::show_select_node_warning(bool p_show) {
+
+ info_message->set_visible(p_show);
}
bool AnimationTrackEditor::is_key_selected(int p_track, int p_key) const {
@@ -4661,6 +4667,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
undo_redo->create_action(TTR("Add Track Key"));
undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_track, p_ofs, value);
+ undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", p_track, p_ofs);
undo_redo->commit_action();
@@ -4868,11 +4875,16 @@ void AnimationTrackEditor::_clear_key_edit() {
}
}
-void AnimationTrackEditor::_clear_selection() {
+void AnimationTrackEditor::_clear_selection(bool p_update) {
+
selection.clear();
- for (int i = 0; i < track_edits.size(); i++) {
- track_edits[i]->update();
+
+ if (p_update) {
+ for (int i = 0; i < track_edits.size(); i++) {
+ track_edits[i]->update();
+ }
}
+
_clear_key_edit();
}
@@ -5543,7 +5555,6 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
undo_redo->commit_action();
- //selection.clear();
_update_key_edit();
}
} break;
@@ -5794,6 +5805,14 @@ AnimationTrackEditor::AnimationTrackEditor() {
timeline_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
timeline_vbox->add_constant_override("separation", 0);
+ info_message = memnew(Label);
+ info_message->set_text(TTR("Select an AnimationPlayer node to create and edit animations."));
+ info_message->set_valign(Label::VALIGN_CENTER);
+ info_message->set_align(Label::ALIGN_CENTER);
+ info_message->set_autowrap(true);
+ info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ main_panel->add_child(info_message);
+
timeline = memnew(AnimationTimelineEdit);
timeline->set_undo_redo(undo_redo);
timeline_vbox->add_child(timeline);
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 96fd10effd..830d5b52d3 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -304,6 +304,8 @@ class AnimationTrackEditor : public VBoxContainer {
VBoxContainer *track_vbox;
AnimationBezierTrackEdit *bezier_edit;
+ Label *info_message;
+
AnimationTimelineEdit *timeline;
HSlider *zoom;
EditorSpinSlider *step;
@@ -385,7 +387,7 @@ class AnimationTrackEditor : public VBoxContainer {
void _insert_key_from_track(float p_ofs, int p_track);
void _add_method_key(const String &p_method);
- void _clear_selection();
+ void _clear_selection(bool p_update = false);
void _clear_selection_for_anim(const Ref<Animation> &p_anim);
void _select_at_anim(const Ref<Animation> &p_anim, int p_track, float p_pos);
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
index 1bb49a4167..e38171eef9 100644
--- a/editor/collada/collada.cpp
+++ b/editor/collada/collada.cpp
@@ -616,7 +616,7 @@ void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &
if (colorarr.size() >= 3) {
- // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
+ // alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity
Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
if (what == "diffuse")
effect.diffuse.color = color;
@@ -854,7 +854,7 @@ void Collada::_parse_light(XMLParser &parser) {
COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
if (colorarr.size() >= 4) {
- // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
+ // alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity
Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
light.color = color;
}
@@ -2297,7 +2297,7 @@ bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) {
//replace parent by this...
Node *parent = node->parent;
- //i wonder if this is allright.. i think it is since created skeleton (first joint) is already animated by bone..
+ //i wonder if this is alright.. i think it is since created skeleton (first joint) is already animated by bone..
node->id = parent->id;
node->name = parent->name;
node->xform_list = parent->xform_list;
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index c5b81c4685..cfc2ec11cf 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -529,7 +529,7 @@ void ConnectionsDock::_make_or_edit_connection() {
// Pick up args here before "it" is deleted by update_tree.
script_function_args = it->get_metadata(0).operator Dictionary()["args"];
for (int i = 0; i < cToMake.binds.size(); i++) {
- script_function_args.append("extra_arg_" + itos(i));
+ script_function_args.append("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cToMake.binds[i].get_type()));
}
}
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 2180742bbb..05b5fa7905 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -378,6 +378,7 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) {
void EditorAudioBus::_show_value(float slider_value) {
String text = vformat("%10.1f dB", _normalized_volume_to_scaled_db(slider_value));
+ slider->set_tooltip(text);
audio_value_preview_label->set_text(text);
Vector2 slider_size = slider->get_size();
Vector2 slider_position = slider->get_global_position();
@@ -773,7 +774,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
is_master = p_is_master;
hovering_drop = false;
- set_tooltip(TTR("Audio Bus, Drag and Drop to rearrange."));
+ set_tooltip(TTR("Drag & drop to rearrange."));
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
@@ -1439,7 +1440,7 @@ Size2 EditorAudioMeterNotches::get_minimum_size() const {
float width = 0;
float height = top_padding + btm_padding;
- for (uint8_t i = 0; i < notches.size(); i++) {
+ for (int i = 0; i < notches.size(); i++) {
if (notches[i].render_db_value) {
width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB").x);
height += font_height;
@@ -1473,7 +1474,7 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
Ref<Font> font = get_font("font", "Label");
float font_height = font->get_height();
- for (uint8_t i = 0; i < notches.size(); i++) {
+ for (int i = 0; i < notches.size(); i++) {
AudioNotch n = notches[i];
draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
Vector2(line_length, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding),
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index e6df00b48c..24ed0ecfd0 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -30,6 +30,7 @@
#include "editor_help.h"
+#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "doc_data_compressed.gen.h"
#include "editor/plugins/script_editor_plugin.h"
@@ -1807,5 +1808,9 @@ void FindBar::_search_text_changed(const String &p_text) {
void FindBar::_search_text_entered(const String &p_text) {
- search_next();
+ if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ search_prev();
+ } else {
+ search_next();
+ }
}
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index af79c21f85..27e61362ed 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -338,10 +338,15 @@ bool EditorHelpSearch::Runner::_phase_match_classes() {
if (search_flags & SEARCH_METHODS)
for (int i = 0; i < class_doc.methods.size(); i++) {
String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower();
- if (method_name.find(term) > -1 ||
- (term.begins_with(".") && method_name.begins_with(term.right(1))) ||
- (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) ||
- (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges()))
+ String aux_term = (search_flags & SEARCH_CASE_SENSITIVE) ? term : term.to_lower();
+
+ if (aux_term.begins_with("."))
+ aux_term = aux_term.right(1);
+
+ if (aux_term.ends_with("("))
+ aux_term = aux_term.left(aux_term.length() - 1).strip_edges();
+
+ if (aux_term.is_subsequence_of(method_name))
match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i]));
}
if (search_flags & SEARCH_SIGNALS)
@@ -431,9 +436,9 @@ bool EditorHelpSearch::Runner::_phase_select_match() {
bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const {
if (search_flags & SEARCH_CASE_SENSITIVE)
- return p_string.find(p_term) > -1;
+ return p_term.is_subsequence_of(p_string);
else
- return p_string.findn(p_term) > -1;
+ return p_term.is_subsequence_ofi(p_string);
}
void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_text) {
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index a76d34e122..8d5858a10d 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -1046,9 +1046,9 @@ void EditorInspectorSection::_notification(int p_what) {
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
- arrow = get_icon("arrow_up", "Tree");
- } else {
arrow = get_icon("arrow", "Tree");
+ } else {
+ arrow = get_icon("arrow_collapsed", "Tree");
}
}
@@ -1087,9 +1087,9 @@ void EditorInspectorSection::_notification(int p_what) {
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
- arrow = get_icon("arrow_up", "Tree");
- } else {
arrow = get_icon("arrow", "Tree");
+ } else {
+ arrow = get_icon("arrow_collapsed", "Tree");
}
}
@@ -1103,13 +1103,12 @@ void EditorInspectorSection::_notification(int p_what) {
draw_rect(Rect2(Vector2(), Vector2(get_size().width, h)), bg_color);
- int hs = get_constant("hseparation", "Tree");
-
+ const int arrow_margin = 3;
Color color = get_color("font_color", "Tree");
- draw_string(font, Point2(hs, font->get_ascent() + (h - font->get_height()) / 2).floor(), label, color, get_size().width);
+ 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()) {
- draw_texture(arrow, Point2(get_size().width - arrow->get_width(), (h - arrow->get_height()) / 2).floor());
+ draw_texture(arrow, Point2(Math::round(arrow_margin * EDSCALE), (h - arrow->get_height()) / 2).floor());
}
}
}
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index b5cdc76115..5474f86c74 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -113,6 +113,10 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) {
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));
+ } break;
}
log->add_text(p_msg);
@@ -128,7 +132,7 @@ void EditorLog::set_tool_button(ToolButton *p_tool_button) {
void EditorLog::_undo_redo_cbk(void *p_self, const String &p_name) {
EditorLog *self = (EditorLog *)p_self;
- self->add_message(p_name);
+ self->add_message(p_name, EditorLog::MSG_TYPE_EDITOR);
}
void EditorLog::_bind_methods() {
diff --git a/editor/editor_log.h b/editor/editor_log.h
index bb56bd34fe..10561b9c83 100644
--- a/editor/editor_log.h
+++ b/editor/editor_log.h
@@ -74,7 +74,8 @@ public:
enum MessageType {
MSG_TYPE_STD,
MSG_TYPE_ERROR,
- MSG_TYPE_WARNING
+ MSG_TYPE_WARNING,
+ MSG_TYPE_EDITOR
};
void add_message(const String &p_msg, MessageType p_type = MSG_TYPE_STD);
diff --git a/editor/editor_network_profiler.cpp b/editor/editor_network_profiler.cpp
index b90fe96cee..8482c4e38a 100644
--- a/editor/editor_network_profiler.cpp
+++ b/editor/editor_network_profiler.cpp
@@ -43,9 +43,15 @@ void EditorNetworkProfiler::_bind_methods() {
void EditorNetworkProfiler::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
+ 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"));
+
+ // 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));
}
}
@@ -113,6 +119,14 @@ void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) {
incoming_bandwidth_text->set_text(vformat(TTR("%s/s"), String::humanize_size(p_incoming)));
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(
+ "font_color_uneditable",
+ get_color("font_color", "Editor") * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5));
+ outgoing_bandwidth_text->add_color_override(
+ "font_color_uneditable",
+ get_color("font_color", "Editor") * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5));
}
bool EditorNetworkProfiler::is_profiling() {
@@ -139,27 +153,32 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
hb->add_spacer();
Label *lb = memnew(Label);
- lb->set_text("Down ");
+ lb->set_text(TTR("Down"));
hb->add_child(lb);
incoming_bandwidth_text = memnew(LineEdit);
incoming_bandwidth_text->set_editable(false);
- incoming_bandwidth_text->set_custom_minimum_size(Size2(100, 0));
+ incoming_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE);
incoming_bandwidth_text->set_align(LineEdit::Align::ALIGN_RIGHT);
- incoming_bandwidth_text->set_text("0.0 B/s");
hb->add_child(incoming_bandwidth_text);
+ Control *down_up_spacer = memnew(Control);
+ down_up_spacer->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
+ hb->add_child(down_up_spacer);
+
lb = memnew(Label);
- lb->set_text("Up ");
+ lb->set_text(TTR("Up"));
hb->add_child(lb);
outgoing_bandwidth_text = memnew(LineEdit);
outgoing_bandwidth_text->set_editable(false);
- outgoing_bandwidth_text->set_custom_minimum_size(Size2(100, 0));
+ outgoing_bandwidth_text->set_custom_minimum_size(Size2(120, 0) * EDSCALE);
outgoing_bandwidth_text->set_align(LineEdit::Align::ALIGN_RIGHT);
- outgoing_bandwidth_text->set_text("0.0 B/s");
hb->add_child(outgoing_bandwidth_text);
+ // Set initial texts in the incoming/outgoing bandwidth labels
+ set_bandwidth(0, 0);
+
counters_display = memnew(Tree);
counters_display->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
counters_display->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -169,7 +188,7 @@ EditorNetworkProfiler::EditorNetworkProfiler() {
counters_display->set_column_titles_visible(true);
counters_display->set_column_title(0, TTR("Node"));
counters_display->set_column_expand(0, true);
- counters_display->set_column_min_width(0, 60);
+ counters_display->set_column_min_width(0, 60 * EDSCALE);
counters_display->set_column_title(1, TTR("Incoming RPC"));
counters_display->set_column_expand(1, false);
counters_display->set_column_min_width(1, 120 * EDSCALE);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index a1998a1d7c..e1bbe4b923 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2212,27 +2212,27 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case EDIT_UNDO: {
if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
- log->add_message("Can't UNDO while mouse buttons are pressed.");
+ 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();
if (!editor_data.get_undo_redo().undo()) {
- log->add_message("There is nothing to UNDO.");
+ log->add_message("Nothing to undo.", EditorLog::MSG_TYPE_EDITOR);
} else if (action != "") {
- log->add_message("UNDO: " + action);
+ log->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
}
}
} break;
case EDIT_REDO: {
if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
- log->add_message("Can't REDO while mouse buttons are pressed.");
+ log->add_message("Can't redo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR);
} else {
if (!editor_data.get_undo_redo().redo()) {
- log->add_message("There is nothing to REDO.");
+ log->add_message("Nothing to redo.", EditorLog::MSG_TYPE_EDITOR);
} else {
String action = editor_data.get_undo_redo().get_current_action_name();
- log->add_message("REDO: " + action);
+ log->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR);
}
}
} break;
@@ -3133,7 +3133,14 @@ void EditorNode::_clear_undo_history() {
void EditorNode::set_current_scene(int p_idx) {
+ //Save the folding in case the scene gets reloaded.
+ if (editor_data.get_scene_path(p_idx) != "")
+ editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
+
if (editor_data.check_and_update_scene(p_idx)) {
+ if (editor_data.get_scene_path(p_idx) != "")
+ editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
+
call_deferred("_clear_undo_history");
}
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 30fb561fbe..f456cf7233 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -922,16 +922,29 @@ EditorPropertyFloat::EditorPropertyFloat() {
void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) {
- Ref<InputEventMouseButton> mb = p_ev;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
- preset->set_global_position(easing_draw->get_global_transform().xform(mb->get_position()));
- preset->popup();
- }
- if (mb.is_valid() && mb->is_doubleclick() && mb->get_button_index() == BUTTON_LEFT) {
- _setup_spin();
+ const Ref<InputEventMouseButton> mb = p_ev;
+ if (mb.is_valid()) {
+ if (mb->is_doubleclick() && mb->get_button_index() == BUTTON_LEFT) {
+ _setup_spin();
+ }
+
+ if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ preset->set_global_position(easing_draw->get_global_transform().xform(mb->get_position()));
+ preset->popup();
+
+ // Ensure the easing doesn't appear as being dragged
+ dragging = false;
+ easing_draw->update();
+ }
+
+ if (mb->get_button_index() == BUTTON_LEFT) {
+ dragging = mb->is_pressed();
+ // Update to display the correct dragging color
+ easing_draw->update();
+ }
}
- Ref<InputEventMouseMotion> mm = p_ev;
+ const Ref<InputEventMouseMotion> mm = p_ev;
if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) {
@@ -969,13 +982,19 @@ void EditorPropertyEasing::_draw_easing() {
Rect2 r(Point2(), s);
r = r.grow(3);
- int points = 48;
+ const int points = 48;
float prev = 1.0;
- float exp = get_edited_object()->get(get_edited_property());
+ const float exp = get_edited_object()->get(get_edited_property());
- Ref<Font> f = get_font("font", "Label");
- Color color = get_color("font_color", "Label");
+ const Ref<Font> f = get_font("font", "Label");
+ const Color font_color = get_color("font_color", "Label");
+ Color line_color;
+ if (dragging) {
+ line_color = get_color("accent_color", "Editor");
+ } else {
+ line_color = get_color("font_color", "Label") * Color(1, 1, 1, 0.9);
+ }
Vector<Point2> lines;
for (int i = 1; i <= points; i++) {
@@ -983,7 +1002,7 @@ void EditorPropertyEasing::_draw_easing() {
float ifl = i / float(points);
float iflp = (i - 1) / float(points);
- float h = 1.0 - Math::ease(ifl, exp);
+ const float h = 1.0 - Math::ease(ifl, exp);
if (flip) {
ifl = 1.0 - ifl;
@@ -995,8 +1014,8 @@ void EditorPropertyEasing::_draw_easing() {
prev = h;
}
- easing_draw->draw_multiline(lines, color, 1.0, true);
- f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), color);
+ easing_draw->draw_multiline(lines, line_color, 1.0, true);
+ f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), font_color);
}
void EditorPropertyEasing::update_property() {
@@ -1033,6 +1052,9 @@ void EditorPropertyEasing::_spin_value_changed(double p_value) {
void EditorPropertyEasing::_spin_focus_exited() {
spin->hide();
+ // Ensure the easing doesn't appear as being dragged
+ dragging = false;
+ easing_draw->update();
}
void EditorPropertyEasing::setup(bool p_full, bool p_flip) {
@@ -1095,6 +1117,7 @@ EditorPropertyEasing::EditorPropertyEasing() {
spin->hide();
add_child(spin);
+ dragging = false;
flip = false;
full = false;
}
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index adf7779dc4..b8d6aa00c2 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -311,6 +311,7 @@ class EditorPropertyEasing : public EditorProperty {
EditorSpinSlider *spin;
bool setting;
+ bool dragging;
bool full;
bool flip;
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index ff19be8bd5..8abe91bdc1 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -264,7 +264,9 @@ void EditorPropertyArray::update_property() {
edit->set_text(String("(Nil) ") + arrtype);
edit->set_pressed(false);
if (vbox) {
+ set_bottom_editor(NULL);
memdelete(vbox);
+ vbox = NULL;
}
return;
}
@@ -631,7 +633,9 @@ void EditorPropertyDictionary::update_property() {
edit->set_text("Dictionary (Nil)"); //This provides symmetry with the array property.
edit->set_pressed(false);
if (vbox) {
+ set_bottom_editor(NULL);
memdelete(vbox);
+ vbox = NULL;
}
return;
}
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 5c15ebb1eb..77e9220b6d 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -116,7 +116,7 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur
uint64_t modified_time = 0;
if (p_str.begins_with("ID:")) {
- hash = p_str.get_slicec(':', 2).to_int();
+ hash = uint32_t(p_str.get_slicec(':', 2).to_int64());
path = "ID:" + p_str.get_slicec(':', 1);
} else {
modified_time = FileAccess::get_modified_time(path);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index e29e44caa2..42c55681ae 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -685,12 +685,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// Tree
theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
- theme->set_icon("arrow_up", "Tree", theme->get_icon("GuiTreeArrowUp", "EditorIcons"));
theme->set_icon("arrow", "Tree", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
theme->set_icon("arrow_collapsed", "Tree", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
theme->set_icon("updown", "Tree", theme->get_icon("GuiTreeUpdown", "EditorIcons"));
theme->set_icon("select_arrow", "Tree", theme->get_icon("GuiDropdown", "EditorIcons"));
- theme->set_icon("select_option", "Tree", theme->get_icon("GuiTreeOption", "EditorIcons"));
theme->set_stylebox("bg_focus", "Tree", style_focus);
theme->set_stylebox("custom_button", "Tree", make_empty_stylebox());
theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
@@ -704,7 +702,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("drop_position_color", "Tree", accent_color);
theme->set_constant("vseparation", "Tree", (extra_spacing + default_margin_size) * EDSCALE);
theme->set_constant("hseparation", "Tree", (extra_spacing + default_margin_size) * EDSCALE);
- theme->set_constant("guide_width", "Tree", border_width);
theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE);
theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
@@ -717,6 +714,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_tree_btn->set_border_width_all(0);
theme->set_stylebox("button_pressed", "Tree", style_tree_btn);
+ Ref<StyleBoxFlat> style_tree_hover = style_default->duplicate();
+ style_tree_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.4));
+ style_tree_hover->set_border_width_all(0);
+ theme->set_stylebox("hover", "Tree", style_tree_hover);
+
Ref<StyleBoxFlat> style_tree_focus = style_default->duplicate();
style_tree_focus->set_bg_color(highlight_color);
style_tree_focus->set_border_width_all(0);
diff --git a/editor/editor_vcs_interface.cpp b/editor/editor_vcs_interface.cpp
index 8da1777871..4df2a06736 100644
--- a/editor/editor_vcs_interface.cpp
+++ b/editor/editor_vcs_interface.cpp
@@ -78,18 +78,12 @@ Dictionary EditorVCSInterface::_get_modified_files_data() {
}
void EditorVCSInterface::_stage_file(String p_file_path) {
-
- return;
}
void EditorVCSInterface::_unstage_file(String p_file_path) {
-
- return;
}
void EditorVCSInterface::_commit(String p_msg) {
-
- return;
}
Array EditorVCSInterface::_get_file_diff(String p_file_path) {
@@ -134,7 +128,6 @@ void EditorVCSInterface::stage_file(String p_file_path) {
call("_stage_file", p_file_path);
}
- return;
}
void EditorVCSInterface::unstage_file(String p_file_path) {
@@ -143,7 +136,6 @@ void EditorVCSInterface::unstage_file(String p_file_path) {
call("_unstage_file", p_file_path);
}
- return;
}
bool EditorVCSInterface::is_addon_ready() {
@@ -157,7 +149,6 @@ void EditorVCSInterface::commit(String p_msg) {
call("_commit", p_msg);
}
- return;
}
Array EditorVCSInterface::get_file_diff(String p_file_path) {
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 536cfaa1dd..202b554be4 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -562,10 +562,8 @@ bool ExportTemplateManager::can_install_android_template() {
Error ExportTemplateManager::install_android_template() {
- // To support custom Android builds, we install various things to the project's res://android folder.
- // First is the Java source code and buildsystem from android_source.zip.
- // Then we extract the Godot Android libraries from pre-build android_release.apk
- // and android_debug.apk, to place them in the libs folder.
+ // To support custom Android builds, we install the Java source code and buildsystem
+ // from android_source.zip to the project's res://android folder.
DirAccessRef da = DirAccess::open("res://");
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
@@ -661,89 +659,6 @@ Error ExportTemplateManager::install_android_template() {
ProgressDialog::get_singleton()->end_task("uncompress_src");
unzClose(pkg);
- // Extract libs from pre-built APKs.
- err = _extract_libs_from_apk("release");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't extract Android libs from android_release.apk.");
- err = _extract_libs_from_apk("debug");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't extract Android libs from android_debug.apk.");
-
- return OK;
-}
-
-Error ExportTemplateManager::_extract_libs_from_apk(const String &p_target_name) {
-
- const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
- const String &apk_file = templates_path.plus_file("android_" + p_target_name + ".apk");
- ERR_FAIL_COND_V(!FileAccess::exists(apk_file), ERR_CANT_OPEN);
-
- FileAccess *src_f = NULL;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
-
- unzFile pkg = unzOpen2(apk_file.utf8().get_data(), &io);
- ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android APK can't be extracted.");
-
- DirAccessRef da = DirAccess::open("res://");
- ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
-
- // 8 steps because 4 arches, 2 libs per arch.
- ProgressDialog::get_singleton()->add_task("extract_libs_from_apk", TTR("Extracting Android Libraries From APKs"), 8);
-
- int ret = unzGoToFirstFile(pkg);
- Set<String> dirs_tested;
- int idx = 0;
- while (ret == UNZ_OK) {
- // Get file path.
- unz_file_info info;
- char fpath[16384];
- ret = unzGetCurrentFileInfo(pkg, &info, fpath, 16384, NULL, 0, NULL, 0);
-
- String path = fpath;
- String base_dir = path.get_base_dir();
- String file = path.get_file();
-
- if (!base_dir.begins_with("lib") || path.ends_with("/")) {
- ret = unzGoToNextFile(pkg);
- continue;
- }
-
- Vector<uint8_t> data;
- data.resize(info.uncompressed_size);
-
- // Read.
- unzOpenCurrentFile(pkg);
- unzReadCurrentFile(pkg, data.ptrw(), data.size());
- unzCloseCurrentFile(pkg);
-
- // We have a "lib" folder in the APK, but it should be "libs/{release,debug}" in the source dir.
- String target_base_dir = base_dir.replace_first("lib", String("libs").plus_file(p_target_name));
-
- if (!dirs_tested.has(base_dir)) {
- da->make_dir_recursive(String("android/build").plus_file(target_base_dir));
- dirs_tested.insert(base_dir);
- }
-
- String to_write = String("res://android/build").plus_file(target_base_dir.plus_file(path.get_file()));
- FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE);
- if (f) {
- f->store_buffer(data.ptr(), data.size());
- memdelete(f);
-#ifndef WINDOWS_ENABLED
- // We can't retrieve Unix permissions from the APK it seems, so simply set 0755 as should be.
- FileAccess::set_unix_permissions(to_write, 0755);
-#endif
- } else {
- ERR_PRINTS("Can't uncompress file: " + to_write);
- }
-
- ProgressDialog::get_singleton()->task_step("extract_libs_from_apk", path, idx);
-
- idx++;
- ret = unzGoToNextFile(pkg);
- }
-
- ProgressDialog::get_singleton()->end_task("extract_libs_from_apk");
- unzClose(pkg);
-
return OK;
}
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index ecb8e85b21..ad3ab507b3 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -72,8 +72,6 @@ class ExportTemplateManager : public ConfirmationDialog {
virtual void ok_pressed();
bool _install_from_file(const String &p_file, bool p_use_progress = true);
- Error _extract_libs_from_apk(const String &p_target_name);
-
void _http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
void _http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
diff --git a/editor/icons/icon_GUI_tree_option.svg b/editor/icons/icon_GUI_tree_option.svg
deleted file mode 100644
index 4200745a78..0000000000
--- a/editor/icons/icon_GUI_tree_option.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m7.5 1a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5zm0 5a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5zm0 5a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5z" fill="#fff" fill-opacity=".58824" stroke-linejoin="round" stroke-opacity=".39216" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_arrow_down.svg b/editor/icons/icon_arrow_down.svg
new file mode 100644
index 0000000000..49a93e6e28
--- /dev/null
+++ b/editor/icons/icon_arrow_down.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 3.002a1 1 0 0 0 -.69336.29102 1 1 0 0 0 0 1.4141l2.293 2.293h-4.5859c-.55228 0-1 .4477-1 1s.44772 1 1 1h4.5859l-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l4-4a1.0001 1.0001 0 0 0 0-1.4141l-4-4a1 1 0 0 0 -.7207-.29102z" fill="#e0e0e0" fill-opacity=".99608" transform="matrix(0 1 -1 0 16.0021 -.00004)"/></svg> \ No newline at end of file
diff --git a/editor/icons/icon_arrow_up.svg b/editor/icons/icon_arrow_up.svg
index 77a20e8c50..9bf19a6a12 100644
--- a/editor/icons/icon_arrow_up.svg
+++ b/editor/icons/icon_arrow_up.svg
@@ -1,5 +1 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path d="m2.9875 1044.4a1.0001 1.0001 0 0 0 1.7168 0.6972l2.293-2.2929v4.5859a1.0001 1.0001 0 1 0 2 0v-4.5859l2.293 2.2929a1.0001 1.0001 0 1 0 1.4141 -1.414l-3.9141-3.9141a1.0001 1.0001 0 0 0 -1.5859 0 1.0001 1.0001 0 0 0 -0.00391 0.01l-3.9102 3.9102a1.0001 1.0001 0 0 0 -0.30273 0.7168z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-opacity=".99608" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8.00008 1049.4022a1 1 0 0 0 .69336-.291 1 1 0 0 0 0-1.4141l-2.293-2.293h4.5859c.55228 0 1-.4477 1-1s-.44772-1-1-1h-4.5859l2.293-2.293a1 1 0 0 0 0-1.4141 1 1 0 0 0 -1.4141 0l-4 4a1.0001 1.0001 0 0 0 0 1.4141l4 4a1 1 0 0 0 .7207.291z" fill="#e0e0e0" fill-opacity=".99608" transform="matrix(0 1 -1 0 1052.4021 -.00004)"/></svg> \ No newline at end of file
diff --git a/editor/icons/icon_bus_vu_db.svg b/editor/icons/icon_bus_vu_db.svg
deleted file mode 100644
index 236e41e1f5..0000000000
--- a/editor/icons/icon_bus_vu_db.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<svg width="32" height="128" version="1.1" viewBox="0 0 32 128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x1="16" x2="16" y2="128" gradientUnits="userSpaceOnUse">
-<stop stop-color="#ff7a7a" offset="0"/>
-<stop stop-color="#e1dc7a" offset=".5"/>
-<stop stop-color="#66ff9e" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -924.36)">
-<path transform="translate(0 924.36)" d="m1.5 0c-0.831 0-1.5 0.669-1.5 1.5 0 0.831 0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5 0-0.831-0.669-1.5-1.5-1.5h-2zm0 7c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm22.5 3.75c-1.5 0-3 1.3056-3 3.25-0.01912 1.3523 2.0191 1.3523 2 0 0-1.0556 0.5-1.25 1-1.25s1 0.19444 1 1.25c0 0.59157-0.35893 1.156-1.1914 1.8633-0.83248 0.70724-2.0616 1.4518-3.3574 2.3008-0.82974 0.54516-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.01912 1.3523-2.0191 0-2h-1.7852c0.28375-0.20667 0.63106-0.39443 0.88867-0.61328 1.0302-0.87519 1.8965-1.9783 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm-7.0293 0.25195c-0.14519 0.0037-0.28782 0.03907-0.41797 0.10352l-2 1c-1.1924 0.59646-0.29787 2.3855 0.89453 1.7891l0.55273-0.27539v5.3809c-0.01913 1.3523 2.0191 1.3523 2 0v-7c-9.16e-4 -0.56314-0.4664-1.0145-1.0293-0.99805zm-15.471 2.998c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm0 7c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm21.5 3c-0.554 0-1 0.446-1 1v1 2h-0.92969c-0.02343-8.24e-4 -0.046882-8.24e-4 -0.070312 0-1.0702 0-2.0626 0.57318-2.5977 1.5-0.5351 0.92681-0.5351 2.0732 0 3 0.5351 0.92681 1.5275 1.5 2.5977 1.5h2c0.554 0 1-0.446 1-1v-8c0-0.554-0.446-1-1-1zm4 0c-0.554 0-1 0.446-1 1v8c0 0.554 0.446 1 1 1h2c1.0702 0 2.0626-0.57319 2.5977-1.5 0.5351-0.92682 0.5351-2.0732 0-3-0.10504-0.18193-0.23173-0.34698-0.36914-0.5 0.1378-0.15331 0.26385-0.31764 0.36914-0.5 0.5351-0.92682 0.5351-2.0732 0-3-0.5351-0.92682-1.5275-1.5-2.5977-1.5h-2zm-14 1c-1.6447 0-3 1.3553-3 3v3c0 1.6447 1.3553 3 3 3s3-1.3553 3-3v-3c0-1.6447-1.3553-3-3-3zm15 1h1c0.35887 0 0.6858 0.18921 0.86523 0.5 0.17944 0.31079 0.17944 0.68921 0 1-0.17943 0.31079-0.50636 0.5-0.86523 0.5h-0.070312-0.92969v-2zm-15 1c0.5713 0 1 0.4287 1 1v3c0 0.5713-0.4287 1-1 1s-1-0.4287-1-1v-3c0-0.5713 0.4287-1 1-1zm-11.5 1c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm19.5 2h1v2h-0.92969c-0.02343-8.24e-4 -0.046882-8.24e-4 -0.070312 0-0.35887 0-0.6858-0.18921-0.86523-0.5-0.17944-0.31079-0.17944-0.68921 0-1 0.17943-0.31079 0.50636-0.5 0.86523-0.5zm7 0h1c0.35887 0 0.6858 0.18921 0.86523 0.5 0.17944 0.31079 0.17944 0.68921 0 1-0.17943 0.31079-0.50636 0.5-0.86523 0.5h-1v-2zm-26.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm22.5 2.75c-1.5 0-3 1.3056-3 3.25-0.01912 1.3523 2.0191 1.3523 2 0 0-1.0556 0.5-1.25 1-1.25s1 0.19444 1 1.25c0 0.59157-0.35893 1.156-1.1914 1.8633-0.83248 0.70724-2.0616 1.4518-3.3574 2.3008-0.82974 0.54516-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.01913 1.3523-2.0191 0-2h-1.7852c0.28375-0.20667 0.63106-0.39443 0.88867-0.61328 1.0302-0.87519 1.8965-1.9783 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm-7.0293 0.25195c-0.14519 0.0037-0.28782 0.03907-0.41797 0.10352l-2 1c-1.1924 0.59646-0.29787 2.3855 0.89453 1.7891l0.55273-0.27539v5.3809c-0.01913 1.3523 2.0191 1.3523 2 0v-7c-9.16e-4 -0.56314-0.4664-1.0145-1.0293-0.99805zm-15.471 3.998c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 1v2h3v-2h-3zm-7 6c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm15.986 3.75c-1.5 0-3 1.3056-3 3.25-0.01913 1.3523 2.0191 1.3523 2 0 0-1.0556 0.5-1.25 1-1.25s1 0.19444 1 1.25c0 0.59157-0.35893 1.156-1.1914 1.8633s-2.0616 1.4518-3.3574 2.3008c-0.82974 0.54516-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.01913 1.3523-2.0191 0-2h-1.7871c0.2841-0.20689 0.63273-0.39419 0.89062-0.61328 1.0302-0.87519 1.8965-1.9783 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm7.0469 0.23828c-0.36561-0.0093-0.70715 0.18167-0.89062 0.49805l-3 5c-0.39877 0.66633 0.080888 1.5131 0.85742 1.5137h3v1c-0.01912 1.3523 2.0191 1.3523 2 0v-2c-5.5e-5 -0.55226-0.44774-0.99994-1-1h-2.2324l2.0898-3.4844c0.40768-0.65656-0.05163-1.5077-0.82422-1.5273zm-23.533 3.0117c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm-7.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm24.547 4.9961c-0.12355-0.0037-0.24673 0.01547-0.36328 0.05664 0 0-0.98349 0.3331-1.8906 1.2402-0.90714 0.90717-1.793 2.457-1.793 4.707-6.13e-4 0.07218 0.006604 0.14421 0.021484 0.21484 0.11389 1.5445 1.4072 2.7852 2.9785 2.7852 1.645 0 3-1.355 3-3 0-1.645-1.355-3-3-3-0.01533 0-0.029642 0.003706-0.044922 0.003906 0.084-0.10099 0.16695-0.21188 0.25195-0.29688 0.59286-0.59287 1.1094-0.75781 1.1094-0.75781 1.0726-0.33926 0.85487-1.9171-0.26953-1.9531zm-9.0605 0.005859c-1.0407 0.006928-2.0405 0.55674-2.584 1.498a1 1 0 0 0 0.36523 1.3672 1 1 0 0 0 1.3672 -0.36719c0.24596-0.42602 0.74477-0.6077 1.207-0.43945 0.46226 0.16824 0.728 0.62882 0.64258 1.1133-0.085422 0.48445-0.49245 0.82617-0.98438 0.82617a1 1 0 0 0 -1 1 1 1 0 0 0 1 1c0.49193 0 0.89896 0.34368 0.98438 0.82812 0.085422 0.48446-0.18032 0.94508-0.64258 1.1133-0.46226 0.1683-0.96107-0.015436-1.207-0.44141-0.27644-0.47871-0.88884-0.6423-1.3672-0.36523-0.47752 0.27639-0.64095 0.88733-0.36523 1.3652 0.72462 1.2553 2.2612 1.816 3.623 1.3203 1.3618-0.4956 2.1813-1.9126 1.9297-3.3398-0.1003-0.56884-0.37254-1.0676-0.74023-1.4746 0.37098-0.40777 0.63937-0.91234 0.74023-1.4844 0.25166-1.4272-0.56786-2.8442-1.9297-3.3398-0.34046-0.12392-0.69218-0.182-1.0391-0.17969zm-15.486 1.998c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm16 1c0.56413 0 1 0.43587 1 1s-0.43587 1-1 1-1-0.43587-1-1 0.43587-1 1-1zm-23.5 4c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm16.533 3.9883c-0.36561-0.0093-0.70715 0.18167-0.89062 0.49805l-3 5c-0.39877 0.66633 0.080888 1.5131 0.85742 1.5137h3v1c-0.01912 1.3523 2.0191 1.3523 2 0v-2c-5.5e-5 -0.55226-0.44774-0.99994-1-1h-2.2324l2.0898-3.4844c0.40768-0.65656-0.05163-1.5077-0.82422-1.5273zm6.9668 0.011719c-1.645 0-3 1.355-3 3 0 0.769 0.30369 1.4666 0.78711 2-0.48282 0.53332-0.78711 1.2315-0.78711 2 0 1.645 1.355 3 3 3s3-1.355 3-3c0-0.76846-0.30429-1.4667-0.78711-2 0.48342-0.53345 0.78711-1.231 0.78711-2 0-1.645-1.355-3-3-3zm0 2c0.56413 0 1 0.4359 1 1 0 0.5642-0.43587 1-1 1s-1-0.4358-1-1c0-0.5641 0.43587-1 1-1zm-23.5 1c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm16 1c0.56413 0 1 0.4359 1 1 0 0.5642-0.43587 1-1 1s-1-0.4358-1-1c0-0.5641 0.43587-1 1-1zm-23.5 4c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm16.447 3.9824c-0.08995 0.0063-0.17865 0.024647-0.26367 0.054687 0 0-0.98349 0.33509-1.8906 1.2422-0.90714 0.9068-1.793 2.457-1.793 4.707-6.13e-4 0.0722 0.006604 0.14421 0.021484 0.21484 0.11389 1.5445 1.4072 2.7852 2.9785 2.7852 1.645 0 3-1.355 3-3 0-1.6451-1.355-3-3-3-0.01533 0-0.029642 0.003706-0.044922 0.003906 0.084-0.10099 0.16695-0.21187 0.25195-0.29688 0.59286-0.5929 1.1094-0.75781 1.1094-0.75781 1.0726-0.33926 0.85487-1.9171-0.26953-1.9531-0.03318-0.0017-0.066429-0.0017-0.099609 0zm7.0527 0.017578c-1.6447 0-3 1.3553-3 3v3c0 1.6447 1.3553 3 3 3s3-1.3553 3-3v-3c0-1.6447-1.3553-3-3-3zm0 2c0.5713 0 1 0.4287 1 1v3c0 0.5713-0.4287 1-1 1s-1-0.4287-1-1v-3c0-0.5713 0.4287-1 1-1zm-23.5 1c-0.831 0-1.5 0.669-1.5 1.5 0 0.831 0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5 0-0.831-0.669-1.5-1.5-1.5h-2zm15.5 1.9863c0.56413 0 1 0.4358 1 1 0 0.5641-0.43587 1-1 1s-1-0.4359-1-1c0-0.5642 0.43587-1 1-1zm-8 0.013672v2h3v-2h-3zm-7.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5zm22.5 3.75c-1.5 0-3 1.3056-3 3.25-0.01912 1.3523 2.0191 1.3523 2 0 0-1.0555 0.5-1.25 1-1.25s1 0.1945 1 1.25c0 0.5916-0.35893 1.1561-1.1914 1.8633-0.83248 0.7072-2.0616 1.4518-3.3574 2.3008-0.82975 0.54515-0.44398 1.8356 0.54883 1.8359h5c1.3523 0.0191 1.3523-2.0191 0-2h-1.7852c0.28375-0.2066 0.63106-0.39438 0.88867-0.61328 1.0302-0.8751 1.8965-1.9782 1.8965-3.3867 0-1.9444-1.5-3.25-3-3.25zm-10 0.25c-1.3523-0.0191-1.3523 2.0191 0 2h3.3828l-3.2773 6.5527c-0.59596 1.1926 1.1931 2.0871 1.7891 0.89454l4-8c0.33239-0.66495-0.15113-1.4472-0.89453-1.4473h-5zm-12.5 3c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5h2c0.831 0 1.5-0.669 1.5-1.5s-0.669-1.5-1.5-1.5h-2zm7.5 2v2h3v-2h-3zm-7.5 5c-0.831 0-1.5 0.669-1.5 1.5s0.669 1.5 1.5 1.5 1.5-0.669 1.5-1.5-0.669-1.5-1.5-1.5z" fill="url(#a)"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_camera_texture.svg b/editor/icons/icon_camera_texture.svg
new file mode 100644
index 0000000000..5629487451
--- /dev/null
+++ b/editor/icons/icon_camera_texture.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0,1036.4)" d="m2 1c-0.55228 0-1 0.44772-1 1v12c0 0.55228 0.44772 1 1 1h12c0.55228 0 1-0.44772 1-1v-12c0-0.55228-0.44772-1-1-1h-12zm1 2h10v8h-10v-8zm5.8184 1.0039c-0.85534 9.758e-4 -1.5654 0.66069-1.6289 1.5137-0.30036-0.27229-0.69029-0.4234-1.0957-0.42383-0.90315 0-1.6367 0.73162-1.6367 1.6348 9.732e-4 0.69217 0.43922 1.3103 1.0918 1.541v1.1855c0 0.30198 0.24293 0.54492 0.54492 0.54492h3.2695c0.30199 0 0.54492-0.24294 0.54492-0.54492v-0.54492l1.6367 1.0898v-3.2715l-1.6367 1.0918v-0.96484c0.34606-0.30952 0.54406-0.75251 0.54492-1.2168 0-0.90315-0.73162-1.6348-1.6348-1.6348z" fill="#e0e0e0" fill-opacity=".99608"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_clipped_camera.svg b/editor/icons/icon_clipped_camera.svg
new file mode 100644
index 0000000000..dd26abc638
--- /dev/null
+++ b/editor/icons/icon_clipped_camera.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m6.5 12v4h3v-1h-2v-3zm-1 0h-2c-0.5 0-1 0.5-1 1v2c-0.01829 0.53653 0.5 1 1 1h2v-1h-2v-2h2zm4-12c-1.5691 0.0017903-2.8718 1.2125-2.9883 2.7773-0.55103-0.49952-1.268-0.77655-2.0117-0.77734-1.6569 0-3 1.3431-3 3 0.00179 1.2698 0.80282 2.4009 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 1-0.446 1-1v-1l3 2v-6l-3 2v-1.7695c0.63486-0.56783 0.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm1 12v4h1v-1h1c0.55228 0 1-0.44772 1-1v-1c0-0.55228-0.44775-0.99374-1-1h-1zm1 1h1v1h-1z" fill="#fc9c9c"/>
+</svg>
diff --git a/editor/icons/icon_height_map_shape.svg b/editor/icons/icon_height_map_shape.svg
new file mode 100644
index 0000000000..09d129a273
--- /dev/null
+++ b/editor/icons/icon_height_map_shape.svg
@@ -0,0 +1,12 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+<linearGradient id="a" x1="8" x2="8" y1="8" y2="11" gradientUnits="userSpaceOnUse">
+<stop stop-color="#68b6ff" offset="0"/>
+<stop stop-color="#a2d2ff" offset="1"/>
+</linearGradient>
+</defs>
+<g transform="translate(0,-1)">
+<path transform="translate(0,-1033.4)" d="m1 1044.4 7 3 7-3-7-3z" fill="#a2d2ff" fill-rule="evenodd"/>
+<path d="m3 11c1-1 2-2 2-4s1-3 3-3 3 1 3 3 1 3 2 4z" fill="url(#a)"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_interpolated_camera.svg b/editor/icons/icon_interpolated_camera.svg
index 7a33c64ca2..24b4832105 100644
--- a/editor/icons/icon_interpolated_camera.svg
+++ b/editor/icons/icon_interpolated_camera.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m9 0a3 3 0 0 0 -2.9883 2.7773 3 3 0 0 0 -2.0117 -0.77734 3 3 0 0 0 -3 3 3 3 0 0 0 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 1-0.446 1-1v-1l3 2v-6l-3 2v-1.7695a3 3 0 0 0 1 -2.2305 3 3 0 0 0 -3 -3zm-6 12v4h1v-4h-1zm3 0v4h1v-1h1a1 1 0 0 0 1 -1v-1a1 1 0 0 0 -1 -1h-1-1zm5 0a1 1 0 0 0 -1 1v2a1 1 0 0 0 1 1h1a1 1 0 0 0 1 -1v-2a1 1 0 0 0 -1 -1h-1zm-4 1h1v1h-1v-1zm4 0h1v2h-1v-2z" fill="#fc9c9c"/>
+<path transform="translate(0,1036.4)" d="m9.5 4e-5c-1.5691 0.0017903-2.8718 1.2125-2.9883 2.7773-0.55103-0.49952-1.268-0.77655-2.0117-0.77734-1.6569 0-3 1.3431-3 3 0.00179 1.2698 0.80282 2.4009 2 2.8242v2.1758c0 0.554 0.44599 1 1 1h6c0.55401 0 0.9853-0.4462 1-1v-1l3 2v-6l-3 2v-1.7695c0.63486-0.56783 0.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm-6 12v4h1v-4zm3 0v4h1v-1h1c0.55228 0 1-0.44772 1-1v-1c0-0.55228-0.44824-1.024-1-1h-1zm5 0c-0.55228 0-1 0.44772-1 1v2c0 0.55228 0.44772 1 1 1h1c0.55228 0 1-0.44772 1-1v-2c0-0.55228-0.44772-1-1-1zm-4 1h1v1h-1zm4 0h1v2h-1z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_mesh_texture.svg b/editor/icons/icon_mesh_texture.svg
new file mode 100644
index 0000000000..a877877c36
--- /dev/null
+++ b/editor/icons/icon_mesh_texture.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m3 1c-1.1046 0-2 0.89543-2 2 5.649e-4 0.71397 0.38169 1.3735 1 1.7305v6.541c-0.61771 0.35663-0.99874 1.0152-1 1.7285 0 1.1046 0.89543 2 2 2 0.71397-5.65e-4 1.3735-0.38169 1.7305-1h6.541c0.35663 0.61771 1.0152 0.99874 1.7285 1 1.1046 0 2-0.89543 2-2 1.01e-4 -0.72747-0.39481-1.3976-1.0312-1.75h0.03125v-6.5215c0.61771-0.35663 0.99874-1.0152 1-1.7285 0-1.1046-0.89543-2-2-2-0.71397 5.648e-4 -1.3735 0.38169-1.7305 1h-6.541c-0.35663-0.61771-1.0152-0.99874-1.7285-1zm1.7266 3h0.6875 5.168 0.68945c0.17478 0.30301 0.42598 0.55488 0.72852 0.73047v0.68359 5.1719 0.68555c-0.30301 0.17478-0.55488 0.42598-0.73047 0.72852h-0.68359-5.1719-0.68555c-0.17478-0.30301-0.42598-0.55488-0.72852-0.73047v-0.6875l-0.0039062 0.003907v-5.8574c0.30302-0.17478 0.55488-0.42598 0.73047-0.72852zm4.0859 2.25v0.70117h-0.8125v0.69922h-1.625v0.69922h-0.8125v0.69922h-0.8125v0.70117h1.625 1.625 1.625 1.625v-1.4004h-0.8125v-1.3984h-0.8125v-0.70117h-0.8125z" fill="#e0e0e0" fill-opacity=".99608"/>
+</svg>
diff --git a/editor/icons/icon_rich_text_effect.svg b/editor/icons/icon_rich_text_effect.svg
new file mode 100644
index 0000000000..c2705ad8c4
--- /dev/null
+++ b/editor/icons/icon_rich_text_effect.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g>
+<path d="m1 1v2h7v-2zm9 0v2h5v-2zm-9 4v2h11v-2zm0 4v2h4v-2zm6 0v2h1c-0.044949-0.094701-0.088906-0.20229-0.125-0.3418-0.077717-0.30039-0.10439-0.81722 0.16406-1.293 0.081489-0.1441 0.18202-0.26127 0.28906-0.36523zm-6 4v2h8.2812c-0.066517-0.011548-0.1231-0.014758-0.20117-0.037109-0.30195-0.08645-0.76491-0.33245-1.0352-0.80664-0.23366-0.4121-0.24101-0.84933-0.18945-1.1562z" fill="#e0e0e0"/>
+<path d="m12.216 8.598a0.53334 3.2001 0 0 0-0.50976 2.2754 3.2001 0.53334 30 0 0-2.2656-0.71484 3.2001 0.53334 30 0 0 1.75 1.6016 0.53334 3.2001 60 0 0-1.7461 1.5996 0.53334 3.2001 60 0 0 2.2578-0.71094 0.53334 3.2001 0 0 0 0.51367 2.3496 0.53334 3.2001 0 0 0 0.51367-2.3516 3.2001 0.53334 30 0 0 2.2539 0.71094 3.2001 0.53334 30 0 0-1.7441-1.5977 0.53334 3.2001 60 0 0 1.748-1.5996 0.53334 3.2001 60 0 0-2.2617 0.71484 0.53334 3.2001 0 0 0-0.50977-2.2773z" fill="#cea4f1" stroke-width="1.0667"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_skeleton_i_k.svg b/editor/icons/icon_skeleton_i_k.svg
new file mode 100644
index 0000000000..851023ab4d
--- /dev/null
+++ b/editor/icons/icon_skeleton_i_k.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m6 2a4 4 0 0 0-4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 0.26562v0.001953h4v-0.001953a2 2 0 0 0 1-0.26562 2 2 0 0 0 1-1.7324v-3.5469a4 4 0 0 0 2-3.4531 4 4 0 0 0-4-4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm-4 2h2v1h-2v-1zm-2 2h1v1h1v-1h1 1v1h1v-1h1v0.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-0.86914z" fill="#e0e0e0"/>
+</svg>
diff --git a/editor/icons/icon_soft_body.svg b/editor/icons/icon_soft_body.svg
index 9930026b61..2c907df847 100644
--- a/editor/icons/icon_soft_body.svg
+++ b/editor/icons/icon_soft_body.svg
@@ -1,56 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16"
- height="16"
- version="1.1"
- viewBox="0 0 16 16"
- id="svg2"
- inkscape:version="0.91 r13725"
- sodipodi:docname="icon_soft_body.svg">
- <metadata
- id="metadata14">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs12" />
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="1920"
- inkscape:window-height="1027"
- id="namedview10"
- showgrid="false"
- inkscape:zoom="18.792233"
- inkscape:cx="2.8961304"
- inkscape:cy="4.3816933"
- inkscape:window-x="-8"
- inkscape:window-y="-8"
- inkscape:window-maximized="1"
- inkscape:current-layer="svg2" />
- <path
- style="opacity:1;fill:#fc9c9c;fill-opacity:0.99607843;fill-rule:nonzero;stroke:none;stroke-width:1.42799997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 2.3447105,1.6091897 c -0.011911,1.9816766 -1.4168958,3.9344766 0,5.9495986 1.4168957,2.0151221 0,6.6693597 0,6.6693597 l 10.9510055,0 c 0,0 1.780829,-4.4523824 0,-6.489075 -1.780829,-2.0366925 -0.183458,-4.119112 0,-6.1298833 z m 1.8894067,0.7549031 7.4390658,0 c -0.431995,1.5996085 -1.62289,4.0426807 0,5.3749802 1.622888,1.3322996 0,5.887932 0,5.887932 l -7.4390658,0 c 0,0 1.3903413,-4.3680495 0,-5.9780743 -1.3903412,-1.6100247 -0.3951213,-3.7149271 0,-5.2848379 z"
- id="rect4142"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="czcczcccczcczc" />
-</svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1s-3 5 0 7-1 7-1 7h13s3-6 0-8 1-6 1-6zm2 2h7s-2 3 1 5 0 5 0 5h-7s2-4-1-6 0-4 0-4z" fill="#fc9c9c" fill-opacity=".996078"/></svg> \ No newline at end of file
diff --git a/editor/icons/icon_spring_arm.svg b/editor/icons/icon_spring_arm.svg
new file mode 100644
index 0000000000..0700966369
--- /dev/null
+++ b/editor/icons/icon_spring_arm.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 14 6-6" fill="none" stroke="#fc9c9c" stroke-width="2"/>
+<path d="m2 2 7 7" fill="none" stroke="#fc9c9c" stroke-width="2"/>
+<path d="m10 9h-6" fill="none" stroke="#fc9c9c" stroke-width="2"/>
+<path d="m9 9v-5" fill="none" stroke="#fc9c9c" stroke-width="2"/>
+</svg>
diff --git a/editor/icons/icon_style_box_line.svg b/editor/icons/icon_style_box_line.svg
new file mode 100644
index 0000000000..28f2eec6c0
--- /dev/null
+++ b/editor/icons/icon_style_box_line.svg
@@ -0,0 +1,11 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m13.303 1c-0.4344 0-0.86973 0.16881-1.2012 0.50586l-1.4688 1.4941h4.3418c0.082839-0.52789-0.072596-1.0872-0.47266-1.4941-0.33144-0.33705-0.76482-0.50586-1.1992-0.50586z" fill="#ff7070"/>
+<path transform="translate(0 1036.4)" d="m10.633 3-1.9668 2h4.8008l1.0352-1.0527c0.2628-0.2673 0.41824-0.60049 0.47266-0.94727h-4.3418z" fill="#ffeb70"/>
+<path transform="translate(0,1036.4)" d="m8.666 5-1.9648 2h2.8809c0.25686-0.33847 0.49465-0.66934 0.68555-1 0.33885-0.5859 0.95098-0.96109 1.627-0.99609 0.44399-0.023642 0.86385 0.115 1.2188 0.35547l0.35352-0.35938h-4.8008z" fill="#9dff70"/>
+</g>
+<path d="m1.2617 13c-0.08284 0.52789 0.072596 1.0872 0.47266 1.4941 0.33144 0.33705 0.76484 0.50586 1.1992 0.50586 0.4344 0 0.8697-0.16881 1.2012-0.50586l1.4688-1.4941h-4.3418zm7.9219 0c0.41312 1.1628 1.5119 2 2.8164 2s2.4033-0.83718 2.8164-2h-5.6328z" fill="#ff70ac"/>
+<path d="m2.7695 11-1.0352 1.0527c-0.2628 0.2673-0.41824 0.60049-0.47266 0.94727h4.3418l1.4238-1.4473c0.020288-0.18998 0.04923-0.37542 0.089844-0.55273h-4.3477zm6.4609 0c-0.13656 0.32585-0.23047 0.65576-0.23047 1 0 0.35235 0.072014 0.68593 0.18359 1h5.6328c0.11158-0.31407 0.18359-0.64765 0.18359-1 0-0.34424-0.093909-0.67415-0.23047-1h-5.5391z" fill="#9f70ff"/>
+<path d="m4.7363 9-1.9668 2h4.3477c0.17955-0.78395 0.54577-1.4354 0.9375-2h-3.3184zm5.8281 0c-0.55248 0.69003-1.0583 1.3421-1.334 2h5.5391c-0.2757-0.65786-0.78149-1.31-1.334-2h-2.8711z" fill="#70deff"/>
+<path d="m6.7012 7-1.9648 2h3.3184c0.14116-0.20345 0.28508-0.40233 0.42383-0.58398 0.38601-0.5053 0.7635-0.96796 1.1035-1.416h-2.8809zm5.2988 0c-0.43047 0.7456-0.94456 1.3867-1.4355 2h2.8711c-0.49104-0.6133-1.0051-1.2544-1.4355-2z" fill="#70ffb9"/>
+</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 449124acec..adfdfee603 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -176,7 +176,6 @@ Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) {
Skeleton *sk = memnew(Skeleton);
int bone = 0;
- sk->set_use_bones_in_world_transform(true); // This improves compatibility in Collada
for (int i = 0; i < p_node->children.size(); i++) {
_populate_skeleton(sk, p_node->children[i], bone, -1);
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index 9ea7c86e0c..79658c5a4c 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -31,9 +31,12 @@
#include "editor_scene_importer_gltf.h"
#include "core/crypto/crypto_core.h"
#include "core/io/json.h"
+#include "core/math/disjoint_set.h"
#include "core/math/math_defs.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
+#include "modules/regex/regex.h"
+#include "scene/3d/bone_attachment.h"
#include "scene/3d/camera.h"
#include "scene/3d/mesh_instance.h"
#include "scene/animation/animation_player.h"
@@ -152,14 +155,21 @@ static Transform _arr_to_xform(const Array &p_array) {
return xform;
}
+String EditorSceneImporterGLTF::_sanitize_scene_name(const String &name) {
+ RegEx regex("([^a-zA-Z0-9_ ]+)");
+ String p_name = regex.sub(name, "", true);
+ return p_name;
+}
+
String EditorSceneImporterGLTF::_gen_unique_name(GLTFState &state, const String &p_name) {
- int index = 1;
+ const String s_name = _sanitize_scene_name(p_name);
String name;
+ int index = 1;
while (true) {
+ name = s_name;
- name = p_name;
if (index > 1) {
name += " " + itos(index);
}
@@ -174,20 +184,63 @@ String EditorSceneImporterGLTF::_gen_unique_name(GLTFState &state, const String
return name;
}
+String EditorSceneImporterGLTF::_sanitize_bone_name(const String &name) {
+ String p_name = name.camelcase_to_underscore(true);
+
+ RegEx pattern_del("([^a-zA-Z0-9_ ])+");
+ p_name = pattern_del.sub(p_name, "", true);
+
+ RegEx pattern_nospace(" +");
+ p_name = pattern_nospace.sub(p_name, "_", true);
+
+ RegEx pattern_multiple("_+");
+ p_name = pattern_multiple.sub(p_name, "_", true);
+
+ RegEx pattern_padded("0+(\\d+)");
+ p_name = pattern_padded.sub(p_name, "$1", true);
+
+ return p_name;
+}
+
+String EditorSceneImporterGLTF::_gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name) {
+
+ const String s_name = _sanitize_bone_name(p_name);
+
+ String name;
+ int index = 1;
+ while (true) {
+ name = s_name;
+
+ if (index > 1) {
+ name += "_" + itos(index);
+ }
+ if (!state.skeletons[skel_i].unique_names.has(name)) {
+ break;
+ }
+ index++;
+ }
+
+ state.skeletons.write[skel_i].unique_names.insert(name);
+
+ return name;
+}
+
Error EditorSceneImporterGLTF::_parse_scenes(GLTFState &state) {
ERR_FAIL_COND_V(!state.json.has("scenes"), ERR_FILE_CORRUPT);
- Array scenes = state.json["scenes"];
+ const Array &scenes = state.json["scenes"];
for (int i = 0; i < 1; i++) { //only first scene is imported
- Dictionary s = scenes[i];
+ const Dictionary &s = scenes[i];
ERR_FAIL_COND_V(!s.has("nodes"), ERR_UNAVAILABLE);
- Array nodes = s["nodes"];
+ const Array &nodes = s["nodes"];
for (int j = 0; j < nodes.size(); j++) {
state.root_nodes.push_back(nodes[j]);
}
- if (s.has("name")) {
- state.scene_name = s["name"];
+ if (s.has("name") && s["name"] != "") {
+ state.scene_name = _gen_unique_name(state, s["name"]);
+ } else {
+ state.scene_name = _gen_unique_name(state, "Scene");
}
}
@@ -197,11 +250,11 @@ Error EditorSceneImporterGLTF::_parse_scenes(GLTFState &state) {
Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) {
ERR_FAIL_COND_V(!state.json.has("nodes"), ERR_FILE_CORRUPT);
- Array nodes = state.json["nodes"];
+ const Array &nodes = state.json["nodes"];
for (int i = 0; i < nodes.size(); i++) {
GLTFNode *node = memnew(GLTFNode);
- Dictionary n = nodes[i];
+ const Dictionary &n = nodes[i];
if (n.has("name")) {
node->name = n["name"];
@@ -214,13 +267,6 @@ Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) {
}
if (n.has("skin")) {
node->skin = n["skin"];
- /*
- if (!state.skin_users.has(node->skin)) {
- state.skin_users[node->skin] = Vector<int>();
- }
-
- state.skin_users[node->skin].push_back(i);
- */
}
if (n.has("matrix")) {
node->xform = _arr_to_xform(n["matrix"]);
@@ -242,7 +288,7 @@ Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) {
}
if (n.has("children")) {
- Array children = n["children"];
+ const Array &children = n["children"];
for (int j = 0; j < children.size(); j++) {
node->children.push_back(children[j]);
}
@@ -251,22 +297,46 @@ Error EditorSceneImporterGLTF::_parse_nodes(GLTFState &state) {
state.nodes.push_back(node);
}
- //build the hierarchy
+ // build the hierarchy
+ for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); node_i++) {
- for (int i = 0; i < state.nodes.size(); i++) {
+ for (int j = 0; j < state.nodes[node_i]->children.size(); j++) {
+ GLTFNodeIndex child_i = state.nodes[node_i]->children[j];
- for (int j = 0; j < state.nodes[i]->children.size(); j++) {
- int child = state.nodes[i]->children[j];
- ERR_FAIL_INDEX_V(child, state.nodes.size(), ERR_FILE_CORRUPT);
- ERR_CONTINUE(state.nodes[child]->parent != -1); //node already has a parent, wtf.
+ ERR_FAIL_INDEX_V(child_i, state.nodes.size(), ERR_FILE_CORRUPT);
+ ERR_CONTINUE(state.nodes[child_i]->parent != -1); //node already has a parent, wtf.
- state.nodes[child]->parent = i;
+ state.nodes[child_i]->parent = node_i;
}
}
+ _compute_node_heights(state);
+
return OK;
}
+void EditorSceneImporterGLTF::_compute_node_heights(GLTFState &state) {
+
+ state.root_nodes.clear();
+ for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); ++node_i) {
+ GLTFNode *node = state.nodes[node_i];
+ node->height = 0;
+
+ GLTFNodeIndex current_i = node_i;
+ while (current_i >= 0) {
+ const GLTFNodeIndex parent_i = state.nodes[current_i]->parent;
+ if (parent_i >= 0) {
+ ++node->height;
+ }
+ current_i = parent_i;
+ }
+
+ if (node->height == 0) {
+ state.root_nodes.push_back(node_i);
+ }
+ }
+}
+
static Vector<uint8_t> _parse_base64_uri(const String &uri) {
int start = uri.find(",");
@@ -292,14 +362,14 @@ Error EditorSceneImporterGLTF::_parse_buffers(GLTFState &state, const String &p_
if (!state.json.has("buffers"))
return OK;
- Array buffers = state.json["buffers"];
- for (int i = 0; i < buffers.size(); i++) {
+ const Array &buffers = state.json["buffers"];
+ for (GLTFBufferIndex i = 0; i < buffers.size(); i++) {
if (i == 0 && state.glb_data.size()) {
state.buffers.push_back(state.glb_data);
} else {
- Dictionary buffer = buffers[i];
+ const Dictionary &buffer = buffers[i];
if (buffer.has("uri")) {
Vector<uint8_t> buffer_data;
@@ -331,10 +401,10 @@ Error EditorSceneImporterGLTF::_parse_buffers(GLTFState &state, const String &p_
Error EditorSceneImporterGLTF::_parse_buffer_views(GLTFState &state) {
ERR_FAIL_COND_V(!state.json.has("bufferViews"), ERR_FILE_CORRUPT);
- Array buffers = state.json["bufferViews"];
- for (int i = 0; i < buffers.size(); i++) {
+ const Array &buffers = state.json["bufferViews"];
+ for (GLTFBufferViewIndex i = 0; i < buffers.size(); i++) {
- Dictionary d = buffers[i];
+ const Dictionary &d = buffers[i];
GLTFBufferView buffer_view;
@@ -352,7 +422,7 @@ Error EditorSceneImporterGLTF::_parse_buffer_views(GLTFState &state) {
}
if (d.has("target")) {
- int target = d["target"];
+ const int target = d["target"];
buffer_view.indices = target == ELEMENT_ARRAY_BUFFER;
}
@@ -389,10 +459,10 @@ EditorSceneImporterGLTF::GLTFType EditorSceneImporterGLTF::_get_type_from_str(co
Error EditorSceneImporterGLTF::_parse_accessors(GLTFState &state) {
ERR_FAIL_COND_V(!state.json.has("accessors"), ERR_FILE_CORRUPT);
- Array accessors = state.json["accessors"];
- for (int i = 0; i < accessors.size(); i++) {
+ const Array &accessors = state.json["accessors"];
+ for (GLTFAccessorIndex i = 0; i < accessors.size(); i++) {
- Dictionary d = accessors[i];
+ const Dictionary &d = accessors[i];
GLTFAccessor accessor;
@@ -422,12 +492,12 @@ Error EditorSceneImporterGLTF::_parse_accessors(GLTFState &state) {
if (d.has("sparse")) {
//eeh..
- Dictionary s = d["sparse"];
+ const Dictionary &s = d["sparse"];
ERR_FAIL_COND_V(!d.has("count"), ERR_PARSE_ERROR);
accessor.sparse_count = d["count"];
ERR_FAIL_COND_V(!d.has("indices"), ERR_PARSE_ERROR);
- Dictionary si = d["indices"];
+ const Dictionary &si = d["indices"];
ERR_FAIL_COND_V(!si.has("bufferView"), ERR_PARSE_ERROR);
accessor.sparse_indices_buffer_view = si["bufferView"];
@@ -439,7 +509,7 @@ Error EditorSceneImporterGLTF::_parse_accessors(GLTFState &state) {
}
ERR_FAIL_COND_V(!d.has("values"), ERR_PARSE_ERROR);
- Dictionary sv = d["values"];
+ const Dictionary &sv = d["values"];
ERR_FAIL_COND_V(!sv.has("bufferView"), ERR_PARSE_ERROR);
accessor.sparse_values_buffer_view = sv["bufferView"];
@@ -456,7 +526,7 @@ Error EditorSceneImporterGLTF::_parse_accessors(GLTFState &state) {
return OK;
}
-String EditorSceneImporterGLTF::_get_component_type_name(uint32_t p_component) {
+String EditorSceneImporterGLTF::_get_component_type_name(const uint32_t p_component) {
switch (p_component) {
case COMPONENT_TYPE_BYTE: return "Byte";
@@ -470,7 +540,7 @@ String EditorSceneImporterGLTF::_get_component_type_name(uint32_t p_component) {
return "<Error>";
}
-String EditorSceneImporterGLTF::_get_type_name(GLTFType p_component) {
+String EditorSceneImporterGLTF::_get_type_name(const GLTFType p_component) {
static const char *names[] = {
"float",
@@ -485,7 +555,7 @@ String EditorSceneImporterGLTF::_get_type_name(GLTFType p_component) {
return names[p_component];
}
-Error EditorSceneImporterGLTF::_decode_buffer_view(GLTFState &state, int p_buffer_view, double *dst, int skip_every, int skip_bytes, int element_size, int count, GLTFType type, int component_count, int component_type, int component_size, bool normalized, int byte_offset, bool for_vertex) {
+Error EditorSceneImporterGLTF::_decode_buffer_view(GLTFState &state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex) {
const GLTFBufferView &bv = state.buffer_views[p_buffer_view];
@@ -496,7 +566,7 @@ Error EditorSceneImporterGLTF::_decode_buffer_view(GLTFState &state, int p_buffe
ERR_FAIL_INDEX_V(bv.buffer, state.buffers.size(), ERR_PARSE_ERROR);
- uint32_t offset = bv.byte_offset + byte_offset;
+ const uint32_t offset = bv.byte_offset + byte_offset;
Vector<uint8_t> buffer = state.buffers[bv.buffer]; //copy on write, so no performance hit
const uint8_t *bufptr = buffer.ptr();
@@ -504,7 +574,7 @@ Error EditorSceneImporterGLTF::_decode_buffer_view(GLTFState &state, int p_buffe
print_verbose("glTF: type " + _get_type_name(type) + " component type: " + _get_component_type_name(component_type) + " stride: " + itos(stride) + " amount " + itos(count));
print_verbose("glTF: accessor offset" + itos(byte_offset) + " view offset: " + itos(bv.byte_offset) + " total buffer len: " + itos(buffer.size()) + " view len " + itos(bv.byte_length));
- int buffer_end = (stride * (count - 1)) + element_size;
+ const int buffer_end = (stride * (count - 1)) + element_size;
ERR_FAIL_COND_V(buffer_end > bv.byte_length, ERR_PARSE_ERROR);
ERR_FAIL_COND_V((int)(offset + buffer_end) > buffer.size(), ERR_PARSE_ERROR);
@@ -573,7 +643,7 @@ Error EditorSceneImporterGLTF::_decode_buffer_view(GLTFState &state, int p_buffe
return OK;
}
-int EditorSceneImporterGLTF::_get_component_type_size(int component_type) {
+int EditorSceneImporterGLTF::_get_component_type_size(const int component_type) {
switch (component_type) {
case COMPONENT_TYPE_BYTE: return 1; break;
@@ -589,7 +659,7 @@ int EditorSceneImporterGLTF::_get_component_type_size(int component_type) {
return 0;
}
-Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p_accessor, bool p_for_vertex) {
+Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
//spec, for reference:
//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
@@ -598,12 +668,12 @@ Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p
const GLTFAccessor &a = state.accessors[p_accessor];
- int component_count_for_type[7] = {
+ const int component_count_for_type[7] = {
1, 2, 3, 4, 4, 9, 16
};
- int component_count = component_count_for_type[a.type];
- int component_size = _get_component_type_size(a.component_type);
+ const int component_count = component_count_for_type[a.type];
+ const int component_size = _get_component_type_size(a.component_type);
ERR_FAIL_COND_V(component_size == 0, Vector<double>());
int element_size = component_count * component_size;
@@ -646,7 +716,7 @@ Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p
ERR_FAIL_INDEX_V(a.buffer_view, state.buffer_views.size(), Vector<double>());
- Error err = _decode_buffer_view(state, a.buffer_view, dst, skip_every, skip_bytes, element_size, a.count, a.type, component_count, a.component_type, component_size, a.normalized, a.byte_offset, p_for_vertex);
+ const Error err = _decode_buffer_view(state, dst, a.buffer_view, skip_every, skip_bytes, element_size, a.count, a.type, component_count, a.component_type, component_size, a.normalized, a.byte_offset, p_for_vertex);
if (err != OK)
return Vector<double>();
@@ -661,20 +731,20 @@ Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p
// I could not find any file using this, so this code is so far untested
Vector<double> indices;
indices.resize(a.sparse_count);
- int indices_component_size = _get_component_type_size(a.sparse_indices_component_type);
+ const int indices_component_size = _get_component_type_size(a.sparse_indices_component_type);
- Error err = _decode_buffer_view(state, a.sparse_indices_buffer_view, indices.ptrw(), 0, 0, indices_component_size, a.sparse_count, TYPE_SCALAR, 1, a.sparse_indices_component_type, indices_component_size, false, a.sparse_indices_byte_offset, false);
+ Error err = _decode_buffer_view(state, indices.ptrw(), a.sparse_indices_buffer_view, 0, 0, indices_component_size, a.sparse_count, TYPE_SCALAR, 1, a.sparse_indices_component_type, indices_component_size, false, a.sparse_indices_byte_offset, false);
if (err != OK)
return Vector<double>();
Vector<double> data;
data.resize(component_count * a.sparse_count);
- err = _decode_buffer_view(state, a.sparse_values_buffer_view, data.ptrw(), skip_every, skip_bytes, element_size, a.sparse_count, a.type, component_count, a.component_type, component_size, a.normalized, a.sparse_values_byte_offset, p_for_vertex);
+ err = _decode_buffer_view(state, data.ptrw(), a.sparse_values_buffer_view, skip_every, skip_bytes, element_size, a.sparse_count, a.type, component_count, a.component_type, component_size, a.normalized, a.sparse_values_byte_offset, p_for_vertex);
if (err != OK)
return Vector<double>();
for (int i = 0; i < indices.size(); i++) {
- int write_offset = int(indices[i]) * component_count;
+ const int write_offset = int(indices[i]) * component_count;
for (int j = 0; j < component_count; j++) {
dst[write_offset + j] = data[i * component_count + j];
@@ -685,14 +755,16 @@ Vector<double> EditorSceneImporterGLTF::_decode_accessor(GLTFState &state, int p
return dst_buffer;
}
-PoolVector<int> EditorSceneImporterGLTF::_decode_accessor_as_ints(GLTFState &state, int p_accessor, bool p_for_vertex) {
+PoolVector<int> EditorSceneImporterGLTF::_decode_accessor_as_ints(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
PoolVector<int> ret;
+
if (attribs.size() == 0)
return ret;
+
const double *attribs_ptr = attribs.ptr();
- int ret_size = attribs.size();
+ const int ret_size = attribs.size();
ret.resize(ret_size);
{
PoolVector<int>::Write w = ret.write();
@@ -703,14 +775,16 @@ PoolVector<int> EditorSceneImporterGLTF::_decode_accessor_as_ints(GLTFState &sta
return ret;
}
-PoolVector<float> EditorSceneImporterGLTF::_decode_accessor_as_floats(GLTFState &state, int p_accessor, bool p_for_vertex) {
+PoolVector<float> EditorSceneImporterGLTF::_decode_accessor_as_floats(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
PoolVector<float> ret;
+
if (attribs.size() == 0)
return ret;
+
const double *attribs_ptr = attribs.ptr();
- int ret_size = attribs.size();
+ const int ret_size = attribs.size();
ret.resize(ret_size);
{
PoolVector<float>::Write w = ret.write();
@@ -721,15 +795,17 @@ PoolVector<float> EditorSceneImporterGLTF::_decode_accessor_as_floats(GLTFState
return ret;
}
-PoolVector<Vector2> EditorSceneImporterGLTF::_decode_accessor_as_vec2(GLTFState &state, int p_accessor, bool p_for_vertex) {
+PoolVector<Vector2> EditorSceneImporterGLTF::_decode_accessor_as_vec2(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
PoolVector<Vector2> ret;
+
if (attribs.size() == 0)
return ret;
+
ERR_FAIL_COND_V(attribs.size() % 2 != 0, ret);
const double *attribs_ptr = attribs.ptr();
- int ret_size = attribs.size() / 2;
+ const int ret_size = attribs.size() / 2;
ret.resize(ret_size);
{
PoolVector<Vector2>::Write w = ret.write();
@@ -740,15 +816,17 @@ PoolVector<Vector2> EditorSceneImporterGLTF::_decode_accessor_as_vec2(GLTFState
return ret;
}
-PoolVector<Vector3> EditorSceneImporterGLTF::_decode_accessor_as_vec3(GLTFState &state, int p_accessor, bool p_for_vertex) {
+PoolVector<Vector3> EditorSceneImporterGLTF::_decode_accessor_as_vec3(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
PoolVector<Vector3> ret;
+
if (attribs.size() == 0)
return ret;
+
ERR_FAIL_COND_V(attribs.size() % 3 != 0, ret);
const double *attribs_ptr = attribs.ptr();
- int ret_size = attribs.size() / 3;
+ const int ret_size = attribs.size() / 3;
ret.resize(ret_size);
{
PoolVector<Vector3>::Write w = ret.write();
@@ -758,13 +836,16 @@ PoolVector<Vector3> EditorSceneImporterGLTF::_decode_accessor_as_vec3(GLTFState
}
return ret;
}
-PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState &state, int p_accessor, bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
PoolVector<Color> ret;
+
if (attribs.size() == 0)
return ret;
- int type = state.accessors[p_accessor].type;
+
+ const int type = state.accessors[p_accessor].type;
ERR_FAIL_COND_V(!(type == TYPE_VEC3 || type == TYPE_VEC4), ret);
int components;
if (type == TYPE_VEC3) {
@@ -772,9 +853,10 @@ PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState &
} else { // TYPE_VEC4
components = 4;
}
+
ERR_FAIL_COND_V(attribs.size() % components != 0, ret);
const double *attribs_ptr = attribs.ptr();
- int ret_size = attribs.size() / components;
+ const int ret_size = attribs.size() / components;
ret.resize(ret_size);
{
PoolVector<Color>::Write w = ret.write();
@@ -784,15 +866,17 @@ PoolVector<Color> EditorSceneImporterGLTF::_decode_accessor_as_color(GLTFState &
}
return ret;
}
-Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state, int p_accessor, bool p_for_vertex) {
+Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
Vector<Quat> ret;
+
if (attribs.size() == 0)
return ret;
+
ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret);
const double *attribs_ptr = attribs.ptr();
- int ret_size = attribs.size() / 4;
+ const int ret_size = attribs.size() / 4;
ret.resize(ret_size);
{
for (int i = 0; i < ret_size; i++) {
@@ -801,12 +885,14 @@ Vector<Quat> EditorSceneImporterGLTF::_decode_accessor_as_quat(GLTFState &state,
}
return ret;
}
-Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFState &state, int p_accessor, bool p_for_vertex) {
+Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
Vector<Transform2D> ret;
+
if (attribs.size() == 0)
return ret;
+
ERR_FAIL_COND_V(attribs.size() % 4 != 0, ret);
ret.resize(attribs.size() / 4);
for (int i = 0; i < ret.size(); i++) {
@@ -816,12 +902,14 @@ Vector<Transform2D> EditorSceneImporterGLTF::_decode_accessor_as_xform2d(GLTFSta
return ret;
}
-Vector<Basis> EditorSceneImporterGLTF::_decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex) {
+Vector<Basis> EditorSceneImporterGLTF::_decode_accessor_as_basis(GLTFState &state, const GLTFAccessorIndex p_accessor, bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
Vector<Basis> ret;
+
if (attribs.size() == 0)
return ret;
+
ERR_FAIL_COND_V(attribs.size() % 9 != 0, ret);
ret.resize(attribs.size() / 9);
for (int i = 0; i < ret.size(); i++) {
@@ -831,12 +919,15 @@ Vector<Basis> EditorSceneImporterGLTF::_decode_accessor_as_basis(GLTFState &stat
}
return ret;
}
-Vector<Transform> EditorSceneImporterGLTF::_decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex) {
- Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
+Vector<Transform> EditorSceneImporterGLTF::_decode_accessor_as_xform(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) {
+
+ const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex);
Vector<Transform> ret;
+
if (attribs.size() == 0)
return ret;
+
ERR_FAIL_COND_V(attribs.size() % 16 != 0, ret);
ret.resize(attribs.size() / 16);
for (int i = 0; i < ret.size(); i++) {
@@ -854,7 +945,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
return OK;
Array meshes = state.json["meshes"];
- for (int i = 0; i < meshes.size(); i++) {
+ for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {
print_verbose("glTF: Parsing mesh: " + itos(i));
Dictionary d = meshes[i];
@@ -865,7 +956,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR);
Array primitives = d["primitives"];
- Dictionary extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary();
+ const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary();
for (int j = 0; j < primitives.size(); j++) {
@@ -880,7 +971,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
if (p.has("mode")) {
- int mode = p["mode"];
+ const int mode = p["mode"];
ERR_FAIL_INDEX_V(mode, 7, ERR_FILE_CORRUPT);
static const Mesh::PrimitiveType primitives2[7] = {
Mesh::PRIMITIVE_POINTS,
@@ -899,7 +990,6 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
if (a.has("POSITION")) {
array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true);
}
-
if (a.has("NORMAL")) {
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
}
@@ -924,9 +1014,6 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
int wc = weights.size();
PoolVector<float>::Write w = weights.write();
- //PoolVector<int> v = array[Mesh::ARRAY_BONES];
- //PoolVector<int>::Read r = v.read();
-
for (int k = 0; k < wc; k += 4) {
float total = 0.0;
total += w[k + 0];
@@ -939,36 +1026,34 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
w[k + 2] /= total;
w[k + 3] /= total;
}
-
- //print_verbose(itos(j / 4) + ": " + itos(r[j + 0]) + ":" + rtos(w[j + 0]) + ", " + itos(r[j + 1]) + ":" + rtos(w[j + 1]) + ", " + itos(r[j + 2]) + ":" + rtos(w[j + 2]) + ", " + itos(r[j + 3]) + ":" + rtos(w[j + 3]));
}
}
array[Mesh::ARRAY_WEIGHTS] = weights;
}
if (p.has("indices")) {
-
PoolVector<int> indices = _decode_accessor_as_ints(state, p["indices"], false);
if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
//swap around indices, convert ccw to cw for front face
- int is = indices.size();
- PoolVector<int>::Write w = indices.write();
+ const int is = indices.size();
+ const PoolVector<int>::Write w = indices.write();
for (int k = 0; k < is; k += 3) {
SWAP(w[k + 1], w[k + 2]);
}
}
array[Mesh::ARRAY_INDEX] = indices;
+
} else if (primitive == Mesh::PRIMITIVE_TRIANGLES) {
//generate indices because they need to be swapped for CW/CCW
- PoolVector<Vector3> vertices = array[Mesh::ARRAY_VERTEX];
+ const PoolVector<Vector3> &vertices = array[Mesh::ARRAY_VERTEX];
ERR_FAIL_COND_V(vertices.size() == 0, ERR_PARSE_ERROR);
PoolVector<int> indices;
- int vs = vertices.size();
+ const int vs = vertices.size();
indices.resize(vs);
{
- PoolVector<int>::Write w = indices.write();
+ const PoolVector<int>::Write w = indices.write();
for (int k = 0; k < vs; k += 3) {
w[k] = k;
w[k + 1] = k + 2;
@@ -1002,23 +1087,23 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
//blend shapes
if (p.has("targets")) {
print_verbose("glTF: Mesh has targets");
- Array targets = p["targets"];
+ const Array &targets = p["targets"];
//ideally BLEND_SHAPE_MODE_RELATIVE since gltf2 stores in displacement
//but it could require a larger refactor?
mesh.mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
if (j == 0) {
- Array target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array();
+ const Array &target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array();
for (int k = 0; k < targets.size(); k++) {
- String name = k < target_names.size() ? (String)target_names[k] : String("morph_") + itos(k);
+ const String name = k < target_names.size() ? (String)target_names[k] : String("morph_") + itos(k);
mesh.mesh->add_blend_shape(name);
}
}
for (int k = 0; k < targets.size(); k++) {
- Dictionary t = targets[k];
+ const Dictionary &t = targets[k];
Array array_copy;
array_copy.resize(Mesh::ARRAY_MAX);
@@ -1031,17 +1116,17 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
if (t.has("POSITION")) {
PoolVector<Vector3> varr = _decode_accessor_as_vec3(state, t["POSITION"], true);
- PoolVector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
- int size = src_varr.size();
+ const PoolVector<Vector3> src_varr = array[Mesh::ARRAY_VERTEX];
+ const int size = src_varr.size();
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
{
- int max_idx = varr.size();
+ const int max_idx = varr.size();
varr.resize(size);
- PoolVector<Vector3>::Write w_varr = varr.write();
- PoolVector<Vector3>::Read r_varr = varr.read();
- PoolVector<Vector3>::Read r_src_varr = src_varr.read();
+ const PoolVector<Vector3>::Write w_varr = varr.write();
+ const PoolVector<Vector3>::Read r_varr = varr.read();
+ const PoolVector<Vector3>::Read r_src_varr = src_varr.read();
for (int l = 0; l < size; l++) {
if (l < max_idx) {
w_varr[l] = r_varr[l] + r_src_varr[l];
@@ -1054,16 +1139,16 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
}
if (t.has("NORMAL")) {
PoolVector<Vector3> narr = _decode_accessor_as_vec3(state, t["NORMAL"], true);
- PoolVector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
+ const PoolVector<Vector3> src_narr = array[Mesh::ARRAY_NORMAL];
int size = src_narr.size();
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR);
{
int max_idx = narr.size();
narr.resize(size);
- PoolVector<Vector3>::Write w_narr = narr.write();
- PoolVector<Vector3>::Read r_narr = narr.read();
- PoolVector<Vector3>::Read r_src_narr = src_narr.read();
+ const PoolVector<Vector3>::Write w_narr = narr.write();
+ const PoolVector<Vector3>::Read r_narr = narr.read();
+ const PoolVector<Vector3>::Read r_src_narr = src_narr.read();
for (int l = 0; l < size; l++) {
if (l < max_idx) {
w_narr[l] = r_narr[l] + r_src_narr[l];
@@ -1075,21 +1160,22 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
array_copy[Mesh::ARRAY_NORMAL] = narr;
}
if (t.has("TANGENT")) {
- PoolVector<Vector3> tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true);
- PoolVector<float> tangents_v4;
- PoolVector<float> src_tangents = array[Mesh::ARRAY_TANGENT];
+ const PoolVector<Vector3> tangents_v3 = _decode_accessor_as_vec3(state, t["TANGENT"], true);
+ const PoolVector<float> src_tangents = array[Mesh::ARRAY_TANGENT];
ERR_FAIL_COND_V(src_tangents.size() == 0, ERR_PARSE_ERROR);
+ PoolVector<float> tangents_v4;
+
{
int max_idx = tangents_v3.size();
int size4 = src_tangents.size();
tangents_v4.resize(size4);
- PoolVector<float>::Write w4 = tangents_v4.write();
+ const PoolVector<float>::Write w4 = tangents_v4.write();
- PoolVector<Vector3>::Read r3 = tangents_v3.read();
- PoolVector<float>::Read r4 = src_tangents.read();
+ const PoolVector<Vector3>::Read r3 = tangents_v3.read();
+ const PoolVector<float>::Read r4 = src_tangents.read();
for (int l = 0; l < size4 / 4; l++) {
@@ -1127,16 +1213,16 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
mesh.mesh->add_surface_from_arrays(primitive, array, morphs);
if (p.has("material")) {
- int material = p["material"];
+ const int material = p["material"];
ERR_FAIL_INDEX_V(material, state.materials.size(), ERR_FILE_CORRUPT);
- Ref<Material> mat = state.materials[material];
+ const Ref<Material> &mat = state.materials[material];
mesh.mesh->surface_set_material(mesh.mesh->get_surface_count() - 1, mat);
}
}
if (d.has("weights")) {
- Array weights = d["weights"];
+ const Array &weights = d["weights"];
ERR_FAIL_COND_V(mesh.mesh->get_blend_shape_count() != weights.size(), ERR_PARSE_ERROR);
mesh.blend_weights.resize(weights.size());
for (int j = 0; j < weights.size(); j++) {
@@ -1157,10 +1243,10 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
if (!state.json.has("images"))
return OK;
- Array images = state.json["images"];
+ const Array &images = state.json["images"];
for (int i = 0; i < images.size(); i++) {
- Dictionary d = images[i];
+ const Dictionary &d = images[i];
String mimetype;
if (d.has("mimeType")) {
@@ -1190,13 +1276,13 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
}
if (d.has("bufferView")) {
- int bvi = d["bufferView"];
+ const GLTFBufferViewIndex bvi = d["bufferView"];
ERR_FAIL_INDEX_V(bvi, state.buffer_views.size(), ERR_PARAMETER_RANGE_ERROR);
const GLTFBufferView &bv = state.buffer_views[bvi];
- int bi = bv.buffer;
+ const GLTFBufferIndex bi = bv.buffer;
ERR_FAIL_INDEX_V(bi, state.buffers.size(), ERR_PARAMETER_RANGE_ERROR);
ERR_FAIL_COND_V(bv.byte_offset + bv.byte_length > state.buffers[bi].size(), ERR_FILE_CORRUPT);
@@ -1209,7 +1295,7 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
if (mimetype.findn("png") != -1) {
//is a png
- Ref<Image> img = Image::_png_mem_loader_func(data_ptr, data_size);
+ const Ref<Image> img = Image::_png_mem_loader_func(data_ptr, data_size);
ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT);
@@ -1223,7 +1309,7 @@ Error EditorSceneImporterGLTF::_parse_images(GLTFState &state, const String &p_b
if (mimetype.findn("jpeg") != -1) {
//is a jpg
- Ref<Image> img = Image::_jpg_mem_loader_func(data_ptr, data_size);
+ const Ref<Image> img = Image::_jpg_mem_loader_func(data_ptr, data_size);
ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT);
@@ -1249,10 +1335,10 @@ Error EditorSceneImporterGLTF::_parse_textures(GLTFState &state) {
if (!state.json.has("textures"))
return OK;
- Array textures = state.json["textures"];
- for (int i = 0; i < textures.size(); i++) {
+ const Array &textures = state.json["textures"];
+ for (GLTFTextureIndex i = 0; i < textures.size(); i++) {
- Dictionary d = textures[i];
+ const Dictionary &d = textures[i];
ERR_FAIL_COND_V(!d.has("source"), ERR_PARSE_ERROR);
@@ -1264,9 +1350,9 @@ Error EditorSceneImporterGLTF::_parse_textures(GLTFState &state) {
return OK;
}
-Ref<Texture> EditorSceneImporterGLTF::_get_texture(GLTFState &state, int p_texture) {
+Ref<Texture> EditorSceneImporterGLTF::_get_texture(GLTFState &state, const GLTFTextureIndex p_texture) {
ERR_FAIL_INDEX_V(p_texture, state.textures.size(), Ref<Texture>());
- int image = state.textures[p_texture].src_image;
+ const GLTFImageIndex image = state.textures[p_texture].src_image;
ERR_FAIL_INDEX_V(image, state.images.size(), Ref<Texture>());
@@ -1278,10 +1364,10 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
if (!state.json.has("materials"))
return OK;
- Array materials = state.json["materials"];
- for (int i = 0; i < materials.size(); i++) {
+ const Array &materials = state.json["materials"];
+ for (GLTFMaterialIndex i = 0; i < materials.size(); i++) {
- Dictionary d = materials[i];
+ const Dictionary &d = materials[i];
Ref<SpatialMaterial> material;
material.instance();
@@ -1291,17 +1377,17 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
if (d.has("pbrMetallicRoughness")) {
- Dictionary mr = d["pbrMetallicRoughness"];
+ const Dictionary &mr = d["pbrMetallicRoughness"];
if (mr.has("baseColorFactor")) {
- Array arr = mr["baseColorFactor"];
+ const Array &arr = mr["baseColorFactor"];
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
- Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
material->set_albedo(c);
}
if (mr.has("baseColorTexture")) {
- Dictionary bct = mr["baseColorTexture"];
+ const Dictionary &bct = mr["baseColorTexture"];
if (bct.has("index")) {
material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, _get_texture(state, bct["index"]));
}
@@ -1323,9 +1409,9 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
}
if (mr.has("metallicRoughnessTexture")) {
- Dictionary bct = mr["metallicRoughnessTexture"];
+ const Dictionary &bct = mr["metallicRoughnessTexture"];
if (bct.has("index")) {
- Ref<Texture> t = _get_texture(state, bct["index"]);
+ const Ref<Texture> t = _get_texture(state, bct["index"]);
material->set_texture(SpatialMaterial::TEXTURE_METALLIC, t);
material->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_BLUE);
material->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, t);
@@ -1341,7 +1427,7 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
}
if (d.has("normalTexture")) {
- Dictionary bct = d["normalTexture"];
+ const Dictionary &bct = d["normalTexture"];
if (bct.has("index")) {
material->set_texture(SpatialMaterial::TEXTURE_NORMAL, _get_texture(state, bct["index"]));
material->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true);
@@ -1351,7 +1437,7 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
}
}
if (d.has("occlusionTexture")) {
- Dictionary bct = d["occlusionTexture"];
+ const Dictionary &bct = d["occlusionTexture"];
if (bct.has("index")) {
material->set_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"]));
material->set_ao_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_RED);
@@ -1360,16 +1446,16 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
}
if (d.has("emissiveFactor")) {
- Array arr = d["emissiveFactor"];
+ const Array &arr = d["emissiveFactor"];
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
material->set_feature(SpatialMaterial::FEATURE_EMISSION, true);
material->set_emission(c);
}
if (d.has("emissiveTexture")) {
- Dictionary bct = d["emissiveTexture"];
+ const Dictionary &bct = d["emissiveTexture"];
if (bct.has("index")) {
material->set_texture(SpatialMaterial::TEXTURE_EMISSION, _get_texture(state, bct["index"]));
material->set_feature(SpatialMaterial::FEATURE_EMISSION, true);
@@ -1378,16 +1464,17 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
}
if (d.has("doubleSided")) {
- bool ds = d["doubleSided"];
+ const bool ds = d["doubleSided"];
if (ds) {
material->set_cull_mode(SpatialMaterial::CULL_DISABLED);
}
}
if (d.has("alphaMode")) {
- String am = d["alphaMode"];
+ const String &am = d["alphaMode"];
if (am != "OPAQUE") {
material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ material->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
}
}
@@ -1399,131 +1486,764 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
return OK;
}
+EditorSceneImporterGLTF::GLTFNodeIndex EditorSceneImporterGLTF::_find_highest_node(GLTFState &state, const Vector<GLTFNodeIndex> &subset) {
+ int heighest = -1;
+ GLTFNodeIndex best_node = -1;
+
+ for (int i = 0; i < subset.size(); ++i) {
+ const GLTFNodeIndex node_i = subset[i];
+ const GLTFNode *node = state.nodes[node_i];
+
+ if (heighest == -1 || node->height < heighest) {
+ heighest = node->height;
+ best_node = node_i;
+ }
+ }
+
+ return best_node;
+}
+
+bool EditorSceneImporterGLTF::_capture_nodes_in_skin(GLTFState &state, GLTFSkin &skin, const GLTFNodeIndex node_index) {
+
+ bool found_joint = false;
+
+ for (int i = 0; i < state.nodes[node_index]->children.size(); ++i) {
+ found_joint |= _capture_nodes_in_skin(state, skin, state.nodes[node_index]->children[i]);
+ }
+
+ if (found_joint) {
+ // Mark it if we happen to find another skins joint...
+ if (state.nodes[node_index]->joint && skin.joints.find(node_index) < 0) {
+ skin.joints.push_back(node_index);
+ } else if (skin.non_joints.find(node_index) < 0) {
+ skin.non_joints.push_back(node_index);
+ }
+ }
+
+ if (skin.joints.find(node_index) > 0) {
+ return true;
+ }
+
+ return false;
+}
+
+void EditorSceneImporterGLTF::_capture_nodes_for_multirooted_skin(GLTFState &state, GLTFSkin &skin) {
+
+ DisjointSet<GLTFNodeIndex> disjoint_set;
+
+ for (int i = 0; i < skin.joints.size(); ++i) {
+ const GLTFNodeIndex node_index = skin.joints[i];
+ const GLTFNodeIndex parent = state.nodes[node_index]->parent;
+ disjoint_set.insert(node_index);
+
+ if (skin.joints.find(parent) >= 0) {
+ disjoint_set.create_union(parent, node_index);
+ }
+ }
+
+ Vector<GLTFNodeIndex> roots;
+ disjoint_set.get_representatives(roots);
+
+ if (roots.size() <= 1) {
+ return;
+ }
+
+ int maxHeight = -1;
+
+ // Determine the max height rooted tree
+ for (int i = 0; i < roots.size(); ++i) {
+ const GLTFNodeIndex root = roots[i];
+
+ if (maxHeight == -1 || state.nodes[root]->height < maxHeight) {
+ maxHeight = state.nodes[root]->height;
+ }
+ }
+
+ // Go up the tree till all of the multiple roots of the skin are at the same hierarchy level.
+ // This sucks, but 99% of all game engines (not just Godot) would have this same issue.
+ for (int i = 0; i < roots.size(); ++i) {
+
+ GLTFNodeIndex current_node = roots[i];
+ while (state.nodes[current_node]->height > maxHeight) {
+ GLTFNodeIndex parent = state.nodes[current_node]->parent;
+
+ if (state.nodes[parent]->joint && skin.joints.find(parent) < 0) {
+ skin.joints.push_back(parent);
+ } else if (skin.non_joints.find(parent) < 0) {
+ skin.non_joints.push_back(parent);
+ }
+
+ current_node = parent;
+ }
+
+ // replace the roots
+ roots.write[i] = current_node;
+ }
+
+ // Climb up the tree until they all have the same parent
+ bool all_same;
+
+ do {
+ all_same = true;
+ const GLTFNodeIndex first_parent = state.nodes[roots[0]]->parent;
+
+ for (int i = 1; i < roots.size(); ++i) {
+ all_same &= (first_parent == state.nodes[roots[i]]->parent);
+ }
+
+ if (!all_same) {
+ for (int i = 0; i < roots.size(); ++i) {
+ const GLTFNodeIndex current_node = roots[i];
+ const GLTFNodeIndex parent = state.nodes[current_node]->parent;
+
+ if (state.nodes[parent]->joint && skin.joints.find(parent) < 0) {
+ skin.joints.push_back(parent);
+ } else if (skin.non_joints.find(parent) < 0) {
+ skin.non_joints.push_back(parent);
+ }
+
+ roots.write[i] = parent;
+ }
+ }
+
+ } while (!all_same);
+}
+
+Error EditorSceneImporterGLTF::_expand_skin(GLTFState &state, GLTFSkin &skin) {
+
+ _capture_nodes_for_multirooted_skin(state, skin);
+
+ // Grab all nodes that lay in between skin joints/nodes
+ DisjointSet<GLTFNodeIndex> disjoint_set;
+
+ Vector<GLTFNodeIndex> all_skin_nodes;
+ all_skin_nodes.append_array(skin.joints);
+ all_skin_nodes.append_array(skin.non_joints);
+
+ for (int i = 0; i < all_skin_nodes.size(); ++i) {
+ const GLTFNodeIndex node_index = all_skin_nodes[i];
+ const GLTFNodeIndex parent = state.nodes[node_index]->parent;
+ disjoint_set.insert(node_index);
+
+ if (all_skin_nodes.find(parent) >= 0) {
+ disjoint_set.create_union(parent, node_index);
+ }
+ }
+
+ Vector<GLTFNodeIndex> out_owners;
+ disjoint_set.get_representatives(out_owners);
+
+ Vector<GLTFNodeIndex> out_roots;
+
+ for (int i = 0; i < out_owners.size(); ++i) {
+ Vector<GLTFNodeIndex> set;
+ disjoint_set.get_members(set, out_owners[i]);
+
+ const GLTFNodeIndex root = _find_highest_node(state, set);
+ ERR_FAIL_COND_V(root < 0, FAILED);
+ out_roots.push_back(root);
+ }
+
+ out_roots.sort();
+
+ for (int i = 0; i < out_roots.size(); ++i) {
+ _capture_nodes_in_skin(state, skin, out_roots[i]);
+ }
+
+ skin.roots = out_roots;
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_verify_skin(GLTFState &state, GLTFSkin &skin) {
+ // Grab all nodes that lay in between skin joints/nodes
+ DisjointSet<GLTFNodeIndex> disjoint_set;
+
+ Vector<GLTFNodeIndex> all_skin_nodes;
+ all_skin_nodes.append_array(skin.joints);
+ all_skin_nodes.append_array(skin.non_joints);
+
+ for (int i = 0; i < all_skin_nodes.size(); ++i) {
+ const GLTFNodeIndex node_index = all_skin_nodes[i];
+ const GLTFNodeIndex parent = state.nodes[node_index]->parent;
+ disjoint_set.insert(node_index);
+
+ if (all_skin_nodes.find(parent) >= 0) {
+ disjoint_set.create_union(parent, node_index);
+ }
+ }
+
+ Vector<GLTFNodeIndex> out_roots;
+ disjoint_set.get_representatives(out_roots);
+ out_roots.sort();
+
+ ERR_FAIL_COND_V(out_roots.size() == 0, FAILED);
+
+ ERR_FAIL_COND_V(out_roots.size() != skin.roots.size(), FAILED);
+ for (int i = 0; i < out_roots.size(); ++i) {
+ ERR_FAIL_COND_V(out_roots.size() != skin.roots.size(), FAILED);
+ }
+
+ // Single rooted skin? Perfectly ok!
+ if (out_roots.size() == 1) {
+ return OK;
+ }
+
+ // Make sure all parents of a multi-rooted skin are the SAME
+ const GLTFNodeIndex parent = state.nodes[out_roots[0]]->parent;
+ for (int i = 1; i < out_roots.size(); ++i) {
+ if (state.nodes[out_roots[i]]->parent != parent) {
+ return FAILED;
+ }
+ }
+
+ return OK;
+}
+
Error EditorSceneImporterGLTF::_parse_skins(GLTFState &state) {
if (!state.json.has("skins"))
return OK;
- Array skins = state.json["skins"];
+ const Array &skins = state.json["skins"];
+
+ // Create the base skins, and mark nodes that are joints
for (int i = 0; i < skins.size(); i++) {
- Dictionary d = skins[i];
+ const Dictionary &d = skins[i];
GLTFSkin skin;
ERR_FAIL_COND_V(!d.has("joints"), ERR_PARSE_ERROR);
- Array joints = d["joints"];
- Vector<Transform> bind_matrices;
+ const Array &joints = d["joints"];
if (d.has("inverseBindMatrices")) {
- bind_matrices = _decode_accessor_as_xform(state, d["inverseBindMatrices"], false);
- ERR_FAIL_COND_V(bind_matrices.size() != joints.size(), ERR_PARSE_ERROR);
+ skin.inverse_binds = _decode_accessor_as_xform(state, d["inverseBindMatrices"], false);
+ ERR_FAIL_COND_V(skin.inverse_binds.size() != joints.size(), ERR_PARSE_ERROR);
}
for (int j = 0; j < joints.size(); j++) {
- int index = joints[j];
- ERR_FAIL_INDEX_V(index, state.nodes.size(), ERR_PARSE_ERROR);
- GLTFNode::Joint joint;
- joint.skin = state.skins.size();
- joint.bone = j;
- state.nodes[index]->joints.push_back(joint);
- GLTFSkin::Bone bone;
- bone.node = index;
- if (bind_matrices.size()) {
- bone.inverse_bind = bind_matrices[j];
- }
+ const GLTFNodeIndex node = joints[j];
+ ERR_FAIL_INDEX_V(node, state.nodes.size(), ERR_PARSE_ERROR);
- skin.bones.push_back(bone);
+ skin.joints.push_back(node);
+ skin.joints_original.push_back(node);
+
+ state.nodes[node]->joint = true;
+ }
+
+ if (d.has("name")) {
+ skin.name = d["name"];
}
- print_verbose("glTF: Skin has skeleton? " + itos(d.has("skeleton")));
if (d.has("skeleton")) {
- int skeleton = d["skeleton"];
- ERR_FAIL_INDEX_V(skeleton, state.nodes.size(), ERR_PARSE_ERROR);
- print_verbose("glTF: Setting skeleton skin to" + itos(skeleton));
- skin.skeleton = skeleton;
- if (!state.skeleton_nodes.has(skeleton)) {
- state.skeleton_nodes[skeleton] = Vector<int>();
+ skin.skin_root = d["skeleton"];
+ }
+
+ state.skins.push_back(skin);
+ }
+
+ for (GLTFSkinIndex i = 0; i < state.skins.size(); ++i) {
+ GLTFSkin &skin = state.skins.write[i];
+
+ // Expand the skin to capture all the extra non-joints that lie in between the actual joints,
+ // and expand the hierarchy to ensure multi-rooted trees lie on the same height level
+ ERR_FAIL_COND_V(_expand_skin(state, skin), ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(_verify_skin(state, skin), ERR_PARSE_ERROR);
+ }
+
+ print_verbose("glTF: Total skins: " + itos(state.skins.size()));
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_determine_skeletons(GLTFState &state) {
+
+ // Using a disjoint set, we are going to potentially combine all skins that are actually branches
+ // of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton.
+ // This is another unclear issue caused by the current glTF specification.
+
+ DisjointSet<GLTFNodeIndex> skeleton_sets;
+
+ for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
+ const GLTFSkin &skin = state.skins[skin_i];
+
+ Vector<GLTFNodeIndex> all_skin_nodes;
+ all_skin_nodes.append_array(skin.joints);
+ all_skin_nodes.append_array(skin.non_joints);
+
+ for (int i = 0; i < all_skin_nodes.size(); ++i) {
+ const GLTFNodeIndex node_index = all_skin_nodes[i];
+ const GLTFNodeIndex parent = state.nodes[node_index]->parent;
+ skeleton_sets.insert(node_index);
+
+ if (all_skin_nodes.find(parent) >= 0) {
+ skeleton_sets.create_union(parent, node_index);
}
- state.skeleton_nodes[skeleton].push_back(i);
}
- if (d.has("name")) {
- skin.name = d["name"];
+ // We are going to connect the separate skin subtrees in each skin together
+ // so that the final roots are entire sets of valid skin trees
+ for (int i = 1; i < skin.roots.size(); ++i) {
+ skeleton_sets.create_union(skin.roots[0], skin.roots[i]);
}
+ }
- //locate the right place to put a Skeleton node
- /*
- if (state.skin_users.has(i)) {
- Vector<int> users = state.skin_users[i];
- int skin_node = -1;
- for (int j = 0; j < users.size(); j++) {
- int user = state.nodes[users[j]]->parent; //always go from parent
- if (j == 0) {
- skin_node = user;
- } else if (skin_node != -1) {
- bool found = false;
- while (skin_node >= 0) {
-
- int cuser = user;
- while (cuser != -1) {
- if (cuser == skin_node) {
- found = true;
- break;
- }
- cuser = state.nodes[skin_node]->parent;
- }
- if (found)
- break;
- skin_node = state.nodes[skin_node]->parent;
- }
+ { // attempt to joint all touching subsets (siblings/parent are part of another skin)
+ Vector<GLTFNodeIndex> groups_representatives;
+ skeleton_sets.get_representatives(groups_representatives);
+
+ Vector<GLTFNodeIndex> highest_group_members;
+ Vector<Vector<GLTFNodeIndex> > groups;
+ for (int i = 0; i < groups_representatives.size(); ++i) {
+ Vector<GLTFNodeIndex> group;
+ skeleton_sets.get_members(group, groups_representatives[i]);
+ highest_group_members.push_back(_find_highest_node(state, group));
+ groups.push_back(group);
+ }
+
+ for (int i = 0; i < highest_group_members.size(); ++i) {
+ const GLTFNodeIndex node_i = highest_group_members[i];
+
+ // Attach any siblings together (this needs to be done n^2/2 times)
+ for (int j = i + 1; j < highest_group_members.size(); ++j) {
+ const GLTFNodeIndex node_j = highest_group_members[j];
+
+ // Even if they are siblings under the root! :)
+ if (state.nodes[node_i]->parent == state.nodes[node_j]->parent) {
+ skeleton_sets.create_union(node_i, node_j);
+ }
+ }
- if (!found) {
- skin_node = -1; //just leave where it is
+ // Attach any parenting going on together (we need to do this n^2 times)
+ const GLTFNodeIndex node_i_parent = state.nodes[node_i]->parent;
+ if (node_i_parent >= 0) {
+ for (int j = 0; j < groups.size() && i != j; ++j) {
+ const Vector<GLTFNodeIndex> &group = groups[j];
+
+ if (group.find(node_i_parent) >= 0) {
+ const GLTFNodeIndex node_j = highest_group_members[j];
+ skeleton_sets.create_union(node_i, node_j);
}
+ }
+ }
+ }
+ }
+
+ // At this point, the skeleton groups should be finalized
+ Vector<GLTFNodeIndex> skeleton_owners;
+ skeleton_sets.get_representatives(skeleton_owners);
+
+ // Mark all the skins actual skeletons, after we have merged them
+ for (GLTFSkeletonIndex skel_i = 0; skel_i < skeleton_owners.size(); ++skel_i) {
- //find a common parent
+ const GLTFNodeIndex skeleton_owner = skeleton_owners[skel_i];
+ GLTFSkeleton skeleton;
+
+ Vector<GLTFNodeIndex> skeleton_nodes;
+ skeleton_sets.get_members(skeleton_nodes, skeleton_owner);
+
+ for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
+ GLTFSkin &skin = state.skins.write[skin_i];
+
+ // If any of the the skeletons nodes exist in a skin, that skin now maps to the skeleton
+ for (int i = 0; i < skeleton_nodes.size(); ++i) {
+ GLTFNodeIndex skel_node_i = skeleton_nodes[i];
+ if (skin.joints.find(skel_node_i) >= 0 || skin.non_joints.find(skel_node_i) >= 0) {
+ skin.skeleton = skel_i;
+ continue;
}
}
+ }
+
+ Vector<GLTFNodeIndex> non_joints;
+ for (int i = 0; i < skeleton_nodes.size(); ++i) {
+ const GLTFNodeIndex node_i = skeleton_nodes[i];
+
+ if (state.nodes[node_i]->joint) {
+ skeleton.joints.push_back(node_i);
+ } else {
+ non_joints.push_back(node_i);
+ }
+ }
+
+ state.skeletons.push_back(skeleton);
+
+ _reparent_non_joint_skeleton_subtrees(state, state.skeletons.write[skel_i], non_joints);
+ }
+
+ for (GLTFSkeletonIndex skel_i = 0; skel_i < state.skeletons.size(); ++skel_i) {
+ GLTFSkeleton &skeleton = state.skeletons.write[skel_i];
+
+ for (int i = 0; i < skeleton.joints.size(); ++i) {
+ const GLTFNodeIndex node_i = skeleton.joints[i];
+ GLTFNode *node = state.nodes[node_i];
+
+ ERR_FAIL_COND_V(!node->joint, ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(node->skeleton >= 0, ERR_PARSE_ERROR);
+ node->skeleton = skel_i;
+ }
+
+ ERR_FAIL_COND_V(_determine_skeleton_roots(state, skel_i), ERR_PARSE_ERROR);
+ }
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_reparent_non_joint_skeleton_subtrees(GLTFState &state, GLTFSkeleton &skeleton, const Vector<GLTFNodeIndex> &non_joints) {
+
+ DisjointSet<GLTFNodeIndex> subtree_set;
+
+ // Populate the disjoint set with ONLY non joints that are in the skeleton hierarchy (non_joints vector)
+ // This way we can find any joints that lie in between joints, as the current glTF specification
+ // mentions nothing about non-joints being in between joints of the same skin. Hopefully one day we
+ // can remove this code.
+
+ // skinD depicted here explains this issue:
+ // https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Animation_Skin
+
+ for (int i = 0; i < non_joints.size(); ++i) {
+ const GLTFNodeIndex node_i = non_joints[i];
+
+ subtree_set.insert(node_i);
+
+ const GLTFNodeIndex parent_i = state.nodes[node_i]->parent;
+ if (parent_i >= 0 && non_joints.find(parent_i) >= 0 && !state.nodes[parent_i]->joint) {
+ subtree_set.create_union(parent_i, node_i);
+ }
+ }
+
+ // Find all the non joint subtrees and re-parent them to a new "fake" joint
+
+ Vector<GLTFNodeIndex> non_joint_subtree_roots;
+ subtree_set.get_representatives(non_joint_subtree_roots);
+
+ for (int root_i = 0; root_i < non_joint_subtree_roots.size(); ++root_i) {
+ const GLTFNodeIndex subtree_root = non_joint_subtree_roots[root_i];
+
+ Vector<GLTFNodeIndex> subtree_nodes;
+ subtree_set.get_members(subtree_nodes, subtree_root);
+
+ for (int subtree_i = 0; subtree_i < subtree_nodes.size(); ++subtree_i) {
+ ERR_FAIL_COND_V(_reparent_to_fake_joint(state, skeleton, subtree_nodes[subtree_i]), FAILED);
+
+ // We modified the tree, recompute all the heights
+ _compute_node_heights(state);
+ }
+ }
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_reparent_to_fake_joint(GLTFState &state, GLTFSkeleton &skeleton, const GLTFNodeIndex node_index) {
+ GLTFNode *node = state.nodes[node_index];
+
+ // Can we just "steal" this joint if it is just a spatial node?
+ if (node->skin < 0 && node->mesh < 0 && node->camera < 0) {
+ node->joint = true;
+ // Add the joint to the skeletons joints
+ skeleton.joints.push_back(node_index);
+ return OK;
+ }
+
+ GLTFNode *fake_joint = memnew(GLTFNode);
+ const GLTFNodeIndex fake_joint_index = state.nodes.size();
+ state.nodes.push_back(fake_joint);
+
+ // We better not be a joint, or we messed up in our logic
+ if (node->joint == true)
+ return FAILED;
+
+ fake_joint->translation = node->translation;
+ fake_joint->rotation = node->rotation;
+ fake_joint->scale = node->scale;
+ fake_joint->xform = node->xform;
+ fake_joint->joint = true;
+
+ // We can use the exact same name here, because the joint will be inside a skeleton and not the scene
+ fake_joint->name = node->name;
+
+ // Clear the nodes transforms, since it will be parented to the fake joint
+ node->translation = Vector3(0, 0, 0);
+ node->rotation = Quat();
+ node->scale = Vector3(1, 1, 1);
+ node->xform = Transform();
+
+ // Transfer the node children to the fake joint
+ for (int child_i = 0; child_i < node->children.size(); ++child_i) {
+ GLTFNode *child = state.nodes[node->children[child_i]];
+ child->parent = fake_joint_index;
+ }
+
+ fake_joint->children = node->children;
+ node->children.clear();
+
+ // add the fake joint to the parent and remove the original joint
+ if (node->parent >= 0) {
+ GLTFNode *parent = state.nodes[node->parent];
+ parent->children.erase(node_index);
+ parent->children.push_back(fake_joint_index);
+ fake_joint->parent = node->parent;
+ }
+
+ // Add the node to the fake joint
+ fake_joint->children.push_back(node_index);
+ node->parent = fake_joint_index;
+ node->fake_joint_parent = fake_joint_index;
+
+ // Add the fake joint to the skeletons joints
+ skeleton.joints.push_back(fake_joint_index);
+
+ // Replace skin_skeletons with fake joints if we must.
+ for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
+ GLTFSkin &skin = state.skins.write[skin_i];
+ if (skin.skin_root == node_index) {
+ skin.skin_root = fake_joint_index;
+ }
+ }
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_determine_skeleton_roots(GLTFState &state, const GLTFSkeletonIndex skel_i) {
+
+ DisjointSet<GLTFNodeIndex> disjoint_set;
+
+ for (GLTFNodeIndex i = 0; i < state.nodes.size(); ++i) {
+ const GLTFNode *node = state.nodes[i];
+
+ if (node->skeleton != skel_i) {
+ continue;
+ }
+
+ disjoint_set.insert(i);
+
+ if (node->parent >= 0 && state.nodes[node->parent]->skeleton == skel_i) {
+ disjoint_set.create_union(node->parent, i);
+ }
+ }
+
+ GLTFSkeleton &skeleton = state.skeletons.write[skel_i];
+
+ Vector<GLTFNodeIndex> owners;
+ disjoint_set.get_representatives(owners);
+
+ Vector<GLTFNodeIndex> roots;
+
+ for (int i = 0; i < owners.size(); ++i) {
+ Vector<GLTFNodeIndex> set;
+ disjoint_set.get_members(set, owners[i]);
+ const GLTFNodeIndex root = _find_highest_node(state, set);
+ ERR_FAIL_COND_V(root < 0, FAILED);
+ roots.push_back(root);
+ }
+
+ roots.sort();
+
+ skeleton.roots = roots;
+
+ if (roots.size() == 0) {
+ return FAILED;
+ } else if (roots.size() == 1) {
+ return OK;
+ }
+
+ // Check that the subtrees have the same parent root
+ const GLTFNodeIndex parent = state.nodes[roots[0]]->parent;
+ for (int i = 1; i < roots.size(); ++i) {
+ if (state.nodes[roots[i]]->parent != parent) {
+ return FAILED;
+ }
+ }
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_create_skeletons(GLTFState &state) {
+ for (GLTFSkeletonIndex skel_i = 0; skel_i < state.skeletons.size(); ++skel_i) {
+
+ GLTFSkeleton &gltf_skeleton = state.skeletons.write[skel_i];
+
+ Skeleton *skeleton = memnew(Skeleton);
+ gltf_skeleton.godot_skeleton = skeleton;
+
+ // Make a unique name, no gltf node represents this skeleton
+ skeleton->set_name(_gen_unique_name(state, "Skeleton"));
+
+ List<GLTFNodeIndex> bones;
- if (skin_node != -1) {
- for (int j = 0; j < users.size(); j++) {
- state.nodes[users[j]]->child_of_skeleton = i;
+ for (int i = 0; i < gltf_skeleton.roots.size(); ++i) {
+ bones.push_back(gltf_skeleton.roots[i]);
+ }
+
+ // Make the skeleton creation deterministic by going through the roots in
+ // a sorted order, and DEPTH FIRST
+ bones.sort();
+
+ while (!bones.empty()) {
+ const GLTFNodeIndex node_i = bones.front()->get();
+ bones.pop_front();
+
+ GLTFNode *node = state.nodes[node_i];
+ ERR_FAIL_COND_V(node->skeleton != skel_i, FAILED);
+
+ { // Add all child nodes to the stack (deterministically)
+ Vector<GLTFNodeIndex> child_nodes;
+ for (int i = 0; i < node->children.size(); ++i) {
+ const GLTFNodeIndex child_i = node->children[i];
+ if (state.nodes[child_i]->skeleton == skel_i) {
+ child_nodes.push_back(child_i);
+ }
}
- state.nodes[skin_node]->skeleton_children.push_back(i);
+ // Depth first insertion
+ child_nodes.sort();
+ for (int i = child_nodes.size() - 1; i >= 0; --i) {
+ bones.push_front(child_nodes[i]);
+ }
}
+
+ const int bone_index = skeleton->get_bone_count();
+
+ if (node->name.empty()) {
+ node->name = "bone";
+ }
+
+ node->name = _gen_unique_bone_name(state, skel_i, node->name);
+
+ skeleton->add_bone(node->name);
+ skeleton->set_bone_rest(bone_index, node->xform);
+ skeleton->set_bone_pose(bone_index, node->xform);
+
+ if (node->parent >= 0 && state.nodes[node->parent]->skeleton == skel_i) {
+ const int bone_parent = skeleton->find_bone(state.nodes[node->parent]->name);
+ ERR_FAIL_COND_V(bone_parent < 0, FAILED);
+ skeleton->set_bone_parent(bone_index, skeleton->find_bone(state.nodes[node->parent]->name));
+ }
+
+ state.scene_nodes.insert(node_i, skeleton);
}
- */
- state.skins.push_back(skin);
}
- print_verbose("glTF: Total skins: " + itos(state.skins.size()));
- //now
+ ERR_FAIL_COND_V(_map_skin_joints_indices_to_skeleton_bone_indices(state), ERR_PARSE_ERROR);
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_map_skin_joints_indices_to_skeleton_bone_indices(GLTFState &state) {
+ for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
+ GLTFSkin &skin = state.skins.write[skin_i];
+
+ const GLTFSkeleton &skeleton = state.skeletons[skin.skeleton];
+
+ for (int joint_index = 0; joint_index < skin.joints_original.size(); ++joint_index) {
+ const GLTFNodeIndex node_i = skin.joints_original[joint_index];
+ const GLTFNode *node = state.nodes[node_i];
+
+ const int bone_index = skeleton.godot_skeleton->find_bone(node->name);
+ ERR_FAIL_COND_V(bone_index < 0, FAILED);
+
+ skin.joint_i_to_bone_i.insert(joint_index, bone_index);
+ }
+ }
+
+ return OK;
+}
+
+Error EditorSceneImporterGLTF::_create_skins(GLTFState &state) {
+ for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
+ GLTFSkin &gltf_skin = state.skins.write[skin_i];
+
+ Ref<Skin> skin;
+ skin.instance();
+
+ // Some skins don't have IBM's! What absolute monsters!
+ const bool has_ibms = !gltf_skin.inverse_binds.empty();
+
+ for (int joint_i = 0; joint_i < gltf_skin.joints_original.size(); ++joint_i) {
+ int bone_i = gltf_skin.joint_i_to_bone_i[joint_i];
+
+ if (has_ibms) {
+ skin->add_bind(bone_i, gltf_skin.inverse_binds[joint_i]);
+ } else {
+ skin->add_bind(bone_i, Transform());
+ }
+ }
+
+ gltf_skin.godot_skin = skin;
+ }
+
+ // Purge the duplicates!
+ _remove_duplicate_skins(state);
+
+ // Create unique names now, after removing duplicates
+ for (GLTFSkinIndex skin_i = 0; skin_i < state.skins.size(); ++skin_i) {
+ Ref<Skin> skin = state.skins[skin_i].godot_skin;
+ if (skin->get_name().empty()) {
+ // Make a unique name, no gltf node represents this skin
+ skin->set_name(_gen_unique_name(state, "Skin"));
+ }
+ }
return OK;
}
+bool EditorSceneImporterGLTF::_skins_are_same(const Ref<Skin> &skin_a, const Ref<Skin> &skin_b) {
+ if (skin_a->get_bind_count() != skin_b->get_bind_count()) {
+ return false;
+ }
+
+ for (int i = 0; i < skin_a->get_bind_count(); ++i) {
+
+ if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) {
+ return false;
+ }
+
+ Transform a_xform = skin_a->get_bind_pose(i);
+ Transform b_xform = skin_b->get_bind_pose(i);
+
+ if (a_xform != b_xform) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void EditorSceneImporterGLTF::_remove_duplicate_skins(GLTFState &state) {
+ for (int i = 0; i < state.skins.size(); ++i) {
+ for (int j = i + 1; j < state.skins.size(); ++j) {
+ const Ref<Skin> &skin_i = state.skins[i].godot_skin;
+ const Ref<Skin> &skin_j = state.skins[j].godot_skin;
+
+ if (_skins_are_same(skin_i, skin_j)) {
+ // replace it and delete the old
+ state.skins.write[j].godot_skin = skin_i;
+ }
+ }
+ }
+}
+
Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) {
if (!state.json.has("cameras"))
return OK;
- Array cameras = state.json["cameras"];
+ const Array &cameras = state.json["cameras"];
- for (int i = 0; i < cameras.size(); i++) {
+ for (GLTFCameraIndex i = 0; i < cameras.size(); i++) {
- Dictionary d = cameras[i];
+ const Dictionary &d = cameras[i];
GLTFCamera camera;
ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR);
- String type = d["type"];
+ const String &type = d["type"];
if (type == "orthographic") {
camera.perspective = false;
if (d.has("orthographic")) {
- Dictionary og = d["orthographic"];
+ const Dictionary &og = d["orthographic"];
camera.fov_size = og["ymag"];
camera.zfar = og["zfar"];
camera.znear = og["znear"];
@@ -1535,7 +2255,7 @@ Error EditorSceneImporterGLTF::_parse_cameras(GLTFState &state) {
camera.perspective = true;
if (d.has("perspective")) {
- Dictionary ppt = d["perspective"];
+ const Dictionary &ppt = d["perspective"];
// GLTF spec is in radians, Godot's camera is in degrees.
camera.fov_size = (double)ppt["yfov"] * 180.0 / Math_PI;
camera.zfar = ppt["zfar"];
@@ -1560,11 +2280,11 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
if (!state.json.has("animations"))
return OK;
- Array animations = state.json["animations"];
+ const Array &animations = state.json["animations"];
- for (int i = 0; i < animations.size(); i++) {
+ for (GLTFAnimationIndex i = 0; i < animations.size(); i++) {
- Dictionary d = animations[i];
+ const Dictionary &d = animations[i];
GLTFAnimation animation;
@@ -1580,25 +2300,25 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
for (int j = 0; j < channels.size(); j++) {
- Dictionary c = channels[j];
+ const Dictionary &c = channels[j];
if (!c.has("target"))
continue;
- Dictionary t = c["target"];
+ const Dictionary &t = c["target"];
if (!t.has("node") || !t.has("path")) {
continue;
}
ERR_FAIL_COND_V(!c.has("sampler"), ERR_PARSE_ERROR);
- int sampler = c["sampler"];
+ const int sampler = c["sampler"];
ERR_FAIL_INDEX_V(sampler, samplers.size(), ERR_PARSE_ERROR);
- int node = t["node"];
+ GLTFNodeIndex node = t["node"];
String path = t["path"];
ERR_FAIL_INDEX_V(node, state.nodes.size(), ERR_PARSE_ERROR);
- GLTFAnimation::Track *track = NULL;
+ GLTFAnimation::Track *track = nullptr;
if (!animation.tracks.has(node)) {
animation.tracks[node] = GLTFAnimation::Track();
@@ -1606,17 +2326,17 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
track = &animation.tracks[node];
- Dictionary s = samplers[sampler];
+ const Dictionary &s = samplers[sampler];
ERR_FAIL_COND_V(!s.has("input"), ERR_PARSE_ERROR);
ERR_FAIL_COND_V(!s.has("output"), ERR_PARSE_ERROR);
- int input = s["input"];
- int output = s["output"];
+ const int input = s["input"];
+ const int output = s["output"];
GLTFAnimation::Interpolation interp = GLTFAnimation::INTERP_LINEAR;
if (s.has("interpolation")) {
- String in = s["interpolation"];
+ const String &in = s["interpolation"];
if (in == "STEP") {
interp = GLTFAnimation::INTERP_STEP;
} else if (in == "LINEAR") {
@@ -1628,33 +2348,33 @@ Error EditorSceneImporterGLTF::_parse_animations(GLTFState &state) {
}
}
- PoolVector<float> times = _decode_accessor_as_floats(state, input, false);
+ const PoolVector<float> times = _decode_accessor_as_floats(state, input, false);
if (path == "translation") {
- PoolVector<Vector3> translations = _decode_accessor_as_vec3(state, output, false);
+ const PoolVector<Vector3> translations = _decode_accessor_as_vec3(state, output, false);
track->translation_track.interpolation = interp;
track->translation_track.times = Variant(times); //convert via variant
track->translation_track.values = Variant(translations); //convert via variant
} else if (path == "rotation") {
- Vector<Quat> rotations = _decode_accessor_as_quat(state, output, false);
+ const Vector<Quat> rotations = _decode_accessor_as_quat(state, output, false);
track->rotation_track.interpolation = interp;
track->rotation_track.times = Variant(times); //convert via variant
track->rotation_track.values = rotations; //convert via variant
} else if (path == "scale") {
- PoolVector<Vector3> scales = _decode_accessor_as_vec3(state, output, false);
+ const PoolVector<Vector3> scales = _decode_accessor_as_vec3(state, output, false);
track->scale_track.interpolation = interp;
track->scale_track.times = Variant(times); //convert via variant
track->scale_track.values = Variant(scales); //convert via variant
} else if (path == "weights") {
- PoolVector<float> weights = _decode_accessor_as_floats(state, output, false);
+ const PoolVector<float> weights = _decode_accessor_as_floats(state, output, false);
ERR_FAIL_INDEX_V(state.nodes[node]->mesh, state.meshes.size(), ERR_PARSE_ERROR);
const GLTFMesh *mesh = &state.meshes[state.nodes[node]->mesh];
ERR_FAIL_COND_V(mesh->blend_weights.size() == 0, ERR_PARSE_ERROR);
- int wc = mesh->blend_weights.size();
+ const int wc = mesh->blend_weights.size();
track->weight_tracks.resize(wc);
- int wlen = weights.size() / wc;
+ const int wlen = weights.size() / wc;
PoolVector<float>::Read r = weights.read();
for (int k = 0; k < wc; k++) { //separate tracks, having them together is not such a good idea
GLTFAnimation::Channel<float> cf;
@@ -1686,11 +2406,16 @@ void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) {
for (int i = 0; i < state.nodes.size(); i++) {
GLTFNode *n = state.nodes[i];
- if (n->name == "") {
+
+ // Any joints get unique names generated when the skeleton is made, unique to the skeleton
+ if (n->skeleton >= 0)
+ continue;
+
+ if (n->name.empty()) {
if (n->mesh >= 0) {
n->name = "Mesh";
- } else if (n->joints.size()) {
- n->name = "Bone";
+ } else if (n->camera >= 0) {
+ n->name = "Camera";
} else {
n->name = "Node";
}
@@ -1700,127 +2425,131 @@ void EditorSceneImporterGLTF::_assign_scene_names(GLTFState &state) {
}
}
-void EditorSceneImporterGLTF::_reparent_skeleton(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, Node *p_parent_node) {
- //reparent skeletons to proper place
- Vector<int> nodes = state.skeleton_nodes[p_node];
- for (int i = 0; i < nodes.size(); i++) {
- Skeleton *skeleton = skeletons[nodes[i]];
- Node *owner = skeleton->get_owner();
- skeleton->get_parent()->remove_child(skeleton);
- p_parent_node->add_child(skeleton);
- skeleton->set_owner(owner);
- //may have meshes as children, set owner in them too
- for (int j = 0; j < skeleton->get_child_count(); j++) {
- skeleton->get_child(j)->set_owner(owner);
- }
- }
-}
+BoneAttachment *EditorSceneImporterGLTF::_generate_bone_attachment(GLTFState &state, Skeleton *skeleton, const GLTFNodeIndex node_index) {
-void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector<Skeleton *> &skeletons) {
- ERR_FAIL_INDEX(p_node, state.nodes.size());
+ const GLTFNode *gltf_node = state.nodes[node_index];
+ const GLTFNode *bone_node = state.nodes[gltf_node->parent];
- GLTFNode *n = state.nodes[p_node];
- Spatial *node;
+ BoneAttachment *bone_attachment = memnew(BoneAttachment);
+ print_verbose("glTF: Creating bone attachment for: " + gltf_node->name);
- if (n->mesh >= 0) {
- ERR_FAIL_INDEX(n->mesh, state.meshes.size());
- MeshInstance *mi = memnew(MeshInstance);
- print_verbose("glTF: Creating mesh for: " + n->name);
- GLTFMesh &mesh = state.meshes.write[n->mesh];
- mi->set_mesh(mesh.mesh);
- if (mesh.mesh->get_name() == "") {
- mesh.mesh->set_name(n->name);
- }
- for (int i = 0; i < mesh.blend_weights.size(); i++) {
- mi->set("blend_shapes/" + mesh.mesh->get_blend_shape_name(i), mesh.blend_weights[i]);
- }
+ ERR_FAIL_COND_V(!bone_node->joint, nullptr);
- node = mi;
+ bone_attachment->set_bone_name(bone_node->name);
- } else if (n->camera >= 0) {
- ERR_FAIL_INDEX(n->camera, state.cameras.size());
- Camera *camera = memnew(Camera);
+ return bone_attachment;
+}
- const GLTFCamera &c = state.cameras[n->camera];
- if (c.perspective) {
- camera->set_perspective(c.fov_size, c.znear, c.znear);
- } else {
- camera->set_orthogonal(c.fov_size, c.znear, c.znear);
- }
+MeshInstance *EditorSceneImporterGLTF::_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
+ const GLTFNode *gltf_node = state.nodes[node_index];
- node = camera;
- } else {
- node = memnew(Spatial);
+ ERR_FAIL_INDEX_V(gltf_node->mesh, state.meshes.size(), nullptr);
+
+ MeshInstance *mi = memnew(MeshInstance);
+ print_verbose("glTF: Creating mesh for: " + gltf_node->name);
+
+ GLTFMesh &mesh = state.meshes.write[gltf_node->mesh];
+ mi->set_mesh(mesh.mesh);
+
+ if (mesh.mesh->get_name() == "") {
+ mesh.mesh->set_name(gltf_node->name);
+ }
+
+ for (int i = 0; i < mesh.blend_weights.size(); i++) {
+ mi->set("blend_shapes/" + mesh.mesh->get_blend_shape_name(i), mesh.blend_weights[i]);
}
- node->set_name(n->name);
+ return mi;
+}
- n->godot_nodes.push_back(node);
+Camera *EditorSceneImporterGLTF::_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
+ const GLTFNode *gltf_node = state.nodes[node_index];
- if (n->skin >= 0 && n->skin < skeletons.size() && Object::cast_to<MeshInstance>(node)) {
- MeshInstance *mi = Object::cast_to<MeshInstance>(node);
+ ERR_FAIL_INDEX_V(gltf_node->camera, state.cameras.size(), nullptr);
- Skeleton *s = skeletons[n->skin];
- s->add_child(node); //According to spec, mesh should actually act as a child of the skeleton, as it inherits its transform
- mi->set_skeleton_path(String(".."));
+ Camera *camera = memnew(Camera);
+ print_verbose("glTF: Creating camera for: " + gltf_node->name);
+ const GLTFCamera &c = state.cameras[gltf_node->camera];
+ if (c.perspective) {
+ camera->set_perspective(c.fov_size, c.znear, c.znear);
} else {
- p_parent->add_child(node);
- node->set_transform(n->xform);
+ camera->set_orthogonal(c.fov_size, c.znear, c.znear);
}
- node->set_owner(p_owner);
+ return camera;
+}
-#if 0
- for (int i = 0; i < n->skeleton_children.size(); i++) {
+Spatial *EditorSceneImporterGLTF::_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index) {
+ const GLTFNode *gltf_node = state.nodes[node_index];
- Skeleton *s = skeletons[n->skeleton_children[i]];
- s->get_parent()->remove_child(s);
- node->add_child(s);
- s->set_owner(p_owner);
- }
-#endif
- for (int i = 0; i < n->children.size(); i++) {
- if (state.nodes[n->children[i]]->joints.size()) {
- _generate_bone(state, n->children[i], skeletons, node);
- } else {
- _generate_node(state, n->children[i], node, p_owner, skeletons);
- }
- }
+ Spatial *spatial = memnew(Spatial);
+ print_verbose("glTF: Creating spatial for: " + gltf_node->name);
- if (state.skeleton_nodes.has(p_node)) {
- _reparent_skeleton(state, p_node, skeletons, node);
- }
+ return spatial;
}
-void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, Node *p_parent_node) {
- ERR_FAIL_INDEX(p_node, state.nodes.size());
+void EditorSceneImporterGLTF::_generate_scene_node(GLTFState &state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index) {
+
+ const GLTFNode *gltf_node = state.nodes[node_index];
+
+ Spatial *current_node = nullptr;
+
+ // Is our parent a skeleton
+ Skeleton *active_skeleton = Object::cast_to<Skeleton>(scene_parent);
+
+ if (gltf_node->skeleton >= 0) {
+ Skeleton *skeleton = state.skeletons[gltf_node->skeleton].godot_skeleton;
- if (state.skeleton_nodes.has(p_node)) {
- _reparent_skeleton(state, p_node, skeletons, p_parent_node);
+ if (active_skeleton != skeleton) {
+ ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons");
+
+ // Add it to the scene if it has not already been added
+ if (skeleton->get_parent() == nullptr) {
+ scene_parent->add_child(skeleton);
+ skeleton->set_owner(scene_root);
+ }
+ }
+
+ active_skeleton = skeleton;
+ current_node = skeleton;
}
- GLTFNode *n = state.nodes[p_node];
+ // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment
+ if (current_node == nullptr && active_skeleton != nullptr && gltf_node->skin < 0) {
+ BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index);
- for (int i = 0; i < n->joints.size(); i++) {
- const int skin = n->joints[i].skin;
- ERR_FAIL_COND(skin < 0);
+ scene_parent->add_child(bone_attachment);
+ bone_attachment->set_owner(scene_root);
- Skeleton *s = skeletons[skin];
- const GLTFNode *gltf_bone_node = state.nodes[state.skins[skin].bones[n->joints[i].bone].node];
- const String bone_name = gltf_bone_node->name;
- const int parent = gltf_bone_node->parent;
- const int parent_index = s->find_bone(state.nodes[parent]->name);
+ // There is no gltf_node that represent this, so just directly create a unique name
+ bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment"));
- const int bone_index = s->find_bone(bone_name);
- s->set_bone_parent(bone_index, parent_index);
+ // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node
+ // and attach it to the bone_attachment
+ scene_parent = bone_attachment;
+ }
+
+ // We still have not managed to make a node
+ if (current_node == nullptr) {
+ if (gltf_node->mesh >= 0) {
+ current_node = _generate_mesh_instance(state, scene_parent, node_index);
+ } else if (gltf_node->camera >= 0) {
+ current_node = _generate_camera(state, scene_parent, node_index);
+ } else {
+ current_node = _generate_spatial(state, scene_parent, node_index);
+ }
- n->godot_nodes.push_back(s);
- n->joints.write[i].godot_bone_index = bone_index;
+ scene_parent->add_child(current_node);
+ current_node->set_owner(scene_root);
+ current_node->set_transform(gltf_node->xform);
+ current_node->set_name(gltf_node->name);
}
- for (int i = 0; i < n->children.size(); i++) {
- _generate_bone(state, n->children[i], skeletons, p_parent_node);
+ state.scene_nodes.insert(node_index, current_node);
+
+ for (int i = 0; i < gltf_node->children.size(); ++i) {
+ _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]);
}
}
@@ -1834,43 +2563,43 @@ struct EditorSceneImporterGLTFInterpolate {
T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
- float t2 = t * t;
- float t3 = t2 * t;
+ const float t2 = t * t;
+ const float t3 = t2 * t;
return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
}
T bezier(T start, T control_1, T control_2, T end, float t) {
/* Formula from Wikipedia article on Bezier curves. */
- real_t omt = (1.0 - t);
- real_t omt2 = omt * omt;
- real_t omt3 = omt2 * omt;
- real_t t2 = t * t;
- real_t t3 = t2 * t;
+ const real_t omt = (1.0 - t);
+ const real_t omt2 = omt * omt;
+ const real_t omt3 = omt2 * omt;
+ const real_t t2 = t * t;
+ const real_t t3 = t2 * t;
return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
}
};
-//thank you for existing, partial specialization
+// thank you for existing, partial specialization
template <>
struct EditorSceneImporterGLTFInterpolate<Quat> {
- Quat lerp(const Quat &a, const Quat &b, float c) const {
+ Quat lerp(const Quat &a, const Quat &b, const float c) const {
ERR_FAIL_COND_V(!a.is_normalized(), Quat());
ERR_FAIL_COND_V(!b.is_normalized(), Quat());
return a.slerp(b, c).normalized();
}
- Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) {
+ Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, const float c) {
ERR_FAIL_COND_V(!p1.is_normalized(), Quat());
ERR_FAIL_COND_V(!p2.is_normalized(), Quat());
return p1.slerp(p2, c).normalized();
}
- Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) {
+ Quat bezier(const Quat start, const Quat control_1, const Quat control_2, const Quat end, const float t) {
ERR_FAIL_COND_V(!start.is_normalized(), Quat());
ERR_FAIL_COND_V(!end.is_normalized(), Quat());
@@ -1879,7 +2608,7 @@ struct EditorSceneImporterGLTFInterpolate<Quat> {
};
template <class T>
-T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, GLTFAnimation::Interpolation p_interp) {
+T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) {
//could use binary search, worth it?
int idx = -1;
@@ -1900,7 +2629,7 @@ T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, cons
return p_values[p_times.size() - 1];
}
- float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+ const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
return interp.lerp(p_values[idx], p_values[idx + 1], c);
@@ -1924,7 +2653,7 @@ T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, cons
return p_values[1 + p_times.size() - 1];
}
- float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+ const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
@@ -1937,12 +2666,12 @@ T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, cons
return p_values[(p_times.size() - 1) * 3 + 1];
}
- float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+ const float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
- T from = p_values[idx * 3 + 1];
- T c1 = from + p_values[idx * 3 + 2];
- T to = p_values[idx * 3 + 4];
- T c2 = to + p_values[idx * 3 + 3];
+ const T from = p_values[idx * 3 + 1];
+ const T c1 = from + p_values[idx * 3 + 2];
+ const T to = p_values[idx * 3 + 4];
+ const T c2 = to + p_values[idx * 3 + 3];
return interp.bezier(from, c1, c2, to, c);
@@ -1952,12 +2681,13 @@ T EditorSceneImporterGLTF::_interpolate_track(const Vector<float> &p_times, cons
ERR_FAIL_V(p_values[0]);
}
-void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons) {
+void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) {
const GLTFAnimation &anim = state.animations[index];
String name = anim.name;
- if (name == "") {
+ if (name.empty()) {
+ // No node represent these, and they are not in the hierarchy, so just make a unique name
name = _gen_unique_name(state, "Animation");
}
@@ -1973,102 +2703,143 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye
//need to find the path
NodePath node_path;
- GLTFNode *node = state.nodes[E->key()];
- for (int n = 0; n < node->godot_nodes.size(); n++) {
+ GLTFNodeIndex node_index = E->key();
+ if (state.nodes[node_index]->fake_joint_parent >= 0) {
+ // Should be same as parent
+ node_index = state.nodes[node_index]->fake_joint_parent;
+ }
- if (node->joints.size()) {
- Skeleton *sk = (Skeleton *)node->godot_nodes[n];
- String path = ap->get_parent()->get_path_to(sk);
- String bone = sk->get_bone_name(node->joints[n].godot_bone_index);
- node_path = path + ":" + bone;
- } else {
- node_path = ap->get_parent()->get_path_to(node->godot_nodes[n]);
- }
+ const GLTFNode *node = state.nodes[E->key()];
- for (int i = 0; i < track.rotation_track.times.size(); i++) {
- length = MAX(length, track.rotation_track.times[i]);
- }
- for (int i = 0; i < track.translation_track.times.size(); i++) {
- length = MAX(length, track.translation_track.times[i]);
+ if (node->skeleton >= 0) {
+ const Skeleton *sk = Object::cast_to<Skeleton>(state.scene_nodes.find(node_index)->get());
+ ERR_FAIL_COND(sk == nullptr);
+
+ const String path = ap->get_parent()->get_path_to(sk);
+ const String bone = node->name;
+ node_path = path + ":" + bone;
+ } else {
+ node_path = ap->get_parent()->get_path_to(state.scene_nodes.find(node_index)->get());
+ }
+
+ for (int i = 0; i < track.rotation_track.times.size(); i++) {
+ length = MAX(length, track.rotation_track.times[i]);
+ }
+ for (int i = 0; i < track.translation_track.times.size(); i++) {
+ length = MAX(length, track.translation_track.times[i]);
+ }
+ for (int i = 0; i < track.scale_track.times.size(); i++) {
+ length = MAX(length, track.scale_track.times[i]);
+ }
+
+ for (int i = 0; i < track.weight_tracks.size(); i++) {
+ for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
+ length = MAX(length, track.weight_tracks[i].times[j]);
}
- for (int i = 0; i < track.scale_track.times.size(); i++) {
- length = MAX(length, track.scale_track.times[i]);
+ }
+
+ if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) {
+ //make transform track
+ int track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_TRANSFORM);
+ animation->track_set_path(track_idx, node_path);
+ //first determine animation length
+
+ const float increment = 1.0 / float(bake_fps);
+ float time = 0.0;
+
+ Vector3 base_pos;
+ Quat base_rot;
+ Vector3 base_scale = Vector3(1, 1, 1);
+
+ if (!track.rotation_track.values.size()) {
+ base_rot = state.nodes[E->key()]->rotation.normalized();
}
- for (int i = 0; i < track.weight_tracks.size(); i++) {
- for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
- length = MAX(length, track.weight_tracks[i].times[j]);
- }
+ if (!track.translation_track.values.size()) {
+ base_pos = state.nodes[E->key()]->translation;
}
- if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) {
- //make transform track
- int track_idx = animation->get_track_count();
- animation->add_track(Animation::TYPE_TRANSFORM);
- animation->track_set_path(track_idx, node_path);
- //first determine animation length
+ if (!track.scale_track.values.size()) {
+ base_scale = state.nodes[E->key()]->scale;
+ }
- float increment = 1.0 / float(bake_fps);
- float time = 0.0;
+ bool last = false;
+ while (true) {
- Vector3 base_pos;
- Quat base_rot;
- Vector3 base_scale = Vector3(1, 1, 1);
+ Vector3 pos = base_pos;
+ Quat rot = base_rot;
+ Vector3 scale = base_scale;
- if (!track.rotation_track.values.size()) {
- base_rot = state.nodes[E->key()]->rotation.normalized();
+ if (track.translation_track.times.size()) {
+ pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
}
- if (!track.translation_track.values.size()) {
- base_pos = state.nodes[E->key()]->translation;
+ if (track.rotation_track.times.size()) {
+ rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
}
- if (!track.scale_track.values.size()) {
- base_scale = state.nodes[E->key()]->scale;
+ if (track.scale_track.times.size()) {
+ scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
}
- bool last = false;
- while (true) {
-
- Vector3 pos = base_pos;
- Quat rot = base_rot;
- Vector3 scale = base_scale;
-
- if (track.translation_track.times.size()) {
+ if (node->skeleton >= 0) {
- pos = _interpolate_track<Vector3>(track.translation_track.times, track.translation_track.values, time, track.translation_track.interpolation);
- }
-
- if (track.rotation_track.times.size()) {
-
- rot = _interpolate_track<Quat>(track.rotation_track.times, track.rotation_track.values, time, track.rotation_track.interpolation);
- }
+ Transform xform;
+ xform.basis.set_quat_scale(rot, scale);
+ xform.origin = pos;
- if (track.scale_track.times.size()) {
+ const Skeleton *skeleton = state.skeletons[node->skeleton].godot_skeleton;
+ const int bone_idx = skeleton->find_bone(node->name);
+ xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform;
- scale = _interpolate_track<Vector3>(track.scale_track.times, track.scale_track.values, time, track.scale_track.interpolation);
- }
+ rot = xform.basis.get_rotation_quat();
+ rot.normalize();
+ scale = xform.basis.get_scale();
+ pos = xform.origin;
+ }
- if (node->joints.size()) {
+ animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
- Transform xform;
- //xform.basis = Basis(rot);
- //xform.basis.scale(scale);
- xform.basis.set_quat_scale(rot, scale);
- xform.origin = pos;
+ if (last) {
+ break;
+ }
+ time += increment;
+ if (time >= length) {
+ last = true;
+ time = length;
+ }
+ }
+ }
- Skeleton *skeleton = skeletons[node->joints[n].skin];
- int bone = node->joints[n].godot_bone_index;
- xform = skeleton->get_bone_rest(bone).affine_inverse() * xform;
+ for (int i = 0; i < track.weight_tracks.size(); i++) {
+ ERR_CONTINUE(node->mesh < 0 || node->mesh >= state.meshes.size());
+ const GLTFMesh &mesh = state.meshes[node->mesh];
+ const String prop = "blend_shapes/" + mesh.mesh->get_blend_shape_name(i);
- rot = xform.basis.get_rotation_quat();
- rot.normalize();
- scale = xform.basis.get_scale();
- pos = xform.origin;
- }
+ const String blend_path = String(node_path) + ":" + prop;
- animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
+ const int track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_VALUE);
+ animation->track_set_path(track_idx, blend_path);
+ // Only LINEAR and STEP (NEAREST) can be supported out of the box by Godot's Animation,
+ // the other modes have to be baked.
+ GLTFAnimation::Interpolation gltf_interp = track.weight_tracks[i].interpolation;
+ if (gltf_interp == GLTFAnimation::INTERP_LINEAR || gltf_interp == GLTFAnimation::INTERP_STEP) {
+ animation->track_set_interpolation_type(track_idx, gltf_interp == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_LINEAR);
+ for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
+ const float t = track.weight_tracks[i].times[j];
+ const float w = track.weight_tracks[i].values[j];
+ animation->track_insert_key(track_idx, t, w);
+ }
+ } else {
+ // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
+ const float increment = 1.0 / float(bake_fps);
+ float time = 0.0;
+ bool last = false;
+ while (true) {
+ _interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
if (last) {
break;
}
@@ -2079,86 +2850,54 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye
}
}
}
-
- for (int i = 0; i < track.weight_tracks.size(); i++) {
- ERR_CONTINUE(node->mesh < 0 || node->mesh >= state.meshes.size());
- const GLTFMesh &mesh = state.meshes[node->mesh];
- String prop = "blend_shapes/" + mesh.mesh->get_blend_shape_name(i);
- node_path = String(node_path) + ":" + prop;
-
- int track_idx = animation->get_track_count();
- animation->add_track(Animation::TYPE_VALUE);
- animation->track_set_path(track_idx, node_path);
-
- // Only LINEAR and STEP (NEAREST) can be supported out of the box by Godot's Animation,
- // the other modes have to be baked.
- GLTFAnimation::Interpolation gltf_interp = track.weight_tracks[i].interpolation;
- if (gltf_interp == GLTFAnimation::INTERP_LINEAR || gltf_interp == GLTFAnimation::INTERP_STEP) {
- animation->track_set_interpolation_type(track_idx, gltf_interp == GLTFAnimation::INTERP_STEP ? Animation::INTERPOLATION_NEAREST : Animation::INTERPOLATION_LINEAR);
- for (int j = 0; j < track.weight_tracks[i].times.size(); j++) {
- float t = track.weight_tracks[i].times[j];
- float w = track.weight_tracks[i].values[j];
- animation->track_insert_key(track_idx, t, w);
- }
- } else {
- // CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
- float increment = 1.0 / float(bake_fps);
- float time = 0.0;
- bool last = false;
- while (true) {
- _interpolate_track<float>(track.weight_tracks[i].times, track.weight_tracks[i].values, time, gltf_interp);
- if (last) {
- break;
- }
- time += increment;
- if (time >= length) {
- last = true;
- time = length;
- }
- }
- }
- }
}
}
+
animation->set_length(length);
ap->add_animation(name, animation);
}
-Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_fps) {
+void EditorSceneImporterGLTF::_process_mesh_instances(GLTFState &state, Spatial *scene_root) {
+ for (GLTFNodeIndex node_i = 0; node_i < state.nodes.size(); ++node_i) {
+ const GLTFNode *node = state.nodes[node_i];
- Spatial *root = memnew(Spatial);
- root->set_name(state.scene_name);
- //generate skeletons
- Vector<Skeleton *> skeletons;
- for (int i = 0; i < state.skins.size(); i++) {
- Skeleton *s = memnew(Skeleton);
- s->set_use_bones_in_world_transform(false); //GLTF does not need this since meshes are always local
- String name = state.skins[i].name;
- if (name == "") {
- name = _gen_unique_name(state, "Skeleton");
- }
- for (int j = 0; j < state.skins[i].bones.size(); j++) {
- s->add_bone(state.nodes[state.skins[i].bones[j].node]->name);
- s->set_bone_rest(j, state.skins[i].bones[j].inverse_bind.affine_inverse());
- }
- s->set_name(name);
- root->add_child(s);
- s->set_owner(root);
- skeletons.push_back(s);
- }
- for (int i = 0; i < state.root_nodes.size(); i++) {
- if (state.nodes[state.root_nodes[i]]->joints.size()) {
- _generate_bone(state, state.root_nodes[i], skeletons, root);
- } else {
- _generate_node(state, state.root_nodes[i], root, root, skeletons);
+ if (node->skin >= 0 && node->mesh >= 0) {
+ const GLTFSkinIndex skin_i = node->skin;
+
+ Map<GLTFNodeIndex, Node *>::Element *mi_element = state.scene_nodes.find(node_i);
+ MeshInstance *mi = Object::cast_to<MeshInstance>(mi_element->get());
+ ERR_FAIL_COND(mi == nullptr);
+
+ const GLTFSkeletonIndex skel_i = state.skins[node->skin].skeleton;
+ const GLTFSkeleton &gltf_skeleton = state.skeletons[skel_i];
+ Skeleton *skeleton = gltf_skeleton.godot_skeleton;
+ ERR_FAIL_COND(skeleton == nullptr);
+
+ mi->get_parent()->remove_child(mi);
+ skeleton->add_child(mi);
+ mi->set_owner(scene_root);
+
+ mi->set_skin(state.skins[skin_i].godot_skin);
+ mi->set_skeleton_path(mi->get_path_to(skeleton));
+ mi->set_transform(Transform());
}
}
+}
- for (int i = 0; i < skeletons.size(); i++) {
- skeletons[i]->localize_rests();
+Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, const int p_bake_fps) {
+
+ Spatial *root = memnew(Spatial);
+
+ // scene_name is already unique
+ root->set_name(state.scene_name);
+
+ for (int i = 0; i < state.root_nodes.size(); ++i) {
+ _generate_scene_node(state, root, root, state.root_nodes[i]);
}
+ _process_mesh_instances(state, root);
+
if (state.animations.size()) {
AnimationPlayer *ap = memnew(AnimationPlayer);
ap->set_name("AnimationPlayer");
@@ -2166,7 +2905,7 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_f
ap->set_owner(root);
for (int i = 0; i < state.animations.size(); i++) {
- _import_animation(state, ap, i, p_bake_fps, skeletons);
+ _import_animation(state, ap, i, p_bake_fps);
}
}
@@ -2241,30 +2980,45 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla
if (err != OK)
return NULL;
- /* STEP 8 PARSE MESHES (we have enough info now) */
- err = _parse_meshes(state);
+ /* STEP 9 PARSE SKINS */
+ err = _parse_skins(state);
if (err != OK)
return NULL;
- /* STEP 9 PARSE SKINS */
- err = _parse_skins(state);
+ /* STEP 10 DETERMINE SKELETONS */
+ err = _determine_skeletons(state);
+ if (err != OK)
+ return NULL;
+
+ /* STEP 11 CREATE SKELETONS */
+ err = _create_skeletons(state);
+ if (err != OK)
+ return NULL;
+
+ /* STEP 12 CREATE SKINS */
+ err = _create_skins(state);
+ if (err != OK)
+ return NULL;
+
+ /* STEP 13 PARSE MESHES (we have enough info now) */
+ err = _parse_meshes(state);
if (err != OK)
return NULL;
- /* STEP 10 PARSE CAMERAS */
+ /* STEP 14 PARSE CAMERAS */
err = _parse_cameras(state);
if (err != OK)
return NULL;
- /* STEP 11 PARSE ANIMATIONS */
+ /* STEP 15 PARSE ANIMATIONS */
err = _parse_animations(state);
if (err != OK)
return NULL;
- /* STEP 12 ASSIGN SCENE NAMES */
+ /* STEP 16 ASSIGN SCENE NAMES */
_assign_scene_names(state);
- /* STEP 13 MAKE SCENE! */
+ /* STEP 17 MAKE SCENE! */
Spatial *scene = _generate_scene(state, p_bake_fps);
return scene;
diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h
index ebf20e122a..6021bf10c8 100644
--- a/editor/import/editor_scene_importer_gltf.h
+++ b/editor/import/editor_scene_importer_gltf.h
@@ -36,11 +36,26 @@
#include "scene/3d/spatial.h"
class AnimationPlayer;
+class BoneAttachment;
+class MeshInstance;
class EditorSceneImporterGLTF : public EditorSceneImporter {
GDCLASS(EditorSceneImporterGLTF, EditorSceneImporter);
+ typedef int GLTFAccessorIndex;
+ typedef int GLTFAnimationIndex;
+ typedef int GLTFBufferIndex;
+ typedef int GLTFBufferViewIndex;
+ typedef int GLTFCameraIndex;
+ typedef int GLTFImageIndex;
+ typedef int GLTFMaterialIndex;
+ typedef int GLTFMeshIndex;
+ typedef int GLTFNodeIndex;
+ typedef int GLTFSkeletonIndex;
+ typedef int GLTFSkinIndex;
+ typedef int GLTFTextureIndex;
+
enum {
ARRAY_BUFFER = 34962,
ELEMENT_ARRAY_BUFFER = 34963,
@@ -61,8 +76,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
};
- String _get_component_type_name(uint32_t p_component);
- int _get_component_type_size(int component_type);
+ String _get_component_type_name(const uint32_t p_component);
+ int _get_component_type_size(const int component_type);
enum GLTFType {
TYPE_SCALAR,
@@ -74,60 +89,48 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
TYPE_MAT4,
};
- String _get_type_name(GLTFType p_component);
+ String _get_type_name(const GLTFType p_component);
struct GLTFNode {
+
//matrices need to be transformed to this
- int parent;
+ GLTFNodeIndex parent;
+ int height;
Transform xform;
String name;
- //Node *godot_node;
- //int godot_bone_index;
-
- int mesh;
- int camera;
- int skin;
- //int skeleton_skin;
- //int child_of_skeleton; // put as children of skeleton
- //Vector<int> skeleton_children; //skeleton put as children of this
-
- struct Joint {
- int skin;
- int bone;
- int godot_bone_index;
-
- Joint() {
- skin = -1;
- bone = -1;
- godot_bone_index = -1;
- }
- };
- Vector<Joint> joints;
+ GLTFMeshIndex mesh;
+ GLTFCameraIndex camera;
+ GLTFSkinIndex skin;
+
+ GLTFSkeletonIndex skeleton;
+ bool joint;
- //keep them for animation
Vector3 translation;
Quat rotation;
Vector3 scale;
Vector<int> children;
- Vector<Node *> godot_nodes;
+
+ GLTFNodeIndex fake_joint_parent;
GLTFNode() :
parent(-1),
+ height(-1),
mesh(-1),
camera(-1),
skin(-1),
- //skeleton_skin(-1),
- //child_of_skeleton(-1),
- scale(Vector3(1, 1, 1)) {
- }
+ skeleton(-1),
+ joint(false),
+ translation(0, 0, 0),
+ scale(Vector3(1, 1, 1)),
+ fake_joint_parent(-1) {}
};
struct GLTFBufferView {
- int buffer;
+ GLTFBufferIndex buffer;
int byte_offset;
int byte_length;
int byte_stride;
@@ -135,7 +138,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
//matrices need to be transformed to this
GLTFBufferView() :
- buffer(0),
+ buffer(-1),
byte_offset(0),
byte_length(0),
byte_stride(0),
@@ -145,7 +148,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
struct GLTFAccessor {
- int buffer_view;
+ GLTFBufferViewIndex buffer_view;
int byte_offset;
int component_type;
bool normalized;
@@ -160,8 +163,6 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
int sparse_values_buffer_view;
int sparse_values_byte_offset;
- //matrices need to be transformed to this
-
GLTFAccessor() {
buffer_view = 0;
byte_offset = 0;
@@ -176,27 +177,67 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
}
};
struct GLTFTexture {
- int src_image;
+ GLTFImageIndex src_image;
};
- struct GLTFSkin {
+ struct GLTFSkeleton {
+ // The *synthesized* skeletons joints
+ Vector<GLTFNodeIndex> joints;
- String name;
- struct Bone {
- Transform inverse_bind;
- int node;
- };
+ // The roots of the skeleton. If there are multiple, each root must have the same parent
+ // (ie roots are siblings)
+ Vector<GLTFNodeIndex> roots;
- int skeleton;
- Vector<Bone> bones;
+ // The created Skeleton for the scene
+ Skeleton *godot_skeleton;
- //matrices need to be transformed to this
+ // Set of unique bone names for the skeleton
+ Set<String> unique_names;
- GLTFSkin() {
- skeleton = -1;
+ GLTFSkeleton() :
+ godot_skeleton(nullptr) {
}
};
+ struct GLTFSkin {
+ String name;
+
+ // The "skeleton" property defined in the gltf spec. -1 = Scene Root
+ GLTFNodeIndex skin_root;
+
+ Vector<GLTFNodeIndex> joints_original;
+ Vector<Transform> inverse_binds;
+
+ // Note: joints + non_joints should form a complete subtree, or subtrees with a common parent
+
+ // All nodes that are skins that are caught in-between the original joints
+ // (inclusive of joints_original)
+ Vector<GLTFNodeIndex> joints;
+
+ // All Nodes that are caught in-between skin joint nodes, and are not defined
+ // as joints by any skin
+ Vector<GLTFNodeIndex> non_joints;
+
+ // The roots of the skin. In the case of multiple roots, their parent *must*
+ // be the same (the roots must be siblings)
+ Vector<GLTFNodeIndex> roots;
+
+ // The GLTF Skeleton this Skin points to (after we determine skeletons)
+ GLTFSkeletonIndex skeleton;
+
+ // A mapping from the joint indices (in the order of joints_original) to the
+ // Godot Skeleton's bone_indices
+ Map<int, int> joint_i_to_bone_i;
+
+ // The Actual Skin that will be created as a mapping between the IBM's of this skin
+ // to the generated skeleton for the mesh instances.
+ Ref<Skin> godot_skin;
+
+ GLTFSkin() :
+ skin_root(-1),
+ skeleton(-1) {}
+ };
+
struct GLTFMesh {
Ref<ArrayMesh> mesh;
Vector<float> blend_weights;
@@ -272,11 +313,10 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Set<String> unique_names;
+ Vector<GLTFSkeleton> skeletons;
Vector<GLTFAnimation> animations;
- Map<int, Vector<int> > skeleton_nodes;
-
- //Map<int, Vector<int> > skin_users; //cache skin users
+ Map<GLTFNodeIndex, Node *> scene_nodes;
~GLTFState() {
for (int i = 0; i < nodes.size(); i++) {
@@ -285,37 +325,38 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
}
};
+ String _sanitize_scene_name(const String &name);
String _gen_unique_name(GLTFState &state, const String &p_name);
- Ref<Texture> _get_texture(GLTFState &state, int p_texture);
+ String _sanitize_bone_name(const String &name);
+ String _gen_unique_bone_name(GLTFState &state, const GLTFSkeletonIndex skel_i, const String &p_name);
+
+ Ref<Texture> _get_texture(GLTFState &state, const GLTFTextureIndex p_texture);
Error _parse_json(const String &p_path, GLTFState &state);
Error _parse_glb(const String &p_path, GLTFState &state);
Error _parse_scenes(GLTFState &state);
Error _parse_nodes(GLTFState &state);
+
+ void _compute_node_heights(GLTFState &state);
+
Error _parse_buffers(GLTFState &state, const String &p_base_path);
Error _parse_buffer_views(GLTFState &state);
GLTFType _get_type_from_str(const String &p_string);
Error _parse_accessors(GLTFState &state);
- Error _decode_buffer_view(GLTFState &state, int p_buffer_view, double *dst, int skip_every, int skip_bytes, int element_size, int count, GLTFType type, int component_count, int component_type, int component_size, bool normalized, int byte_offset, bool for_vertex);
- Vector<double> _decode_accessor(GLTFState &state, int p_accessor, bool p_for_vertex);
- PoolVector<float> _decode_accessor_as_floats(GLTFState &state, int p_accessor, bool p_for_vertex);
- PoolVector<int> _decode_accessor_as_ints(GLTFState &state, int p_accessor, bool p_for_vertex);
- PoolVector<Vector2> _decode_accessor_as_vec2(GLTFState &state, int p_accessor, bool p_for_vertex);
- PoolVector<Vector3> _decode_accessor_as_vec3(GLTFState &state, int p_accessor, bool p_for_vertex);
- PoolVector<Color> _decode_accessor_as_color(GLTFState &state, int p_accessor, bool p_for_vertex);
- Vector<Quat> _decode_accessor_as_quat(GLTFState &state, int p_accessor, bool p_for_vertex);
- Vector<Transform2D> _decode_accessor_as_xform2d(GLTFState &state, int p_accessor, bool p_for_vertex);
- Vector<Basis> _decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex);
- Vector<Transform> _decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex);
-
- void _reparent_skeleton(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, Node *p_parent_node);
- void _generate_bone(GLTFState &state, int p_node, Vector<Skeleton *> &skeletons, Node *p_parent_node);
- void _generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector<Skeleton *> &skeletons);
- void _import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector<Skeleton *> skeletons);
-
- Spatial *_generate_scene(GLTFState &state, int p_bake_fps);
+ Error _decode_buffer_view(GLTFState &state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex);
+
+ Vector<double> _decode_accessor(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ PoolVector<float> _decode_accessor_as_floats(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ PoolVector<int> _decode_accessor_as_ints(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ PoolVector<Vector2> _decode_accessor_as_vec2(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ PoolVector<Vector3> _decode_accessor_as_vec3(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ PoolVector<Color> _decode_accessor_as_color(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ Vector<Quat> _decode_accessor_as_quat(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ Vector<Transform2D> _decode_accessor_as_xform2d(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ Vector<Basis> _decode_accessor_as_basis(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
+ Vector<Transform> _decode_accessor_as_xform(GLTFState &state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex);
Error _parse_meshes(GLTFState &state);
Error _parse_images(GLTFState &state, const String &p_base_path);
@@ -323,16 +364,46 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
Error _parse_materials(GLTFState &state);
+ GLTFNodeIndex _find_highest_node(GLTFState &state, const Vector<GLTFNodeIndex> &subset);
+
+ bool _capture_nodes_in_skin(GLTFState &state, GLTFSkin &skin, const GLTFNodeIndex node_index);
+ void _capture_nodes_for_multirooted_skin(GLTFState &state, GLTFSkin &skin);
+ Error _expand_skin(GLTFState &state, GLTFSkin &skin);
+ Error _verify_skin(GLTFState &state, GLTFSkin &skin);
Error _parse_skins(GLTFState &state);
+ Error _determine_skeletons(GLTFState &state);
+ Error _reparent_non_joint_skeleton_subtrees(GLTFState &state, GLTFSkeleton &skeleton, const Vector<GLTFNodeIndex> &non_joints);
+ Error _reparent_to_fake_joint(GLTFState &state, GLTFSkeleton &skeleton, const GLTFNodeIndex node_index);
+ Error _determine_skeleton_roots(GLTFState &state, const GLTFSkeletonIndex skel_i);
+
+ Error _create_skeletons(GLTFState &state);
+ Error _map_skin_joints_indices_to_skeleton_bone_indices(GLTFState &state);
+
+ Error _create_skins(GLTFState &state);
+ bool _skins_are_same(const Ref<Skin> &skin_a, const Ref<Skin> &skin_b);
+ void _remove_duplicate_skins(GLTFState &state);
+
Error _parse_cameras(GLTFState &state);
Error _parse_animations(GLTFState &state);
+ BoneAttachment *_generate_bone_attachment(GLTFState &state, Skeleton *skeleton, const GLTFNodeIndex node_index);
+ MeshInstance *_generate_mesh_instance(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
+ Camera *_generate_camera(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
+ Spatial *_generate_spatial(GLTFState &state, Node *scene_parent, const GLTFNodeIndex node_index);
+
+ void _generate_scene_node(GLTFState &state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index);
+ Spatial *_generate_scene(GLTFState &state, const int p_bake_fps);
+
+ void _process_mesh_instances(GLTFState &state, Spatial *scene_root);
+
void _assign_scene_names(GLTFState &state);
template <class T>
- T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, GLTFAnimation::Interpolation p_interp);
+ T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp);
+
+ void _import_animation(GLTFState &state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps);
public:
virtual uint32_t get_import_flags() const;
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 64994e21b0..b111750992 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1178,7 +1178,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "animation/filter_script", PROPERTY_HINT_MULTILINE_TEXT), ""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.anim),Files (.tres)"), animations_out ? true : false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "animation/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.anim),Files (.tres)"), animations_out));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/keep_custom_tracks"), animations_out));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/optimizer/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/optimizer/max_linear_error"), 0.05));
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 6918fe7977..1d72e370b3 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -132,6 +132,7 @@ void ImportDock::set_edit_path(const String &p_path) {
params->paths.push_back(p_path);
import->set_disabled(false);
import_as->set_disabled(false);
+ preset->set_disabled(false);
imported->set_text(p_path.get_file());
}
@@ -287,6 +288,7 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
params->paths = p_paths;
import->set_disabled(false);
import_as->set_disabled(false);
+ preset->set_disabled(false);
imported->set_text(itos(p_paths.size()) + TTR(" Files"));
}
@@ -367,6 +369,7 @@ void ImportDock::clear() {
import->set_disabled(true);
import_as->clear();
import_as->set_disabled(true);
+ preset->set_disabled(true);
params->values.clear();
params->properties.clear();
params->update();
@@ -528,11 +531,13 @@ ImportDock::ImportDock() {
HBoxContainer *hb = memnew(HBoxContainer);
add_margin_child(TTR("Import As:"), hb);
import_as = memnew(OptionButton);
+ import_as->set_disabled(true);
import_as->connect("item_selected", this, "_importer_selected");
hb->add_child(import_as);
import_as->set_h_size_flags(SIZE_EXPAND_FILL);
preset = memnew(MenuButton);
- preset->set_text(TTR("Preset..."));
+ preset->set_text(TTR("Preset"));
+ preset->set_disabled(true);
preset->get_popup()->connect("index_pressed", this, "_preset_selected");
hb->add_child(preset);
@@ -545,6 +550,7 @@ ImportDock::ImportDock() {
add_child(hb);
import = memnew(Button);
import->set_text(TTR("Reimport"));
+ import->set_disabled(true);
import->connect("pressed", this, "_reimport_attempt");
hb->add_spacer();
hb->add_child(import);
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 173079b6de..d7451849a1 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -38,7 +38,7 @@
#include "editor/animation_track_editor.h"
#include "editor/editor_settings.h"
-// For onion skinning
+// For onion skinning.
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "scene/main/viewport.h"
@@ -690,8 +690,10 @@ void AnimationPlayerEditor::set_state(const Dictionary &p_state) {
if (p_state.has("animation")) {
String anim = p_state["animation"];
- _select_anim_by_name(anim);
- _animation_edit();
+ if (!anim.empty() && player->has_animation(anim)) {
+ _select_anim_by_name(anim);
+ _animation_edit();
+ }
}
}
}
@@ -1088,20 +1090,6 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag)
EditorNode::get_singleton()->get_inspector()->refresh();
}
-void AnimationPlayerEditor::_hide_anim_editors() {
-
- player = NULL;
- hide();
- set_process(false);
-
- track_editor->set_animation(Ref<Animation>());
- track_editor->set_root(NULL);
- track_editor->show_select_node_warning(true);
-}
-
-void AnimationPlayerEditor::_animation_about_to_show_menu() {
-}
-
void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
String current;
@@ -1489,7 +1477,7 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() {
player->seek(cpos, false);
player->restore_animated_values(values_backup);
- // Restor state of main editors.
+ // Restore state of main editors.
if (SpatialEditor::get_singleton()->is_visible()) {
// 3D
SpatialEditor::get_singleton()->set_state(spatial_edit_state);
@@ -1519,7 +1507,7 @@ void AnimationPlayerEditor::_stop_onion_skinning() {
_free_onion_layers();
- // Clean up the overlay
+ // Clean up the overlay.
onion.can_overlay = false;
plugin->update_overlays();
}
@@ -1557,7 +1545,6 @@ void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_list_changed"), &AnimationPlayerEditor::_list_changed);
ClassDB::bind_method(D_METHOD("_animation_key_editor_seek"), &AnimationPlayerEditor::_animation_key_editor_seek);
ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_len_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
- ClassDB::bind_method(D_METHOD("_hide_anim_editors"), &AnimationPlayerEditor::_hide_anim_editors);
ClassDB::bind_method(D_METHOD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate);
ClassDB::bind_method(D_METHOD("_blend_editor_next_changed"), &AnimationPlayerEditor::_blend_editor_next_changed);
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &AnimationPlayerEditor::_unhandled_key_input);
@@ -1776,7 +1763,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay
_update_player();
- // Onion skinning
+ // Onion skinning.
track_editor->connect("visibility_changed", this, "_editor_visibility_changed");
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 4ad30675ec..eed7344395 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -130,9 +130,9 @@ class AnimationPlayerEditor : public VBoxContainer {
AnimationTrackEditor *track_editor;
- // Onion skinning
+ // Onion skinning.
struct {
- // Settings
+ // Settings.
bool enabled;
bool past;
bool future;
@@ -142,11 +142,11 @@ class AnimationPlayerEditor : public VBoxContainer {
bool include_gizmos;
int get_needed_capture_count() const {
- // 'Differences only' needs a capture of the present
+ // 'Differences only' needs a capture of the present.
return (past && future ? 2 * steps : steps) + (differences_only ? 1 : 0);
}
- // Rendering
+ // Rendering.
int64_t last_frame;
int can_overlay;
Size2 capture_size;
@@ -195,8 +195,6 @@ class AnimationPlayerEditor : public VBoxContainer {
void _update_player();
void _blend_edited();
- void _hide_anim_editors();
-
void _animation_player_changed(Object *p_pl);
void _animation_key_editor_seek(float p_pos, bool p_drag);
@@ -205,7 +203,6 @@ class AnimationPlayerEditor : public VBoxContainer {
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
void _animation_tool_menu(int p_option);
void _onion_skinning_menu(int p_option);
- void _animation_about_to_show_menu();
void _editor_visibility_changed();
bool _are_onion_layers_valid();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index e4cd71fec0..6f612b5c79 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -3678,7 +3678,6 @@ void CanvasItemEditor::_notification(int p_what) {
key_auto_insert_button->set_icon(get_icon("AutoKey", "EditorIcons"));
zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
- zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
presets_menu->set_icon(get_icon("ControlLayout", "EditorIcons"));
@@ -4036,9 +4035,22 @@ void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) {
view_offset.x = Math::round(view_offset.x + ofs.x);
view_offset.y = Math::round(view_offset.y + ofs.y);
+ _update_zoom_label();
update_viewport();
}
+void CanvasItemEditor::_update_zoom_label() {
+ String zoom_text;
+ if (zoom >= 10) {
+ // Don't show a decimal when the zoom level is higher than 1000 %
+ zoom_text = rtos(Math::round(zoom * 100)) + " %";
+ } else {
+ zoom_text = rtos(Math::stepify(zoom * 100, 0.1)) + " %";
+ }
+
+ zoom_reset->set_text(zoom_text);
+}
+
void CanvasItemEditor::_button_zoom_minus() {
_zoom_on_position(zoom / Math_SQRT2, viewport_scrollable->get_size() / 2.0);
}
@@ -4811,6 +4823,7 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
Dictionary state = p_state;
if (state.has("zoom")) {
zoom = p_state["zoom"];
+ _update_zoom_label();
}
if (state.has("ofs")) {
@@ -5128,6 +5141,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
zoom_hb = memnew(HBoxContainer);
viewport->add_child(zoom_hb);
zoom_hb->set_begin(Point2(5, 5));
+ // Bring the zoom percentage closer to the zoom buttons
+ zoom_hb->add_constant_override("separation", Math::round(-8 * EDSCALE));
zoom_minus = memnew(ToolButton);
zoom_hb->add_child(zoom_minus);
@@ -5140,6 +5155,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
zoom_reset->connect("pressed", this, "_button_zoom_reset");
zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0));
zoom_reset->set_focus_mode(FOCUS_NONE);
+ zoom_reset->set_text_align(Button::TextAlign::ALIGN_CENTER);
+ // Prevent the button's size from changing when the text size changes
+ zoom_reset->set_custom_minimum_size(Size2(75 * EDSCALE, 0));
zoom_plus = memnew(ToolButton);
zoom_hb->add_child(zoom_plus);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 4e030c63da..6cce1ca10e 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -525,6 +525,7 @@ private:
HBoxContainer *zoom_hb;
void _zoom_on_position(float p_zoom, Point2 p_position = Point2());
+ void _update_zoom_label();
void _button_zoom_minus();
void _button_zoom_reset();
void _button_zoom_plus();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 8b6bab374c..4c22138a20 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -538,9 +538,13 @@ void ScriptEditor::_open_recent_script(int p_idx) {
// if it's a path then it's most likely a deleted file not help
} else if (path.find("::") != -1) {
// built-in script
- String scene_path = path.get_slice("::", 0);
- if (!EditorNode::get_singleton()->is_scene_open(scene_path)) {
- EditorNode::get_singleton()->load_scene(scene_path);
+ String res_path = path.get_slice("::", 0);
+ if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
+ if (!EditorNode::get_singleton()->is_scene_open(res_path)) {
+ EditorNode::get_singleton()->load_scene(res_path);
+ }
+ } else {
+ EditorNode::get_singleton()->load_resource(res_path);
}
Ref<Script> script = ResourceLoader::load(path);
if (script.is_valid()) {
@@ -1028,12 +1032,16 @@ void ScriptEditor::_menu_option(int p_option) {
if (extensions.find(path.get_extension()) || built_in) {
if (built_in) {
- String scene_path = path.get_slice("::", 0);
- if (!EditorNode::get_singleton()->is_scene_open(scene_path)) {
- EditorNode::get_singleton()->load_scene(scene_path);
- script_editor->call_deferred("_menu_option", p_option);
- previous_scripts.push_back(path); //repeat the operation
- return;
+ String res_path = path.get_slice("::", 0);
+ if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
+ if (!EditorNode::get_singleton()->is_scene_open(res_path)) {
+ EditorNode::get_singleton()->load_scene(res_path);
+ script_editor->call_deferred("_menu_option", p_option);
+ previous_scripts.push_back(path); //repeat the operation
+ return;
+ }
+ } else {
+ EditorNode::get_singleton()->load_resource(res_path);
}
}
@@ -3300,8 +3308,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
debug_menu->set_text(TTR("Debug"));
debug_menu->set_switch_on_hover(true);
debug_menu->get_popup()->set_hide_on_window_lose_focus(true);
- debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10), DEBUG_NEXT);
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11), DEBUG_STEP);
+ debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10), DEBUG_NEXT);
debug_menu->get_popup()->add_separator();
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/break", TTR("Break")), DEBUG_BREAK);
debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/continue", TTR("Continue"), KEY_F12), DEBUG_CONTINUE);
@@ -3463,15 +3471,18 @@ void ScriptEditorPlugin::edit(Object *p_object) {
if (Object::cast_to<Script>(p_object)) {
Script *p_script = Object::cast_to<Script>(p_object);
- String scene_path = p_script->get_path().get_slice("::", 0);
+ String res_path = p_script->get_path().get_slice("::", 0);
- if (_is_built_in_script(p_script) && !EditorNode::get_singleton()->is_scene_open(scene_path)) {
- EditorNode::get_singleton()->load_scene(scene_path);
-
- script_editor->call_deferred("edit", p_script);
- } else {
- script_editor->edit(p_script);
+ if (_is_built_in_script(p_script)) {
+ if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
+ if (!EditorNode::get_singleton()->is_scene_open(res_path)) {
+ EditorNode::get_singleton()->load_scene(res_path);
+ }
+ } else {
+ EditorNode::get_singleton()->load_resource(res_path);
+ }
}
+ script_editor->edit(p_script);
} else if (Object::cast_to<TextFile>(p_object)) {
script_editor->edit(Object::cast_to<TextFile>(p_object));
}
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 3b300a7ad5..073e6f74e9 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1532,93 +1532,98 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
Ref<InputEventMouseButton> mb = ev;
+ Ref<InputEventKey> k = ev;
+ Point2 local_pos;
+ bool create_menu = false;
- if (mb.is_valid()) {
-
- if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
- int col, row;
- TextEdit *tx = code_editor->get_text_edit();
- tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
- Vector2 mpos = mb->get_global_position() - tx->get_global_position();
-
- tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
- if (tx->is_right_click_moving_caret()) {
- if (tx->is_selection_active()) {
+ TextEdit *tx = code_editor->get_text_edit();
+ if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
+ local_pos = mb->get_global_position() - tx->get_global_position();
+ create_menu = true;
+ } else if (k.is_valid() && k->get_scancode() == KEY_MENU) {
+ local_pos = tx->_get_cursor_pixel_pos();
+ create_menu = true;
+ }
- int from_line = tx->get_selection_from_line();
- int to_line = tx->get_selection_to_line();
- int from_column = tx->get_selection_from_column();
- int to_column = tx->get_selection_to_column();
+ if (create_menu) {
+ int col, row;
+ tx->_get_mouse_pos(local_pos, row, col);
- if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
- // Right click is outside the selected text
- tx->deselect();
- }
- }
- if (!tx->is_selection_active()) {
- tx->cursor_set_line(row, true, false);
- tx->cursor_set_column(col);
+ tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+ if (tx->is_right_click_moving_caret()) {
+ if (tx->is_selection_active()) {
+ int from_line = tx->get_selection_from_line();
+ int to_line = tx->get_selection_to_line();
+ int from_column = tx->get_selection_from_column();
+ int to_column = tx->get_selection_to_column();
+
+ if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
+ // Right click is outside the selected text
+ tx->deselect();
}
}
+ if (!tx->is_selection_active()) {
+ tx->cursor_set_line(row, true, false);
+ tx->cursor_set_column(col);
+ }
+ }
- String word_at_mouse = tx->get_word_at_pos(mpos);
- if (word_at_mouse == "")
- word_at_mouse = tx->get_word_under_cursor();
- if (word_at_mouse == "")
- word_at_mouse = tx->get_selection_text();
+ String word_at_pos = tx->get_word_at_pos(local_pos);
+ if (word_at_pos == "")
+ word_at_pos = tx->get_word_under_cursor();
+ if (word_at_pos == "")
+ word_at_pos = tx->get_selection_text();
- bool has_color = (word_at_mouse == "Color");
- bool foldable = tx->can_fold(row) || tx->is_folded(row);
- bool open_docs = false;
- bool goto_definition = false;
+ bool has_color = (word_at_pos == "Color");
+ bool foldable = tx->can_fold(row) || tx->is_folded(row);
+ bool open_docs = false;
+ bool goto_definition = false;
- if (word_at_mouse.is_resource_file()) {
+ if (word_at_pos.is_resource_file()) {
+ open_docs = true;
+ } else {
+ Node *base = get_tree()->get_edited_scene_root();
+ if (base) {
+ base = _find_node_for_script(base, base, script);
+ }
+ ScriptLanguage::LookupResult result;
+ if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) {
open_docs = true;
- } else {
-
- Node *base = get_tree()->get_edited_scene_root();
- if (base) {
- base = _find_node_for_script(base, base, script);
- }
- ScriptLanguage::LookupResult result;
- if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_mouse, script->get_path(), base, result) == OK) {
- open_docs = true;
- }
}
+ }
- if (has_color) {
- String line = tx->get_line(row);
- color_position.x = row;
- color_position.y = col;
-
- int begin = 0;
- int end = 0;
- bool valid = false;
- for (int i = col; i < line.length(); i++) {
- if (line[i] == '(') {
- begin = i;
- continue;
- } else if (line[i] == ')') {
- end = i + 1;
- valid = true;
- break;
- }
+ if (has_color) {
+ String line = tx->get_line(row);
+ color_position.x = row;
+ color_position.y = col;
+
+ int begin = 0;
+ int end = 0;
+ bool valid = false;
+ for (int i = col; i < line.length(); i++) {
+ if (line[i] == '(') {
+ begin = i;
+ continue;
+ } else if (line[i] == ')') {
+ end = i + 1;
+ valid = true;
+ break;
}
- if (valid) {
- color_args = line.substr(begin, end - begin);
- String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
- if (color.size() > 2) {
- float alpha = color.size() > 3 ? color[3] : 1.0f;
- color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
- }
- color_panel->set_position(get_global_transform().xform(get_local_mouse_position()));
- } else {
- has_color = false;
+ }
+ if (valid) {
+ color_args = line.substr(begin, end - begin);
+ String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
+ Vector<float> color = stripped.split_floats(",");
+ if (color.size() > 2) {
+ float alpha = color.size() > 3 ? color[3] : 1.0f;
+ color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
}
+ color_panel->set_position(get_global_transform().xform(local_pos));
+ } else {
+ has_color = false;
}
- _make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition);
}
+ _make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition, local_pos);
}
}
@@ -1643,7 +1648,7 @@ void ScriptTextEditor::_color_changed(const Color &p_color) {
code_editor->get_text_edit()->update();
}
-void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition) {
+void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) {
context_menu->clear();
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
@@ -1680,7 +1685,7 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p
context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);
}
- context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_position(get_global_transform().xform(p_pos));
context_menu->set_size(Vector2(1, 1));
context_menu->popup();
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 38c6da5c33..0ea8726ecc 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -169,7 +169,7 @@ protected:
void _edit_option(int p_op);
void _edit_option_toggle_inline_comment();
- void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition);
+ void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos);
void _text_edit_gui_input(const Ref<InputEvent> &ev);
void _color_changed(const Color &p_color);
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index e81c97d5dd..df3e23a9e9 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -523,9 +523,16 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
tx->cursor_set_column(col);
}
}
- _make_context_menu(tx->is_selection_active());
+ _make_context_menu(tx->is_selection_active(), get_local_mouse_position());
}
}
+
+ Ref<InputEventKey> k = ev;
+ if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_MENU) {
+ TextEdit *tx = shader_editor->get_text_edit();
+ _make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
+ context_menu->grab_focus();
+ }
}
void ShaderEditor::_update_bookmark_list() {
@@ -565,7 +572,7 @@ void ShaderEditor::_bookmark_item_pressed(int p_idx) {
}
}
-void ShaderEditor::_make_context_menu(bool p_selection) {
+void ShaderEditor::_make_context_menu(bool p_selection, Vector2 p_position) {
context_menu->clear();
if (p_selection) {
@@ -585,7 +592,7 @@ void ShaderEditor::_make_context_menu(bool p_selection) {
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_bookmark"), BOOKMARK_TOGGLE);
- context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_position(get_global_transform().xform(p_position));
context_menu->set_size(Vector2(1, 1));
context_menu->popup();
}
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 8d3f4d4fe8..ca9f489713 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -122,7 +122,7 @@ class ShaderEditor : public PanelContainer {
protected:
void _notification(int p_what);
static void _bind_methods();
- void _make_context_menu(bool p_selection);
+ void _make_context_menu(bool p_selection, Vector2 p_position);
void _text_edit_gui_input(const Ref<InputEvent> &ev);
void _update_bookmark_list();
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index ecc631d045..18049e62b4 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -5186,7 +5186,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() {
// The maximum height an object can travel to be snapped
const float max_snap_height = 20.0;
- // Will be set to `true` if at least one node from the selection was sucessfully snapped
+ // Will be set to `true` if at least one node from the selection was successfully snapped
bool snapped_to_floor = false;
if (keys.size()) {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 728b67f6fa..aa61f4bae1 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -58,6 +58,7 @@ public:
RID instance;
Ref<ArrayMesh> mesh;
Ref<Material> material;
+ Ref<SkinReference> skin_reference;
RID skeleton;
bool billboard;
bool unscaled;
@@ -101,7 +102,7 @@ protected:
public:
void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false);
- void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const RID &p_skeleton = RID(), const Ref<Material> &p_material = Ref<Material>());
+ void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>());
void add_collision_segments(const Vector<Vector3> &p_lines);
void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1);
diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp
index 2deb2090e2..69fd592652 100644
--- a/editor/plugins/sprite_editor_plugin.cpp
+++ b/editor/plugins/sprite_editor_plugin.cpp
@@ -102,7 +102,7 @@ Vector<Vector2> expand(const Vector<Vector2> &points, const Rect2i &rect, float
int lasti = p2->Contour.size() - 1;
Vector2 prev = Vector2(p2->Contour[lasti].X / PRECISION, p2->Contour[lasti].Y / PRECISION);
- for (unsigned int i = 0; i < p2->Contour.size(); i++) {
+ for (uint64_t i = 0; i < p2->Contour.size(); i++) {
Vector2 cur = Vector2(p2->Contour[i].X / PRECISION, p2->Contour[i].Y / PRECISION);
if (cur.distance_to(prev) > 0.5) {
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index d91de6cbf6..394122d91d 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -464,9 +464,11 @@ void SpriteFramesEditor::_animation_select() {
if (updating)
return;
- double value = anim_speed->get_line_edit()->get_text().to_double();
- if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim)))
- _animation_fps_changed(value);
+ if (frames->has_animation(edited_anim)) {
+ double value = anim_speed->get_line_edit()->get_text().to_double();
+ if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim)))
+ _animation_fps_changed(value);
+ }
TreeItem *selected = animations->get_selected();
ERR_FAIL_COND(!selected);
@@ -548,6 +550,7 @@ void SpriteFramesEditor::_animation_name_edited() {
undo_redo->commit_action();
}
+
void SpriteFramesEditor::_animation_add() {
String name = "New Anim";
@@ -578,13 +581,21 @@ void SpriteFramesEditor::_animation_add() {
undo_redo->commit_action();
animations->grab_focus();
}
+
void SpriteFramesEditor::_animation_remove() {
+
if (updating)
return;
if (!frames->has_animation(edited_anim))
return;
+ delete_dialog->set_text(TTR("Delete Animation?"));
+ delete_dialog->popup_centered_minsize();
+}
+
+void SpriteFramesEditor::_animation_remove_confirmed() {
+
undo_redo->create_action(TTR("Remove Animation"));
undo_redo->add_do_method(frames, "remove_animation", edited_anim);
undo_redo->add_undo_method(frames, "add_animation", edited_anim);
@@ -598,6 +609,8 @@ void SpriteFramesEditor::_animation_remove() {
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
+ edited_anim = StringName();
+
undo_redo->commit_action();
}
@@ -743,7 +756,9 @@ Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f
if (frame.is_null())
return Variant();
- return EditorNode::get_singleton()->drag_resource(frame, p_from);
+ Dictionary drag_data = EditorNode::get_singleton()->drag_resource(frame, p_from);
+ drag_data["frame"] = idx; // store the frame, incase we want to reorder frames inside 'drop_data_fw'
+ return drag_data;
}
bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
@@ -753,8 +768,9 @@ bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &
if (!d.has("type"))
return false;
+ // reordering frames
if (d.has("from") && (Object *)(d["from"]) == tree)
- return false;
+ return true;
if (String(d["type"]) == "resource" && d.has("resource")) {
RES r = d["resource"];
@@ -806,13 +822,31 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
Ref<Texture> texture = r;
if (texture.is_valid()) {
-
- undo_redo->create_action(TTR("Add Frame"));
- undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos);
- undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
- undo_redo->add_do_method(this, "_update_library");
- undo_redo->add_undo_method(this, "_update_library");
- undo_redo->commit_action();
+ bool reorder = false;
+ if (d.has("from") && (Object *)(d["from"]) == tree)
+ reorder = true;
+
+ if (reorder) { //drop is from reordering frames
+ int from_frame = -1;
+ if (d.has("frame"))
+ from_frame = d["frame"];
+
+ undo_redo->create_action(TTR("Move Frame"));
+ undo_redo->add_do_method(frames, "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame);
+ undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos);
+ undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos);
+ undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, from_frame);
+ undo_redo->add_do_method(this, "_update_library");
+ undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
+ } else {
+ undo_redo->create_action(TTR("Add Frame"));
+ undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos);
+ undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
+ undo_redo->add_do_method(this, "_update_library");
+ undo_redo->add_undo_method(this, "_update_library");
+ undo_redo->commit_action();
+ }
}
}
@@ -840,6 +874,7 @@ void SpriteFramesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_animation_name_edited"), &SpriteFramesEditor::_animation_name_edited);
ClassDB::bind_method(D_METHOD("_animation_add"), &SpriteFramesEditor::_animation_add);
ClassDB::bind_method(D_METHOD("_animation_remove"), &SpriteFramesEditor::_animation_remove);
+ ClassDB::bind_method(D_METHOD("_animation_remove_confirmed"), &SpriteFramesEditor::_animation_remove_confirmed);
ClassDB::bind_method(D_METHOD("_animation_loop_changed"), &SpriteFramesEditor::_animation_loop_changed);
ClassDB::bind_method(D_METHOD("_animation_fps_changed"), &SpriteFramesEditor::_animation_fps_changed);
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw);
@@ -870,7 +905,6 @@ SpriteFramesEditor::SpriteFramesEditor() {
new_anim = memnew(ToolButton);
new_anim->set_tooltip(TTR("New Animation"));
hbc_animlist->add_child(new_anim);
- new_anim->set_h_size_flags(SIZE_EXPAND_FILL);
new_anim->connect("pressed", this, "_animation_add");
remove_anim = memnew(ToolButton);
@@ -926,7 +960,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
paste->set_tooltip(TTR("Paste"));
hbc->add_child(paste);
- hbc->add_spacer(false);
+ hbc->add_child(memnew(VSeparator));
empty = memnew(ToolButton);
empty->set_tooltip(TTR("Insert Empty (Before)"));
@@ -987,6 +1021,10 @@ SpriteFramesEditor::SpriteFramesEditor() {
edited_anim = "default";
+ delete_dialog = memnew(ConfirmationDialog);
+ add_child(delete_dialog);
+ delete_dialog->connect("confirmed", this, "_animation_remove_confirmed");
+
split_sheet_dialog = memnew(ConfirmationDialog);
add_child(split_sheet_dialog);
VBoxContainer *split_sheet_vb = memnew(VBoxContainer);
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index d64431cde7..f20b54f910 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -73,6 +73,8 @@ class SpriteFramesEditor : public HSplitContainer {
StringName edited_anim;
+ ConfirmationDialog *delete_dialog;
+
ConfirmationDialog *split_sheet_dialog;
ScrollContainer *splite_sheet_scroll;
TextureRect *split_sheet_preview;
@@ -98,6 +100,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _animation_name_edited();
void _animation_add();
void _animation_remove();
+ void _animation_remove_confirmed();
void _animation_loop_changed();
void _animation_fps_changed(double p_value);
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 89e419ede8..d0320bcd8b 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -30,6 +30,7 @@
#include "text_editor.h"
+#include "core/os/keyboard.h"
#include "editor_node.h"
void TextEditor::add_syntax_highlighter(SyntaxHighlighter *p_highlighter) {
@@ -577,13 +578,21 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
}
if (!mb->is_pressed()) {
- _make_context_menu(tx->is_selection_active(), can_fold, is_folded);
+ _make_context_menu(tx->is_selection_active(), can_fold, is_folded, get_local_mouse_position());
}
}
}
+
+ Ref<InputEventKey> k = ev;
+ if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_MENU) {
+ TextEdit *tx = code_editor->get_text_edit();
+ int line = tx->cursor_get_line();
+ _make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
+ context_menu->grab_focus();
+ }
}
-void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded) {
+void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position) {
context_menu->clear();
if (p_selection) {
@@ -609,7 +618,7 @@ void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is
if (p_can_fold || p_is_folded)
context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE);
- context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ context_menu->set_position(get_global_transform().xform(p_position));
context_menu->set_size(Vector2(1, 1));
context_menu->popup();
}
diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h
index c8b49a61e0..7d441a187d 100644
--- a/editor/plugins/text_editor.h
+++ b/editor/plugins/text_editor.h
@@ -101,7 +101,7 @@ protected:
void _notification(int p_what);
void _edit_option(int p_op);
- void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded);
+ void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position);
void _text_edit_gui_input(const Ref<InputEvent> &ev);
Map<String, SyntaxHighlighter *> highlighters;
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 4d349f06b7..21eebf9ca2 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -625,9 +625,12 @@ void TextureRegionEditor::_update_rect() {
rect = node_sprite->get_region_rect();
else if (node_sprite_3d)
rect = node_sprite_3d->get_region_rect();
- else if (node_ninepatch)
+ else if (node_ninepatch) {
rect = node_ninepatch->get_region_rect();
- else if (obj_styleBox.is_valid())
+ if (rect == Rect2()) {
+ rect = Rect2(Vector2(), node_ninepatch->get_texture()->get_size());
+ }
+ } else if (obj_styleBox.is_valid())
rect = obj_styleBox->get_region_rect();
else if (atlas_tex.is_valid())
rect = atlas_tex->get_region();
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 26fae96025..90276041a8 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -376,7 +376,7 @@ void TileMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
}
// Implementation detail of TileMapEditor::_update_palette();
-// in modern C++ this could have been inside its body
+// In modern C++ this could have been inside its body.
namespace {
struct _PaletteEntry {
int id;
@@ -393,10 +393,10 @@ void TileMapEditor::_update_palette() {
if (!node)
return;
- // Update the clear button
+ // Update the clear button.
clear_transform_button->set_disabled(!flip_h && !flip_v && !transpose);
- // Update the palette
+ // Update the palette.
Vector<int> selected = get_selected_tiles();
int selected_single = palette->get_current();
int selected_manual = manual_palette->get_current();
@@ -405,8 +405,15 @@ void TileMapEditor::_update_palette() {
manual_palette->hide();
Ref<TileSet> tileset = node->get_tileset();
- if (tileset.is_null())
+ if (tileset.is_null()) {
+ search_box->set_text("");
+ search_box->set_editable(false);
+ info_message->show();
return;
+ }
+
+ search_box->set_editable(true);
+ info_message->hide();
List<int> tiles;
tileset->get_tile_list(&tiles);
@@ -421,7 +428,6 @@ void TileMapEditor::_update_palette() {
bool sort_by_name = bool(EDITOR_DEF("editors/tile_map/sort_tiles_by_name", true));
palette->add_constant_override("hseparation", hseparation * EDSCALE);
- palette->add_constant_override("vseparation", 8 * EDSCALE);
palette->set_fixed_icon_size(Size2(min_size, min_size));
palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1));
@@ -479,7 +485,7 @@ void TileMapEditor::_update_palette() {
region.position += (region.size + Vector2(spacing, spacing)) * tileset->autotile_get_icon_coordinate(entries[i].id);
}
- // Transpose and flip
+ // Transpose and flip.
palette->set_item_icon_transposed(palette->get_item_count() - 1, transpose);
if (flip_h) {
region.size.x = -region.size.x;
@@ -488,14 +494,14 @@ void TileMapEditor::_update_palette() {
region.size.y = -region.size.y;
}
- // Set region
+ // Set region.
if (region.size != Size2())
palette->set_item_icon_region(palette->get_item_count() - 1, region);
- // Set icon
+ // Set icon.
palette->set_item_icon(palette->get_item_count() - 1, tex);
- // Modulation
+ // Modulation.
Color color = tileset->tile_get_modulate(entries[i].id);
palette->set_item_icon_modulate(palette->get_item_count() - 1, color);
}
@@ -511,50 +517,47 @@ void TileMapEditor::_update_palette() {
palette->select(0);
}
- if (sel_tile != TileMap::INVALID_CELL) {
- if ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) ||
- (!priority_atlastile && tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE)) {
+ if (sel_tile != TileMap::INVALID_CELL && ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || (!priority_atlastile && tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE))) {
- const Map<Vector2, uint32_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile);
+ const Map<Vector2, uint32_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile);
- Vector<Vector2> entries2;
- for (const Map<Vector2, uint32_t>::Element *E = tiles2.front(); E; E = E->next()) {
- entries2.push_back(E->key());
+ Vector<Vector2> entries2;
+ for (const Map<Vector2, uint32_t>::Element *E = tiles2.front(); E; E = E->next()) {
+ entries2.push_back(E->key());
+ }
+ // Sort tiles in row-major order.
+ struct SwapComparator {
+ _FORCE_INLINE_ bool operator()(const Vector2 &v_l, const Vector2 &v_r) const {
+ return v_l.y != v_r.y ? v_l.y < v_r.y : v_l.x < v_r.x;
}
- // Sort tiles in row-major order
- struct SwapComparator {
- _FORCE_INLINE_ bool operator()(const Vector2 &v_l, const Vector2 &v_r) const {
- return v_l.y != v_r.y ? v_l.y < v_r.y : v_l.x < v_r.x;
- }
- };
- entries2.sort_custom<SwapComparator>();
-
- Ref<Texture> tex = tileset->tile_get_texture(sel_tile);
+ };
+ entries2.sort_custom<SwapComparator>();
- for (int i = 0; i < entries2.size(); i++) {
+ Ref<Texture> tex = tileset->tile_get_texture(sel_tile);
- manual_palette->add_item(String());
+ for (int i = 0; i < entries2.size(); i++) {
- if (tex.is_valid()) {
+ manual_palette->add_item(String());
- Rect2 region = tileset->tile_get_region(sel_tile);
- int spacing = tileset->autotile_get_spacing(sel_tile);
- region.size = tileset->autotile_get_size(sel_tile); // !!
- region.position += (region.size + Vector2(spacing, spacing)) * entries2[i];
+ if (tex.is_valid()) {
- if (!region.has_no_area())
- manual_palette->set_item_icon_region(manual_palette->get_item_count() - 1, region);
+ Rect2 region = tileset->tile_get_region(sel_tile);
+ int spacing = tileset->autotile_get_spacing(sel_tile);
+ region.size = tileset->autotile_get_size(sel_tile); // !!
+ region.position += (region.size + Vector2(spacing, spacing)) * entries2[i];
- manual_palette->set_item_icon(manual_palette->get_item_count() - 1, tex);
- }
+ if (!region.has_no_area())
+ manual_palette->set_item_icon_region(manual_palette->get_item_count() - 1, region);
- manual_palette->set_item_metadata(manual_palette->get_item_count() - 1, entries2[i]);
+ manual_palette->set_item_icon(manual_palette->get_item_count() - 1, tex);
}
+
+ manual_palette->set_item_metadata(manual_palette->get_item_count() - 1, entries2[i]);
}
}
if (manual_palette->get_item_count() > 0) {
- // Only show the manual palette if at least tile exists in it
+ // Only show the manual palette if at least tile exists in it.
if (selected_manual == -1 || selected_single != palette->get_current())
selected_manual = 0;
if (selected_manual < manual_palette->get_item_count())
@@ -1951,6 +1954,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
add_child(priority_button);
search_box = memnew(LineEdit);
+ search_box->set_placeholder(TTR("Filter tiles"));
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
search_box->connect("text_entered", this, "_text_entered");
search_box->connect("text_changed", this, "_text_changed");
@@ -1973,7 +1977,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
palette_container->set_custom_minimum_size(Size2(mw, 0));
add_child(palette_container);
- // Add tile palette
+ // Add tile palette.
palette = memnew(ItemList);
palette->set_h_size_flags(SIZE_EXPAND_FILL);
palette->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1981,11 +1985,21 @@ 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->connect("item_selected", this, "_palette_selected");
palette->connect("multi_selected", this, "_palette_multi_selected");
palette_container->add_child(palette);
- // Add autotile override palette
+ // Add message for when no texture is selected.
+ info_message = memnew(Label);
+ info_message->set_text(TTR("Give a TileSet resource to this TileMap to use its tiles."));
+ info_message->set_valign(Label::VALIGN_CENTER);
+ info_message->set_align(Label::ALIGN_CENTER);
+ info_message->set_autowrap(true);
+ info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ palette->add_child(info_message);
+
+ // Add autotile override palette.
manual_palette = memnew(ItemList);
manual_palette->set_h_size_flags(SIZE_EXPAND_FILL);
manual_palette->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1995,15 +2009,14 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
manual_palette->hide();
palette_container->add_child(manual_palette);
- // Add menu items
+ // Add menu items.
toolbar = memnew(HBoxContainer);
toolbar->hide();
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar);
- // Separator
toolbar->add_child(memnew(VSeparator));
- // Tools
+ // Tools.
paint_button = memnew(ToolButton);
paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P));
paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint"));
@@ -2031,18 +2044,18 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
_update_button_tool();
- // Container to the right of the toolbar
+ // Container to the right of the toolbar.
toolbar_right = memnew(HBoxContainer);
toolbar_right->hide();
toolbar_right->set_h_size_flags(SIZE_EXPAND_FILL);
toolbar_right->set_alignment(BoxContainer::ALIGN_END);
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar_right);
- // Tile position
+ // Tile position.
tile_info = memnew(Label);
toolbar_right->add_child(tile_info);
- // Menu
+ // Menu.
options = memnew(MenuButton);
options->set_text("TileMap");
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons"));
@@ -2136,7 +2149,8 @@ void TileMapEditorPlugin::make_visible(bool p_visible) {
tile_map_editor->show();
tile_map_editor->get_toolbar()->show();
tile_map_editor->get_toolbar_right()->show();
- CanvasItemEditor::get_singleton()->set_current_tool(CanvasItemEditor::TOOL_SELECT); //Change to TOOL_SELECT when TileMap node is selected, to prevent accidental movement.
+ // Change to TOOL_SELECT when TileMap node is selected, to prevent accidental movement.
+ CanvasItemEditor::get_singleton()->set_current_tool(CanvasItemEditor::TOOL_SELECT);
} else {
tile_map_editor->hide();
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index c841eb1f98..e3d678c2fd 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -82,6 +82,8 @@ class TileMapEditor : public VBoxContainer {
ItemList *palette;
ItemList *manual_palette;
+ Label *info_message;
+
HBoxContainer *toolbar;
HBoxContainer *toolbar_right;
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 9096a0e0be..e0bf8dfdb2 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -579,6 +579,14 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
scroll->set_v_size_flags(SIZE_EXPAND_FILL);
scroll->set_clip_contents(true);
+ empty_message = memnew(Label);
+ empty_message->set_text(TTR("Add or select a texture on the left panel to edit the tiles bound to it."));
+ empty_message->set_valign(Label::VALIGN_CENTER);
+ empty_message->set_align(Label::ALIGN_CENTER);
+ empty_message->set_autowrap(true);
+ empty_message->set_v_size_flags(SIZE_EXPAND_FILL);
+ main_vb->add_child(empty_message);
+
workspace_container = memnew(Control);
scroll->add_child(workspace_container);
@@ -627,7 +635,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
helper = memnew(TilesetEditorContext(this));
tile_names_visible = false;
- // config scale
+ // Config scale.
max_scale = 10.0f;
min_scale = 0.1f;
scale_ratio = 1.2f;
@@ -3123,12 +3131,28 @@ void TileSetEditor::update_workspace_tile_mode() {
}
tools[SELECT_NEXT]->set_disabled(true);
tools[SELECT_PREVIOUS]->set_disabled(true);
+
+ tools[ZOOM_OUT]->hide();
+ tools[ZOOM_1]->hide();
+ tools[ZOOM_IN]->hide();
+ tools[VISIBLE_INFO]->hide();
+
+ scroll->hide();
+ empty_message->show();
} else {
for (int i = 1; i < WORKSPACE_MODE_MAX; i++) {
tool_workspacemode[i]->set_disabled(false);
}
tools[SELECT_NEXT]->set_disabled(false);
tools[SELECT_PREVIOUS]->set_disabled(false);
+
+ tools[ZOOM_OUT]->show();
+ tools[ZOOM_1]->show();
+ tools[ZOOM_IN]->show();
+ tools[VISIBLE_INFO]->show();
+
+ scroll->show();
+ empty_message->hide();
}
if (workspace_mode != WORKSPACE_EDIT) {
diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h
index fff9ef7731..944dc04e4e 100644
--- a/editor/plugins/tile_set_editor_plugin.h
+++ b/editor/plugins/tile_set_editor_plugin.h
@@ -138,6 +138,7 @@ class TileSetEditor : public HSplitContainer {
int current_item_index;
Sprite *preview;
ScrollContainer *scroll;
+ Label *empty_message;
Control *workspace_container;
bool draw_handles;
Control *workspace_overlay;
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index c059977487..e8cd7692b6 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -59,14 +59,6 @@ void VersionControlEditorPlugin::_selected_a_vcs(int p_id) {
List<StringName> available_addons = get_available_vcs_names();
const StringName selected_vcs = set_up_choice->get_item_text(p_id);
-
- if (available_addons.find(selected_vcs) != NULL) {
-
- set_up_init_button->set_disabled(false);
- } else {
-
- set_up_init_button->set_disabled(true);
- }
}
void VersionControlEditorPlugin::_populate_available_vcs_names() {
@@ -75,9 +67,6 @@ void VersionControlEditorPlugin::_populate_available_vcs_names() {
if (!called) {
- set_up_choice->add_item("Select an available VCS");
-
- fetch_available_vcs_addon_names();
List<StringName> available_addons = get_available_vcs_names();
for (int i = 0; i < available_addons.size(); i++) {
@@ -95,19 +84,22 @@ VersionControlEditorPlugin *VersionControlEditorPlugin::get_singleton() {
void VersionControlEditorPlugin::popup_vcs_set_up_dialog(const Control *p_gui_base) {
- Size2 popup_size = Size2(400, 100);
- Size2 window_size = p_gui_base->get_viewport_rect().size;
- popup_size.x = MIN(window_size.x * 0.5, popup_size.x);
- popup_size.y = MIN(window_size.y * 0.5, popup_size.y);
+ fetch_available_vcs_addon_names();
+ List<StringName> available_addons = get_available_vcs_names();
+ if (available_addons.size() >= 1) {
- if (get_is_vcs_intialized()) {
+ Size2 popup_size = Size2(400, 100);
+ Size2 window_size = p_gui_base->get_viewport_rect().size;
+ popup_size.x = MIN(window_size.x * 0.5, popup_size.x);
+ popup_size.y = MIN(window_size.y * 0.5, popup_size.y);
- set_up_init_button->set_disabled(true);
- }
+ _populate_available_vcs_names();
- _populate_available_vcs_names();
+ set_up_dialog->popup_centered_clamped(popup_size * EDSCALE);
+ } else {
- set_up_dialog->popup_centered_clamped(popup_size * EDSCALE);
+ EditorNode::get_singleton()->show_warning(TTR("No VCS addons are available."), TTR("Error"));
+ }
}
void VersionControlEditorPlugin::_initialize_vcs() {
@@ -120,7 +112,7 @@ void VersionControlEditorPlugin::_initialize_vcs() {
return;
}
- int id = set_up_choice->get_selected_id();
+ const int id = set_up_choice->get_selected_id();
String selected_addon = set_up_choice->get_item_text(id);
String path = ScriptServer::get_global_class_path(selected_addon);
@@ -381,7 +373,19 @@ void VersionControlEditorPlugin::register_editor() {
void VersionControlEditorPlugin::fetch_available_vcs_addon_names() {
- ScriptServer::get_global_class_list(&available_addons);
+ List<StringName> global_classes;
+ ScriptServer::get_global_class_list(&global_classes);
+
+ for (int i = 0; i != global_classes.size(); i++) {
+
+ String path = ScriptServer::get_global_class_path(global_classes[i]);
+ Ref<Script> script = ResourceLoader::load(path);
+
+ if (script->get_instance_base_type() == "EditorVCSInterface") {
+
+ available_addons.push_back(global_classes[i]);
+ }
+ }
}
void VersionControlEditorPlugin::clear_stage_area() {
@@ -427,7 +431,6 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
version_control_actions->add_child(set_up_dialog);
set_up_ok_button = set_up_dialog->get_ok();
- set_up_ok_button->set_disabled(false);
set_up_ok_button->set_text(TTR("Close"));
set_up_vbc = memnew(VBoxContainer);
@@ -454,7 +457,6 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
set_up_init_settings = NULL;
set_up_init_button = memnew(Button);
- set_up_init_button->set_disabled(true);
set_up_init_button->set_text(TTR("Initialize"));
set_up_init_button->connect("pressed", this, "_initialize_vcs");
set_up_vbc->add_child(set_up_init_button);
@@ -564,7 +566,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
diff_heading = memnew(Label);
diff_heading->set_text(TTR("Status"));
- diff_heading->set_tooltip(TTR("View file diffs before commiting them to the latest version"));
+ diff_heading->set_tooltip(TTR("View file diffs before committing them to the latest version"));
diff_hbc->add_child(diff_heading);
diff_file_name = memnew(Label);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index c6e3dc1e32..e2527a4039 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -928,16 +928,36 @@ public:
TextureButton *favorite_button;
TextureRect *icon;
bool icon_needs_reload;
+ bool hover;
ProjectListItemControl() {
favorite_button = NULL;
icon = NULL;
icon_needs_reload = true;
+ hover = false;
}
void set_is_favorite(bool fav) {
favorite_button->set_modulate(fav ? Color(1, 1, 1, 1) : Color(1, 1, 1, 0.2));
}
+
+ void _notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_MOUSE_ENTER: {
+ hover = true;
+ update();
+ } break;
+ case NOTIFICATION_MOUSE_EXIT: {
+ hover = false;
+ update();
+ } break;
+ case NOTIFICATION_DRAW: {
+ if (hover) {
+ draw_style_box(get_stylebox("hover", "Tree"), Rect2(Point2(), get_size() - Size2(10, 0) * EDSCALE));
+ }
+ } break;
+ }
+ }
};
class ProjectList : public ScrollContainer {
@@ -1260,6 +1280,8 @@ void ProjectList::create_project_item_control(int p_index) {
TextureButton *favorite = memnew(TextureButton);
favorite->set_name("FavoriteButton");
favorite->set_normal_texture(favorite_icon);
+ // This makes the project's "hover" style display correctly when hovering the favorite icon
+ favorite->set_mouse_filter(MOUSE_FILTER_PASS);
favorite->connect("pressed", this, "_favorite_pressed", varray(hb));
favorite_box->add_child(favorite);
favorite_box->set_alignment(BoxContainer::ALIGN_CENTER);
@@ -1735,6 +1757,12 @@ void ProjectManager::_notification(int p_what) {
if (_project_list->get_project_count() == 0 && StreamPeerSSL::is_available())
open_templates->popup_centered_minsize();
+
+ if (_project_list->get_project_count() >= 1) {
+ // Focus on the search box immediately to allow the user
+ // to search without having to reach for their mouse
+ project_filter->search_box->grab_focus();
+ }
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index a0d2332ffc..edc14ccf71 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -1043,6 +1043,84 @@ void ProjectSettingsEditor::_copy_to_platform_about_to_show() {
}
}
+Variant ProjectSettingsEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+
+ TreeItem *selected = input_editor->get_selected();
+ if (!selected || selected->get_parent() != input_editor->get_root())
+ return Variant();
+
+ String name = selected->get_text(0);
+ VBoxContainer *vb = memnew(VBoxContainer);
+ HBoxContainer *hb = memnew(HBoxContainer);
+ Label *label = memnew(Label(name));
+ hb->set_modulate(Color(1, 1, 1, 1.0f));
+ hb->add_child(label);
+ vb->add_child(hb);
+ set_drag_preview(vb);
+
+ Dictionary drag_data;
+ drag_data["type"] = "nodes";
+
+ input_editor->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+
+ return drag_data;
+}
+
+bool ProjectSettingsEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+ Dictionary d = p_data;
+ if (!d.has("type") || d["type"] != "nodes")
+ return false;
+
+ TreeItem *selected = input_editor->get_selected();
+ TreeItem *item = input_editor->get_item_at_position(p_point);
+ if (!selected || !item || item->get_parent() == selected)
+ return false;
+
+ return true;
+}
+
+void ProjectSettingsEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+
+ if (!can_drop_data_fw(p_point, p_data, p_from))
+ return;
+
+ TreeItem *selected = input_editor->get_selected();
+ TreeItem *item = input_editor->get_item_at_position(p_point);
+ TreeItem *target = item->get_parent() == input_editor->get_root() ? item : item->get_parent();
+
+ String selected_name = "input/" + selected->get_text(0);
+ int old_order = ProjectSettings::get_singleton()->get_order(selected_name);
+ String target_name = "input/" + target->get_text(0);
+ int target_order = ProjectSettings::get_singleton()->get_order(target_name);
+
+ int order = old_order;
+ bool is_below = target_order > old_order;
+ TreeItem *iterator = is_below ? selected->get_next() : selected->get_prev();
+
+ undo_redo->create_action(TTR("Moved Input Action Event"));
+ while (iterator != target) {
+
+ String iterator_name = "input/" + iterator->get_text(0);
+ int iterator_order = ProjectSettings::get_singleton()->get_order(iterator_name);
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", iterator_name, order);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", iterator_name, iterator_order);
+ order = iterator_order;
+ iterator = is_below ? iterator->get_next() : iterator->get_prev();
+ }
+
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", target_name, order);
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", selected_name, target_order);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", target_name, target_order);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", selected_name, old_order);
+
+ undo_redo->add_do_method(this, "_update_actions");
+ undo_redo->add_undo_method(this, "_update_actions");
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+ undo_redo->commit_action();
+}
+
void ProjectSettingsEditor::_copy_to_platform(int p_which) {
String path = globals_editor->get_inspector()->get_selected_path();
@@ -1310,7 +1388,7 @@ void ProjectSettingsEditor::_translation_res_option_delete(Object *p_item, int p
void ProjectSettingsEditor::_translation_filter_option_changed() {
int sel_id = translation_locale_filter_mode->get_selected_id();
- TreeItem *t = translation_filter->get_selected();
+ TreeItem *t = translation_filter->get_edited();
String locale = t->get_tooltip(0);
bool checked = t->is_checked(0);
@@ -1662,6 +1740,10 @@ void ProjectSettingsEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_editor_restart_close"), &ProjectSettingsEditor::_editor_restart_close);
ClassDB::bind_method(D_METHOD("get_tabs"), &ProjectSettingsEditor::get_tabs);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ProjectSettingsEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ProjectSettingsEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &ProjectSettingsEditor::drop_data_fw);
}
ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
@@ -1844,6 +1926,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
input_editor->connect("item_activated", this, "_action_activated");
input_editor->connect("cell_selected", this, "_action_selected");
input_editor->connect("button_pressed", this, "_action_button_pressed");
+ input_editor->set_drag_forwarding(this);
+
popup_add = memnew(PopupMenu);
add_child(popup_add);
popup_add->connect("id_pressed", this, "_add_item");
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index d302c0d34b..4dfd8ba602 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -158,6 +158,10 @@ class ProjectSettingsEditor : public AcceptDialog {
void _toggle_search_bar(bool p_pressed);
+ Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
+ bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+ void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
void _copy_to_platform_about_to_show();
ProjectSettingsEditor();
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 16f1575757..2ddf1f7056 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -759,8 +759,13 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
_delete_confirm();
} else {
- if (remove_list.size() > 1) {
+ if (remove_list.size() >= 2) {
delete_dialog->set_text(vformat(TTR("Delete %d nodes?"), remove_list.size()));
+ } else if (remove_list.size() == 1 && remove_list[0] == editor_data->get_edited_scene_root()) {
+ delete_dialog->set_text(vformat(TTR("Delete the root node \"%s\"?"), remove_list[0]->get_name()));
+ } else if (remove_list.size() == 1 && remove_list[0]->get_filename() == "" && remove_list[0]->get_child_count() >= 1) {
+ // Display this message only for non-instanced scenes
+ delete_dialog->set_text(vformat(TTR("Delete node \"%s\" and its children?"), remove_list[0]->get_name()));
} else {
delete_dialog->set_text(vformat(TTR("Delete node \"%s\"?"), remove_list[0]->get_name()));
}
@@ -1504,7 +1509,7 @@ bool SceneTreeDock::_validate_no_foreign() {
// When edited_scene inherits from another one the root Node will be the parent Scene,
// we don't want to consider that Node a foreign one otherwise we would not be able to
- // delete it
+ // delete it.
if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene == E->get()) {
continue;
}
@@ -1528,7 +1533,7 @@ void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
List<Node *> selection = editor_selection->get_selected_node_list();
if (selection.empty())
- return; //nothing to reparent
+ return; // Nothing to reparent.
Vector<Node *> nodes;
@@ -1544,18 +1549,32 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
Node *new_parent = p_new_parent;
ERR_FAIL_COND(!new_parent);
+ if (p_nodes.size() == 0)
+ return; // Nothing to reparent.
+
+ p_nodes.sort_custom<Node::Comparator>(); //Makes result reliable.
+
+ bool no_change = true;
+ for (int ni = 0; ni < p_nodes.size(); ni++) {
+
+ if (p_nodes[ni] == p_new_parent)
+ return; // Attempt to reparent to itself.
+
+ if (p_nodes[ni]->get_parent() != p_new_parent || p_position_in_parent + ni != p_nodes[ni]->get_position_in_parent())
+ no_change = false;
+ }
+
+ if (no_change)
+ return; // Position and parent didn't change.
+
Node *validate = new_parent;
while (validate) {
- ERR_FAIL_COND_MSG(p_nodes.find(validate) != -1, "Selection changed at some point.. can't reparent.");
+ ERR_FAIL_COND_MSG(p_nodes.find(validate) != -1, "Selection changed at some point. Can't reparent.");
validate = validate->get_parent();
}
- //ok all valid
-
- if (p_nodes.size() == 0)
- return; //nothing to reparent
- //sort by tree order, so re-adding is easy
+ // Sort by tree order, so re-adding is easy.
p_nodes.sort_custom<Node::Comparator>();
editor_data->get_undo_redo().create_action(TTR("Reparent Node"));
@@ -1567,7 +1586,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
for (int ni = 0; ni < p_nodes.size(); ni++) {
- //no undo for now, sorry
+ // No undo implemented for this yet.
Node *node = p_nodes[ni];
fill_path_renames(node, new_parent, &path_renames);
@@ -1577,14 +1596,11 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
node->get_owned_by(node->get_owner(), &owned);
Array owners;
for (List<Node *>::Element *E = owned.front(); E; E = E->next()) {
-
owners.push_back(E->get());
}
- if (new_parent == node->get_parent() && node->get_index() < p_position_in_parent + ni) {
- //if child will generate a gap when moved, adjust
- inc--;
- }
+ if (new_parent == node->get_parent() && node->get_index() < p_position_in_parent + ni)
+ inc--; // If the child will generate a gap when moved, adjust.
editor_data->get_undo_redo().add_do_method(node->get_parent(), "remove_child", node);
editor_data->get_undo_redo().add_do_method(new_parent, "add_child", node);
@@ -1596,17 +1612,17 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
String old_name = former_names[ni];
String new_name = new_parent->validate_child_name(node);
- // name was modified, fix the path renames
+ // Name was modified, fix the path renames.
if (old_name.casecmp_to(new_name) != 0) {
- // Fix the to name to have the new name
+ // Fix the to name to have the new name.
NodePath old_new_name = path_renames[ni].second;
NodePath new_path;
Vector<StringName> unfixed_new_names = old_new_name.get_names();
Vector<StringName> fixed_new_names;
- // Get last name and replace with fixed new name
+ // Get last name and replace with fixed new name.
for (int a = 0; a < (unfixed_new_names.size() - 1); a++) {
fixed_new_names.push_back(unfixed_new_names[a]);
}
@@ -1640,8 +1656,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
inc++;
}
- //add and move in a second step.. (so old order is preserved)
-
+ // Add and move in a second step (so old order is preserved).
for (int ni = 0; ni < p_nodes.size(); ni++) {
Node *node = p_nodes[ni];
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 6ee09012a5..6ba507fb9c 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -434,6 +434,15 @@ int ScriptEditorDebugger::_update_scene_tree(TreeItem *parent, const Array &node
}
item->set_metadata(0, id);
+ if (id == inspected_object_id) {
+ TreeItem *cti = item->get_parent();
+ while (cti) {
+ cti->set_collapsed(false);
+ cti = cti->get_parent();
+ }
+ item->select(0);
+ }
+
// Set current item as collapsed if necessary
if (parent) {
if (!unfold_cache.has(id)) {
@@ -1042,17 +1051,15 @@ void ScriptEditorDebugger::_performance_draw() {
which.push_back(i);
}
- Ref<Font> graph_font = get_font("font", "TextEdit");
-
if (which.empty()) {
- String text = TTR("Pick one or more items from the list to display the graph.");
-
- perf_draw->draw_string(graph_font, Point2i(MAX(0, perf_draw->get_size().x - graph_font->get_string_size(text).x), perf_draw->get_size().y + graph_font->get_ascent()) / 2, text, get_color("font_color", "Label"), perf_draw->get_size().x);
-
+ info_message->show();
return;
}
+ info_message->hide();
+
Ref<StyleBox> graph_sb = get_stylebox("normal", "TextEdit");
+ Ref<Font> graph_font = get_font("font", "TextEdit");
int cols = Math::ceil(Math::sqrt((float)which.size()));
int rows = Math::ceil((float)which.size() / cols);
@@ -1121,7 +1128,6 @@ void ScriptEditorDebugger::_notification(int p_what) {
forward->set_icon(get_icon("Forward", "EditorIcons"));
dobreak->set_icon(get_icon("Pause", "EditorIcons"));
docontinue->set_icon(get_icon("DebugContinue", "EditorIcons"));
- //scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
le_set->connect("pressed", this, "_live_edit_set");
le_clear->connect("pressed", this, "_live_edit_clear");
error_tree->connect("item_selected", this, "_error_selected");
@@ -1193,7 +1199,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
if (connection.is_null())
break;
- EditorNode::get_log()->add_message("** Debug Process Started **");
+ EditorNode::get_log()->add_message("--- Debugging process started ---", EditorLog::MSG_TYPE_EDITOR);
ppeer->set_stream_peer(connection);
@@ -1203,7 +1209,7 @@ void ScriptEditorDebugger::_notification(int p_what) {
dobreak->set_disabled(false);
tabs->set_current_tab(0);
- _set_reason_text(TTR("Child Process Connected"), MESSAGE_SUCCESS);
+ _set_reason_text(TTR("Child process connected."), MESSAGE_SUCCESS);
profiler->clear();
inspect_scene_tree->clear();
@@ -1391,7 +1397,7 @@ void ScriptEditorDebugger::stop() {
ppeer->set_stream_peer(Ref<StreamPeer>());
if (connection.is_valid()) {
- EditorNode::get_log()->add_message("** Debug Process Stopped **");
+ EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR);
connection.unref();
reason->set_text("");
@@ -2142,11 +2148,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
step = memnew(ToolButton);
hbc->add_child(step);
step->set_tooltip(TTR("Step Into"));
+ step->set_shortcut(ED_GET_SHORTCUT("debugger/step_into"));
step->connect("pressed", this, "debug_step");
next = memnew(ToolButton);
hbc->add_child(next);
next->set_tooltip(TTR("Step Over"));
+ next->set_shortcut(ED_GET_SHORTCUT("debugger/step_over"));
next->connect("pressed", this, "debug_next");
hbc->add_child(memnew(VSeparator));
@@ -2154,11 +2162,13 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
dobreak = memnew(ToolButton);
hbc->add_child(dobreak);
dobreak->set_tooltip(TTR("Break"));
+ dobreak->set_shortcut(ED_GET_SHORTCUT("debugger/break"));
dobreak->connect("pressed", this, "debug_break");
docontinue = memnew(ToolButton);
hbc->add_child(docontinue);
docontinue->set_tooltip(TTR("Continue"));
+ docontinue->set_shortcut(ED_GET_SHORTCUT("debugger/continue"));
docontinue->connect("pressed", this, "debug_continue");
back = memnew(Button);
@@ -2299,11 +2309,14 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
perf_monitors->set_column_title(0, TTR("Monitor"));
perf_monitors->set_column_title(1, TTR("Value"));
perf_monitors->set_column_titles_visible(true);
- hsp->add_child(perf_monitors);
perf_monitors->connect("item_edited", this, "_performance_select");
+ hsp->add_child(perf_monitors);
+
perf_draw = memnew(Control);
+ perf_draw->set_clip_contents(true);
perf_draw->connect("draw", this, "_performance_draw");
hsp->add_child(perf_draw);
+
hsp->set_name(TTR("Monitors"));
hsp->set_split_offset(340 * EDSCALE);
tabs->add_child(hsp);
@@ -2337,6 +2350,14 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
perf_items.push_back(it);
perf_max.write[i] = 0;
}
+
+ info_message = memnew(Label);
+ info_message->set_text(TTR("Pick one or more items from the list to display the graph."));
+ info_message->set_valign(Label::VALIGN_CENTER);
+ info_message->set_align(Label::ALIGN_CENTER);
+ info_message->set_autowrap(true);
+ info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ perf_draw->add_child(info_message);
}
{ //vmem inspect
@@ -2348,7 +2369,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
vmem_hb->add_child(memnew(Label(TTR("Total:") + " ")));
vmem_total = memnew(LineEdit);
vmem_total->set_editable(false);
- vmem_total->set_custom_minimum_size(Size2(100, 1) * EDSCALE);
+ vmem_total->set_custom_minimum_size(Size2(100, 0) * EDSCALE);
vmem_hb->add_child(vmem_total);
vmem_refresh = memnew(ToolButton);
vmem_hb->add_child(vmem_refresh);
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index ce48edfe89..cc284476c0 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -135,6 +135,7 @@ class ScriptEditorDebugger : public Control {
Tree *perf_monitors;
Control *perf_draw;
+ Label *info_message;
Tree *vmem_tree;
Button *vmem_refresh;
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index b4643231d7..c9c1f9c3e0 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -110,7 +110,7 @@ void EditorSettingsDialog::_filter_shortcuts(const String &p_filter) {
}
void EditorSettingsDialog::_undo_redo_callback(void *p_self, const String &p_name) {
- EditorNode::get_log()->add_message(p_name);
+ EditorNode::get_log()->add_message(p_name, EditorLog::MSG_TYPE_EDITOR);
}
void EditorSettingsDialog::_notification(int p_what) {
@@ -151,7 +151,7 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
if (ED_IS_SHORTCUT("editor/undo", p_event)) {
String action = undo_redo->get_current_action_name();
if (action != "")
- EditorNode::get_log()->add_message("UNDO: " + action);
+ EditorNode::get_log()->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
undo_redo->undo();
handled = true;
}
@@ -159,7 +159,7 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
undo_redo->redo();
String action = undo_redo->get_current_action_name();
if (action != "")
- EditorNode::get_log()->add_message("REDO: " + action);
+ EditorNode::get_log()->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR);
handled = true;
}
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 4c5371769f..9f940c46e6 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -172,8 +172,8 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidde
instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario());
VS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id());
- if (skeleton.is_valid())
- VS::get_singleton()->instance_attach_skeleton(instance, skeleton);
+ if (skin_reference.is_valid())
+ VS::get_singleton()->instance_attach_skeleton(instance, skin_reference->get_skeleton());
if (extra_margin)
VS::get_singleton()->instance_set_extra_visibility_margin(instance, 1);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, VS::SHADOW_CASTING_SETTING_OFF);
@@ -181,14 +181,14 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidde
VS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26
}
-void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const RID &p_skeleton, const Ref<Material> &p_material) {
+void EditorSpatialGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const Ref<SkinReference> &p_skin_reference, const Ref<Material> &p_material) {
ERR_FAIL_COND(!spatial_node);
Instance ins;
ins.billboard = p_billboard;
ins.mesh = p_mesh;
- ins.skeleton = p_skeleton;
+ ins.skin_reference = p_skin_reference;
ins.material = p_material;
if (valid) {
ins.create_instance(spatial_node, hidden);
@@ -783,9 +783,10 @@ Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const {
LightSpatialGizmoPlugin::LightSpatialGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/light", Color(1, 1, 0.2));
+ Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/light", Color(1, 1, 0.7));
- create_material("lines", gizmo_color);
+ create_material("lines_primary", gizmo_color);
+ create_material("lines_secondary", gizmo_color * Color(1, 1, 1, 0.35));
create_material("lines_billboard", gizmo_color, true);
create_icon_material("light_directional_icon", SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons"));
@@ -937,7 +938,7 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
if (Object::cast_to<DirectionalLight>(light)) {
- Ref<Material> material = get_material("lines", p_gizmo);
+ Ref<Material> material = get_material("lines_primary", p_gizmo);
Ref<Material> icon = get_material("light_directional_icon", p_gizmo);
const int arrow_points = 7;
@@ -975,31 +976,39 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
if (Object::cast_to<OmniLight>(light)) {
- Ref<Material> material = get_material("lines_billboard", p_gizmo);
- Ref<Material> icon = get_material("light_omni_icon", p_gizmo);
+ // Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation
+ const Ref<Material> lines_material = get_material("lines_secondary", p_gizmo);
+ const Ref<Material> lines_billboard_material = get_material("lines_billboard", p_gizmo);
+ const Ref<Material> icon = get_material("light_omni_icon", p_gizmo);
OmniLight *on = Object::cast_to<OmniLight>(light);
-
- float r = on->get_param(Light::PARAM_RANGE);
-
+ const float r = on->get_param(Light::PARAM_RANGE);
Vector<Vector3> points;
+ Vector<Vector3> points_billboard;
- for (int i = 0; i <= 360; i++) {
+ for (int i = 0; i < 120; i++) {
- float ra = Math::deg2rad((float)i);
- float rb = Math::deg2rad((float)i + 1);
- Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
- Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
+ // Create a circle
+ const float ra = Math::deg2rad((float)(i * 3));
+ const float rb = Math::deg2rad((float)((i + 1) * 3));
+ const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r;
+ const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r;
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
+ // Draw axis-aligned circles
+ points.push_back(Vector3(a.x, 0, a.y));
+ points.push_back(Vector3(b.x, 0, b.y));
+ points.push_back(Vector3(0, a.x, a.y));
+ points.push_back(Vector3(0, b.x, b.y));
points.push_back(Vector3(a.x, a.y, 0));
points.push_back(Vector3(b.x, b.y, 0));
+
+ // Draw a billboarded circle
+ points_billboard.push_back(Vector3(a.x, a.y, 0));
+ points_billboard.push_back(Vector3(b.x, b.y, 0));
}
- p_gizmo->add_lines(points, material, true);
+ p_gizmo->add_lines(points, lines_material, true);
+ p_gizmo->add_lines(points_billboard, lines_billboard_material, true);
p_gizmo->add_unscaled_billboard(icon, 0.05);
Vector<Vector3> handles;
@@ -1009,40 +1018,44 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
if (Object::cast_to<SpotLight>(light)) {
- Ref<Material> material = get_material("lines", p_gizmo);
- Ref<Material> icon = get_material("light_spot_icon", p_gizmo);
+ const Ref<Material> material_primary = get_material("lines_primary", p_gizmo);
+ const Ref<Material> material_secondary = get_material("lines_secondary", p_gizmo);
+ const Ref<Material> icon = get_material("light_spot_icon", p_gizmo);
- Vector<Vector3> points;
+ Vector<Vector3> points_primary;
+ Vector<Vector3> points_secondary;
SpotLight *sl = Object::cast_to<SpotLight>(light);
float r = sl->get_param(Light::PARAM_RANGE);
float w = r * Math::sin(Math::deg2rad(sl->get_param(Light::PARAM_SPOT_ANGLE)));
float d = r * Math::cos(Math::deg2rad(sl->get_param(Light::PARAM_SPOT_ANGLE)));
- for (int i = 0; i < 360; i++) {
-
- float ra = Math::deg2rad((float)i);
- float rb = Math::deg2rad((float)i + 1);
- Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
- Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
+ for (int i = 0; i < 120; i++) {
- points.push_back(Vector3(a.x, a.y, -d));
- points.push_back(Vector3(b.x, b.y, -d));
+ // Draw a circle
+ const float ra = Math::deg2rad((float)(i * 3));
+ const float rb = Math::deg2rad((float)((i + 1) * 3));
+ const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
+ const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
- if (i % 90 == 0) {
+ points_primary.push_back(Vector3(a.x, a.y, -d));
+ points_primary.push_back(Vector3(b.x, b.y, -d));
- points.push_back(Vector3(a.x, a.y, -d));
- points.push_back(Vector3());
+ if (i % 15 == 0) {
+ // Draw 8 lines from the cone origin to the sides of the circle
+ points_secondary.push_back(Vector3(a.x, a.y, -d));
+ points_secondary.push_back(Vector3());
}
}
- points.push_back(Vector3(0, 0, -r));
- points.push_back(Vector3());
+ points_primary.push_back(Vector3(0, 0, -r));
+ points_primary.push_back(Vector3());
- p_gizmo->add_lines(points, material);
+ p_gizmo->add_lines(points_primary, material_primary);
+ p_gizmo->add_lines(points_secondary, material_secondary);
- float ra = 16 * Math_PI * 2.0 / 64.0;
- Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
+ const float ra = 16 * Math_PI * 2.0 / 64.0;
+ const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
Vector<Vector3> handles;
handles.push_back(Vector3(0, 0, -r));
@@ -1789,7 +1802,7 @@ void SkeletonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
}
Ref<ArrayMesh> m = surface_tool->commit();
- p_gizmo->add_mesh(m, false, skel->get_skeleton());
+ p_gizmo->add_mesh(m, false, skel->register_skin(Ref<Skin>()));
}
////
@@ -3712,7 +3725,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
Ref<ConcavePolygonShape> cs2 = s;
Ref<ArrayMesh> mesh = cs2->get_debug_mesh();
- p_gizmo->add_mesh(mesh, false, RID(), material);
+ p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material);
}
if (Object::cast_to<RayShape>(*s)) {
@@ -3734,7 +3747,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
Ref<HeightMapShape> hms = s;
Ref<ArrayMesh> mesh = hms->get_debug_mesh();
- p_gizmo->add_mesh(mesh, false, RID(), material);
+ p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material);
}
}
diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html
index 349420b3f3..12b9af21e5 100644
--- a/misc/dist/html/full-size.html
+++ b/misc/dist/html/full-size.html
@@ -182,7 +182,7 @@ $GODOT_HEAD_INCLUDE
});
animationCallbacks = animationCallbacks.filter(function(value) {
return (value != animateStatusIndeterminate);
- }
+ });
switch (mode) {
case 'progress':
statusProgress.style.display = 'block';
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index 3a0ac9f389..e309233a8b 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -86,7 +86,7 @@ do
if grep -q "thirdparty" <<< $file; then
continue;
fi
- if grep -q "platform/android/java/src/com" <<< $file; then
+ if grep -q "platform/android/java/lib/src/com" <<< $file; then
continue;
fi
diff --git a/misc/ide/jetbrains/AndroidManifest.xml b/misc/ide/jetbrains/AndroidManifest.xml
deleted file mode 100644
index 232a95e779..0000000000
--- a/misc/ide/jetbrains/AndroidManifest.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- package="com.godot.game"
- android:versionCode="1"
- android:versionName="1.0"
- android:installLocation="auto"
- >
-<supports-screens android:smallScreens="true"
- android:normalScreens="true"
- android:largeScreens="true"
- android:xlargeScreens="true"/>
-
- <uses-feature android:glEsVersion="0x00020000" android:required="true" />
-
-
-
- <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" >
- <activity android:name="org.godotengine.godot.Godot"
- android:label="@string/godot_project_name_string"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- android:launchMode="singleTask"
- android:screenOrientation="landscape"
- android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"
- android:resizeableActivity="false"
- tools:ignore="UnusedAttribute">
-
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <service android:name="org.godotengine.godot.GodotDownloaderService" />
-
-
-
- </application>
-
- <instrumentation android:icon="@drawable/icon"
- android:label="@string/godot_project_name_string"
- android:name="org.godotengine.godot.GodotInstrumentation"
- android:targetPackage="com.godot.game" />
-
-</manifest>
diff --git a/misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.jar b/misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index f6b961fd5a..0000000000
--- a/misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.properties b/misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index 22e7a5c60b..0000000000
--- a/misc/ide/jetbrains/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Wed Aug 21 13:47:30 PDT 2019
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/misc/ide/jetbrains/gradlew b/misc/ide/jetbrains/gradlew
deleted file mode 100755
index cccdd3d517..0000000000
--- a/misc/ide/jetbrains/gradlew
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env sh
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
- echo "$*"
-}
-
-die () {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=$((i+1))
- done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/misc/ide/jetbrains/gradlew.bat b/misc/ide/jetbrains/gradlew.bat
deleted file mode 100644
index f9553162f1..0000000000
--- a/misc/ide/jetbrains/gradlew.bat
+++ /dev/null
@@ -1,84 +0,0 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/misc/travis/clang-format.sh b/misc/travis/clang-format.sh
index 48378281d4..097b2a9378 100755
--- a/misc/travis/clang-format.sh
+++ b/misc/travis/clang-format.sh
@@ -11,7 +11,7 @@ else
RANGE=HEAD
fi
-FILES=$(git diff-tree --no-commit-id --name-only -r $RANGE | grep -v thirdparty/ | grep -v platform/android/java/src/com/ | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc|java|glsl)$")
+FILES=$(git diff-tree --no-commit-id --name-only -r $RANGE | grep -v thirdparty/ | grep -v platform/android/java/lib/src/com/ | grep -E "\.(c|h|cpp|hpp|cc|hh|cxx|m|mm|inc|java|glsl)$")
echo "Checking files:\n$FILES"
# create a random filename to store our generated patch
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
index e5439fd132..f2f51d9dd3 100644
--- a/modules/assimp/editor_scene_importer_assimp.cpp
+++ b/modules/assimp/editor_scene_importer_assimp.cpp
@@ -529,7 +529,7 @@ void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_anim
}
//
-// Mesh Generation from indicies ? why do we need so much mesh code
+// Mesh Generation from indices ? why do we need so much mesh code
// [debt needs looked into]
Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(
ImportState &state,
@@ -541,6 +541,25 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(
mesh.instance();
bool has_uvs = false;
+ Map<String, uint32_t> morph_mesh_string_lookup;
+
+ for (int i = 0; i < p_surface_indices.size(); i++) {
+ const unsigned int mesh_idx = p_surface_indices[0];
+ const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx];
+ for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
+
+ String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName);
+ if (!morph_mesh_string_lookup.has(ai_anim_mesh_name)) {
+ morph_mesh_string_lookup.insert(ai_anim_mesh_name, j);
+ mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
+ if (ai_anim_mesh_name.empty()) {
+ ai_anim_mesh_name = String("morph_") + itos(j);
+ }
+ mesh->add_blend_shape(ai_anim_mesh_name);
+ }
+ }
+ }
+
//
// Process Vertex Weights
//
@@ -680,6 +699,25 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(
mat->set_cull_mode(SpatialMaterial::CULL_BACK);
// Now process materials
+ aiTextureType base_color = aiTextureType_BASE_COLOR;
+ {
+ String filename, path;
+ AssimpImageData image_data;
+
+ if (AssimpUtils::GetAssimpTexture(state, ai_material, base_color, filename, path, image_data)) {
+ AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
+
+ // anything transparent must be culled
+ if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) {
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ mat->set_cull_mode(SpatialMaterial::CULL_DISABLED); // since you can see both sides in transparent mode
+ }
+
+ mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, image_data.texture);
+ }
+ }
+
aiTextureType tex_diffuse = aiTextureType_DIFFUSE;
{
String filename, path;
@@ -731,6 +769,60 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(
}
}
+ aiTextureType tex_normal_camera = aiTextureType_NORMAL_CAMERA;
+ {
+ String filename, path;
+ Ref<ImageTexture> texture;
+ AssimpImageData image_data;
+
+ // Process texture normal map
+ if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal_camera, filename, path, image_data)) {
+ AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
+ mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture);
+ }
+ }
+
+ aiTextureType tex_emission_color = aiTextureType_EMISSION_COLOR;
+ {
+ String filename, path;
+ Ref<ImageTexture> texture;
+ AssimpImageData image_data;
+
+ // Process texture normal map
+ if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emission_color, filename, path, image_data)) {
+ AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
+ mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture);
+ }
+ }
+
+ aiTextureType tex_metalness = aiTextureType_METALNESS;
+ {
+ String filename, path;
+ Ref<ImageTexture> texture;
+ AssimpImageData image_data;
+
+ // Process texture normal map
+ if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_metalness, filename, path, image_data)) {
+ AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
+ mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, image_data.texture);
+ }
+ }
+
+ aiTextureType tex_roughness = aiTextureType_DIFFUSE_ROUGHNESS;
+ {
+ String filename, path;
+ Ref<ImageTexture> texture;
+ AssimpImageData image_data;
+
+ // Process texture normal map
+ if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) {
+ AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
+ mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, image_data.texture);
+ }
+ }
+
aiTextureType tex_emissive = aiTextureType_EMISSIVE;
{
String filename = "";
@@ -772,16 +864,17 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(
}
}
- aiTextureType tex_roughness = aiTextureType_SHININESS;
+ aiTextureType tex_ao_map = aiTextureType_AMBIENT_OCCLUSION;
{
String filename, path;
Ref<ImageTexture> texture;
AssimpImageData image_data;
// Process texture normal map
- if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) {
+ if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_ao_map, filename, path, image_data)) {
AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
- mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, image_data.texture);
+ mat->set_feature(SpatialMaterial::FEATURE_AMBIENT_OCCLUSION, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION, image_data.texture);
}
}
@@ -789,16 +882,15 @@ Ref<Mesh> EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(
Array morphs;
morphs.resize(ai_mesh->mNumAnimMeshes);
Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
- Map<uint32_t, String> morph_mesh_idx_names;
+
for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName);
- mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
+
if (ai_anim_mesh_name.empty()) {
ai_anim_mesh_name = String("morph_") + itos(j);
}
- mesh->add_blend_shape(ai_anim_mesh_name);
- morph_mesh_idx_names.insert(j, ai_anim_mesh_name);
+
Array array_copy;
array_copy.resize(VisualServer::ARRAY_MAX);
@@ -1188,7 +1280,6 @@ void EditorSceneImporterAssimp::create_bone(ImportState &state, RecursiveState &
// this transform is a bone
recursive_state.skeleton->add_bone(recursive_state.node_name);
- ERR_FAIL_COND(recursive_state.skeleton == NULL); // serious bug we must now exit.
//ERR_FAIL_COND(recursive_state.skeleton->get_name() == "");
print_verbose("Bone added to lookup: " + AssimpUtils::get_assimp_string(recursive_state.bone->mName));
print_verbose("Skeleton attached to: " + recursive_state.skeleton->get_name());
diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp
index 5a32fa1c2c..8708430257 100644
--- a/modules/bmp/image_loader_bmp.cpp
+++ b/modules/bmp/image_loader_bmp.cpp
@@ -63,139 +63,137 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
ERR_FAIL_V(ERR_UNAVAILABLE);
}
- if (err == OK) {
- // Image data (might be indexed)
- PoolVector<uint8_t> data;
- int data_len = 0;
+ // Image data (might be indexed)
+ PoolVector<uint8_t> data;
+ int data_len = 0;
- if (bits_per_pixel <= 8) { // indexed
- data_len = width * height;
- } else { // color
- data_len = width * height * 4;
- }
- ERR_FAIL_COND_V(data_len == 0, ERR_BUG);
- err = data.resize(data_len);
-
- PoolVector<uint8_t>::Write data_w = data.write();
- uint8_t *write_buffer = data_w.ptr();
-
- const uint32_t width_bytes = width * bits_per_pixel / 8;
- const uint32_t line_width = (width_bytes + 3) & ~3;
-
- // The actual data traversal is determined by
- // the data width in case of 8/4/1 bit images
- const uint32_t w = bits_per_pixel >= 24 ? width : width_bytes;
- const uint8_t *line = p_buffer + (line_width * (height - 1));
-
- for (unsigned int i = 0; i < height; i++) {
- const uint8_t *line_ptr = line;
-
- for (unsigned int j = 0; j < w; j++) {
- switch (bits_per_pixel) {
- case 1: {
- uint8_t color_index = *line_ptr;
-
- write_buffer[index + 0] = (color_index >> 7) & 1;
- write_buffer[index + 1] = (color_index >> 6) & 1;
- write_buffer[index + 2] = (color_index >> 5) & 1;
- write_buffer[index + 3] = (color_index >> 4) & 1;
- write_buffer[index + 4] = (color_index >> 3) & 1;
- write_buffer[index + 5] = (color_index >> 2) & 1;
- write_buffer[index + 6] = (color_index >> 1) & 1;
- write_buffer[index + 7] = (color_index >> 0) & 1;
-
- index += 8;
- line_ptr += 1;
- } break;
- case 4: {
- uint8_t color_index = *line_ptr;
-
- write_buffer[index + 0] = (color_index >> 4) & 0x0f;
- write_buffer[index + 1] = color_index & 0x0f;
-
- index += 2;
- line_ptr += 1;
- } break;
- case 8: {
- uint8_t color_index = *line_ptr;
-
- write_buffer[index] = color_index;
-
- index += 1;
- line_ptr += 1;
- } break;
- case 24: {
- uint32_t color = *((uint32_t *)line_ptr);
-
- write_buffer[index + 2] = color & 0xff;
- write_buffer[index + 1] = (color >> 8) & 0xff;
- write_buffer[index + 0] = (color >> 16) & 0xff;
- write_buffer[index + 3] = 0xff;
-
- index += 4;
- line_ptr += 3;
- } break;
- case 32: {
- uint32_t color = *((uint32_t *)line_ptr);
-
- write_buffer[index + 2] = color & 0xff;
- write_buffer[index + 1] = (color >> 8) & 0xff;
- write_buffer[index + 0] = (color >> 16) & 0xff;
- write_buffer[index + 3] = color >> 24;
-
- index += 4;
- line_ptr += 4;
- } break;
- }
+ if (bits_per_pixel <= 8) { // indexed
+ data_len = width * height;
+ } else { // color
+ data_len = width * height * 4;
+ }
+ ERR_FAIL_COND_V(data_len == 0, ERR_BUG);
+ err = data.resize(data_len);
+
+ PoolVector<uint8_t>::Write data_w = data.write();
+ uint8_t *write_buffer = data_w.ptr();
+
+ const uint32_t width_bytes = width * bits_per_pixel / 8;
+ const uint32_t line_width = (width_bytes + 3) & ~3;
+
+ // The actual data traversal is determined by
+ // the data width in case of 8/4/1 bit images
+ const uint32_t w = bits_per_pixel >= 24 ? width : width_bytes;
+ const uint8_t *line = p_buffer + (line_width * (height - 1));
+
+ for (uint64_t i = 0; i < height; i++) {
+ const uint8_t *line_ptr = line;
+
+ for (unsigned int j = 0; j < w; j++) {
+ switch (bits_per_pixel) {
+ case 1: {
+ uint8_t color_index = *line_ptr;
+
+ write_buffer[index + 0] = (color_index >> 7) & 1;
+ write_buffer[index + 1] = (color_index >> 6) & 1;
+ write_buffer[index + 2] = (color_index >> 5) & 1;
+ write_buffer[index + 3] = (color_index >> 4) & 1;
+ write_buffer[index + 4] = (color_index >> 3) & 1;
+ write_buffer[index + 5] = (color_index >> 2) & 1;
+ write_buffer[index + 6] = (color_index >> 1) & 1;
+ write_buffer[index + 7] = (color_index >> 0) & 1;
+
+ index += 8;
+ line_ptr += 1;
+ } break;
+ case 4: {
+ uint8_t color_index = *line_ptr;
+
+ write_buffer[index + 0] = (color_index >> 4) & 0x0f;
+ write_buffer[index + 1] = color_index & 0x0f;
+
+ index += 2;
+ line_ptr += 1;
+ } break;
+ case 8: {
+ uint8_t color_index = *line_ptr;
+
+ write_buffer[index] = color_index;
+
+ index += 1;
+ line_ptr += 1;
+ } break;
+ case 24: {
+ uint32_t color = *((uint32_t *)line_ptr);
+
+ write_buffer[index + 2] = color & 0xff;
+ write_buffer[index + 1] = (color >> 8) & 0xff;
+ write_buffer[index + 0] = (color >> 16) & 0xff;
+ write_buffer[index + 3] = 0xff;
+
+ index += 4;
+ line_ptr += 3;
+ } break;
+ case 32: {
+ uint32_t color = *((uint32_t *)line_ptr);
+
+ write_buffer[index + 2] = color & 0xff;
+ write_buffer[index + 1] = (color >> 8) & 0xff;
+ write_buffer[index + 0] = (color >> 16) & 0xff;
+ write_buffer[index + 3] = color >> 24;
+
+ index += 4;
+ line_ptr += 4;
+ } break;
}
- line -= line_width;
}
+ line -= line_width;
+ }
- if (p_color_buffer == NULL || color_table_size == 0) { // regular pixels
+ if (p_color_buffer == NULL || color_table_size == 0) { // regular pixels
- p_image->create(width, height, 0, Image::FORMAT_RGBA8, data);
+ p_image->create(width, height, 0, Image::FORMAT_RGBA8, data);
- } else { // data is in indexed format, extend it
+ } else { // data is in indexed format, extend it
- // Palette data
- PoolVector<uint8_t> palette_data;
- palette_data.resize(color_table_size * 4);
+ // Palette data
+ PoolVector<uint8_t> palette_data;
+ palette_data.resize(color_table_size * 4);
- PoolVector<uint8_t>::Write palette_data_w = palette_data.write();
- uint8_t *pal = palette_data_w.ptr();
+ PoolVector<uint8_t>::Write palette_data_w = palette_data.write();
+ uint8_t *pal = palette_data_w.ptr();
- const uint8_t *cb = p_color_buffer;
+ const uint8_t *cb = p_color_buffer;
- for (unsigned int i = 0; i < color_table_size; ++i) {
- uint32_t color = *((uint32_t *)cb);
+ for (unsigned int i = 0; i < color_table_size; ++i) {
+ uint32_t color = *((uint32_t *)cb);
- pal[i * 4 + 0] = (color >> 16) & 0xff;
- pal[i * 4 + 1] = (color >> 8) & 0xff;
- pal[i * 4 + 2] = (color)&0xff;
- pal[i * 4 + 3] = 0xff;
+ pal[i * 4 + 0] = (color >> 16) & 0xff;
+ pal[i * 4 + 1] = (color >> 8) & 0xff;
+ pal[i * 4 + 2] = (color)&0xff;
+ pal[i * 4 + 3] = 0xff;
- cb += 4;
- }
- // Extend palette to image
- PoolVector<uint8_t> extended_data;
- extended_data.resize(data.size() * 4);
+ cb += 4;
+ }
+ // Extend palette to image
+ PoolVector<uint8_t> extended_data;
+ extended_data.resize(data.size() * 4);
- PoolVector<uint8_t>::Write ex_w = extended_data.write();
- uint8_t *dest = ex_w.ptr();
+ PoolVector<uint8_t>::Write ex_w = extended_data.write();
+ uint8_t *dest = ex_w.ptr();
- const int num_pixels = width * height;
+ const int num_pixels = width * height;
- for (int i = 0; i < num_pixels; i++) {
- dest[0] = pal[write_buffer[i] * 4 + 0];
- dest[1] = pal[write_buffer[i] * 4 + 1];
- dest[2] = pal[write_buffer[i] * 4 + 2];
- dest[3] = pal[write_buffer[i] * 4 + 3];
+ for (int i = 0; i < num_pixels; i++) {
+ dest[0] = pal[write_buffer[i] * 4 + 0];
+ dest[1] = pal[write_buffer[i] * 4 + 1];
+ dest[2] = pal[write_buffer[i] * 4 + 2];
+ dest[3] = pal[write_buffer[i] * 4 + 3];
- dest += 4;
- }
- p_image->create(width, height, 0, Image::FORMAT_RGBA8, extended_data);
+ dest += 4;
}
+ p_image->create(width, height, 0, Image::FORMAT_RGBA8, extended_data);
}
}
return err;
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index f1b3fa2ac6..5a76f32977 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -114,7 +114,7 @@ void CSGBrush::_regen_face_aabbs() {
faces.write[i].aabb.position = faces[i].vertices[0];
faces.write[i].aabb.expand_to(faces[i].vertices[1]);
faces.write[i].aabb.expand_to(faces[i].vertices[2]);
- faces.write[i].aabb.grow_by(faces[i].aabb.get_longest_axis_size() * 0.001); //make it a tad bigger to avoid num precision erros
+ faces.write[i].aabb.grow_by(faces[i].aabb.get_longest_axis_size() * 0.001); //make it a tad bigger to avoid num precision errors
}
}
diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp
index e6bfa5525d..0d26943af6 100644
--- a/modules/csg/csg_gizmos.cpp
+++ b/modules/csg/csg_gizmos.cpp
@@ -377,7 +377,7 @@ void CSGShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
break;
}
- p_gizmo->add_mesh(mesh, false, RID(), solid_material);
+ p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), solid_material);
}
if (Object::cast_to<CSGSphere>(cs)) {
diff --git a/modules/cvtt/SCsub b/modules/cvtt/SCsub
index 142af0c800..746b23ca28 100644
--- a/modules/cvtt/SCsub
+++ b/modules/cvtt/SCsub
@@ -6,19 +6,18 @@ Import('env_modules')
env_cvtt = env_modules.Clone()
# Thirdparty source files
-if env['builtin_squish']:
- thirdparty_dir = "#thirdparty/cvtt/"
- thirdparty_sources = [
- "ConvectionKernels.cpp"
- ]
+thirdparty_dir = "#thirdparty/cvtt/"
+thirdparty_sources = [
+ "ConvectionKernels.cpp"
+]
- thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
+thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_cvtt.Prepend(CPPPATH=[thirdparty_dir])
+env_cvtt.Prepend(CPPPATH=[thirdparty_dir])
- env_thirdparty = env_cvtt.Clone()
- env_thirdparty.disable_warnings()
- env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
+env_thirdparty = env_cvtt.Clone()
+env_thirdparty.disable_warnings()
+env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
# Godot source files
env_cvtt.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 7f52f5736c..8a05b6cfa3 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -64,9 +64,9 @@ typedef enum {
GODOT_PROPERTY_HINT_LAYERS_3D_RENDER,
GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS,
GODOT_PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
- GODOT_PROPERTY_HINT_DIR, ///< a directort path must be passed
+ GODOT_PROPERTY_HINT_DIR, ///< a directory path must be passed
GODOT_PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
- GODOT_PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed
+ GODOT_PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
GODOT_PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
GODOT_PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
GODOT_PROPERTY_HINT_PLACEHOLDER_TEXT, ///< used to set a placeholder text for string properties
diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp
index 9de073fc8e..22898a73ce 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -200,7 +200,7 @@ void PluginScriptLanguage::get_recognized_extensions(List<String> *p_extensions)
}
void PluginScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const {
- // TODO: provid this statically in `godot_pluginscript_language_desc` ?
+ // TODO: provide this statically in `godot_pluginscript_language_desc` ?
if (_desc.get_public_functions) {
Array functions;
_desc.get_public_functions(_data, (godot_array *)&functions);
@@ -212,7 +212,7 @@ void PluginScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) c
}
void PluginScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const {
- // TODO: provid this statically in `godot_pluginscript_language_desc` ?
+ // TODO: provide this statically in `godot_pluginscript_language_desc` ?
if (_desc.get_public_constants) {
Dictionary constants;
_desc.get_public_constants(_data, (godot_dictionary *)&constants);
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index be131c5402..212ff51b80 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -149,7 +149,7 @@ void VideoStreamPlaybackGDNative::update(float p_delta) {
if (mix_callback) {
if (pcm_write_idx >= 0) {
// Previous remains
- int mixed = mix_callback(mix_udata, pcm, samples_decoded);
+ int mixed = mix_callback(mix_udata, pcm + pcm_write_idx * num_channels, samples_decoded);
if (mixed == samples_decoded) {
pcm_write_idx = -1;
} else {
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 5dab063061..c8ec80c101 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -99,7 +99,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
#endif
instance->owner->set_script_instance(instance);
- /* STEP 2, INITIALIZE AND CONSRTUCT */
+ /* STEP 2, INITIALIZE AND CONSTRUCT */
#ifndef NO_THREADS
GDScriptLanguage::singleton->lock->lock();
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7166189416..dea2225e91 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1520,8 +1520,16 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
if (ret2 < 0)
return ERR_PARSE_ERROR;
+ int message_ret = 0;
+ if (as->message) {
+ message_ret = _parse_expression(codegen, as->message, p_stack_level + 1, false);
+ if (message_ret < 0)
+ return ERR_PARSE_ERROR;
+ }
+
codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSERT);
codegen.opcodes.push_back(ret2);
+ codegen.opcodes.push_back(message_ret);
#endif
} break;
case GDScriptParser::Node::TYPE_BREAKPOINT: {
@@ -2064,7 +2072,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
}
instance->owner->set_script_instance(instance);
- /* STEP 2, INITIALIZE AND CONSRTUCT */
+ /* STEP 2, INITIALIZE AND CONSTRUCT */
Variant::CallError ce;
p_script->initializer->call(instance, NULL, 0, ce);
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 68f2a9473e..bdeea9cef3 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -1475,20 +1475,25 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSERT) {
- CHECK_SPACE(2);
+ CHECK_SPACE(3);
#ifdef DEBUG_ENABLED
GET_VARIANT_PTR(test, 1);
+ GET_VARIANT_PTR(message, 2);
bool result = test->booleanize();
if (!result) {
-
- err_text = "Assertion failed.";
+ const String &message_str = *message;
+ if (message_str.empty()) {
+ err_text = "Assertion failed.";
+ } else {
+ err_text = "Assertion failed: " + message_str;
+ }
OPCODE_BREAK;
}
#endif
- ip += 2;
+ ip += 3;
}
DISPATCH_OPCODE;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index e96bf0238a..967b0c83ae 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -1207,7 +1207,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (_get_completable_identifier(COMPLETION_INDEX, identifier)) {
if (identifier == StringName()) {
- identifier = "@temp"; //so it parses allright
+ identifier = "@temp"; //so it parses alright
}
completion_node = op;
@@ -1399,9 +1399,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
unary = true;
break;
case OperatorNode::OP_NEG:
- priority = 1;
- unary = true;
- break;
case OperatorNode::OP_POS:
priority = 1;
unary = true;
@@ -2846,15 +2843,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
assigned = subexpr;
} else {
- ConstantNode *c = alloc_node<ConstantNode>();
- if (lv->datatype.has_type && lv->datatype.kind == DataType::BUILTIN) {
- Variant::CallError err;
- c->value = Variant::construct(lv->datatype.builtin_type, NULL, 0, err);
- } else {
- c->value = Variant();
- }
- c->line = var_line;
- assigned = c;
+ assigned = _get_default_value_for_type(lv->datatype, var_line);
}
lv->assign = assigned;
//must be added later, to avoid self-referencing.
@@ -3280,15 +3269,36 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
case GDScriptTokenizer::TK_PR_ASSERT: {
tokenizer->advance();
- Node *condition = _parse_and_reduce_expression(p_block, p_static);
- if (!condition) {
- if (_recover_from_completion()) {
- break;
- }
+
+ if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after assert");
+ return;
+ }
+
+ tokenizer->advance();
+
+ Vector<Node *> args;
+ const bool result = _parse_arguments(p_block, args, p_static);
+ if (!result) {
+ return;
+ }
+
+ if (args.empty() || args.size() > 2) {
+ _set_error("Wrong number of arguments, expected 1 or 2");
return;
}
+
AssertNode *an = alloc_node<AssertNode>();
- an->condition = condition;
+ an->condition = _reduce_expression(args[0], p_static);
+
+ if (args.size() == 2) {
+ an->message = _reduce_expression(args[1], p_static);
+ } else {
+ ConstantNode *message_node = alloc_node<ConstantNode>();
+ message_node->value = String();
+ an->message = message_node;
+ }
+
p_block->statements.push_back(an);
if (!_end_statement()) {
@@ -3533,6 +3543,15 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
+ if (p_class->classname_used && ProjectSettings::get_singleton()->has_setting("autoload/" + p_class->name)) {
+ const String autoload_path = ProjectSettings::get_singleton()->get_setting("autoload/" + p_class->name);
+ if (autoload_path.begins_with("*")) {
+ // It's a singleton, and not just a regular AutoLoad script.
+ _set_error("The class \"" + p_class->name + "\" conflicts with the AutoLoad singleton of the same name, and is therefore redundant. Remove the class_name declaration to fix this error.");
+ }
+ return;
+ }
+
tokenizer->advance(2);
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
@@ -4839,35 +4858,29 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- Variant::Type initial_type = member.data_type.has_type ? member.data_type.builtin_type : member._export.type;
+ Node *expr;
- if (initial_type != Variant::NIL && initial_type != Variant::OBJECT) {
- IdentifierNode *id = alloc_node<IdentifierNode>();
- id->name = member.identifier;
-
- Node *expr;
+ if (member.data_type.has_type) {
+ expr = _get_default_value_for_type(member.data_type);
+ } else {
+ DataType exported_type;
+ exported_type.has_type = true;
+ exported_type.kind = DataType::BUILTIN;
+ exported_type.builtin_type = member._export.type;
+ expr = _get_default_value_for_type(exported_type);
+ }
- // Make sure arrays and dictionaries are not shared
- if (initial_type == Variant::ARRAY) {
- expr = alloc_node<ArrayNode>();
- } else if (initial_type == Variant::DICTIONARY) {
- expr = alloc_node<DictionaryNode>();
- } else {
- ConstantNode *cn = alloc_node<ConstantNode>();
- Variant::CallError ce2;
- cn->value = Variant::construct(initial_type, NULL, 0, ce2);
- expr = cn;
- }
+ IdentifierNode *id = alloc_node<IdentifierNode>();
+ id->name = member.identifier;
- OperatorNode *op = alloc_node<OperatorNode>();
- op->op = OperatorNode::OP_INIT_ASSIGN;
- op->arguments.push_back(id);
- op->arguments.push_back(expr);
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op = OperatorNode::OP_INIT_ASSIGN;
+ op->arguments.push_back(id);
+ op->arguments.push_back(expr);
- p_class->initializer->statements.push_back(op);
+ p_class->initializer->statements.push_back(op);
- member.initial_assignment = op;
- }
+ member.initial_assignment = op;
}
if (autoexport && member.data_type.has_type) {
@@ -5727,28 +5740,35 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source,
}
}
- // Still look for class constants in parent script
+ // Still look for class constants in parent scripts
if (!found && (base_type.kind == DataType::GDSCRIPT || base_type.kind == DataType::SCRIPT)) {
Ref<Script> scr = base_type.script_type;
ERR_FAIL_COND_V(scr.is_null(), result);
- Map<StringName, Variant> constants;
- scr->get_constants(&constants);
+ while (scr.is_valid()) {
+ Map<StringName, Variant> constants;
+ scr->get_constants(&constants);
- if (constants.has(id)) {
- Ref<GDScript> gds = constants[id];
+ if (constants.has(id)) {
+ Ref<GDScript> gds = constants[id];
- if (gds.is_valid()) {
- result.kind = DataType::GDSCRIPT;
- result.script_type = gds;
- found = true;
- } else {
- Ref<Script> scr2 = constants[id];
- if (scr2.is_valid()) {
- result.kind = DataType::SCRIPT;
- result.script_type = scr2;
+ if (gds.is_valid()) {
+ result.kind = DataType::GDSCRIPT;
+ result.script_type = gds;
found = true;
+ } else {
+ Ref<Script> scr2 = constants[id];
+ if (scr2.is_valid()) {
+ result.kind = DataType::SCRIPT;
+ result.script_type = scr2;
+ found = true;
+ }
}
}
+ if (found) {
+ break;
+ } else {
+ scr = scr->get_base_script();
+ }
}
}
@@ -6140,6 +6160,31 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data
return false;
}
+GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType &p_type, int p_line) {
+ Node *result;
+
+ if (p_type.has_type && p_type.kind == DataType::BUILTIN && p_type.builtin_type != Variant::NIL && p_type.builtin_type != Variant::OBJECT) {
+ if (p_type.builtin_type == Variant::ARRAY) {
+ result = alloc_node<ArrayNode>();
+ } else if (p_type.builtin_type == Variant::DICTIONARY) {
+ result = alloc_node<DictionaryNode>();
+ } else {
+ ConstantNode *c = alloc_node<ConstantNode>();
+ Variant::CallError err;
+ c->value = Variant::construct(p_type.builtin_type, NULL, 0, err);
+ result = c;
+ }
+ } else {
+ ConstantNode *c = alloc_node<ConstantNode>();
+ c->value = Variant();
+ result = c;
+ }
+
+ result->line = p_line;
+
+ return result;
+}
+
GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
#ifdef DEBUG_ENABLED
if (p_node->get_datatype().has_type && p_node->type != Node::TYPE_ARRAY && p_node->type != Node::TYPE_DICTIONARY) {
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 72aa819a8c..04ce9cf4c6 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -481,7 +481,12 @@ public:
struct AssertNode : public Node {
Node *condition;
- AssertNode() { type = TYPE_ASSERT; }
+ Node *message;
+ AssertNode() :
+ condition(0),
+ message(0) {
+ type = TYPE_ASSERT;
+ }
};
struct BreakpointNode : public Node {
@@ -610,6 +615,7 @@ private:
bool _get_function_signature(DataType &p_base_type, const StringName &p_function, DataType &r_return_type, List<DataType> &r_arg_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) const;
bool _get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type) const;
bool _is_type_compatible(const DataType &p_container, const DataType &p_expression, bool p_allow_implicit_conversion = false) const;
+ Node *_get_default_value_for_type(const DataType &p_type, int p_line = -1);
DataType _reduce_node_type(Node *p_node);
DataType _reduce_function_call_type(const OperatorNode *p_call);
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 45f9ec9c6a..9e8727ec58 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -189,6 +189,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
lsp::DocumentSymbol symbol;
const GDScriptParser::ClassNode::Constant &c = E->value();
const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression);
+ ERR_FAIL_COND(!node);
symbol.name = E->key();
symbol.kind = lsp::SymbolKind::Constant;
symbol.deprecated = false;
@@ -674,6 +675,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
const GDScriptParser::ClassNode::Constant &c = E->value();
const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression);
+ ERR_FAIL_COND_V(!node, class_api);
Dictionary api;
api["name"] = E->key();
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index afe461b68e..ce3de9bc3b 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -100,9 +100,10 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
String root_uri = p_params["rootUri"];
String root = p_params["rootPath"];
- bool is_same_workspace = root == workspace->root;
+ bool is_same_workspace;
+#ifndef WINDOWS_ENABLED
is_same_workspace = root.to_lower() == workspace->root.to_lower();
-#ifdef WINDOWS_ENABLED
+#else
is_same_workspace = root.replace("\\", "/").to_lower() == workspace->root.to_lower();
#endif
@@ -142,6 +143,7 @@ void GDScriptLanguageProtocol::poll() {
Error GDScriptLanguageProtocol::start(int p_port) {
if (server == NULL) {
server = dynamic_cast<WebSocketServer *>(ClassDB::instance("WebSocketServer"));
+ ERR_FAIL_COND_V(!server, FAILED);
server->set_buffers(8192, 1024, 8192, 1024); // 8mb should be way more than enough
server->connect("data_received", this, "on_data_received");
server->connect("client_connected", this, "on_client_connected");
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 9bea4557ac..62c212a2bd 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -64,7 +64,7 @@ void GDScriptLanguageServer::thread_main(void *p_userdata) {
void GDScriptLanguageServer::start() {
int port = (int)_EDITOR_GET("network/language_server/remote_port");
if (protocol.start(port) == OK) {
- EditorNode::get_log()->add_message("** GDScript Language Server Started **");
+ EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR);
ERR_FAIL_COND(thread != NULL || thread_exit);
thread_exit = false;
thread = Thread::create(GDScriptLanguageServer::thread_main, this);
@@ -78,7 +78,7 @@ void GDScriptLanguageServer::stop() {
memdelete(thread);
thread = NULL;
protocol.stop();
- EditorNode::get_log()->add_message("** GDScript Language Server Stopped **");
+ EditorNode::get_log()->add_message("--- GDScript language server stopped ---", EditorLog::MSG_TYPE_EDITOR);
}
void register_lsp_types() {
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index f211fae526..7c58c7aa15 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -380,8 +380,8 @@ GDScriptTextDocument::~GDScriptTextDocument() {
memdelete(file_checker);
}
-void GDScriptTextDocument::sync_script_content(const String &p_uri, const String &p_content) {
- String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_uri);
+void GDScriptTextDocument::sync_script_content(const String &p_path, const String &p_content) {
+ String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_path);
GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content);
}
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 07b4f7f596..7e2986ca85 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -884,9 +884,15 @@ void GridMapEditor::update_palette() {
if (mesh_library.is_null()) {
last_mesh_library = NULL;
+ search_box->set_text("");
+ search_box->set_editable(false);
+ info_message->show();
return;
}
+ search_box->set_editable(true);
+ info_message->hide();
+
Vector<int> ids;
ids = mesh_library->get_item_list();
@@ -1069,6 +1075,7 @@ void GridMapEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
+ get_tree()->connect("node_removed", this, "_node_removed");
mesh_library_palette->connect("item_selected", this, "_item_selected_cbk");
for (int i = 0; i < 3; i++) {
@@ -1085,6 +1092,7 @@ void GridMapEditor::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
+ get_tree()->disconnect("node_removed", this, "_node_removed");
_clear_clipboard_data();
for (int i = 0; i < 3; i++) {
@@ -1198,6 +1206,7 @@ void GridMapEditor::_bind_methods() {
ClassDB::bind_method("_floor_changed", &GridMapEditor::_floor_changed);
ClassDB::bind_method("_floor_mouse_exited", &GridMapEditor::_floor_mouse_exited);
ClassDB::bind_method("_set_selection", &GridMapEditor::_set_selection);
+ ClassDB::bind_method("_node_removed", &GridMapEditor::_node_removed);
ClassDB::bind_method(D_METHOD("_set_display_mode", "mode"), &GridMapEditor::_set_display_mode);
}
@@ -1296,6 +1305,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
search_box = memnew(LineEdit);
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ search_box->set_placeholder(TTR("Filter meshes"));
hb->add_child(search_box);
search_box->connect("text_changed", this, "_text_changed");
search_box->connect("gui_input", this, "_sbox_input");
@@ -1331,6 +1341,14 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
add_child(mesh_library_palette);
mesh_library_palette->set_v_size_flags(SIZE_EXPAND_FILL);
+ info_message = memnew(Label);
+ info_message->set_text(TTR("Give a MeshLibrary resource to this GridMap to use its meshes."));
+ info_message->set_valign(Label::VALIGN_CENTER);
+ info_message->set_align(Label::ALIGN_CENTER);
+ info_message->set_autowrap(true);
+ info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE);
+ mesh_library_palette->add_child(info_message);
+
edit_axis = Vector3::AXIS_Y;
edit_floor[0] = -1;
edit_floor[1] = -1;
@@ -1346,7 +1364,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
paste_mesh = VisualServer::get_singleton()->mesh_create();
{
- //selection mesh create
+ // Selection mesh create.
PoolVector<Vector3> lines;
PoolVector<Vector3> triangles;
@@ -1424,7 +1442,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
inner_mat.instance();
inner_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.2));
- //inner_mat->set_flag(SpatialMaterial::FLAG_ONTOP, true);
inner_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
inner_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
@@ -1444,7 +1461,6 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
selection_floor_mat->set_on_top_of_alpha();
selection_floor_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
selection_floor_mat->set_line_width(3.0);
- //selection_floor_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
d[VS::ARRAY_VERTEX] = lines;
VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d);
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index d174ac1035..103913485f 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -197,12 +197,16 @@ class GridMapEditor : public VBoxContainer {
RID instance;
};
+ ItemList *mesh_library_palette;
+ Label *info_message;
+
+ EditorNode *editor;
+
void update_grid();
void _configure();
void _menu_option(int);
void update_palette();
void _set_display_mode(int p_mode);
- ItemList *mesh_library_palette;
void _item_selected_cbk(int idx);
void _update_cursor_transform();
void _update_cursor_instance();
@@ -227,7 +231,6 @@ class GridMapEditor : public VBoxContainer {
void _delete_selection();
void _fill_selection();
- EditorNode *editor;
bool do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click);
friend class GridMapEditorPlugin;
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index f751719531..4c1ebd8d74 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -18,7 +18,7 @@ android_arch_dirs = {
def get_android_out_dir(env):
- return os.path.join(Dir('#platform/android/java/libs').abspath,
+ return os.path.join(Dir('#platform/android/java/lib/libs').abspath,
'release' if env['target'] == 'release' else 'debug',
android_arch_dirs[env['android_arch']])
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 1888bb3cb9..74710db224 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -1785,6 +1785,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.append("uint32_t get_bindings_version() { return ");
output.append(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n");
+ output.append("uint32_t get_cs_glue_version() { return ");
+ output.append(String::num_uint64(CS_GLUE_VERSION) + "; }\n");
+
output.append("\nvoid register_generated_icalls() " OPEN_BLOCK);
output.append("\tgodot_register_glue_header_icalls();\n");
diff --git a/modules/mono/glue/Managed/Files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs
index f3dc9d8490..99542d0c0a 100644
--- a/modules/mono/glue/Managed/Files/Rect2.cs
+++ b/modules/mono/glue/Managed/Files/Rect2.cs
@@ -157,13 +157,13 @@ namespace Godot
public bool Intersects(Rect2 b)
{
- if (_position.x > b._position.x + b._size.x)
+ if (_position.x >= b._position.x + b._size.x)
return false;
- if (_position.x + _size.x < b._position.x)
+ if (_position.x + _size.x <= b._position.x)
return false;
- if (_position.y > b._position.y + b._size.y)
+ if (_position.y >= b._position.y + b._size.y)
return false;
- if (_position.y + _size.y < b._position.y)
+ if (_position.y + _size.y <= b._position.y)
return false;
return true;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index cd111abd4d..915a01af7e 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -44,7 +44,6 @@
#include "core/project_settings.h"
#include "../csharp_script.h"
-#include "../glue/cs_glue_version.gen.h"
#include "../godotsharp_dirs.h"
#include "../utils/path_utils.h"
#include "gd_mono_class.h"
@@ -395,23 +394,24 @@ uint64_t get_core_api_hash();
uint64_t get_editor_api_hash();
#endif
uint32_t get_bindings_version();
+uint32_t get_cs_glue_version();
void register_generated_icalls();
#else
uint64_t get_core_api_hash() {
- CRASH_NOW();
GD_UNREACHABLE();
}
#ifdef TOOLS_ENABLED
uint64_t get_editor_api_hash() {
- CRASH_NOW();
GD_UNREACHABLE();
}
#endif
uint32_t get_bindings_version() {
- CRASH_NOW();
+ GD_UNREACHABLE();
+}
+uint32_t get_cs_glue_version() {
GD_UNREACHABLE();
}
@@ -687,7 +687,7 @@ bool GDMono::_load_core_api_assembly() {
APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(core_api_assembly, APIAssembly::API_CORE);
core_api_assembly_out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash ||
GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version ||
- CS_GLUE_VERSION != api_assembly_ver.cs_glue_version;
+ GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version;
if (!core_api_assembly_out_of_sync) {
GDMonoUtils::update_godot_api_cache();
@@ -722,7 +722,7 @@ bool GDMono::_load_editor_api_assembly() {
APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(editor_api_assembly, APIAssembly::API_EDITOR);
editor_api_assembly_out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash ||
GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version ||
- CS_GLUE_VERSION != api_assembly_ver.cs_glue_version;
+ GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version;
} else {
editor_api_assembly_out_of_sync = false;
}
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 70389b6729..6bed1742eb 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -578,6 +578,10 @@ void VisualScript::get_data_connection_list(const StringName &p_func, List<DataC
}
}
+void VisualScript::set_tool_enabled(bool p_enabled) {
+ is_tool_script = p_enabled;
+}
+
void VisualScript::add_variable(const StringName &p_name, const Variant &p_default_value, bool p_export) {
ERR_FAIL_COND(instances.size());
@@ -894,7 +898,7 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) {
#ifdef TOOLS_ENABLED
- if (!ScriptServer::is_scripting_enabled()) {
+ if (!ScriptServer::is_scripting_enabled() && !is_tool_script) {
PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(VisualScriptLanguage::singleton, Ref<Script>((Script *)this), p_this));
placeholders.insert(sins);
@@ -958,7 +962,7 @@ Error VisualScript::reload(bool p_keep_state) {
bool VisualScript::is_tool() const {
- return false;
+ return is_tool_script;
}
bool VisualScript::is_valid() const {
@@ -1164,6 +1168,11 @@ void VisualScript::_set_data(const Dictionary &p_data) {
data_connect(name, data_connections[j + 0], data_connections[j + 1], data_connections[j + 2], data_connections[j + 3]);
}
}
+
+ if (d.has("is_tool_script"))
+ is_tool_script = d["is_tool_script"];
+ else
+ is_tool_script = false;
}
Dictionary VisualScript::_get_data() const {
@@ -1246,6 +1255,8 @@ Dictionary VisualScript::_get_data() const {
d["functions"] = funcs;
+ d["is_tool_script"] = is_tool_script;
+
return d;
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 098c28370d..14927c4363 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -247,6 +247,8 @@ private:
Map<Object *, VisualScriptInstance *> instances;
+ bool is_tool_script;
+
#ifdef TOOLS_ENABLED
Set<PlaceHolderScriptInstance *> placeholders;
//void _update_placeholder(PlaceHolderScriptInstance *p_placeholder);
@@ -273,6 +275,7 @@ public:
Vector2 get_function_scroll(const StringName &p_name) const;
void get_function_list(List<StringName> *r_functions) const;
int get_function_node_id(const StringName &p_name) const;
+ void set_tool_enabled(bool p_enabled);
void add_node(const StringName &p_func, int p_id, const Ref<VisualScriptNode> &p_node, const Point2 &p_pos = Point2());
void remove_node(const StringName &p_func, int p_id);
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 8faa342bbe..7262dde359 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -2227,6 +2227,10 @@ void VisualScriptEditor::_change_base_type() {
select_base_type->popup_create(true, true);
}
+void VisualScriptEditor::_toggle_tool_script() {
+ script->set_tool_enabled(!script->is_tool());
+}
+
void VisualScriptEditor::clear_edit_menu() {
memdelete(edit_menu);
memdelete(left_vsplit);
@@ -3448,6 +3452,7 @@ void VisualScriptEditor::_bind_methods() {
ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members);
ClassDB::bind_method("_change_base_type", &VisualScriptEditor::_change_base_type);
ClassDB::bind_method("_change_base_type_callback", &VisualScriptEditor::_change_base_type_callback);
+ ClassDB::bind_method("_toggle_tool_script", &VisualScriptEditor::_toggle_tool_script);
ClassDB::bind_method("_node_selected", &VisualScriptEditor::_node_selected);
ClassDB::bind_method("_node_moved", &VisualScriptEditor::_node_moved);
ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node);
@@ -3533,6 +3538,11 @@ VisualScriptEditor::VisualScriptEditor() {
left_vb->set_v_size_flags(SIZE_EXPAND_FILL);
//left_vb->set_custom_minimum_size(Size2(230, 1) * EDSCALE);
+ CheckButton *tool_script_check = memnew(CheckButton);
+ tool_script_check->set_text(TTR("Make Tool:"));
+ left_vb->add_child(tool_script_check);
+ tool_script_check->connect("pressed", this, "_toggle_tool_script");
+
base_type_select = memnew(Button);
left_vb->add_margin_child(TTR("Base Type:"), base_type_select);
base_type_select->connect("pressed", this, "_change_base_type");
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index 4f302d1d72..5df9b1a004 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -186,6 +186,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _node_filter_changed(const String &p_text);
void _change_base_type_callback();
void _change_base_type();
+ void _toggle_tool_script();
void _member_selected();
void _member_edited();
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 1bd8161fa7..65172a12c0 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -50,30 +50,8 @@ if lib_arch_dir != '':
else: # release_debug, debug
lib_type_dir = 'debug'
- out_dir = '#platform/android/java/libs/' + lib_type_dir + '/' + lib_arch_dir
+ out_dir = '#platform/android/java/lib/libs/' + lib_type_dir + '/' + lib_arch_dir
env_android.Command(out_dir + '/libgodot_android.so', '#bin/libgodot' + env['SHLIBSUFFIX'], Move("$TARGET", "$SOURCE"))
stl_lib_path = str(env['ANDROID_NDK_ROOT']) + '/sources/cxx-stl/llvm-libc++/libs/' + lib_arch_dir + '/libc++_shared.so'
env_android.Command(out_dir + '/libc++_shared.so', stl_lib_path, Copy("$TARGET", "$SOURCE"))
-
-# Zip android/java folder for the source export template.
-print("Archiving platform/android/java as bin/android_source.zip...")
-import os
-import zipfile
-# Change dir to avoid have zipped paths start from the android/java folder.
-olddir = os.getcwd()
-os.chdir(Dir('#platform/android/java').abspath)
-bindir = Dir('#bin').abspath
-# Make 'bin' dir if missing, can happen on fresh clone.
-if not os.path.exists(bindir):
- os.makedirs(bindir)
-zipf = zipfile.ZipFile(os.path.join(bindir, 'android_source.zip'), 'w', zipfile.ZIP_DEFLATED)
-exclude_dirs = ['.gradle', 'build', 'libs', 'patches']
-for root, dirs, files in os.walk('.', topdown=True):
- # Change 'dirs' in place to exclude folders we don't want.
- # https://stackoverflow.com/a/19859907
- dirs[:] = [d for d in dirs if d not in exclude_dirs]
- for f in files:
- zipf.write(os.path.join(root, f))
-zipf.close()
-os.chdir(olddir)
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 441fa38bff..b37f04c4f8 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -794,6 +794,10 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
string_table.write[attr_value] = version_name;
}
+ if (tname == "instrumentation" && attrname == "targetPackage") {
+ string_table.write[attr_value] = get_package_name(package_name);
+ }
+
if (tname == "activity" && attrname == "screenOrientation") {
encode_uint32(orientation == 0 ? 0 : 1, &p_manifest.write[iofs + 16]);
@@ -1304,7 +1308,7 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/opengl_debug"), false));
- for (unsigned int i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
+ for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icons[i].option_id, PROPERTY_HINT_FILE, "*.png"), ""));
}
@@ -1470,8 +1474,8 @@ public:
if (use_remote) {
if (use_reverse) {
- static const char *const msg = "** Device API >= 21; debugging over USB **";
- EditorNode::get_singleton()->get_log()->add_message(msg);
+ static const char *const msg = "--- Device API >= 21; debugging over USB ---";
+ EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR);
print_line(String(msg).to_upper());
args.clear();
@@ -1511,8 +1515,8 @@ public:
}
} else {
- static const char *const msg = "** Device API < 21; debugging over Wi-Fi **";
- EditorNode::get_singleton()->get_log()->add_message(msg);
+ static const char *const msg = "--- Device API < 21; debugging over Wi-Fi ---";
+ EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR);
print_line(String(msg).to_upper());
}
}
@@ -1533,7 +1537,7 @@ public:
args.push_back("-a");
args.push_back("android.intent.action.MAIN");
args.push_back("-n");
- args.push_back(get_package_name(package_name) + "/org.godotengine.godot.Godot");
+ args.push_back(get_package_name(package_name) + "/com.godot.game.GodotApp");
err = OS::get_singleton()->execute(adb, args, true, NULL, NULL, &rv);
if (err || rv != 0) {
@@ -2096,7 +2100,7 @@ public:
if (file == "res/drawable-nodpi-v4/icon.png") {
bool found = false;
- for (unsigned int i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
+ for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges();
if (icon_path != "" && icon_path.ends_with(".png")) {
FileAccess *f = FileAccess::open(icon_path, FileAccess::READ);
@@ -2222,7 +2226,7 @@ public:
APKExportData ed;
ed.ep = &ep;
ed.apk = unaligned_apk;
- for (unsigned int i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
+ for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges();
if (icon_path != "" && icon_path.ends_with(".png") && FileAccess::exists(icon_path)) {
Vector<uint8_t> data = FileAccess::get_file_as_array(icon_path);
diff --git a/platform/android/java/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 5114aeb8c5..d5f4ba18d6 100644
--- a/platform/android/java/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -41,7 +41,7 @@
android:value="xr_mode_metadata_value" />
<activity
- android:name="org.godotengine.godot.Godot"
+ android:name=".GodotApp"
android:label="@string/godot_project_name_string"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:launchMode="singleTask"
@@ -56,18 +56,10 @@
</intent-filter>
</activity>
- <service android:name="org.godotengine.godot.GodotDownloaderService" />
-
<!-- Custom application XML added by add-ons. -->
<!--CHUNK_APPLICATION_BEGIN-->
<!--CHUNK_APPLICATION_END-->
</application>
- <instrumentation
- android:icon="@drawable/icon"
- android:label="@string/godot_project_name_string"
- android:name="org.godotengine.godot.GodotInstrumentation"
- android:targetPackage="org.godotengine.game" />
-
</manifest>
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
new file mode 100644
index 0000000000..9f64c3dc8a
--- /dev/null
+++ b/platform/android/java/app/build.gradle
@@ -0,0 +1,121 @@
+// Gradle build config for Godot Engine's Android port.
+//
+// Do not remove/modify comments ending with BEGIN/END, they are used to inject
+// addon-specific configuration.
+apply from: 'config.gradle'
+
+buildscript {
+ apply from: 'config.gradle'
+
+ repositories {
+ google()
+ jcenter()
+//CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN
+//CHUNK_BUILDSCRIPT_REPOSITORIES_END
+ }
+ dependencies {
+ classpath libraries.androidGradlePlugin
+//CHUNK_BUILDSCRIPT_DEPENDENCIES_BEGIN
+//CHUNK_BUILDSCRIPT_DEPENDENCIES_END
+ }
+}
+
+apply plugin: 'com.android.application'
+
+allprojects {
+ repositories {
+ mavenCentral()
+ google()
+ jcenter()
+//CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN
+//CHUNK_ALLPROJECTS_REPOSITORIES_END
+ }
+}
+
+dependencies {
+ if (rootProject.findProject(":lib")) {
+ implementation project(":lib")
+ } else {
+ // Custom build mode. In this scenario this project is the only one around and the Godot
+ // library is available through the pre-generated godot-lib.*.aar android archive files.
+ debugImplementation fileTree(dir: 'libs/debug', include: ['*.jar', '*.aar'])
+ releaseImplementation fileTree(dir: 'libs/release', include: ['*.jar', '*.aar'])
+ }
+//CHUNK_DEPENDENCIES_BEGIN
+//CHUNK_DEPENDENCIES_END
+}
+
+android {
+ compileSdkVersion versions.compileSdk
+ buildToolsVersion versions.buildTools
+
+ defaultConfig {
+ // Feel free to modify the application id to your own.
+ applicationId "com.godot.game"
+ minSdkVersion versions.minSdk
+ targetSdkVersion versions.targetSdk
+//CHUNK_ANDROID_DEFAULTCONFIG_BEGIN
+//CHUNK_ANDROID_DEFAULTCONFIG_END
+ }
+
+ lintOptions {
+ abortOnError false
+ disable 'MissingTranslation', 'UnusedResources'
+ }
+
+ packagingOptions {
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/NOTICE'
+ }
+
+ // Both signing and zip-aligning will be done at export time
+ buildTypes.all { buildType ->
+ buildType.zipAlignEnabled false
+ buildType.signingConfig null
+ }
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = [
+ 'src'
+//DIR_SRC_BEGIN
+//DIR_SRC_END
+ ]
+ res.srcDirs = [
+ 'res'
+//DIR_RES_BEGIN
+//DIR_RES_END
+ ]
+ aidl.srcDirs = [
+ 'aidl'
+//DIR_AIDL_BEGIN
+//DIR_AIDL_END
+ ]
+ assets.srcDirs = [
+ 'assets'
+//DIR_ASSETS_BEGIN
+//DIR_ASSETS_END
+ ]
+ }
+ debug.jniLibs.srcDirs = [
+ 'libs/debug'
+//DIR_JNI_DEBUG_BEGIN
+//DIR_JNI_DEBUG_END
+ ]
+ release.jniLibs.srcDirs = [
+ 'libs/release'
+//DIR_JNI_RELEASE_BEGIN
+//DIR_JNI_RELEASE_END
+ ]
+ }
+
+ applicationVariants.all { variant ->
+ variant.outputs.all { output ->
+ output.outputFileName = "android_${variant.name}.apk"
+ }
+ }
+}
+
+//CHUNK_GLOBAL_BEGIN
+//CHUNK_GLOBAL_END
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
new file mode 100644
index 0000000000..20c3123221
--- /dev/null
+++ b/platform/android/java/app/config.gradle
@@ -0,0 +1,12 @@
+ext.versions = [
+ androidGradlePlugin : '3.4.2',
+ compileSdk : 28,
+ minSdk : 18,
+ targetSdk : 28,
+ buildTools : '28.0.3',
+
+]
+
+ext.libraries = [
+ androidGradlePlugin : "com.android.tools.build:gradle:$versions.androidGradlePlugin"
+]
diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java
new file mode 100644
index 0000000000..fabd7b1dbb
--- /dev/null
+++ b/platform/android/java/app/src/com/godot/game/GodotApp.java
@@ -0,0 +1,10 @@
+package com.godot.game;
+
+import org.godotengine.godot.Godot;
+
+/**
+ * Template activity for Godot Android custom builds.
+ * Feel free to extend and modify this class for your custom logic.
+ */
+public class GodotApp extends Godot {
+}
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index 0f8499ba91..99ffa937b0 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -1,111 +1,95 @@
-// Gradle build config for Godot Engine's Android port.
-//
-// Do not remove/modify comments ending with BEGIN/END, they are used to inject
-// addon-specific configuration.
+apply from: 'app/config.gradle'
buildscript {
+ apply from: 'app/config.gradle'
+
repositories {
google()
jcenter()
-//CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN
-//CHUNK_BUILDSCRIPT_REPOSITORIES_END
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.4.2'
-//CHUNK_BUILDSCRIPT_DEPENDENCIES_BEGIN
-//CHUNK_BUILDSCRIPT_DEPENDENCIES_END
+ classpath libraries.androidGradlePlugin
}
}
-apply plugin: 'com.android.application'
-
allprojects {
repositories {
- mavenCentral()
google()
jcenter()
-//CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN
-//CHUNK_ALLPROJECTS_REPOSITORIES_END
+ mavenCentral()
}
}
-dependencies {
- implementation "com.android.support:support-core-utils:28.0.0"
-//CHUNK_DEPENDENCIES_BEGIN
-//CHUNK_DEPENDENCIES_END
-}
+def binDir = "../../../bin/"
-android {
- compileSdkVersion 28
- buildToolsVersion "28.0.3"
- useLibrary 'org.apache.http.legacy'
-
- defaultConfig {
- minSdkVersion 18
- targetSdkVersion 28
-//CHUNK_ANDROID_DEFAULTCONFIG_BEGIN
-//CHUNK_ANDROID_DEFAULTCONFIG_END
- }
-
- lintOptions {
- abortOnError false
- disable 'MissingTranslation', 'UnusedResources'
- }
+/**
+ * Copy the generated 'android_debug.apk' binary template into the Godot bin directory.
+ * Depends on the app build task to ensure the binary is generated prior to copying.
+ */
+task copyDebugBinaryToBin(type: Copy) {
+ dependsOn ':app:build'
+ from('app/build/outputs/apk/debug')
+ into(binDir)
+ include('android_debug.apk')
+}
- packagingOptions {
- exclude 'META-INF/LICENSE'
- exclude 'META-INF/NOTICE'
- }
+/**
+ * Copy the generated 'android_release.apk' binary template into the Godot bin directory.
+ * Depends on the app build task to ensure the binary is generated prior to copying.
+ */
+task copyReleaseBinaryToBin(type: Copy) {
+ dependsOn ':app:build'
+ from('app/build/outputs/apk/release')
+ into(binDir)
+ include('android_release.apk')
+}
- // Both signing and zip-aligning will be done at export time
- buildTypes.all { buildType ->
- buildType.zipAlignEnabled false
- buildType.signingConfig null
- }
+/**
+ * Copy the Godot android library archive debug file into the app debug libs directory.
+ * Depends on the library build task to ensure the AAR file is generated prior to copying.
+ */
+task copyDebugAAR(type: Copy) {
+ dependsOn ':lib:build'
+ from('lib/build/outputs/aar')
+ into('app/libs/debug')
+ include('godot-lib.debug.aar')
+}
- sourceSets {
- main {
- manifest.srcFile 'AndroidManifest.xml'
- java.srcDirs = [
- 'src'
-//DIR_SRC_BEGIN
-//DIR_SRC_END
- ]
- res.srcDirs = [
- 'res'
-//DIR_RES_BEGIN
-//DIR_RES_END
- ]
- aidl.srcDirs = [
- 'aidl'
-//DIR_AIDL_BEGIN
-//DIR_AIDL_END
- ]
- assets.srcDirs = [
- 'assets'
-//DIR_ASSETS_BEGIN
-//DIR_ASSETS_END
- ]
- }
- debug.jniLibs.srcDirs = [
- 'libs/debug'
-//DIR_JNI_DEBUG_BEGIN
-//DIR_JNI_DEBUG_END
- ]
- release.jniLibs.srcDirs = [
- 'libs/release'
-//DIR_JNI_RELEASE_BEGIN
-//DIR_JNI_RELEASE_END
- ]
- }
+/**
+ * Copy the Godot android library archive release file into the app release libs directory.
+ * Depends on the library build task to ensure the AAR file is generated prior to copying.
+ */
+task copyReleaseAAR(type: Copy) {
+ dependsOn ':lib:build'
+ from('lib/build/outputs/aar')
+ into('app/libs/release')
+ include('godot-lib.release.aar')
+}
- // No longer used, as it's not useful for build source template
- //applicationVariants.all { variant ->
- // variant.outputs.all { output ->
- // output.outputFileName = "../../../../../../../bin/android_${variant.name}.apk"
- // }
- //}
+/**
+ * Generate Godot custom build template by zipping the source files from the app directory, as well
+ * as the AAR files generated by 'copyDebugAAR' and 'copyReleaseAAR'.
+ * The zip file also includes some gradle tools to allow building of the custom build.
+ */
+task zipCustomBuild(type: Zip) {
+ dependsOn 'copyDebugAAR'
+ dependsOn 'copyReleaseAAR'
+ from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradle.properties','gradlew', 'gradlew.bat', 'gradle/**']))
+ include '**/*'
+ archiveName 'android_source.zip'
+ destinationDir(file(binDir))
}
-//CHUNK_GLOBAL_BEGIN
-//CHUNK_GLOBAL_END
+/**
+ * Master task used to coordinate the tasks defined above to generate the set of Godot templates.
+ */
+task generateGodotTemplates(type: GradleBuild) {
+ tasks = [
+ // Copy the generated aar library files to the custom build directory.
+ 'copyDebugAAR', 'copyReleaseAAR',
+ // Zip the custom build directory.
+ 'zipCustomBuild',
+ // Copy the prebuilt binary templates to the bin directory.
+ 'copyDebugBinaryToBin', 'copyReleaseBinaryToBin',
+ ]
+}
diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
index 558870dad5..bf50265715 100644
--- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
+#Mon Sep 02 02:44:30 PDT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
new file mode 100644
index 0000000000..517fc403b2
--- /dev/null
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.godotengine.godot"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application>
+
+ <service android:name=".GodotDownloaderService" />
+
+ </application>
+
+ <instrumentation
+ android:icon="@drawable/icon"
+ android:label="@string/godot_project_name_string"
+ android:name=".GodotInstrumentation"
+ android:targetPackage="org.godotengine.godot" />
+
+</manifest>
diff --git a/misc/ide/jetbrains/CMakeLists.txt b/platform/android/java/lib/CMakeLists.txt
index b6e56e0778..d3bdf6a5f2 100644
--- a/misc/ide/jetbrains/CMakeLists.txt
+++ b/platform/android/java/lib/CMakeLists.txt
@@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
-set(GODOT_ROOT_DIR ../../..)
+set(GODOT_ROOT_DIR ../../../..)
# Get sources
file(GLOB_RECURSE SOURCES ${GODOT_ROOT_DIR}/*.c**)
diff --git a/platform/android/java/THIRDPARTY.md b/platform/android/java/lib/THIRDPARTY.md
index 2496b59263..2496b59263 100644
--- a/platform/android/java/THIRDPARTY.md
+++ b/platform/android/java/lib/THIRDPARTY.md
diff --git a/platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl b/platform/android/java/lib/aidl/com/android/vending/billing/IInAppBillingService.aidl
index 0f2bcae338..0f2bcae338 100644
--- a/platform/android/java/aidl/com/android/vending/billing/IInAppBillingService.aidl
+++ b/platform/android/java/lib/aidl/com/android/vending/billing/IInAppBillingService.aidl
diff --git a/platform/android/java/aidl/com/android/vending/licensing/ILicenseResultListener.aidl b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl
index 869cb16f68..869cb16f68 100644
--- a/platform/android/java/aidl/com/android/vending/licensing/ILicenseResultListener.aidl
+++ b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl
diff --git a/platform/android/java/aidl/com/android/vending/licensing/ILicensingService.aidl b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl
index 9541a2090c..9541a2090c 100644
--- a/platform/android/java/aidl/com/android/vending/licensing/ILicensingService.aidl
+++ b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl
diff --git a/misc/ide/jetbrains/build.gradle b/platform/android/java/lib/build.gradle
index dea81b4ea3..6d07504e45 100644
--- a/misc/ide/jetbrains/build.gradle
+++ b/platform/android/java/lib/build.gradle
@@ -1,60 +1,43 @@
-buildscript {
- repositories {
- google()
- jcenter()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:3.4.2'
- }
-}
-
-allprojects {
- repositories {
- google()
- jcenter()
- }
-}
-
apply plugin: 'com.android.library'
dependencies {
implementation "com.android.support:support-core-utils:28.0.0"
}
-def pathToRootDir = "../../../"
+def pathToRootDir = "../../../../"
// Note: Only keep the abis you support to speed up the gradle 'assemble' task.
def supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"]
android {
+ compileSdkVersion versions.compileSdk
+ buildToolsVersion versions.buildTools
+ useLibrary 'org.apache.http.legacy'
+
+ defaultConfig {
+ minSdkVersion versions.minSdk
+ targetSdkVersion versions.targetSdk
+ }
lintOptions {
abortOnError false
- disable "MissingTranslation", 'UnusedResources'
+ disable 'MissingTranslation', 'UnusedResources'
}
- compileSdkVersion 28
- buildToolsVersion "28.0.3"
- useLibrary 'org.apache.http.legacy'
-
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
- defaultConfig {
- minSdkVersion 18
- targetSdkVersion 28
- }
sourceSets {
main {
- manifest.srcFile "AndroidManifest.xml"
- java.srcDirs = ["${pathToRootDir}platform/android/java/src"]
- res.srcDirs = ["${pathToRootDir}platform/android/java/res"]
- aidl.srcDirs = ["${pathToRootDir}platform/android/java/aidl"]
- assets.srcDirs = ["${pathToRootDir}platform/android/java/assets"]
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ res.srcDirs = ['res']
+ aidl.srcDirs = ['aidl']
+ assets.srcDirs = ['assets']
}
- debug.jniLibs.srcDirs = ["${pathToRootDir}platform/android/java/libs/debug"]
- release.jniLibs.srcDirs = ["${pathToRootDir}platform/android/java/libs/release"]
+ debug.jniLibs.srcDirs = ['libs/debug']
+ release.jniLibs.srcDirs = ['libs/release']
}
libraryVariants.all { variant ->
diff --git a/platform/android/java/patches/com.google.android.vending.expansion.downloader.patch b/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch
index 1189cfbfbb..49cc41e817 100644
--- a/platform/android/java/patches/com.google.android.vending.expansion.downloader.patch
+++ b/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch
@@ -175,7 +175,7 @@ index e4b1b0f1c..36cd6aacf 100644
-import com.android.vending.expansion.downloader.R;
+// -- GODOT start --
+//import com.android.vending.expansion.downloader.R;
-+import com.godot.game.R;
++import org.godotengine.godot.R;
+// -- GODOT end --
import java.io.File;
@@ -250,7 +250,7 @@ index f1536e80e..4b214b22d 100644
-import com.android.vending.expansion.downloader.R;
+// -- GODOT start --
+//import com.android.vending.expansion.downloader.R;
-+import com.godot.game.R;
++import org.godotengine.godot.R;
+// -- GODOT end --
+
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
diff --git a/platform/android/java/patches/com.google.android.vending.licensing.patch b/platform/android/java/lib/patches/com.google.android.vending.licensing.patch
index 9f8e5b8eab..4adb81d951 100644
--- a/platform/android/java/patches/com.google.android.vending.licensing.patch
+++ b/platform/android/java/lib/patches/com.google.android.vending.licensing.patch
@@ -21,7 +21,7 @@ index a0d2779af..a8bf65f9c 100644
*/
+// -- GODOT start --
-+import com.godot.game.BuildConfig;
+import org.godotengine.godot.BuildConfig;
+// -- GODOT end --
+
/**
diff --git a/platform/android/java/res/drawable-hdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.png
index 2c246b04a4..2c246b04a4 100644
--- a/platform/android/java/res/drawable-hdpi/notify_panel_notification_icon_bg.png
+++ b/platform/android/java/lib/res/drawable-hdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/java/res/drawable-mdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.png
index 8bcd464bed..8bcd464bed 100644
--- a/platform/android/java/res/drawable-mdpi/notify_panel_notification_icon_bg.png
+++ b/platform/android/java/lib/res/drawable-mdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/java/res/drawable-nodpi/icon.png b/platform/android/java/lib/res/drawable-nodpi/icon.png
index 6ad9b43117..6ad9b43117 100644
--- a/platform/android/java/res/drawable-nodpi/icon.png
+++ b/platform/android/java/lib/res/drawable-nodpi/icon.png
Binary files differ
diff --git a/platform/android/java/res/drawable-xhdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.png
index 372b763ec5..372b763ec5 100644
--- a/platform/android/java/res/drawable-xhdpi/notify_panel_notification_icon_bg.png
+++ b/platform/android/java/lib/res/drawable-xhdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/java/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png b/platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png
index b458ff3057..b458ff3057 100644
--- a/platform/android/java/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png
+++ b/platform/android/java/lib/res/drawable-xxhdpi/notify_panel_notification_icon_bg.png
Binary files differ
diff --git a/platform/android/java/res/layout/downloading_expansion.xml b/platform/android/java/lib/res/layout/downloading_expansion.xml
index 4a9700965f..4a9700965f 100644
--- a/platform/android/java/res/layout/downloading_expansion.xml
+++ b/platform/android/java/lib/res/layout/downloading_expansion.xml
diff --git a/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml b/platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
index fae1faeb60..fae1faeb60 100644
--- a/platform/android/java/res/layout/status_bar_ongoing_event_progress_bar.xml
+++ b/platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
diff --git a/platform/android/java/res/values-ar/strings.xml b/platform/android/java/lib/res/values-ar/strings.xml
index 9f3dc6d6ac..9f3dc6d6ac 100644
--- a/platform/android/java/res/values-ar/strings.xml
+++ b/platform/android/java/lib/res/values-ar/strings.xml
diff --git a/platform/android/java/res/values-bg/strings.xml b/platform/android/java/lib/res/values-bg/strings.xml
index bd8109277e..bd8109277e 100644
--- a/platform/android/java/res/values-bg/strings.xml
+++ b/platform/android/java/lib/res/values-bg/strings.xml
diff --git a/platform/android/java/res/values-ca/strings.xml b/platform/android/java/lib/res/values-ca/strings.xml
index 494cb88468..494cb88468 100644
--- a/platform/android/java/res/values-ca/strings.xml
+++ b/platform/android/java/lib/res/values-ca/strings.xml
diff --git a/platform/android/java/res/values-cs/strings.xml b/platform/android/java/lib/res/values-cs/strings.xml
index 30ce00f895..30ce00f895 100644
--- a/platform/android/java/res/values-cs/strings.xml
+++ b/platform/android/java/lib/res/values-cs/strings.xml
diff --git a/platform/android/java/res/values-da/strings.xml b/platform/android/java/lib/res/values-da/strings.xml
index 4c2a1cf0f4..4c2a1cf0f4 100644
--- a/platform/android/java/res/values-da/strings.xml
+++ b/platform/android/java/lib/res/values-da/strings.xml
diff --git a/platform/android/java/res/values-de/strings.xml b/platform/android/java/lib/res/values-de/strings.xml
index 52946d4cce..52946d4cce 100644
--- a/platform/android/java/res/values-de/strings.xml
+++ b/platform/android/java/lib/res/values-de/strings.xml
diff --git a/platform/android/java/res/values-el/strings.xml b/platform/android/java/lib/res/values-el/strings.xml
index 181dc51762..181dc51762 100644
--- a/platform/android/java/res/values-el/strings.xml
+++ b/platform/android/java/lib/res/values-el/strings.xml
diff --git a/platform/android/java/res/values-en/strings.xml b/platform/android/java/lib/res/values-en/strings.xml
index 976a565013..976a565013 100644
--- a/platform/android/java/res/values-en/strings.xml
+++ b/platform/android/java/lib/res/values-en/strings.xml
diff --git a/platform/android/java/res/values-es-rES/strings.xml b/platform/android/java/lib/res/values-es-rES/strings.xml
index 73f63a08f8..73f63a08f8 100644
--- a/platform/android/java/res/values-es-rES/strings.xml
+++ b/platform/android/java/lib/res/values-es-rES/strings.xml
diff --git a/platform/android/java/res/values-es/strings.xml b/platform/android/java/lib/res/values-es/strings.xml
index 07b718a641..07b718a641 100644
--- a/platform/android/java/res/values-es/strings.xml
+++ b/platform/android/java/lib/res/values-es/strings.xml
diff --git a/platform/android/java/res/values-fa/strings.xml b/platform/android/java/lib/res/values-fa/strings.xml
index f1e29013c4..f1e29013c4 100644
--- a/platform/android/java/res/values-fa/strings.xml
+++ b/platform/android/java/lib/res/values-fa/strings.xml
diff --git a/platform/android/java/res/values-fi/strings.xml b/platform/android/java/lib/res/values-fi/strings.xml
index 323d82aff1..323d82aff1 100644
--- a/platform/android/java/res/values-fi/strings.xml
+++ b/platform/android/java/lib/res/values-fi/strings.xml
diff --git a/platform/android/java/res/values-fr/strings.xml b/platform/android/java/lib/res/values-fr/strings.xml
index 32bead2661..32bead2661 100644
--- a/platform/android/java/res/values-fr/strings.xml
+++ b/platform/android/java/lib/res/values-fr/strings.xml
diff --git a/platform/android/java/res/values-hi/strings.xml b/platform/android/java/lib/res/values-hi/strings.xml
index 8aab2a8c63..8aab2a8c63 100644
--- a/platform/android/java/res/values-hi/strings.xml
+++ b/platform/android/java/lib/res/values-hi/strings.xml
diff --git a/platform/android/java/res/values-hr/strings.xml b/platform/android/java/lib/res/values-hr/strings.xml
index caf55e2241..caf55e2241 100644
--- a/platform/android/java/res/values-hr/strings.xml
+++ b/platform/android/java/lib/res/values-hr/strings.xml
diff --git a/platform/android/java/res/values-hu/strings.xml b/platform/android/java/lib/res/values-hu/strings.xml
index e7f9e51226..e7f9e51226 100644
--- a/platform/android/java/res/values-hu/strings.xml
+++ b/platform/android/java/lib/res/values-hu/strings.xml
diff --git a/platform/android/java/res/values-in/strings.xml b/platform/android/java/lib/res/values-in/strings.xml
index 9e9a8b0c03..9e9a8b0c03 100644
--- a/platform/android/java/res/values-in/strings.xml
+++ b/platform/android/java/lib/res/values-in/strings.xml
diff --git a/platform/android/java/res/values-it/strings.xml b/platform/android/java/lib/res/values-it/strings.xml
index 1f5e5a049e..1f5e5a049e 100644
--- a/platform/android/java/res/values-it/strings.xml
+++ b/platform/android/java/lib/res/values-it/strings.xml
diff --git a/platform/android/java/res/values-iw/strings.xml b/platform/android/java/lib/res/values-iw/strings.xml
index f52ede2085..f52ede2085 100644
--- a/platform/android/java/res/values-iw/strings.xml
+++ b/platform/android/java/lib/res/values-iw/strings.xml
diff --git a/platform/android/java/res/values-ja/strings.xml b/platform/android/java/lib/res/values-ja/strings.xml
index 7f85f57df7..7f85f57df7 100644
--- a/platform/android/java/res/values-ja/strings.xml
+++ b/platform/android/java/lib/res/values-ja/strings.xml
diff --git a/platform/android/java/res/values-ko/strings.xml b/platform/android/java/lib/res/values-ko/strings.xml
index fab0bdd753..fab0bdd753 100644
--- a/platform/android/java/res/values-ko/strings.xml
+++ b/platform/android/java/lib/res/values-ko/strings.xml
diff --git a/platform/android/java/res/values-lt/strings.xml b/platform/android/java/lib/res/values-lt/strings.xml
index 6e3677fde7..6e3677fde7 100644
--- a/platform/android/java/res/values-lt/strings.xml
+++ b/platform/android/java/lib/res/values-lt/strings.xml
diff --git a/platform/android/java/res/values-lv/strings.xml b/platform/android/java/lib/res/values-lv/strings.xml
index 701fc271ac..701fc271ac 100644
--- a/platform/android/java/res/values-lv/strings.xml
+++ b/platform/android/java/lib/res/values-lv/strings.xml
diff --git a/platform/android/java/res/values-nb/strings.xml b/platform/android/java/lib/res/values-nb/strings.xml
index 73147ca1af..73147ca1af 100644
--- a/platform/android/java/res/values-nb/strings.xml
+++ b/platform/android/java/lib/res/values-nb/strings.xml
diff --git a/platform/android/java/res/values-nl/strings.xml b/platform/android/java/lib/res/values-nl/strings.xml
index e501928a35..e501928a35 100644
--- a/platform/android/java/res/values-nl/strings.xml
+++ b/platform/android/java/lib/res/values-nl/strings.xml
diff --git a/platform/android/java/res/values-pl/strings.xml b/platform/android/java/lib/res/values-pl/strings.xml
index ea5da73b6f..ea5da73b6f 100644
--- a/platform/android/java/res/values-pl/strings.xml
+++ b/platform/android/java/lib/res/values-pl/strings.xml
diff --git a/platform/android/java/res/values-pt/strings.xml b/platform/android/java/lib/res/values-pt/strings.xml
index bdda7cd2c7..bdda7cd2c7 100644
--- a/platform/android/java/res/values-pt/strings.xml
+++ b/platform/android/java/lib/res/values-pt/strings.xml
diff --git a/platform/android/java/res/values-ro/strings.xml b/platform/android/java/lib/res/values-ro/strings.xml
index 3686da4c19..3686da4c19 100644
--- a/platform/android/java/res/values-ro/strings.xml
+++ b/platform/android/java/lib/res/values-ro/strings.xml
diff --git a/platform/android/java/res/values-ru/strings.xml b/platform/android/java/lib/res/values-ru/strings.xml
index 954067658b..954067658b 100644
--- a/platform/android/java/res/values-ru/strings.xml
+++ b/platform/android/java/lib/res/values-ru/strings.xml
diff --git a/platform/android/java/res/values-sk/strings.xml b/platform/android/java/lib/res/values-sk/strings.xml
index 37d1283124..37d1283124 100644
--- a/platform/android/java/res/values-sk/strings.xml
+++ b/platform/android/java/lib/res/values-sk/strings.xml
diff --git a/platform/android/java/res/values-sl/strings.xml b/platform/android/java/lib/res/values-sl/strings.xml
index 0bb249c375..0bb249c375 100644
--- a/platform/android/java/res/values-sl/strings.xml
+++ b/platform/android/java/lib/res/values-sl/strings.xml
diff --git a/platform/android/java/res/values-sr/strings.xml b/platform/android/java/lib/res/values-sr/strings.xml
index 0e83cab1a1..0e83cab1a1 100644
--- a/platform/android/java/res/values-sr/strings.xml
+++ b/platform/android/java/lib/res/values-sr/strings.xml
diff --git a/platform/android/java/res/values-sv/strings.xml b/platform/android/java/lib/res/values-sv/strings.xml
index e3a04ac2ec..e3a04ac2ec 100644
--- a/platform/android/java/res/values-sv/strings.xml
+++ b/platform/android/java/lib/res/values-sv/strings.xml
diff --git a/platform/android/java/res/values-th/strings.xml b/platform/android/java/lib/res/values-th/strings.xml
index 0aa893b8bf..0aa893b8bf 100644
--- a/platform/android/java/res/values-th/strings.xml
+++ b/platform/android/java/lib/res/values-th/strings.xml
diff --git a/platform/android/java/res/values-tl/strings.xml b/platform/android/java/lib/res/values-tl/strings.xml
index e7e2af4909..e7e2af4909 100644
--- a/platform/android/java/res/values-tl/strings.xml
+++ b/platform/android/java/lib/res/values-tl/strings.xml
diff --git a/platform/android/java/res/values-tr/strings.xml b/platform/android/java/lib/res/values-tr/strings.xml
index 97af1243a6..97af1243a6 100644
--- a/platform/android/java/res/values-tr/strings.xml
+++ b/platform/android/java/lib/res/values-tr/strings.xml
diff --git a/platform/android/java/res/values-uk/strings.xml b/platform/android/java/lib/res/values-uk/strings.xml
index 3dea6908a9..3dea6908a9 100644
--- a/platform/android/java/res/values-uk/strings.xml
+++ b/platform/android/java/lib/res/values-uk/strings.xml
diff --git a/platform/android/java/res/values-vi/strings.xml b/platform/android/java/lib/res/values-vi/strings.xml
index a6552130b0..a6552130b0 100644
--- a/platform/android/java/res/values-vi/strings.xml
+++ b/platform/android/java/lib/res/values-vi/strings.xml
diff --git a/platform/android/java/res/values-zh-rCN/strings.xml b/platform/android/java/lib/res/values-zh-rCN/strings.xml
index 6668c56bd9..6668c56bd9 100644
--- a/platform/android/java/res/values-zh-rCN/strings.xml
+++ b/platform/android/java/lib/res/values-zh-rCN/strings.xml
diff --git a/platform/android/java/res/values-zh-rHK/strings.xml b/platform/android/java/lib/res/values-zh-rHK/strings.xml
index 8a6269da0f..8a6269da0f 100644
--- a/platform/android/java/res/values-zh-rHK/strings.xml
+++ b/platform/android/java/lib/res/values-zh-rHK/strings.xml
diff --git a/platform/android/java/res/values-zh-rTW/strings.xml b/platform/android/java/lib/res/values-zh-rTW/strings.xml
index b1bb39d5d6..b1bb39d5d6 100644
--- a/platform/android/java/res/values-zh-rTW/strings.xml
+++ b/platform/android/java/lib/res/values-zh-rTW/strings.xml
diff --git a/platform/android/java/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml
index a1b81a6186..a1b81a6186 100644
--- a/platform/android/java/res/values/strings.xml
+++ b/platform/android/java/lib/res/values/strings.xml
diff --git a/platform/android/java/res/values/styles.xml b/platform/android/java/lib/res/values/styles.xml
index a442f61e7e..a442f61e7e 100644
--- a/platform/android/java/res/values/styles.xml
+++ b/platform/android/java/lib/res/values/styles.xml
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/Constants.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Constants.java
index 1dcc370d83..1dcc370d83 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/Constants.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Constants.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
index 9cb294d721..9cb294d721 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
index 452c7d1483..452c7d1483 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
index 3771d19c9b..3771d19c9b 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Helpers.java
index 36cd6aacfe..2a72c9818d 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Helpers.java
@@ -26,7 +26,7 @@ import android.util.Log;
// -- GODOT start --
//import com.android.vending.expansion.downloader.R;
-import com.godot.game.R;
+import org.godotengine.godot.R;
// -- GODOT end --
import java.io.File;
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
index cef3794701..cef3794701 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderService.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
index 4de9de0c62..4de9de0c62 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderService.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/IStub.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IStub.java
index d5bc3a843e..d5bc3a843e 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/IStub.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IStub.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/SystemFacade.java
index a0e1165cc4..a0e1165cc4 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/SystemFacade.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
index 3ccc191c60..3ccc191c60 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
index 45111b16a3..45111b16a3 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
index 4b214b22d7..0abaf2e052 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java
@@ -18,7 +18,7 @@ package com.google.android.vending.expansion.downloader.impl;
// -- GODOT start --
//import com.android.vending.expansion.downloader.R;
-import com.godot.game.R;
+import org.godotengine.godot.R;
// -- GODOT end --
import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
index c114b8a64a..c114b8a64a 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
index 8d41a76900..8d41a76900 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
index c658b4cc43..c658b4cc43 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java
diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
index 3f440e9893..3f440e9893 100644
--- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
+++ b/platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/AESObfuscator.java b/platform/android/java/lib/src/com/google/android/vending/licensing/AESObfuscator.java
index d6ccb0c5e4..d6ccb0c5e4 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/AESObfuscator.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/AESObfuscator.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/APKExpansionPolicy.java b/platform/android/java/lib/src/com/google/android/vending/licensing/APKExpansionPolicy.java
index 37fad8926a..37fad8926a 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/APKExpansionPolicy.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/APKExpansionPolicy.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/DeviceLimiter.java b/platform/android/java/lib/src/com/google/android/vending/licensing/DeviceLimiter.java
index e5c5e2d7ca..e5c5e2d7ca 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/DeviceLimiter.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/DeviceLimiter.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/LicenseChecker.java b/platform/android/java/lib/src/com/google/android/vending/licensing/LicenseChecker.java
index 15017b3425..15017b3425 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/LicenseChecker.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/LicenseChecker.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/LicenseCheckerCallback.java b/platform/android/java/lib/src/com/google/android/vending/licensing/LicenseCheckerCallback.java
index 8b869ddaaf..8b869ddaaf 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/LicenseCheckerCallback.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/LicenseCheckerCallback.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/LicenseValidator.java b/platform/android/java/lib/src/com/google/android/vending/licensing/LicenseValidator.java
index 11a00786d0..11a00786d0 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/LicenseValidator.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/LicenseValidator.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/NullDeviceLimiter.java b/platform/android/java/lib/src/com/google/android/vending/licensing/NullDeviceLimiter.java
index d87af3153f..d87af3153f 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/NullDeviceLimiter.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/NullDeviceLimiter.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/Obfuscator.java b/platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java
index 008c150a8e..008c150a8e 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/Obfuscator.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/Policy.java b/platform/android/java/lib/src/com/google/android/vending/licensing/Policy.java
index b672a078b7..b672a078b7 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/Policy.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/Policy.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java b/platform/android/java/lib/src/com/google/android/vending/licensing/PreferenceObfuscator.java
index feb579af04..feb579af04 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/PreferenceObfuscator.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/ResponseData.java b/platform/android/java/lib/src/com/google/android/vending/licensing/ResponseData.java
index 3b5d557e76..3b5d557e76 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/ResponseData.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/ResponseData.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/ServerManagedPolicy.java b/platform/android/java/lib/src/com/google/android/vending/licensing/ServerManagedPolicy.java
index e2f0bfdca8..e2f0bfdca8 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/ServerManagedPolicy.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/ServerManagedPolicy.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/StrictPolicy.java b/platform/android/java/lib/src/com/google/android/vending/licensing/StrictPolicy.java
index c2d55c37f1..c2d55c37f1 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/StrictPolicy.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/StrictPolicy.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/ValidationException.java b/platform/android/java/lib/src/com/google/android/vending/licensing/ValidationException.java
index ee4df47c68..ee4df47c68 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/ValidationException.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/ValidationException.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java b/platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64.java
index a8bf65f9ca..79efca9621 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64.java
@@ -32,7 +32,7 @@ package com.google.android.vending.licensing.util;
*/
// -- GODOT start --
-import com.godot.game.BuildConfig;
+import org.godotengine.godot.BuildConfig;
// -- GODOT end --
/**
diff --git a/platform/android/java/src/com/google/android/vending/licensing/util/Base64DecoderException.java b/platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64DecoderException.java
index 1aef1b54b8..1aef1b54b8 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/util/Base64DecoderException.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64DecoderException.java
diff --git a/platform/android/java/src/com/google/android/vending/licensing/util/URIQueryDecoder.java b/platform/android/java/lib/src/com/google/android/vending/licensing/util/URIQueryDecoder.java
index 5155bf5ac3..5155bf5ac3 100644
--- a/platform/android/java/src/com/google/android/vending/licensing/util/URIQueryDecoder.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/util/URIQueryDecoder.java
diff --git a/platform/android/java/src/org/godotengine/godot/Dictionary.java b/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java
index 588d9ae646..588d9ae646 100644
--- a/platform/android/java/src/org/godotengine/godot/Dictionary.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Dictionary.java
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index 1b3239777c..739aa285bf 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -97,7 +97,7 @@ import org.godotengine.godot.input.GodotEditText;
import org.godotengine.godot.payments.PaymentsManager;
import org.godotengine.godot.xr.XRMode;
-public class Godot extends Activity implements SensorEventListener, IDownloaderClient {
+public abstract class Godot extends Activity implements SensorEventListener, IDownloaderClient {
static final int MAX_SINGLETONS = 64;
static final int REQUEST_RECORD_AUDIO_PERMISSION = 1;
@@ -146,8 +146,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private void setButtonPausedState(boolean paused) {
mStatePaused = paused;
- int stringResourceID = paused ? com.godot.game.R.string.text_button_resume :
- com.godot.game.R.string.text_button_pause;
+ int stringResourceID = paused ? R.string.text_button_resume :
+ R.string.text_button_pause;
mPauseButton.setText(stringResourceID);
}
@@ -357,7 +357,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
//
Bundle args = new Bundle();
args.putParcelable("intent", mCurrentIntent);
- startInstrumentation(new ComponentName(Godot.this, GodotInstrumentation.class), null, args);
+ startInstrumentation(new ComponentName(this, GodotInstrumentation.class), null, args);
}
public void alert(final String message, final String title) {
@@ -614,17 +614,17 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
GodotDownloaderService.class);
- setContentView(com.godot.game.R.layout.downloading_expansion);
- mPB = (ProgressBar)findViewById(com.godot.game.R.id.progressBar);
- mStatusText = (TextView)findViewById(com.godot.game.R.id.statusText);
- mProgressFraction = (TextView)findViewById(com.godot.game.R.id.progressAsFraction);
- mProgressPercent = (TextView)findViewById(com.godot.game.R.id.progressAsPercentage);
- mAverageSpeed = (TextView)findViewById(com.godot.game.R.id.progressAverageSpeed);
- mTimeRemaining = (TextView)findViewById(com.godot.game.R.id.progressTimeRemaining);
- mDashboard = findViewById(com.godot.game.R.id.downloaderDashboard);
- mCellMessage = findViewById(com.godot.game.R.id.approveCellular);
- mPauseButton = (Button)findViewById(com.godot.game.R.id.pauseButton);
- mWiFiSettingsButton = (Button)findViewById(com.godot.game.R.id.wifiSettingsButton);
+ setContentView(R.layout.downloading_expansion);
+ mPB = (ProgressBar)findViewById(R.id.progressBar);
+ mStatusText = (TextView)findViewById(R.id.statusText);
+ mProgressFraction = (TextView)findViewById(R.id.progressAsFraction);
+ mProgressPercent = (TextView)findViewById(R.id.progressAsPercentage);
+ mAverageSpeed = (TextView)findViewById(R.id.progressAverageSpeed);
+ mTimeRemaining = (TextView)findViewById(R.id.progressTimeRemaining);
+ mDashboard = findViewById(R.id.downloaderDashboard);
+ mCellMessage = findViewById(R.id.approveCellular);
+ mPauseButton = (Button)findViewById(R.id.pauseButton);
+ mWiFiSettingsButton = (Button)findViewById(R.id.wifiSettingsButton);
return;
}
@@ -669,12 +669,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
return;
}
mView.onPause();
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.focusout();
- }
- });
+
mSensorManager.unregisterListener(this);
for (int i = 0; i < singleton_count; i++) {
@@ -703,6 +698,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
@Override
protected void onResume() {
super.onResume();
+ activityResumed = true;
if (!godot_initialized) {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
@@ -711,12 +707,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
mView.onResume();
- mView.queueEvent(new Runnable() {
- @Override
- public void run() {
- GodotLib.focusin();
- }
- });
+
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mGravity, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
@@ -737,8 +728,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
singletons[i].onMainResume();
}
-
- activityResumed = true;
}
public void UiChangeListener() {
@@ -1094,9 +1083,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
@Override
public void onDownloadProgress(DownloadProgressInfo progress) {
- mAverageSpeed.setText(getString(com.godot.game.R.string.kilobytes_per_second,
+ mAverageSpeed.setText(getString(R.string.kilobytes_per_second,
Helpers.getSpeedString(progress.mCurrentSpeed)));
- mTimeRemaining.setText(getString(com.godot.game.R.string.time_remaining,
+ mTimeRemaining.setText(getString(R.string.time_remaining,
Helpers.getTimeRemaining(progress.mTimeRemaining)));
mPB.setMax((int)(progress.mOverallTotal >> 8));
diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java b/platform/android/java/lib/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
index e7e2a3f808..e7e2a3f808 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotDownloaderAlarmReceiver.java
diff --git a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java b/platform/android/java/lib/src/org/godotengine/godot/GodotDownloaderService.java
index 8e10710c9f..8e10710c9f 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotDownloaderService.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotDownloaderService.java
diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 98174157ec..04566cf62c 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -29,26 +29,18 @@
/*************************************************************************/
package org.godotengine.godot;
-import android.app.*;
import android.content.*;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
-import android.graphics.*;
-import android.hardware.*;
import android.media.*;
import android.net.Uri;
import android.os.*;
-import android.text.*;
-import android.text.method.*;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
-import android.view.*;
-import android.view.inputmethod.InputMethodManager;
import java.io.IOException;
import java.io.InputStream;
-import java.util.HashMap;
import java.util.Locale;
import org.godotengine.godot.input.*;
//android.os.Build
diff --git a/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java b/platform/android/java/lib/src/org/godotengine/godot/GodotInstrumentation.java
index 0466f380e8..0466f380e8 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotInstrumentation.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotInstrumentation.java
diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index af51c840cb..067fa6f4b9 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -211,4 +211,16 @@ public class GodotLib {
* Invoked on the GL thread to configure the height of the virtual keyboard.
*/
public static native void setVirtualKeyboardHeight(int p_height);
+
+ /**
+ * Invoked on the GL thread when the {@link GodotRenderer} has been resumed.
+ * @see GodotRenderer#onActivityResumed()
+ */
+ public static native void onRendererResumed();
+
+ /**
+ * Invoked on the GL thread when the {@link GodotRenderer} has been paused.
+ * @see GodotRenderer#onActivityPaused()
+ */
+ public static native void onRendererPaused();
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java b/platform/android/java/lib/src/org/godotengine/godot/GodotPaymentV3.java
index 1432cd3a67..1432cd3a67 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotPaymentV3.java
diff --git a/platform/android/java/src/org/godotengine/godot/GodotRenderer.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
index 8e3775c2a9..56ba88656e 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotRenderer.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderer.java
@@ -40,7 +40,14 @@ import org.godotengine.godot.utils.GLUtils;
*/
class GodotRenderer implements GLSurfaceView.Renderer {
+ private boolean activityJustResumed = false;
+
public void onDrawFrame(GL10 gl) {
+ if (activityJustResumed) {
+ GodotLib.onRendererResumed();
+ activityJustResumed = false;
+ }
+
GodotLib.step();
for (int i = 0; i < Godot.singleton_count; i++) {
Godot.singletons[i].onGLDrawFrame(gl);
@@ -58,4 +65,14 @@ class GodotRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GodotLib.newcontext(GLUtils.use_32);
}
+
+ void onActivityResumed() {
+ // We defer invoking GodotLib.onRendererResumed() until the first draw frame call.
+ // This ensures we have a valid GL context and surface when we do so.
+ activityJustResumed = true;
+ }
+
+ void onActivityPaused() {
+ GodotLib.onRendererPaused();
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/GodotView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
index fc3e47e69d..5511e5d782 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
@@ -68,6 +68,7 @@ public class GodotView extends GLSurfaceView {
private final Godot activity;
private final GodotInputHandler inputHandler;
+ private final GodotRenderer godotRenderer;
public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) {
super(activity);
@@ -77,6 +78,7 @@ public class GodotView extends GLSurfaceView {
this.activity = activity;
this.inputHandler = new GodotInputHandler(this);
+ this.godotRenderer = new GodotRenderer();
init(xrMode, false, 16, 0);
}
@@ -161,10 +163,38 @@ public class GodotView extends GLSurfaceView {
}
/* Set the renderer responsible for frame rendering */
- setRenderer(new GodotRenderer());
+ setRenderer(godotRenderer);
}
public void onBackPressed() {
activity.onBackPressed();
}
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ // Resume the renderer
+ godotRenderer.onActivityResumed();
+ GodotLib.focusin();
+ }
+ });
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.focusout();
+ // Pause the renderer
+ godotRenderer.onActivityPaused();
+ }
+ });
+ }
}
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
index 45b739baa0..45b739baa0 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotEditText.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index a443a0ad90..a443a0ad90 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index d6e7ad5b18..9b372c75e3 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -32,7 +32,6 @@ package org.godotengine.godot.input;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
index 4042c42e9d..4042c42e9d 100644
--- a/platform/android/java/src/org/godotengine/godot/input/InputManagerCompat.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
diff --git a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
index e4bafa7ff9..e4bafa7ff9 100644
--- a/platform/android/java/src/org/godotengine/godot/input/InputManagerV16.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
diff --git a/platform/android/java/src/org/godotengine/godot/input/Joystick.java b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
index ff95bfb0c5..ff95bfb0c5 100644
--- a/platform/android/java/src/org/godotengine/godot/input/Joystick.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/Joystick.java
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java b/platform/android/java/lib/src/org/godotengine/godot/payments/ConsumeTask.java
index f872e7af56..4c1050c948 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ConsumeTask.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/ConsumeTask.java
@@ -33,7 +33,6 @@ package org.godotengine.godot.payments;
import android.content.Context;
import android.os.AsyncTask;
import android.os.RemoteException;
-import android.util.Log;
import com.android.vending.billing.IInAppBillingService;
import java.lang.ref.WeakReference;
diff --git a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java b/platform/android/java/lib/src/org/godotengine/godot/payments/HandlePurchaseTask.java
index 5424ebb49d..1a914967a2 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/HandlePurchaseTask.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/HandlePurchaseTask.java
@@ -31,18 +31,7 @@
package org.godotengine.godot.payments;
import android.app.Activity;
-import android.app.PendingIntent;
-import android.app.ProgressDialog;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentSender.SendIntentException;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-import com.android.vending.billing.IInAppBillingService;
-import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.utils.Crypt;
import org.json.JSONException;
import org.json.JSONObject;
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java b/platform/android/java/lib/src/org/godotengine/godot/payments/PaymentsCache.java
index 8a2facbcfb..8a2facbcfb 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsCache.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/PaymentsCache.java
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/lib/src/org/godotengine/godot/payments/PaymentsManager.java
index a0dbc432c1..c079c55854 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/PaymentsManager.java
@@ -43,7 +43,6 @@ import android.util.Log;
import com.android.vending.billing.IInAppBillingService;
import java.util.ArrayList;
import java.util.Arrays;
-import org.godotengine.godot.Godot;
import org.godotengine.godot.GodotPaymentV3;
import org.json.JSONException;
import org.json.JSONObject;
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java b/platform/android/java/lib/src/org/godotengine/godot/payments/PurchaseTask.java
index 650c5178f0..9adc85e521 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PurchaseTask.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/PurchaseTask.java
@@ -32,19 +32,12 @@ package org.godotengine.godot.payments;
import android.app.Activity;
import android.app.PendingIntent;
-import android.app.ProgressDialog;
-import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import com.android.vending.billing.IInAppBillingService;
-import org.godotengine.godot.GodotLib;
-import org.godotengine.godot.utils.Crypt;
-import org.json.JSONException;
-import org.json.JSONObject;
abstract public class PurchaseTask {
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java b/platform/android/java/lib/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
index daca6ef5ae..daca6ef5ae 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/ReleaseAllConsumablesTask.java
diff --git a/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java b/platform/android/java/lib/src/org/godotengine/godot/payments/ValidateTask.java
index d32c80e8e0..17a2a197ad 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/ValidateTask.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/payments/ValidateTask.java
@@ -31,21 +31,10 @@
package org.godotengine.godot.payments;
import android.app.Activity;
-import android.app.PendingIntent;
import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-import com.android.vending.billing.IInAppBillingService;
import java.lang.ref.WeakReference;
-import org.godotengine.godot.Godot;
-import org.godotengine.godot.GodotLib;
import org.godotengine.godot.GodotPaymentV3;
-import org.godotengine.godot.utils.Crypt;
import org.godotengine.godot.utils.HttpRequester;
import org.godotengine.godot.utils.RequestParams;
import org.json.JSONException;
diff --git a/platform/android/java/src/org/godotengine/godot/utils/Crypt.java b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java
index 4c551d1d21..4c551d1d21 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/Crypt.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java
diff --git a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/lib/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index b61007faa3..b61007faa3 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
diff --git a/platform/android/java/src/org/godotengine/godot/utils/GLUtils.java b/platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java
index 6c95494f8b..6c95494f8b 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/GLUtils.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/GLUtils.java
diff --git a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java b/platform/android/java/lib/src/org/godotengine/godot/utils/HttpRequester.java
index e98f533c23..02ae753b3e 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/HttpRequester.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/HttpRequester.java
@@ -39,12 +39,9 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
-import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
@@ -58,7 +55,6 @@ import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
diff --git a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java b/platform/android/java/lib/src/org/godotengine/godot/utils/RequestParams.java
index b9fe0dd0c9..b9fe0dd0c9 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/RequestParams.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/RequestParams.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/XRMode.java b/platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java
index 5896b23ac3..5896b23ac3 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/XRMode.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/ovr/OvrConfigChooser.java b/platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrConfigChooser.java
index ff836a31ca..ff836a31ca 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/ovr/OvrConfigChooser.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrConfigChooser.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/ovr/OvrContextFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrContextFactory.java
index 5f6da8c672..5f6da8c672 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/ovr/OvrContextFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrContextFactory.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/ovr/OvrWindowSurfaceFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrWindowSurfaceFactory.java
index f1e38c35d8..f1e38c35d8 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/ovr/OvrWindowSurfaceFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/ovr/OvrWindowSurfaceFactory.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java
index 3836967f86..3836967f86 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularConfigChooser.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/regular/RegularContextFactory.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
index 4f1e9a696b..4f1e9a696b 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularContextFactory.java
diff --git a/platform/android/java/src/org/godotengine/godot/xr/regular/RegularFallbackConfigChooser.java b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularFallbackConfigChooser.java
index f5718ef2b3..f5718ef2b3 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/regular/RegularFallbackConfigChooser.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/xr/regular/RegularFallbackConfigChooser.java
diff --git a/misc/ide/jetbrains/settings.gradle b/platform/android/java/settings.gradle
index 1904ab94e7..f6921c70aa 100644
--- a/misc/ide/jetbrains/settings.gradle
+++ b/platform/android/java/settings.gradle
@@ -1,2 +1,5 @@
// Configure the root project.
rootProject.name = "Godot"
+
+include ':app'
+include ':lib'
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index f53df7afe9..30676783db 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -1387,3 +1387,21 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResu
AudioDriver::get_singleton()->capture_start();
}
}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz) {
+ if (step == 0)
+ return;
+
+ if (os_android->get_main_loop()) {
+ os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_RESUMED);
+ }
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz) {
+ if (step == 0)
+ return;
+
+ if (os_android->get_main_loop()) {
+ os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_PAUSED);
+ }
+}
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index 66591a2cb2..11bda94f8d 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -64,6 +64,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *env, jobject p_obj, jint ID, jstring method, jobjectArray params);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jobject obj, jint p_height);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jobject p_obj, jstring p_permission, jboolean p_result);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz);
}
#endif /* !JAVA_GODOT_LIB_JNI_H */
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 1cbf4d6a70..99fbe989df 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -287,7 +287,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_40x40", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_80x80", PROPERTY_HINT_FILE, "*.png"), "")); // Spotlight on devices with retina display
- for (unsigned int i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
+ for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, loading_screen_infos[i].preset_key, PROPERTY_HINT_FILE, "*.png"), ""));
}
@@ -489,7 +489,7 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
DirAccess *da = DirAccess::open(p_iconset_dir);
ERR_FAIL_COND_V(!da, ERR_CANT_OPEN);
- for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
+ for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
IconInfo info = icon_infos[i];
String icon_path = p_preset->get(info.preset_key);
if (icon_path.length() == 0) {
@@ -539,7 +539,7 @@ Error EditorExportPlatformIOS::_export_loading_screens(const Ref<EditorExportPre
DirAccess *da = DirAccess::open(p_dest_dir);
ERR_FAIL_COND_V(!da, ERR_CANT_OPEN);
- for (unsigned int i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
+ for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
LoadingScreenInfo info = loading_screen_infos[i];
String loading_screen_file = p_preset->get(info.preset_key);
if (loading_screen_file.size() > 0) {
@@ -626,7 +626,7 @@ private:
static String _hex_pad(uint32_t num) {
Vector<char> ret;
ret.resize(sizeof(num) * 2);
- for (unsigned int i = 0; i < sizeof(num) * 2; ++i) {
+ for (uint64_t i = 0; i < sizeof(num) * 2; ++i) {
uint8_t four_bits = (num >> (sizeof(num) * 8 - (i + 1) * 4)) & 0xF;
ret.write[i] = _hex_char(four_bits);
}
@@ -1169,7 +1169,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
valid = false;
}
- for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
+ for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
IconInfo info = icon_infos[i];
String icon_path = p_preset->get(info.preset_key);
if (icon_path.length() == 0) {
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 56b0a44dbc..94090bcdc1 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -240,7 +240,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
{ "is32", "s8mk", false, 16 } //16x16 24-bit RLE + 8-bit uncompressed mask
};
- for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
+ for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy?
copy->convert(Image::FORMAT_RGBA8);
copy->resize(icon_infos[i].size, icon_infos[i].size);
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index ea110b11ca..bb18c2da8a 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -500,7 +500,7 @@ Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t
size_t block_size = (p_len - step) > BLOCK_SIZE ? (size_t)BLOCK_SIZE : (p_len - step);
- for (uint32_t i = 0; i < block_size; i++) {
+ for (uint64_t i = 0; i < block_size; i++) {
strm_in.write[i] = p_buffer[step + i];
}
@@ -524,14 +524,14 @@ Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t
//package->store_buffer(strm_out.ptr(), strm.total_out - total_out_before);
int start = file_buffer.size();
file_buffer.resize(file_buffer.size() + bh.compressed_size);
- for (uint32_t i = 0; i < bh.compressed_size; i++)
+ for (uint64_t i = 0; i < bh.compressed_size; i++)
file_buffer.write[start + i] = strm_out[i];
} else {
bh.compressed_size = block_size;
//package->store_buffer(strm_in.ptr(), block_size);
int start = file_buffer.size();
file_buffer.resize(file_buffer.size() + block_size);
- for (uint32_t i = 0; i < bh.compressed_size; i++)
+ for (uint64_t i = 0; i < bh.compressed_size; i++)
file_buffer.write[start + i] = strm_in[i];
}
@@ -554,7 +554,7 @@ Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t
//package->store_buffer(strm_out.ptr(), strm.total_out - total_out_before);
int start = file_buffer.size();
file_buffer.resize(file_buffer.size() + (strm.total_out - total_out_before));
- for (uint32_t i = 0; i < (strm.total_out - total_out_before); i++)
+ for (uint64_t i = 0; i < (strm.total_out - total_out_before); i++)
file_buffer.write[start + i] = strm_out[i];
deflateEnd(&strm);
diff --git a/platform/windows/camera_win.cpp b/platform/windows/camera_win.cpp
index b97796fe89..10787d0d0a 100644
--- a/platform/windows/camera_win.cpp
+++ b/platform/windows/camera_win.cpp
@@ -30,9 +30,12 @@
#include "camera_win.h"
-///@TODO sorry guys, I got about 80% through implementing this using DirectShow only to find out Microsoft deprecated half the API and its replacement is as confusing as they could make it
-// Joey suggested looking into libuvc which offers a more direct route to webcams over USB and this is very promissing but it wouldn't compile on windows for me...
-// I've gutted the classes I implemented DirectShow in just to have a skeleton for someone to work on, mail me for more details or if you want a copy....
+///@TODO sorry guys, I got about 80% through implementing this using DirectShow only
+// to find out Microsoft deprecated half the API and its replacement is as confusing
+// as they could make it. Joey suggested looking into libuvc which offers a more direct
+// route to webcams over USB and this is very promising but it wouldn't compile on
+// windows for me...I've gutted the classes I implemented DirectShow in just to have
+// a skeleton for someone to work on, mail me for more details or if you want a copy....
//////////////////////////////////////////////////////////////////////////
// CameraFeedWindows - Subclass for our camera feed on windows
@@ -69,7 +72,8 @@ bool CameraFeedWindows::activate_feed() {
return true;
};
-///@TODO we should probably have a callback method here that is being called by the camera API which provides frames and call back into the CameraServer to update our texture
+///@TODO we should probably have a callback method here that is being called by the
+// camera API which provides frames and call back into the CameraServer to update our texture
void CameraFeedWindows::deactivate_feed(){
///@TODO this should deactivate our camera and stop the process of capturing frames
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index dfa0a45538..687981f32b 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -378,6 +378,13 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
}
+ // 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);
+ }
+
// disable resizable window
if (!current_videomode.resizable && !current_videomode.fullscreen) {
XSizeHints *xsh;
@@ -1559,7 +1566,7 @@ bool OS_X11::is_window_maximize_allowed() {
bool found_wm_act_max_horz = false;
bool found_wm_act_max_vert = false;
- for (unsigned int i = 0; i < len; i++) {
+ 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)
@@ -1605,7 +1612,7 @@ bool OS_X11::is_window_maximized() const {
bool found_wm_max_horz = false;
bool found_wm_max_vert = false;
- for (unsigned int i = 0; i < len; i++) {
+ 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)
@@ -3021,7 +3028,7 @@ void OS_X11::alert(const String &p_alert, const String &p_title) {
String program;
for (int i = 0; i < path_elems.size(); i++) {
- for (unsigned int k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
+ for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
String tested_path = path_elems[i].plus_file(message_programs[k]);
if (FileAccess::exists(tested_path)) {
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index fc5e5cbba2..b38fbfe981 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -602,9 +602,7 @@ void CanvasItem::_notification(int p_what) {
}
global_invalid = true;
} break;
- case NOTIFICATION_DRAW: {
-
- } break;
+ case NOTIFICATION_DRAW:
case NOTIFICATION_TRANSFORM_CHANGED: {
} break;
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
index 9fe5fb98b6..6436b3878f 100644
--- a/scene/2d/line_builder.cpp
+++ b/scene/2d/line_builder.cpp
@@ -155,7 +155,7 @@ void LineBuilder::build() {
texture_mode == Line2D::LINE_TEXTURE_STRETCH;
if (distance_required) {
total_distance = calculate_total_distance(points);
- //Ajust totalDistance.
+ //Adjust totalDistance.
// The line's outer length will be a little higher due to begin and end caps
if (begin_cap_mode == Line2D::LINE_CAP_BOX || begin_cap_mode == Line2D::LINE_CAP_ROUND) {
if (retrieve_curve)
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index e389d5f98f..678db85ff0 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -271,7 +271,7 @@ void NavigationPolygon::make_polygons_from_outlines() {
struct Polygon p;
- for (int i = 0; i < tp.GetNumPoints(); i++) {
+ for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
Map<Vector2, int>::Element *E = points.find(tp[i]);
if (!E) {
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 9b6020e0fd..28f7243c44 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1209,7 +1209,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_
return colliding;
}
-//so, if you pass 45 as limit, avoid numerical precision erros when angle is 45.
+//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index 89072519d5..50ca466df3 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -149,12 +149,38 @@ Ref<Mesh> MeshInstance::get_mesh() const {
void MeshInstance::_resolve_skeleton_path() {
- if (skeleton_path.is_empty())
+ Ref<SkinReference> new_skin_reference;
+
+ if (!skeleton_path.is_empty()) {
+ Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path));
+ if (skeleton) {
+ new_skin_reference = skeleton->register_skin(skin);
+ if (skin.is_null()) {
+ //a skin was created for us
+ skin = new_skin_reference->get_skin();
+ _change_notify();
+ }
+ }
+ }
+
+ skin_ref = new_skin_reference;
+
+ if (skin_ref.is_valid()) {
+ VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton());
+ } else {
+ VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), RID());
+ }
+}
+
+void MeshInstance::set_skin(const Ref<Skin> &p_skin) {
+ skin = p_skin;
+ if (!is_inside_tree())
return;
+ _resolve_skeleton_path();
+}
- Skeleton *skeleton = Object::cast_to<Skeleton>(get_node(skeleton_path));
- if (skeleton)
- VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skeleton->get_skeleton());
+Ref<Skin> MeshInstance::get_skin() const {
+ return skin;
}
void MeshInstance::set_skeleton_path(const NodePath &p_skeleton) {
@@ -365,6 +391,8 @@ void MeshInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance::get_mesh);
ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &MeshInstance::set_skeleton_path);
ClassDB::bind_method(D_METHOD("get_skeleton_path"), &MeshInstance::get_skeleton_path);
+ ClassDB::bind_method(D_METHOD("set_skin", "skin"), &MeshInstance::set_skin);
+ ClassDB::bind_method(D_METHOD("get_skin"), &MeshInstance::get_skin);
ClassDB::bind_method(D_METHOD("get_surface_material_count"), &MeshInstance::get_surface_material_count);
ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance::set_surface_material);
@@ -380,6 +408,7 @@ void MeshInstance::_bind_methods() {
ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
}
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index 8b690b0c21..77ead75dd3 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -31,8 +31,10 @@
#ifndef MESH_INSTANCE_H
#define MESH_INSTANCE_H
+#include "scene/3d/skeleton.h"
#include "scene/3d/visual_instance.h"
#include "scene/resources/mesh.h"
+#include "scene/resources/skin.h"
class MeshInstance : public GeometryInstance {
@@ -40,6 +42,8 @@ class MeshInstance : public GeometryInstance {
protected:
Ref<Mesh> mesh;
+ Ref<Skin> skin;
+ Ref<SkinReference> skin_ref;
NodePath skeleton_path;
struct BlendShapeTrack {
@@ -70,6 +74,9 @@ public:
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh() const;
+ void set_skin(const Ref<Skin> &p_skin);
+ Ref<Skin> get_skin() const;
+
void set_skeleton_path(const NodePath &p_skeleton);
NodePath get_skeleton_path();
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 0756be5fc8..71040d2d68 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1137,7 +1137,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in
return colliding;
}
-//so, if you pass 45 as limit, avoid numerical precision erros when angle is 45.
+//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
@@ -2182,7 +2182,7 @@ void PhysicalBone::_notification(int p_what) {
void PhysicalBone::_direct_state_changed(Object *p_state) {
- if (!simulate_physics) {
+ if (!simulate_physics || !_internal_simulate_physics) {
return;
}
@@ -2205,7 +2205,7 @@ void PhysicalBone::_direct_state_changed(Object *p_state) {
// Update skeleton
if (parent_skeleton) {
if (-1 != bone_id) {
- parent_skeleton->set_bone_global_pose(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse));
+ parent_skeleton->set_bone_global_pose_override(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse), 1.0, true);
}
}
}
@@ -2716,7 +2716,6 @@ void PhysicalBone::_start_physics_simulation() {
PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
- parent_skeleton->set_bone_ignore_animation(bone_id, true);
_internal_simulate_physics = true;
}
@@ -2728,6 +2727,6 @@ void PhysicalBone::_stop_physics_simulation() {
PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0);
PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0);
PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, "");
- parent_skeleton->set_bone_ignore_animation(bone_id, false);
+ parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
_internal_simulate_physics = false;
}
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index e192e040f2..ead1e69f90 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -36,6 +36,34 @@
#include "scene/3d/physics_body.h"
#include "scene/resources/surface_tool.h"
+void SkinReference::_skin_changed() {
+ if (skeleton_node) {
+ skeleton_node->_make_dirty();
+ }
+}
+
+void SkinReference::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_skin_changed"), &SkinReference::_skin_changed);
+ ClassDB::bind_method(D_METHOD("get_skeleton"), &SkinReference::get_skeleton);
+ ClassDB::bind_method(D_METHOD("get_skin"), &SkinReference::get_skin);
+}
+
+RID SkinReference::get_skeleton() const {
+ return skeleton;
+}
+
+Ref<Skin> SkinReference::get_skin() const {
+ return skin;
+}
+
+SkinReference::~SkinReference() {
+ if (skeleton_node) {
+ skeleton_node->skin_bindings.erase(this);
+ }
+
+ VS::get_singleton()->free(skeleton);
+}
+
bool Skeleton::_set(const StringName &p_path, const Variant &p_value) {
String path = p_path;
@@ -196,110 +224,77 @@ void Skeleton::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_WORLD: {
-
- VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform());
-
- } break;
- case NOTIFICATION_EXIT_WORLD: {
-
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform());
- } break;
case NOTIFICATION_UPDATE_SKELETON: {
VisualServer *vs = VisualServer::get_singleton();
Bone *bonesptr = bones.ptrw();
int len = bones.size();
- vs->skeleton_allocate(skeleton, len); // if same size, nothing really happens
-
_update_process_order();
const int *order = process_order.ptr();
- // pose changed, rebuild cache of inverses
- if (rest_global_inverse_dirty) {
-
- // calculate global rests and invert them
- for (int i = 0; i < len; i++) {
- Bone &b = bonesptr[order[i]];
- if (b.parent >= 0)
- b.rest_global_inverse = bonesptr[b.parent].rest_global_inverse * b.rest;
- else
- b.rest_global_inverse = b.rest;
- }
- for (int i = 0; i < len; i++) {
- Bone &b = bonesptr[order[i]];
- b.rest_global_inverse.affine_invert();
- }
-
- rest_global_inverse_dirty = false;
- }
-
for (int i = 0; i < len; i++) {
Bone &b = bonesptr[order[i]];
- if (b.disable_rest) {
- if (b.enabled) {
+ if (b.global_pose_override_amount >= 0.999) {
+ b.pose_global = b.global_pose_override;
+ } else {
+ if (b.disable_rest) {
+ if (b.enabled) {
- Transform pose = b.pose;
- if (b.custom_pose_enable) {
+ Transform pose = b.pose;
+ if (b.parent >= 0) {
- pose = b.custom_pose * pose;
- }
+ b.pose_global = bonesptr[b.parent].pose_global * pose;
+ } else {
- if (b.parent >= 0) {
-
- b.pose_global = bonesptr[b.parent].pose_global * pose;
+ b.pose_global = pose;
+ }
} else {
- b.pose_global = pose;
- }
- } else {
-
- if (b.parent >= 0) {
+ if (b.parent >= 0) {
- b.pose_global = bonesptr[b.parent].pose_global;
- } else {
+ b.pose_global = bonesptr[b.parent].pose_global;
+ } else {
- b.pose_global = Transform();
+ b.pose_global = Transform();
+ }
}
- }
- } else {
- if (b.enabled) {
+ } else {
+ if (b.enabled) {
- Transform pose = b.pose;
- if (b.custom_pose_enable) {
+ Transform pose = b.pose;
- pose = b.custom_pose * pose;
- }
+ if (b.parent >= 0) {
- if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
+ } else {
- b.pose_global = bonesptr[b.parent].pose_global * (b.rest * pose);
+ b.pose_global = b.rest * pose;
+ }
} else {
- b.pose_global = b.rest * pose;
- }
- } else {
+ if (b.parent >= 0) {
- if (b.parent >= 0) {
+ b.pose_global = bonesptr[b.parent].pose_global * b.rest;
+ } else {
- b.pose_global = bonesptr[b.parent].pose_global * b.rest;
- } else {
-
- b.pose_global = b.rest;
+ b.pose_global = b.rest;
+ }
}
}
+
+ if (b.global_pose_override_amount >= CMP_EPSILON) {
+ b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount);
+ }
}
- b.transform_final = b.pose_global * b.rest_global_inverse;
- vs->skeleton_bone_set_transform(skeleton, order[i], b.transform_final);
+ if (b.global_pose_override_reset) {
+ b.global_pose_override_amount = 0.0;
+ }
for (List<uint32_t>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
@@ -311,28 +306,37 @@ void Skeleton::_notification(int p_what) {
}
}
+ //update skins
+ for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
+
+ const Skin *skin = E->get()->skin.operator->();
+ RID skeleton = E->get()->skeleton;
+ uint32_t bind_count = skin->get_bind_count();
+
+ if (E->get()->bind_count != bind_count) {
+ VS::get_singleton()->skeleton_allocate(skeleton, bind_count);
+ E->get()->bind_count = bind_count;
+ }
+
+ for (uint32_t i = 0; i < bind_count; i++) {
+ uint32_t bone_index = skin->get_bind_bone(i);
+ ERR_CONTINUE(bone_index >= (uint32_t)len);
+ vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
+ }
+ }
+
dirty = false;
} break;
}
}
-Transform Skeleton::get_bone_transform(int p_bone) const {
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
- if (dirty)
- const_cast<Skeleton *>(this)->notification(NOTIFICATION_UPDATE_SKELETON);
- return bones[p_bone].pose_global * bones[p_bone].rest_global_inverse;
-}
-
-void Skeleton::set_bone_global_pose(int p_bone, const Transform &p_pose) {
+void Skeleton::set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent) {
ERR_FAIL_INDEX(p_bone, bones.size());
- if (bones[p_bone].parent == -1) {
-
- set_bone_pose(p_bone, bones[p_bone].rest_global_inverse * p_pose); //fast
- } else {
-
- set_bone_pose(p_bone, bones[p_bone].rest.affine_inverse() * (get_bone_global_pose(bones[p_bone].parent).affine_inverse() * p_pose)); //slow
- }
+ bones.write[p_bone].global_pose_override_amount = p_amount;
+ bones.write[p_bone].global_pose_override = p_pose;
+ bones.write[p_bone].global_pose_override_reset = !p_persistent;
+ _make_dirty();
}
Transform Skeleton::get_bone_global_pose(int p_bone) const {
@@ -343,11 +347,6 @@ Transform Skeleton::get_bone_global_pose(int p_bone) const {
return bones[p_bone].pose_global;
}
-RID Skeleton::get_skeleton() const {
-
- return skeleton;
-}
-
// skeleton creation api
void Skeleton::add_bone(const String &p_name) {
@@ -362,8 +361,6 @@ void Skeleton::add_bone(const String &p_name) {
b.name = p_name;
bones.push_back(b);
process_order_dirty = true;
-
- rest_global_inverse_dirty = true;
_make_dirty();
update_gizmo();
}
@@ -408,7 +405,6 @@ void Skeleton::set_bone_parent(int p_bone, int p_parent) {
ERR_FAIL_COND(p_parent != -1 && (p_parent < 0));
bones.write[p_bone].parent = p_parent;
- rest_global_inverse_dirty = true;
process_order_dirty = true;
_make_dirty();
}
@@ -426,23 +422,11 @@ void Skeleton::unparent_bone_and_rest(int p_bone) {
}
bones.write[p_bone].parent = -1;
- bones.write[p_bone].rest_global_inverse = bones[p_bone].rest.affine_inverse(); //same thing
process_order_dirty = true;
_make_dirty();
}
-void Skeleton::set_bone_ignore_animation(int p_bone, bool p_ignore) {
- ERR_FAIL_INDEX(p_bone, bones.size());
- bones.write[p_bone].ignore_animation = p_ignore;
-}
-
-bool Skeleton::is_bone_ignore_animation(int p_bone) const {
-
- ERR_FAIL_INDEX_V(p_bone, bones.size(), false);
- return bones[p_bone].ignore_animation;
-}
-
void Skeleton::set_bone_disable_rest(int p_bone, bool p_disable) {
ERR_FAIL_INDEX(p_bone, bones.size());
@@ -467,7 +451,6 @@ void Skeleton::set_bone_rest(int p_bone, const Transform &p_rest) {
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].rest = p_rest;
- rest_global_inverse_dirty = true;
_make_dirty();
}
Transform Skeleton::get_bone_rest(int p_bone) const {
@@ -482,7 +465,6 @@ void Skeleton::set_bone_enabled(int p_bone, bool p_enabled) {
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].enabled = p_enabled;
- rest_global_inverse_dirty = true;
_make_dirty();
}
bool Skeleton::is_bone_enabled(int p_bone) const {
@@ -529,7 +511,6 @@ void Skeleton::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound)
void Skeleton::clear_bones() {
bones.clear();
- rest_global_inverse_dirty = true;
process_order_dirty = true;
_make_dirty();
@@ -552,23 +533,6 @@ Transform Skeleton::get_bone_pose(int p_bone) const {
return bones[p_bone].pose;
}
-void Skeleton::set_bone_custom_pose(int p_bone, const Transform &p_custom_pose) {
-
- ERR_FAIL_INDEX(p_bone, bones.size());
- //ERR_FAIL_COND( !is_inside_scene() );
-
- bones.write[p_bone].custom_pose_enable = (p_custom_pose != Transform());
- bones.write[p_bone].custom_pose = p_custom_pose;
-
- _make_dirty();
-}
-
-Transform Skeleton::get_bone_custom_pose(int p_bone) const {
-
- ERR_FAIL_INDEX_V(p_bone, bones.size(), Transform());
- return bones[p_bone].custom_pose;
-}
-
void Skeleton::_make_dirty() {
if (dirty)
@@ -747,14 +711,66 @@ void Skeleton::physical_bones_remove_collision_exception(RID p_exception) {
#endif // _3D_DISABLED
-void Skeleton::set_use_bones_in_world_transform(bool p_enable) {
- use_bones_in_world_transform = p_enable;
- if (is_inside_tree()) {
- VS::get_singleton()->skeleton_set_world_transform(skeleton, use_bones_in_world_transform, get_global_transform());
- }
+void Skeleton::_skin_changed() {
+ _make_dirty();
}
-bool Skeleton::is_using_bones_in_world_transform() const {
- return use_bones_in_world_transform;
+
+Ref<SkinReference> Skeleton::register_skin(const Ref<Skin> &p_skin) {
+
+ for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
+ if (E->get()->skin == p_skin) {
+ return Ref<SkinReference>(E->get());
+ }
+ }
+
+ Ref<Skin> skin = p_skin;
+
+ if (skin.is_null()) {
+ //need to create one from existing code, this is for compatibility only
+ //when skeletons did not support skins. It is also used by gizmo
+ //to display the skeleton.
+
+ skin.instance();
+ skin->set_bind_count(bones.size());
+ _update_process_order(); //just in case
+
+ // pose changed, rebuild cache of inverses
+ const Bone *bonesptr = bones.ptr();
+ int len = bones.size();
+ const int *order = process_order.ptr();
+
+ // calculate global rests and invert them
+ for (int i = 0; i < len; i++) {
+ const Bone &b = bonesptr[order[i]];
+ if (b.parent >= 0) {
+ skin->set_bind_pose(order[i], skin->get_bind_pose(b.parent) * b.rest);
+ } else {
+ skin->set_bind_pose(order[i], b.rest);
+ }
+ }
+
+ for (int i = 0; i < len; i++) {
+ //the inverse is what is actually required
+ skin->set_bind_bone(i, i);
+ skin->set_bind_pose(i, skin->get_bind_pose(i).affine_inverse());
+ }
+ }
+
+ ERR_FAIL_COND_V(skin.is_null(), Ref<SkinReference>());
+
+ Ref<SkinReference> skin_ref;
+ skin_ref.instance();
+
+ skin_ref->skeleton_node = this;
+ skin_ref->bind_count = 0;
+ skin_ref->skeleton = VisualServer::get_singleton()->skeleton_create();
+ skin_ref->skeleton_node = this;
+ skin_ref->skin = skin;
+
+ skin_bindings.insert(skin_ref.operator->());
+
+ skin->connect("changed", skin_ref.operator->(), "_skin_changed");
+ return skin_ref;
}
void Skeleton::_bind_methods() {
@@ -773,6 +789,8 @@ void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_rest", "bone_idx"), &Skeleton::get_bone_rest);
ClassDB::bind_method(D_METHOD("set_bone_rest", "bone_idx", "rest"), &Skeleton::set_bone_rest);
+ ClassDB::bind_method(D_METHOD("register_skin", "skin"), &Skeleton::register_skin);
+
ClassDB::bind_method(D_METHOD("localize_rests"), &Skeleton::localize_rests);
ClassDB::bind_method(D_METHOD("set_bone_disable_rest", "bone_idx", "disable"), &Skeleton::set_bone_disable_rest);
@@ -787,17 +805,9 @@ void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton::get_bone_pose);
ClassDB::bind_method(D_METHOD("set_bone_pose", "bone_idx", "pose"), &Skeleton::set_bone_pose);
- ClassDB::bind_method(D_METHOD("set_bone_global_pose", "bone_idx", "pose"), &Skeleton::set_bone_global_pose);
+ ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton::set_bone_global_pose_override, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton::get_bone_global_pose);
- ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton::get_bone_custom_pose);
- ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton::set_bone_custom_pose);
-
- ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform);
-
- ClassDB::bind_method(D_METHOD("set_use_bones_in_world_transform", "enable"), &Skeleton::set_use_bones_in_world_transform);
- ClassDB::bind_method(D_METHOD("is_using_bones_in_world_transform"), &Skeleton::is_using_bones_in_world_transform);
-
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation);
@@ -807,22 +817,19 @@ void Skeleton::_bind_methods() {
#endif // _3D_DISABLED
- ClassDB::bind_method(D_METHOD("set_bone_ignore_animation", "bone", "ignore"), &Skeleton::set_bone_ignore_animation);
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones_in_world_transform"), "set_use_bones_in_world_transform", "is_using_bones_in_world_transform");
BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON);
}
Skeleton::Skeleton() {
- rest_global_inverse_dirty = true;
dirty = false;
process_order_dirty = true;
- skeleton = VisualServer::get_singleton()->skeleton_create();
- set_notify_transform(true);
- use_bones_in_world_transform = false;
}
Skeleton::~Skeleton() {
- VisualServer::get_singleton()->free(skeleton);
+
+ //some skins may remain bound
+ for (Set<SkinReference *>::Element *E = skin_bindings.front(); E; E = E->next()) {
+ E->get()->skeleton_node = nullptr;
+ }
}
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index 5b55dffbc8..f20c550055 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -33,6 +33,7 @@
#include "core/rid.h"
#include "scene/3d/spatial.h"
+#include "scene/resources/skin.h"
#ifndef _3D_DISABLED
typedef int BoneId;
@@ -40,10 +41,38 @@ typedef int BoneId;
class PhysicalBone;
#endif // _3D_DISABLED
+class Skeleton;
+
+class SkinReference : public Reference {
+ GDCLASS(SkinReference, Reference)
+ friend class Skeleton;
+
+ Skeleton *skeleton_node;
+ RID skeleton;
+ Ref<Skin> skin;
+ uint32_t bind_count = 0;
+ void _skin_changed();
+
+protected:
+ static void _bind_methods();
+
+public:
+ RID get_skeleton() const;
+ Ref<Skin> get_skin() const;
+ ~SkinReference();
+};
+
class Skeleton : public Spatial {
GDCLASS(Skeleton, Spatial);
+private:
+ friend class SkinReference;
+
+ Set<SkinReference *> skin_bindings;
+
+ void _skin_changed();
+
struct Bone {
String name;
@@ -52,19 +81,15 @@ class Skeleton : public Spatial {
int parent;
int sort_index; //used for re-sorting process order
- bool ignore_animation;
-
bool disable_rest;
Transform rest;
- Transform rest_global_inverse;
Transform pose;
Transform pose_global;
- bool custom_pose_enable;
- Transform custom_pose;
-
- Transform transform_final;
+ float global_pose_override_amount;
+ bool global_pose_override_reset;
+ Transform global_pose_override;
#ifndef _3D_DISABLED
PhysicalBone *physical_bone;
@@ -76,9 +101,9 @@ class Skeleton : public Spatial {
Bone() {
parent = -1;
enabled = true;
- ignore_animation = false;
- custom_pose_enable = false;
disable_rest = false;
+ global_pose_override_amount = 0;
+ global_pose_override_reset = false;
#ifndef _3D_DISABLED
physical_bone = NULL;
cache_parent_physical_bone = NULL;
@@ -86,17 +111,12 @@ class Skeleton : public Spatial {
}
};
- bool rest_global_inverse_dirty;
-
Vector<Bone> bones;
Vector<int> process_order;
bool process_order_dirty;
- RID skeleton;
-
void _make_dirty();
bool dirty;
- bool use_bones_in_world_transform;
// bind helpers
Array _get_bound_child_nodes_to_bone(int p_bone) const {
@@ -127,8 +147,6 @@ public:
NOTIFICATION_UPDATE_SKELETON = 50
};
- RID get_skeleton() const;
-
// skeleton creation api
void add_bone(const String &p_name);
int find_bone(const String &p_name) const;
@@ -141,9 +159,6 @@ public:
void unparent_bone_and_rest(int p_bone);
- void set_bone_ignore_animation(int p_bone, bool p_ignore);
- bool is_bone_ignore_animation(int p_bone) const;
-
void set_bone_disable_rest(int p_bone, bool p_disable);
bool is_bone_rest_disabled(int p_bone) const;
@@ -151,10 +166,9 @@ public:
void set_bone_rest(int p_bone, const Transform &p_rest);
Transform get_bone_rest(int p_bone) const;
- Transform get_bone_transform(int p_bone) const;
Transform get_bone_global_pose(int p_bone) const;
- void set_bone_global_pose(int p_bone, const Transform &p_pose);
+ void set_bone_global_pose_override(int p_bone, const Transform &p_pose, float p_amount, bool p_persistent = false);
void set_bone_enabled(int p_bone, bool p_enabled);
bool is_bone_enabled(int p_bone) const;
@@ -170,14 +184,10 @@ public:
void set_bone_pose(int p_bone, const Transform &p_pose);
Transform get_bone_pose(int p_bone) const;
- void set_bone_custom_pose(int p_bone, const Transform &p_custom_pose);
- Transform get_bone_custom_pose(int p_bone) const;
-
void localize_rests(); // used for loaders and tools
int get_process_order(int p_idx);
- void set_use_bones_in_world_transform(bool p_enable);
- bool is_using_bones_in_world_transform() const;
+ Ref<SkinReference> register_skin(const Ref<Skin> &p_skin);
#ifndef _3D_DISABLED
// Physical bone API
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 051f832882..728c23fbaa 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -256,7 +256,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
Skeleton *sk = Object::cast_to<Skeleton>(child);
bone_idx = sk->find_bone(a->track_get_path(i).get_subname(0));
- if (bone_idx == -1 || sk->is_bone_ignore_animation(bone_idx)) {
+ if (bone_idx == -1) {
continue;
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index bb7c400cfe..eb152bc41e 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -622,7 +622,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
Skeleton *sk = Object::cast_to<Skeleton>(spatial);
int bone_idx = sk->find_bone(path.get_subname(0));
- if (bone_idx != -1 && !sk->is_bone_ignore_animation(bone_idx)) {
+ if (bone_idx != -1) {
track_xform->skeleton = sk;
track_xform->bone_idx = bone_idx;
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 8f6d53c21c..ba5936562a 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -820,11 +820,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
t.value = t.object->get_indexed(t.subpath);
t.value.zero();
- if (t.skeleton) {
- t.skip = t.skeleton->is_bone_ignore_animation(t.bone_idx);
- } else {
- t.skip = false;
- }
+ t.skip = false;
}
/* STEP 2 PROCESS ANIMATIONS */
diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp
index 7a1b10792b..4ec22cf3df 100644
--- a/scene/animation/skeleton_ik.cpp
+++ b/scene/animation/skeleton_ik.cpp
@@ -320,7 +320,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove
new_bone_pose.basis = new_bone_pose.basis * p_task->chain.tips[0].end_effector->goal_transform.basis;
}
- p_task->skeleton->set_bone_global_pose(ci->bone, new_bone_pose);
+ p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0);
if (!ci->children.empty())
ci = &ci->children.write[0];
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 0f7d4466c8..1f9793190d 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -191,7 +191,7 @@ void Tween::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
// Are we processing during 'regular' time?
if (tween_process_mode == TWEEN_PROCESS_IDLE)
- // Do nothing since we whould only process during idle time
+ // Do nothing since we would only process during idle time
break;
// Should we update?
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 174c2fce7d..d39f017cad 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -818,7 +818,7 @@ Size2 Control::get_minimum_size() const {
Ref<Texture> Control::get_icon(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
const Ref<Texture> *tex = data.icon_override.getptr(p_name);
if (tex)
@@ -860,7 +860,7 @@ Ref<Texture> Control::get_icon(const StringName &p_name, const StringName &p_typ
}
Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
const Ref<Shader> *sdr = data.shader_override.getptr(p_name);
if (sdr)
@@ -903,7 +903,7 @@ Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_ty
Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
const Ref<StyleBox> *style = data.style_override.getptr(p_name);
if (style)
return *style;
@@ -949,7 +949,7 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &
}
Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
const Ref<Font> *font = data.font_override.getptr(p_name);
if (font)
return *font;
@@ -986,7 +986,7 @@ Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type)
}
Color Control::get_color(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
const Color *color = data.color_override.getptr(p_name);
if (color)
return *color;
@@ -1026,7 +1026,7 @@ Color Control::get_color(const StringName &p_name, const StringName &p_type) con
int Control::get_constant(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
const int *constant = data.constant_override.getptr(p_name);
if (constant)
return *constant;
@@ -1102,7 +1102,7 @@ bool Control::has_constant_override(const StringName &p_name) const {
bool Control::has_icon(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
if (has_icon_override(p_name))
return true;
}
@@ -1141,7 +1141,7 @@ bool Control::has_icon(const StringName &p_name, const StringName &p_type) const
bool Control::has_shader(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
if (has_shader_override(p_name))
return true;
}
@@ -1179,7 +1179,7 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con
}
bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
if (has_stylebox_override(p_name))
return true;
}
@@ -1217,7 +1217,7 @@ bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) c
}
bool Control::has_font(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
if (has_font_override(p_name))
return true;
}
@@ -1256,7 +1256,7 @@ bool Control::has_font(const StringName &p_name, const StringName &p_type) const
bool Control::has_color(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
if (has_color_override(p_name))
return true;
}
@@ -1295,7 +1295,7 @@ bool Control::has_color(const StringName &p_name, const StringName &p_type) cons
bool Control::has_constant(const StringName &p_name, const StringName &p_type) const {
- if (p_type == StringName() || p_type == "") {
+ if (p_type == StringName() || p_type == get_class_name()) {
if (has_constant_override(p_name))
return true;
}
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 59bbdad97a..9ed1d2bf45 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -35,6 +35,7 @@
#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
+#include "scene/main/viewport.h" // Only used to check for more modals when dimming the editor.
#endif
// WindowDialog
@@ -59,7 +60,7 @@ void WindowDialog::_fix_size() {
float left = 0;
float bottom = 0;
float right = 0;
- // Check validity, because the theme could contain a different type of StyleBox
+ // 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);
@@ -242,7 +243,7 @@ void WindowDialog::_notification(int p_what) {
} break;
case NOTIFICATION_POPUP_HIDE: {
- if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton())
+ if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton() && !get_viewport()->gui_has_modal_stack())
EditorNode::get_singleton()->dim_editor(false);
} break;
#endif
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 6893c38733..04e03f569e 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -87,7 +87,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} else {
- if (b->is_doubleclick()) {
+ if (b->is_doubleclick() && selecting_enabled) {
selection.enabled = true;
selection.begin = 0;
@@ -195,13 +195,13 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
unsigned int code = k->get_scancode();
- if (k->get_command()) {
+ if (k->get_command() && is_shortcut_keys_enabled()) {
bool handled = true;
switch (code) {
- case (KEY_X): { // CUT
+ case (KEY_X): { // CUT.
if (editable) {
cut_text();
@@ -209,13 +209,13 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
- case (KEY_C): { // COPY
+ case (KEY_C): { // COPY.
copy_text();
} break;
- case (KEY_V): { // PASTE
+ case (KEY_V): { // PASTE.
if (editable) {
@@ -224,7 +224,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
- case (KEY_Z): { // undo / redo
+ case (KEY_Z): { // Undo/redo.
if (editable) {
if (k->get_shift()) {
redo();
@@ -234,7 +234,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
} break;
- case (KEY_U): { // Delete from start to cursor
+ case (KEY_U): { // Delete from start to cursor.
if (editable) {
@@ -255,7 +255,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
- case (KEY_Y): { // PASTE (Yank for unix users)
+ case (KEY_Y): { // PASTE (Yank for unix users).
if (editable) {
@@ -263,7 +263,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
} break;
- case (KEY_K): { // Delete from cursor_pos to end
+ case (KEY_K): { // Delete from cursor_pos to end.
if (editable) {
@@ -273,14 +273,15 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
} break;
- case (KEY_A): { //Select All
+ case (KEY_A): { // Select all.
select();
+
} break;
#ifdef APPLE_STYLE_KEYS
- case (KEY_LEFT): { // Go to start of text - like HOME key
+ case (KEY_LEFT): { // Go to start of text - like HOME key.
set_cursor_position(0);
} break;
- case (KEY_RIGHT): { // Go to end of text - like END key
+ case (KEY_RIGHT): { // Go to end of text - like END key.
set_cursor_position(text.length());
} break;
#endif
@@ -473,7 +474,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
int text_len = text.length();
if (cursor_pos == text_len)
- break; // nothing to do
+ break; // Nothing to do.
#ifdef APPLE_STYLE_KEYS
if (k->get_alt()) {
@@ -531,6 +532,16 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
set_cursor_position(text.length());
shift_selection_check_post(k->get_shift());
} break;
+ case KEY_MENU: {
+ if (context_menu_enabled) {
+ Point2 pos = Point2(get_cursor_pixel_pos(), (get_size().y + get_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->popup();
+ menu->grab_focus();
+ }
+ } break;
default: {
@@ -730,7 +741,7 @@ void LineEdit::_notification(int p_what) {
Color cursor_color = get_color("cursor_color");
const String &t = using_placeholder ? placeholder_translated : text;
- // draw placeholder color
+ // Draw placeholder color.
if (using_placeholder)
font_color.a *= placeholder_alpha;
@@ -745,24 +756,28 @@ void LineEdit::_notification(int p_what) {
color_icon = get_color("clear_button_color");
}
}
- r_icon->draw(ci, Point2(width - r_icon->get_width() - style->get_margin(MARGIN_RIGHT), height / 2 - r_icon->get_height() / 2), color_icon);
+
+ float icon_width = MIN(r_icon->get_width(), r_icon->get_width() * (height - (style->get_margin(MARGIN_TOP) + style->get_margin(MARGIN_BOTTOM))) / r_icon->get_height());
+ float icon_height = MIN(r_icon->get_height(), height - (style->get_margin(MARGIN_TOP) + style->get_margin(MARGIN_BOTTOM)));
+ Rect2 icon_region = Rect2(Point2(width - icon_width - style->get_margin(MARGIN_RIGHT), height / 2 - icon_height / 2), Size2(icon_width, icon_height));
+ draw_texture_rect_region(r_icon, icon_region, Rect2(Point2(), r_icon->get_size()), color_icon);
if (align == ALIGN_CENTER) {
if (window_pos == 0) {
- x_ofs = MAX(style->get_margin(MARGIN_LEFT), int(size.width - cached_text_width - r_icon->get_width() - style->get_margin(MARGIN_RIGHT) * 2) / 2);
+ x_ofs = MAX(style->get_margin(MARGIN_LEFT), int(size.width - cached_text_width - icon_width - style->get_margin(MARGIN_RIGHT) * 2) / 2);
}
} else {
- x_ofs = MAX(style->get_margin(MARGIN_LEFT), x_ofs - r_icon->get_width() - style->get_margin(MARGIN_RIGHT));
+ x_ofs = MAX(style->get_margin(MARGIN_LEFT), x_ofs - icon_width - style->get_margin(MARGIN_RIGHT));
}
- ofs_max -= r_icon->get_width();
+ ofs_max -= icon_width;
}
int caret_height = font->get_height() > y_area ? y_area : font->get_height();
FontDrawer drawer(font, Color(1, 1, 1));
while (true) {
- //end of string, break!
+ // End of string, break.
if (char_ofs >= t.length())
break;
@@ -799,7 +814,7 @@ void LineEdit::_notification(int p_what) {
CharType next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1];
int char_width = font->get_char_size(cchar, next).width;
- // end of widget, break!
+ // End of widget, break.
if ((x_ofs + char_width) > ofs_max)
break;
@@ -854,7 +869,7 @@ void LineEdit::_notification(int p_what) {
}
}
- if (char_ofs == cursor_pos && draw_caret) { //may be at the end
+ if (char_ofs == cursor_pos && draw_caret) { // May be at the end.
if (ime_text.length() == 0) {
#ifdef TOOLS_ENABLED
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color);
@@ -1043,7 +1058,7 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
}
pixel_ofs += char_w;
- if (pixel_ofs > p_x) { //found what we look for
+ if (pixel_ofs > p_x) { // Found what we look for.
break;
}
@@ -1053,6 +1068,52 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
set_cursor_position(ofs);
}
+int LineEdit::get_cursor_pixel_pos() {
+
+ Ref<Font> font = get_font("font");
+ int ofs = window_pos;
+ Ref<StyleBox> style = get_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();
+
+ switch (align) {
+
+ case ALIGN_FILL:
+ case ALIGN_LEFT: {
+
+ pixel_ofs = int(style->get_offset().x);
+ } break;
+ case ALIGN_CENTER: {
+
+ if (window_pos != 0)
+ pixel_ofs = int(style->get_offset().x);
+ else
+ pixel_ofs = int(size.width - (cached_width)) / 2;
+
+ if (display_clear_icon)
+ pixel_ofs -= int(r_icon_width / 2 + style->get_margin(MARGIN_RIGHT));
+ } break;
+ case ALIGN_RIGHT: {
+
+ pixel_ofs = int(size.width - style->get_margin(MARGIN_RIGHT) - (cached_width));
+
+ if (display_clear_icon)
+ pixel_ofs -= int(r_icon_width + style->get_margin(MARGIN_RIGHT));
+ } break;
+ }
+
+ while (ofs < cursor_pos) {
+ if (font != NULL) {
+ pixel_ofs += font->get_char_size(text[ofs]).width;
+ }
+ ofs++;
+ }
+
+ return pixel_ofs;
+}
+
bool LineEdit::cursor_get_blink_enabled() const {
return caret_blink_enabled;
}
@@ -1210,15 +1271,18 @@ void LineEdit::set_cursor_position(int p_pos) {
Ref<Font> font = get_font("font");
if (cursor_pos <= window_pos) {
- /* Adjust window if cursor goes too much to the left */
+ // Adjust window if cursor goes too much to the left.
set_window_pos(MAX(0, cursor_pos - 1));
} else {
- /* Adjust window if cursor goes too much to the right */
+ // Adjust window if cursor goes too much to the right.
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<Texture> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon;
- window_width -= r_icon->get_width();
+
+ float icon_width = MIN(r_icon->get_width(), r_icon->get_width() * (get_size().height - (style->get_margin(MARGIN_TOP) + style->get_margin(MARGIN_BOTTOM))) / r_icon->get_height());
+
+ window_width -= icon_width;
}
if (window_width < 0)
@@ -1232,10 +1296,10 @@ void LineEdit::set_cursor_position(int p_pos) {
for (int i = cursor_pos; i >= window_pos; i--) {
if (i >= text.length()) {
- //do not do this, because if the cursor is at the end, its just fine that it takes no space
- //accum_width = font->get_char_size(' ').width; //anything should do
+ // Do not do this, because if the cursor is at the end, its just fine that it takes no space.
+ // accum_width = font->get_char_size(' ').width;
} else {
- accum_width += font->get_char_size(text[i], i + 1 < text.length() ? text[i + 1] : 0).width; //anything should do
+ accum_width += font->get_char_size(text[i], i + 1 < text.length() ? text[i + 1] : 0).width; // Anything should do.
}
if (accum_width > window_width)
break;
@@ -1300,12 +1364,13 @@ Size2 LineEdit::get_minimum_size() const {
Size2 min = style->get_minimum_size();
min.height += font->get_height();
- //minimum size of text
+ // Minimum size of text.
int space_size = font->get_char_size(' ').x;
int mstext = get_constant("minimum_spaces") * space_size;
if (expand_to_text_length) {
- mstext = MAX(mstext, font->get_string_size(text).x + space_size); //add a spce because some fonts are too exact, and because cursor needs a bit more when at the end
+ // Add a space because some fonts are too exact, and because cursor needs a bit more when at the end.
+ mstext = MAX(mstext, font->get_string_size(text).x + space_size);
}
min.width += mstext;
@@ -1313,8 +1378,6 @@ Size2 LineEdit::get_minimum_size() const {
return min;
}
-/* selection */
-
void LineEdit::deselect() {
selection.begin = 0;
@@ -1347,6 +1410,8 @@ int LineEdit::get_max_length() const {
}
void LineEdit::selection_fill_at_cursor() {
+ if (!selecting_enabled)
+ return;
selection.begin = cursor_pos;
selection.end = selection.cursor_start;
@@ -1361,6 +1426,8 @@ void LineEdit::selection_fill_at_cursor() {
}
void LineEdit::select_all() {
+ if (!selecting_enabled)
+ return;
if (!text.length())
return;
@@ -1377,32 +1444,7 @@ void LineEdit::set_editable(bool p_editable) {
return;
editable = p_editable;
-
- // Reorganize context menu.
- menu->clear();
-
- if (editable) {
- menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
- menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
- }
-
- if (editable) {
- menu->add_separator();
- menu->add_item(RTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X);
- }
-
- menu->add_item(RTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C);
-
- if (editable) {
- menu->add_item(RTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V);
- }
-
- menu->add_separator();
- menu->add_item(RTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A);
-
- if (editable) {
- menu->add_item(RTR("Clear"), MENU_CLEAR);
- }
+ _generate_context_menu();
update();
}
@@ -1425,8 +1467,8 @@ bool LineEdit::is_secret() const {
void LineEdit::set_secret_character(const String &p_string) {
- // An empty string as the secret character would crash the engine
- // It also wouldn't make sense to use multiple characters as the secret character
+ // An empty string as the secret character would crash the engine.
+ // It also wouldn't make sense to use multiple characters as the secret character.
ERR_FAIL_COND_MSG(p_string.length() != 1, "Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given).");
secret_character = p_string;
@@ -1438,6 +1480,8 @@ String LineEdit::get_secret_character() const {
}
void LineEdit::select(int p_from, int p_to) {
+ if (!selecting_enabled)
+ return;
if (p_from == 0 && p_to == 0) {
deselect();
@@ -1545,6 +1589,29 @@ bool LineEdit::is_clear_button_enabled() const {
return clear_button_enabled;
}
+void LineEdit::set_shortcut_keys_enabled(bool p_enabled) {
+ shortcut_keys_enabled = p_enabled;
+
+ _generate_context_menu();
+}
+
+bool LineEdit::is_shortcut_keys_enabled() const {
+ return shortcut_keys_enabled;
+}
+
+void LineEdit::set_selecting_enabled(bool p_enabled) {
+ selecting_enabled = p_enabled;
+
+ if (!selecting_enabled)
+ deselect();
+
+ _generate_context_menu();
+}
+
+bool LineEdit::is_selecting_enabled() const {
+ return selecting_enabled;
+}
+
void LineEdit::set_right_icon(const Ref<Texture> &p_icon) {
if (right_icon == p_icon) {
return;
@@ -1553,8 +1620,11 @@ void LineEdit::set_right_icon(const Ref<Texture> &p_icon) {
update();
}
-void LineEdit::_text_changed() {
+Ref<Texture> LineEdit::get_right_icon() {
+ return right_icon;
+}
+void LineEdit::_text_changed() {
if (expand_to_text_length)
minimum_size_changed();
@@ -1608,6 +1678,25 @@ void LineEdit::_create_undo_state() {
undo_stack.push_back(op);
}
+void LineEdit::_generate_context_menu() {
+ // Reorganize context menu.
+ menu->clear();
+ if (editable)
+ menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_X : 0);
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_C : 0);
+ if (editable)
+ menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_V : 0);
+ menu->add_separator();
+ if (is_selecting_enabled())
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_A : 0);
+ if (editable) {
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
+ menu->add_separator();
+ menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_Z : 0);
+ menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z : 0);
+ }
+}
+
void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed);
@@ -1652,6 +1741,12 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled);
ClassDB::bind_method(D_METHOD("set_clear_button_enabled", "enable"), &LineEdit::set_clear_button_enabled);
ClassDB::bind_method(D_METHOD("is_clear_button_enabled"), &LineEdit::is_clear_button_enabled);
+ ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &LineEdit::set_shortcut_keys_enabled);
+ ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &LineEdit::is_shortcut_keys_enabled);
+ ClassDB::bind_method(D_METHOD("set_selecting_enabled", "enable"), &LineEdit::set_selecting_enabled);
+ ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &LineEdit::is_selecting_enabled);
+ ClassDB::bind_method(D_METHOD("set_right_icon", "icon"), &LineEdit::set_right_icon);
+ ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "new_text")));
ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "new_text")));
@@ -1680,6 +1775,9 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
ADD_GROUP("Placeholder", "placeholder_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha");
@@ -1707,6 +1805,8 @@ LineEdit::LineEdit() {
clear_button_enabled = false;
clear_button_status.press_attempt = false;
clear_button_status.pressing_inside = false;
+ shortcut_keys_enabled = true;
+ selecting_enabled = true;
deselect();
set_focus_mode(FOCUS_ALL);
@@ -1724,7 +1824,7 @@ LineEdit::LineEdit() {
context_menu_enabled = true;
menu = memnew(PopupMenu);
add_child(menu);
- editable = false; // initialise to opposite first, so we get past the early-out in set_editable
+ editable = false; // Initialise to opposite first, so we get past the early-out in set_editable.
set_editable(true);
menu->connect("id_pressed", this, "menu_option");
expand_to_text_length = false;
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 1d33f7d4ce..3424131dad 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -75,18 +75,22 @@ private:
String ime_text;
Point2 ime_selection;
+ bool selecting_enabled;
+
bool context_menu_enabled;
PopupMenu *menu;
int cursor_pos;
int window_pos;
- int max_length; // 0 for no maximum
+ int max_length; // 0 for no maximum.
int cached_width;
int cached_placeholder_width;
bool clear_button_enabled;
+ bool shortcut_keys_enabled;
+
Ref<Texture> right_icon;
struct Selection {
@@ -118,6 +122,8 @@ private:
void _clear_redo();
void _create_undo_state();
+ void _generate_context_menu();
+
Timer *caret_blink_timer;
void _text_changed();
@@ -137,6 +143,7 @@ private:
void set_window_pos(int p_pos);
void set_cursor_at_pixel_pos(int p_x);
+ int get_cursor_pixel_pos();
void _reset_caret_blink_timer();
void _toggle_draw_caret();
@@ -216,7 +223,14 @@ public:
void set_clear_button_enabled(bool p_enabled);
bool is_clear_button_enabled() const;
+ void set_shortcut_keys_enabled(bool p_enabled);
+ bool is_shortcut_keys_enabled() const;
+
+ void set_selecting_enabled(bool p_enabled);
+ bool is_selecting_enabled() const;
+
void set_right_icon(const Ref<Texture> &p_icon);
+ Ref<Texture> get_right_icon();
virtual bool is_text_field() const;
LineEdit();
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index d1840e43a3..de8df4215d 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -116,10 +116,16 @@ void OptionButton::add_item(const String &p_label, int p_id) {
void OptionButton::set_item_text(int p_idx, const String &p_text) {
popup->set_item_text(p_idx, p_text);
+
+ if (current == p_idx)
+ set_text(p_text);
}
void OptionButton::set_item_icon(int p_idx, const Ref<Texture> &p_icon) {
popup->set_item_icon(p_idx, p_icon);
+
+ if (current == p_idx)
+ set_icon(p_icon);
}
void OptionButton::set_item_id(int p_idx, int p_id) {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 77d5c8e91f..d9ae42d6e6 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2631,7 +2631,7 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selection_enabled"), "set_selection_enabled", "is_selection_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", (PropertyHint)(PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE), "17/17:RichTextEffect", PROPERTY_USAGE_DEFAULT, "RichTextEffect"), "set_effects", "get_effects");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_RESOURCE_TYPE, "17/17:RichTextEffect", (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE), "RichTextEffect"), "set_effects", "get_effects");
ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
ADD_SIGNAL(MethodInfo("meta_hover_started", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 6755f9ef2a..1c212700ef 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -456,7 +456,7 @@ public:
void push_meta(const Variant &p_meta);
void push_table(int p_columns);
void push_fade(int p_start_index, int p_length);
- void push_shake(int p_level, float p_rate);
+ void push_shake(int p_strength, float p_rate);
void push_wave(float p_frequency, float p_amplitude);
void push_tornado(float p_frequency, float p_radius);
void push_rainbow(float p_saturation, float p_value, float p_frequency);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7bcef5f9ab..d5f1d317c7 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -647,7 +647,7 @@ void TextEdit::_notification(int p_what) {
if (scrolling && get_v_scroll() != target_v_scroll) {
double target_y = target_v_scroll - get_v_scroll();
double dist = sqrt(target_y * target_y);
- // To ensure minimap is responsive overide the speed setting.
+ // To ensure minimap is responsive override the speed setting.
double vel = ((target_y / dist) * ((minimap_clicked) ? 3000 : v_scroll_speed)) * get_physics_process_delta_time();
if (Math::abs(vel) >= dist) {
@@ -2081,6 +2081,44 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
r_col = col;
}
+Vector2i TextEdit::_get_cursor_pixel_pos() {
+ adjust_viewport_to_cursor();
+ int row = (cursor.line - get_first_visible_line() - cursor.wrap_ofs);
+ // Correct for hidden and wrapped lines
+ for (int i = get_first_visible_line(); i < cursor.line; i++) {
+ if (is_line_hidden(i)) {
+ row -= 1;
+ continue;
+ }
+ row += times_line_wraps(i);
+ }
+ // Row might be wrapped. Adjust row and r_column
+ Vector<String> rows2 = get_wrap_rows_text(cursor.line);
+ while (rows2.size() > 1) {
+ if (cursor.column >= rows2[0].length()) {
+ cursor.column -= rows2[0].length();
+ rows2.remove(0);
+ row++;
+ } else {
+ break;
+ }
+ }
+
+ // Calculate final pixel position
+ int y = (row - get_v_scroll_offset() + 1 /*Bottom of line*/) * get_row_height();
+ int x = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs;
+ int ix = 0;
+ while (ix < rows2[0].size() && ix < cursor.column) {
+ if (cache.font != NULL) {
+ x += cache.font->get_char_size(rows2[0].get(ix)).width;
+ }
+ ix++;
+ }
+ x += get_indent_level(cursor.line) * cache.font->get_char_size(' ').width;
+
+ return Vector2i(x, y);
+}
+
void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const {
float rows = p_mouse.y;
@@ -2417,7 +2455,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mm.is_valid()) {
if (select_identifiers_enabled) {
- if (mm->get_command() && mm->get_button_mask() == 0) {
+ if (!dragging_minimap && !dragging_selection && mm->get_command() && mm->get_button_mask() == 0) {
String new_word = get_word_at_pos(mm->get_position());
if (new_word != highlighted_word) {
@@ -2475,7 +2513,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
#endif
if (select_identifiers_enabled) {
- if (k->is_pressed()) {
+ if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
highlighted_word = get_word_at_pos(get_local_mouse_position());
update();
@@ -3222,7 +3260,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (readonly)
break;
- if (k->get_shift() && !k->get_command() && !k->get_alt()) {
+ if (k->get_shift() && !k->get_command() && !k->get_alt() && is_shortcut_keys_enabled()) {
cut();
break;
}
@@ -3453,13 +3491,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
- select_all();
+ if (is_shortcut_keys_enabled()) {
+ select_all();
+ }
#else
if ((!k->get_command() && !k->get_control())) {
scancode_handled = false;
break;
}
- if (!k->get_shift() && k->get_command())
+ if (!k->get_shift() && k->get_command() && is_shortcut_keys_enabled())
select_all();
else if (k->get_control()) {
if (k->get_shift())
@@ -3515,8 +3555,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
scancode_handled = false;
break;
}
-
- cut();
+ if (is_shortcut_keys_enabled()) {
+ cut();
+ }
} break;
case KEY_C: {
@@ -3526,7 +3567,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
break;
}
- copy();
+ if (is_shortcut_keys_enabled()) {
+ copy();
+ }
} break;
case KEY_Z: {
@@ -3540,10 +3583,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
break;
}
- if (k->get_shift())
- redo();
- else
- undo();
+ if (is_shortcut_keys_enabled()) {
+ if (k->get_shift())
+ redo();
+ else
+ undo();
+ }
} break;
case KEY_Y: {
@@ -3556,7 +3601,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
break;
}
- redo();
+ if (is_shortcut_keys_enabled()) {
+ redo();
+ }
} break;
case KEY_V: {
if (readonly) {
@@ -3567,7 +3614,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
break;
}
- paste();
+ if (is_shortcut_keys_enabled()) {
+ paste();
+ }
} break;
case KEY_SPACE: {
@@ -3585,6 +3634,16 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
} break;
+ case KEY_MENU: {
+ 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->popup();
+ menu->grab_focus();
+ }
+ } break;
+
default: {
scancode_handled = false;
@@ -4061,6 +4120,25 @@ int TextEdit::_get_control_height() const {
return control_height;
}
+void TextEdit::_generate_context_menu() {
+ // Reorganize context menu.
+ menu->clear();
+ if (!readonly)
+ menu->add_item(RTR("Cut"), MENU_CUT, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_X : 0);
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_C : 0);
+ if (!readonly)
+ menu->add_item(RTR("Paste"), MENU_PASTE, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_V : 0);
+ menu->add_separator();
+ if (is_selecting_enabled())
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_A : 0);
+ if (!readonly) {
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
+ menu->add_separator();
+ menu->add_item(RTR("Undo"), MENU_UNDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_Z : 0);
+ menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z : 0);
+ }
+}
+
int TextEdit::get_visible_rows() const {
return _get_control_height() / get_row_height();
}
@@ -4769,6 +4847,7 @@ void TextEdit::set_readonly(bool p_readonly) {
return;
readonly = p_readonly;
+ _generate_context_menu();
// Reorganize context menu.
menu->clear();
@@ -5108,6 +5187,8 @@ void TextEdit::paste() {
}
void TextEdit::select_all() {
+ if (!selecting_enabled)
+ return;
if (text.size() == 1 && text[0].length() == 0)
return;
@@ -5132,6 +5213,8 @@ void TextEdit::deselect() {
}
void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_to_column) {
+ if (!selecting_enabled)
+ return;
if (p_from_line < 0)
p_from_line = 0;
@@ -6247,7 +6330,7 @@ void TextEdit::_confirm_completion() {
CharType last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1];
if ((last_completion_char == '"' || last_completion_char == '\'') && last_completion_char == next_char) {
- _base_remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
+ _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1);
}
if (last_completion_char == '(') {
@@ -6775,6 +6858,29 @@ bool TextEdit::is_context_menu_enabled() {
return context_menu_enabled;
}
+void TextEdit::set_shortcut_keys_enabled(bool p_enabled) {
+ shortcut_keys_enabled = p_enabled;
+
+ _generate_context_menu();
+}
+
+void TextEdit::set_selecting_enabled(bool p_enabled) {
+ selecting_enabled = p_enabled;
+
+ if (!selecting_enabled)
+ deselect();
+
+ _generate_context_menu();
+}
+
+bool TextEdit::is_selecting_enabled() const {
+ return selecting_enabled;
+}
+
+bool TextEdit::is_shortcut_keys_enabled() const {
+ return shortcut_keys_enabled;
+}
+
PopupMenu *TextEdit::get_menu() const {
return menu;
}
@@ -6830,6 +6936,10 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_wrap_enabled"), &TextEdit::is_wrap_enabled);
ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &TextEdit::set_context_menu_enabled);
ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &TextEdit::is_context_menu_enabled);
+ ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &TextEdit::set_shortcut_keys_enabled);
+ ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &TextEdit::is_shortcut_keys_enabled);
+ ClassDB::bind_method(D_METHOD("set_selecting_enabled", "enable"), &TextEdit::set_selecting_enabled);
+ ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &TextEdit::is_selecting_enabled);
ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut);
ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy);
@@ -6920,6 +7030,8 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hiding_enabled"), "set_hiding_enabled", "is_hiding_enabled");
@@ -7078,7 +7190,9 @@ TextEdit::TextEdit() {
minimap_char_size = Point2(1, 2);
minimap_line_spacing = 1;
+ selecting_enabled = true;
context_menu_enabled = true;
+ shortcut_keys_enabled = true;
menu = memnew(PopupMenu);
add_child(menu);
readonly = true; // Initialise to opposite first, so we get past the early-out in set_readonly.
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 9c568acd93..e5d9b006fe 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -365,10 +365,15 @@ private:
int search_result_line;
int search_result_col;
+ bool selecting_enabled;
+
bool context_menu_enabled;
+ bool shortcut_keys_enabled;
int executing_line;
+ void _generate_context_menu();
+
int get_visible_rows() const;
int get_total_visible_rows() const;
@@ -582,6 +587,7 @@ public:
int cursor_get_column() const;
int cursor_get_line() const;
+ Vector2i _get_cursor_pixel_pos();
bool cursor_get_blink_enabled() const;
void cursor_set_blink_enabled(const bool p_enabled);
@@ -737,6 +743,12 @@ public:
void set_context_menu_enabled(bool p_enable);
bool is_context_menu_enabled();
+ void set_selecting_enabled(bool p_enabled);
+ bool is_selecting_enabled() const;
+
+ void set_shortcut_keys_enabled(bool p_enabled);
+ bool is_shortcut_keys_enabled() const;
+
PopupMenu *get_menu() const;
String get_text_for_completion();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 2a18436a5e..57663bbe82 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -328,7 +328,7 @@ void TreeItem::set_collapsed(bool p_collapsed) {
ci = ci->parent;
}
- if (ci) { // collapsing cursor/selectd, move it!
+ if (ci) { // collapsing cursor/selected, move it!
if (tree->select_mode == Tree::SELECT_MULTI) {
@@ -914,7 +914,6 @@ void Tree::update_cache() {
cache.arrow_collapsed = get_icon("arrow_collapsed");
cache.arrow = get_icon("arrow");
cache.select_arrow = get_icon("select_arrow");
- cache.select_option = get_icon("select_option");
cache.updown = get_icon("updown");
cache.custom_button = get_stylebox("custom_button");
@@ -930,7 +929,6 @@ void Tree::update_cache() {
cache.vseparation = get_constant("vseparation");
cache.item_margin = get_constant("item_margin");
cache.button_margin = get_constant("button_margin");
- cache.guide_width = get_constant("guide_width");
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");
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index fdc6da5055..f12d8fc4d2 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -416,7 +416,6 @@ private:
Ref<Texture> arrow_collapsed;
Ref<Texture> arrow;
Ref<Texture> select_arrow;
- Ref<Texture> select_option;
Ref<Texture> updown;
Color font_color;
@@ -429,7 +428,6 @@ private:
int hseparation;
int vseparation;
int item_margin;
- int guide_width;
int button_margin;
Point2 offset;
int draw_relationship_lines;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index bd01ca2886..ba04cb69f2 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2861,6 +2861,8 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
BIND_CONSTANT(NOTIFICATION_CRASH);
BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE);
+ BIND_CONSTANT(NOTIFICATION_APP_RESUMED);
+ BIND_CONSTANT(NOTIFICATION_APP_PAUSED);
BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT);
BIND_ENUM_CONSTANT(PAUSE_MODE_STOP);
diff --git a/scene/main/node.h b/scene/main/node.h
index 51a1436014..a8bcd2f273 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -250,7 +250,9 @@ public:
NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED,
NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT,
NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH,
- NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE
+ NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE,
+ NOTIFICATION_APP_RESUMED = MainLoop::NOTIFICATION_APP_RESUMED,
+ NOTIFICATION_APP_PAUSED = MainLoop::NOTIFICATION_APP_PAUSED
};
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 5483fe1d6f..0465c9305b 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -630,6 +630,7 @@ void SceneTree::_notification(int p_notification) {
break;
}
} break;
+
case NOTIFICATION_WM_GO_BACK_REQUEST: {
get_root()->propagate_notification(p_notification);
@@ -639,28 +640,23 @@ void SceneTree::_notification(int p_notification) {
break;
}
} 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_IN:
- case NOTIFICATION_WM_FOCUS_OUT:
- case NOTIFICATION_WM_ABOUT: {
- if (p_notification == NOTIFICATION_WM_FOCUS_IN) {
- InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
- if (id) {
- id->ensure_touch_mouse_raised();
- }
+ case NOTIFICATION_WM_FOCUS_IN: {
+
+ InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
+ if (id) {
+ id->ensure_touch_mouse_raised();
}
get_root()->propagate_notification(p_notification);
} break;
+
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);
@@ -669,7 +665,15 @@ void SceneTree::_notification(int p_notification) {
} break;
- case NOTIFICATION_CRASH: {
+ 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:
+ case NOTIFICATION_APP_PAUSED: {
get_root()->propagate_notification(p_notification);
} break;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index e3af521e8c..418ee6af0e 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -364,6 +364,9 @@ void register_scene_types() {
/* REGISTER 3D */
+ ClassDB::register_class<Skin>();
+ ClassDB::register_virtual_class<SkinReference>();
+
ClassDB::register_class<Spatial>();
ClassDB::register_virtual_class<SpatialGizmo>();
ClassDB::register_class<Skeleton>();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index d761eb01fe..f68dc9af38 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -657,7 +657,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("hseparation", "Tree", 4 * scale);
theme->set_constant("vseparation", "Tree", 4 * scale);
- theme->set_constant("guide_width", "Tree", 2 * scale);
theme->set_constant("item_margin", "Tree", 12 * scale);
theme->set_constant("button_margin", "Tree", 4 * scale);
theme->set_constant("draw_relationship_lines", "Tree", 0);
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index cd229732ba..1c41f30a94 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -1713,6 +1713,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
if (groups.size()) {
+ groups.sort_custom<StringName::AlphCompare>();
String sgroups = " groups=[\n";
for (int j = 0; j < groups.size(); j++) {
sgroups += "\"" + String(groups[j]).c_escape() + "\",\n";
diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp
new file mode 100644
index 0000000000..8446e2f249
--- /dev/null
+++ b/scene/resources/skin.cpp
@@ -0,0 +1,102 @@
+#include "skin.h"
+
+void Skin::set_bind_count(int p_size) {
+ ERR_FAIL_COND(p_size < 0);
+ binds.resize(p_size);
+ binds_ptr = binds.ptrw();
+ bind_count = p_size;
+ emit_changed();
+}
+
+void Skin::add_bind(int p_bone, const Transform &p_pose) {
+ uint32_t index = bind_count;
+ set_bind_count(bind_count + 1);
+ set_bind_bone(index, p_bone);
+ set_bind_pose(index, p_pose);
+}
+
+void Skin::set_bind_bone(int p_index, int p_bone) {
+ ERR_FAIL_INDEX(p_index, bind_count);
+ binds_ptr[p_index].bone = p_bone;
+ emit_changed();
+}
+
+void Skin::set_bind_pose(int p_index, const Transform &p_pose) {
+ ERR_FAIL_INDEX(p_index, bind_count);
+ binds_ptr[p_index].pose = p_pose;
+ emit_changed();
+}
+
+void Skin::clear_binds() {
+ binds.clear();
+ binds_ptr = nullptr;
+ bind_count = 0;
+ emit_changed();
+}
+
+bool Skin::_set(const StringName &p_name, const Variant &p_value) {
+ String name = p_name;
+ if (name == "bind_count") {
+ set_bind_count(p_value);
+ return true;
+ } else if (name.begins_with("bind/")) {
+ int index = name.get_slicec('/', 1).to_int();
+ String what = name.get_slicec('/', 2);
+ if (what == "bone") {
+ set_bind_bone(index, p_value);
+ return true;
+ } else if (what == "pose") {
+ set_bind_pose(index, p_value);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Skin::_get(const StringName &p_name, Variant &r_ret) const {
+
+ String name = p_name;
+ if (name == "bind_count") {
+ r_ret = get_bind_count();
+ return true;
+ } else if (name.begins_with("bind/")) {
+ int index = name.get_slicec('/', 1).to_int();
+ String what = name.get_slicec('/', 2);
+ if (what == "bone") {
+ r_ret = get_bind_bone(index);
+ return true;
+ } else if (what == "pose") {
+ r_ret = get_bind_pose(index);
+ return true;
+ }
+ }
+ return false;
+}
+void Skin::_get_property_list(List<PropertyInfo> *p_list) const {
+ p_list->push_back(PropertyInfo(Variant::INT, "bind_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"));
+ for (int i = 0; i < get_bind_count(); i++) {
+ p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"));
+ p_list->push_back(PropertyInfo(Variant::TRANSFORM, "bind/" + itos(i) + "/pose"));
+ }
+}
+
+void Skin::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_bind_count", "bind_count"), &Skin::set_bind_count);
+ ClassDB::bind_method(D_METHOD("get_bind_count"), &Skin::get_bind_count);
+
+ ClassDB::bind_method(D_METHOD("add_bind", "bone", "pose"), &Skin::add_bind);
+
+ ClassDB::bind_method(D_METHOD("set_bind_pose", "bind_index", "pose"), &Skin::set_bind_pose);
+ ClassDB::bind_method(D_METHOD("get_bind_pose", "bind_index"), &Skin::get_bind_pose);
+
+ ClassDB::bind_method(D_METHOD("set_bind_bone", "bind_index", "bone"), &Skin::set_bind_bone);
+ ClassDB::bind_method(D_METHOD("get_bind_bone", "bind_index"), &Skin::get_bind_bone);
+
+ ClassDB::bind_method(D_METHOD("clear_binds"), &Skin::clear_binds);
+}
+
+Skin::Skin() {
+ bind_count = 0;
+ binds_ptr = nullptr;
+}
diff --git a/scene/resources/skin.h b/scene/resources/skin.h
new file mode 100644
index 0000000000..a7e55bfa89
--- /dev/null
+++ b/scene/resources/skin.h
@@ -0,0 +1,54 @@
+#ifndef SKIN_H
+#define SKIN_H
+
+#include "core/resource.h"
+
+class Skin : public Resource {
+ GDCLASS(Skin, Resource)
+
+ struct Bind {
+ int bone;
+ Transform pose;
+ };
+
+ Vector<Bind> binds;
+
+ Bind *binds_ptr;
+ int bind_count;
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static void _bind_methods();
+
+public:
+ void set_bind_count(int p_size);
+ inline int get_bind_count() const { return bind_count; }
+
+ void add_bind(int p_bone, const Transform &p_pose);
+
+ void set_bind_bone(int p_index, int p_bone);
+ void set_bind_pose(int p_index, const Transform &p_pose);
+
+ inline int get_bind_bone(int p_index) const {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_INDEX_V(p_index, bind_count, -1);
+#endif
+ return binds_ptr[p_index].bone;
+ }
+
+ inline Transform get_bind_pose(int p_index) const {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_INDEX_V(p_index, bind_count, Transform());
+#endif
+ return binds_ptr[p_index].pose;
+ }
+
+ void clear_binds();
+
+ Skin();
+};
+
+#endif // SKIN_H
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 5dd429fa75..4453032f67 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -713,6 +713,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
Vector<Point2> verts;
Vector<int> indices;
Vector<Color> colors;
+ Vector<Point2> uvs;
//DRAW SHADOW
if (draw_shadow) {
@@ -799,9 +800,17 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
}
}
+ //COMPUTE UV COORDINATES
+ Rect2 uv_rect = style_rect.grow(aa_on ? aa_size : 0);
+ uvs.resize(verts.size());
+ for (int i = 0; i < verts.size(); i++) {
+ uvs.write[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width;
+ uvs.write[i].y = (verts[i].y - uv_rect.position.y) / uv_rect.size.height;
+ }
+
//DRAWING
VisualServer *vs = VisualServer::get_singleton();
- vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors);
+ vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors, uvs);
}
float StyleBoxFlat::get_style_margin(Margin p_margin) const {
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index f5c599b67e..b7173b157e 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "visual_shader_nodes.h"
+
////////////// Scalar
String VisualShaderNodeScalarConstant::get_caption() const {
@@ -38,9 +39,11 @@ String VisualShaderNodeScalarConstant::get_caption() const {
int VisualShaderNodeScalarConstant::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeScalarConstant::PortType VisualShaderNodeScalarConstant::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarConstant::get_input_port_name(int p_port) const {
return String();
}
@@ -48,9 +51,11 @@ String VisualShaderNodeScalarConstant::get_input_port_name(int p_port) const {
int VisualShaderNodeScalarConstant::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeScalarConstant::PortType VisualShaderNodeScalarConstant::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarConstant::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -158,9 +163,11 @@ String VisualShaderNodeColorConstant::get_caption() const {
int VisualShaderNodeColorConstant::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeColorConstant::PortType VisualShaderNodeColorConstant::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeColorConstant::get_input_port_name(int p_port) const {
return String();
}
@@ -168,9 +175,11 @@ String VisualShaderNodeColorConstant::get_input_port_name(int p_port) const {
int VisualShaderNodeColorConstant::get_output_port_count() const {
return 2;
}
+
VisualShaderNodeColorConstant::PortType VisualShaderNodeColorConstant::get_output_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const {
return p_port == 0 ? "" : "alpha"; //no output port means the editor will be used as port
}
@@ -222,9 +231,11 @@ String VisualShaderNodeVec3Constant::get_caption() const {
int VisualShaderNodeVec3Constant::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeVec3Constant::PortType VisualShaderNodeVec3Constant::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVec3Constant::get_input_port_name(int p_port) const {
return String();
}
@@ -232,9 +243,11 @@ String VisualShaderNodeVec3Constant::get_input_port_name(int p_port) const {
int VisualShaderNodeVec3Constant::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeVec3Constant::PortType VisualShaderNodeVec3Constant::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVec3Constant::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -280,9 +293,11 @@ String VisualShaderNodeTransformConstant::get_caption() const {
int VisualShaderNodeTransformConstant::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeTransformConstant::PortType VisualShaderNodeTransformConstant::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeTransformConstant::get_input_port_name(int p_port) const {
return String();
}
@@ -290,9 +305,11 @@ String VisualShaderNodeTransformConstant::get_input_port_name(int p_port) const
int VisualShaderNodeTransformConstant::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeTransformConstant::PortType VisualShaderNodeTransformConstant::get_output_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
+
String VisualShaderNodeTransformConstant::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -346,9 +363,11 @@ String VisualShaderNodeTexture::get_caption() const {
int VisualShaderNodeTexture::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeTexture::get_input_port_name(int p_port) const {
return p_port == 0 ? "uv" : "lod";
}
@@ -356,11 +375,13 @@ String VisualShaderNodeTexture::get_input_port_name(int p_port) const {
int VisualShaderNodeTexture::get_output_port_count() const {
return 2;
}
+
VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_output_port_type(int p_port) const {
if (p_port == 0 && source == SOURCE_DEPTH)
return PORT_TYPE_SCALAR;
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeTexture::get_output_port_name(int p_port) const {
if (p_port == 0 && source == SOURCE_DEPTH)
return "depth";
@@ -632,9 +653,11 @@ String VisualShaderNodeCubeMap::get_caption() const {
int VisualShaderNodeCubeMap::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeCubeMap::PortType VisualShaderNodeCubeMap::get_input_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeCubeMap::get_input_port_name(int p_port) const {
return p_port == 0 ? "uv" : "lod";
}
@@ -642,9 +665,11 @@ String VisualShaderNodeCubeMap::get_input_port_name(int p_port) const {
int VisualShaderNodeCubeMap::get_output_port_count() const {
return 2;
}
+
VisualShaderNodeCubeMap::PortType VisualShaderNodeCubeMap::get_output_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeCubeMap::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
@@ -735,6 +760,7 @@ void VisualShaderNodeCubeMap::_bind_methods() {
VisualShaderNodeCubeMap::VisualShaderNodeCubeMap() {
texture_type = TYPE_DATA;
}
+
////////////// Scalar Op
String VisualShaderNodeScalarOp::get_caption() const {
@@ -744,9 +770,11 @@ String VisualShaderNodeScalarOp::get_caption() const {
int VisualShaderNodeScalarOp::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeScalarOp::PortType VisualShaderNodeScalarOp::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarOp::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -754,9 +782,11 @@ String VisualShaderNodeScalarOp::get_input_port_name(int p_port) const {
int VisualShaderNodeScalarOp::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeScalarOp::PortType VisualShaderNodeScalarOp::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarOp::get_output_port_name(int p_port) const {
return "op"; //no output port means the editor will be used as port
}
@@ -832,9 +862,11 @@ String VisualShaderNodeVectorOp::get_caption() const {
int VisualShaderNodeVectorOp::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeVectorOp::PortType VisualShaderNodeVectorOp::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorOp::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -842,9 +874,11 @@ String VisualShaderNodeVectorOp::get_input_port_name(int p_port) const {
int VisualShaderNodeVectorOp::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeVectorOp::PortType VisualShaderNodeVectorOp::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorOp::get_output_port_name(int p_port) const {
return "op"; //no output port means the editor will be used as port
}
@@ -924,9 +958,11 @@ String VisualShaderNodeColorOp::get_caption() const {
int VisualShaderNodeColorOp::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeColorOp::PortType VisualShaderNodeColorOp::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeColorOp::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -934,9 +970,11 @@ String VisualShaderNodeColorOp::get_input_port_name(int p_port) const {
int VisualShaderNodeColorOp::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeColorOp::PortType VisualShaderNodeColorOp::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeColorOp::get_output_port_name(int p_port) const {
return "op"; //no output port means the editor will be used as port
}
@@ -1072,9 +1110,11 @@ String VisualShaderNodeTransformMult::get_caption() const {
int VisualShaderNodeTransformMult::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeTransformMult::PortType VisualShaderNodeTransformMult::get_input_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
+
String VisualShaderNodeTransformMult::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -1082,9 +1122,11 @@ String VisualShaderNodeTransformMult::get_input_port_name(int p_port) const {
int VisualShaderNodeTransformMult::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeTransformMult::PortType VisualShaderNodeTransformMult::get_output_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
+
String VisualShaderNodeTransformMult::get_output_port_name(int p_port) const {
return "mult"; //no output port means the editor will be used as port
}
@@ -1147,9 +1189,11 @@ String VisualShaderNodeTransformVecMult::get_caption() const {
int VisualShaderNodeTransformVecMult::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeTransformVecMult::PortType VisualShaderNodeTransformVecMult::get_input_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_TRANSFORM : PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeTransformVecMult::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -1157,9 +1201,11 @@ String VisualShaderNodeTransformVecMult::get_input_port_name(int p_port) const {
int VisualShaderNodeTransformVecMult::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeTransformVecMult::PortType VisualShaderNodeTransformVecMult::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeTransformVecMult::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -1221,9 +1267,11 @@ String VisualShaderNodeScalarFunc::get_caption() const {
int VisualShaderNodeScalarFunc::get_input_port_count() const {
return 1;
}
+
VisualShaderNodeScalarFunc::PortType VisualShaderNodeScalarFunc::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarFunc::get_input_port_name(int p_port) const {
return "";
}
@@ -1231,9 +1279,11 @@ String VisualShaderNodeScalarFunc::get_input_port_name(int p_port) const {
int VisualShaderNodeScalarFunc::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeScalarFunc::PortType VisualShaderNodeScalarFunc::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarFunc::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -1350,9 +1400,11 @@ String VisualShaderNodeVectorFunc::get_caption() const {
int VisualShaderNodeVectorFunc::get_input_port_count() const {
return 1;
}
+
VisualShaderNodeVectorFunc::PortType VisualShaderNodeVectorFunc::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorFunc::get_input_port_name(int p_port) const {
return "";
}
@@ -1360,9 +1412,11 @@ String VisualShaderNodeVectorFunc::get_input_port_name(int p_port) const {
int VisualShaderNodeVectorFunc::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeVectorFunc::PortType VisualShaderNodeVectorFunc::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorFunc::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -1675,9 +1729,11 @@ String VisualShaderNodeDotProduct::get_caption() const {
int VisualShaderNodeDotProduct::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeDotProduct::PortType VisualShaderNodeDotProduct::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeDotProduct::get_input_port_name(int p_port) const {
return p_port == 0 ? "a" : "b";
}
@@ -1685,9 +1741,11 @@ String VisualShaderNodeDotProduct::get_input_port_name(int p_port) const {
int VisualShaderNodeDotProduct::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeDotProduct::PortType VisualShaderNodeDotProduct::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeDotProduct::get_output_port_name(int p_port) const {
return "dot";
}
@@ -1710,9 +1768,11 @@ String VisualShaderNodeVectorLen::get_caption() const {
int VisualShaderNodeVectorLen::get_input_port_count() const {
return 1;
}
+
VisualShaderNodeVectorLen::PortType VisualShaderNodeVectorLen::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorLen::get_input_port_name(int p_port) const {
return "";
}
@@ -1720,9 +1780,11 @@ String VisualShaderNodeVectorLen::get_input_port_name(int p_port) const {
int VisualShaderNodeVectorLen::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeVectorLen::PortType VisualShaderNodeVectorLen::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeVectorLen::get_output_port_name(int p_port) const {
return "length";
}
@@ -1745,7 +1807,7 @@ int VisualShaderNodeDeterminant::get_input_port_count() const {
return 1;
}
-VisualShaderNodeScalarClamp::PortType VisualShaderNodeDeterminant::get_input_port_type(int p_port) const {
+VisualShaderNodeDeterminant::PortType VisualShaderNodeDeterminant::get_input_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
@@ -1872,7 +1934,7 @@ int VisualShaderNodeVectorDerivativeFunc::get_output_port_count() const {
return 1;
}
-VisualShaderNodeScalarDerivativeFunc::PortType VisualShaderNodeVectorDerivativeFunc::get_output_port_type(int p_port) const {
+VisualShaderNodeVectorDerivativeFunc::PortType VisualShaderNodeVectorDerivativeFunc::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
@@ -2078,7 +2140,7 @@ int VisualShaderNodeOuterProduct::get_input_port_count() const {
return 2;
}
-VisualShaderNodeFaceForward::PortType VisualShaderNodeOuterProduct::get_input_port_type(int p_port) const {
+VisualShaderNodeOuterProduct::PortType VisualShaderNodeOuterProduct::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
@@ -2143,7 +2205,7 @@ int VisualShaderNodeVectorScalarStep::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorClamp::PortType VisualShaderNodeVectorScalarStep::get_output_port_type(int p_port) const {
+VisualShaderNodeVectorScalarStep::PortType VisualShaderNodeVectorScalarStep::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
@@ -2234,7 +2296,7 @@ int VisualShaderNodeVectorSmoothStep::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorClamp::PortType VisualShaderNodeVectorSmoothStep::get_output_port_type(int p_port) const {
+VisualShaderNodeVectorSmoothStep::PortType VisualShaderNodeVectorSmoothStep::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
@@ -2285,7 +2347,7 @@ int VisualShaderNodeVectorScalarSmoothStep::get_output_port_count() const {
return 1;
}
-VisualShaderNodeVectorClamp::PortType VisualShaderNodeVectorScalarSmoothStep::get_output_port_type(int p_port) const {
+VisualShaderNodeVectorScalarSmoothStep::PortType VisualShaderNodeVectorScalarSmoothStep::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
@@ -2540,6 +2602,7 @@ VisualShaderNodeVectorScalarMix::VisualShaderNodeVectorScalarMix() {
}
////////////// Vector Compose
+
String VisualShaderNodeVectorCompose::get_caption() const {
return "VectorCompose";
}
@@ -2547,9 +2610,11 @@ String VisualShaderNodeVectorCompose::get_caption() const {
int VisualShaderNodeVectorCompose::get_input_port_count() const {
return 3;
}
+
VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeVectorCompose::get_input_port_name(int p_port) const {
if (p_port == 0) {
return "x";
@@ -2563,9 +2628,11 @@ String VisualShaderNodeVectorCompose::get_input_port_name(int p_port) const {
int VisualShaderNodeVectorCompose::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeVectorCompose::PortType VisualShaderNodeVectorCompose::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorCompose::get_output_port_name(int p_port) const {
return "vec";
}
@@ -2590,9 +2657,11 @@ String VisualShaderNodeTransformCompose::get_caption() const {
int VisualShaderNodeTransformCompose::get_input_port_count() const {
return 4;
}
+
VisualShaderNodeTransformCompose::PortType VisualShaderNodeTransformCompose::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeTransformCompose::get_input_port_name(int p_port) const {
if (p_port == 0) {
return "x";
@@ -2608,9 +2677,11 @@ String VisualShaderNodeTransformCompose::get_input_port_name(int p_port) const {
int VisualShaderNodeTransformCompose::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeTransformCompose::PortType VisualShaderNodeTransformCompose::get_output_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
+
String VisualShaderNodeTransformCompose::get_output_port_name(int p_port) const {
return "xform";
}
@@ -2635,9 +2706,11 @@ String VisualShaderNodeVectorDecompose::get_caption() const {
int VisualShaderNodeVectorDecompose::get_input_port_count() const {
return 1;
}
+
VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVectorDecompose::get_input_port_name(int p_port) const {
return "vec";
}
@@ -2645,9 +2718,11 @@ String VisualShaderNodeVectorDecompose::get_input_port_name(int p_port) const {
int VisualShaderNodeVectorDecompose::get_output_port_count() const {
return 3;
}
+
VisualShaderNodeVectorDecompose::PortType VisualShaderNodeVectorDecompose::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeVectorDecompose::get_output_port_name(int p_port) const {
if (p_port == 0) {
return "x";
@@ -2679,9 +2754,11 @@ String VisualShaderNodeTransformDecompose::get_caption() const {
int VisualShaderNodeTransformDecompose::get_input_port_count() const {
return 1;
}
+
VisualShaderNodeTransformDecompose::PortType VisualShaderNodeTransformDecompose::get_input_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
+
String VisualShaderNodeTransformDecompose::get_input_port_name(int p_port) const {
return "xform";
}
@@ -2689,9 +2766,11 @@ String VisualShaderNodeTransformDecompose::get_input_port_name(int p_port) const
int VisualShaderNodeTransformDecompose::get_output_port_count() const {
return 4;
}
+
VisualShaderNodeTransformDecompose::PortType VisualShaderNodeTransformDecompose::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeTransformDecompose::get_output_port_name(int p_port) const {
if (p_port == 0) {
return "x";
@@ -2726,9 +2805,11 @@ String VisualShaderNodeScalarUniform::get_caption() const {
int VisualShaderNodeScalarUniform::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeScalarUniform::PortType VisualShaderNodeScalarUniform::get_input_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarUniform::get_input_port_name(int p_port) const {
return String();
}
@@ -2736,9 +2817,11 @@ String VisualShaderNodeScalarUniform::get_input_port_name(int p_port) const {
int VisualShaderNodeScalarUniform::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeScalarUniform::PortType VisualShaderNodeScalarUniform::get_output_port_type(int p_port) const {
return PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeScalarUniform::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
@@ -2746,6 +2829,7 @@ String VisualShaderNodeScalarUniform::get_output_port_name(int p_port) const {
String VisualShaderNodeScalarUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return "uniform float " + get_uniform_name() + ";\n";
}
+
String VisualShaderNodeScalarUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
}
@@ -2803,9 +2887,11 @@ String VisualShaderNodeColorUniform::get_caption() const {
int VisualShaderNodeColorUniform::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeColorUniform::PortType VisualShaderNodeColorUniform::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeColorUniform::get_input_port_name(int p_port) const {
return String();
}
@@ -2813,9 +2899,11 @@ String VisualShaderNodeColorUniform::get_input_port_name(int p_port) const {
int VisualShaderNodeColorUniform::get_output_port_count() const {
return 2;
}
+
VisualShaderNodeColorUniform::PortType VisualShaderNodeColorUniform::get_output_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeColorUniform::get_output_port_name(int p_port) const {
return p_port == 0 ? "color" : "alpha"; //no output port means the editor will be used as port
}
@@ -2843,9 +2931,11 @@ String VisualShaderNodeVec3Uniform::get_caption() const {
int VisualShaderNodeVec3Uniform::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeVec3Uniform::PortType VisualShaderNodeVec3Uniform::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVec3Uniform::get_input_port_name(int p_port) const {
return String();
}
@@ -2853,12 +2943,15 @@ String VisualShaderNodeVec3Uniform::get_input_port_name(int p_port) const {
int VisualShaderNodeVec3Uniform::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeVec3Uniform::PortType VisualShaderNodeVec3Uniform::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeVec3Uniform::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
+
String VisualShaderNodeVec3Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return "uniform vec3 " + get_uniform_name() + ";\n";
}
@@ -2879,9 +2972,11 @@ String VisualShaderNodeTransformUniform::get_caption() const {
int VisualShaderNodeTransformUniform::get_input_port_count() const {
return 0;
}
+
VisualShaderNodeTransformUniform::PortType VisualShaderNodeTransformUniform::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
+
String VisualShaderNodeTransformUniform::get_input_port_name(int p_port) const {
return String();
}
@@ -2889,12 +2984,15 @@ String VisualShaderNodeTransformUniform::get_input_port_name(int p_port) const {
int VisualShaderNodeTransformUniform::get_output_port_count() const {
return 1;
}
+
VisualShaderNodeTransformUniform::PortType VisualShaderNodeTransformUniform::get_output_port_type(int p_port) const {
return PORT_TYPE_TRANSFORM;
}
+
String VisualShaderNodeTransformUniform::get_output_port_name(int p_port) const {
return ""; //no output port means the editor will be used as port
}
+
String VisualShaderNodeTransformUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return "uniform mat4 " + get_uniform_name() + ";\n";
}
@@ -2915,9 +3013,11 @@ String VisualShaderNodeTextureUniform::get_caption() const {
int VisualShaderNodeTextureUniform::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_input_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const {
return p_port == 0 ? "uv" : "lod";
}
@@ -2925,9 +3025,11 @@ String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const {
int VisualShaderNodeTextureUniform::get_output_port_count() const {
return 2;
}
+
VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_output_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
@@ -2989,6 +3091,7 @@ void VisualShaderNodeTextureUniform::set_color_default(ColorDefault p_default) {
color_default = p_default;
emit_changed();
}
+
VisualShaderNodeTextureUniform::ColorDefault VisualShaderNodeTextureUniform::get_color_default() const {
return color_default;
}
@@ -3125,9 +3228,11 @@ String VisualShaderNodeCubeMapUniform::get_caption() const {
int VisualShaderNodeCubeMapUniform::get_input_port_count() const {
return 2;
}
+
VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_input_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeCubeMapUniform::get_input_port_name(int p_port) const {
return p_port == 0 ? "normal" : "lod";
}
@@ -3135,9 +3240,11 @@ String VisualShaderNodeCubeMapUniform::get_input_port_name(int p_port) const {
int VisualShaderNodeCubeMapUniform::get_output_port_count() const {
return 2;
}
+
VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_output_port_type(int p_port) const {
return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
}
+
String VisualShaderNodeCubeMapUniform::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
diff --git a/servers/camera_server.h b/servers/camera_server.h
index 5a62af3d60..c76d046e58 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -81,7 +81,7 @@ public:
void remove_feed(const Ref<CameraFeed> &p_feed);
// get our feeds
- Ref<CameraFeed> get_feed(int p_idx);
+ Ref<CameraFeed> get_feed(int p_index);
int get_feed_count();
Array get_feeds();
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 31b468b50b..9aaebefd80 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -357,7 +357,6 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
- virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform) = 0;
/* Light API */
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 4bc65a8f4f..1b9c3e2eff 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -924,6 +924,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
if (r_data_type) {
*r_data_type = shader->varyings[p_identifier].type;
}
+ if (r_array_size) {
+ *r_array_size = shader->varyings[p_identifier].array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_VARYING;
}
@@ -2759,6 +2762,12 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
return false;
}
+ if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
+ if (r_message)
+ *r_message = RTR("Varyings can only be assigned in vertex function.");
+ return false;
+ }
+
return true;
}
@@ -4695,7 +4704,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
- _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 allowed.");
+ _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed.");
return ERR_PARSE_ERROR;
}
@@ -4877,13 +4886,36 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
varying.type = type;
varying.precision = precision;
varying.interpolation = interpolation;
- shader->varyings[name] = varying;
tk = _get_token();
- if (tk.type != TK_SEMICOLON) {
- _set_error("Expected ';'");
+ if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
+ _set_error("Expected ';' or '['");
return ERR_PARSE_ERROR;
}
+
+ if (tk.type == TK_BRACKET_OPEN) {
+ tk = _get_token();
+ if (tk.type == TK_INT_CONSTANT && tk.constant > 0) {
+ varying.array_size = (int)tk.constant;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_error("Expected ';'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+ shader->varyings[name] = varying;
}
} break;
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 6753456323..3a5630ef42 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -519,11 +519,13 @@ public:
DataType type;
DataInterpolation interpolation;
DataPrecision precision;
+ int array_size;
Varying() :
type(TYPE_VOID),
interpolation(INTERPOLATION_FLAT),
- precision(PRECISION_DEFAULT) {}
+ precision(PRECISION_DEFAULT),
+ array_size(0) {}
};
struct Uniform {
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 75910ff1c0..019f477362 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -235,6 +235,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VEC"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_VEC"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_HEIGHT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_UV"] = constt(ShaderLanguage::TYPE_VEC2);
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index dcfbd28dd6..0df228457e 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -294,7 +294,6 @@ public:
BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &)
- BIND3(skeleton_set_world_transform, RID, bool, const Transform &)
/* Light API */
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index 0863d5c2e3..f515af4d91 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -461,7 +461,7 @@ void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport,
VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
viewport->viewport_render_direct_to_screen = p_enable;
- // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unneccesary buffer allocation
+ // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (VSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
VSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 41993d7c88..273cf728c1 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -230,7 +230,6 @@ public:
FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
- FUNC3(skeleton_set_world_transform, RID, bool, const Transform &)
/* Light API */
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 1b0164e5ca..5e6c4d9b1e 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -391,7 +391,6 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
- virtual void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_base_transform) = 0;
/* Light API */
diff --git a/thirdparty/assimp/code/FBX/FBXConverter.cpp b/thirdparty/assimp/code/FBX/FBXConverter.cpp
index 9bd970098e..3f64016ea4 100644
--- a/thirdparty/assimp/code/FBX/FBXConverter.cpp
+++ b/thirdparty/assimp/code/FBX/FBXConverter.cpp
@@ -78,7 +78,7 @@ namespace Assimp {
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
- FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit )
+ FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones )
: defaultMaterialIndex()
, lights()
, cameras()
@@ -90,8 +90,7 @@ namespace Assimp {
, mNodeNames()
, anim_fps()
, out(out)
- , doc(doc)
- , mCurrentUnit(FbxUnit::cm) {
+ , doc(doc) {
// animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed
// to determine which nodes need to be generated.
@@ -2002,6 +2001,21 @@ namespace Assimp {
TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh);
TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh);
TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
+
+ // Maya PBR
+ TrySetTextureProperties(out_mat, textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+
+ // Maya stingray
+ TrySetTextureProperties(out_mat, textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+ TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh);
}
void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
@@ -3589,9 +3603,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
}
// ------------------------------------------------------------------------------------------------
- void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit)
+ void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones)
{
- FBXConverter converter(out, doc, removeEmptyBones, unit);
+ FBXConverter converter(out, doc, removeEmptyBones);
}
} // !FBX
diff --git a/thirdparty/assimp/code/FBX/FBXConverter.h b/thirdparty/assimp/code/FBX/FBXConverter.h
index b458627392..ab610058a4 100644
--- a/thirdparty/assimp/code/FBX/FBXConverter.h
+++ b/thirdparty/assimp/code/FBX/FBXConverter.h
@@ -92,7 +92,7 @@ enum class FbxUnit {
* @param doc Parsed FBX document
* @param removeEmptyBones Will remove bones, which do not have any references to vertices.
*/
-void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
+void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones);
/** Dummy class to encapsulate the conversion process */
class FBXConverter {
@@ -123,7 +123,7 @@ public:
};
public:
- FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
+ FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones);
~FBXConverter();
private:
diff --git a/thirdparty/assimp/code/FBX/FBXImporter.cpp b/thirdparty/assimp/code/FBX/FBXImporter.cpp
index bd359dbf29..271935a568 100644
--- a/thirdparty/assimp/code/FBX/FBXImporter.cpp
+++ b/thirdparty/assimp/code/FBX/FBXImporter.cpp
@@ -191,7 +191,7 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
}
// convert the FBX DOM to aiScene
- ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones, unit);
+ ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
// size relative to cm
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
diff --git a/thirdparty/assimp/include/assimp/material.h b/thirdparty/assimp/include/assimp/material.h
index 4b5a1293dd..206eb2a2b0 100644
--- a/thirdparty/assimp/include/assimp/material.h
+++ b/thirdparty/assimp/include/assimp/material.h
@@ -196,34 +196,40 @@ enum aiTextureType
* (#aiMaterialProperty::mSemantic) for all material properties
* *not* related to textures.
*/
- aiTextureType_NONE = 0x0,
+ aiTextureType_NONE = 0,
+
+ /** LEGACY API MATERIALS
+ * Legacy refers to materials which
+ * Were originally implemented in the specifications around 2000.
+ * These must never be removed, as most engines support them.
+ */
/** The texture is combined with the result of the diffuse
* lighting equation.
*/
- aiTextureType_DIFFUSE = 0x1,
+ aiTextureType_DIFFUSE = 1,
/** The texture is combined with the result of the specular
* lighting equation.
*/
- aiTextureType_SPECULAR = 0x2,
+ aiTextureType_SPECULAR = 2,
/** The texture is combined with the result of the ambient
* lighting equation.
*/
- aiTextureType_AMBIENT = 0x3,
+ aiTextureType_AMBIENT = 3,
/** The texture is added to the result of the lighting
* calculation. It isn't influenced by incoming light.
*/
- aiTextureType_EMISSIVE = 0x4,
+ aiTextureType_EMISSIVE = 4,
/** The texture is a height map.
*
* By convention, higher gray-scale values stand for
* higher elevations from the base height.
*/
- aiTextureType_HEIGHT = 0x5,
+ aiTextureType_HEIGHT = 5,
/** The texture is a (tangent space) normal-map.
*
@@ -231,7 +237,7 @@ enum aiTextureType
* normal maps. Assimp does (intentionally) not
* distinguish here.
*/
- aiTextureType_NORMALS = 0x6,
+ aiTextureType_NORMALS = 6,
/** The texture defines the glossiness of the material.
*
@@ -240,21 +246,21 @@ enum aiTextureType
* function defined to map the linear color values in the
* texture to a suitable exponent. Have fun.
*/
- aiTextureType_SHININESS = 0x7,
+ aiTextureType_SHININESS = 7,
/** The texture defines per-pixel opacity.
*
* Usually 'white' means opaque and 'black' means
* 'transparency'. Or quite the opposite. Have fun.
*/
- aiTextureType_OPACITY = 0x8,
+ aiTextureType_OPACITY = 8,
/** Displacement texture
*
* The exact purpose and format is application-dependent.
* Higher color values stand for higher vertex displacements.
*/
- aiTextureType_DISPLACEMENT = 0x9,
+ aiTextureType_DISPLACEMENT = 9,
/** Lightmap texture (aka Ambient Occlusion)
*
@@ -263,14 +269,28 @@ enum aiTextureType
* scaling value for the final color value of a pixel. Its
* intensity is not affected by incoming light.
*/
- aiTextureType_LIGHTMAP = 0xA,
+ aiTextureType_LIGHTMAP = 10,
/** Reflection texture
*
* Contains the color of a perfect mirror reflection.
* Rarely used, almost never for real-time applications.
*/
- aiTextureType_REFLECTION = 0xB,
+ aiTextureType_REFLECTION = 11,
+
+ /** PBR Materials
+ * PBR definitions from maya and other modelling packages now use this standard.
+ * This was originally introduced around 2012.
+ * Support for this is in game engines like Godot, Unreal or Unity3D.
+ * Modelling packages which use this are very common now.
+ */
+
+ aiTextureType_BASE_COLOR = 12,
+ aiTextureType_NORMAL_CAMERA = 13,
+ aiTextureType_EMISSION_COLOR = 14,
+ aiTextureType_METALNESS = 15,
+ aiTextureType_DIFFUSE_ROUGHNESS = 16,
+ aiTextureType_AMBIENT_OCCLUSION = 17,
/** Unknown texture
*
@@ -278,7 +298,7 @@ enum aiTextureType
* above is considered to be 'unknown'. It is still imported,
* but is excluded from any further post-processing.
*/
- aiTextureType_UNKNOWN = 0xC,
+ aiTextureType_UNKNOWN = 18,
#ifndef SWIG