@nayan-ui/engine 1.0.0-beta.3 → 1.0.0-beta.4
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.
- package/README.md +167 -69
- package/lib/module/assets/AssetLoader.js +1 -1
- package/lib/module/assets/ProceduralCache.js +31 -4
- package/lib/module/assets/font.js +10 -7
- package/lib/module/assets/model.js +41 -19
- package/lib/module/assets/storage.shared.js +2 -0
- package/lib/module/assets/storage.web.js +1 -0
- package/lib/module/assets/texture.js +14 -11
- package/lib/module/index.js +4 -1
- package/lib/module/media/audio.js +6 -3
- package/lib/module/native/BrowserEngine.js +17 -0
- package/lib/module/render/GameView.js +86 -18
- package/lib/module/render/light.js +24 -0
- package/lib/module/render/quality.js +12 -5
- package/lib/module/render/useWorld.js +72 -0
- package/lib/module/world/Scoreboard.js +21 -3
- package/lib/module/world/TransformBatch.js +5 -3
- package/lib/module/world/World.js +27 -13
- package/lib/module/world/color.js +80 -0
- package/lib/module/world/desc.js +6 -5
- package/lib/module/world/effects.js +20 -8
- package/lib/typescript/src/assets/AssetLoader.d.ts +1 -1
- package/lib/typescript/src/assets/ProceduralCache.d.ts +12 -0
- package/lib/typescript/src/assets/model.d.ts +10 -0
- package/lib/typescript/src/index.d.ts +4 -1
- package/lib/typescript/src/native/EngineBridge.d.ts +6 -2
- package/lib/typescript/src/native/spec/NativeNayanEngine.d.ts +29 -0
- package/lib/typescript/src/render/GameView.d.ts +19 -7
- package/lib/typescript/src/render/light.d.ts +12 -0
- package/lib/typescript/src/render/quality.d.ts +4 -2
- package/lib/typescript/src/render/useWorld.d.ts +20 -0
- package/lib/typescript/src/types.d.ts +13 -4
- package/lib/typescript/src/world/Scoreboard.d.ts +12 -2
- package/lib/typescript/src/world/TransformBatch.d.ts +2 -2
- package/lib/typescript/src/world/World.d.ts +10 -2
- package/lib/typescript/src/world/color.d.ts +18 -0
- package/lib/typescript/src/world/effects.d.ts +13 -12
- package/lib/typescript/src/world/types.d.ts +11 -6
- package/lib/web/engine_core_bg.wasm +0 -0
- package/lib/web/index.js +521 -255
- package/lib/web/types/src/assets/AssetLoader.d.ts +1 -1
- package/lib/web/types/src/assets/ProceduralCache.d.ts +12 -0
- package/lib/web/types/src/assets/model.d.ts +10 -0
- package/lib/web/types/src/index.d.ts +4 -1
- package/lib/web/types/src/native/EngineBridge.d.ts +6 -2
- package/lib/web/types/src/native/spec/NativeNayanEngine.d.ts +29 -0
- package/lib/web/types/src/render/GameView.d.ts +19 -7
- package/lib/web/types/src/render/light.d.ts +11 -0
- package/lib/web/types/src/render/quality.d.ts +4 -2
- package/lib/web/types/src/render/useWorld.d.ts +19 -0
- package/lib/web/types/src/types.d.ts +13 -4
- package/lib/web/types/src/world/Scoreboard.d.ts +12 -2
- package/lib/web/types/src/world/TransformBatch.d.ts +2 -2
- package/lib/web/types/src/world/World.d.ts +10 -2
- package/lib/web/types/src/world/color.d.ts +17 -0
- package/lib/web/types/src/world/effects.d.ts +13 -12
- package/lib/web/types/src/world/types.d.ts +11 -6
- package/native/android/src/main/java/com/nayanui/engine/EngineSurfaceView.java +87 -26
- package/native/core/build/EngineCore.xcframework/ios-arm64/libengine_core.a +0 -0
- package/native/core/build/EngineCore.xcframework/ios-arm64-simulator/libengine_core.a +0 -0
- package/native/core/build/android/arm64-v8a/libengine_core.a +0 -0
- package/native/core/build/android/armeabi-v7a/libengine_core.a +0 -0
- package/native/core/build/android/x86/libengine_core.a +0 -0
- package/native/core/build/android/x86_64/libengine_core.a +0 -0
- package/native/core/include/engine_core.h +9 -0
- package/native/cpp/NayanEngineModule.cpp +171 -0
- package/native/cpp/NayanEngineModule.h +30 -0
- package/native/cpp/generated/NayanEngineSpecJSI.h +105 -0
- package/native/ios/NayanEngineSurface.mm +30 -1
- package/package.json +2 -2
- package/src/native/spec/NativeNayanEngine.ts +39 -0
|
@@ -70,12 +70,14 @@ protected:
|
|
|
70
70
|
methodMap_["shapePrepare"] = MethodMetadata {.argCount = 3, .invoker = __shapePrepare};
|
|
71
71
|
methodMap_["solidPrepare"] = MethodMetadata {.argCount = 2, .invoker = __solidPrepare};
|
|
72
72
|
methodMap_["modelLoad"] = MethodMetadata {.argCount = 3, .invoker = __modelLoad};
|
|
73
|
+
methodMap_["modelLoadAsync"] = MethodMetadata {.argCount = 3, .invoker = __modelLoadAsync};
|
|
73
74
|
methodMap_["modelVertices"] = MethodMetadata {.argCount = 1, .invoker = __modelVertices};
|
|
74
75
|
methodMap_["modelIndices"] = MethodMetadata {.argCount = 1, .invoker = __modelIndices};
|
|
75
76
|
methodMap_["modelSize"] = MethodMetadata {.argCount = 1, .invoker = __modelSize};
|
|
76
77
|
methodMap_["modelTexture"] = MethodMetadata {.argCount = 1, .invoker = __modelTexture};
|
|
77
78
|
methodMap_["meshAlias"] = MethodMetadata {.argCount = 1, .invoker = __meshAlias};
|
|
78
79
|
methodMap_["meshCreate"] = MethodMetadata {.argCount = 2, .invoker = __meshCreate};
|
|
80
|
+
methodMap_["renderModel"] = MethodMetadata {.argCount = 3, .invoker = __renderModel};
|
|
79
81
|
methodMap_["pathExtrude"] = MethodMetadata {.argCount = 4, .invoker = __pathExtrude};
|
|
80
82
|
methodMap_["geometrySmoothNormals"] = MethodMetadata {.argCount = 2, .invoker = __geometrySmoothNormals};
|
|
81
83
|
methodMap_["geometrySolid"] = MethodMetadata {.argCount = 1, .invoker = __geometrySolid};
|
|
@@ -83,9 +85,11 @@ protected:
|
|
|
83
85
|
methodMap_["geometryFaceOutward"] = MethodMetadata {.argCount = 2, .invoker = __geometryFaceOutward};
|
|
84
86
|
methodMap_["geometryPlace"] = MethodMetadata {.argCount = 8, .invoker = __geometryPlace};
|
|
85
87
|
methodMap_["textureLoad"] = MethodMetadata {.argCount = 1, .invoker = __textureLoad};
|
|
88
|
+
methodMap_["textureLoadAsync"] = MethodMetadata {.argCount = 1, .invoker = __textureLoadAsync};
|
|
86
89
|
methodMap_["texturePixels"] = MethodMetadata {.argCount = 1, .invoker = __texturePixels};
|
|
87
90
|
methodMap_["textureSize"] = MethodMetadata {.argCount = 1, .invoker = __textureSize};
|
|
88
91
|
methodMap_["fontLoad"] = MethodMetadata {.argCount = 4, .invoker = __fontLoad};
|
|
92
|
+
methodMap_["fontLoadAsync"] = MethodMetadata {.argCount = 4, .invoker = __fontLoadAsync};
|
|
89
93
|
methodMap_["fontGlyphs"] = MethodMetadata {.argCount = 1, .invoker = __fontGlyphs};
|
|
90
94
|
methodMap_["loadError"] = MethodMetadata {.argCount = 0, .invoker = __loadError};
|
|
91
95
|
methodMap_["generateBuiltinMeshes"] = MethodMetadata {.argCount = 0, .invoker = __generateBuiltinMeshes};
|
|
@@ -94,6 +98,11 @@ protected:
|
|
|
94
98
|
methodMap_["renderMeshIndices"] = MethodMetadata {.argCount = 1, .invoker = __renderMeshIndices};
|
|
95
99
|
methodMap_["renderMesh"] = MethodMetadata {.argCount = 5, .invoker = __renderMesh};
|
|
96
100
|
methodMap_["renderFrame"] = MethodMetadata {.argCount = 9, .invoker = __renderFrame};
|
|
101
|
+
methodMap_["publishFrame"] = MethodMetadata {.argCount = 9, .invoker = __publishFrame};
|
|
102
|
+
methodMap_["renderStats"] = MethodMetadata {.argCount = 1, .invoker = __renderStats};
|
|
103
|
+
methodMap_["hasFrameClock"] = MethodMetadata {.argCount = 0, .invoker = __hasFrameClock};
|
|
104
|
+
methodMap_["startFrames"] = MethodMetadata {.argCount = 2, .invoker = __startFrames};
|
|
105
|
+
methodMap_["stopFrames"] = MethodMetadata {.argCount = 1, .invoker = __stopFrames};
|
|
97
106
|
methodMap_["renderOverlay"] = MethodMetadata {.argCount = 8, .invoker = __renderOverlay};
|
|
98
107
|
methodMap_["renderError"] = MethodMetadata {.argCount = 0, .invoker = __renderError};
|
|
99
108
|
methodMap_["renderBackend"] = MethodMetadata {.argCount = 0, .invoker = __renderBackend};
|
|
@@ -101,6 +110,7 @@ protected:
|
|
|
101
110
|
methodMap_["drawingCommand"] = MethodMetadata {.argCount = 2, .invoker = __drawingCommand};
|
|
102
111
|
methodMap_["drawingDestroy"] = MethodMetadata {.argCount = 1, .invoker = __drawingDestroy};
|
|
103
112
|
methodMap_["audioLoad"] = MethodMetadata {.argCount = 1, .invoker = __audioLoad};
|
|
113
|
+
methodMap_["audioLoadAsync"] = MethodMetadata {.argCount = 1, .invoker = __audioLoadAsync};
|
|
104
114
|
methodMap_["audioPlay"] = MethodMetadata {.argCount = 5, .invoker = __audioPlay};
|
|
105
115
|
methodMap_["audioStop"] = MethodMetadata {.argCount = 1, .invoker = __audioStop};
|
|
106
116
|
methodMap_["audioSetVolume"] = MethodMetadata {.argCount = 1, .invoker = __audioSetVolume};
|
|
@@ -573,6 +583,16 @@ private:
|
|
|
573
583
|
count <= 2 ? throw jsi::JSError(rt, "Expected argument in position 2 to be passed") : args[2].asNumber());
|
|
574
584
|
}
|
|
575
585
|
|
|
586
|
+
static jsi::Value __modelLoadAsync(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
587
|
+
static_assert(
|
|
588
|
+
bridging::getParameterCount(&T::modelLoadAsync) == 4,
|
|
589
|
+
"Expected modelLoadAsync(...) to have 4 parameters");
|
|
590
|
+
return bridging::callFromJs<jsi::Value>(rt, &T::modelLoadAsync, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
591
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt),
|
|
592
|
+
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asBool(),
|
|
593
|
+
count <= 2 ? throw jsi::JSError(rt, "Expected argument in position 2 to be passed") : args[2].asNumber());
|
|
594
|
+
}
|
|
595
|
+
|
|
576
596
|
static jsi::Value __modelVertices(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
577
597
|
static_assert(
|
|
578
598
|
bridging::getParameterCount(&T::modelVertices) == 2,
|
|
@@ -622,6 +642,16 @@ private:
|
|
|
622
642
|
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asObject(rt));
|
|
623
643
|
}
|
|
624
644
|
|
|
645
|
+
static jsi::Value __renderModel(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
646
|
+
static_assert(
|
|
647
|
+
bridging::getParameterCount(&T::renderModel) == 4,
|
|
648
|
+
"Expected renderModel(...) to have 4 parameters");
|
|
649
|
+
return bridging::callFromJs<bool>(rt, &T::renderModel, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
650
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber(),
|
|
651
|
+
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asNumber(),
|
|
652
|
+
count <= 2 ? throw jsi::JSError(rt, "Expected argument in position 2 to be passed") : args[2].asNumber());
|
|
653
|
+
}
|
|
654
|
+
|
|
625
655
|
static jsi::Value __pathExtrude(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
626
656
|
static_assert(
|
|
627
657
|
bridging::getParameterCount(&T::pathExtrude) == 5,
|
|
@@ -694,6 +724,14 @@ private:
|
|
|
694
724
|
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt));
|
|
695
725
|
}
|
|
696
726
|
|
|
727
|
+
static jsi::Value __textureLoadAsync(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
728
|
+
static_assert(
|
|
729
|
+
bridging::getParameterCount(&T::textureLoadAsync) == 2,
|
|
730
|
+
"Expected textureLoadAsync(...) to have 2 parameters");
|
|
731
|
+
return bridging::callFromJs<jsi::Value>(rt, &T::textureLoadAsync, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
732
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt));
|
|
733
|
+
}
|
|
734
|
+
|
|
697
735
|
static jsi::Value __texturePixels(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
698
736
|
static_assert(
|
|
699
737
|
bridging::getParameterCount(&T::texturePixels) == 2,
|
|
@@ -721,6 +759,17 @@ private:
|
|
|
721
759
|
count <= 3 ? throw jsi::JSError(rt, "Expected argument in position 3 to be passed") : args[3].asNumber());
|
|
722
760
|
}
|
|
723
761
|
|
|
762
|
+
static jsi::Value __fontLoadAsync(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
763
|
+
static_assert(
|
|
764
|
+
bridging::getParameterCount(&T::fontLoadAsync) == 5,
|
|
765
|
+
"Expected fontLoadAsync(...) to have 5 parameters");
|
|
766
|
+
return bridging::callFromJs<jsi::Value>(rt, &T::fontLoadAsync, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
767
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt),
|
|
768
|
+
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asNumber(),
|
|
769
|
+
count <= 2 ? throw jsi::JSError(rt, "Expected argument in position 2 to be passed") : args[2].asString(rt),
|
|
770
|
+
count <= 3 ? throw jsi::JSError(rt, "Expected argument in position 3 to be passed") : args[3].asNumber());
|
|
771
|
+
}
|
|
772
|
+
|
|
724
773
|
static jsi::Value __fontGlyphs(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
725
774
|
static_assert(
|
|
726
775
|
bridging::getParameterCount(&T::fontGlyphs) == 2,
|
|
@@ -794,6 +843,54 @@ private:
|
|
|
794
843
|
count <= 8 ? throw jsi::JSError(rt, "Expected argument in position 8 to be passed") : args[8].asNumber());
|
|
795
844
|
}
|
|
796
845
|
|
|
846
|
+
static jsi::Value __publishFrame(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
847
|
+
static_assert(
|
|
848
|
+
bridging::getParameterCount(&T::publishFrame) == 10,
|
|
849
|
+
"Expected publishFrame(...) to have 10 parameters");
|
|
850
|
+
return bridging::callFromJs<double>(rt, &T::publishFrame, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
851
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber(),
|
|
852
|
+
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asObject(rt),
|
|
853
|
+
count <= 2 ? throw jsi::JSError(rt, "Expected argument in position 2 to be passed") : args[2].asObject(rt),
|
|
854
|
+
count <= 3 ? throw jsi::JSError(rt, "Expected argument in position 3 to be passed") : args[3].asObject(rt),
|
|
855
|
+
count <= 4 ? throw jsi::JSError(rt, "Expected argument in position 4 to be passed") : args[4].asObject(rt),
|
|
856
|
+
count <= 5 ? throw jsi::JSError(rt, "Expected argument in position 5 to be passed") : args[5].asObject(rt),
|
|
857
|
+
count <= 6 ? throw jsi::JSError(rt, "Expected argument in position 6 to be passed") : args[6].asNumber(),
|
|
858
|
+
count <= 7 ? throw jsi::JSError(rt, "Expected argument in position 7 to be passed") : args[7].asObject(rt),
|
|
859
|
+
count <= 8 ? throw jsi::JSError(rt, "Expected argument in position 8 to be passed") : args[8].asNumber());
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
static jsi::Value __renderStats(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
863
|
+
static_assert(
|
|
864
|
+
bridging::getParameterCount(&T::renderStats) == 2,
|
|
865
|
+
"Expected renderStats(...) to have 2 parameters");
|
|
866
|
+
return bridging::callFromJs<jsi::Array>(rt, &T::renderStats, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
867
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber());
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
static jsi::Value __hasFrameClock(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* /*args*/, size_t /*count*/) {
|
|
871
|
+
static_assert(
|
|
872
|
+
bridging::getParameterCount(&T::hasFrameClock) == 1,
|
|
873
|
+
"Expected hasFrameClock(...) to have 1 parameters");
|
|
874
|
+
return bridging::callFromJs<bool>(rt, &T::hasFrameClock, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule));
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
static jsi::Value __startFrames(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
878
|
+
static_assert(
|
|
879
|
+
bridging::getParameterCount(&T::startFrames) == 3,
|
|
880
|
+
"Expected startFrames(...) to have 3 parameters");
|
|
881
|
+
bridging::callFromJs<void>(rt, &T::startFrames, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
882
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber(),
|
|
883
|
+
count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asObject(rt).asFunction(rt));return jsi::Value::undefined();
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
static jsi::Value __stopFrames(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
887
|
+
static_assert(
|
|
888
|
+
bridging::getParameterCount(&T::stopFrames) == 2,
|
|
889
|
+
"Expected stopFrames(...) to have 2 parameters");
|
|
890
|
+
bridging::callFromJs<void>(rt, &T::stopFrames, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
891
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber());return jsi::Value::undefined();
|
|
892
|
+
}
|
|
893
|
+
|
|
797
894
|
static jsi::Value __renderOverlay(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
798
895
|
static_assert(
|
|
799
896
|
bridging::getParameterCount(&T::renderOverlay) == 9,
|
|
@@ -858,6 +955,14 @@ private:
|
|
|
858
955
|
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt));
|
|
859
956
|
}
|
|
860
957
|
|
|
958
|
+
static jsi::Value __audioLoadAsync(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
959
|
+
static_assert(
|
|
960
|
+
bridging::getParameterCount(&T::audioLoadAsync) == 2,
|
|
961
|
+
"Expected audioLoadAsync(...) to have 2 parameters");
|
|
962
|
+
return bridging::callFromJs<jsi::Value>(rt, &T::audioLoadAsync, static_cast<NativeNayanEngineCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
|
|
963
|
+
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asObject(rt));
|
|
964
|
+
}
|
|
965
|
+
|
|
861
966
|
static jsi::Value __audioPlay(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
|
|
862
967
|
static_assert(
|
|
863
968
|
bridging::getParameterCount(&T::audioPlay) == 6,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// The EngineSurface view: a CAMetalLayer the Rust renderer draws into with Metal. JS refers to it by
|
|
2
|
-
// `surfaceId
|
|
2
|
+
// `surfaceId`. A display link asks the game for each frame on the JS thread (`deliverFrame`); the
|
|
3
|
+
// frames it publishes are drawn on the engine's render thread.
|
|
3
4
|
#import <QuartzCore/CAMetalLayer.h>
|
|
4
5
|
#import <QuartzCore/CADisplayLink.h>
|
|
5
6
|
#import <React/RCTViewManager.h>
|
|
@@ -7,6 +8,10 @@
|
|
|
7
8
|
|
|
8
9
|
#include <engine_core.h>
|
|
9
10
|
|
|
11
|
+
namespace facebook::react {
|
|
12
|
+
void deliverFrame(int surface, double timeMs); // NayanEngineModule.cpp
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
@interface NayanEngineSurfaceView : UIView <UIGestureRecognizerDelegate>
|
|
11
16
|
@property (nonatomic, assign) NSInteger surfaceId;
|
|
12
17
|
@property (nonatomic, assign) NSInteger drawingId;
|
|
@@ -18,6 +23,7 @@
|
|
|
18
23
|
@implementation NayanEngineSurfaceView {
|
|
19
24
|
BOOL _attached;
|
|
20
25
|
CADisplayLink *_drawingClock;
|
|
26
|
+
CADisplayLink *_clock;
|
|
21
27
|
UITouch *_drawingTouch;
|
|
22
28
|
UIPinchGestureRecognizer *_drawingPinch;
|
|
23
29
|
UIPanGestureRecognizer *_drawingPan;
|
|
@@ -47,6 +53,8 @@
|
|
|
47
53
|
[self addGestureRecognizer:_drawingPan];
|
|
48
54
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopDrawingClock) name:UIApplicationWillResignActiveNotification object:nil];
|
|
49
55
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startDrawingClock) name:UIApplicationDidBecomeActiveNotification object:nil];
|
|
56
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopClock) name:UIApplicationWillResignActiveNotification object:nil];
|
|
57
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startClock) name:UIApplicationDidBecomeActiveNotification object:nil];
|
|
50
58
|
self.layer.opaque = YES;
|
|
51
59
|
}
|
|
52
60
|
return self;
|
|
@@ -74,10 +82,12 @@
|
|
|
74
82
|
(int32_t)_surfaceId, (__bridge void *)self.layer, (uint32_t)(size.width * scale), (uint32_t)(size.height * scale)) == 1;
|
|
75
83
|
if (_drawingId >= 0) engine_drawing_invalidate((int32_t)_drawingId);
|
|
76
84
|
[self startDrawingClock];
|
|
85
|
+
[self startClock];
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
- (void)detach
|
|
80
89
|
{
|
|
90
|
+
[self stopClock];
|
|
81
91
|
[self stopDrawingClock];
|
|
82
92
|
if (_attached) {
|
|
83
93
|
engine_render_detach((int32_t)_surfaceId);
|
|
@@ -126,6 +136,25 @@
|
|
|
126
136
|
_drawingBackground = value;
|
|
127
137
|
if (_drawingId >= 0) engine_drawing_invalidate((int32_t)_drawingId);
|
|
128
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* The game's display clock: once per refresh while the surface is attached, on screen and the app is
|
|
141
|
+
* active, the engine is asked for its next frame on the JS thread. 60 a second, also on ProMotion
|
|
142
|
+
* screens, so a JS game loop isn't run twice as often.
|
|
143
|
+
*/
|
|
144
|
+
- (void)startClock {
|
|
145
|
+
if (_clock != nil || _surfaceId < 0 || self.window == nil || !_attached || UIApplication.sharedApplication.applicationState != UIApplicationStateActive) return;
|
|
146
|
+
_clock = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
|
|
147
|
+
if (@available(iOS 15.0, *)) _clock.preferredFrameRateRange = CAFrameRateRangeMake(30, 60, 60);
|
|
148
|
+
else _clock.preferredFramesPerSecond = 60;
|
|
149
|
+
[_clock addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
|
|
150
|
+
}
|
|
151
|
+
- (void)stopClock {
|
|
152
|
+
[_clock invalidate];
|
|
153
|
+
_clock = nil;
|
|
154
|
+
}
|
|
155
|
+
- (void)tick:(CADisplayLink *)link {
|
|
156
|
+
if (_surfaceId >= 0) facebook::react::deliverFrame((int)_surfaceId, link.timestamp * 1000.0);
|
|
157
|
+
}
|
|
129
158
|
- (void)startDrawingClock {
|
|
130
159
|
if (_drawingClock != nil || _drawingId < 0 || self.window == nil || !_attached || UIApplication.sharedApplication.applicationState != UIApplicationStateActive) return;
|
|
131
160
|
_drawingClock = [CADisplayLink displayLinkWithTarget:self selector:@selector(presentDrawing)];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nayan-ui/engine",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "Fast 3D game engine for React and React Native: Rust and wgpu rendering, Rapier physics, animation, particle effects, audio, haptics and drawing.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"3d",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"webgpu",
|
|
26
26
|
"wgpu"
|
|
27
27
|
],
|
|
28
|
-
"homepage": "https://www.nayanui.com/engine",
|
|
28
|
+
"homepage": "https://www.nayanui.com/game-engine",
|
|
29
29
|
"bugs": {
|
|
30
30
|
"url": "https://github.com/ursnj/nayan-ui/issues"
|
|
31
31
|
},
|
|
@@ -100,6 +100,8 @@ export interface Spec extends TurboModule {
|
|
|
100
100
|
shapePrepare(vertices: Object, indices: Object, options: string): number;
|
|
101
101
|
solidPrepare(recipe: string, options: string): number;
|
|
102
102
|
modelLoad(data: Object, center: boolean, fit: number): number;
|
|
103
|
+
/** `modelLoad` on a background native thread (the data is copied first): resolves to the mesh id, or -1. */
|
|
104
|
+
modelLoadAsync(data: Object, center: boolean, fit: number): Promise<number>;
|
|
103
105
|
/** 11 floats per vertex (position, normal, color, uv); aliases native memory. */
|
|
104
106
|
modelVertices(mesh: number): Object;
|
|
105
107
|
/** u32 triangle indices; aliases native memory. */
|
|
@@ -112,6 +114,11 @@ export interface Spec extends TurboModule {
|
|
|
112
114
|
meshAlias(base: number): number;
|
|
113
115
|
/** Registers geometry (copied): 11 floats per vertex, u32 triangle indices. Returns the mesh id, or -1. */
|
|
114
116
|
meshCreate(vertices: Object, indices: Object): number;
|
|
117
|
+
/**
|
|
118
|
+
* Hands a core model's own geometry (from `meshCreate`, `modelLoad`, a font) to the renderer, in
|
|
119
|
+
* Rust: nothing is copied through JS. `texture` -1 for none. False if the mesh is unknown.
|
|
120
|
+
*/
|
|
121
|
+
renderModel(mesh: number, texture: number, shine: number): boolean;
|
|
115
122
|
/**
|
|
116
123
|
* Fills 2D contours ([x, y] f32 pairs, `counts[k]` points per contour) by the non-zero or even-odd
|
|
117
124
|
* rule and extrudes them `depth` deep. Returns an ArrayBuffer of 11 floats per vertex (unindexed).
|
|
@@ -141,12 +148,16 @@ export interface Spec extends TurboModule {
|
|
|
141
148
|
): void;
|
|
142
149
|
/** Decodes a PNG/JPEG ArrayBuffer. Returns the texture id, or -1. */
|
|
143
150
|
textureLoad(data: Object): number;
|
|
151
|
+
/** `textureLoad` on a background native thread: resolves to the texture id, or -1. */
|
|
152
|
+
textureLoadAsync(data: Object): Promise<number>;
|
|
144
153
|
/** RGBA8 pixels, top row first; aliases native memory. */
|
|
145
154
|
texturePixels(texture: number): Object;
|
|
146
155
|
/** [width, height]. */
|
|
147
156
|
textureSize(texture: number): Array<number>;
|
|
148
157
|
/** Builds extruded glyph meshes for `chars`. Returns the font id, or -1. */
|
|
149
158
|
fontLoad(data: Object, depth: number, chars: string, weight: number): number;
|
|
159
|
+
/** `fontLoad` (outlines and glyph meshes) on a background native thread: resolves to the font id, or -1. */
|
|
160
|
+
fontLoadAsync(data: Object, depth: number, chars: string, weight: number): Promise<number>;
|
|
150
161
|
/** [codepoint, mesh (-1 = nothing drawn), advance, ...] followed by the cap height. */
|
|
151
162
|
fontGlyphs(font: number): Array<number>;
|
|
152
163
|
/** Why the last model / texture / font / alias load failed ("" after a success). */
|
|
@@ -182,6 +193,32 @@ export interface Spec extends TurboModule {
|
|
|
182
193
|
viewProj: Object,
|
|
183
194
|
world: number
|
|
184
195
|
): number;
|
|
196
|
+
/**
|
|
197
|
+
* `renderFrame`'s arguments, but the frame is copied and drawn on the native render thread: returns
|
|
198
|
+
* at once, with `viewProj` written. 1 once the surface has presented a frame, 0 before, -1 if the
|
|
199
|
+
* last frame failed (see `renderError`).
|
|
200
|
+
*/
|
|
201
|
+
publishFrame(
|
|
202
|
+
surface: number,
|
|
203
|
+
frame: Object,
|
|
204
|
+
matrices: Object,
|
|
205
|
+
colors: Object,
|
|
206
|
+
regions: Object,
|
|
207
|
+
ranges: Object,
|
|
208
|
+
count: number,
|
|
209
|
+
viewProj: Object,
|
|
210
|
+
world: number
|
|
211
|
+
): number;
|
|
212
|
+
/** [frames presented, smoothed render milliseconds] for a surface drawn by the render thread. */
|
|
213
|
+
renderStats(surface: number): Array<number>;
|
|
214
|
+
/** True where the platform drives frames from its display clock (`startFrames`); else use requestAnimationFrame. */
|
|
215
|
+
hasFrameClock(): boolean;
|
|
216
|
+
/**
|
|
217
|
+
* Calls `onFrame` on the JS thread once per display refresh while the surface is attached and
|
|
218
|
+
* visible, with the frame time in milliseconds. A frame JS hasn't started yet isn't queued again.
|
|
219
|
+
*/
|
|
220
|
+
startFrames(surface: number, onFrame: (timeMs: number) => void): void;
|
|
221
|
+
stopFrames(surface: number): void;
|
|
185
222
|
/**
|
|
186
223
|
* The screen-space overlay drawn over surface `surface` from its next frame on, copied from a world's
|
|
187
224
|
* buffers. In points: x right and y up from the view's top-left (on screen y <= 0), z toward the
|
|
@@ -210,6 +247,8 @@ export interface Spec extends TurboModule {
|
|
|
210
247
|
// Audio (global)
|
|
211
248
|
/** Decodes a WAV ArrayBuffer. Returns a sound id, or -1. */
|
|
212
249
|
audioLoad(data: Object): number;
|
|
250
|
+
/** `audioLoad` on a background native thread: resolves to the sound id, or -1. */
|
|
251
|
+
audioLoadAsync(data: Object): Promise<number>;
|
|
213
252
|
/** Returns a voice id (> 0), or 0 if nothing played. */
|
|
214
253
|
audioPlay(sound: number, volume: number, pan: number, pitch: number, loop: boolean): number;
|
|
215
254
|
audioStop(voice: number): void;
|