@nayan-ui/engine 1.0.0-beta.5 → 1.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +95 -4
  2. package/lib/module/assets/ProceduralCache.js +5 -0
  3. package/lib/module/assets/loft.js +15 -63
  4. package/lib/module/assets/procedural.js +500 -0
  5. package/lib/module/assets/shape.js +147 -245
  6. package/lib/module/assets/texture.js +65 -0
  7. package/lib/module/drawing/DrawingDocument.js +1 -1
  8. package/lib/module/index.js +4 -1
  9. package/lib/module/media/audio-worklet.js +27 -0
  10. package/lib/module/media/audio.js +20 -0
  11. package/lib/module/media/input.web.js +107 -0
  12. package/lib/module/media/microphone.js +89 -0
  13. package/lib/module/media/speech.js +80 -0
  14. package/lib/module/media/speechPlatform.js +12 -0
  15. package/lib/module/media/speechPlatform.web.js +16 -0
  16. package/lib/module/native/BrowserEngine.js +122 -0
  17. package/lib/module/native/NativeNayanEngine.web.js +2 -0
  18. package/lib/module/render/GameView.js +45 -13
  19. package/lib/module/render/quality.js +151 -17
  20. package/lib/module/world/World.js +63 -0
  21. package/lib/typescript/src/assets/ProceduralCache.d.ts +2 -0
  22. package/lib/typescript/src/assets/loft.d.ts +3 -1
  23. package/lib/typescript/src/assets/procedural.d.ts +394 -0
  24. package/lib/typescript/src/assets/shape.d.ts +13 -7
  25. package/lib/typescript/src/assets/texture.d.ts +63 -0
  26. package/lib/typescript/src/index.d.ts +8 -2
  27. package/lib/typescript/src/media/audio.d.ts +13 -0
  28. package/lib/typescript/src/media/input.web.d.ts +4 -0
  29. package/lib/typescript/src/media/microphone.d.ts +51 -0
  30. package/lib/typescript/src/media/speech.d.ts +38 -0
  31. package/lib/typescript/src/media/speechPlatform.d.ts +5 -0
  32. package/lib/typescript/src/media/speechPlatform.web.d.ts +5 -0
  33. package/lib/typescript/src/native/EngineBridge.d.ts +7 -1
  34. package/lib/typescript/src/native/spec/NativeNayanEngine.d.ts +72 -0
  35. package/lib/typescript/src/render/GameView.d.ts +30 -3
  36. package/lib/typescript/src/render/quality.d.ts +54 -2
  37. package/lib/typescript/src/types.d.ts +9 -2
  38. package/lib/typescript/src/world/World.d.ts +16 -0
  39. package/lib/typescript/src/world/types.d.ts +8 -0
  40. package/lib/web/audio-worklet.js +27 -0
  41. package/lib/web/engine_core_bg.wasm +0 -0
  42. package/lib/web/index.js +1181 -422
  43. package/lib/web/types/src/assets/ProceduralCache.d.ts +2 -0
  44. package/lib/web/types/src/assets/loft.d.ts +3 -1
  45. package/lib/web/types/src/assets/procedural.d.ts +393 -0
  46. package/lib/web/types/src/assets/shape.d.ts +13 -7
  47. package/lib/web/types/src/assets/texture.d.ts +63 -0
  48. package/lib/web/types/src/index.d.ts +8 -2
  49. package/lib/web/types/src/media/audio.d.ts +13 -0
  50. package/lib/web/types/src/media/input.d.ts +3 -0
  51. package/lib/web/types/src/media/microphone.d.ts +50 -0
  52. package/lib/web/types/src/media/speech.d.ts +37 -0
  53. package/lib/web/types/src/media/speechPlatform.d.ts +4 -0
  54. package/lib/web/types/src/native/EngineBridge.d.ts +7 -1
  55. package/lib/web/types/src/native/spec/NativeNayanEngine.d.ts +72 -0
  56. package/lib/web/types/src/render/GameView.d.ts +30 -3
  57. package/lib/web/types/src/render/quality.d.ts +54 -2
  58. package/lib/web/types/src/types.d.ts +9 -2
  59. package/lib/web/types/src/world/World.d.ts +16 -0
  60. package/lib/web/types/src/world/types.d.ts +8 -0
  61. package/native/android/src/main/AndroidManifest.xml +10 -0
  62. package/native/android/src/main/java/com/nayanui/engine/EngineMicrophone.java +60 -0
  63. package/native/android/src/main/java/com/nayanui/engine/EngineSpeech.java +28 -0
  64. package/native/android/src/main/java/com/nayanui/engine/EngineSurfaceView.java +1 -0
  65. package/native/android/src/main/java/com/nayanui/engine/NayanEnginePackage.java +2 -0
  66. package/native/core/build/EngineCore.xcframework/ios-arm64/libengine_core.a +0 -0
  67. package/native/core/build/EngineCore.xcframework/ios-arm64-simulator/libengine_core.a +0 -0
  68. package/native/core/build/android/arm64-v8a/libengine_core.a +0 -0
  69. package/native/core/build/android/armeabi-v7a/libengine_core.a +0 -0
  70. package/native/core/build/android/x86/libengine_core.a +0 -0
  71. package/native/core/build/android/x86_64/libengine_core.a +0 -0
  72. package/native/core/include/engine_core.h +63 -1
  73. package/native/cpp/NayanEngineModule.cpp +296 -0
  74. package/native/cpp/NayanEngineModule.h +40 -0
  75. package/native/cpp/generated/NayanEngineSpecJSI.h +397 -0
  76. package/package.json +1 -1
  77. package/src/native/spec/NativeNayanEngine.ts +77 -0
