Expose GodotPlugin's utility methods used for registration and signal emitting.
This enables creation and use of a plugin like class by composition rather than inheritance.
This commit is contained in:
parent
daf1151b79
commit
64f5a7b8ca
4 changed files with 148 additions and 25 deletions
|
@ -45,7 +45,9 @@ import androidx.annotation.Nullable;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
@ -107,14 +109,47 @@ public abstract class GodotPlugin {
|
|||
* This method is invoked on the render thread.
|
||||
*/
|
||||
public final void onRegisterPluginWithGodotNative() {
|
||||
nativeRegisterSingleton(getPluginName(), this);
|
||||
registeredSignals.putAll(registerPluginWithGodotNative(this, new GodotPluginInfoProvider() {
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPluginName() {
|
||||
return GodotPlugin.this.getPluginName();
|
||||
}
|
||||
|
||||
Class clazz = getClass();
|
||||
@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();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the plugin with Godot native code.
|
||||
*
|
||||
* This method must be invoked on the render thread.
|
||||
*/
|
||||
public static Map<String, SignalInfo> registerPluginWithGodotNative(Object pluginObject, GodotPluginInfoProvider pluginInfoProvider) {
|
||||
nativeRegisterSingleton(pluginInfoProvider.getPluginName(), pluginObject);
|
||||
|
||||
Class clazz = pluginObject.getClass();
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
boolean found = false;
|
||||
|
||||
for (String s : getPluginMethods()) {
|
||||
for (String s : pluginInfoProvider.getPluginMethods()) {
|
||||
if (s.equals(method.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
|
@ -123,7 +158,7 @@ public abstract class GodotPlugin {
|
|||
if (!found)
|
||||
continue;
|
||||
|
||||
List<String> ptr = new ArrayList<String>();
|
||||
List<String> ptr = new ArrayList<>();
|
||||
|
||||
Class[] paramTypes = method.getParameterTypes();
|
||||
for (Class c : paramTypes) {
|
||||
|
@ -133,21 +168,24 @@ public abstract class GodotPlugin {
|
|||
String[] pt = new String[ptr.size()];
|
||||
ptr.toArray(pt);
|
||||
|
||||
nativeRegisterMethod(getPluginName(), method.getName(), method.getReturnType().getName(), pt);
|
||||
nativeRegisterMethod(pluginInfoProvider.getPluginName(), method.getName(), method.getReturnType().getName(), pt);
|
||||
}
|
||||
|
||||
// Register the signals for this plugin.
|
||||
for (SignalInfo signalInfo : getPluginSignals()) {
|
||||
Map<String, SignalInfo> registeredSignals = new HashMap<>();
|
||||
for (SignalInfo signalInfo : pluginInfoProvider.getPluginSignals()) {
|
||||
String signalName = signalInfo.getName();
|
||||
nativeRegisterSignal(getPluginName(), signalName, signalInfo.getParamTypesNames());
|
||||
nativeRegisterSignal(pluginInfoProvider.getPluginName(), signalName, signalInfo.getParamTypesNames());
|
||||
registeredSignals.put(signalName, signalInfo);
|
||||
}
|
||||
|
||||
// Get the list of gdnative libraries to register.
|
||||
Set<String> gdnativeLibrariesPaths = getPluginGDNativeLibrariesPaths();
|
||||
Set<String> gdnativeLibrariesPaths = pluginInfoProvider.getPluginGDNativeLibrariesPaths();
|
||||
if (!gdnativeLibrariesPaths.isEmpty()) {
|
||||
nativeRegisterGDNativeLibraries(gdnativeLibrariesPaths.toArray(new String[0]));
|
||||
}
|
||||
|
||||
return registeredSignals;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -274,8 +312,8 @@ public abstract class GodotPlugin {
|
|||
|
||||
/**
|
||||
* Emit a registered Godot signal.
|
||||
* @param signalName
|
||||
* @param signalArgs
|
||||
* @param signalName Name of the signal to emit. It will be validated against the set of registered signals.
|
||||
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the {@link SignalInfo} matching the registered signalName parameter.
|
||||
*/
|
||||
protected void emitSignal(final String signalName, final Object... signalArgs) {
|
||||
try {
|
||||
|
@ -285,6 +323,27 @@ public abstract class GodotPlugin {
|
|||
throw new IllegalArgumentException(
|
||||
"Signal " + signalName + " is not registered for this plugin.");
|
||||
}
|
||||
emitSignal(getGodot(), getPluginName(), signalInfo, signalArgs);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
Log.w(TAG, exception.getMessage());
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a Godot signal.
|
||||
* @param godot
|
||||
* @param pluginName Name of the Godot plugin the signal will be emitted from. The plugin must already be registered with the Godot engine.
|
||||
* @param signalInfo Information about the signal to emit.
|
||||
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the given {@link SignalInfo} parameter.
|
||||
*/
|
||||
public static void emitSignal(Godot godot, String pluginName, SignalInfo signalInfo, final Object... signalArgs) {
|
||||
try {
|
||||
if (signalInfo == null) {
|
||||
throw new IllegalArgumentException("Signal must be non null.");
|
||||
}
|
||||
|
||||
// Validate the arguments count.
|
||||
Class<?>[] signalParamTypes = signalInfo.getParamTypes();
|
||||
|
@ -301,12 +360,8 @@ public abstract class GodotPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
runOnRenderThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
nativeEmitSignal(getPluginName(), signalName, signalArgs);
|
||||
}
|
||||
});
|
||||
godot.runOnRenderThread(() -> nativeEmitSignal(pluginName, signalInfo.getName(), signalArgs));
|
||||
|
||||
} catch (IllegalArgumentException exception) {
|
||||
Log.w(TAG, exception.getMessage());
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
@ -334,7 +389,7 @@ public abstract class GodotPlugin {
|
|||
* Used to register gdnative libraries bundled by the plugin.
|
||||
* @param gdnlibPaths Paths to the libraries relative to the 'assets' directory.
|
||||
*/
|
||||
private native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths);
|
||||
private static native void nativeRegisterGDNativeLibraries(String[] gdnlibPaths);
|
||||
|
||||
/**
|
||||
* Used to complete registration of the {@link GodotPlugin} instance's methods.
|
||||
|
@ -342,7 +397,7 @@ public abstract class GodotPlugin {
|
|||
* @param signalName Name of the signal to register
|
||||
* @param signalParamTypes Signal parameters types
|
||||
*/
|
||||
private native void nativeRegisterSignal(String pluginName, String signalName, String[] signalParamTypes);
|
||||
private static native void nativeRegisterSignal(String pluginName, String signalName, String[] signalParamTypes);
|
||||
|
||||
/**
|
||||
* Used to emit signal by {@link GodotPlugin} instance.
|
||||
|
@ -350,5 +405,5 @@ public abstract class GodotPlugin {
|
|||
* @param signalName Name of the signal to emit
|
||||
* @param signalParams Signal parameters
|
||||
*/
|
||||
private native void nativeEmitSignal(String pluginName, String signalName, Object[] signalParams);
|
||||
private static native void nativeEmitSignal(String pluginName, String signalName, Object[] signalParams);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*************************************************************************/
|
||||
/* GodotPluginInfoProvider.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 androidx.annotation.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides the set of information expected from a Godot plugin.
|
||||
*/
|
||||
public interface GodotPluginInfoProvider {
|
||||
|
||||
/**
|
||||
* Returns the name of the plugin.
|
||||
*/
|
||||
@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();
|
||||
|
||||
/**
|
||||
* Returns the paths for the plugin's gdnative libraries (if any).
|
||||
*
|
||||
* The paths must be relative to the 'assets' directory and point to a '*.gdnlib' file.
|
||||
*/
|
||||
@NonNull
|
||||
Set<String> getPluginGDNativeLibrariesPaths();
|
||||
}
|
|
@ -87,7 +87,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
|
|||
s->add_method(mname, mid, types, get_jni_type(retval));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types) {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types) {
|
||||
String singleton_name = jstring_to_string(j_plugin_name, env);
|
||||
|
||||
ERR_FAIL_COND(!jni_singletons.has(singleton_name));
|
||||
|
@ -109,7 +109,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegis
|
|||
singleton->add_signal(signal_name, types);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params) {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params) {
|
||||
String singleton_name = jstring_to_string(j_plugin_name, env);
|
||||
|
||||
ERR_FAIL_COND(!jni_singletons.has(singleton_name));
|
||||
|
@ -134,7 +134,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
|
|||
singleton->emit_signal(signal_name, args, count);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jobject obj, jobjectArray gdnlib_paths) {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) {
|
||||
int gdnlib_count = env->GetArrayLength(gdnlib_paths);
|
||||
if (gdnlib_count == 0) {
|
||||
return;
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
extern "C" {
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSingleton(JNIEnv *env, jclass clazz, jstring name, jobject obj);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterMethod(JNIEnv *env, jclass clazz, jstring sname, jstring name, jstring ret, jobjectArray args);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jobject obj, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jobject obj, jobjectArray gdnlib_paths);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_param_types);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitSignal(JNIEnv *env, jclass clazz, jstring j_plugin_name, jstring j_signal_name, jobjectArray j_signal_params);
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths);
|
||||
}
|
||||
|
||||
#endif // GODOT_PLUGIN_JNI_H
|
||||
|
|
Loading…
Reference in a new issue