Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/platform/android/java_godot_wrapper.cpp
20923 views
1
/**************************************************************************/
2
/* java_godot_wrapper.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "java_godot_wrapper.h"
32
33
#include "jni_utils.h"
34
35
// JNIEnv is only valid within the thread it belongs to, in a multi threading environment
36
// we can't cache it.
37
// For Godot we call most access methods from our thread and we thus get a valid JNIEnv
38
// from get_jni_env(). For one or two we expect to pass the environment
39
40
// TODO we could probably create a base class for this...
41
42
GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) {
43
godot_instance = p_env->NewGlobalRef(p_godot_instance);
44
45
// get info about our Godot class so we can get pointers and stuff...
46
godot_class = jni_find_class(p_env, "org/godotengine/godot/Godot");
47
if (godot_class) {
48
godot_class = (jclass)p_env->NewGlobalRef(godot_class);
49
} else {
50
// this is a pretty serious fail.. bail... pointers will stay 0
51
return;
52
}
53
54
// get some Godot method pointers...
55
_restart = p_env->GetMethodID(godot_class, "restart", "()V");
56
_finish = p_env->GetMethodID(godot_class, "forceQuit", "(I)Z");
57
_set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V");
58
_alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V");
59
_is_dark_mode_supported = p_env->GetMethodID(godot_class, "isDarkModeSupported", "()Z");
60
_is_dark_mode = p_env->GetMethodID(godot_class, "isDarkMode", "()Z");
61
_get_accent_color = p_env->GetMethodID(godot_class, "getAccentColor", "()I");
62
_get_base_color = p_env->GetMethodID(godot_class, "getBaseColor", "()I");
63
_get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;");
64
_set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V");
65
_has_clipboard = p_env->GetMethodID(godot_class, "hasClipboard", "()Z");
66
_show_dialog = p_env->GetMethodID(godot_class, "showDialog", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V");
67
_show_input_dialog = p_env->GetMethodID(godot_class, "showInputDialog", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
68
_show_file_picker = p_env->GetMethodID(godot_class, "showFilePicker", "(Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)V");
69
_request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z");
70
_request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z");
71
_get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;");
72
_get_ca_certificates = p_env->GetMethodID(godot_class, "getCACertificates", "()Ljava/lang/String;");
73
_init_input_devices = p_env->GetMethodID(godot_class, "initInputDevices", "()V");
74
_vibrate = p_env->GetMethodID(godot_class, "vibrate", "(II)V");
75
_get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;");
76
_on_godot_setup_completed = p_env->GetMethodID(godot_class, "onGodotSetupCompleted", "()V");
77
_on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V");
78
_on_godot_terminating = p_env->GetMethodID(godot_class, "onGodotTerminating", "()V");
79
_create_new_godot_instance = p_env->GetMethodID(godot_class, "createNewGodotInstance", "([Ljava/lang/String;)I");
80
_get_render_view = p_env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;");
81
_begin_benchmark_measure = p_env->GetMethodID(godot_class, "nativeBeginBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V");
82
_end_benchmark_measure = p_env->GetMethodID(godot_class, "nativeEndBenchmarkMeasure", "(Ljava/lang/String;Ljava/lang/String;)V");
83
_dump_benchmark = p_env->GetMethodID(godot_class, "nativeDumpBenchmark", "(Ljava/lang/String;)V");
84
_get_gdextension_list_config_file = p_env->GetMethodID(godot_class, "getGDExtensionConfigFiles", "()[Ljava/lang/String;");
85
_check_internal_feature_support = p_env->GetMethodID(godot_class, "checkInternalFeatureSupport", "(Ljava/lang/String;)Z");
86
_sign_apk = p_env->GetMethodID(godot_class, "nativeSignApk", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
87
_verify_apk = p_env->GetMethodID(godot_class, "nativeVerifyApk", "(Ljava/lang/String;)I");
88
_enable_immersive_mode = p_env->GetMethodID(godot_class, "nativeEnableImmersiveMode", "(Z)V");
89
_is_in_immersive_mode = p_env->GetMethodID(godot_class, "isInImmersiveMode", "()Z");
90
_set_window_color = p_env->GetMethodID(godot_class, "setWindowColor", "(Ljava/lang/String;)V");
91
_on_editor_workspace_selected = p_env->GetMethodID(godot_class, "nativeOnEditorWorkspaceSelected", "(Ljava/lang/String;)V");
92
_get_activity = p_env->GetMethodID(godot_class, "getActivity", "()Landroid/app/Activity;");
93
_build_env_connect = p_env->GetMethodID(godot_class, "nativeBuildEnvConnect", "(Lorg/godotengine/godot/variant/Callable;)Z");
94
_build_env_disconnect = p_env->GetMethodID(godot_class, "nativeBuildEnvDisconnect", "()V");
95
_build_env_execute = p_env->GetMethodID(godot_class, "nativeBuildEnvExecute", "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/godotengine/godot/variant/Callable;Lorg/godotengine/godot/variant/Callable;)I");
96
_build_env_cancel = p_env->GetMethodID(godot_class, "nativeBuildEnvCancel", "(I)V");
97
_build_env_clean_project = p_env->GetMethodID(godot_class, "nativeBuildEnvCleanProject", "(Ljava/lang/String;Ljava/lang/String;Lorg/godotengine/godot/variant/Callable;)V");
98
}
99
100
GodotJavaWrapper::~GodotJavaWrapper() {
101
if (godot_view) {
102
delete godot_view;
103
}
104
105
JNIEnv *env = get_jni_env();
106
ERR_FAIL_NULL(env);
107
env->DeleteGlobalRef(godot_instance);
108
env->DeleteGlobalRef(godot_class);
109
}
110
111
jobject GodotJavaWrapper::get_activity() {
112
if (_get_activity) {
113
JNIEnv *env = get_jni_env();
114
ERR_FAIL_NULL_V(env, nullptr);
115
jobject activity = env->CallObjectMethod(godot_instance, _get_activity);
116
return activity;
117
}
118
return nullptr;
119
}
120
121
GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() {
122
if (godot_view != nullptr) {
123
return godot_view;
124
}
125
if (_get_render_view) {
126
JNIEnv *env = get_jni_env();
127
ERR_FAIL_NULL_V(env, nullptr);
128
jobject godot_render_view = env->CallObjectMethod(godot_instance, _get_render_view);
129
if (!env->IsSameObject(godot_render_view, nullptr)) {
130
godot_view = new GodotJavaViewWrapper(godot_render_view);
131
}
132
}
133
return godot_view;
134
}
135
136
void GodotJavaWrapper::on_godot_setup_completed(JNIEnv *p_env) {
137
if (_on_godot_setup_completed) {
138
if (p_env == nullptr) {
139
p_env = get_jni_env();
140
}
141
p_env->CallVoidMethod(godot_instance, _on_godot_setup_completed);
142
}
143
}
144
145
void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
146
if (_on_godot_main_loop_started) {
147
if (p_env == nullptr) {
148
p_env = get_jni_env();
149
}
150
ERR_FAIL_NULL(p_env);
151
p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
152
}
153
}
154
155
void GodotJavaWrapper::on_godot_terminating(JNIEnv *p_env) {
156
if (_on_godot_terminating) {
157
if (p_env == nullptr) {
158
p_env = get_jni_env();
159
}
160
ERR_FAIL_NULL(p_env);
161
p_env->CallVoidMethod(godot_instance, _on_godot_terminating);
162
}
163
}
164
165
void GodotJavaWrapper::restart(JNIEnv *p_env) {
166
if (_restart) {
167
if (p_env == nullptr) {
168
p_env = get_jni_env();
169
}
170
ERR_FAIL_NULL(p_env);
171
p_env->CallVoidMethod(godot_instance, _restart);
172
}
173
}
174
175
bool GodotJavaWrapper::force_quit(JNIEnv *p_env, int p_instance_id) {
176
if (_finish) {
177
if (p_env == nullptr) {
178
p_env = get_jni_env();
179
}
180
ERR_FAIL_NULL_V(p_env, false);
181
return p_env->CallBooleanMethod(godot_instance, _finish, p_instance_id);
182
}
183
return false;
184
}
185
186
void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
187
if (_set_keep_screen_on) {
188
JNIEnv *env = get_jni_env();
189
ERR_FAIL_NULL(env);
190
env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled);
191
}
192
}
193
194
void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
195
if (_alert) {
196
JNIEnv *env = get_jni_env();
197
ERR_FAIL_NULL(env);
198
jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
199
jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
200
env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
201
env->DeleteLocalRef(jStrMessage);
202
env->DeleteLocalRef(jStrTitle);
203
}
204
}
205
206
bool GodotJavaWrapper::is_dark_mode_supported() {
207
if (_is_dark_mode_supported) {
208
JNIEnv *env = get_jni_env();
209
ERR_FAIL_NULL_V(env, false);
210
return env->CallBooleanMethod(godot_instance, _is_dark_mode_supported);
211
} else {
212
return false;
213
}
214
}
215
216
bool GodotJavaWrapper::is_dark_mode() {
217
if (_is_dark_mode) {
218
JNIEnv *env = get_jni_env();
219
ERR_FAIL_NULL_V(env, false);
220
return env->CallBooleanMethod(godot_instance, _is_dark_mode);
221
} else {
222
return false;
223
}
224
}
225
226
// Convert ARGB to RGBA.
227
static Color _argb_to_rgba(int p_color) {
228
int alpha = (p_color >> 24) & 0xFF;
229
int red = (p_color >> 16) & 0xFF;
230
int green = (p_color >> 8) & 0xFF;
231
int blue = p_color & 0xFF;
232
return Color(red / 255.0f, green / 255.0f, blue / 255.0f, alpha / 255.0f);
233
}
234
235
Color GodotJavaWrapper::get_accent_color() {
236
if (_get_accent_color) {
237
JNIEnv *env = get_jni_env();
238
ERR_FAIL_NULL_V(env, Color(0, 0, 0, 0));
239
int accent_color = env->CallIntMethod(godot_instance, _get_accent_color);
240
return _argb_to_rgba(accent_color);
241
} else {
242
return Color(0, 0, 0, 0);
243
}
244
}
245
246
Color GodotJavaWrapper::get_base_color() {
247
if (_get_base_color) {
248
JNIEnv *env = get_jni_env();
249
ERR_FAIL_NULL_V(env, Color(0, 0, 0, 0));
250
int base_color = env->CallIntMethod(godot_instance, _get_base_color);
251
return _argb_to_rgba(base_color);
252
} else {
253
return Color(0, 0, 0, 0);
254
}
255
}
256
257
bool GodotJavaWrapper::has_get_clipboard() {
258
return _get_clipboard != nullptr;
259
}
260
261
String GodotJavaWrapper::get_clipboard() {
262
String clipboard;
263
if (_get_clipboard) {
264
JNIEnv *env = get_jni_env();
265
ERR_FAIL_NULL_V(env, String());
266
jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard);
267
clipboard = jstring_to_string(s, env);
268
env->DeleteLocalRef(s);
269
}
270
return clipboard;
271
}
272
273
String GodotJavaWrapper::get_input_fallback_mapping() {
274
String input_fallback_mapping;
275
if (_get_input_fallback_mapping) {
276
JNIEnv *env = get_jni_env();
277
ERR_FAIL_NULL_V(env, String());
278
jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping);
279
input_fallback_mapping = jstring_to_string(fallback_mapping, env);
280
env->DeleteLocalRef(fallback_mapping);
281
}
282
return input_fallback_mapping;
283
}
284
285
bool GodotJavaWrapper::has_set_clipboard() {
286
return _set_clipboard != nullptr;
287
}
288
289
void GodotJavaWrapper::set_clipboard(const String &p_text) {
290
if (_set_clipboard) {
291
JNIEnv *env = get_jni_env();
292
ERR_FAIL_NULL(env);
293
jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
294
env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
295
env->DeleteLocalRef(jStr);
296
}
297
}
298
299
bool GodotJavaWrapper::has_has_clipboard() {
300
return _has_clipboard != nullptr;
301
}
302
303
bool GodotJavaWrapper::has_clipboard() {
304
if (_has_clipboard) {
305
JNIEnv *env = get_jni_env();
306
ERR_FAIL_NULL_V(env, false);
307
return env->CallBooleanMethod(godot_instance, _has_clipboard);
308
} else {
309
return false;
310
}
311
}
312
313
Error GodotJavaWrapper::show_dialog(const String &p_title, const String &p_description, const Vector<String> &p_buttons) {
314
if (_show_input_dialog) {
315
JNIEnv *env = get_jni_env();
316
ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
317
jstring j_title = env->NewStringUTF(p_title.utf8().get_data());
318
jstring j_description = env->NewStringUTF(p_description.utf8().get_data());
319
jobjectArray j_buttons = env->NewObjectArray(p_buttons.size(), jni_find_class(env, "java/lang/String"), nullptr);
320
for (int i = 0; i < p_buttons.size(); ++i) {
321
jstring j_button = env->NewStringUTF(p_buttons[i].utf8().get_data());
322
env->SetObjectArrayElement(j_buttons, i, j_button);
323
env->DeleteLocalRef(j_button);
324
}
325
env->CallVoidMethod(godot_instance, _show_dialog, j_title, j_description, j_buttons);
326
env->DeleteLocalRef(j_title);
327
env->DeleteLocalRef(j_description);
328
env->DeleteLocalRef(j_buttons);
329
return OK;
330
} else {
331
return ERR_UNCONFIGURED;
332
}
333
}
334
335
Error GodotJavaWrapper::show_input_dialog(const String &p_title, const String &p_message, const String &p_existing_text) {
336
if (_show_input_dialog) {
337
JNIEnv *env = get_jni_env();
338
ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
339
jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
340
jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
341
jstring jStrExistingText = env->NewStringUTF(p_existing_text.utf8().get_data());
342
env->CallVoidMethod(godot_instance, _show_input_dialog, jStrTitle, jStrMessage, jStrExistingText);
343
env->DeleteLocalRef(jStrTitle);
344
env->DeleteLocalRef(jStrMessage);
345
env->DeleteLocalRef(jStrExistingText);
346
return OK;
347
} else {
348
return ERR_UNCONFIGURED;
349
}
350
}
351
352
Error GodotJavaWrapper::show_file_picker(const String &p_current_directory, const String &p_filename, int p_mode, const Vector<String> &p_filters) {
353
if (_show_file_picker) {
354
JNIEnv *env = get_jni_env();
355
ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
356
jstring j_current_directory = env->NewStringUTF(p_current_directory.utf8().get_data());
357
jstring j_filename = env->NewStringUTF(p_filename.utf8().get_data());
358
jint j_mode = p_mode;
359
Vector<String> filters;
360
for (const String &E : p_filters) {
361
filters.append_array(E.get_slicec(';', 0).split(",")); // Add extensions.
362
filters.append_array(E.get_slicec(';', 2).split(",")); // Add MIME types.
363
}
364
jobjectArray j_filters = env->NewObjectArray(filters.size(), jni_find_class(env, "java/lang/String"), nullptr);
365
for (int i = 0; i < filters.size(); ++i) {
366
jstring j_filter = env->NewStringUTF(filters[i].utf8().get_data());
367
env->SetObjectArrayElement(j_filters, i, j_filter);
368
env->DeleteLocalRef(j_filter);
369
}
370
env->CallVoidMethod(godot_instance, _show_file_picker, j_current_directory, j_filename, j_mode, j_filters);
371
env->DeleteLocalRef(j_current_directory);
372
env->DeleteLocalRef(j_filename);
373
env->DeleteLocalRef(j_filters);
374
return OK;
375
} else {
376
return ERR_UNCONFIGURED;
377
}
378
}
379
380
bool GodotJavaWrapper::request_permission(const String &p_name) {
381
if (_request_permission) {
382
JNIEnv *env = get_jni_env();
383
ERR_FAIL_NULL_V(env, false);
384
jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
385
bool result = env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
386
env->DeleteLocalRef(jStrName);
387
return result;
388
} else {
389
return false;
390
}
391
}
392
393
bool GodotJavaWrapper::request_permissions() {
394
if (_request_permissions) {
395
JNIEnv *env = get_jni_env();
396
ERR_FAIL_NULL_V(env, false);
397
return env->CallBooleanMethod(godot_instance, _request_permissions);
398
} else {
399
return false;
400
}
401
}
402
403
Vector<String> GodotJavaWrapper::get_granted_permissions() const {
404
Vector<String> permissions_list;
405
if (_get_granted_permissions) {
406
JNIEnv *env = get_jni_env();
407
ERR_FAIL_NULL_V(env, permissions_list);
408
jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions);
409
jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object);
410
411
jsize len = env->GetArrayLength(*arr);
412
for (int i = 0; i < len; i++) {
413
jstring jstr = (jstring)env->GetObjectArrayElement(*arr, i);
414
String str = jstring_to_string(jstr, env);
415
permissions_list.push_back(str);
416
env->DeleteLocalRef(jstr);
417
}
418
}
419
return permissions_list;
420
}
421
422
Vector<String> GodotJavaWrapper::get_gdextension_list_config_file() const {
423
Vector<String> config_file_list;
424
if (_get_gdextension_list_config_file) {
425
JNIEnv *env = get_jni_env();
426
ERR_FAIL_NULL_V(env, config_file_list);
427
jobject config_file_list_object = env->CallObjectMethod(godot_instance, _get_gdextension_list_config_file);
428
jobjectArray *arr = reinterpret_cast<jobjectArray *>(&config_file_list_object);
429
430
jsize len = env->GetArrayLength(*arr);
431
for (int i = 0; i < len; i++) {
432
jstring j_config_file = (jstring)env->GetObjectArrayElement(*arr, i);
433
String config_file = jstring_to_string(j_config_file, env);
434
config_file_list.push_back(config_file);
435
env->DeleteLocalRef(j_config_file);
436
}
437
}
438
return config_file_list;
439
}
440
441
String GodotJavaWrapper::get_ca_certificates() const {
442
String ca_certificates;
443
if (_get_ca_certificates) {
444
JNIEnv *env = get_jni_env();
445
ERR_FAIL_NULL_V(env, String());
446
jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_ca_certificates);
447
ca_certificates = jstring_to_string(s, env);
448
env->DeleteLocalRef(s);
449
}
450
return ca_certificates;
451
}
452
453
void GodotJavaWrapper::init_input_devices() {
454
if (_init_input_devices) {
455
JNIEnv *env = get_jni_env();
456
ERR_FAIL_NULL(env);
457
env->CallVoidMethod(godot_instance, _init_input_devices);
458
}
459
}
460
461
void GodotJavaWrapper::vibrate(int p_duration_ms, float p_amplitude) {
462
if (_vibrate) {
463
JNIEnv *env = get_jni_env();
464
ERR_FAIL_NULL(env);
465
466
int j_amplitude = -1.0;
467
468
if (p_amplitude != -1.0) {
469
j_amplitude = CLAMP(int(p_amplitude * 255), 1, 255);
470
}
471
472
env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms, j_amplitude);
473
}
474
}
475
476
int GodotJavaWrapper::create_new_godot_instance(const List<String> &args) {
477
if (_create_new_godot_instance) {
478
JNIEnv *env = get_jni_env();
479
ERR_FAIL_NULL_V(env, 0);
480
jobjectArray jargs = env->NewObjectArray(args.size(), jni_find_class(env, "java/lang/String"), env->NewStringUTF(""));
481
int i = 0;
482
for (List<String>::ConstIterator itr = args.begin(); itr != args.end(); ++itr, ++i) {
483
jstring j_arg = env->NewStringUTF(itr->utf8().get_data());
484
env->SetObjectArrayElement(jargs, i, j_arg);
485
env->DeleteLocalRef(j_arg);
486
}
487
return env->CallIntMethod(godot_instance, _create_new_godot_instance, jargs);
488
} else {
489
return 0;
490
}
491
}
492
493
void GodotJavaWrapper::begin_benchmark_measure(const String &p_context, const String &p_label) {
494
if (_begin_benchmark_measure) {
495
JNIEnv *env = get_jni_env();
496
ERR_FAIL_NULL(env);
497
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
498
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
499
env->CallVoidMethod(godot_instance, _begin_benchmark_measure, j_context, j_label);
500
env->DeleteLocalRef(j_context);
501
env->DeleteLocalRef(j_label);
502
}
503
}
504
505
void GodotJavaWrapper::end_benchmark_measure(const String &p_context, const String &p_label) {
506
if (_end_benchmark_measure) {
507
JNIEnv *env = get_jni_env();
508
ERR_FAIL_NULL(env);
509
jstring j_context = env->NewStringUTF(p_context.utf8().get_data());
510
jstring j_label = env->NewStringUTF(p_label.utf8().get_data());
511
env->CallVoidMethod(godot_instance, _end_benchmark_measure, j_context, j_label);
512
env->DeleteLocalRef(j_context);
513
env->DeleteLocalRef(j_label);
514
}
515
}
516
517
void GodotJavaWrapper::dump_benchmark(const String &benchmark_file) {
518
if (_dump_benchmark) {
519
JNIEnv *env = get_jni_env();
520
ERR_FAIL_NULL(env);
521
jstring j_benchmark_file = env->NewStringUTF(benchmark_file.utf8().get_data());
522
env->CallVoidMethod(godot_instance, _dump_benchmark, j_benchmark_file);
523
env->DeleteLocalRef(j_benchmark_file);
524
}
525
}
526
527
bool GodotJavaWrapper::check_internal_feature_support(const String &p_feature) const {
528
if (_check_internal_feature_support) {
529
JNIEnv *env = get_jni_env();
530
ERR_FAIL_NULL_V(env, false);
531
532
jstring j_feature = env->NewStringUTF(p_feature.utf8().get_data());
533
bool result = env->CallBooleanMethod(godot_instance, _check_internal_feature_support, j_feature);
534
env->DeleteLocalRef(j_feature);
535
return result;
536
} else {
537
return false;
538
}
539
}
540
541
Error GodotJavaWrapper::sign_apk(const String &p_input_path, const String &p_output_path, const String &p_keystore_path, const String &p_keystore_user, const String &p_keystore_password) {
542
if (_sign_apk) {
543
JNIEnv *env = get_jni_env();
544
ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
545
546
jstring j_input_path = env->NewStringUTF(p_input_path.utf8().get_data());
547
jstring j_output_path = env->NewStringUTF(p_output_path.utf8().get_data());
548
jstring j_keystore_path = env->NewStringUTF(p_keystore_path.utf8().get_data());
549
jstring j_keystore_user = env->NewStringUTF(p_keystore_user.utf8().get_data());
550
jstring j_keystore_password = env->NewStringUTF(p_keystore_password.utf8().get_data());
551
552
int result = env->CallIntMethod(godot_instance, _sign_apk, j_input_path, j_output_path, j_keystore_path, j_keystore_user, j_keystore_password);
553
554
env->DeleteLocalRef(j_input_path);
555
env->DeleteLocalRef(j_output_path);
556
env->DeleteLocalRef(j_keystore_path);
557
env->DeleteLocalRef(j_keystore_user);
558
env->DeleteLocalRef(j_keystore_password);
559
560
return static_cast<Error>(result);
561
} else {
562
return ERR_UNCONFIGURED;
563
}
564
}
565
566
Error GodotJavaWrapper::verify_apk(const String &p_apk_path) {
567
if (_verify_apk) {
568
JNIEnv *env = get_jni_env();
569
ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
570
571
jstring j_apk_path = env->NewStringUTF(p_apk_path.utf8().get_data());
572
int result = env->CallIntMethod(godot_instance, _verify_apk, j_apk_path);
573
env->DeleteLocalRef(j_apk_path);
574
return static_cast<Error>(result);
575
} else {
576
return ERR_UNCONFIGURED;
577
}
578
}
579
580
void GodotJavaWrapper::enable_immersive_mode(bool p_enabled) {
581
if (_enable_immersive_mode) {
582
JNIEnv *env = get_jni_env();
583
ERR_FAIL_NULL(env);
584
env->CallVoidMethod(godot_instance, _enable_immersive_mode, p_enabled);
585
}
586
}
587
588
bool GodotJavaWrapper::is_in_immersive_mode() {
589
if (_is_in_immersive_mode) {
590
JNIEnv *env = get_jni_env();
591
ERR_FAIL_NULL_V(env, false);
592
return env->CallBooleanMethod(godot_instance, _is_in_immersive_mode);
593
} else {
594
return false;
595
}
596
}
597
598
void GodotJavaWrapper::set_window_color(const Color &p_color) {
599
if (_set_window_color) {
600
JNIEnv *env = get_jni_env();
601
ERR_FAIL_NULL(env);
602
String color = "#" + p_color.to_html(false);
603
jstring jStrColor = env->NewStringUTF(color.utf8().get_data());
604
env->CallVoidMethod(godot_instance, _set_window_color, jStrColor);
605
}
606
}
607
608
void GodotJavaWrapper::on_editor_workspace_selected(const String &p_workspace) {
609
if (_on_editor_workspace_selected) {
610
JNIEnv *env = get_jni_env();
611
ERR_FAIL_NULL(env);
612
613
jstring j_workspace = env->NewStringUTF(p_workspace.utf8().get_data());
614
env->CallVoidMethod(godot_instance, _on_editor_workspace_selected, j_workspace);
615
}
616
}
617
618
bool GodotJavaWrapper::build_env_connect(const Callable &p_callback) {
619
if (_build_env_connect) {
620
JNIEnv *env = get_jni_env();
621
ERR_FAIL_NULL_V(env, false);
622
623
jobject j_callback = callable_to_jcallable(env, p_callback);
624
jboolean result = env->CallBooleanMethod(godot_instance, _build_env_connect, j_callback);
625
env->DeleteLocalRef(j_callback);
626
627
return result;
628
}
629
630
return false;
631
}
632
633
void GodotJavaWrapper::build_env_disconnect() {
634
if (_build_env_disconnect) {
635
JNIEnv *env = get_jni_env();
636
ERR_FAIL_NULL(env);
637
638
env->CallVoidMethod(godot_instance, _build_env_disconnect);
639
}
640
}
641
642
int GodotJavaWrapper::build_env_execute(const String &p_build_tool, const List<String> &p_arguments, const String &p_project_path, const String &p_gradle_build_directory, const Callable &p_output_callback, const Callable &p_result_callback) {
643
if (_build_env_execute) {
644
JNIEnv *env = get_jni_env();
645
ERR_FAIL_NULL_V(env, -1);
646
647
jstring j_build_tool = env->NewStringUTF(p_build_tool.utf8().get_data());
648
jobjectArray j_args = env->NewObjectArray(p_arguments.size(), env->FindClass("java/lang/String"), nullptr);
649
for (int i = 0; i < p_arguments.size(); i++) {
650
jstring j_arg = env->NewStringUTF(p_arguments.get(i).utf8().get_data());
651
env->SetObjectArrayElement(j_args, i, j_arg);
652
env->DeleteLocalRef(j_arg);
653
}
654
jstring j_project_path = env->NewStringUTF(p_project_path.utf8().get_data());
655
jstring j_gradle_build_directory = env->NewStringUTF(p_gradle_build_directory.utf8().get_data());
656
jobject j_output_callback = callable_to_jcallable(env, p_output_callback);
657
jobject j_result_callback = callable_to_jcallable(env, p_result_callback);
658
659
jint result = env->CallIntMethod(godot_instance, _build_env_execute, j_build_tool, j_args, j_project_path, j_gradle_build_directory, j_output_callback, j_result_callback);
660
661
env->DeleteLocalRef(j_build_tool);
662
env->DeleteLocalRef(j_args);
663
env->DeleteLocalRef(j_project_path);
664
env->DeleteLocalRef(j_gradle_build_directory);
665
env->DeleteLocalRef(j_output_callback);
666
env->DeleteLocalRef(j_result_callback);
667
668
return result;
669
}
670
671
return -1;
672
}
673
674
void GodotJavaWrapper::build_env_cancel(int p_job_id) {
675
if (_build_env_cancel) {
676
JNIEnv *env = get_jni_env();
677
ERR_FAIL_NULL(env);
678
env->CallVoidMethod(godot_instance, _build_env_cancel, p_job_id);
679
}
680
}
681
682
void GodotJavaWrapper::build_env_clean_project(const String &p_project_path, const String &p_gradle_build_directory, const Callable &p_callback) {
683
if (_build_env_clean_project) {
684
JNIEnv *env = get_jni_env();
685
ERR_FAIL_NULL(env);
686
687
jstring j_project_path = env->NewStringUTF(p_project_path.utf8().get_data());
688
jstring j_gradle_build_directory = env->NewStringUTF(p_gradle_build_directory.utf8().get_data());
689
jobject j_callback = callable_to_jcallable(env, p_callback);
690
691
env->CallVoidMethod(godot_instance, _build_env_clean_project, j_project_path, j_gradle_build_directory, j_callback);
692
693
env->DeleteLocalRef(j_project_path);
694
env->DeleteLocalRef(j_gradle_build_directory);
695
env->DeleteLocalRef(j_callback);
696
}
697
}
698
699