@@ -186,6 +186,7 @@ NayanEngineModule::NayanEngineModule(std::shared_ptr<CallInvoker> jsInvoker)
186
186
 
187
187
  // Worlds are freed when the module and every buffer aliasing them are gone.
188
188
  NayanEngineModule::~NayanEngineModule() {
189
+ engine_speech_shutdown();
189
190
  {
190
191
  std::lock_guard<std::mutex> lock(framesMutex);
191
192
  liveModules.erase(this);
@@ -564,6 +565,20 @@ jsi::Array NayanEngineModule::modelSize(jsi::Runtime &rt, double mesh) {
564
565
  return jsi::Array::createWithElements(rt, size[0], size[1], size[2]);
565
566
  }
566
567
 
568
+ jsi::Array NayanEngineModule::modelBake(jsi::Runtime &rt, double mesh, jsi::String spec) {
569
+ const auto json = spec.utf8(rt);
570
+ float out[4] = {0, 0, 0, 0};
571
+ if (!engine_model_bake(id(mesh), reinterpret_cast<const uint8_t *>(json.data()), json.size(), out)) {
572
+ return jsi::Array(rt, 0);
573
+ }
574
+ return jsi::Array::createWithElements(rt, out[0], out[1], out[2], out[3]);
575
+ }
576
+
577
+ bool NayanEngineModule::bakeKept(jsi::Runtime &rt, jsi::String key) {
578
+ const auto k = key.utf8(rt);
579
+ return engine_bake_kept(reinterpret_cast<const uint8_t *>(k.data()), k.size()) != 0;
580
+ }
581
+
567
582
  double NayanEngineModule::modelTexture(jsi::Runtime &, double mesh) {
568
583
  return engine_model_texture(id(mesh));
569
584
  }
@@ -838,6 +853,19 @@ void NayanEngineModule::renderOverlay(
838
853
  static_cast<float>(width), static_cast<float>(height));
839
854
  }
840
855
 
856
+ void NayanEngineModule::renderBackdrop(
857
+ jsi::Runtime &rt, double surface, jsi::Object matrices, jsi::Object colors, jsi::Object regions, jsi::Object ranges, double count) {
858
+ jsi::ArrayBuffer m = fileData(rt, matrices, "renderBackdrop");
859
+ jsi::ArrayBuffer c = fileData(rt, colors, "renderBackdrop");
860
+ jsi::ArrayBuffer g = fileData(rt, regions, "renderBackdrop");
861
+ jsi::ArrayBuffer r = fileData(rt, ranges, "renderBackdrop");
862
+ size_t capacity = std::min({m.size(rt) / (16 * sizeof(float)), c.size(rt) / (4 * sizeof(float)), g.size(rt) / (4 * sizeof(float))});
863
+ size_t n = count > 0 ? std::min(static_cast<size_t>(count), capacity) : 0;
864
+ engine_render_backdrop(
865
+ static_cast<int32_t>(surface), reinterpret_cast<const float *>(m.data(rt)), reinterpret_cast<const float *>(c.data(rt)),
866
+ reinterpret_cast<const float *>(g.data(rt)), capacity, reinterpret_cast<const uint32_t *>(r.data(rt)), r.size(rt) / sizeof(uint32_t), n);
867
+ }
868
+
841
869
  jsi::String NayanEngineModule::renderError(jsi::Runtime &rt) {
842
870
  std::string message(engine_render_error(nullptr, 0) + 1, '\0');
843
871
  message.resize(engine_render_error(message.data(), message.size()));
@@ -901,6 +929,97 @@ bool NayanEngineModule::audioIsRunning(jsi::Runtime &) {
901
929
  return engine_audio_is_running() != 0;
902
930
  }
903
931
 
932
+ void NayanEngineModule::audioRelease(jsi::Runtime &, double sound) {
933
+ engine_audio_release(id(sound));
934
+ }
935
+
936
+ double NayanEngineModule::audioDuration(jsi::Runtime &, double sound) {
937
+ return engine_audio_duration(id(sound));
938
+ }
939
+
940
+ jsi::Object NayanEngineModule::audioLevels(jsi::Runtime &rt, double sound, double perSecond) {
941
+ const uint32_t s = id(sound);
942
+ const size_t count = engine_audio_levels(s, static_cast<float>(perSecond), nullptr, 0);
943
+ auto buffer = std::make_shared<OwnedBuffer>(count * sizeof(float));
944
+ engine_audio_levels(s, static_cast<float>(perSecond), reinterpret_cast<float *>(buffer->data()), count);
945
+ return jsi::ArrayBuffer(rt, buffer);
946
+ }
947
+
948
+ namespace {
949
+ // A pending microphone prompt: the promise it resolves, owned until the answer arrives.
950
+ using MicPromise = AsyncPromise<bool>;
951
+
952
+ #ifndef __ANDROID__
953
+ void micAnswered(void *context, int32_t granted) {
954
+ std::unique_ptr<std::shared_ptr<MicPromise>> promise(static_cast<std::shared_ptr<MicPromise> *>(context));
955
+ (*promise)->resolve(granted != 0);
956
+ }
957
+ #endif
958
+
959
+ #ifdef __ANDROID__
960
+ facebook::jni::alias_ref<facebook::jni::JClass> microphoneClass() {
961
+ static auto cls = facebook::jni::findClassStatic("com/nayanui/engine/EngineMicrophone");
962
+ return cls;
963
+ }
964
+ #endif
965
+ } // namespace
966
+
967
+ double NayanEngineModule::micPermission(jsi::Runtime &) {
968
+ #ifdef __ANDROID__
969
+ try {
970
+ static const auto permission = microphoneClass()->getStaticMethod<jint()>("permission");
971
+ return permission(microphoneClass());
972
+ } catch (...) {
973
+ return 0;
974
+ }
975
+ #else
976
+ return engine_audio_mic_permission();
977
+ #endif
978
+ }
979
+
980
+ jsi::Value NayanEngineModule::micRequestPermission(jsi::Runtime &rt) {
981
+ auto promise = std::make_shared<MicPromise>(rt, jsInvoker_);
982
+ jsi::Value result(rt, promise->get(rt));
983
+ #ifdef __ANDROID__
984
+ // Java answers through nativePermissionResult(token, granted) below, which frees the token.
985
+ auto *token = new std::shared_ptr<MicPromise>(promise);
986
+ try {
987
+ static const auto request = microphoneClass()->getStaticMethod<void(jlong)>("request");
988
+ request(microphoneClass(), static_cast<jlong>(reinterpret_cast<intptr_t>(token)));
989
+ } catch (...) {
990
+ delete token;
991
+ promise->resolve(false);
992
+ }
993
+ #else
994
+ engine_audio_mic_request(micAnswered, new std::shared_ptr<MicPromise>(promise));
995
+ #endif
996
+ return result;
997
+ }
998
+
999
+ bool NayanEngineModule::micStart(jsi::Runtime &, double maxSeconds) {
1000
+ return engine_audio_mic_start(static_cast<float>(maxSeconds)) != 0;
1001
+ }
1002
+
1003
+ void NayanEngineModule::micStop(jsi::Runtime &) {
1004
+ engine_audio_mic_stop();
1005
+ }
1006
+
1007
+ double NayanEngineModule::micState(jsi::Runtime &) {
1008
+ return engine_audio_mic_state();
1009
+ }
1010
+
1011
+ double NayanEngineModule::micLevel(jsi::Runtime &) {
1012
+ return engine_audio_mic_level();
1013
+ }
1014
+
1015
+ double NayanEngineModule::micHeld(jsi::Runtime &) {
1016
+ return engine_audio_mic_held();
1017
+ }
1018
+
1019
+ double NayanEngineModule::micTake(jsi::Runtime &, double seconds, double skipEnd) {
1020
+ return engine_audio_mic_take(static_cast<float>(seconds), static_cast<float>(skipEnd));
1021
+ }
1022
+
904
1023
  bool NayanEngineModule::hapticsSupported(jsi::Runtime &) {
905
1024
  return engine_haptics_supported() != 0;
906
1025
  }
@@ -915,6 +1034,158 @@ void NayanEngineModule::hapticsPlay(jsi::Runtime &rt, jsi::Array taps, bool thro
915
1034
  engine_haptics_play(values.data(), static_cast<uint32_t>(n / 3), throttle ? 1 : 0);
916
1035
  }
917
1036
 
1037
+ // Procedural worlds. Handles are the core's own (u32, 0 = none); no JSI object owns them.
1038
+
1039
+ namespace {
1040
+
1041
+ uint32_t handle(double v) {
1042
+ return (v >= 0 && v <= static_cast<double>(UINT32_MAX)) ? static_cast<uint32_t>(v) : 0;
1043
+ }
1044
+
1045
+ const uint8_t *utf8(const std::string &text) {
1046
+ return reinterpret_cast<const uint8_t *>(text.data());
1047
+ }
1048
+
1049
+ /** A core function's f64 output (two calls: size, then copy) as an owned ArrayBuffer. */
1050
+ jsi::Object doubles(jsi::Runtime &rt, const std::function<size_t(double *, size_t)> &read) {
1051
+ const size_t count = read(nullptr, 0);
1052
+ auto out = std::make_shared<OwnedBuffer>(count * sizeof(double));
1053
+ if (count > 0 && read(reinterpret_cast<double *>(out->data()), count) != count) {
1054
+ throw jsi::JSError(rt, "NayanEngine worldgen: output changed while reading");
1055
+ }
1056
+ return jsi::ArrayBuffer(rt, std::move(out));
1057
+ }
1058
+
1059
+ std::string text(const std::function<size_t(uint8_t *, size_t)> &read) {
1060
+ std::string out(read(nullptr, 0), '\0');
1061
+ if (!out.empty()) read(reinterpret_cast<uint8_t *>(out.data()), out.size() + 1);
1062
+ return out;
1063
+ }
1064
+
1065
+ } // namespace
1066
+
1067
+ double NayanEngineModule::worldgenBuild(jsi::Runtime &rt, jsi::String recipe, jsi::String key, bool prepareTerrain) {
1068
+ const auto r = recipe.utf8(rt), k = key.utf8(rt);
1069
+ return engine_worldgen_build(utf8(r), r.size(), utf8(k), k.size(), prepareTerrain ? 1 : 0);
1070
+ }
1071
+
1072
+ jsi::Value NayanEngineModule::worldgenBuildAsync(jsi::Runtime &rt, jsi::String recipe, jsi::String key, bool prepareTerrain) {
1073
+ auto r = std::make_shared<std::string>(recipe.utf8(rt));
1074
+ auto k = std::make_shared<std::string>(key.utf8(rt));
1075
+ return runInBackground(rt, jsInvoker_, [r, k, prepareTerrain]() {
1076
+ return static_cast<double>(engine_worldgen_build(utf8(*r), r->size(), utf8(*k), k->size(), prepareTerrain ? 1 : 0));
1077
+ });
1078
+ }
1079
+
1080
+ jsi::String NayanEngineModule::worldgenError(jsi::Runtime &rt) {
1081
+ return jsi::String::createFromUtf8(rt, text([](uint8_t *out, size_t cap) { return engine_worldgen_error(out, cap); }));
1082
+ }
1083
+
1084
+ bool NayanEngineModule::worldgenKept(jsi::Runtime &rt, jsi::String key) {
1085
+ const auto k = key.utf8(rt);
1086
+ return engine_worldgen_kept(utf8(k), k.size()) != 0;
1087
+ }
1088
+
1089
+ void NayanEngineModule::worldgenFree(jsi::Runtime &, double world) {
1090
+ engine_worldgen_free(handle(world));
1091
+ }
1092
+
1093
+ jsi::String NayanEngineModule::worldgenInfo(jsi::Runtime &rt, double world) {
1094
+ const uint32_t w = handle(world);
1095
+ return jsi::String::createFromUtf8(rt, text([w](uint8_t *out, size_t cap) { return engine_worldgen_info(w, out, cap); }));
1096
+ }
1097
+
1098
+ jsi::Object NayanEngineModule::worldgenLayer(jsi::Runtime &rt, double world, jsi::String name) {
1099
+ const uint32_t w = handle(world);
1100
+ const auto n = name.utf8(rt);
1101
+ return doubles(rt, [w, &n](double *out, size_t cap) { return engine_worldgen_layer(w, utf8(n), n.size(), out, cap); });
1102
+ }
1103
+
1104
+ jsi::Object NayanEngineModule::worldgenReachable(jsi::Runtime &rt, double world) {
1105
+ const uint32_t w = handle(world);
1106
+ return doubles(rt, [w](double *out, size_t cap) { return engine_worldgen_reachable(w, out, cap); });
1107
+ }
1108
+
1109
+ jsi::Object NayanEngineModule::worldgenOverview(jsi::Runtime &rt, double world) {
1110
+ const uint32_t w = handle(world);
1111
+ const size_t count = engine_worldgen_overview(w, nullptr, 0);
1112
+ auto out = std::make_shared<OwnedBuffer>(count);
1113
+ if (count > 0) engine_worldgen_overview(w, out->data(), count);
1114
+ return jsi::ArrayBuffer(rt, std::move(out));
1115
+ }
1116
+
1117
+ bool NayanEngineModule::worldgenPick(jsi::Runtime &, double world, double run) {
1118
+ return engine_worldgen_pick(handle(world), handle(run)) != 0;
1119
+ }
1120
+
1121
+ jsi::Object NayanEngineModule::worldgenTerrain(jsi::Runtime &rt, double world, double material) {
1122
+ return geometryResult(rt, engine_worldgen_terrain(handle(world), handle(material)));
1123
+ }
1124
+
1125
+ jsi::Object NayanEngineModule::worldgenMesh(jsi::Runtime &rt, jsi::String recipe) {
1126
+ const auto r = recipe.utf8(rt);
1127
+ return geometryResult(rt, engine_worldgen_mesh(utf8(r), r.size()));
1128
+ }
1129
+
1130
+ bool NayanEngineModule::worldgenPaint(jsi::Runtime &rt, jsi::Object vertices, jsi::String recipe) {
1131
+ jsi::ArrayBuffer v = fileData(rt, vertices, "worldgenPaint");
1132
+ if (v.size(rt) % (11 * sizeof(float)) != 0) {
1133
+ throw jsi::JSError(rt, "NayanEngine.worldgenPaint: incomplete vertices");
1134
+ }
1135
+ const auto r = recipe.utf8(rt);
1136
+ return engine_worldgen_paint(reinterpret_cast<float *>(v.data(rt)), v.size(rt) / (11 * sizeof(float)), utf8(r), r.size()) != 0;
1137
+ }
1138
+
1139
+ double NayanEngineModule::worldgenGround(jsi::Runtime &, double world, double x, double z) {
1140
+ return engine_worldgen_ground(handle(world), x, z);
1141
+ }
1142
+
1143
+ double NayanEngineModule::worldgenSurface(jsi::Runtime &, double world, double x, double z) {
1144
+ return engine_worldgen_surface(handle(world), x, z);
1145
+ }
1146
+
1147
+ double NayanEngineModule::worldgenPlatform(jsi::Runtime &, double world, double x, double z) {
1148
+ return engine_worldgen_platform(handle(world), x, z);
1149
+ }
1150
+
1151
+ bool NayanEngineModule::worldgenWalkable(jsi::Runtime &, double world, double x, double z, double radius) {
1152
+ return engine_worldgen_walkable(handle(world), x, z, radius) != 0;
1153
+ }
1154
+
1155
+ double NayanEngineModule::worldgenClearance(jsi::Runtime &, double world, double x, double z, double radius) {
1156
+ return engine_worldgen_clearance(handle(world), x, z, radius);
1157
+ }
1158
+
1159
+ double NayanEngineModule::worldgenSolidClearance(jsi::Runtime &, double world, double x, double z, double radius, double bottom, double top) {
1160
+ return engine_worldgen_solid_clearance(handle(world), x, z, radius, bottom, top);
1161
+ }
1162
+
1163
+ double NayanEngineModule::worldgenFieldIndex(jsi::Runtime &rt, double world, jsi::String name) {
1164
+ const auto n = name.utf8(rt);
1165
+ return engine_worldgen_field_index(handle(world), utf8(n), n.size());
1166
+ }
1167
+
1168
+ double NayanEngineModule::worldgenField(jsi::Runtime &, double world, double field, double x, double z) {
1169
+ return engine_worldgen_field(handle(world), handle(field), x, z);
1170
+ }
1171
+
1172
+ jsi::Array NayanEngineModule::worldgenTilt(jsi::Runtime &rt, double world, double x, double z, double yaw) {
1173
+ double q[4] = {0, 0, 0, 1};
1174
+ engine_worldgen_tilt(handle(world), x, z, yaw, q);
1175
+ return jsi::Array::createWithElements(rt, q[0], q[1], q[2], q[3]);
1176
+ }
1177
+
1178
+ bool NayanEngineModule::worldgenSight(jsi::Runtime &, double world, double ax, double az, double bx, double bz, double radius, double step, double rise) {
1179
+ return engine_worldgen_sight(handle(world), ax, az, bx, bz, radius, step, rise) != 0;
1180
+ }
1181
+
1182
+ jsi::Array NayanEngineModule::worldgenMove(jsi::Runtime &rt, double world, double x, double z, double dx, double dz, double radius, jsi::Object bodies) {
1183
+ auto list = fileData(rt, bodies, "worldgenMove");
1184
+ double point[2] = {x, z};
1185
+ engine_worldgen_move(handle(world), point, dx, dz, radius, reinterpret_cast<const double *>(list.data(rt)), list.size(rt) / (3 * sizeof(double)));
1186
+ return jsi::Array::createWithElements(rt, point[0], point[1]);
1187
+ }
1188
+
918
1189
  } // namespace facebook::react
919
1190
 
920
1191
  #ifdef __ANDROID__
@@ -963,6 +1234,13 @@ Java_com_nayanui_engine_EngineSurfaceView_nativeAttach(JNIEnv *env, jclass, jint
963
1234
  return engine_render_attach(surface, window, static_cast<uint32_t>(width), static_cast<uint32_t>(height)) == 1 ? JNI_TRUE : JNI_FALSE;
964
1235
  }
965
1236
 
1237
+ /** EngineMicrophone's answer to micRequestPermission: resolves the promise and frees its token. */
1238
+ extern "C" JNIEXPORT void JNICALL Java_com_nayanui_engine_EngineMicrophone_nativePermissionResult(JNIEnv *, jclass, jlong token, jboolean granted) {
1239
+ std::unique_ptr<std::shared_ptr<facebook::react::AsyncPromise<bool>>> promise(
1240
+ reinterpret_cast<std::shared_ptr<facebook::react::AsyncPromise<bool>> *>(static_cast<intptr_t>(token)));
1241
+ if (promise) (*promise)->resolve(granted == JNI_TRUE);
1242
+ }
1243
+
966
1244
  extern "C" JNIEXPORT void JNICALL Java_com_nayanui_engine_EngineSurfaceView_nativeDetach(JNIEnv *, jclass, jint surface) {
967
1245
  releaseWindow(surface);
968
1246
  }
@@ -996,3 +1274,21 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_nayanui_engine_EngineSurfaceVie
996
1274
  return result;
997
1275
  }
