diff --git a/doc/classes/CameraFeed.xml b/doc/classes/CameraFeed.xml index 974f6d4a334c..96f393fee3fa 100644 --- a/doc/classes/CameraFeed.xml +++ b/doc/classes/CameraFeed.xml @@ -56,6 +56,9 @@ Feed supplies separate Y and CbCr images that need to be combined and converted to RGB. + + Feed external images. + Unspecified position. diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 21de46f4fc78..b5a6fbc860f0 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -2475,6 +2475,8 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Refget("xr_features/xr_mode"); if (xr_mode_index == XR_MODE_OPENXR) { command_line_strings.push_back("--xr_mode_openxr"); + } else if (xr_mode_index == XR_MODE_ARCORE) { + command_line_strings.push_back("--xr_mode_arcore"); } else { // XRMode.REGULAR is the default. command_line_strings.push_back("--xr_mode_regular"); } diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 2498394adda1..872ff0314cec 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -60,6 +60,7 @@ static const int APP_CATEGORY_VIDEO = 8; // This should match the entries in 'platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java' static const int XR_MODE_REGULAR = 0; static const int XR_MODE_OPENXR = 1; +static const int XR_MODE_ARCORE = 2; struct CustomExportData { String assets_directory; diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 52350c12a6d3..c06e0e88a597 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -250,6 +250,7 @@ private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) { break; case REGULAR: + case ARCORE: default: /* By default, GLSurfaceView() creates a RGB_565 opaque surface. * If we want a translucent one, we should change the surface's diff --git a/platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java b/platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java index 2c2c9f39d649..d020940a5584 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java +++ b/platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java @@ -35,7 +35,8 @@ */ public enum XRMode { REGULAR(0, "Regular", "--xr_mode_regular", "Default Android Gamepad"), // Regular/flatscreen - OPENXR(1, "OpenXR", "--xr_mode_openxr", ""); + OPENXR(1, "OpenXR", "--xr_mode_openxr", ""), + ARCORE(2, "AR Core", "--xr_mode_arcore", "Default Android Gamepad"); final int index; final String label; diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 79ba2528ba79..67840ea5d811 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -331,3 +331,13 @@ void GodotJavaWrapper::dump_benchmark(const String &benchmark_file) { env->CallVoidMethod(godot_instance, _dump_benchmark, j_benchmark_file); } } + +int GodotJavaWrapper::get_display_rotation() { + if (_get_display_rotation) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, 0); + return env->CallIntMethod(godot_instance, _get_display_rotation); + } else { + return 0; + } +} diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index ba42d5dccd66..e9d8d373bcd8 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -70,6 +70,7 @@ class GodotJavaWrapper { jmethodID _begin_benchmark_measure = nullptr; jmethodID _end_benchmark_measure = nullptr; jmethodID _dump_benchmark = nullptr; + jmethodID _get_display_rotation = nullptr; public: GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance); @@ -102,6 +103,7 @@ class GodotJavaWrapper { void begin_benchmark_measure(const String &p_label); void end_benchmark_measure(const String &p_label); void dump_benchmark(const String &benchmark_file); + int get_display_rotation(); }; #endif // JAVA_GODOT_WRAPPER_H diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp index 0661ffd576df..b08fa4f446c3 100644 --- a/servers/camera/camera_feed.cpp +++ b/servers/camera/camera_feed.cpp @@ -53,6 +53,7 @@ void CameraFeed::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_RGB_img", "rgb_img"), &CameraFeed::set_RGB_img); ClassDB::bind_method(D_METHOD("_set_YCbCr_img", "ycbcr_img"), &CameraFeed::set_YCbCr_img); + ClassDB::bind_method(D_METHOD("_set_external", "external_img"), &CameraFeed::set_external); ClassDB::bind_method(D_METHOD("get_datatype"), &CameraFeed::get_datatype); @@ -64,6 +65,7 @@ void CameraFeed::_bind_methods() { BIND_ENUM_CONSTANT(FEED_RGB); BIND_ENUM_CONSTANT(FEED_YCBCR); BIND_ENUM_CONSTANT(FEED_YCBCR_SEP); + BIND_ENUM_CONSTANT(FEED_EXTERNAL); BIND_ENUM_CONSTANT(FEED_UNSPECIFIED); BIND_ENUM_CONSTANT(FEED_FRONT); @@ -147,6 +149,7 @@ CameraFeed::CameraFeed() { transform = Transform2D(1.0, 0.0, 0.0, -1.0, 0.0, 1.0); texture[CameraServer::FEED_Y_IMAGE] = RenderingServer::get_singleton()->texture_2d_placeholder_create(); texture[CameraServer::FEED_CBCR_IMAGE] = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + texture[CameraServer::FEED_EXTERNAL] = RenderingServer::get_singleton()->texture_2d_placeholder_create(); } CameraFeed::CameraFeed(String p_name, FeedPosition p_position) { @@ -244,6 +247,28 @@ void CameraFeed::set_YCbCr_imgs(const Ref &p_y_img, const Ref &p_c } } +void CameraFeed::set_external(const Ref &p_external_img) { + ERR_FAIL_COND(p_external_img.is_null()); + + if (active) { + int new_external_width = p_external_img->get_width(); + int new_external_height = p_external_img->get_height(); + + if ((base_width != new_external_width) || (base_height != new_external_height)) { + // assume that camera image doesn't change formats etc. + base_width = new_external_width; + base_height = new_external_height; + + { + RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_external_img); + RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_EXTERNAL], new_texture); + } + } else { + RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_EXTERNAL], p_external_img); + } + } +} + bool CameraFeed::activate_feed() { // nothing to do here return true; diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h index b85a44cfaec1..d40d61d5c995 100644 --- a/servers/camera/camera_feed.h +++ b/servers/camera/camera_feed.h @@ -49,7 +49,8 @@ class CameraFeed : public RefCounted { FEED_NOIMAGE, // we don't have an image yet FEED_RGB, // our texture will contain a normal RGB texture that can be used directly FEED_YCBCR, // our texture will contain a YCbCr texture that needs to be converted to RGB before output - FEED_YCBCR_SEP // our camera is split into two textures, first plane contains Y data, second plane contains CbCr data + FEED_YCBCR_SEP, // our camera is split into two textures, first plane contains Y data, second plane contains CbCr data + FEED_EXTERNAL // specific for android, camera feed is managed externally, assumed RGB }; enum FeedPosition { @@ -101,6 +102,7 @@ class CameraFeed : public RefCounted { void set_RGB_img(const Ref &p_rgb_img); void set_YCbCr_img(const Ref &p_ycbcr_img); void set_YCbCr_imgs(const Ref &p_y_img, const Ref &p_cbcr_img); + void set_external(const Ref &p_external_img); virtual bool activate_feed(); virtual void deactivate_feed(); diff --git a/servers/camera_server.h b/servers/camera_server.h index 4e0b75fbf618..abdb70565a40 100644 --- a/servers/camera_server.h +++ b/servers/camera_server.h @@ -56,7 +56,8 @@ class CameraServer : public Object { FEED_YCBCR_IMAGE = 0, FEED_Y_IMAGE = 0, FEED_CBCR_IMAGE = 1, - FEED_IMAGES = 2 + FEED_EXTERNAL = 2, + FEED_IMAGES = 3 }; typedef CameraServer *(*CreateFunc)();