Merge pull request #47047 from m4gr3d/simplify_godot_plugin_methods_registration
[3.2] Improve Godot Android plugin methods registration
This commit is contained in:
commit
8ec3a33115
9 changed files with 245 additions and 65 deletions
|
@ -44,7 +44,7 @@ import androidx.fragment.app.FragmentActivity;
|
|||
* It's also a reference implementation for how to setup and use the {@link Godot} fragment
|
||||
* within an Android app.
|
||||
*/
|
||||
public abstract class FullScreenGodotApp extends FragmentActivity {
|
||||
public abstract class FullScreenGodotApp extends FragmentActivity implements GodotHost {
|
||||
|
||||
@Nullable
|
||||
private Godot godotFragment;
|
||||
|
@ -65,6 +65,8 @@ public abstract class FullScreenGodotApp extends FragmentActivity {
|
|||
public void onNewIntent(Intent intent) {
|
||||
if (godotFragment != null) {
|
||||
godotFragment.onNewIntent(intent);
|
||||
} else {
|
||||
super.onNewIntent(intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ import java.io.InputStream;
|
|||
import java.lang.reflect.Method;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -143,6 +144,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
// Used to dispatch events to the main thread.
|
||||
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private GodotHost godotHost;
|
||||
private GodotPluginRegistry pluginRegistry;
|
||||
|
||||
static private Intent mCurrentIntent;
|
||||
|
@ -231,7 +233,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
|
||||
protected void onGLDrawFrame(GL10 gl) {}
|
||||
protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
|
||||
//protected void onGLSurfaceCreated(GL10 gl, EGLConfig config) {} // singletons won't be ready until first GodotLib.step()
|
||||
// protected void onGLSurfaceCreated(GL10 gl, EGLConfig config) {} // singletons won't be ready until first GodotLib.step()
|
||||
|
||||
public void registerMethods() {}
|
||||
}
|
||||
|
@ -269,6 +271,22 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
}
|
||||
public ResultCallback result_callback;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (getParentFragment() instanceof GodotHost) {
|
||||
godotHost = (GodotHost)getParentFragment();
|
||||
} else if (getActivity() instanceof GodotHost) {
|
||||
godotHost = (GodotHost)getActivity();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
godotHost = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (result_callback != null) {
|
||||
|
@ -299,6 +317,20 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Invoked on the render thread when the Godot setup is complete.
|
||||
*/
|
||||
@CallSuper
|
||||
protected void onGodotSetupCompleted() {
|
||||
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||
plugin.onGodotSetupCompleted();
|
||||
}
|
||||
|
||||
if (godotHost != null) {
|
||||
godotHost.onGodotSetupCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked on the render thread when the Godot main loop has started.
|
||||
*/
|
||||
|
@ -307,6 +339,10 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||
plugin.onGodotMainLoopStarted();
|
||||
}
|
||||
|
||||
if (godotHost != null) {
|
||||
godotHost.onGodotMainLoopStarted();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -409,7 +445,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||
} else {
|
||||
//deprecated in API 26
|
||||
// deprecated in API 26
|
||||
v.vibrate(durationMs);
|
||||
}
|
||||
}
|
||||
|
@ -464,6 +500,21 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
|
||||
@CallSuper
|
||||
protected String[] getCommandLine() {
|
||||
String[] original = parseCommandLine();
|
||||
String[] updated;
|
||||
List<String> hostCommandLine = godotHost != null ? godotHost.getCommandLine() : null;
|
||||
if (hostCommandLine == null || hostCommandLine.isEmpty()) {
|
||||
updated = original;
|
||||
} else {
|
||||
updated = Arrays.copyOf(original, original.length + hostCommandLine.size());
|
||||
for (int i = 0; i < hostCommandLine.size(); i++) {
|
||||
updated[original.length + i] = hostCommandLine.get(i);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
private String[] parseCommandLine() {
|
||||
InputStream is;
|
||||
try {
|
||||
is = getActivity().getAssets().open("_cl_");
|
||||
|
@ -584,7 +635,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
|
||||
|
||||
//check for apk expansion API
|
||||
// check for apk expansion API
|
||||
boolean md5mismatch = false;
|
||||
command_line = getCommandLine();
|
||||
String main_pack_md5 = null;
|
||||
|
@ -642,9 +693,9 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
|||
command_line = new_args.toArray(new String[new_args.size()]);
|
||||
}
|
||||
if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
|
||||
//check that environment is ok!
|
||||
// check that environment is ok!
|
||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
//show popup and die
|
||||
// show popup and die
|
||||
}
|
||||
|
||||
// Build the full path to the app's expansion files
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*************************************************************************/
|
||||
/* GodotHost.java */
|
||||
/*************************************************************************/
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Denotate a component (e.g: Activity, Fragment) that hosts the {@link Godot} fragment.
|
||||
*/
|
||||
public interface GodotHost {
|
||||
|
||||
/**
|
||||
* Provides a set of command line parameters to setup the engine.
|
||||
*/
|
||||
default List<String> getCommandLine() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked on the render thread when the Godot setup is complete.
|
||||
*/
|
||||
default void onGodotSetupCompleted() {}
|
||||
|
||||
/**
|
||||
* Invoked on the render thread when the Godot main loop has started.
|
||||
*/
|
||||
default void onGodotMainLoopStarted() {}
|
||||
}
|
|
@ -46,6 +46,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -109,31 +110,9 @@ public abstract class GodotPlugin {
|
|||
* This method is invoked on the render thread.
|
||||
*/
|
||||
public final void onRegisterPluginWithGodotNative() {
|
||||
registeredSignals.putAll(registerPluginWithGodotNative(this, new GodotPluginInfoProvider() {
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPluginName() {
|
||||
return GodotPlugin.this.getPluginName();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<String> getPluginMethods() {
|
||||
return GodotPlugin.this.getPluginMethods();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Set<SignalInfo> getPluginSignals() {
|
||||
return GodotPlugin.this.getPluginSignals();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Set<String> getPluginGDNativeLibrariesPaths() {
|
||||
return GodotPlugin.this.getPluginGDNativeLibrariesPaths();
|
||||
}
|
||||
}));
|
||||
registeredSignals.putAll(
|
||||
registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
|
||||
getPluginGDNativeLibrariesPaths()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,23 +120,41 @@ public abstract class GodotPlugin {
|
|||
*
|
||||
* This method must be invoked on the render thread.
|
||||
*/
|
||||
public static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject, GodotPluginInfoProvider pluginInfoProvider) {
|
||||
nativeRegisterSingleton(pluginInfoProvider.getPluginName(), pluginObject);
|
||||
public static void registerPluginWithGodotNative(Object pluginObject,
|
||||
GodotPluginInfoProvider pluginInfoProvider) {
|
||||
registerPluginWithGodotNative(pluginObject, pluginInfoProvider.getPluginName(),
|
||||
Collections.emptyList(), pluginInfoProvider.getPluginSignals(),
|
||||
pluginInfoProvider.getPluginGDNativeLibrariesPaths());
|
||||
|
||||
// Notify that registration is complete.
|
||||
pluginInfoProvider.onPluginRegistered();
|
||||
}
|
||||
|
||||
private static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject,
|
||||
String pluginName, List<String> pluginMethods, Set<SignalInfo> pluginSignals,
|
||||
Set<String> pluginGDNativeLibrariesPaths) {
|
||||
nativeRegisterSingleton(pluginName, pluginObject);
|
||||
|
||||
Set<Method> filteredMethods = new HashSet<>();
|
||||
Class clazz = pluginObject.getClass();
|
||||
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
boolean found = false;
|
||||
|
||||
for (String s : pluginInfoProvider.getPluginMethods()) {
|
||||
if (s.equals(method.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
// Check if the method is annotated with {@link UsedByGodot}.
|
||||
if (method.getAnnotation(UsedByGodot.class) != null) {
|
||||
filteredMethods.add(method);
|
||||
} else {
|
||||
// For backward compatibility, process the methods from the given <pluginMethods> argument.
|
||||
for (String methodName : pluginMethods) {
|
||||
if (methodName.equals(method.getName())) {
|
||||
filteredMethods.add(method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Method method : filteredMethods) {
|
||||
List<String> ptr = new ArrayList<>();
|
||||
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
|
@ -168,21 +165,20 @@ public abstract class GodotPlugin {
|
|||
String[] pt = new String[ptr.size()];
|
||||
ptr.toArray(pt);
|
||||
|
||||
nativeRegisterMethod(pluginInfoProvider.getPluginName(), method.getName(), method.getReturnType().getName(), pt);
|
||||
nativeRegisterMethod(pluginName, method.getName(), method.getReturnType().getName(), pt);
|
||||
}
|
||||
|
||||
// Register the signals for this plugin.
|
||||
Map<String, SignalInfo> registeredSignals = new HashMap<>();
|
||||
for (SignalInfo signalInfo : pluginInfoProvider.getPluginSignals()) {
|
||||
for (SignalInfo signalInfo : pluginSignals) {
|
||||
String signalName = signalInfo.getName();
|
||||
nativeRegisterSignal(pluginInfoProvider.getPluginName(), signalName, signalInfo.getParamTypesNames());
|
||||
nativeRegisterSignal(pluginName, signalName, signalInfo.getParamTypesNames());
|
||||
registeredSignals.put(signalName, signalInfo);
|
||||
}
|
||||
|
||||
// Get the list of gdnative libraries to register.
|
||||
Set<String> gdnativeLibrariesPaths = pluginInfoProvider.getPluginGDNativeLibrariesPaths();
|
||||
if (!gdnativeLibrariesPaths.isEmpty()) {
|
||||
nativeRegisterGDNativeLibraries(gdnativeLibrariesPaths.toArray(new String[0]));
|
||||
if (!pluginGDNativeLibrariesPaths.isEmpty()) {
|
||||
nativeRegisterGDNativeLibraries(pluginGDNativeLibrariesPaths.toArray(new String[0]));
|
||||
}
|
||||
|
||||
return registeredSignals;
|
||||
|
@ -235,6 +231,11 @@ public abstract class GodotPlugin {
|
|||
*/
|
||||
public boolean onMainBackPressed() { return false; }
|
||||
|
||||
/**
|
||||
* Invoked on the render thread when the Godot setup is complete.
|
||||
*/
|
||||
public void onGodotSetupCompleted() {}
|
||||
|
||||
/**
|
||||
* Invoked on the render thread when the Godot main loop has started.
|
||||
*/
|
||||
|
@ -266,8 +267,11 @@ public abstract class GodotPlugin {
|
|||
|
||||
/**
|
||||
* Returns the list of methods to be exposed to Godot.
|
||||
*
|
||||
* @deprecated Used the {@link UsedByGodot} annotation instead.
|
||||
*/
|
||||
@NonNull
|
||||
@Deprecated
|
||||
public List<String> getPluginMethods() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ package org.godotengine.godot.plugin;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -46,17 +46,13 @@ public interface GodotPluginInfoProvider {
|
|||
@NonNull
|
||||
String getPluginName();
|
||||
|
||||
/**
|
||||
* Returns the list of methods to be exposed to Godot.
|
||||
*/
|
||||
@NonNull
|
||||
List<String> getPluginMethods();
|
||||
|
||||
/**
|
||||
* Returns the list of signals to be exposed to Godot.
|
||||
*/
|
||||
@NonNull
|
||||
Set<SignalInfo> getPluginSignals();
|
||||
default Set<SignalInfo> getPluginSignals() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the paths for the plugin's gdnative libraries (if any).
|
||||
|
@ -64,5 +60,14 @@ public interface GodotPluginInfoProvider {
|
|||
* The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
|
||||
*/
|
||||
@NonNull
|
||||
Set<String> getPluginGDNativeLibrariesPaths();
|
||||
default Set<String> getPluginGDNativeLibrariesPaths() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is invoked on the render thread when the plugin described by this instance has been
|
||||
* registered.
|
||||
*/
|
||||
default void onPluginRegistered() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*************************************************************************/
|
||||
/* UsedByGodot.java */
|
||||
/*************************************************************************/
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.godot.plugin;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a method is being invoked from the Godot game logic.
|
||||
*
|
||||
* At runtime, annotated plugin methods are detected and automatically registered.
|
||||
*/
|
||||
@Target({ ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface UsedByGodot {}
|
|
@ -201,7 +201,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jc
|
|||
}
|
||||
|
||||
if (err != OK) {
|
||||
return; //should exit instead and print the error
|
||||
return; // should exit instead and print the error
|
||||
}
|
||||
|
||||
java_class_wrapper = memnew(JavaClassWrapper(godot_java->get_activity()));
|
||||
|
@ -252,9 +252,10 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl
|
|||
|
||||
if (step == 1) {
|
||||
if (!Main::start()) {
|
||||
return; //should exit instead and print the error
|
||||
return; // should exit instead and print the error
|
||||
}
|
||||
|
||||
godot_java->on_godot_setup_completed(env);
|
||||
os_android->main_loop_begin();
|
||||
godot_java->on_godot_main_loop_started(env);
|
||||
++step;
|
||||
|
|
|
@ -74,6 +74,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
|
|||
_is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z");
|
||||
_vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V");
|
||||
_get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;");
|
||||
_on_godot_setup_completed = p_env->GetMethodID(godot_class, "onGodotSetupCompleted", "()V");
|
||||
_on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V");
|
||||
|
||||
// get some Activity method pointers...
|
||||
|
@ -117,11 +118,21 @@ void GodotJavaWrapper::gfx_init(bool gl2) {
|
|||
}
|
||||
|
||||
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
|
||||
if (_on_video_init)
|
||||
if (_on_video_init) {
|
||||
if (p_env == NULL)
|
||||
p_env = get_jni_env();
|
||||
|
||||
p_env->CallVoidMethod(godot_instance, _on_video_init);
|
||||
p_env->CallVoidMethod(godot_instance, _on_video_init);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::on_godot_setup_completed(JNIEnv *p_env) {
|
||||
if (_on_godot_setup_completed) {
|
||||
if (p_env == NULL) {
|
||||
p_env = get_jni_env();
|
||||
}
|
||||
p_env->CallVoidMethod(godot_instance, _on_godot_setup_completed);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
|
||||
|
@ -129,24 +140,26 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
|
|||
if (p_env == NULL) {
|
||||
p_env = get_jni_env();
|
||||
}
|
||||
p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
|
||||
}
|
||||
p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::restart(JNIEnv *p_env) {
|
||||
if (_restart)
|
||||
if (_restart) {
|
||||
if (p_env == NULL)
|
||||
p_env = get_jni_env();
|
||||
|
||||
p_env->CallVoidMethod(godot_instance, _restart);
|
||||
p_env->CallVoidMethod(godot_instance, _restart);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
|
||||
if (_finish)
|
||||
if (_finish) {
|
||||
if (p_env == NULL)
|
||||
p_env = get_jni_env();
|
||||
|
||||
p_env->CallVoidMethod(godot_instance, _finish);
|
||||
p_env->CallVoidMethod(godot_instance, _finish);
|
||||
}
|
||||
}
|
||||
|
||||
void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
|
||||
|
|
|
@ -63,6 +63,7 @@ private:
|
|||
jmethodID _is_activity_resumed = 0;
|
||||
jmethodID _vibrate = 0;
|
||||
jmethodID _get_input_fallback_mapping = 0;
|
||||
jmethodID _on_godot_setup_completed = 0;
|
||||
jmethodID _on_godot_main_loop_started = 0;
|
||||
jmethodID _get_class_loader = 0;
|
||||
|
||||
|
@ -77,6 +78,7 @@ public:
|
|||
|
||||
void gfx_init(bool gl2);
|
||||
void on_video_init(JNIEnv *p_env = NULL);
|
||||
void on_godot_setup_completed(JNIEnv *p_env = NULL);
|
||||
void on_godot_main_loop_started(JNIEnv *p_env = NULL);
|
||||
void restart(JNIEnv *p_env = NULL);
|
||||
void force_quit(JNIEnv *p_env = NULL);
|
||||
|
|
Loading…
Reference in a new issue