diff options
59 files changed, 107 insertions, 3599 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 000b628ba7..99c68eb433 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -298,6 +298,10 @@ Error _OS::set_thread_name(const String &p_name) { return Thread::set_name(p_name); } +Thread::ID _OS::get_thread_caller_id() const { + return Thread::get_caller_id(); +}; + bool _OS::has_feature(const String &p_feature) const { return OS::get_singleton()->has_feature(p_feature); } @@ -764,6 +768,7 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap", "enabled"), &_OS::set_use_file_access_save_and_swap); ClassDB::bind_method(D_METHOD("set_thread_name", "name"), &_OS::set_thread_name); + ClassDB::bind_method(D_METHOD("get_thread_caller_id"), &_OS::get_thread_caller_id); ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature); diff --git a/core/core_bind.h b/core/core_bind.h index 665858cd26..0fe5d9c80c 100644 --- a/core/core_bind.h +++ b/core/core_bind.h @@ -232,6 +232,7 @@ public: String get_user_data_dir() const; Error set_thread_name(const String &p_name); + Thread::ID get_thread_caller_id() const; bool has_feature(const String &p_feature) const; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index 21336a99ec..6b6d0a8ab4 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -3074,11 +3074,16 @@ int String::rfindn(const String &p_str, int p_from) const { } bool String::ends_with(const String &p_string) const { + int l = p_string.length(); + if (l == 0) { + return true; + } + int pos = rfind(p_string); if (pos == -1) { return false; } - return pos + p_string.length() == length(); + return pos + l == length(); } bool String::begins_with(const String &p_string) const { diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 909380b3b2..de3d89ee0f 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -313,7 +313,8 @@ <return type="int"> </return> <description> - Returns a hashed integer value representing the array contents. + Returns a hashed integer value representing the array and its contents. + [b]Note:[/b] Arrays with equal contents can still produce different hashes. Only the exact same arrays will produce the same hashed integer value. </description> </method> <method name="insert"> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index ed94f9d90f..e209fc9ad9 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -136,6 +136,14 @@ Returns the keycode of the given string (e.g. "Escape"). </description> </method> + <method name="get_thread_caller_id" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the ID of the current thread. This can be used in logs to ease debugging of multi-threaded applications. + [b]Note:[/b] Thread IDs are not deterministic and may be reused across application restarts. + </description> + </method> <method name="get_cmdline_args"> <return type="PackedStringArray"> </return> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index c500052592..2b918b9db8 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -5,6 +5,7 @@ </brief_description> <description> Node for 2D tile-based maps. Tilemaps use a [TileSet] which contain a list of tiles (textures plus optional collision, navigation, and/or occluder shapes) which are used to create grid-based maps. + When doing physics queries against the tilemap, the cell coordinates are encoded as [code]metadata[/code] for each detected collision shape returned by methods such as [method PhysicsDirectSpaceState2D.intersect_shape], [method PhysicsDirectBodyState2D.get_contact_collider_shape_metadata] etc. </description> <tutorials> <link title="Using Tilemaps">https://docs.godotengine.org/en/latest/tutorials/2d/using_tilemaps.html</link> diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml index 80f97c3419..b2ab356b0d 100644 --- a/doc/classes/VideoPlayer.xml +++ b/doc/classes/VideoPlayer.xml @@ -7,6 +7,7 @@ Control node for playing video streams using [VideoStream] resources. Supported video formats are [url=https://www.webmproject.org/]WebM[/url] ([code].webm[/code], [VideoStreamWebm]), [url=https://www.theora.org/]Ogg Theora[/url] ([code].ogv[/code], [VideoStreamTheora]), and any format exposed via a GDNative plugin using [VideoStreamGDNative]. [b]Note:[/b] Due to a bug, VideoPlayer does not support localization remapping yet. + [b]Warning:[/b] On HTML5, video playback [i]will[/i] perform poorly due to missing architecture-specific assembly optimizations, especially for VP8/VP9. </description> <tutorials> </tutorials> diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e8cf081320..e1c66f43b9 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -76,6 +76,9 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory subdirectory_item->set_metadata(0, lpath); if (!p_select_in_favorites && (path == lpath || ((display_mode == DISPLAY_MODE_SPLIT) && path.get_base_dir() == lpath))) { subdirectory_item->select(0); + // Keep select an item when re-created a tree + // To prevent crashing when nothing is selected. + subdirectory_item->set_as_cursor(0); } if (p_unfold_path && path.begins_with(lpath) && path != lpath) { @@ -1407,10 +1410,16 @@ void FileSystemDock::_make_scene_confirm() { void FileSystemDock::_file_removed(String p_file) { emit_signal("file_removed", p_file); + + path = "res://"; + current_path->set_text(path); } void FileSystemDock::_folder_removed(String p_folder) { emit_signal("folder_removed", p_folder); + + path = "res://"; + current_path->set_text(path); } void FileSystemDock::_rename_operation_confirm() { @@ -1465,6 +1474,9 @@ void FileSystemDock::_rename_operation_confirm() { print_verbose("FileSystem: saving moved scenes."); _save_scenes_after_move(file_renames); + + path = new_path; + current_path->set_text(path); } void FileSystemDock::_duplicate_operation_confirm() { @@ -1573,6 +1585,9 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path, bool p_ove print_verbose("FileSystem: saving moved scenes."); _save_scenes_after_move(file_renames); + + path = "res://"; + current_path->set_text(path); } } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index b2d143c416..7c39175049 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -1364,10 +1364,18 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { search_hb2->add_child(memnew(Label(TTR("Site:") + " "))); repository = memnew(OptionButton); - repository->add_item("godotengine.org"); - repository->set_item_metadata(0, "https://godotengine.org/asset-library/api"); - repository->add_item("localhost"); - repository->set_item_metadata(1, "http://127.0.0.1/asset-library/api"); + { + Dictionary default_urls; + default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api"; + default_urls["localhost"] = "http://127.0.0.1/asset-library/api"; + Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true); + Array keys = available_urls.keys(); + for (int i = 0; i < available_urls.size(); i++) { + String key = keys[i]; + repository->add_item(key); + repository->set_item_metadata(i, available_urls[key]); + } + } repository->connect("item_selected", callable_mp(this, &EditorAssetLibrary::_repository_changed)); diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format index 4e1fbdeb20..6467efe22e 100755 --- a/misc/hooks/pre-commit-clang-format +++ b/misc/hooks/pre-commit-clang-format @@ -74,25 +74,39 @@ else against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi +# To get consistent formatting, we recommend contributors to use the same +# clang-format version as CI. +RECOMMENDED_CLANG_FORMAT_MAJOR="11" + if [ ! -x "$CLANG_FORMAT" ] ; then + message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x." + if [ ! -t 1 ] ; then if [ -x "$ZENITY" ] ; then - $ZENITY --error --title="Error" --text="Error: clang-format executable not found." + $ZENITY --error --title="Error" --text="$message" exit 1 elif [ -x "$XMSG" ] ; then - $XMSG -center -title "Error" "Error: clang-format executable not found." + $XMSG -center -title "Error" "$message" exit 1 elif [ \( \( "$OSTYPE" = "msys" \) -o \( "$OSTYPE" = "win32" \) \) -a \( -x "$PWSH" \) ]; then winmessage="$(canonicalize_filename "./.git/hooks/winmessage.ps1")" - $PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "Error: clang-format executable not found." + $PWSH -noprofile -executionpolicy bypass -file "$winmessage" -center -title "Error" --text "$message" exit 1 fi fi - printf "Error: clang-format executable not found.\n" + printf "$message\n" printf "Set the correct path in $(canonicalize_filename "$0").\n" exit 1 fi +CLANG_FORMAT_VERSION="$(clang-format --version | cut -d' ' -f3)" +CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d'.' -f1)" + +if [ "$CLANG_FORMAT_MAJOR" != "$RECOMMENDED_CLANG_FORMAT_MAJOR" ]; then + echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected $CLANG_FORMAT_MAJOR.x.x)." + echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly." +fi + # create a random filename to store our generated patch prefix="pre-commit-clang-format" suffix="$(date +%s)" diff --git a/modules/SCsub b/modules/SCsub index 24598f4b28..64da3bd0be 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -45,18 +45,6 @@ for name, path in env.module_list.items(): else: SConscript(path + "/SCsub") # Custom. - # Some modules are not linked automatically but can be enabled optionally - # on iOS, so we handle those specially. - if env["platform"] == "iphone" and name in [ - "arkit", - "camera", - "camera_iphone", - "gamecenter", - "inappstore", - "icloud", - ]: - continue - lib = env_modules.add_library("module_%s" % name, env.modules_sources) env.Prepend(LIBS=[lib]) if env["vsproj"]: diff --git a/modules/arkit/SCsub b/modules/arkit/SCsub deleted file mode 100644 index 7e103d6565..0000000000 --- a/modules/arkit/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -Import("env") -Import("env_modules") - -env_arkit = env_modules.Clone() - -# (iOS) Enable module support -env_arkit.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - -# (iOS) Build as separate static library -modules_sources = [] -env_arkit.add_source_files(modules_sources, "*.cpp") -env_arkit.add_source_files(modules_sources, "*.mm") -mod_lib = env_modules.add_library("#bin/libgodot_arkit_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/arkit/arkit.gdip b/modules/arkit/arkit.gdip deleted file mode 100644 index 22c0a07e26..0000000000 --- a/modules/arkit/arkit.gdip +++ /dev/null @@ -1,18 +0,0 @@ -[config] -name="ARKit" -binary="arkit_lib.a" - -initialization="register_arkit_types" -deinitialization="unregister_arkit_types" - -[dependencies] -linked=[] -embedded=[] -system=["AVFoundation.framework", "ARKit.framework"] - -capabilities=["arkit"] - -files=[] - -[plist] -NSCameraUsageDescription="Device camera is used for some functionality" diff --git a/modules/arkit/arkit_interface.h b/modules/arkit/arkit_interface.h deleted file mode 100644 index f9b7709aba..0000000000 --- a/modules/arkit/arkit_interface.h +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************/ -/* arkit_interface.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 ARKIT_INTERFACE_H -#define ARKIT_INTERFACE_H - -#include "servers/camera/camera_feed.h" -#include "servers/xr/xr_interface.h" -#include "servers/xr/xr_positional_tracker.h" - -/** - @author Bastiaan Olij <mux213@gmail.com> - - ARKit interface between iPhone and Godot -*/ - -// forward declaration for some needed objects -class ARKitShader; - -#ifdef __OBJC__ - -typedef ARAnchor GodotARAnchor; - -#else - -typedef void GodotARAnchor; -#endif - -class ARKitInterface : public XRInterface { - GDCLASS(ARKitInterface, XRInterface); - -private: - bool initialized; - bool session_was_started; - bool plane_detection_is_enabled; - bool light_estimation_is_enabled; - real_t ambient_intensity; - real_t ambient_color_temperature; - - Transform transform; - CameraMatrix projection; - float eye_height, z_near, z_far; - - Ref<CameraFeed> feed; - size_t image_width[2]; - size_t image_height[2]; - Vector<uint8_t> img_data[2]; - - struct anchor_map { - XRPositionalTracker *tracker; - unsigned char uuid[16]; - }; - - ///@TODO should use memory map object from Godot? - unsigned int num_anchors; - unsigned int max_anchors; - anchor_map *anchors; - XRPositionalTracker *get_anchor_for_uuid(const unsigned char *p_uuid); - void remove_anchor_for_uuid(const unsigned char *p_uuid); - void remove_all_anchors(); - -protected: - static void _bind_methods(); - -public: - void start_session(); - void stop_session(); - - bool get_anchor_detection_is_enabled() const override; - void set_anchor_detection_is_enabled(bool p_enable) override; - virtual int get_camera_feed_id() override; - - bool get_light_estimation_is_enabled() const; - void set_light_estimation_is_enabled(bool p_enable); - - real_t get_ambient_intensity() const; - real_t get_ambient_color_temperature() const; - - /* while Godot has its own raycast logic this takes ARKits camera into account and hits on any ARAnchor */ - Array raycast(Vector2 p_screen_coord); - - virtual void notification(int p_what) override; - - virtual StringName get_name() const override; - virtual int get_capabilities() const override; - - virtual bool is_initialized() const override; - virtual bool initialize() override; - virtual void uninitialize() override; - - virtual Size2 get_render_targetsize() override; - virtual bool is_stereo() override; - virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) override; - virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) override; - virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override; - - virtual void process() override; - - // called by delegate (void * because C++ and Obj-C don't always mix, should really change all platform/iphone/*.cpp files to .mm) - void _add_or_update_anchor(GodotARAnchor *p_anchor); - void _remove_anchor(GodotARAnchor *p_anchor); - - ARKitInterface(); - ~ARKitInterface(); -}; - -#endif /* !ARKIT_INTERFACE_H */ diff --git a/modules/arkit/arkit_interface.mm b/modules/arkit/arkit_interface.mm deleted file mode 100644 index 608afd4ff3..0000000000 --- a/modules/arkit/arkit_interface.mm +++ /dev/null @@ -1,791 +0,0 @@ -/*************************************************************************/ -/* arkit_interface.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "core/input/input.h" -#include "core/os/os.h" -#include "scene/resources/surface_tool.h" -#include "servers/rendering/rendering_server_globals.h" - -#import <ARKit/ARKit.h> -#import <UIKit/UIKit.h> - -#include <dlfcn.h> - -#include "arkit_interface.h" -#include "arkit_session_delegate.h" - -// just a dirty workaround for now, declare these as globals. I'll probably encapsulate ARSession and associated logic into an mm object and change ARKitInterface to a normal cpp object that consumes it. -API_AVAILABLE(ios(11.0)) -ARSession *ar_session; - -ARKitSessionDelegate *ar_delegate; -NSTimeInterval last_timestamp; - -/* this is called when we initialize or when we come back from having our app pushed to the background, just (re)start our session */ -void ARKitInterface::start_session() { - // We're active... - session_was_started = true; - - // Ignore this if we're not initialized... - if (initialized) { - print_line("Starting ARKit session"); - - if (@available(iOS 11, *)) { - Class ARWorldTrackingConfigurationClass = NSClassFromString(@"ARWorldTrackingConfiguration"); - ARWorldTrackingConfiguration *configuration = [ARWorldTrackingConfigurationClass new]; - - configuration.lightEstimationEnabled = light_estimation_is_enabled; - if (plane_detection_is_enabled) { - if (@available(iOS 11.3, *)) { - configuration.planeDetection = ARPlaneDetectionVertical | ARPlaneDetectionHorizontal; - } else { - configuration.planeDetection = ARPlaneDetectionHorizontal; - } - } else { - configuration.planeDetection = 0; - } - - // make sure our camera is on - if (feed.is_valid()) { - feed->set_active(true); - } - - [ar_session runWithConfiguration:configuration]; - } - } -} - -void ARKitInterface::stop_session() { - session_was_started = false; - - // Ignore this if we're not initialized... - if (initialized) { - // make sure our camera is off - if (feed.is_valid()) { - feed->set_active(false); - } - - if (@available(iOS 11.0, *)) { - [ar_session pause]; - } - } -} - -void ARKitInterface::notification(int p_what) { - // TODO, this is not being called, need to find out why, possibly because this is not a node. - // in that case we need to find a way to get these notifications! - switch (p_what) { - case DisplayServer::WINDOW_EVENT_FOCUS_IN: { - print_line("Focus in"); - - start_session(); - }; break; - case DisplayServer::WINDOW_EVENT_FOCUS_OUT: { - print_line("Focus out"); - - stop_session(); - }; break; - default: - break; - } -} - -bool ARKitInterface::get_anchor_detection_is_enabled() const { - return plane_detection_is_enabled; -} - -void ARKitInterface::set_anchor_detection_is_enabled(bool p_enable) { - if (plane_detection_is_enabled != p_enable) { - plane_detection_is_enabled = p_enable; - - // Restart our session (this will be ignore if we're not initialised) - if (session_was_started) { - start_session(); - } - } -} - -int ARKitInterface::get_camera_feed_id() { - if (feed.is_null()) { - return 0; - } else { - return feed->get_id(); - } -} - -bool ARKitInterface::get_light_estimation_is_enabled() const { - return light_estimation_is_enabled; -} - -void ARKitInterface::set_light_estimation_is_enabled(bool p_enable) { - if (light_estimation_is_enabled != p_enable) { - light_estimation_is_enabled = p_enable; - - // Restart our session (this will be ignore if we're not initialised) - if (session_was_started) { - start_session(); - } - } -} - -real_t ARKitInterface::get_ambient_intensity() const { - return ambient_intensity; -} - -real_t ARKitInterface::get_ambient_color_temperature() const { - return ambient_color_temperature; -} - -StringName ARKitInterface::get_name() const { - return "ARKit"; -} - -int ARKitInterface::get_capabilities() const { - return ARKitInterface::XR_MONO + ARKitInterface::XR_AR; -} - -Array ARKitInterface::raycast(Vector2 p_screen_coord) { - if (@available(iOS 11, *)) { - Array arr; - Size2 screen_size = DisplayServer::get_singleton()->screen_get_size(); - CGPoint point; - point.x = p_screen_coord.x / screen_size.x; - point.y = p_screen_coord.y / screen_size.y; - - ///@TODO maybe give more options here, for now we're taking just ARAchors into account that were found during plane detection keeping their size into account - - NSArray<ARHitTestResult *> *results = [ar_session.currentFrame hitTest:point types:ARHitTestResultTypeExistingPlaneUsingExtent]; - - for (ARHitTestResult *result in results) { - Transform transform; - - matrix_float4x4 m44 = result.worldTransform; - transform.basis.elements[0].x = m44.columns[0][0]; - transform.basis.elements[1].x = m44.columns[0][1]; - transform.basis.elements[2].x = m44.columns[0][2]; - transform.basis.elements[0].y = m44.columns[1][0]; - transform.basis.elements[1].y = m44.columns[1][1]; - transform.basis.elements[2].y = m44.columns[1][2]; - transform.basis.elements[0].z = m44.columns[2][0]; - transform.basis.elements[1].z = m44.columns[2][1]; - transform.basis.elements[2].z = m44.columns[2][2]; - transform.origin.x = m44.columns[3][0]; - transform.origin.y = m44.columns[3][1]; - transform.origin.z = m44.columns[3][2]; - - /* important, NOT scaled to world_scale !! */ - arr.push_back(transform); - } - - return arr; - } else { - return Array(); - } -} - -void ARKitInterface::_bind_methods() { - ClassDB::bind_method(D_METHOD("_notification", "what"), &ARKitInterface::_notification); - - ClassDB::bind_method(D_METHOD("set_light_estimation_is_enabled", "enable"), &ARKitInterface::set_light_estimation_is_enabled); - ClassDB::bind_method(D_METHOD("get_light_estimation_is_enabled"), &ARKitInterface::get_light_estimation_is_enabled); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_estimation"), "set_light_estimation_is_enabled", "get_light_estimation_is_enabled"); - - ClassDB::bind_method(D_METHOD("get_ambient_intensity"), &ARKitInterface::get_ambient_intensity); - ClassDB::bind_method(D_METHOD("get_ambient_color_temperature"), &ARKitInterface::get_ambient_color_temperature); - - ClassDB::bind_method(D_METHOD("raycast", "screen_coord"), &ARKitInterface::raycast); -} - -bool ARKitInterface::is_stereo() { - // this is a mono device... - return false; -} - -bool ARKitInterface::is_initialized() const { - return initialized; -} - -bool ARKitInterface::initialize() { - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, false); - - if (@available(iOS 11, *)) { - if (!initialized) { - print_line("initializing ARKit"); - - // create our ar session and delegate - Class ARSessionClass = NSClassFromString(@"ARSession"); - if (ARSessionClass == Nil) { - void *arkit_handle = dlopen("/System/Library/Frameworks/ARKit.framework/ARKit", RTLD_NOW); - if (arkit_handle) { - ARSessionClass = NSClassFromString(@"ARSession"); - } else { - print_line("ARKit init failed"); - return false; - } - } - ar_session = [ARSessionClass new]; - ar_delegate = [ARKitSessionDelegate new]; - ar_delegate.arkit_interface = this; - ar_session.delegate = ar_delegate; - - // reset our transform - transform = Transform(); - - // make this our primary interface - xr_server->set_primary_interface(this); - - // make sure we have our feed setup - if (feed.is_null()) { - feed.instance(); - feed->set_name("ARKit"); - - CameraServer *cs = CameraServer::get_singleton(); - if (cs != NULL) { - cs->add_feed(feed); - } - } - feed->set_active(true); - - // yeah! - initialized = true; - - // Start our session... - start_session(); - } - - return true; - } else { - return false; - } -} - -void ARKitInterface::uninitialize() { - if (initialized) { - XRServer *xr_server = XRServer::get_singleton(); - if (xr_server != NULL) { - // no longer our primary interface - xr_server->clear_primary_interface_if(this); - } - - if (feed.is_valid()) { - CameraServer *cs = CameraServer::get_singleton(); - if ((cs != NULL)) { - cs->remove_feed(feed); - } - feed.unref(); - } - - remove_all_anchors(); - - if (@available(iOS 11.0, *)) { - ar_session = nil; - } - - ar_delegate = nil; - initialized = false; - session_was_started = false; - } -} - -Size2 ARKitInterface::get_render_targetsize() { - // _THREAD_SAFE_METHOD_ - - Size2 target_size = DisplayServer::get_singleton()->screen_get_size(); - - return target_size; -} - -Transform ARKitInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) { - // _THREAD_SAFE_METHOD_ - - Transform transform_for_eye; - - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, transform_for_eye); - - if (initialized) { - float world_scale = xr_server->get_world_scale(); - - // just scale our origin point of our transform, note that we really shouldn't be using world_scale in ARKit but.... - transform_for_eye = transform; - transform_for_eye.origin *= world_scale; - - transform_for_eye = p_cam_transform * xr_server->get_reference_frame() * transform_for_eye; - } else { - // huh? well just return what we got.... - transform_for_eye = p_cam_transform; - } - - return transform_for_eye; -} - -CameraMatrix ARKitInterface::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) { - // Remember our near and far, it will be used in process when we obtain our projection from our ARKit session. - z_near = p_z_near; - z_far = p_z_far; - - return projection; -} - -void ARKitInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) { - // _THREAD_SAFE_METHOD_ - - // We must have a valid render target - ERR_FAIL_COND(!p_render_target.is_valid()); - - // Because we are rendering to our device we must use our main viewport! - ERR_FAIL_COND(p_screen_rect == Rect2()); - - // get the size of our screen - // Rect2 screen_rect = p_screen_rect; - - // screen_rect.position.x += screen_rect.size.x; - // screen_rect.size.x = -screen_rect.size.x; - // screen_rect.position.y += screen_rect.size.y; - // screen_rect.size.y = -screen_rect.size.y; - - // VSG::rasterizer->set_current_render_target(RID()); - // VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0); -} - -XRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) { - if (anchors == NULL) { - num_anchors = 0; - max_anchors = 10; - anchors = (anchor_map *)malloc(sizeof(anchor_map) * max_anchors); - } - - ERR_FAIL_NULL_V(anchors, NULL); - - for (unsigned int i = 0; i < num_anchors; i++) { - if (memcmp(anchors[i].uuid, p_uuid, 16) == 0) { - return anchors[i].tracker; - } - } - - if (num_anchors + 1 == max_anchors) { - max_anchors += 10; - anchors = (anchor_map *)realloc(anchors, sizeof(anchor_map) * max_anchors); - ERR_FAIL_NULL_V(anchors, NULL); - } - - XRPositionalTracker *new_tracker = memnew(XRPositionalTracker); - new_tracker->set_tracker_type(XRServer::TRACKER_ANCHOR); - - char tracker_name[256]; - sprintf(tracker_name, "Anchor %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", p_uuid[0], p_uuid[1], p_uuid[2], p_uuid[3], p_uuid[4], p_uuid[5], p_uuid[6], p_uuid[7], p_uuid[8], p_uuid[9], p_uuid[10], p_uuid[11], p_uuid[12], p_uuid[13], p_uuid[14], p_uuid[15]); - - String name = tracker_name; - print_line("Adding tracker " + name); - new_tracker->set_tracker_name(name); - - // add our tracker - XRServer::get_singleton()->add_tracker(new_tracker); - anchors[num_anchors].tracker = new_tracker; - memcpy(anchors[num_anchors].uuid, p_uuid, 16); - num_anchors++; - - return new_tracker; -} - -void ARKitInterface::remove_anchor_for_uuid(const unsigned char *p_uuid) { - if (anchors != NULL) { - for (unsigned int i = 0; i < num_anchors; i++) { - if (memcmp(anchors[i].uuid, p_uuid, 16) == 0) { - // remove our tracker - XRServer::get_singleton()->remove_tracker(anchors[i].tracker); - memdelete(anchors[i].tracker); - - // bring remaining forward - for (unsigned int j = i + 1; j < num_anchors; j++) { - anchors[j - 1] = anchors[j]; - }; - - // decrease count - num_anchors--; - return; - } - } - } -} - -void ARKitInterface::remove_all_anchors() { - if (anchors != NULL) { - for (unsigned int i = 0; i < num_anchors; i++) { - // remove our tracker - XRServer::get_singleton()->remove_tracker(anchors[i].tracker); - memdelete(anchors[i].tracker); - }; - - free(anchors); - anchors = NULL; - num_anchors = 0; - } -} - -void ARKitInterface::process() { - // _THREAD_SAFE_METHOD_ - - if (@available(iOS 11.0, *)) { - if (initialized) { - // get our next ARFrame - ARFrame *current_frame = ar_session.currentFrame; - if (last_timestamp != current_frame.timestamp) { - // only process if we have a new frame - last_timestamp = current_frame.timestamp; - - // get some info about our screen and orientation - Size2 screen_size = DisplayServer::get_singleton()->screen_get_size(); - UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown; - - if (@available(iOS 13, *)) { - orientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - orientation = [[UIApplication sharedApplication] statusBarOrientation]; -#endif - } - - // Grab our camera image for our backbuffer - CVPixelBufferRef pixelBuffer = current_frame.capturedImage; - if ((CVPixelBufferGetPlaneCount(pixelBuffer) == 2) && (feed != NULL)) { - // Plane 0 is our Y and Plane 1 is our CbCr buffer - - // ignored, we check each plane separately - // image_width = CVPixelBufferGetWidth(pixelBuffer); - // image_height = CVPixelBufferGetHeight(pixelBuffer); - - // printf("Pixel buffer %i - %i\n", image_width, image_height); - - CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); - - // get our buffers - unsigned char *dataY = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); - unsigned char *dataCbCr = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1); - - if (dataY == NULL) { - print_line("Couldn't access Y pixel buffer data"); - } else if (dataCbCr == NULL) { - print_line("Couldn't access CbCr pixel buffer data"); - } else { - Ref<Image> img[2]; - size_t extraLeft, extraRight, extraTop, extraBottom; - - CVPixelBufferGetExtendedPixels(pixelBuffer, &extraLeft, &extraRight, &extraTop, &extraBottom); - - { - // do Y - size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0); - size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); - size_t bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); - - if ((image_width[0] != new_width) || (image_height[0] != new_height)) { - printf("- Camera padding l:%lu r:%lu t:%lu b:%lu\n", extraLeft, extraRight, extraTop, extraBottom); - printf("- Camera Y plane size: %lu, %lu - %lu\n", new_width, new_height, bytes_per_row); - - image_width[0] = new_width; - image_height[0] = new_height; - img_data[0].resize(new_width * new_height); - } - - uint8_t *w = img_data[0].ptrw(); - if (new_width == bytes_per_row) { - memcpy(w, dataY, new_width * new_height); - } else { - size_t offset_a = 0; - size_t offset_b = extraLeft + (extraTop * bytes_per_row); - for (size_t r = 0; r < new_height; r++) { - memcpy(w + offset_a, dataY + offset_b, new_width); - offset_a += new_width; - offset_b += bytes_per_row; - } - } - - img[0].instance(); - img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); - } - - { - // do CbCr - size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1); - size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); - size_t bytes_per_row = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); - - if ((image_width[1] != new_width) || (image_height[1] != new_height)) { - printf("- Camera CbCr plane size: %lu, %lu - %lu\n", new_width, new_height, bytes_per_row); - - image_width[1] = new_width; - image_height[1] = new_height; - img_data[1].resize(2 * new_width * new_height); - } - - uint8_t *w = img_data[1].ptrw(); - if ((2 * new_width) == bytes_per_row) { - memcpy(w, dataCbCr, 2 * new_width * new_height); - } else { - size_t offset_a = 0; - size_t offset_b = extraLeft + (extraTop * bytes_per_row); - for (size_t r = 0; r < new_height; r++) { - memcpy(w + offset_a, dataCbCr + offset_b, 2 * new_width); - offset_a += 2 * new_width; - offset_b += bytes_per_row; - } - } - - img[1].instance(); - img[1]->create(new_width, new_height, 0, Image::FORMAT_RG8, img_data[1]); - } - - // set our texture... - feed->set_YCbCr_imgs(img[0], img[1]); - - // now build our transform to display this as a background image that matches our camera - CGAffineTransform affine_transform = [current_frame displayTransformForOrientation:orientation viewportSize:CGSizeMake(screen_size.width, screen_size.height)]; - - // we need to invert this, probably row v.s. column notation - affine_transform = CGAffineTransformInvert(affine_transform); - - if (orientation != UIInterfaceOrientationPortrait) { - affine_transform.b = -affine_transform.b; - affine_transform.d = -affine_transform.d; - affine_transform.ty = 1.0 - affine_transform.ty; - } else { - affine_transform.c = -affine_transform.c; - affine_transform.a = -affine_transform.a; - affine_transform.tx = 1.0 - affine_transform.tx; - } - - Transform2D display_transform = Transform2D( - affine_transform.a, affine_transform.b, - affine_transform.c, affine_transform.d, - affine_transform.tx, affine_transform.ty); - - feed->set_transform(display_transform); - } - - // and unlock - CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); - } - - // Record light estimation to apply to our scene - if (light_estimation_is_enabled) { - ambient_intensity = current_frame.lightEstimate.ambientIntensity; - - ///@TODO it's there, but not there.. what to do with this... - // https://developer.apple.com/documentation/arkit/arlightestimate?language=objc - // ambient_color_temperature = current_frame.lightEstimate.ambientColorTemperature; - } - - // Process our camera - ARCamera *camera = current_frame.camera; - - // strangely enough we have to states, rolling them up into one - if (camera.trackingState == ARTrackingStateNotAvailable) { - // no tracking, would be good if we black out the screen or something... - tracking_state = XRInterface::XR_NOT_TRACKING; - } else { - if (camera.trackingState == ARTrackingStateNormal) { - tracking_state = XRInterface::XR_NORMAL_TRACKING; - } else if (camera.trackingStateReason == ARTrackingStateReasonExcessiveMotion) { - tracking_state = XRInterface::XR_EXCESSIVE_MOTION; - } else if (camera.trackingStateReason == ARTrackingStateReasonInsufficientFeatures) { - tracking_state = XRInterface::XR_INSUFFICIENT_FEATURES; - } else { - tracking_state = XRInterface::XR_UNKNOWN_TRACKING; - } - - // copy our current frame transform - matrix_float4x4 m44 = camera.transform; - if (orientation == UIInterfaceOrientationLandscapeLeft) { - transform.basis.elements[0].x = m44.columns[0][0]; - transform.basis.elements[1].x = m44.columns[0][1]; - transform.basis.elements[2].x = m44.columns[0][2]; - transform.basis.elements[0].y = m44.columns[1][0]; - transform.basis.elements[1].y = m44.columns[1][1]; - transform.basis.elements[2].y = m44.columns[1][2]; - } else if (orientation == UIInterfaceOrientationPortrait) { - transform.basis.elements[0].x = m44.columns[1][0]; - transform.basis.elements[1].x = m44.columns[1][1]; - transform.basis.elements[2].x = m44.columns[1][2]; - transform.basis.elements[0].y = -m44.columns[0][0]; - transform.basis.elements[1].y = -m44.columns[0][1]; - transform.basis.elements[2].y = -m44.columns[0][2]; - } else if (orientation == UIInterfaceOrientationLandscapeRight) { - transform.basis.elements[0].x = -m44.columns[0][0]; - transform.basis.elements[1].x = -m44.columns[0][1]; - transform.basis.elements[2].x = -m44.columns[0][2]; - transform.basis.elements[0].y = -m44.columns[1][0]; - transform.basis.elements[1].y = -m44.columns[1][1]; - transform.basis.elements[2].y = -m44.columns[1][2]; - } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { - // this may not be correct - transform.basis.elements[0].x = m44.columns[1][0]; - transform.basis.elements[1].x = m44.columns[1][1]; - transform.basis.elements[2].x = m44.columns[1][2]; - transform.basis.elements[0].y = m44.columns[0][0]; - transform.basis.elements[1].y = m44.columns[0][1]; - transform.basis.elements[2].y = m44.columns[0][2]; - } - transform.basis.elements[0].z = m44.columns[2][0]; - transform.basis.elements[1].z = m44.columns[2][1]; - transform.basis.elements[2].z = m44.columns[2][2]; - transform.origin.x = m44.columns[3][0]; - transform.origin.y = m44.columns[3][1]; - transform.origin.z = m44.columns[3][2]; - - // copy our current frame projection, investigate using projectionMatrixWithViewportSize:orientation:zNear:zFar: so we can set our own near and far - m44 = [camera projectionMatrixForOrientation:orientation viewportSize:CGSizeMake(screen_size.width, screen_size.height) zNear:z_near zFar:z_far]; - projection.matrix[0][0] = m44.columns[0][0]; - projection.matrix[1][0] = m44.columns[1][0]; - projection.matrix[2][0] = m44.columns[2][0]; - projection.matrix[3][0] = m44.columns[3][0]; - projection.matrix[0][1] = m44.columns[0][1]; - projection.matrix[1][1] = m44.columns[1][1]; - projection.matrix[2][1] = m44.columns[2][1]; - projection.matrix[3][1] = m44.columns[3][1]; - projection.matrix[0][2] = m44.columns[0][2]; - projection.matrix[1][2] = m44.columns[1][2]; - projection.matrix[2][2] = m44.columns[2][2]; - projection.matrix[3][2] = m44.columns[3][2]; - projection.matrix[0][3] = m44.columns[0][3]; - projection.matrix[1][3] = m44.columns[1][3]; - projection.matrix[2][3] = m44.columns[2][3]; - projection.matrix[3][3] = m44.columns[3][3]; - } - } - } - } -} - -void ARKitInterface::_add_or_update_anchor(GodotARAnchor *p_anchor) { - // _THREAD_SAFE_METHOD_ - - if (@available(iOS 11.0, *)) { - ARAnchor *anchor = (ARAnchor *)p_anchor; - - unsigned char uuid[16]; - [anchor.identifier getUUIDBytes:uuid]; - - XRPositionalTracker *tracker = get_anchor_for_uuid(uuid); - if (tracker != NULL) { - // lets update our mesh! (using Arjens code as is for now) - // we should also probably limit how often we do this... - - // can we safely cast this? - ARPlaneAnchor *planeAnchor = (ARPlaneAnchor *)anchor; - - if (@available(iOS 11.3, *)) { - if (planeAnchor.geometry.triangleCount > 0) { - Ref<SurfaceTool> surftool; - surftool.instance(); - surftool->begin(Mesh::PRIMITIVE_TRIANGLES); - - for (int j = planeAnchor.geometry.triangleCount * 3 - 1; j >= 0; j--) { - int16_t index = planeAnchor.geometry.triangleIndices[j]; - simd_float3 vrtx = planeAnchor.geometry.vertices[index]; - simd_float2 textcoord = planeAnchor.geometry.textureCoordinates[index]; - surftool->set_uv(Vector2(textcoord[0], textcoord[1])); - surftool->set_color(Color(0.8, 0.8, 0.8)); - surftool->add_vertex(Vector3(vrtx[0], vrtx[1], vrtx[2])); - } - - surftool->generate_normals(); - tracker->set_mesh(surftool->commit()); - } else { - Ref<Mesh> nomesh; - tracker->set_mesh(nomesh); - } - } else { - Ref<Mesh> nomesh; - tracker->set_mesh(nomesh); - } - - // Note, this also contains a scale factor which gives us an idea of the size of the anchor - // We may extract that in our XRAnchor class - Basis b; - matrix_float4x4 m44 = anchor.transform; - b.elements[0].x = m44.columns[0][0]; - b.elements[1].x = m44.columns[0][1]; - b.elements[2].x = m44.columns[0][2]; - b.elements[0].y = m44.columns[1][0]; - b.elements[1].y = m44.columns[1][1]; - b.elements[2].y = m44.columns[1][2]; - b.elements[0].z = m44.columns[2][0]; - b.elements[1].z = m44.columns[2][1]; - b.elements[2].z = m44.columns[2][2]; - tracker->set_orientation(b); - tracker->set_rw_position(Vector3(m44.columns[3][0], m44.columns[3][1], m44.columns[3][2])); - } - } -} - -void ARKitInterface::_remove_anchor(GodotARAnchor *p_anchor) { - // _THREAD_SAFE_METHOD_ - - if (@available(iOS 11.0, *)) { - ARAnchor *anchor = (ARAnchor *)p_anchor; - - unsigned char uuid[16]; - [anchor.identifier getUUIDBytes:uuid]; - - remove_anchor_for_uuid(uuid); - } -} - -ARKitInterface::ARKitInterface() { - initialized = false; - session_was_started = false; - plane_detection_is_enabled = false; - light_estimation_is_enabled = false; - if (@available(iOS 11.0, *)) { - ar_session = nil; - } - z_near = 0.01; - z_far = 1000.0; - projection.set_perspective(60.0, 1.0, z_near, z_far, false); - anchors = NULL; - num_anchors = 0; - ambient_intensity = 1.0; - ambient_color_temperature = 1.0; - image_width[0] = 0; - image_width[1] = 0; - image_height[0] = 0; - image_height[1] = 0; -} - -ARKitInterface::~ARKitInterface() { - remove_all_anchors(); - - // and make sure we cleanup if we haven't already - if (is_initialized()) { - uninitialize(); - } -} diff --git a/modules/arkit/arkit_module.cpp b/modules/arkit/arkit_module.cpp deleted file mode 100644 index be3c5e29ca..0000000000 --- a/modules/arkit/arkit_module.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* arkit_module.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "arkit_module.h" - -#include "arkit_interface.h" - -void register_arkit_types() { - // does it make sense to register the class? - - Ref<ARKitInterface> arkit_interface; - arkit_interface.instance(); - XRServer::get_singleton()->add_interface(arkit_interface); -} - -void unregister_arkit_types() { - // should clean itself up nicely :) -} diff --git a/modules/arkit/arkit_module.h b/modules/arkit/arkit_module.h deleted file mode 100644 index ca48371152..0000000000 --- a/modules/arkit/arkit_module.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************/ -/* arkit_module.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 ARKIT_REGISTER_TYPES_H -#define ARKIT_REGISTER_TYPES_H - -void register_arkit_types(); -void unregister_arkit_types(); - -#endif // ARKIT_REGISTER_TYPES_H diff --git a/modules/arkit/arkit_session_delegate.h b/modules/arkit/arkit_session_delegate.h deleted file mode 100644 index f227d50b35..0000000000 --- a/modules/arkit/arkit_session_delegate.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* arkit_session_delegate.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 ARKIT_SESSION_DELEGATE_H -#define ARKIT_SESSION_DELEGATE_H - -#import <ARKit/ARKit.h> -#import <UIKit/UIKit.h> - -class ARKitInterface; - -@interface ARKitSessionDelegate : NSObject <ARSessionDelegate> { - ARKitInterface *arkit_interface; -} - -@property(nonatomic) ARKitInterface *arkit_interface; - -- (void)session:(ARSession *)session didAddAnchors:(NSArray<ARAnchor *> *)anchors API_AVAILABLE(ios(11.0)); -- (void)session:(ARSession *)session didRemoveAnchors:(NSArray<ARAnchor *> *)anchors API_AVAILABLE(ios(11.0)); -- (void)session:(ARSession *)session didUpdateAnchors:(NSArray<ARAnchor *> *)anchors API_AVAILABLE(ios(11.0)); -@end - -#endif /* !ARKIT_SESSION_DELEGATE_H */ diff --git a/modules/arkit/arkit_session_delegate.mm b/modules/arkit/arkit_session_delegate.mm deleted file mode 100644 index 97af5bf42c..0000000000 --- a/modules/arkit/arkit_session_delegate.mm +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************/ -/* arkit_session_delegate.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "arkit_session_delegate.h" -#include "arkit_interface.h" - -@implementation ARKitSessionDelegate - -@synthesize arkit_interface; - -- (void)session:(ARSession *)session didAddAnchors:(NSArray<ARAnchor *> *)anchors { - for (ARAnchor *anchor in anchors) { - arkit_interface->_add_or_update_anchor(anchor); - } -} - -- (void)session:(ARSession *)session didRemoveAnchors:(NSArray<ARAnchor *> *)anchors { - for (ARAnchor *anchor in anchors) { - arkit_interface->_remove_anchor(anchor); - } -} - -- (void)session:(ARSession *)session didUpdateAnchors:(NSArray<ARAnchor *> *)anchors { - for (ARAnchor *anchor in anchors) { - arkit_interface->_add_or_update_anchor(anchor); - } -} - -@end diff --git a/modules/arkit/config.py b/modules/arkit/config.py deleted file mode 100644 index e68603fc93..0000000000 --- a/modules/arkit/config.py +++ /dev/null @@ -1,6 +0,0 @@ -def can_build(env, platform): - return platform == "iphone" - - -def configure(env): - pass diff --git a/modules/camera_iphone/SCsub b/modules/camera_iphone/SCsub deleted file mode 100644 index 0a37d9a6f5..0000000000 --- a/modules/camera_iphone/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -Import("env") -Import("env_modules") - -env_camera = env_modules.Clone() - -# (iOS) Enable module support -env_camera.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - -# (iOS) Build as separate static library -modules_sources = [] -env_camera.add_source_files(modules_sources, "*.cpp") -env_camera.add_source_files(modules_sources, "*.mm") -mod_lib = env_modules.add_library("#bin/libgodot_camera_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/camera_iphone/camera.gdip b/modules/camera_iphone/camera.gdip deleted file mode 100644 index 09017b8d27..0000000000 --- a/modules/camera_iphone/camera.gdip +++ /dev/null @@ -1,18 +0,0 @@ -[config] -name="Camera" -binary="camera_lib.a" - -initialization="register_camera_types" -deinitialization="unregister_camera_types" - -[dependencies] -linked=[] -embedded=[] -system=["AVFoundation.framework"] - -capabilities=[] - -files=[] - -[plist] -NSCameraUsageDescription="Device camera is used for some functionality" diff --git a/modules/camera_iphone/camera_ios.h b/modules/camera_iphone/camera_ios.h deleted file mode 100644 index 0566457a0f..0000000000 --- a/modules/camera_iphone/camera_ios.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* camera_ios.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 CAMERAIOS_H -#define CAMERAIOS_H - -#include "servers/camera_server.h" - -class CameraIOS : public CameraServer { -private: -public: - CameraIOS(); - ~CameraIOS(); - - void update_feeds(); -}; - -#endif /* CAMERAIOS_H */ diff --git a/modules/camera_iphone/camera_ios.mm b/modules/camera_iphone/camera_ios.mm deleted file mode 100644 index 39568fbd6c..0000000000 --- a/modules/camera_iphone/camera_ios.mm +++ /dev/null @@ -1,445 +0,0 @@ -/*************************************************************************/ -/* camera_ios.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -///@TODO this is a near duplicate of CameraOSX, we should find a way to combine those to minimize code duplication!!!! -// If you fix something here, make sure you fix it there as wel! - -#include "camera_ios.h" -#include "servers/camera/camera_feed.h" - -#import <AVFoundation/AVFoundation.h> -#import <UIKit/UIKit.h> - -////////////////////////////////////////////////////////////////////////// -// MyCaptureSession - This is a little helper class so we can capture our frames - -@interface MyCaptureSession : AVCaptureSession <AVCaptureVideoDataOutputSampleBufferDelegate> { - Ref<CameraFeed> feed; - size_t width[2]; - size_t height[2]; - Vector<uint8_t> img_data[2]; - - AVCaptureDeviceInput *input; - AVCaptureVideoDataOutput *output; -} - -@end - -@implementation MyCaptureSession - -- (id)initForFeed:(Ref<CameraFeed>)p_feed andDevice:(AVCaptureDevice *)p_device { - if (self = [super init]) { - NSError *error; - feed = p_feed; - width[0] = 0; - height[0] = 0; - width[1] = 0; - height[1] = 0; - - // prepare our device - [p_device lockForConfiguration:&error]; - - [p_device setFocusMode:AVCaptureFocusModeLocked]; - [p_device setExposureMode:AVCaptureExposureModeLocked]; - [p_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeLocked]; - - [p_device unlockForConfiguration]; - - [self beginConfiguration]; - - // setup our capture - self.sessionPreset = AVCaptureSessionPreset1280x720; - - input = [AVCaptureDeviceInput deviceInputWithDevice:p_device error:&error]; - if (!input) { - print_line("Couldn't get input device for camera"); - } else { - [self addInput:input]; - } - - output = [AVCaptureVideoDataOutput new]; - if (!output) { - print_line("Couldn't get output device for camera"); - } else { - NSDictionary *settings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) }; - output.videoSettings = settings; - - // discard if the data output queue is blocked (as we process the still image) - [output setAlwaysDiscardsLateVideoFrames:YES]; - - // now set ourselves as the delegate to receive new frames. Note that we're doing this on the main thread at the moment, we may need to change this.. - [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; - - [self addOutput:output]; - } - - [self commitConfiguration]; - - // kick off our session.. - [self startRunning]; - }; - return self; -} - -- (void)cleanup { - // stop running - [self stopRunning]; - - // cleanup - [self beginConfiguration]; - - if (input) { - [self removeInput:input]; - // don't release this - input = nil; - } - - if (output) { - [self removeOutput:output]; - [output setSampleBufferDelegate:nil queue:NULL]; - output = nil; - } - - [self commitConfiguration]; -} - -- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { - // This gets called every time our camera has a new image for us to process. - // May need to investigate in a way to throttle this if we get more images then we're rendering frames.. - - // For now, version 1, we're just doing the bare minimum to make this work... - - CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); - // int width = CVPixelBufferGetWidth(pixelBuffer); - // int height = CVPixelBufferGetHeight(pixelBuffer); - - // It says that we need to lock this on the documentation pages but it's not in the samples - // need to lock our base address so we can access our pixel buffers, better safe then sorry? - CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); - - // get our buffers - unsigned char *dataY = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); - unsigned char *dataCbCr = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1); - if (dataY == NULL) { - print_line("Couldn't access Y pixel buffer data"); - } else if (dataCbCr == NULL) { - print_line("Couldn't access CbCr pixel buffer data"); - } else { - UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown; - - if (@available(iOS 13, *)) { - orientation = [UIApplication sharedApplication].delegate.window.windowScene.interfaceOrientation; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - orientation = [[UIApplication sharedApplication] statusBarOrientation]; -#endif - } - - Ref<Image> img[2]; - - { - // do Y - size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0); - size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); - - if ((width[0] != new_width) || (height[0] != new_height)) { - width[0] = new_width; - height[0] = new_height; - img_data[0].resize(new_width * new_height); - } - - uint8_t *w = img_data[0].ptrw(); - memcpy(w, dataY, new_width * new_height); - - img[0].instance(); - img[0]->create(new_width, new_height, 0, Image::FORMAT_R8, img_data[0]); - } - - { - // do CbCr - size_t new_width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1); - size_t new_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); - - if ((width[1] != new_width) || (height[1] != new_height)) { - width[1] = new_width; - height[1] = new_height; - img_data[1].resize(2 * new_width * new_height); - } - - uint8_t *w = img_data[1].ptrw(); - memcpy(w, dataCbCr, 2 * new_width * new_height); - - ///TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion - img[1].instance(); - img[1]->create(new_width, new_height, 0, Image::FORMAT_RG8, img_data[1]); - } - - // set our texture... - feed->set_YCbCr_imgs(img[0], img[1]); - - // update our matrix to match the orientation, note, before changing anything - // here, be aware that the project orientation settings must match your xcode - // settings or this will go wrong! - Transform2D display_transform; - switch (orientation) { - case UIInterfaceOrientationPortrait: { - display_transform = Transform2D(0.0, -1.0, -1.0, 0.0, 1.0, 1.0); - } break; - case UIInterfaceOrientationLandscapeRight: { - display_transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0); - } break; - case UIInterfaceOrientationLandscapeLeft: { - display_transform = Transform2D(-1.0, 0.0, 0.0, 1.0, 1.0, 0.0); - } break; - default: { - display_transform = Transform2D(0.0, 1.0, 1.0, 0.0, 0.0, 0.0); - } break; - } - - //TODO: this is correct for the camera on the back, I have a feeling this needs to be inversed for the camera on the front! - feed->set_transform(display_transform); - } - - // and unlock - CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); -} - -@end - -////////////////////////////////////////////////////////////////////////// -// CameraFeedIOS - Subclass for camera feeds in iOS - -class CameraFeedIOS : public CameraFeed { -private: - AVCaptureDevice *device; - MyCaptureSession *capture_session; - -public: - bool get_is_arkit() const; - AVCaptureDevice *get_device() const; - - CameraFeedIOS(); - ~CameraFeedIOS(); - - void set_device(AVCaptureDevice *p_device); - - bool activate_feed(); - void deactivate_feed(); -}; - -AVCaptureDevice *CameraFeedIOS::get_device() const { - return device; -}; - -CameraFeedIOS::CameraFeedIOS() { - capture_session = NULL; - device = NULL; - transform = Transform2D(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); /* should re-orientate this based on device orientation */ -}; - -void CameraFeedIOS::set_device(AVCaptureDevice *p_device) { - device = p_device; - - // get some info - NSString *device_name = p_device.localizedName; - name = device_name.UTF8String; - position = CameraFeed::FEED_UNSPECIFIED; - if ([p_device position] == AVCaptureDevicePositionBack) { - position = CameraFeed::FEED_BACK; - } else if ([p_device position] == AVCaptureDevicePositionFront) { - position = CameraFeed::FEED_FRONT; - }; -}; - -CameraFeedIOS::~CameraFeedIOS() { - if (capture_session) { - capture_session = nil; - }; - - if (device) { - device = nil; - }; -}; - -bool CameraFeedIOS::activate_feed() { - if (capture_session) { - // already recording! - } else { - // start camera capture - capture_session = [[MyCaptureSession alloc] initForFeed:this andDevice:device]; - }; - - return true; -}; - -void CameraFeedIOS::deactivate_feed() { - // end camera capture if we have one - if (capture_session) { - [capture_session cleanup]; - capture_session = nil; - }; -}; - -////////////////////////////////////////////////////////////////////////// -// MyDeviceNotifications - This is a little helper class gets notifications -// when devices are connected/disconnected - -@interface MyDeviceNotifications : NSObject { - CameraIOS *camera_server; -} - -@end - -@implementation MyDeviceNotifications - -- (void)devices_changed:(NSNotification *)notification { - camera_server->update_feeds(); -} - -- (id)initForServer:(CameraIOS *)p_server { - if (self = [super init]) { - camera_server = p_server; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(devices_changed:) name:AVCaptureDeviceWasConnectedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(devices_changed:) name:AVCaptureDeviceWasDisconnectedNotification object:nil]; - }; - return self; -} - -- (void)dealloc { - // remove notifications - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceWasConnectedNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceWasDisconnectedNotification object:nil]; -} - -@end - -MyDeviceNotifications *device_notifications = nil; - -////////////////////////////////////////////////////////////////////////// -// CameraIOS - Subclass for our camera server on iPhone - -void CameraIOS::update_feeds() { - // this way of doing things is deprecated but still works, - // rewrite to using AVCaptureDeviceDiscoverySession - - NSMutableArray *deviceTypes = [NSMutableArray array]; - - if (@available(iOS 10, *)) { - [deviceTypes addObject:AVCaptureDeviceTypeBuiltInWideAngleCamera]; - [deviceTypes addObject:AVCaptureDeviceTypeBuiltInTelephotoCamera]; - - if (@available(iOS 10.2, *)) { - [deviceTypes addObject:AVCaptureDeviceTypeBuiltInDualCamera]; - } - - if (@available(iOS 11.1, *)) { - [deviceTypes addObject:AVCaptureDeviceTypeBuiltInTrueDepthCamera]; - } - - AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession - discoverySessionWithDeviceTypes:deviceTypes - mediaType:AVMediaTypeVideo - position:AVCaptureDevicePositionUnspecified]; - - // remove devices that are gone.. - for (int i = feeds.size() - 1; i >= 0; i--) { - Ref<CameraFeedIOS> feed(feeds[i]); - - if (feed.is_null()) { - // feed not managed by us - } else if (![session.devices containsObject:feed->get_device()]) { - // remove it from our array, this will also destroy it ;) - remove_feed(feed); - }; - }; - - // add new devices.. - for (AVCaptureDevice *device in session.devices) { - bool found = false; - - for (int i = 0; i < feeds.size() && !found; i++) { - Ref<CameraFeedIOS> feed(feeds[i]); - - if (feed.is_null()) { - // feed not managed by us - } else if (feed->get_device() == device) { - found = true; - }; - }; - - if (!found) { - Ref<CameraFeedIOS> newfeed; - newfeed.instance(); - newfeed->set_device(device); - add_feed(newfeed); - }; - }; - } -}; - -CameraIOS::CameraIOS() { - // check if we have our usage description - NSString *usage_desc = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSCameraUsageDescription"]; - if (usage_desc == NULL) { - // don't initialise if we don't get anything - print_line("No NSCameraUsageDescription key in pList, no access to cameras."); - return; - } else if (usage_desc.length == 0) { - // don't initialise if we don't get anything - print_line("Empty NSCameraUsageDescription key in pList, no access to cameras."); - return; - } - - // now we'll request access. - // If this is the first time the user will be prompted with the string (iOS will read it). - // Once a decision is made it is returned. If the user wants to change it later on they - // need to go into setting. - print_line("Requesting Camera permissions"); - - [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo - completionHandler:^(BOOL granted) { - if (granted) { - print_line("Access to cameras granted!"); - - // Find available cameras we have at this time - update_feeds(); - - // should only have one of these.... - device_notifications = [[MyDeviceNotifications alloc] initForServer:this]; - } else { - print_line("No access to cameras!"); - } - }]; -}; - -CameraIOS::~CameraIOS() { - device_notifications = nil; -}; diff --git a/modules/camera_iphone/camera_module.cpp b/modules/camera_iphone/camera_module.cpp deleted file mode 100644 index 7ea035892e..0000000000 --- a/modules/camera_iphone/camera_module.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* camera_module.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "camera_module.h" - -#include "camera_ios.h" - -void register_camera_types() { - CameraServer::make_default<CameraIOS>(); -} - -void unregister_camera_types() { -} diff --git a/modules/camera_iphone/camera_module.h b/modules/camera_iphone/camera_module.h deleted file mode 100644 index 5a94d8b529..0000000000 --- a/modules/camera_iphone/camera_module.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************/ -/* camera_module.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -void register_camera_types(); -void unregister_camera_types(); diff --git a/modules/camera_iphone/config.py b/modules/camera_iphone/config.py deleted file mode 100644 index e68603fc93..0000000000 --- a/modules/camera_iphone/config.py +++ /dev/null @@ -1,6 +0,0 @@ -def can_build(env, platform): - return platform == "iphone" - - -def configure(env): - pass diff --git a/modules/gamecenter/SCsub b/modules/gamecenter/SCsub deleted file mode 100644 index 72fbf7ab0e..0000000000 --- a/modules/gamecenter/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -Import("env") -Import("env_modules") - -env_gamecenter = env_modules.Clone() - -# (iOS) Enable module support -env_gamecenter.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - -# (iOS) Build as separate static library -modules_sources = [] -env_gamecenter.add_source_files(modules_sources, "*.cpp") -env_gamecenter.add_source_files(modules_sources, "*.mm") -mod_lib = env_modules.add_library("#bin/libgodot_gamecenter_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/gamecenter/config.py b/modules/gamecenter/config.py deleted file mode 100644 index e68603fc93..0000000000 --- a/modules/gamecenter/config.py +++ /dev/null @@ -1,6 +0,0 @@ -def can_build(env, platform): - return platform == "iphone" - - -def configure(env): - pass diff --git a/modules/gamecenter/game_center.h b/modules/gamecenter/game_center.h deleted file mode 100644 index 1ac00ca126..0000000000 --- a/modules/gamecenter/game_center.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************/ -/* game_center.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 GAME_CENTER_H -#define GAME_CENTER_H - -#include "core/object/class_db.h" - -class GameCenter : public Object { - GDCLASS(GameCenter, Object); - - static GameCenter *instance; - static void _bind_methods(); - - List<Variant> pending_events; - - bool authenticated; - - void return_connect_error(const char *p_error_description); - -public: - Error authenticate(); - bool is_authenticated(); - - Error post_score(Dictionary p_score); - Error award_achievement(Dictionary p_params); - void reset_achievements(); - void request_achievements(); - void request_achievement_descriptions(); - Error show_game_center(Dictionary p_params); - Error request_identity_verification_signature(); - - void game_center_closed(); - - int get_pending_event_count(); - Variant pop_pending_event(); - - static GameCenter *get_singleton(); - - GameCenter(); - ~GameCenter(); -}; - -#endif diff --git a/modules/gamecenter/game_center.mm b/modules/gamecenter/game_center.mm deleted file mode 100644 index b971bc1da3..0000000000 --- a/modules/gamecenter/game_center.mm +++ /dev/null @@ -1,380 +0,0 @@ -/*************************************************************************/ -/* game_center.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "game_center.h" -#import "platform/iphone/app_delegate.h" - -#import "game_center_delegate.h" -#import "platform/iphone/view_controller.h" -#import <GameKit/GameKit.h> - -GameCenter *GameCenter::instance = NULL; -GodotGameCenterDelegate *gameCenterDelegate = nil; - -void GameCenter::_bind_methods() { - ClassDB::bind_method(D_METHOD("authenticate"), &GameCenter::authenticate); - ClassDB::bind_method(D_METHOD("is_authenticated"), &GameCenter::is_authenticated); - - ClassDB::bind_method(D_METHOD("post_score"), &GameCenter::post_score); - ClassDB::bind_method(D_METHOD("award_achievement", "achievement"), &GameCenter::award_achievement); - ClassDB::bind_method(D_METHOD("reset_achievements"), &GameCenter::reset_achievements); - ClassDB::bind_method(D_METHOD("request_achievements"), &GameCenter::request_achievements); - ClassDB::bind_method(D_METHOD("request_achievement_descriptions"), &GameCenter::request_achievement_descriptions); - ClassDB::bind_method(D_METHOD("show_game_center"), &GameCenter::show_game_center); - ClassDB::bind_method(D_METHOD("request_identity_verification_signature"), &GameCenter::request_identity_verification_signature); - - ClassDB::bind_method(D_METHOD("get_pending_event_count"), &GameCenter::get_pending_event_count); - ClassDB::bind_method(D_METHOD("pop_pending_event"), &GameCenter::pop_pending_event); -}; - -Error GameCenter::authenticate() { - //if this class isn't available, game center isn't implemented - if ((NSClassFromString(@"GKLocalPlayer")) == nil) { - return ERR_UNAVAILABLE; - } - - GKLocalPlayer *player = [GKLocalPlayer localPlayer]; - ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); - - UIViewController *root_controller = [[UIApplication sharedApplication] delegate].window.rootViewController; - ERR_FAIL_COND_V(!root_controller, FAILED); - - // This handler is called several times. First when the view needs to be shown, then again - // after the view is cancelled or the user logs in. Or if the user's already logged in, it's - // called just once to confirm they're authenticated. This is why no result needs to be specified - // in the presentViewController phase. In this case, more calls to this function will follow. - _weakify(root_controller); - _weakify(player); - player.authenticateHandler = (^(UIViewController *controller, NSError *error) { - _strongify(root_controller); - _strongify(player); - - if (controller) { - [root_controller presentViewController:controller animated:YES completion:nil]; - } else { - Dictionary ret; - ret["type"] = "authentication"; - if (player.isAuthenticated) { - ret["result"] = "ok"; - if (@available(iOS 13, *)) { - ret["player_id"] = [player.teamPlayerID UTF8String]; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - ret["player_id"] = [player.playerID UTF8String]; -#endif - } - - GameCenter::get_singleton()->authenticated = true; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - GameCenter::get_singleton()->authenticated = false; - }; - - pending_events.push_back(ret); - }; - }); - - return OK; -}; - -bool GameCenter::is_authenticated() { - return authenticated; -}; - -Error GameCenter::post_score(Dictionary p_score) { - ERR_FAIL_COND_V(!p_score.has("score") || !p_score.has("category"), ERR_INVALID_PARAMETER); - float score = p_score["score"]; - String category = p_score["category"]; - - NSString *cat_str = [[NSString alloc] initWithUTF8String:category.utf8().get_data()]; - GKScore *reporter = [[GKScore alloc] initWithLeaderboardIdentifier:cat_str]; - reporter.value = score; - - ERR_FAIL_COND_V([GKScore respondsToSelector:@selector(reportScores)], ERR_UNAVAILABLE); - - [GKScore reportScores:@[ reporter ] - withCompletionHandler:^(NSError *error) { - Dictionary ret; - ret["type"] = "post_score"; - if (error == nil) { - ret["result"] = "ok"; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - }; - - pending_events.push_back(ret); - }]; - - return OK; -}; - -Error GameCenter::award_achievement(Dictionary p_params) { - ERR_FAIL_COND_V(!p_params.has("name") || !p_params.has("progress"), ERR_INVALID_PARAMETER); - String name = p_params["name"]; - float progress = p_params["progress"]; - - NSString *name_str = [[NSString alloc] initWithUTF8String:name.utf8().get_data()]; - GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier:name_str]; - ERR_FAIL_COND_V(!achievement, FAILED); - - ERR_FAIL_COND_V([GKAchievement respondsToSelector:@selector(reportAchievements)], ERR_UNAVAILABLE); - - achievement.percentComplete = progress; - achievement.showsCompletionBanner = NO; - if (p_params.has("show_completion_banner")) { - achievement.showsCompletionBanner = p_params["show_completion_banner"] ? YES : NO; - } - - [GKAchievement reportAchievements:@[ achievement ] - withCompletionHandler:^(NSError *error) { - Dictionary ret; - ret["type"] = "award_achievement"; - if (error == nil) { - ret["result"] = "ok"; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; - - return OK; -}; - -void GameCenter::request_achievement_descriptions() { - [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *descriptions, NSError *error) { - Dictionary ret; - ret["type"] = "achievement_descriptions"; - if (error == nil) { - ret["result"] = "ok"; - PackedStringArray names; - PackedStringArray titles; - PackedStringArray unachieved_descriptions; - PackedStringArray achieved_descriptions; - PackedInt32Array maximum_points; - Array hidden; - Array replayable; - - for (NSUInteger i = 0; i < [descriptions count]; i++) { - GKAchievementDescription *description = [descriptions objectAtIndex:i]; - - const char *str = [description.identifier UTF8String]; - names.push_back(String::utf8(str != NULL ? str : "")); - - str = [description.title UTF8String]; - titles.push_back(String::utf8(str != NULL ? str : "")); - - str = [description.unachievedDescription UTF8String]; - unachieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); - - str = [description.achievedDescription UTF8String]; - achieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); - - maximum_points.push_back(description.maximumPoints); - - hidden.push_back(description.hidden == YES); - - replayable.push_back(description.replayable == YES); - } - - ret["names"] = names; - ret["titles"] = titles; - ret["unachieved_descriptions"] = unachieved_descriptions; - ret["achieved_descriptions"] = achieved_descriptions; - ret["maximum_points"] = maximum_points; - ret["hidden"] = hidden; - ret["replayable"] = replayable; - - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; -}; - -void GameCenter::request_achievements() { - [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) { - Dictionary ret; - ret["type"] = "achievements"; - if (error == nil) { - ret["result"] = "ok"; - PackedStringArray names; - PackedFloat32Array percentages; - - for (NSUInteger i = 0; i < [achievements count]; i++) { - GKAchievement *achievement = [achievements objectAtIndex:i]; - const char *str = [achievement.identifier UTF8String]; - names.push_back(String::utf8(str != NULL ? str : "")); - - percentages.push_back(achievement.percentComplete); - } - - ret["names"] = names; - ret["progress"] = percentages; - - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; -}; - -void GameCenter::reset_achievements() { - [GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error) { - Dictionary ret; - ret["type"] = "reset_achievements"; - if (error == nil) { - ret["result"] = "ok"; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; -}; - -Error GameCenter::show_game_center(Dictionary p_params) { - ERR_FAIL_COND_V(!NSProtocolFromString(@"GKGameCenterControllerDelegate"), FAILED); - - GKGameCenterViewControllerState view_state = GKGameCenterViewControllerStateDefault; - if (p_params.has("view")) { - String view_name = p_params["view"]; - if (view_name == "default") { - view_state = GKGameCenterViewControllerStateDefault; - } else if (view_name == "leaderboards") { - view_state = GKGameCenterViewControllerStateLeaderboards; - } else if (view_name == "achievements") { - view_state = GKGameCenterViewControllerStateAchievements; - } else if (view_name == "challenges") { - view_state = GKGameCenterViewControllerStateChallenges; - } else { - return ERR_INVALID_PARAMETER; - } - } - - GKGameCenterViewController *controller = [[GKGameCenterViewController alloc] init]; - ERR_FAIL_COND_V(!controller, FAILED); - - UIViewController *root_controller = [[UIApplication sharedApplication] delegate].window.rootViewController; - ERR_FAIL_COND_V(!root_controller, FAILED); - - controller.gameCenterDelegate = gameCenterDelegate; - controller.viewState = view_state; - if (view_state == GKGameCenterViewControllerStateLeaderboards) { - controller.leaderboardIdentifier = nil; - if (p_params.has("leaderboard_name")) { - String name = p_params["leaderboard_name"]; - NSString *name_str = [[NSString alloc] initWithUTF8String:name.utf8().get_data()]; - controller.leaderboardIdentifier = name_str; - } - } - - [root_controller presentViewController:controller animated:YES completion:nil]; - - return OK; -}; - -Error GameCenter::request_identity_verification_signature() { - ERR_FAIL_COND_V(!is_authenticated(), ERR_UNAUTHORIZED); - - GKLocalPlayer *player = [GKLocalPlayer localPlayer]; - [player generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) { - Dictionary ret; - ret["type"] = "identity_verification_signature"; - if (error == nil) { - ret["result"] = "ok"; - ret["public_key_url"] = [publicKeyUrl.absoluteString UTF8String]; - ret["signature"] = [[signature base64EncodedStringWithOptions:0] UTF8String]; - ret["salt"] = [[salt base64EncodedStringWithOptions:0] UTF8String]; - ret["timestamp"] = timestamp; - if (@available(iOS 13, *)) { - ret["player_id"] = [player.teamPlayerID UTF8String]; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - ret["player_id"] = [player.playerID UTF8String]; -#endif - } - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - }; - - pending_events.push_back(ret); - }]; - - return OK; -}; - -void GameCenter::game_center_closed() { - Dictionary ret; - ret["type"] = "show_game_center"; - ret["result"] = "ok"; - pending_events.push_back(ret); -} - -int GameCenter::get_pending_event_count() { - return pending_events.size(); -}; - -Variant GameCenter::pop_pending_event() { - Variant front = pending_events.front()->get(); - pending_events.pop_front(); - - return front; -}; - -GameCenter *GameCenter::get_singleton() { - return instance; -}; - -GameCenter::GameCenter() { - ERR_FAIL_COND(instance != NULL); - instance = this; - authenticated = false; - - gameCenterDelegate = [[GodotGameCenterDelegate alloc] init]; -}; - -GameCenter::~GameCenter() { - if (gameCenterDelegate) { - gameCenterDelegate = nil; - } -} diff --git a/modules/gamecenter/game_center_delegate.h b/modules/gamecenter/game_center_delegate.h deleted file mode 100644 index ef1d2ae93d..0000000000 --- a/modules/gamecenter/game_center_delegate.h +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************/ -/* game_center_delegate.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -#import <GameKit/GameKit.h> - -@interface GodotGameCenterDelegate : NSObject <GKGameCenterControllerDelegate> - -@end diff --git a/modules/gamecenter/game_center_delegate.mm b/modules/gamecenter/game_center_delegate.mm deleted file mode 100644 index 6e20db572b..0000000000 --- a/modules/gamecenter/game_center_delegate.mm +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* game_center_delegate.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -#import "game_center_delegate.h" - -#include "game_center.h" - -@implementation GodotGameCenterDelegate - -- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController { - //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone - if (GameCenter::get_singleton()) { - GameCenter::get_singleton()->game_center_closed(); - } - [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; -} - -@end diff --git a/modules/gamecenter/game_center_module.cpp b/modules/gamecenter/game_center_module.cpp deleted file mode 100644 index 8f6ef291c0..0000000000 --- a/modules/gamecenter/game_center_module.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* game_center_module.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "game_center_module.h" - -#include "core/config/engine.h" - -#include "game_center.h" - -GameCenter *game_center; - -void register_gamecenter_types() { - game_center = memnew(GameCenter); - Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center)); -} - -void unregister_gamecenter_types() { - if (game_center) { - memdelete(game_center); - } -} diff --git a/modules/gamecenter/game_center_module.h b/modules/gamecenter/game_center_module.h deleted file mode 100644 index 5df3645b1c..0000000000 --- a/modules/gamecenter/game_center_module.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************/ -/* game_center_module.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -void register_gamecenter_types(); -void unregister_gamecenter_types(); diff --git a/modules/gamecenter/gamecenter.gdip b/modules/gamecenter/gamecenter.gdip deleted file mode 100644 index eb44effbdd..0000000000 --- a/modules/gamecenter/gamecenter.gdip +++ /dev/null @@ -1,17 +0,0 @@ -[config] -name="GameCenter" -binary="gamecenter_lib.a" - -initialization="register_gamecenter_types" -deinitialization="unregister_gamecenter_types" - -[dependencies] -linked=[] -embedded=[] -system=["GameKit.framework"] - -capabilities=["gamekit"] - -files=[] - -[plist] diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index e08961564d..944f4f052c 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1724,6 +1724,12 @@ void NativeScriptLanguage::unregister_script(NativeScript *script) { S->get().erase(script); if (S->get().size() == 0) { library_script_users.erase(S); + + Map<String, Ref<GDNative>>::Element *G = library_gdnatives.find(script->lib_path); + if (G) { + G->get()->terminate(); + library_gdnatives.erase(G); + } } } #ifndef NO_THREADS diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index b792ff54d6..ccc942d86b 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -269,19 +269,21 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) col = keywords[word]; } else if (member_keywords.has(word)) { col = member_keywords[word]; + } + + if (col != Color()) { for (int k = j - 1; k >= 0; k--) { if (str[k] == '.') { - col = Color(); //member indexing not allowed + col = Color(); // keyword & member indexing not allowed break; } else if (str[k] > 32) { break; } } - } - - if (col != Color()) { - in_keyword = true; - keyword_color = col; + if (col != Color()) { + in_keyword = true; + keyword_color = col; + } } } diff --git a/modules/icloud/SCsub b/modules/icloud/SCsub deleted file mode 100644 index 805a484600..0000000000 --- a/modules/icloud/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -Import("env") -Import("env_modules") - -env_icloud = env_modules.Clone() - -# (iOS) Enable module support -env_icloud.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - -# (iOS) Build as separate static library -modules_sources = [] -env_icloud.add_source_files(modules_sources, "*.cpp") -env_icloud.add_source_files(modules_sources, "*.mm") -mod_lib = env_modules.add_library("#bin/libgodot_icloud_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/icloud/config.py b/modules/icloud/config.py deleted file mode 100644 index e68603fc93..0000000000 --- a/modules/icloud/config.py +++ /dev/null @@ -1,6 +0,0 @@ -def can_build(env, platform): - return platform == "iphone" - - -def configure(env): - pass diff --git a/modules/icloud/icloud.gdip b/modules/icloud/icloud.gdip deleted file mode 100644 index 9f81be8a34..0000000000 --- a/modules/icloud/icloud.gdip +++ /dev/null @@ -1,17 +0,0 @@ -[config] -name="iCloud" -binary="icloud_lib.a" - -initialization="register_icloud_types" -deinitialization="unregister_icloud_types" - -[dependencies] -linked=[] -embedded=[] -system=[] - -capabilities=[] - -files=[] - -[plist] diff --git a/modules/icloud/icloud.h b/modules/icloud/icloud.h deleted file mode 100644 index 7b7aa52b63..0000000000 --- a/modules/icloud/icloud.h +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************/ -/* icloud.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 ICLOUD_H -#define ICLOUD_H - -#include "core/object/class_db.h" - -class ICloud : public Object { - GDCLASS(ICloud, Object); - - static ICloud *instance; - static void _bind_methods(); - - List<Variant> pending_events; - -public: - Error remove_key(String p_param); - Array set_key_values(Dictionary p_params); - Variant get_key_value(String p_param); - Error synchronize_key_values(); - Variant get_all_key_values(); - - int get_pending_event_count(); - Variant pop_pending_event(); - - static ICloud *get_singleton(); - - ICloud(); - ~ICloud(); -}; - -#endif diff --git a/modules/icloud/icloud.mm b/modules/icloud/icloud.mm deleted file mode 100644 index 937ef38018..0000000000 --- a/modules/icloud/icloud.mm +++ /dev/null @@ -1,345 +0,0 @@ -/*************************************************************************/ -/* icloud.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "icloud.h" - -#import "platform/iphone/app_delegate.h" - -#import <Foundation/Foundation.h> - -ICloud *ICloud::instance = NULL; - -void ICloud::_bind_methods() { - ClassDB::bind_method(D_METHOD("remove_key"), &ICloud::remove_key); - - ClassDB::bind_method(D_METHOD("set_key_values"), &ICloud::set_key_values); - ClassDB::bind_method(D_METHOD("get_key_value"), &ICloud::get_key_value); - - ClassDB::bind_method(D_METHOD("synchronize_key_values"), &ICloud::synchronize_key_values); - ClassDB::bind_method(D_METHOD("get_all_key_values"), &ICloud::get_all_key_values); - - ClassDB::bind_method(D_METHOD("get_pending_event_count"), &ICloud::get_pending_event_count); - ClassDB::bind_method(D_METHOD("pop_pending_event"), &ICloud::pop_pending_event); -}; - -int ICloud::get_pending_event_count() { - return pending_events.size(); -}; - -Variant ICloud::pop_pending_event() { - Variant front = pending_events.front()->get(); - pending_events.pop_front(); - - return front; -}; - -ICloud *ICloud::get_singleton() { - return instance; -}; - -//convert from apple's abstract type to godot's abstract type.... -Variant nsobject_to_variant(NSObject *object) { - if ([object isKindOfClass:[NSString class]]) { - const char *str = [(NSString *)object UTF8String]; - return String::utf8(str != NULL ? str : ""); - } else if ([object isKindOfClass:[NSData class]]) { - PackedByteArray ret; - NSData *data = (NSData *)object; - if ([data length] > 0) { - ret.resize([data length]); - { - // PackedByteArray::Write w = ret.write(); - copymem((void *)ret.ptr(), [data bytes], [data length]); - } - } - return ret; - } else if ([object isKindOfClass:[NSArray class]]) { - Array result; - NSArray *array = (NSArray *)object; - for (NSUInteger i = 0; i < [array count]; ++i) { - NSObject *value = [array objectAtIndex:i]; - result.push_back(nsobject_to_variant(value)); - } - return result; - } else if ([object isKindOfClass:[NSDictionary class]]) { - Dictionary result; - NSDictionary *dic = (NSDictionary *)object; - - NSArray *keys = [dic allKeys]; - int count = [keys count]; - for (int i = 0; i < count; ++i) { - NSObject *k = [keys objectAtIndex:i]; - NSObject *v = [dic objectForKey:k]; - - result[nsobject_to_variant(k)] = nsobject_to_variant(v); - } - return result; - } else if ([object isKindOfClass:[NSNumber class]]) { - //Every type except numbers can reliably identify its type. The following is comparing to the *internal* representation, which isn't guaranteed to match the type that was used to create it, and is not advised, particularly when dealing with potential platform differences (ie, 32/64 bit) - //To avoid errors, we'll cast as broadly as possible, and only return int or float. - //bool, char, int, uint, longlong -> int - //float, double -> float - NSNumber *num = (NSNumber *)object; - if (strcmp([num objCType], @encode(BOOL)) == 0) { - return Variant((int)[num boolValue]); - } else if (strcmp([num objCType], @encode(char)) == 0) { - return Variant((int)[num charValue]); - } else if (strcmp([num objCType], @encode(int)) == 0) { - return Variant([num intValue]); - } else if (strcmp([num objCType], @encode(unsigned int)) == 0) { - return Variant((int)[num unsignedIntValue]); - } else if (strcmp([num objCType], @encode(long long)) == 0) { - return Variant((int)[num longValue]); - } else if (strcmp([num objCType], @encode(float)) == 0) { - return Variant([num floatValue]); - } else if (strcmp([num objCType], @encode(double)) == 0) { - return Variant((float)[num doubleValue]); - } else { - return Variant(); - } - } else if ([object isKindOfClass:[NSDate class]]) { - //this is a type that icloud supports...but how did you submit it in the first place? - //I guess this is a type that *might* show up, if you were, say, trying to make your game - //compatible with existing cloud data written by another engine's version of your game - WARN_PRINT("NSDate unsupported, returning null Variant"); - return Variant(); - } else if ([object isKindOfClass:[NSNull class]] or object == nil) { - return Variant(); - } else { - WARN_PRINT("Trying to convert unknown NSObject type to Variant"); - return Variant(); - } -} - -NSObject *variant_to_nsobject(Variant v) { - if (v.get_type() == Variant::STRING) { - return [[NSString alloc] initWithUTF8String:((String)v).utf8().get_data()]; - } else if (v.get_type() == Variant::FLOAT) { - return [NSNumber numberWithDouble:(double)v]; - } else if (v.get_type() == Variant::INT) { - return [NSNumber numberWithLongLong:(long)(int)v]; - } else if (v.get_type() == Variant::BOOL) { - return [NSNumber numberWithBool:BOOL((bool)v)]; - } else if (v.get_type() == Variant::DICTIONARY) { - NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; - Dictionary dic = v; - Array keys = dic.keys(); - for (int i = 0; i < keys.size(); ++i) { - NSString *key = [[NSString alloc] initWithUTF8String:((String)(keys[i])).utf8().get_data()]; - NSObject *value = variant_to_nsobject(dic[keys[i]]); - - if (key == NULL || value == NULL) { - return NULL; - } - - [result setObject:value forKey:key]; - } - return result; - } else if (v.get_type() == Variant::ARRAY) { - NSMutableArray *result = [[NSMutableArray alloc] init]; - Array arr = v; - for (int i = 0; i < arr.size(); ++i) { - NSObject *value = variant_to_nsobject(arr[i]); - if (value == NULL) { - //trying to add something unsupported to the array. cancel the whole array - return NULL; - } - [result addObject:value]; - } - return result; - } else if (v.get_type() == Variant::PACKED_BYTE_ARRAY) { - PackedByteArray arr = v; - // PackedByteArray::Read r = arr.read(); - NSData *result = [NSData dataWithBytes:arr.ptr() length:arr.size()]; - return result; - } - WARN_PRINT(String("Could not add unsupported type to iCloud: '" + Variant::get_type_name(v.get_type()) + "'").utf8().get_data()); - return NULL; -} - -Error ICloud::remove_key(String p_param) { - NSString *key = [[NSString alloc] initWithUTF8String:p_param.utf8().get_data()]; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - if (![[store dictionaryRepresentation] objectForKey:key]) { - return ERR_INVALID_PARAMETER; - } - - [store removeObjectForKey:key]; - return OK; -} - -//return an array of the keys that could not be set -Array ICloud::set_key_values(Dictionary p_params) { - Array keys = p_params.keys(); - - Array error_keys; - - for (int i = 0; i < keys.size(); ++i) { - String variant_key = keys[i]; - Variant variant_value = p_params[variant_key]; - - NSString *key = [[NSString alloc] initWithUTF8String:variant_key.utf8().get_data()]; - if (key == NULL) { - error_keys.push_back(variant_key); - continue; - } - - NSObject *value = variant_to_nsobject(variant_value); - - if (value == NULL) { - error_keys.push_back(variant_key); - continue; - } - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - [store setObject:value forKey:key]; - } - - return error_keys; -} - -Variant ICloud::get_key_value(String p_param) { - NSString *key = [[NSString alloc] initWithUTF8String:p_param.utf8().get_data()]; - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - if (![[store dictionaryRepresentation] objectForKey:key]) { - return Variant(); - } - - Variant result = nsobject_to_variant([[store dictionaryRepresentation] objectForKey:key]); - - return result; -} - -Variant ICloud::get_all_key_values() { - Dictionary result; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - NSDictionary *store_dictionary = [store dictionaryRepresentation]; - - NSArray *keys = [store_dictionary allKeys]; - int count = [keys count]; - for (int i = 0; i < count; ++i) { - NSString *k = [keys objectAtIndex:i]; - NSObject *v = [store_dictionary objectForKey:k]; - - const char *str = [k UTF8String]; - if (str != NULL) { - result[String::utf8(str)] = nsobject_to_variant(v); - } - } - - return result; -} - -Error ICloud::synchronize_key_values() { - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - BOOL result = [store synchronize]; - if (result == YES) { - return OK; - } else { - return FAILED; - } -} - -/* -Error ICloud::initial_sync() { - //you sometimes have to write something to the store to get it to download new data. go apple! - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - if ([store boolForKey:@"isb"]) - { - [store setBool:NO forKey:@"isb"]; - } - else - { - [store setBool:YES forKey:@"isb"]; - } - return synchronize(); -} - -*/ -ICloud::ICloud() { - ERR_FAIL_COND(instance != NULL); - instance = this; - //connected = false; - - [[NSNotificationCenter defaultCenter] - addObserverForName:NSUbiquitousKeyValueStoreDidChangeExternallyNotification - object:[NSUbiquitousKeyValueStore defaultStore] - queue:nil - usingBlock:^(NSNotification *notification) { - NSDictionary *userInfo = [notification userInfo]; - NSInteger change = [[userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey] integerValue]; - - Dictionary ret; - ret["type"] = "key_value_changed"; - - //PackedStringArray result_keys; - //Array result_values; - Dictionary keyValues; - String reason = ""; - - if (change == NSUbiquitousKeyValueStoreServerChange) { - reason = "server"; - } else if (change == NSUbiquitousKeyValueStoreInitialSyncChange) { - reason = "initial_sync"; - } else if (change == NSUbiquitousKeyValueStoreQuotaViolationChange) { - reason = "quota_violation"; - } else if (change == NSUbiquitousKeyValueStoreAccountChange) { - reason = "account"; - } - - ret["reason"] = reason; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - NSArray *keys = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]; - for (NSString *key in keys) { - const char *str = [key UTF8String]; - if (str == NULL) { - continue; - } - - NSObject *object = [store objectForKey:key]; - - //figure out what kind of object it is - Variant value = nsobject_to_variant(object); - - keyValues[String::utf8(str)] = value; - } - - ret["changed_values"] = keyValues; - pending_events.push_back(ret); - }]; -} - -ICloud::~ICloud() {} diff --git a/modules/icloud/icloud_module.cpp b/modules/icloud/icloud_module.cpp deleted file mode 100644 index 8a2c41a38c..0000000000 --- a/modules/icloud/icloud_module.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* icloud_module.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "icloud_module.h" - -#include "core/config/engine.h" - -#include "icloud.h" - -ICloud *icloud; - -void register_icloud_types() { - icloud = memnew(ICloud); - Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud)); -} - -void unregister_icloud_types() { - if (icloud) { - memdelete(icloud); - } -} diff --git a/modules/icloud/icloud_module.h b/modules/icloud/icloud_module.h deleted file mode 100644 index fb8b5fe66e..0000000000 --- a/modules/icloud/icloud_module.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************/ -/* icloud_module.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -void register_icloud_types(); -void unregister_icloud_types(); diff --git a/modules/inappstore/SCsub b/modules/inappstore/SCsub deleted file mode 100644 index cee6a256d5..0000000000 --- a/modules/inappstore/SCsub +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -Import("env") -Import("env_modules") - -env_inappstore = env_modules.Clone() - -# (iOS) Enable module support -env_inappstore.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - -# (iOS) Build as separate static library -modules_sources = [] -env_inappstore.add_source_files(modules_sources, "*.cpp") -env_inappstore.add_source_files(modules_sources, "*.mm") -mod_lib = env_modules.add_library("#bin/libgodot_inappstore_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/inappstore/config.py b/modules/inappstore/config.py deleted file mode 100644 index e68603fc93..0000000000 --- a/modules/inappstore/config.py +++ /dev/null @@ -1,6 +0,0 @@ -def can_build(env, platform): - return platform == "iphone" - - -def configure(env): - pass diff --git a/modules/inappstore/in_app_store.h b/modules/inappstore/in_app_store.h deleted file mode 100644 index c66c306319..0000000000 --- a/modules/inappstore/in_app_store.h +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************/ -/* in_app_store.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 IN_APP_STORE_H -#define IN_APP_STORE_H - -#include "core/object/class_db.h" - -#ifdef __OBJC__ -@class GodotProductsDelegate; -@class GodotTransactionsObserver; - -typedef GodotProductsDelegate InAppStoreProductDelegate; -typedef GodotTransactionsObserver InAppStoreTransactionObserver; -#else -typedef void InAppStoreProductDelegate; -typedef void InAppStoreTransactionObserver; -#endif - -class InAppStore : public Object { - GDCLASS(InAppStore, Object); - - static InAppStore *instance; - static void _bind_methods(); - - List<Variant> pending_events; - - InAppStoreProductDelegate *products_request_delegate; - InAppStoreTransactionObserver *transactions_observer; - -public: - Error request_product_info(Dictionary p_params); - Error restore_purchases(); - Error purchase(Dictionary p_params); - - int get_pending_event_count(); - Variant pop_pending_event(); - void finish_transaction(String product_id); - void set_auto_finish_transaction(bool b); - - void _post_event(Variant p_event); - void _record_purchase(String product_id); - - static InAppStore *get_singleton(); - - InAppStore(); - ~InAppStore(); -}; - -#endif diff --git a/modules/inappstore/in_app_store.mm b/modules/inappstore/in_app_store.mm deleted file mode 100644 index 427808ae75..0000000000 --- a/modules/inappstore/in_app_store.mm +++ /dev/null @@ -1,411 +0,0 @@ -/*************************************************************************/ -/* in_app_store.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "in_app_store.h" - -#import <Foundation/Foundation.h> -#import <StoreKit/StoreKit.h> - -InAppStore *InAppStore::instance = NULL; - -@interface SKProduct (LocalizedPrice) - -@property(nonatomic, readonly) NSString *localizedPrice; - -@end - -//----------------------------------// -// SKProduct extension -//----------------------------------// -@implementation SKProduct (LocalizedPrice) - -- (NSString *)localizedPrice { - NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; - [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; - [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; - [numberFormatter setLocale:self.priceLocale]; - NSString *formattedString = [numberFormatter stringFromNumber:self.price]; - return formattedString; -} - -@end - -@interface GodotProductsDelegate : NSObject <SKProductsRequestDelegate> - -@property(nonatomic, strong) NSMutableArray *loadedProducts; -@property(nonatomic, strong) NSMutableArray *pendingRequests; - -- (void)performRequestWithProductIDs:(NSSet *)productIDs; -- (Error)purchaseProductWithProductID:(NSString *)productID; -- (void)reset; - -@end - -@implementation GodotProductsDelegate - -- (instancetype)init { - self = [super init]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - self.loadedProducts = [NSMutableArray new]; - self.pendingRequests = [NSMutableArray new]; -} - -- (void)performRequestWithProductIDs:(NSSet *)productIDs { - SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIDs]; - - request.delegate = self; - [self.pendingRequests addObject:request]; - [request start]; -} - -- (Error)purchaseProductWithProductID:(NSString *)productID { - SKProduct *product = nil; - - NSLog(@"searching for product!"); - - if (self.loadedProducts) { - for (SKProduct *storedProduct in self.loadedProducts) { - if ([storedProduct.productIdentifier isEqualToString:productID]) { - product = storedProduct; - break; - } - } - } - - if (!product) { - return ERR_INVALID_PARAMETER; - } - - NSLog(@"product found!"); - - SKPayment *payment = [SKPayment paymentWithProduct:product]; - [[SKPaymentQueue defaultQueue] addPayment:payment]; - - NSLog(@"purchase sent!"); - - return OK; -} - -- (void)reset { - [self.loadedProducts removeAllObjects]; - [self.pendingRequests removeAllObjects]; -} - -- (void)request:(SKRequest *)request didFailWithError:(NSError *)error { - [self.pendingRequests removeObject:request]; - - Dictionary ret; - ret["type"] = "product_info"; - ret["result"] = "error"; - ret["error"] = String::utf8([error.localizedDescription UTF8String]); - - InAppStore::get_singleton()->_post_event(ret); -} - -- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { - [self.pendingRequests removeObject:request]; - - NSArray *products = response.products; - [self.loadedProducts addObjectsFromArray:products]; - - Dictionary ret; - ret["type"] = "product_info"; - ret["result"] = "ok"; - PackedStringArray titles; - PackedStringArray descriptions; - PackedFloat32Array prices; - PackedStringArray ids; - PackedStringArray localized_prices; - PackedStringArray currency_codes; - - for (NSUInteger i = 0; i < [products count]; i++) { - SKProduct *product = [products objectAtIndex:i]; - - const char *str = [product.localizedTitle UTF8String]; - titles.push_back(String::utf8(str != NULL ? str : "")); - - str = [product.localizedDescription UTF8String]; - descriptions.push_back(String::utf8(str != NULL ? str : "")); - prices.push_back([product.price doubleValue]); - ids.push_back(String::utf8([product.productIdentifier UTF8String])); - localized_prices.push_back(String::utf8([product.localizedPrice UTF8String])); - currency_codes.push_back(String::utf8([[[product priceLocale] objectForKey:NSLocaleCurrencyCode] UTF8String])); - } - - ret["titles"] = titles; - ret["descriptions"] = descriptions; - ret["prices"] = prices; - ret["ids"] = ids; - ret["localized_prices"] = localized_prices; - ret["currency_codes"] = currency_codes; - - PackedStringArray invalid_ids; - - for (NSString *ipid in response.invalidProductIdentifiers) { - invalid_ids.push_back(String::utf8([ipid UTF8String])); - } - - ret["invalid_ids"] = invalid_ids; - - InAppStore::get_singleton()->_post_event(ret); -} - -@end - -@interface GodotTransactionsObserver : NSObject <SKPaymentTransactionObserver> - -@property(nonatomic, assign) BOOL shouldAutoFinishTransactions; -@property(nonatomic, strong) NSMutableDictionary *pendingTransactions; - -- (void)finishTransactionWithProductID:(NSString *)productID; -- (void)reset; - -@end - -@implementation GodotTransactionsObserver - -- (instancetype)init { - self = [super init]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - self.pendingTransactions = [NSMutableDictionary new]; -} - -- (void)finishTransactionWithProductID:(NSString *)productID { - SKPaymentTransaction *transaction = self.pendingTransactions[productID]; - - if (transaction) { - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } - - self.pendingTransactions[productID] = nil; -} - -- (void)reset { - [self.pendingTransactions removeAllObjects]; -} - -- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { - printf("transactions updated!\n"); - for (SKPaymentTransaction *transaction in transactions) { - switch (transaction.transactionState) { - case SKPaymentTransactionStatePurchased: { - printf("status purchased!\n"); - String pid = String::utf8([transaction.payment.productIdentifier UTF8String]); - String transactionId = String::utf8([transaction.transactionIdentifier UTF8String]); - InAppStore::get_singleton()->_record_purchase(pid); - Dictionary ret; - ret["type"] = "purchase"; - ret["result"] = "ok"; - ret["product_id"] = pid; - ret["transaction_id"] = transactionId; - - NSData *receipt = nil; - int sdk_version = [[[UIDevice currentDevice] systemVersion] intValue]; - - NSBundle *bundle = [NSBundle mainBundle]; - // Get the transaction receipt file path location in the app bundle. - NSURL *receiptFileURL = [bundle appStoreReceiptURL]; - - // Read in the contents of the transaction file. - receipt = [NSData dataWithContentsOfURL:receiptFileURL]; - - NSString *receipt_to_send = nil; - - if (receipt != nil) { - receipt_to_send = [receipt base64EncodedStringWithOptions:0]; - } - Dictionary receipt_ret; - receipt_ret["receipt"] = String::utf8(receipt_to_send != nil ? [receipt_to_send UTF8String] : ""); - receipt_ret["sdk"] = sdk_version; - ret["receipt"] = receipt_ret; - - InAppStore::get_singleton()->_post_event(ret); - - if (self.shouldAutoFinishTransactions) { - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } else { - self.pendingTransactions[transaction.payment.productIdentifier] = transaction; - } - - } break; - case SKPaymentTransactionStateFailed: { - printf("status transaction failed!\n"); - String pid = String::utf8([transaction.payment.productIdentifier UTF8String]); - Dictionary ret; - ret["type"] = "purchase"; - ret["result"] = "error"; - ret["product_id"] = pid; - ret["error"] = String::utf8([transaction.error.localizedDescription UTF8String]); - InAppStore::get_singleton()->_post_event(ret); - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } break; - case SKPaymentTransactionStateRestored: { - printf("status transaction restored!\n"); - String pid = String::utf8([transaction.originalTransaction.payment.productIdentifier UTF8String]); - InAppStore::get_singleton()->_record_purchase(pid); - Dictionary ret; - ret["type"] = "restore"; - ret["result"] = "ok"; - ret["product_id"] = pid; - InAppStore::get_singleton()->_post_event(ret); - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } break; - default: { - printf("status default %i!\n", (int)transaction.transactionState); - } break; - } - } -} - -@end - -void InAppStore::_bind_methods() { - ClassDB::bind_method(D_METHOD("request_product_info"), &InAppStore::request_product_info); - ClassDB::bind_method(D_METHOD("restore_purchases"), &InAppStore::restore_purchases); - ClassDB::bind_method(D_METHOD("purchase"), &InAppStore::purchase); - - ClassDB::bind_method(D_METHOD("get_pending_event_count"), &InAppStore::get_pending_event_count); - ClassDB::bind_method(D_METHOD("pop_pending_event"), &InAppStore::pop_pending_event); - ClassDB::bind_method(D_METHOD("finish_transaction"), &InAppStore::finish_transaction); - ClassDB::bind_method(D_METHOD("set_auto_finish_transaction"), &InAppStore::set_auto_finish_transaction); -} - -Error InAppStore::request_product_info(Dictionary p_params) { - ERR_FAIL_COND_V(!p_params.has("product_ids"), ERR_INVALID_PARAMETER); - - PackedStringArray pids = p_params["product_ids"]; - printf("************ request product info! %i\n", pids.size()); - - NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:pids.size()]; - for (int i = 0; i < pids.size(); i++) { - printf("******** adding %s to product list\n", pids[i].utf8().get_data()); - NSString *pid = [[NSString alloc] initWithUTF8String:pids[i].utf8().get_data()]; - [array addObject:pid]; - }; - - NSSet *products = [[NSSet alloc] initWithArray:array]; - - [products_request_delegate performRequestWithProductIDs:products]; - - return OK; -} - -Error InAppStore::restore_purchases() { - printf("restoring purchases!\n"); - [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; - - return OK; -} - -Error InAppStore::purchase(Dictionary p_params) { - ERR_FAIL_COND_V(![SKPaymentQueue canMakePayments], ERR_UNAVAILABLE); - if (![SKPaymentQueue canMakePayments]) { - return ERR_UNAVAILABLE; - } - - printf("purchasing!\n"); - Dictionary params = p_params; - ERR_FAIL_COND_V(!params.has("product_id"), ERR_INVALID_PARAMETER); - - NSString *pid = [[NSString alloc] initWithUTF8String:String(params["product_id"]).utf8().get_data()]; - - return [products_request_delegate purchaseProductWithProductID:pid]; -} - -int InAppStore::get_pending_event_count() { - return pending_events.size(); -} - -Variant InAppStore::pop_pending_event() { - Variant front = pending_events.front()->get(); - pending_events.pop_front(); - - return front; -} - -void InAppStore::_post_event(Variant p_event) { - pending_events.push_back(p_event); -} - -void InAppStore::_record_purchase(String product_id) { - String skey = "purchased/" + product_id; - NSString *key = [[NSString alloc] initWithUTF8String:skey.utf8().get_data()]; - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:key]; - [[NSUserDefaults standardUserDefaults] synchronize]; -} - -InAppStore *InAppStore::get_singleton() { - return instance; -} - -InAppStore::InAppStore() { - ERR_FAIL_COND(instance != NULL); - instance = this; - - products_request_delegate = [[GodotProductsDelegate alloc] init]; - transactions_observer = [[GodotTransactionsObserver alloc] init]; - - [[SKPaymentQueue defaultQueue] addTransactionObserver:transactions_observer]; -} - -void InAppStore::finish_transaction(String product_id) { - NSString *prod_id = [NSString stringWithCString:product_id.utf8().get_data() encoding:NSUTF8StringEncoding]; - - [transactions_observer finishTransactionWithProductID:prod_id]; -} - -void InAppStore::set_auto_finish_transaction(bool b) { - transactions_observer.shouldAutoFinishTransactions = b; -} - -InAppStore::~InAppStore() { - [products_request_delegate reset]; - [transactions_observer reset]; - - products_request_delegate = nil; - [[SKPaymentQueue defaultQueue] removeTransactionObserver:transactions_observer]; - transactions_observer = nil; -} diff --git a/modules/inappstore/in_app_store_module.cpp b/modules/inappstore/in_app_store_module.cpp deleted file mode 100644 index c89735cd1c..0000000000 --- a/modules/inappstore/in_app_store_module.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* in_app_store_module.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "in_app_store_module.h" - -#include "core/config/engine.h" - -#include "in_app_store.h" - -InAppStore *store_kit; - -void register_inappstore_types() { - store_kit = memnew(InAppStore); - Engine::get_singleton()->add_singleton(Engine::Singleton("InAppStore", store_kit)); -} - -void unregister_inappstore_types() { - if (store_kit) { - memdelete(store_kit); - } -} diff --git a/modules/inappstore/in_app_store_module.h b/modules/inappstore/in_app_store_module.h deleted file mode 100644 index dc38969825..0000000000 --- a/modules/inappstore/in_app_store_module.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************/ -/* in_app_store_module.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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. */ -/*************************************************************************/ - -void register_inappstore_types(); -void unregister_inappstore_types(); diff --git a/modules/inappstore/inappstore.gdip b/modules/inappstore/inappstore.gdip deleted file mode 100644 index 7a5efb8ad3..0000000000 --- a/modules/inappstore/inappstore.gdip +++ /dev/null @@ -1,17 +0,0 @@ -[config] -name="InAppStore" -binary="inappstore_lib.a" - -initialization="register_inappstore_types" -deinitialization="unregister_inappstore_types" - -[dependencies] -linked=[] -embedded=[] -system=["StoreKit.framework"] - -capabilities=[] - -files=[] - -[plist] diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 286858bff1..359f6bba4d 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -1204,7 +1204,7 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) { MonoReflectionType *elem_reftype = nullptr; GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype); - return system_generic_list_to_Array(p_obj, p_type.type_class, elem_reftype); + return system_generic_list_to_Array_variant(p_obj, p_type.type_class, elem_reftype); } } break; } @@ -1333,15 +1333,22 @@ MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_cl return mono_object; } -Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, [[maybe_unused]] MonoReflectionType *p_elem_reftype) { +Variant system_generic_list_to_Array_variant(MonoObject *p_obj, GDMonoClass *p_class, [[maybe_unused]] MonoReflectionType *p_elem_reftype) { GDMonoMethod *to_array = p_class->get_method("ToArray", 0); CRASH_COND(to_array == nullptr); MonoException *exc = nullptr; - MonoArray *mono_array = (MonoArray *)to_array->invoke_raw(p_obj, nullptr, &exc); + MonoObject *array = to_array->invoke_raw(p_obj, nullptr, &exc); UNHANDLED_EXCEPTION(exc); - return mono_array_to_Array(mono_array); + ERR_FAIL_NULL_V(array, Variant()); + + ManagedType type = ManagedType::from_class(mono_object_get_class(array)); + + bool result_is_array = type.type_encoding != MONO_TYPE_SZARRAY && type.type_encoding != MONO_TYPE_ARRAY; + ERR_FAIL_COND_V(result_is_array, Variant()); + + return mono_object_to_variant(array, type); } MonoArray *Array_to_mono_array(const Array &p_array) { diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 7d0036a1d8..668809ae5d 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -140,7 +140,7 @@ MonoObject *Dictionary_to_system_generic_dict(const Dictionary &p_dict, GDMonoCl Dictionary system_generic_dict_to_Dictionary(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype); MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype); -Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype); +Variant system_generic_list_to_Array_variant(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype); // Array diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 7452f390da..17796beb6f 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -188,38 +188,6 @@ def configure(env): LINKFLAGS=[ "-isysroot", "$IPHONESDK", - "-framework", - "AudioToolbox", - "-framework", - "AVFoundation", - "-framework", - "CoreAudio", - "-framework", - "CoreGraphics", - "-framework", - "CoreMedia", - "-framework", - "CoreVideo", - "-framework", - "CoreMotion", - "-framework", - "Foundation", - "-framework", - "GameController", - "-framework", - "MediaPlayer", - "-framework", - "Metal", - "-framework", - "QuartzCore", - "-framework", - "Security", - "-framework", - "SystemConfiguration", - "-framework", - "UIKit", - "-framework", - "ARKit", ] ) diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 865510731e..44dd6e0e5f 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -112,7 +112,6 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) { if (mesh.is_valid()) { mesh->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance3D::_mesh_changed)); - materials.clear(); } mesh = p_mesh; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 4aa9c31522..6b5d8cb658 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -709,7 +709,7 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const } } - return Variant(); + return false; } void Control::drop_data(const Point2 &p_point, const Variant &p_data) { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 10a42c8f6e..51f780462f 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -629,10 +629,17 @@ Variant LineEdit::get_drag_data(const Point2 &p_point) { } bool LineEdit::can_drop_data(const Point2 &p_point, const Variant &p_data) const { + bool drop_override = Control::can_drop_data(p_point, p_data); // In case user wants to drop custom data. + if (drop_override) { + return drop_override; + } + return p_data.get_type() == Variant::STRING; } void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { + Control::drop_data(p_point, p_data); + if (p_data.get_type() == Variant::STRING) { set_cursor_at_pixel_pos(p_point.x); int selected = selection.end - selection.begin; diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index b9ac6d7505..1e33ab0758 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -171,7 +171,10 @@ void Range::set_as_ratio(double p_value) { } double Range::get_as_ratio() const { - ERR_FAIL_COND_V_MSG(Math::is_equal_approx(get_max(), get_min()), 0.0, "Cannot get ratio when minimum and maximum value are equal."); + if (Math::is_equal_approx(get_max(), get_min())) { + // Avoid division by zero. + return 1.0; + } if (shared->exp_ratio && get_min() >= 0) { double exp_min = get_min() == 0 ? 0.0 : Math::log(get_min()) / Math::log((double)2); |