You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Merge pull request #103972 from m4gr3d/xr_editor_hybrid_support
Add support for running hybrid apps from the XR editor
This commit is contained in:
@@ -311,9 +311,7 @@ void EditorDebuggerNode::stop(bool p_force) {
|
|||||||
|
|
||||||
// Also close all debugging sessions.
|
// Also close all debugging sessions.
|
||||||
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
|
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
|
||||||
if (dbg->is_session_active()) {
|
dbg->_stop_and_notify();
|
||||||
dbg->_stop_and_notify();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
_break_state_changed();
|
_break_state_changed();
|
||||||
breakpoints.clear();
|
breakpoints.clear();
|
||||||
|
|||||||
@@ -2176,7 +2176,7 @@ void EditorNode::try_autosave() {
|
|||||||
Node *scene = editor_data.get_edited_scene_root();
|
Node *scene = editor_data.get_edited_scene_root();
|
||||||
|
|
||||||
if (scene && !scene->get_scene_file_path().is_empty()) { // Only autosave if there is a scene and if it has a path.
|
if (scene && !scene->get_scene_file_path().is_empty()) { // Only autosave if there is a scene and if it has a path.
|
||||||
_save_scene(scene->get_scene_file_path());
|
_save_scene(scene->get_scene_file_path(), -1, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_menu_option(SCENE_SAVE_ALL_SCENES);
|
_menu_option(SCENE_SAVE_ALL_SCENES);
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ android_files = [
|
|||||||
"rendering_context_driver_vulkan_android.cpp",
|
"rendering_context_driver_vulkan_android.cpp",
|
||||||
"variant/callable_jni.cpp",
|
"variant/callable_jni.cpp",
|
||||||
"dialog_utils_jni.cpp",
|
"dialog_utils_jni.cpp",
|
||||||
"game_menu_utils_jni.cpp",
|
"editor/game_menu_utils_jni.cpp",
|
||||||
|
"editor/editor_utils_jni.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
env_android = env.Clone()
|
env_android = env.Clone()
|
||||||
|
|||||||
82
platform/android/editor/editor_utils_jni.cpp
Normal file
82
platform/android/editor/editor_utils_jni.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* editor_utils_jni.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* 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 "editor_utils_jni.h"
|
||||||
|
|
||||||
|
#include "jni_utils.h"
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
#include "editor/gui/editor_run_bar.h"
|
||||||
|
#include "main/main.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_EditorUtils_runScene(JNIEnv *p_env, jclass, jstring p_scene, jobjectArray p_scene_args) {
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Vector<String> scene_args;
|
||||||
|
jint length = p_env->GetArrayLength(p_scene_args);
|
||||||
|
for (jint i = 0; i < length; ++i) {
|
||||||
|
jstring j_arg = (jstring)p_env->GetObjectArrayElement(p_scene_args, i);
|
||||||
|
String arg = jstring_to_string(j_arg, p_env);
|
||||||
|
scene_args.push_back(arg);
|
||||||
|
p_env->DeleteLocalRef(j_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
String scene = jstring_to_string(p_scene, p_env);
|
||||||
|
|
||||||
|
EditorRunBar *editor_run_bar = EditorRunBar::get_singleton();
|
||||||
|
if (editor_run_bar != nullptr) {
|
||||||
|
if (scene.is_empty()) {
|
||||||
|
editor_run_bar->play_main_scene(false);
|
||||||
|
} else {
|
||||||
|
editor_run_bar->play_custom_scene(scene, scene_args);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<String> args;
|
||||||
|
|
||||||
|
for (const String &a : Main::get_forwardable_cli_arguments(Main::CLI_SCOPE_PROJECT)) {
|
||||||
|
args.push_back(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const String &arg : scene_args) {
|
||||||
|
args.push_back(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scene.is_empty()) {
|
||||||
|
args.push_back("--scene");
|
||||||
|
args.push_back(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = OS::get_singleton()->create_instance(args);
|
||||||
|
ERR_FAIL_COND(err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
37
platform/android/editor/editor_utils_jni.h
Normal file
37
platform/android/editor/editor_utils_jni.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* editor_utils_jni.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* 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. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_EditorUtils_runScene(JNIEnv *p_env, jclass, jstring p_scene, jobjectArray p_scene_args);
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ static GameViewPlugin *_get_game_view_plugin() {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -54,7 +54,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -63,7 +63,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -72,7 +72,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeTyp
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -81,7 +81,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectM
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -90,7 +90,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelecti
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -99,7 +99,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraO
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -108,7 +108,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraM
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -117,7 +117,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamer
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -126,7 +126,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamer
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
if (EditorInterface::get_singleton()) {
|
if (EditorInterface::get_singleton()) {
|
||||||
EditorInterface::get_singleton()->play_main_scene();
|
EditorInterface::get_singleton()->play_main_scene();
|
||||||
@@ -134,7 +134,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_playMainSc
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled) {
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled) {
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||||
@@ -33,15 +33,15 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz);
|
||||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled);
|
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled);
|
||||||
}
|
}
|
||||||
@@ -180,6 +180,8 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
|
||||||
|
|
||||||
implementation "androidx.fragment:fragment:$versions.fragmentVersion"
|
implementation "androidx.fragment:fragment:$versions.fragmentVersion"
|
||||||
implementation project(":lib")
|
implementation project(":lib")
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,22 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- Intent filter used to intercept hybrid PANEL launch for the current editor project, and route it
|
||||||
|
properly through the editor 'run' logic (e.g: debugger setup) -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="org.godotengine.xr.hybrid.PANEL" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- Intent filter used to intercept hybrid IMMERSIVE launch for the current editor project, and route it
|
||||||
|
properly through the editor 'run' logic (e.g: debugger setup) -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="org.godotengine.xr.hybrid.IMMERSIVE" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".GodotGame"
|
android:name=".GodotGame"
|
||||||
@@ -101,8 +117,7 @@
|
|||||||
android:autoRemoveFromRecents="true"
|
android:autoRemoveFromRecents="true"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
android:resizeableActivity="false"
|
android:resizeableActivity="false"
|
||||||
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
|
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" />
|
||||||
</activity>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
We remove this meta-data originating from the vendors plugin as we only need the loader for
|
We remove this meta-data originating from the vendors plugin as we only need the loader for
|
||||||
|
|||||||
@@ -60,14 +60,19 @@ import org.godotengine.editor.utils.verifyApk
|
|||||||
import org.godotengine.godot.BuildConfig
|
import org.godotengine.godot.BuildConfig
|
||||||
import org.godotengine.godot.GodotActivity
|
import org.godotengine.godot.GodotActivity
|
||||||
import org.godotengine.godot.GodotLib
|
import org.godotengine.godot.GodotLib
|
||||||
|
import org.godotengine.godot.editor.utils.EditorUtils
|
||||||
|
import org.godotengine.godot.editor.utils.GameMenuUtils
|
||||||
|
import org.godotengine.godot.editor.utils.GameMenuUtils.GameEmbedMode
|
||||||
|
import org.godotengine.godot.editor.utils.GameMenuUtils.fetchGameEmbedMode
|
||||||
import org.godotengine.godot.error.Error
|
import org.godotengine.godot.error.Error
|
||||||
import org.godotengine.godot.utils.DialogUtils
|
import org.godotengine.godot.utils.DialogUtils
|
||||||
import org.godotengine.godot.utils.GameMenuUtils
|
|
||||||
import org.godotengine.godot.utils.GameMenuUtils.GameEmbedMode
|
|
||||||
import org.godotengine.godot.utils.GameMenuUtils.fetchGameEmbedMode
|
|
||||||
import org.godotengine.godot.utils.PermissionsUtil
|
import org.godotengine.godot.utils.PermissionsUtil
|
||||||
import org.godotengine.godot.utils.ProcessPhoenix
|
import org.godotengine.godot.utils.ProcessPhoenix
|
||||||
import org.godotengine.godot.utils.isNativeXRDevice
|
import org.godotengine.godot.utils.isNativeXRDevice
|
||||||
|
import org.godotengine.godot.xr.HybridMode
|
||||||
|
import org.godotengine.godot.xr.getHybridAppLaunchMode
|
||||||
|
import org.godotengine.godot.xr.HYBRID_APP_PANEL_CATEGORY
|
||||||
|
import org.godotengine.godot.xr.HYBRID_APP_IMMERSIVE_CATEGORY
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +103,8 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||||||
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
|
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
|
||||||
private const val EDITOR_PROJECT_MANAGER_ARG_SHORT = "-p"
|
private const val EDITOR_PROJECT_MANAGER_ARG_SHORT = "-p"
|
||||||
internal const val XR_MODE_ARG = "--xr-mode"
|
internal const val XR_MODE_ARG = "--xr-mode"
|
||||||
|
private const val SCENE_ARG = "--scene"
|
||||||
|
private const val PATH_ARG = "--path"
|
||||||
|
|
||||||
// Info for the various classes used by the editor.
|
// Info for the various classes used by the editor.
|
||||||
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
|
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
|
||||||
@@ -236,6 +243,50 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||||||
setupGameMenuBar()
|
setupGameMenuBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(newIntent: Intent) {
|
||||||
|
if (newIntent.hasCategory(HYBRID_APP_PANEL_CATEGORY) || newIntent.hasCategory(HYBRID_APP_IMMERSIVE_CATEGORY)) {
|
||||||
|
val params = newIntent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
|
||||||
|
Log.d(TAG, "Received hybrid transition intent $newIntent with parameters ${params.contentToString()}")
|
||||||
|
// Override EXTRA_NEW_LAUNCH so the editor is not restarted
|
||||||
|
newIntent.putExtra(EXTRA_NEW_LAUNCH, false)
|
||||||
|
|
||||||
|
godot?.runOnRenderThread {
|
||||||
|
// Look for the scene and xr-mode arguments
|
||||||
|
var scene = ""
|
||||||
|
var xrMode = XR_MODE_DEFAULT
|
||||||
|
var path = ""
|
||||||
|
if (params != null) {
|
||||||
|
val sceneIndex = params.indexOf(SCENE_ARG)
|
||||||
|
if (sceneIndex != -1 && sceneIndex + 1 < params.size) {
|
||||||
|
scene = params[sceneIndex +1]
|
||||||
|
}
|
||||||
|
|
||||||
|
val xrModeIndex = params.indexOf(XR_MODE_ARG)
|
||||||
|
if (xrModeIndex != -1 && xrModeIndex + 1 < params.size) {
|
||||||
|
xrMode = params[xrModeIndex + 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
val pathIndex = params.indexOf(PATH_ARG)
|
||||||
|
if (pathIndex != -1 && pathIndex + 1 < params.size) {
|
||||||
|
path = params[pathIndex + 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val sceneArgs = mutableSetOf(XR_MODE_ARG, xrMode).apply {
|
||||||
|
if (path.isNotEmpty() && scene.isEmpty()) {
|
||||||
|
add(PATH_ARG)
|
||||||
|
add(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Running scene $scene with arguments: $sceneArgs")
|
||||||
|
EditorUtils.runScene(scene, sceneArgs.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onNewIntent(newIntent)
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun shouldShowGameMenuBar() = gameMenuContainer != null
|
protected open fun shouldShowGameMenuBar() = gameMenuContainer != null
|
||||||
|
|
||||||
private fun setupGameMenuBar() {
|
private fun setupGameMenuBar() {
|
||||||
@@ -327,26 +378,41 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (hasEditor) {
|
if (hasEditor) {
|
||||||
EDITOR_MAIN_INFO
|
return EDITOR_MAIN_INFO
|
||||||
} else {
|
}
|
||||||
// Launching a game.
|
|
||||||
val openxrEnabled = xrMode == XR_MODE_ON ||
|
// Launching a game.
|
||||||
(xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())
|
if (isNativeXRDevice(applicationContext)) {
|
||||||
if (openxrEnabled && isNativeXRDevice(applicationContext)) {
|
if (xrMode == XR_MODE_ON) {
|
||||||
XR_RUN_GAME_INFO
|
return XR_RUN_GAME_INFO
|
||||||
} else {
|
}
|
||||||
if (godot?.isProjectManagerHint() == true || isNativeXRDevice(applicationContext)) {
|
|
||||||
|
if ((xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())) {
|
||||||
|
val hybridLaunchMode = getHybridAppLaunchMode()
|
||||||
|
|
||||||
|
return if (hybridLaunchMode == HybridMode.PANEL) {
|
||||||
RUN_GAME_INFO
|
RUN_GAME_INFO
|
||||||
} else {
|
} else {
|
||||||
val resolvedEmbedMode = resolveGameEmbedModeIfNeeded(gameEmbedMode)
|
XR_RUN_GAME_INFO
|
||||||
if (resolvedEmbedMode == GameEmbedMode.DISABLED) {
|
|
||||||
RUN_GAME_INFO
|
|
||||||
} else {
|
|
||||||
EMBEDDED_RUN_GAME_INFO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Native XR devices don't support embed mode yet.
|
||||||
|
return RUN_GAME_INFO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Project manager doesn't support embed mode.
|
||||||
|
if (godot?.isProjectManagerHint() == true) {
|
||||||
|
return RUN_GAME_INFO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for embed mode launch.
|
||||||
|
val resolvedEmbedMode = resolveGameEmbedModeIfNeeded(gameEmbedMode)
|
||||||
|
return if (resolvedEmbedMode == GameEmbedMode.DISABLED) {
|
||||||
|
RUN_GAME_INFO
|
||||||
|
} else {
|
||||||
|
EMBEDDED_RUN_GAME_INFO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,6 +692,7 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||||||
return verifyApk(godot.fileAccessHandler, apkPath)
|
return verifyApk(godot.fileAccessHandler, apkPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
override fun supportsFeature(featureTag: String): Boolean {
|
override fun supportsFeature(featureTag: String): Boolean {
|
||||||
if (featureTag == "xr_editor") {
|
if (featureTag == "xr_editor") {
|
||||||
return isNativeXRDevice(applicationContext)
|
return isNativeXRDevice(applicationContext)
|
||||||
@@ -639,11 +706,12 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||||||
return BuildConfig.FLAVOR == "picoos"
|
return BuildConfig.FLAVOR == "picoos"
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return super.supportsFeature(featureTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun onEditorConnected(connectedEditorId: Int) {
|
internal fun onEditorConnected(editorId: Int) {
|
||||||
when (connectedEditorId) {
|
Log.d(TAG, "Editor $editorId connected!")
|
||||||
|
when (editorId) {
|
||||||
EMBEDDED_RUN_GAME_INFO.windowId, RUN_GAME_INFO.windowId -> {
|
EMBEDDED_RUN_GAME_INFO.windowId, RUN_GAME_INFO.windowId -> {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
embeddedGameViewContainerWindow?.isVisible = false
|
embeddedGameViewContainerWindow?.isVisible = false
|
||||||
@@ -652,12 +720,16 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|||||||
|
|
||||||
XR_RUN_GAME_INFO.windowId -> {
|
XR_RUN_GAME_INFO.windowId -> {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
updateEmbeddedGameView(true, false)
|
updateEmbeddedGameView(gameRunning = true, gameEmbedded = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun onEditorDisconnected(editorId: Int) {
|
||||||
|
Log.d(TAG, "Editor $editorId disconnected!")
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateEmbeddedGameView(gameRunning: Boolean, gameEmbedded: Boolean) {
|
private fun updateEmbeddedGameView(gameRunning: Boolean, gameEmbedded: Boolean) {
|
||||||
if (gameRunning) {
|
if (gameRunning) {
|
||||||
embeddedGameStateLabel?.apply {
|
embeddedGameStateLabel?.apply {
|
||||||
|
|||||||
@@ -35,9 +35,11 @@ import android.util.Log
|
|||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import org.godotengine.godot.Godot
|
import org.godotengine.godot.Godot
|
||||||
import org.godotengine.godot.GodotLib
|
import org.godotengine.godot.GodotLib
|
||||||
import org.godotengine.godot.utils.GameMenuUtils
|
import org.godotengine.godot.editor.utils.GameMenuUtils
|
||||||
import org.godotengine.godot.utils.PermissionsUtil
|
import org.godotengine.godot.utils.PermissionsUtil
|
||||||
import org.godotengine.godot.utils.ProcessPhoenix
|
import org.godotengine.godot.utils.ProcessPhoenix
|
||||||
|
import org.godotengine.godot.xr.HYBRID_APP_FEATURE
|
||||||
|
import org.godotengine.godot.xr.isHybridAppEnabled
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for the Godot play windows.
|
* Base class for the Godot play windows.
|
||||||
@@ -101,4 +103,14 @@ abstract class BaseGodotGame: GodotEditor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun getEditorGameEmbedMode() = GameMenuUtils.GameEmbedMode.AUTO
|
protected open fun getEditorGameEmbedMode() = GameMenuUtils.GameEmbedMode.AUTO
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
override fun supportsFeature(featureTag: String): Boolean {
|
||||||
|
if (HYBRID_APP_FEATURE == featureTag) {
|
||||||
|
// Check if hybrid is enabled
|
||||||
|
return isHybridAppEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.supportsFeature(featureTag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,9 @@ internal class EditorMessageDispatcher(private val editor: BaseGodotEditor) {
|
|||||||
MSG_REGISTER_MESSENGER -> {
|
MSG_REGISTER_MESSENGER -> {
|
||||||
val editorId = msg.arg1
|
val editorId = msg.arg1
|
||||||
val messenger = msg.replyTo
|
val messenger = msg.replyTo
|
||||||
registerMessenger(editorId, messenger)
|
registerMessenger(editorId, messenger) {
|
||||||
|
editor.onEditorDisconnected(editorId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MSG_DISPATCH_GAME_MENU_ACTION -> {
|
MSG_DISPATCH_GAME_MENU_ACTION -> {
|
||||||
@@ -211,8 +213,8 @@ internal class EditorMessageDispatcher(private val editor: BaseGodotEditor) {
|
|||||||
} else if (messenger.binder.isBinderAlive) {
|
} else if (messenger.binder.isBinderAlive) {
|
||||||
messenger.binder.linkToDeath({
|
messenger.binder.linkToDeath({
|
||||||
Log.v(TAG, "Removing messenger for $editorId")
|
Log.v(TAG, "Removing messenger for $editorId")
|
||||||
cleanEditorConnection(editorId)
|
|
||||||
messengerDeathCallback?.run()
|
messengerDeathCallback?.run()
|
||||||
|
cleanEditorConnection(editorId)
|
||||||
}, 0)
|
}, 0)
|
||||||
editorConnectionsInfos[editorId] = EditorConnectionInfo(messenger)
|
editorConnectionsInfos[editorId] = EditorConnectionInfo(messenger)
|
||||||
editor.onEditorConnected(editorId)
|
editor.onEditorConnected(editorId)
|
||||||
@@ -234,7 +236,8 @@ internal class EditorMessageDispatcher(private val editor: BaseGodotEditor) {
|
|||||||
/**
|
/**
|
||||||
* Utility method to register a [Messenger] attached to this handler with a host.
|
* Utility method to register a [Messenger] attached to this handler with a host.
|
||||||
*
|
*
|
||||||
* This is done so that the host can send request to the editor instance attached to this handle.
|
* This is done so that the host can send request (e.g: force-quit when the host exits) to the editor instance
|
||||||
|
* attached to this handle.
|
||||||
*
|
*
|
||||||
* Note that this is only done when the editor instance is internal (not exported) to prevent
|
* Note that this is only done when the editor instance is internal (not exported) to prevent
|
||||||
* arbitrary apps from having the ability to send requests.
|
* arbitrary apps from having the ability to send requests.
|
||||||
|
|||||||
@@ -37,12 +37,17 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.CallSuper
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import org.godotengine.editor.embed.GameMenuFragment
|
import org.godotengine.editor.embed.GameMenuFragment
|
||||||
import org.godotengine.godot.utils.GameMenuUtils
|
import org.godotengine.godot.GodotLib
|
||||||
|
import org.godotengine.godot.editor.utils.GameMenuUtils
|
||||||
import org.godotengine.godot.utils.ProcessPhoenix
|
import org.godotengine.godot.utils.ProcessPhoenix
|
||||||
import org.godotengine.godot.utils.isHorizonOSDevice
|
import org.godotengine.godot.utils.isHorizonOSDevice
|
||||||
import org.godotengine.godot.utils.isNativeXRDevice
|
import org.godotengine.godot.utils.isNativeXRDevice
|
||||||
|
import org.godotengine.godot.xr.HYBRID_APP_PANEL_FEATURE
|
||||||
|
import org.godotengine.godot.xr.XRMode
|
||||||
|
import org.godotengine.godot.xr.isHybridAppEnabled
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drives the 'run project' window of the Godot Editor.
|
* Drives the 'run project' window of the Godot Editor.
|
||||||
@@ -82,6 +87,18 @@ open class GodotGame : BaseGodotGame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getCommandLine(): MutableList<String> {
|
||||||
|
val updatedArgs = super.getCommandLine()
|
||||||
|
if (!updatedArgs.contains(XRMode.REGULAR.cmdLineArg)) {
|
||||||
|
updatedArgs.add(XRMode.REGULAR.cmdLineArg)
|
||||||
|
}
|
||||||
|
if (!updatedArgs.contains(XR_MODE_ARG)) {
|
||||||
|
updatedArgs.add(XR_MODE_ARG)
|
||||||
|
updatedArgs.add("off")
|
||||||
|
}
|
||||||
|
return updatedArgs
|
||||||
|
}
|
||||||
|
|
||||||
override fun enterPiPMode() {
|
override fun enterPiPMode() {
|
||||||
if (hasPiPSystemFeature()) {
|
if (hasPiPSystemFeature()) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
@@ -245,4 +262,19 @@ open class GodotGame : BaseGodotGame() {
|
|||||||
expandGameMenuButton?.isVisible = shouldShowGameMenuBar() && isMenuBarCollapsable() && collapsed
|
expandGameMenuButton?.isVisible = shouldShowGameMenuBar() && isMenuBarCollapsable() && collapsed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
override fun supportsFeature(featureTag: String): Boolean {
|
||||||
|
if (HYBRID_APP_PANEL_FEATURE == featureTag) {
|
||||||
|
// Check if openxr is enabled
|
||||||
|
if (!GodotLib.getGlobal("xr/openxr/enabled").toBoolean()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if hybrid is enabled
|
||||||
|
return isHybridAppEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.supportsFeature(featureTag)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
|||||||
import android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
|
import android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
|
||||||
import org.godotengine.editor.GodotGame
|
import org.godotengine.editor.GodotGame
|
||||||
import org.godotengine.editor.R
|
import org.godotengine.editor.R
|
||||||
import org.godotengine.godot.utils.GameMenuUtils
|
import org.godotengine.godot.editor.utils.GameMenuUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Host the Godot game from the editor when the embedded mode is enabled.
|
* Host the Godot game from the editor when the embedded mode is enabled.
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean devBuild = buildType == "dev"
|
boolean devBuild = buildType == "dev"
|
||||||
boolean debugSymbols = devBuild
|
boolean debugSymbols = devBuild || (buildType == "debug" && isAndroidStudio())
|
||||||
boolean runTests = devBuild
|
boolean runTests = devBuild
|
||||||
boolean storeRelease = buildType == "release"
|
boolean storeRelease = buildType == "release"
|
||||||
boolean productionBuild = storeRelease
|
boolean productionBuild = storeRelease
|
||||||
|
|||||||
@@ -1026,7 +1026,7 @@ class Godot private constructor(val context: Context) {
|
|||||||
*/
|
*/
|
||||||
@Keep
|
@Keep
|
||||||
private fun hasFeature(feature: String): Boolean {
|
private fun hasFeature(feature: String): Boolean {
|
||||||
if (primaryHost?.supportsFeature(feature) ?: false) {
|
if (primaryHost?.supportsFeature(feature) == true) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
|
|||||||
private val TAG = GodotActivity::class.java.simpleName
|
private val TAG = GodotActivity::class.java.simpleName
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
protected val EXTRA_COMMAND_LINE_PARAMS = "command_line_params"
|
val EXTRA_COMMAND_LINE_PARAMS = "command_line_params"
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
protected val EXTRA_NEW_LAUNCH = "new_launch_requested"
|
protected val EXTRA_NEW_LAUNCH = "new_launch_requested"
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* EditorUtils.kt */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* 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. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
package org.godotengine.godot.editor.utils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for accessing and using editor specific capabilities.
|
||||||
|
*
|
||||||
|
* This class is only functional on editor builds.
|
||||||
|
*/
|
||||||
|
object EditorUtils {
|
||||||
|
@JvmStatic
|
||||||
|
external fun runScene(scene: String, sceneArgs: Array<String>)
|
||||||
|
}
|
||||||
@@ -28,13 +28,15 @@
|
|||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
package org.godotengine.godot.utils
|
package org.godotengine.godot.editor.utils
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import org.godotengine.godot.GodotLib
|
import org.godotengine.godot.GodotLib
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for accessing and using game menu APIs.
|
* Utility class for accessing and using game menu APIs.
|
||||||
|
*
|
||||||
|
* This class is only functional on editor builds.
|
||||||
*/
|
*/
|
||||||
object GameMenuUtils {
|
object GameMenuUtils {
|
||||||
private val TAG = GameMenuUtils::class.java.simpleName
|
private val TAG = GameMenuUtils::class.java.simpleName
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/* HybridAppUtils.kt */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* 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. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains utility methods and constants for hybrid apps.
|
||||||
|
*/
|
||||||
|
@file:JvmName("HybridAppUtils")
|
||||||
|
|
||||||
|
package org.godotengine.godot.xr
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import org.godotengine.godot.GodotLib
|
||||||
|
|
||||||
|
private const val TAG = "HybridAppUtils"
|
||||||
|
|
||||||
|
enum class HybridMode(private val nativeValue: Int) {
|
||||||
|
NONE( -1),
|
||||||
|
IMMERSIVE(0),
|
||||||
|
PANEL(1);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromNative(nativeValue: Int): HybridMode {
|
||||||
|
for (mode in HybridMode.entries) {
|
||||||
|
if (mode.nativeValue == nativeValue) {
|
||||||
|
return mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const val HYBRID_APP_FEATURE = "godot_openxr_hybrid_app"
|
||||||
|
const val HYBRID_APP_PANEL_FEATURE = "godot_openxr_panel_app"
|
||||||
|
const val HYBRID_APP_PANEL_CATEGORY = "org.godotengine.xr.hybrid.PANEL"
|
||||||
|
const val HYBRID_APP_IMMERSIVE_CATEGORY = "org.godotengine.xr.hybrid.IMMERSIVE"
|
||||||
|
|
||||||
|
fun isHybridAppEnabled() = GodotLib.getGlobal("xr/hybrid_app/enabled").toBoolean()
|
||||||
|
|
||||||
|
fun getHybridAppLaunchMode(): HybridMode {
|
||||||
|
if (!isHybridAppEnabled()) {
|
||||||
|
return HybridMode.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val launchModeValue = GodotLib.getGlobal("xr/hybrid_app/launch_mode").toInt()
|
||||||
|
return HybridMode.fromNative(launchModeValue)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "Unable to retrieve 'xr/hybrid_app/launch_mode' project setting", e)
|
||||||
|
return HybridMode.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user