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
|
* It's also a reference implementation for how to setup and use the {@link Godot} fragment
|
||||||
* within an Android app.
|
* within an Android app.
|
||||||
*/
|
*/
|
||||||
public abstract class FullScreenGodotApp extends FragmentActivity {
|
public abstract class FullScreenGodotApp extends FragmentActivity implements GodotHost {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Godot godotFragment;
|
private Godot godotFragment;
|
||||||
|
@ -65,6 +65,8 @@ public abstract class FullScreenGodotApp extends FragmentActivity {
|
||||||
public void onNewIntent(Intent intent) {
|
public void onNewIntent(Intent intent) {
|
||||||
if (godotFragment != null) {
|
if (godotFragment != null) {
|
||||||
godotFragment.onNewIntent(intent);
|
godotFragment.onNewIntent(intent);
|
||||||
|
} else {
|
||||||
|
super.onNewIntent(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@ import java.io.InputStream;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -143,6 +144,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
||||||
// Used to dispatch events to the main thread.
|
// Used to dispatch events to the main thread.
|
||||||
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
|
private GodotHost godotHost;
|
||||||
private GodotPluginRegistry pluginRegistry;
|
private GodotPluginRegistry pluginRegistry;
|
||||||
|
|
||||||
static private Intent mCurrentIntent;
|
static private Intent mCurrentIntent;
|
||||||
|
@ -231,7 +233,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
||||||
|
|
||||||
protected void onGLDrawFrame(GL10 gl) {}
|
protected void onGLDrawFrame(GL10 gl) {}
|
||||||
protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
|
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() {}
|
public void registerMethods() {}
|
||||||
}
|
}
|
||||||
|
@ -269,6 +271,22 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
||||||
}
|
}
|
||||||
public ResultCallback result_callback;
|
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
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (result_callback != null) {
|
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.
|
* 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()) {
|
for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
|
||||||
plugin.onGodotMainLoopStarted();
|
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) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE));
|
v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||||
} else {
|
} else {
|
||||||
//deprecated in API 26
|
// deprecated in API 26
|
||||||
v.vibrate(durationMs);
|
v.vibrate(durationMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,6 +500,21 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
protected String[] getCommandLine() {
|
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;
|
InputStream is;
|
||||||
try {
|
try {
|
||||||
is = getActivity().getAssets().open("_cl_");
|
is = getActivity().getAssets().open("_cl_");
|
||||||
|
@ -584,7 +635,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
|
||||||
mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
|
pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
|
||||||
|
|
||||||
//check for apk expansion API
|
// check for apk expansion API
|
||||||
boolean md5mismatch = false;
|
boolean md5mismatch = false;
|
||||||
command_line = getCommandLine();
|
command_line = getCommandLine();
|
||||||
String main_pack_md5 = null;
|
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()]);
|
command_line = new_args.toArray(new String[new_args.size()]);
|
||||||
}
|
}
|
||||||
if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
|
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)) {
|
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
|
// 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.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -109,31 +110,9 @@ public abstract class GodotPlugin {
|
||||||
* This method is invoked on the render thread.
|
* This method is invoked on the render thread.
|
||||||
*/
|
*/
|
||||||
public final void onRegisterPluginWithGodotNative() {
|
public final void onRegisterPluginWithGodotNative() {
|
||||||
registeredSignals.putAll(registerPluginWithGodotNative(this, new GodotPluginInfoProvider() {
|
registeredSignals.putAll(
|
||||||
@NonNull
|
registerPluginWithGodotNative(this, getPluginName(), getPluginMethods(), getPluginSignals(),
|
||||||
@Override
|
getPluginGDNativeLibrariesPaths()));
|
||||||
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();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,23 +120,41 @@ public abstract class GodotPlugin {
|
||||||
*
|
*
|
||||||
* This method must be invoked on the render thread.
|
* This method must be invoked on the render thread.
|
||||||
*/
|
*/
|
||||||
public static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject, GodotPluginInfoProvider pluginInfoProvider) {
|
public static void registerPluginWithGodotNative(Object pluginObject,
|
||||||
nativeRegisterSingleton(pluginInfoProvider.getPluginName(), 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();
|
Class clazz = pluginObject.getClass();
|
||||||
|
|
||||||
Method[] methods = clazz.getDeclaredMethods();
|
Method[] methods = clazz.getDeclaredMethods();
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
boolean found = false;
|
// Check if the method is annotated with {@link UsedByGodot}.
|
||||||
|
if (method.getAnnotation(UsedByGodot.class) != null) {
|
||||||
for (String s : pluginInfoProvider.getPluginMethods()) {
|
filteredMethods.add(method);
|
||||||
if (s.equals(method.getName())) {
|
} else {
|
||||||
found = true;
|
// For backward compatibility, process the methods from the given <pluginMethods> argument.
|
||||||
break;
|
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<>();
|
List<String> ptr = new ArrayList<>();
|
||||||
|
|
||||||
Class[] paramTypes = method.getParameterTypes();
|
Class[] paramTypes = method.getParameterTypes();
|
||||||
|
@ -168,21 +165,20 @@ public abstract class GodotPlugin {
|
||||||
String[] pt = new String[ptr.size()];
|
String[] pt = new String[ptr.size()];
|
||||||
ptr.toArray(pt);
|
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.
|
// Register the signals for this plugin.
|
||||||
Map<String, SignalInfo> registeredSignals = new HashMap<>();
|
Map<String, SignalInfo> registeredSignals = new HashMap<>();
|
||||||
for (SignalInfo signalInfo : pluginInfoProvider.getPluginSignals()) {
|
for (SignalInfo signalInfo : pluginSignals) {
|
||||||
String signalName = signalInfo.getName();
|
String signalName = signalInfo.getName();
|
||||||
nativeRegisterSignal(pluginInfoProvider.getPluginName(), signalName, signalInfo.getParamTypesNames());
|
nativeRegisterSignal(pluginName, signalName, signalInfo.getParamTypesNames());
|
||||||
registeredSignals.put(signalName, signalInfo);
|
registeredSignals.put(signalName, signalInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of gdnative libraries to register.
|
// Get the list of gdnative libraries to register.
|
||||||
Set<String> gdnativeLibrariesPaths = pluginInfoProvider.getPluginGDNativeLibrariesPaths();
|
if (!pluginGDNativeLibrariesPaths.isEmpty()) {
|
||||||
if (!gdnativeLibrariesPaths.isEmpty()) {
|
nativeRegisterGDNativeLibraries(pluginGDNativeLibrariesPaths.toArray(new String[0]));
|
||||||
nativeRegisterGDNativeLibraries(gdnativeLibrariesPaths.toArray(new String[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return registeredSignals;
|
return registeredSignals;
|
||||||
|
@ -235,6 +231,11 @@ public abstract class GodotPlugin {
|
||||||
*/
|
*/
|
||||||
public boolean onMainBackPressed() { return false; }
|
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.
|
* 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.
|
* Returns the list of methods to be exposed to Godot.
|
||||||
|
*
|
||||||
|
* @deprecated Used the {@link UsedByGodot} annotation instead.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
public List<String> getPluginMethods() {
|
public List<String> getPluginMethods() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ package org.godotengine.godot.plugin;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,17 +46,13 @@ public interface GodotPluginInfoProvider {
|
||||||
@NonNull
|
@NonNull
|
||||||
String getPluginName();
|
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.
|
* Returns the list of signals to be exposed to Godot.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
Set<SignalInfo> getPluginSignals();
|
default Set<SignalInfo> getPluginSignals() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the paths for the plugin's gdnative libraries (if any).
|
* 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.
|
* The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@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) {
|
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()));
|
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 (step == 1) {
|
||||||
if (!Main::start()) {
|
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();
|
os_android->main_loop_begin();
|
||||||
godot_java->on_godot_main_loop_started(env);
|
godot_java->on_godot_main_loop_started(env);
|
||||||
++step;
|
++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");
|
_is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z");
|
||||||
_vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V");
|
_vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V");
|
||||||
_get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;");
|
_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");
|
_on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V");
|
||||||
|
|
||||||
// get some Activity method pointers...
|
// get some Activity method pointers...
|
||||||
|
@ -117,11 +118,21 @@ void GodotJavaWrapper::gfx_init(bool gl2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
|
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
|
||||||
if (_on_video_init)
|
if (_on_video_init) {
|
||||||
if (p_env == NULL)
|
if (p_env == NULL)
|
||||||
p_env = get_jni_env();
|
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) {
|
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) {
|
if (p_env == NULL) {
|
||||||
p_env = get_jni_env();
|
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) {
|
void GodotJavaWrapper::restart(JNIEnv *p_env) {
|
||||||
if (_restart)
|
if (_restart) {
|
||||||
if (p_env == NULL)
|
if (p_env == NULL)
|
||||||
p_env = get_jni_env();
|
p_env = get_jni_env();
|
||||||
|
|
||||||
p_env->CallVoidMethod(godot_instance, _restart);
|
p_env->CallVoidMethod(godot_instance, _restart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
|
void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
|
||||||
if (_finish)
|
if (_finish) {
|
||||||
if (p_env == NULL)
|
if (p_env == NULL)
|
||||||
p_env = get_jni_env();
|
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) {
|
void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
jmethodID _is_activity_resumed = 0;
|
jmethodID _is_activity_resumed = 0;
|
||||||
jmethodID _vibrate = 0;
|
jmethodID _vibrate = 0;
|
||||||
jmethodID _get_input_fallback_mapping = 0;
|
jmethodID _get_input_fallback_mapping = 0;
|
||||||
|
jmethodID _on_godot_setup_completed = 0;
|
||||||
jmethodID _on_godot_main_loop_started = 0;
|
jmethodID _on_godot_main_loop_started = 0;
|
||||||
jmethodID _get_class_loader = 0;
|
jmethodID _get_class_loader = 0;
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ public:
|
||||||
|
|
||||||
void gfx_init(bool gl2);
|
void gfx_init(bool gl2);
|
||||||
void on_video_init(JNIEnv *p_env = NULL);
|
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 on_godot_main_loop_started(JNIEnv *p_env = NULL);
|
||||||
void restart(JNIEnv *p_env = NULL);
|
void restart(JNIEnv *p_env = NULL);
|
||||||
void force_quit(JNIEnv *p_env = NULL);
|
void force_quit(JNIEnv *p_env = NULL);
|
||||||
|
|
Loading…
Reference in a new issue