Skip to content

Commit b9c3b1d

Browse files
committed
Misc improvements to the GodotPlugin API
- Add overload method for `GodotPlugin#emitSignal(...)` - Allow passing `null` values as signal arguments
1 parent caefb0f commit b9c3b1d

File tree

6 files changed

+44
-45
lines changed

6 files changed

+44
-45
lines changed

platform/android/api/java_class_wrapper.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class JavaClass : public RefCounted {
6868
RBMap<StringName, Variant> constant_map;
6969

7070
struct MethodInfo {
71+
bool _public = false;
7172
bool _static = false;
7273
bool _constructor = false;
7374
Vector<uint32_t> param_types;
@@ -274,7 +275,7 @@ class JavaClassWrapper : public Object {
274275

275276
Ref<JavaObject> exception;
276277

277-
Ref<JavaClass> _wrap(const String &p_class, bool p_allow_non_public_methods_access);
278+
Ref<JavaClass> _wrap(const String &p_class, bool p_allow_non_public_methods_access = false);
278279

279280
static JavaClassWrapper *singleton;
280281

@@ -293,7 +294,7 @@ class JavaClassWrapper : public Object {
293294
}
294295

295296
#ifdef ANDROID_ENABLED
296-
Ref<JavaClass> wrap_jclass(jclass p_class, bool p_allow_private_methods_access = false);
297+
Ref<JavaClass> wrap_jclass(jclass p_class, bool p_allow_non_public_methods_access = false);
297298
#endif
298299
JavaClassWrapper();
299300
};

platform/android/api/jni_singleton.h

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,31 +60,15 @@ class JNISingleton : public Object {
6060
}
6161

6262
// Check the method we're looking for is in the JNISingleton map.
63+
// This is done because JNISingletons register methods differently than wrapped JavaClass / JavaObject to allow
64+
// for access to private methods annotated with the @UsedByGodot annotation.
65+
// In the future, we should remove access to private methods and require that JNISingletons' methods exposed to
66+
// GDScript be all public, similarly to what we do for wrapped JavaClass / JavaObject methods. Doing so will
67+
// also allow dropping and deprecating the @UsedByGodot annotation.
6368
RBMap<StringName, MethodData>::Element *E = method_map.find(p_method);
6469
if (E) {
6570
if (wrapped_object.is_valid()) {
66-
// Check that the arguments match.
67-
int method_arg_count = E->get().argtypes.size();
68-
if (p_argcount < method_arg_count) {
69-
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
70-
} else if (p_argcount > method_arg_count) {
71-
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
72-
} else {
73-
// Check the arguments are valid.
74-
bool arguments_valid = true;
75-
for (int i = 0; i < p_argcount; i++) {
76-
if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) {
77-
arguments_valid = false;
78-
break;
79-
}
80-
}
81-
82-
if (arguments_valid) {
83-
return wrapped_object->callp(p_method, p_args, p_argcount, r_error);
84-
} else {
85-
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
86-
}
87-
}
71+
return wrapped_object->callp(p_method, p_args, p_argcount, r_error);
8872
} else {
8973
r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
9074
}

platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ protected void runOnRenderThread(Runnable action) {
361361
/**
362362
* Emit a registered Godot signal.
363363
* @param signalName Name of the signal to emit. It will be validated against the set of registered signals.
364-
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the {@link SignalInfo} matching the registered signalName parameter.
364+
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the registered {@link SignalInfo} matching the signalName parameter.
365365
*/
366366
protected void emitSignal(final String signalName, final Object... signalArgs) {
367367
try {
@@ -380,6 +380,15 @@ protected void emitSignal(final String signalName, final Object... signalArgs) {
380380
}
381381
}
382382

383+
/**
384+
* Emit a registered Godot signal.
385+
* @param signal Signal to emit. It will be validated against the set of registered signals.
386+
* @param signalArgs Arguments used to populate the emitted signal. The arguments will be validated against the registered {@link SignalInfo} matching the signal parameter.
387+
*/
388+
protected void emitSignal(SignalInfo signal, final Object... signalArgs) {
389+
emitSignal(signal.getName(), signalArgs);
390+
}
391+
383392
/**
384393
* Emit a Godot signal.
385394
* @param godot Godot instance
@@ -402,7 +411,8 @@ public static void emitSignal(Godot godot, String pluginName, SignalInfo signalI
402411

403412
// Validate the argument's types.
404413
for (int i = 0; i < signalParamTypes.length; i++) {
405-
if (!signalParamTypes[i].isInstance(signalArgs[i])) {
414+
Object signalArg = signalArgs[i];
415+
if (signalArg != null && !signalParamTypes[i].isInstance(signalArg)) {
406416
throw new IllegalArgumentException(
407417
"Invalid type for argument #" + i + ". Should be of type " + signalParamTypes[i].getName());
408418
}

platform/android/java_class_wrapper.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
199199
case ARG_ARRAY_BIT | ARG_TYPE_CHARSEQUENCE: {
200200
if (p_args[i]->get_type() == Variant::ARRAY) {
201201
Array arr = *p_args[i];
202-
if (arr.is_typed() && arr.get_typed_builtin() != Variant::STRING) {
202+
if (arr.is_typed() && (arr.get_typed_builtin() != Variant::STRING || arr.get_typed_builtin() != Variant::STRING_NAME)) {
203203
arg_expected = Variant::ARRAY;
204204
}
205205
} else if (p_args[i]->get_type() != Variant::PACKED_STRING_ARRAY) {
@@ -1527,6 +1527,7 @@ Ref<JavaClass> JavaClassWrapper::_wrap(const String &p_class, bool p_allow_non_p
15271527
}
15281528

15291529
JavaClass::MethodInfo mi;
1530+
mi._public = is_public;
15301531
mi._static = (mods & 0x8) != 0;
15311532
mi._constructor = is_constructor;
15321533
bool valid = true;
@@ -1686,15 +1687,15 @@ Ref<JavaClass> JavaClassWrapper::_wrap(const String &p_class, bool p_allow_non_p
16861687
return java_class;
16871688
}
16881689

1689-
Ref<JavaClass> JavaClassWrapper::wrap_jclass(jclass p_class, bool p_allow_private_methods_access) {
1690+
Ref<JavaClass> JavaClassWrapper::wrap_jclass(jclass p_class, bool p_allow_non_public_methods_access) {
16901691
JNIEnv *env = get_jni_env();
16911692
ERR_FAIL_NULL_V(env, Ref<JavaClass>());
16921693

16931694
jstring class_name = (jstring)env->CallObjectMethod(p_class, Class_getName);
16941695
String class_name_string = jstring_to_string(class_name, env);
16951696
env->DeleteLocalRef(class_name);
16961697

1697-
return _wrap(class_name_string, p_allow_private_methods_access);
1698+
return _wrap(class_name_string, p_allow_non_public_methods_access);
16981699
}
16991700

17001701
JavaClassWrapper *JavaClassWrapper::singleton = nullptr;

platform/android/jni_utils.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,17 @@ Callable jcallable_to_callable(JNIEnv *p_env, jobject p_jcallable_obj) {
5555
ERR_FAIL_NULL_V(p_env, Callable());
5656

5757
const Variant *callable_variant = nullptr;
58-
jclass callable_class = jni_find_class(p_env, "org/godotengine/godot/variant/Callable");
59-
if (callable_class && p_env->IsInstanceOf(p_jcallable_obj, callable_class)) {
60-
jmethodID get_native_pointer = p_env->GetMethodID(callable_class, "getNativePointer", "()J");
61-
jlong native_callable = p_env->CallLongMethod(p_jcallable_obj, get_native_pointer);
58+
if (p_jcallable_obj) {
59+
jclass callable_class = jni_find_class(p_env, "org/godotengine/godot/variant/Callable");
60+
if (callable_class && p_env->IsInstanceOf(p_jcallable_obj, callable_class)) {
61+
jmethodID get_native_pointer = p_env->GetMethodID(callable_class, "getNativePointer", "()J");
62+
jlong native_callable = p_env->CallLongMethod(p_jcallable_obj, get_native_pointer);
6263

63-
callable_variant = reinterpret_cast<const Variant *>(native_callable);
64-
}
64+
callable_variant = reinterpret_cast<const Variant *>(native_callable);
65+
}
6566

66-
p_env->DeleteLocalRef(callable_class);
67+
p_env->DeleteLocalRef(callable_class);
68+
}
6769

6870
ERR_FAIL_NULL_V(callable_variant, Callable());
6971
return *callable_variant;
@@ -73,16 +75,18 @@ String charsequence_to_string(JNIEnv *p_env, jobject p_charsequence) {
7375
ERR_FAIL_NULL_V(p_env, String());
7476

7577
String result;
76-
jclass bclass = jni_find_class(p_env, "java/lang/CharSequence");
77-
if (bclass && p_env->IsInstanceOf(p_charsequence, bclass)) {
78-
jmethodID to_string = p_env->GetMethodID(bclass, "toString", "()Ljava/lang/String;");
79-
jstring obj_string = (jstring)p_env->CallObjectMethod(p_charsequence, to_string);
78+
if (p_charsequence) {
79+
jclass bclass = jni_find_class(p_env, "java/lang/CharSequence");
80+
if (bclass && p_env->IsInstanceOf(p_charsequence, bclass)) {
81+
jmethodID to_string = p_env->GetMethodID(bclass, "toString", "()Ljava/lang/String;");
82+
jstring obj_string = (jstring)p_env->CallObjectMethod(p_charsequence, to_string);
83+
84+
result = jstring_to_string(obj_string, p_env);
85+
p_env->DeleteLocalRef(obj_string);
86+
}
8087

81-
result = jstring_to_string(obj_string, p_env);
82-
p_env->DeleteLocalRef(obj_string);
88+
p_env->DeleteLocalRef(bclass);
8389
}
84-
85-
p_env->DeleteLocalRef(bclass);
8690
return result;
8791
}
8892

platform/android/plugin/godot_plugin_jni.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
128128

129129
for (int i = 0; i < count; i++) {
130130
jobject j_param = env->GetObjectArrayElement(j_signal_params, i);
131-
ERR_FAIL_NULL(j_param);
132131
memnew_placement(&variant_params[i], Variant(_jobject_to_variant(env, j_param)));
133132
args[i] = &variant_params[i];
134133
env->DeleteLocalRef(j_param);

0 commit comments

Comments
 (0)