998
1276
  #endif
1277
+
1278
+ namespace {
1279
+ void speechAnswered(void *context, const uint8_t *data, size_t len) {
1280
+ using Promise = facebook::react::AsyncPromise<std::string>;
1281
+ std::unique_ptr<std::shared_ptr<Promise>> promise(static_cast<std::shared_ptr<Promise> *>(context));
1282
+ (*promise)->resolve(std::string(reinterpret_cast<const char *>(data), len));
1283
+ }
1284
+ }
1285
+ namespace facebook::react {
1286
+ jsi::Value NayanEngineModule::speechRequest(jsi::Runtime &rt, jsi::String command) {
1287
+ auto promise = std::make_shared<AsyncPromise<std::string>>(rt, jsInvoker_);
1288
+ jsi::Value result(rt, promise->get(rt));
1289
+ const std::string text = command.utf8(rt);
1290
+ engine_speech_request(reinterpret_cast<const uint8_t *>(text.data()), text.size(), speechAnswered,
1291
+ new std::shared_ptr<AsyncPromise<std::string>>(promise));
1292
+ return result;
1293
+ }
1294
+ }
@@ -15,6 +15,8 @@ class NayanEngineModule : public NativeNayanEngineCxxSpec<NayanEngineModule> {
15
15
  explicit NayanEngineModule(std::shared_ptr<CallInvoker> jsInvoker);
16
16
  ~NayanEngineModule();
17
17
 
18
+ jsi::Value speechRequest(jsi::Runtime &rt, jsi::String command);
19
+
18
20
  double createWorld(jsi::Runtime &rt, double capacity);
19
21
  void destroyWorld(jsi::Runtime &rt, double world);
20
22
  double spawnDesc(jsi::Runtime &rt, double world, jsi::Object desc);
@@ -67,6 +69,8 @@ class NayanEngineModule : public NativeNayanEngineCxxSpec<NayanEngineModule> {
67
69
  jsi::Object modelVertices(jsi::Runtime &rt, double mesh);
68
70
  jsi::Object modelIndices(jsi::Runtime &rt, double mesh);
69
71
  jsi::Array modelSize(jsi::Runtime &rt, double mesh);
72
+ jsi::Array modelBake(jsi::Runtime &rt, double mesh, jsi::String spec);
73
+ bool bakeKept(jsi::Runtime &rt, jsi::String key);
70
74
  double modelTexture(jsi::Runtime &rt, double mesh);
71
75
  double meshAlias(jsi::Runtime &rt, double base);
72
76
  double meshCreate(jsi::Runtime &rt, jsi::Object vertices, jsi::Object indices);
@@ -137,6 +141,7 @@ class NayanEngineModule : public NativeNayanEngineCxxSpec<NayanEngineModule> {
137
141
  double count,
138
142
  double width,
139
143
  double height);
144
+ void renderBackdrop(jsi::Runtime &rt, double surface, jsi::Object matrices, jsi::Object colors, jsi::Object regions, jsi::Object ranges, double count);
140
145
  jsi::String renderError(jsi::Runtime &rt);
141
146
  jsi::String renderBackend(jsi::Runtime &rt);
142
147
  double drawingCreate(jsi::Runtime &rt, double width, double height, double ratio);
@@ -149,8 +154,43 @@ class NayanEngineModule : public NativeNayanEngineCxxSpec<NayanEngineModule> {
149
154
  void audioSetVolume(jsi::Runtime &rt, double volume);
150
155
  void audioSetMuted(jsi::Runtime &rt, bool muted);
151
156
  bool audioIsRunning(jsi::Runtime &rt);
157
+ void audioRelease(jsi::Runtime &rt, double sound);
158
+ double audioDuration(jsi::Runtime &rt, double sound);
159
+ jsi::Object audioLevels(jsi::Runtime &rt, double sound, double perSecond);
160
+ double micPermission(jsi::Runtime &rt);
161
+ jsi::Value micRequestPermission(jsi::Runtime &rt);
162
+ bool micStart(jsi::Runtime &rt, double maxSeconds);
163
+ void micStop(jsi::Runtime &rt);
164
+ double micState(jsi::Runtime &rt);
165
+ double micLevel(jsi::Runtime &rt);
166
+ double micHeld(jsi::Runtime &rt);
167
+ double micTake(jsi::Runtime &rt, double seconds, double skipEnd);
152
168
  bool hapticsSupported(jsi::Runtime &rt);
153
169
  void hapticsPlay(jsi::Runtime &rt, jsi::Array taps, bool throttle);
170
+ double worldgenBuild(jsi::Runtime &rt, jsi::String recipe, jsi::String key, bool prepareTerrain);
171
+ jsi::Value worldgenBuildAsync(jsi::Runtime &rt, jsi::String recipe, jsi::String key, bool prepareTerrain);
172
+ jsi::String worldgenError(jsi::Runtime &rt);
173
+ bool worldgenKept(jsi::Runtime &rt, jsi::String key);
174
+ void worldgenFree(jsi::Runtime &rt, double world);
175
+ jsi::String worldgenInfo(jsi::Runtime &rt, double world);
176
+ jsi::Object worldgenLayer(jsi::Runtime &rt, double world, jsi::String name);
177
+ jsi::Object worldgenReachable(jsi::Runtime &rt, double world);
178
+ jsi::Object worldgenOverview(jsi::Runtime &rt, double world);
179
+ bool worldgenPick(jsi::Runtime &rt, double world, double run);
180
+ jsi::Object worldgenTerrain(jsi::Runtime &rt, double world, double material);
181
+ jsi::Object worldgenMesh(jsi::Runtime &rt, jsi::String recipe);
182
+ bool worldgenPaint(jsi::Runtime &rt, jsi::Object vertices, jsi::String recipe);
183
+ double worldgenGround(jsi::Runtime &rt, double world, double x, double z);
184
+ double worldgenSurface(jsi::Runtime &rt, double world, double x, double z);
185
+ double worldgenPlatform(jsi::Runtime &rt, double world, double x, double z);
186
+ bool worldgenWalkable(jsi::Runtime &rt, double world, double x, double z, double radius);
187
+ double worldgenClearance(jsi::Runtime &rt, double world, double x, double z, double radius);
188
+ double worldgenSolidClearance(jsi::Runtime &rt, double world, double x, double z, double radius, double bottom, double top);
189
+ double worldgenFieldIndex(jsi::Runtime &rt, double world, jsi::String name);
190
+ double worldgenField(jsi::Runtime &rt, double world, double field, double x, double z);
191
+ jsi::Array worldgenTilt(jsi::Runtime &rt, double world, double x, double z, double yaw);
192
+ bool worldgenSight(jsi::Runtime &rt, double world, double ax, double az, double bx, double bz, double radius, double step, double rise);
193
+ jsi::Array worldgenMove(jsi::Runtime &rt, double world, double x, double z, double dx, double dz, double radius, jsi::Object bodies);
154
194
 
155
195
  private:
156
196
  std::shared_ptr<::World> owner(double id) const;