@nayan-ui/engine 0.0.0-stage → 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/LICENSE +21 -0
- package/NayanEngine.podspec +28 -0
- package/README.md +308 -2
- package/lib/module/assets/AssetBytesCache.js +76 -0
- package/lib/module/assets/AssetCache.js +19 -0
- package/lib/module/assets/AssetLoader.js +52 -0
- package/lib/module/assets/CacheGeneration.js +7 -0
- package/lib/module/assets/IndexedDbCache.web.js +149 -0
- package/lib/module/assets/ProceduralCache.js +249 -0
- package/lib/module/assets/font.js +139 -0
- package/lib/module/assets/loft.js +142 -0
- package/lib/module/assets/model.js +96 -0
- package/lib/module/assets/modelling.js +254 -0
- package/lib/module/assets/shape.js +926 -0
- package/lib/module/assets/source.js +58 -0
- package/lib/module/assets/source.web.js +22 -0
- package/lib/module/assets/storage.js +4 -0
- package/lib/module/assets/storage.shared.js +38 -0
- package/lib/module/assets/storage.web.js +38 -0
- package/lib/module/assets/surface.js +47 -0
- package/lib/module/assets/texture.js +69 -0
- package/lib/module/drawing/DrawingCanvas.js +38 -0
- package/lib/module/drawing/DrawingCanvas.web.js +206 -0
- package/lib/module/drawing/DrawingDocument.js +256 -0
- package/lib/module/drawing/types.js +4 -0
- package/lib/module/globals.d.ts +12 -0
- package/lib/module/index.js +39 -0
- package/lib/module/input/Joystick.js +84 -0
- package/lib/module/input/Joystick.web.js +93 -0
- package/lib/module/input/keyboard.js +250 -0
- package/lib/module/media/audio-worklet.js +34 -0
- package/lib/module/media/audio.js +97 -0
- package/lib/module/media/haptics.js +82 -0
- package/lib/module/media/output.web.js +66 -0
- package/lib/module/native/BrowserEngine.js +568 -0
- package/lib/module/native/EngineBridge.js +4 -0
- package/lib/module/native/NativeNayanEngine.js +7 -0
- package/lib/module/native/NativeNayanEngine.web.js +62 -0
- package/lib/module/native/prepare.js +7 -0
- package/lib/module/native/prepare.web.js +17 -0
- package/lib/module/native/spec/NativeNayanEngine.js +17 -0
- package/lib/module/package.json +1 -0
- package/lib/module/render/GameView.js +317 -0
- package/lib/module/render/camera.js +34 -0
- package/lib/module/render/host.js +39 -0
- package/lib/module/render/host.web.js +104 -0
- package/lib/module/render/light.js +24 -0
- package/lib/module/render/meshes.js +159 -0
- package/lib/module/render/quality.js +119 -0
- package/lib/module/render/responder.js +4 -0
- package/lib/module/render/responder.web.js +97 -0
- package/lib/module/render/touch.js +185 -0
- package/lib/module/render/useWorld.js +72 -0
- package/lib/module/types.js +30 -0
- package/lib/module/world/Scoreboard.js +161 -0
- package/lib/module/world/TransformBatch.js +128 -0
- package/lib/module/world/World.js +704 -0
- package/lib/module/world/color.js +80 -0
- package/lib/module/world/desc.js +187 -0
- package/lib/module/world/effects.js +463 -0
- package/lib/module/world/quat.js +86 -0
- package/lib/module/world/types.js +4 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/assets/AssetBytesCache.d.ts +7 -0
- package/lib/typescript/src/assets/AssetCache.d.ts +9 -0
- package/lib/typescript/src/assets/AssetLoader.d.ts +11 -0
- package/lib/typescript/src/assets/CacheGeneration.d.ts +3 -0
- package/lib/typescript/src/assets/IndexedDbCache.web.d.ts +20 -0
- package/lib/typescript/src/assets/ProceduralCache.d.ts +45 -0
- package/lib/typescript/src/assets/font.d.ts +53 -0
- package/lib/typescript/src/assets/loft.d.ts +31 -0
- package/lib/typescript/src/assets/model.d.ts +58 -0
- package/lib/typescript/src/assets/modelling.d.ts +157 -0
- package/lib/typescript/src/assets/shape.d.ts +203 -0
- package/lib/typescript/src/assets/source.d.ts +10 -0
- package/lib/typescript/src/assets/source.web.d.ts +8 -0
- package/lib/typescript/src/assets/storage.d.ts +2 -0
- package/lib/typescript/src/assets/storage.shared.d.ts +7 -0
- package/lib/typescript/src/assets/storage.web.d.ts +7 -0
- package/lib/typescript/src/assets/surface.d.ts +17 -0
- package/lib/typescript/src/assets/texture.d.ts +30 -0
- package/lib/typescript/src/drawing/DrawingCanvas.d.ts +5 -0
- package/lib/typescript/src/drawing/DrawingCanvas.web.d.ts +4 -0
- package/lib/typescript/src/drawing/DrawingDocument.d.ts +210 -0
- package/lib/typescript/src/drawing/types.d.ts +12 -0
- package/lib/typescript/src/index.d.ts +45 -0
- package/lib/typescript/src/input/Joystick.d.ts +20 -0
- package/lib/typescript/src/input/Joystick.web.d.ts +13 -0
- package/lib/typescript/src/input/keyboard.d.ts +17 -0
- package/lib/typescript/src/media/audio.d.ts +46 -0
- package/lib/typescript/src/media/haptics.d.ts +22 -0
- package/lib/typescript/src/media/output.web.d.ts +4 -0
- package/lib/typescript/src/native/BrowserEngine.d.ts +8 -0
- package/lib/typescript/src/native/EngineBridge.d.ts +26 -0
- package/lib/typescript/src/native/NativeNayanEngine.d.ts +5 -0
- package/lib/typescript/src/native/NativeNayanEngine.web.d.ts +10 -0
- package/lib/typescript/src/native/prepare.d.ts +3 -0
- package/lib/typescript/src/native/prepare.web.d.ts +2 -0
- package/lib/typescript/src/native/spec/NativeNayanEngine.d.ts +211 -0
- package/lib/typescript/src/render/GameView.d.ts +107 -0
- package/lib/typescript/src/render/camera.d.ts +6 -0
- package/lib/typescript/src/render/host.d.ts +29 -0
- package/lib/typescript/src/render/host.web.d.ts +16 -0
- package/lib/typescript/src/render/light.d.ts +12 -0
- package/lib/typescript/src/render/meshes.d.ts +45 -0
- package/lib/typescript/src/render/quality.d.ts +48 -0
- package/lib/typescript/src/render/responder.d.ts +2 -0
- package/lib/typescript/src/render/responder.web.d.ts +40 -0
- package/lib/typescript/src/render/touch.d.ts +26 -0
- package/lib/typescript/src/render/useWorld.d.ts +20 -0
- package/lib/typescript/src/types.d.ts +81 -0
- package/lib/typescript/src/world/Scoreboard.d.ts +75 -0
- package/lib/typescript/src/world/TransformBatch.d.ts +39 -0
- package/lib/typescript/src/world/World.d.ts +207 -0
- package/lib/typescript/src/world/color.d.ts +18 -0
- package/lib/typescript/src/world/desc.d.ts +17 -0
- package/lib/typescript/src/world/effects.d.ts +157 -0
- package/lib/typescript/src/world/quat.d.ts +31 -0
- package/lib/typescript/src/world/types.d.ts +238 -0
- package/lib/web/audio-worklet.js +29 -0
- package/lib/web/engine_core_bg.wasm +0 -0
- package/lib/web/index.js +8240 -0
- package/lib/web/types/src/assets/AssetBytesCache.d.ts +6 -0
- package/lib/web/types/src/assets/AssetCache.d.ts +8 -0
- package/lib/web/types/src/assets/AssetLoader.d.ts +10 -0
- package/lib/web/types/src/assets/CacheGeneration.d.ts +2 -0
- package/lib/web/types/src/assets/IndexedDbCache.d.ts +19 -0
- package/lib/web/types/src/assets/ProceduralCache.d.ts +44 -0
- package/lib/web/types/src/assets/font.d.ts +52 -0
- package/lib/web/types/src/assets/loft.d.ts +30 -0
- package/lib/web/types/src/assets/model.d.ts +57 -0
- package/lib/web/types/src/assets/modelling.d.ts +156 -0
- package/lib/web/types/src/assets/shape.d.ts +202 -0
- package/lib/web/types/src/assets/source.d.ts +7 -0
- package/lib/web/types/src/assets/storage.d.ts +6 -0
- package/lib/web/types/src/assets/storage.shared.d.ts +6 -0
- package/lib/web/types/src/assets/surface.d.ts +16 -0
- package/lib/web/types/src/assets/texture.d.ts +29 -0
- package/lib/web/types/src/drawing/DrawingCanvas.d.ts +3 -0
- package/lib/web/types/src/drawing/DrawingDocument.d.ts +209 -0
- package/lib/web/types/src/drawing/types.d.ts +11 -0
- package/lib/web/types/src/index.d.ts +44 -0
- package/lib/web/types/src/input/Joystick.d.ts +12 -0
- package/lib/web/types/src/input/keyboard.d.ts +16 -0
- package/lib/web/types/src/media/audio.d.ts +45 -0
- package/lib/web/types/src/media/haptics.d.ts +21 -0
- package/lib/web/types/src/media/output.d.ts +3 -0
- package/lib/web/types/src/native/BrowserEngine.d.ts +7 -0
- package/lib/web/types/src/native/EngineBridge.d.ts +25 -0
- package/lib/web/types/src/native/NativeNayanEngine.d.ts +9 -0
- package/lib/web/types/src/native/prepare.d.ts +1 -0
- package/lib/web/types/src/native/spec/NativeNayanEngine.d.ts +210 -0
- package/lib/web/types/src/render/GameView.d.ts +106 -0
- package/lib/web/types/src/render/camera.d.ts +5 -0
- package/lib/web/types/src/render/host.d.ts +15 -0
- package/lib/web/types/src/render/light.d.ts +11 -0
- package/lib/web/types/src/render/meshes.d.ts +44 -0
- package/lib/web/types/src/render/quality.d.ts +47 -0
- package/lib/web/types/src/render/responder.d.ts +39 -0
- package/lib/web/types/src/render/touch.d.ts +25 -0
- package/lib/web/types/src/render/useWorld.d.ts +19 -0
- package/lib/web/types/src/types.d.ts +80 -0
- package/lib/web/types/src/world/Scoreboard.d.ts +74 -0
- package/lib/web/types/src/world/TransformBatch.d.ts +38 -0
- package/lib/web/types/src/world/World.d.ts +206 -0
- package/lib/web/types/src/world/color.d.ts +17 -0
- package/lib/web/types/src/world/desc.d.ts +16 -0
- package/lib/web/types/src/world/effects.d.ts +156 -0
- package/lib/web/types/src/world/quat.d.ts +30 -0
- package/lib/web/types/src/world/types.d.ts +237 -0
- package/native/android/CMakeLists.txt +34 -0
- package/native/android/NayanEngineSpec.h +15 -0
- package/native/android/build.gradle +26 -0
- package/native/android/codegen/CMakeLists.txt +3 -0
- package/native/android/proguard-rules.pro +2 -0
- package/native/android/src/main/java/com/nayanui/engine/EngineSurfaceView.java +295 -0
- package/native/android/src/main/java/com/nayanui/engine/EngineSurfaceViewManager.java +45 -0
- package/native/android/src/main/java/com/nayanui/engine/NayanEnginePackage.java +24 -0
- package/native/core/build/EngineCore.xcframework/Info.plist +43 -0
- 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/drawing-licenses.txt +58 -0
- package/native/core/include/engine_core.h +331 -0
- package/native/cpp/NayanEngineModule.cpp +998 -0
- package/native/cpp/NayanEngineModule.h +174 -0
- package/native/cpp/generated/NayanEngineSpecJSI.cpp +2 -0
- package/native/cpp/generated/NayanEngineSpecJSI.h +1026 -0
- package/native/ios/NayanEngineProvider.h +5 -0
- package/native/ios/NayanEngineProvider.mm +21 -0
- package/native/ios/NayanEngineSurface.mm +252 -0
- package/native/scripts/check-package.mjs +39 -0
- package/package.json +162 -4
- package/react-native.config.js +18 -0
- package/src/native/spec/NativeNayanEngine.ts +265 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#import "NayanEngineProvider.h"
|
|
2
|
+
|
|
3
|
+
#import <ReactCommon/CallInvoker.h>
|
|
4
|
+
#import <ReactCommon/TurboModule.h>
|
|
5
|
+
|
|
6
|
+
#include "NayanEngineModule.h"
|
|
7
|
+
#include <engine_core.h>
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
@implementation NayanEngineProvider
|
|
11
|
+
|
|
12
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
13
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
14
|
+
{
|
|
15
|
+
NSURL *support = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] firstObject];
|
|
16
|
+
NSData *path = [support.path dataUsingEncoding:NSUTF8StringEncoding];
|
|
17
|
+
if (path != nil) engine_cache_directory(static_cast<const uint8_t *>(path.bytes), path.length);
|
|
18
|
+
return std::make_shared<facebook::react::NayanEngineModule>(params.jsInvoker);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@end
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// The EngineSurface view: a CAMetalLayer the Rust renderer draws into with Metal. JS refers to it by
|
|
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.
|
|
4
|
+
#import <QuartzCore/CAMetalLayer.h>
|
|
5
|
+
#import <QuartzCore/CADisplayLink.h>
|
|
6
|
+
#import <React/RCTViewManager.h>
|
|
7
|
+
#import <UIKit/UIKit.h>
|
|
8
|
+
|
|
9
|
+
#include <engine_core.h>
|
|
10
|
+
|
|
11
|
+
namespace facebook::react {
|
|
12
|
+
void deliverFrame(int surface, double timeMs); // NayanEngineModule.cpp
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@interface NayanEngineSurfaceView : UIView <UIGestureRecognizerDelegate>
|
|
16
|
+
@property (nonatomic, assign) NSInteger surfaceId;
|
|
17
|
+
@property (nonatomic, assign) NSInteger drawingId;
|
|
18
|
+
@property (nonatomic, assign) NSInteger drawingMode;
|
|
19
|
+
@property (nonatomic, assign) NSInteger drawingBackground;
|
|
20
|
+
@property (nonatomic, copy) RCTDirectEventBlock onDrawingChange;
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
@implementation NayanEngineSurfaceView {
|
|
24
|
+
BOOL _attached;
|
|
25
|
+
CADisplayLink *_drawingClock;
|
|
26
|
+
CADisplayLink *_clock;
|
|
27
|
+
UITouch *_drawingTouch;
|
|
28
|
+
UIPinchGestureRecognizer *_drawingPinch;
|
|
29
|
+
UIPanGestureRecognizer *_drawingPan;
|
|
30
|
+
CFTimeInterval _lastDrawingEvent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
+ (Class)layerClass
|
|
34
|
+
{
|
|
35
|
+
return [CAMetalLayer class];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
39
|
+
{
|
|
40
|
+
if (self = [super initWithFrame:frame]) {
|
|
41
|
+
_surfaceId = -1;
|
|
42
|
+
_drawingId = -1;
|
|
43
|
+
_drawingBackground = 0xffffff;
|
|
44
|
+
self.multipleTouchEnabled = YES;
|
|
45
|
+
_drawingPinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchDrawing:)];
|
|
46
|
+
_drawingPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDrawing:)];
|
|
47
|
+
_drawingPinch.delegate = self;
|
|
48
|
+
_drawingPan.delegate = self;
|
|
49
|
+
_drawingPan.minimumNumberOfTouches = 2;
|
|
50
|
+
_drawingPinch.enabled = NO;
|
|
51
|
+
_drawingPan.enabled = NO;
|
|
52
|
+
[self addGestureRecognizer:_drawingPinch];
|
|
53
|
+
[self addGestureRecognizer:_drawingPan];
|
|
54
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopDrawingClock) name:UIApplicationWillResignActiveNotification object:nil];
|
|
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];
|
|
58
|
+
self.layer.opaque = YES;
|
|
59
|
+
}
|
|
60
|
+
return self;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- (void)setSurfaceId:(NSInteger)surfaceId
|
|
64
|
+
{
|
|
65
|
+
if (surfaceId == _surfaceId) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
[self detach];
|
|
69
|
+
_surfaceId = surfaceId;
|
|
70
|
+
[self attach];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
- (void)attach
|
|
74
|
+
{
|
|
75
|
+
CGFloat scale = self.window.screen.scale ?: UIScreen.mainScreen.scale;
|
|
76
|
+
CGSize size = self.bounds.size;
|
|
77
|
+
if (_surfaceId < 0 || self.window == nil || size.width <= 0 || size.height <= 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
self.layer.contentsScale = scale;
|
|
81
|
+
_attached = engine_render_attach(
|
|
82
|
+
(int32_t)_surfaceId, (__bridge void *)self.layer, (uint32_t)(size.width * scale), (uint32_t)(size.height * scale)) == 1;
|
|
83
|
+
if (_drawingId >= 0) engine_drawing_invalidate((int32_t)_drawingId);
|
|
84
|
+
[self startDrawingClock];
|
|
85
|
+
[self startClock];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
- (void)detach
|
|
89
|
+
{
|
|
90
|
+
[self stopClock];
|
|
91
|
+
[self stopDrawingClock];
|
|
92
|
+
if (_attached) {
|
|
93
|
+
engine_render_detach((int32_t)_surfaceId);
|
|
94
|
+
_attached = NO;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (void)layoutSubviews
|
|
99
|
+
{
|
|
100
|
+
[super layoutSubviews];
|
|
101
|
+
[self attach];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
- (void)didMoveToWindow
|
|
105
|
+
{
|
|
106
|
+
[super didMoveToWindow];
|
|
107
|
+
if (self.window == nil) {
|
|
108
|
+
[self detach];
|
|
109
|
+
} else {
|
|
110
|
+
[self attach];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
- (void)dealloc
|
|
115
|
+
{
|
|
116
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
117
|
+
[self detach];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
- (void)setDrawingId:(NSInteger)value {
|
|
121
|
+
if (_drawingId == value) return;
|
|
122
|
+
[self stopDrawingClock];
|
|
123
|
+
_drawingId = value;
|
|
124
|
+
_drawingPinch.enabled = value >= 0;
|
|
125
|
+
_drawingPan.enabled = value >= 0;
|
|
126
|
+
if (value >= 0) engine_drawing_invalidate((int32_t)value);
|
|
127
|
+
[self startDrawingClock];
|
|
128
|
+
}
|
|
129
|
+
- (void)setDrawingMode:(NSInteger)value {
|
|
130
|
+
if (_drawingTouch != nil) engine_drawing_touch((int32_t)_drawingId, 3, 0, 0, 1);
|
|
131
|
+
_drawingTouch = nil;
|
|
132
|
+
_drawingMode = value;
|
|
133
|
+
_drawingPan.minimumNumberOfTouches = value == 0 ? 2 : 1;
|
|
134
|
+
}
|
|
135
|
+
- (void)setDrawingBackground:(NSInteger)value {
|
|
136
|
+
_drawingBackground = value;
|
|
137
|
+
if (_drawingId >= 0) engine_drawing_invalidate((int32_t)_drawingId);
|
|
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
|
+
}
|
|
158
|
+
- (void)startDrawingClock {
|
|
159
|
+
if (_drawingClock != nil || _drawingId < 0 || self.window == nil || !_attached || UIApplication.sharedApplication.applicationState != UIApplicationStateActive) return;
|
|
160
|
+
_drawingClock = [CADisplayLink displayLinkWithTarget:self selector:@selector(presentDrawing)];
|
|
161
|
+
if (@available(iOS 15.0, *)) _drawingClock.preferredFrameRateRange = CAFrameRateRangeMake(30, 120, 120);
|
|
162
|
+
[_drawingClock addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
|
|
163
|
+
}
|
|
164
|
+
- (void)stopDrawingClock {
|
|
165
|
+
[_drawingClock invalidate];
|
|
166
|
+
_drawingClock = nil;
|
|
167
|
+
if (_drawingTouch != nil) {
|
|
168
|
+
CGPoint point = [_drawingTouch locationInView:self];
|
|
169
|
+
engine_drawing_touch((int32_t)_drawingId, 2, point.x, point.y, 1);
|
|
170
|
+
_drawingTouch = nil;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
- (void)presentDrawing {
|
|
174
|
+
engine_drawing_present((int32_t)_drawingId, (int32_t)_surfaceId, self.bounds.size.width, self.bounds.size.height, (uint32_t)_drawingBackground);
|
|
175
|
+
CFTimeInterval now = CACurrentMediaTime();
|
|
176
|
+
if (_onDrawingChange != nil && now - _lastDrawingEvent >= 0.1) {
|
|
177
|
+
_lastDrawingEvent = now;
|
|
178
|
+
char *event = engine_drawing_take_event((int32_t)_drawingId);
|
|
179
|
+
if (event != nullptr) {
|
|
180
|
+
NSString *state = [NSString stringWithUTF8String:event];
|
|
181
|
+
engine_drawing_result_free(event);
|
|
182
|
+
_onDrawingChange(@{@"state": state ?: @"{}", @"documentId": @(_drawingId)});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gesture { return _drawingTouch == nil || _drawingTouch.type != UITouchTypePencil; }
|
|
187
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)a shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)b { return YES; }
|
|
188
|
+
- (void)pinchDrawing:(UIPinchGestureRecognizer *)gesture {
|
|
189
|
+
if (gesture.state == UIGestureRecognizerStateChanged) {
|
|
190
|
+
engine_drawing_transform((int32_t)_drawingId, 0, 0, gesture.scale);
|
|
191
|
+
gesture.scale = 1;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
- (void)panDrawing:(UIPanGestureRecognizer *)gesture {
|
|
195
|
+
if (gesture.state == UIGestureRecognizerStateChanged) {
|
|
196
|
+
CGPoint delta = [gesture translationInView:self];
|
|
197
|
+
engine_drawing_transform((int32_t)_drawingId, delta.x, delta.y, 1);
|
|
198
|
+
[gesture setTranslation:CGPointZero inView:self];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
- (void)sampleDrawing:(UITouch *)touch phase:(int32_t)phase {
|
|
202
|
+
CGPoint point = [touch locationInView:self];
|
|
203
|
+
CGFloat pressure = touch.type == UITouchTypePencil && touch.maximumPossibleForce > 0 ? touch.force / touch.maximumPossibleForce : 1;
|
|
204
|
+
engine_drawing_touch((int32_t)_drawingId, phase, point.x, point.y, pressure);
|
|
205
|
+
}
|
|
206
|
+
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
207
|
+
if (_drawingId < 0) { [super touchesBegan:touches withEvent:event]; return; }
|
|
208
|
+
if (_drawingMode != 0 || _drawingTouch != nil) return;
|
|
209
|
+
UITouch *touch = touches.anyObject;
|
|
210
|
+
for (UITouch *candidate in touches) if (candidate.type == UITouchTypePencil) { touch = candidate; break; }
|
|
211
|
+
// A Pencil is tracked independently; fingers arriving during its stroke are palm touches.
|
|
212
|
+
if (touch.type != UITouchTypePencil && event.allTouches.count != 1) return;
|
|
213
|
+
_drawingTouch = touch;
|
|
214
|
+
[self sampleDrawing:touch phase:0];
|
|
215
|
+
}
|
|
216
|
+
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
217
|
+
if (_drawingId < 0) { [super touchesMoved:touches withEvent:event]; return; }
|
|
218
|
+
if (_drawingTouch == nil || ![touches containsObject:_drawingTouch]) return;
|
|
219
|
+
NSArray<UITouch *> *samples = [event coalescedTouchesForTouch:_drawingTouch];
|
|
220
|
+
if (samples.count == 0) [self sampleDrawing:_drawingTouch phase:1];
|
|
221
|
+
else for (UITouch *sample in samples) [self sampleDrawing:sample phase:1];
|
|
222
|
+
}
|
|
223
|
+
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
224
|
+
if (_drawingId < 0) { [super touchesEnded:touches withEvent:event]; return; }
|
|
225
|
+
if (_drawingTouch != nil && [touches containsObject:_drawingTouch]) { [self sampleDrawing:_drawingTouch phase:2]; _drawingTouch = nil; }
|
|
226
|
+
}
|
|
227
|
+
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
228
|
+
if (_drawingId < 0) { [super touchesCancelled:touches withEvent:event]; return; }
|
|
229
|
+
if (_drawingTouch != nil && [touches containsObject:_drawingTouch]) { engine_drawing_touch((int32_t)_drawingId, 3, 0, 0, 1); _drawingTouch = nil; }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@end
|
|
233
|
+
|
|
234
|
+
@interface NayanEngineSurfaceManager : RCTViewManager
|
|
235
|
+
@end
|
|
236
|
+
|
|
237
|
+
@implementation NayanEngineSurfaceManager
|
|
238
|
+
|
|
239
|
+
RCT_EXPORT_MODULE(NayanEngineSurface)
|
|
240
|
+
|
|
241
|
+
- (UIView *)view
|
|
242
|
+
{
|
|
243
|
+
return [NayanEngineSurfaceView new];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
RCT_EXPORT_VIEW_PROPERTY(surfaceId, NSInteger)
|
|
247
|
+
RCT_EXPORT_VIEW_PROPERTY(drawingId, NSInteger)
|
|
248
|
+
RCT_EXPORT_VIEW_PROPERTY(drawingMode, NSInteger)
|
|
249
|
+
RCT_EXPORT_VIEW_PROPERTY(drawingBackground, NSInteger)
|
|
250
|
+
RCT_EXPORT_VIEW_PROPERTY(onDrawingChange, RCTDirectEventBlock)
|
|
251
|
+
|
|
252
|
+
@end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const root = resolve(fileURLToPath(new URL('../..', import.meta.url)));
|
|
6
|
+
const metadata = JSON.parse(await readFile(resolve(root, 'package.json'), 'utf8'));
|
|
7
|
+
const required = new Set([
|
|
8
|
+
'README.md',
|
|
9
|
+
'NayanEngine.podspec',
|
|
10
|
+
'react-native.config.js',
|
|
11
|
+
'src/native/spec/NativeNayanEngine.ts',
|
|
12
|
+
'native/cpp/generated/NayanEngineSpecJSI.h',
|
|
13
|
+
'native/core/include/engine_core.h',
|
|
14
|
+
'native/core/build/EngineCore.xcframework/Info.plist',
|
|
15
|
+
'native/core/build/EngineCore.xcframework/ios-arm64/libengine_core.a',
|
|
16
|
+
'native/core/build/EngineCore.xcframework/ios-arm64-simulator/libengine_core.a',
|
|
17
|
+
'lib/web/engine_core_bg.wasm',
|
|
18
|
+
'lib/web/audio-worklet.js'
|
|
19
|
+
]);
|
|
20
|
+
for (const abi of ['arm64-v8a', 'armeabi-v7a', 'x86_64', 'x86']) required.add(`native/core/build/android/${abi}/libengine_core.a`);
|
|
21
|
+
function exportedFiles(value) {
|
|
22
|
+
if (typeof value === 'string') required.add(value);
|
|
23
|
+
else for (const item of Object.values(value)) exportedFiles(item);
|
|
24
|
+
}
|
|
25
|
+
exportedFiles(metadata.exports);
|
|
26
|
+
const missing = [];
|
|
27
|
+
for (const path of required) {
|
|
28
|
+
try {
|
|
29
|
+
const info = await stat(resolve(root, path));
|
|
30
|
+
if (!info.isFile() || info.size === 0) missing.push(path);
|
|
31
|
+
} catch {
|
|
32
|
+
missing.push(path);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (missing.length)
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Engine package is incomplete:\n${missing.map((path) => ` ${path}`).join('\n')}\nBuild the native core on macOS and run engine:build before packing or publishing.`
|
|
38
|
+
);
|
|
39
|
+
console.error(`Verified ${required.size} required engine package files for ${metadata.version}.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,164 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nayan-ui/engine",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0-beta.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
|
+
"keywords": [
|
|
6
|
+
"3d",
|
|
7
|
+
"android",
|
|
8
|
+
"drawing",
|
|
9
|
+
"game-engine",
|
|
10
|
+
"ios",
|
|
11
|
+
"metal",
|
|
12
|
+
"nayan-ui",
|
|
13
|
+
"particles",
|
|
14
|
+
"physics",
|
|
15
|
+
"rapier",
|
|
16
|
+
"react",
|
|
17
|
+
"react-game-engine",
|
|
18
|
+
"react-native",
|
|
19
|
+
"react-native-game-engine",
|
|
20
|
+
"rust",
|
|
21
|
+
"vulkan",
|
|
22
|
+
"web",
|
|
23
|
+
"webassembly",
|
|
24
|
+
"webgl",
|
|
25
|
+
"webgpu",
|
|
26
|
+
"wgpu"
|
|
27
|
+
],
|
|
28
|
+
"homepage": "https://www.nayanui.com/game-engine",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/ursnj/nayan-ui/issues"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"author": "Niranjan Devasani <niranjan.devasani@gmail.com> (https://github.com/ursnj)",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/ursnj/nayan-ui.git"
|
|
37
|
+
},
|
|
38
|
+
"workspaces": [
|
|
39
|
+
"example"
|
|
40
|
+
],
|
|
41
|
+
"files": [
|
|
42
|
+
"src/native/spec",
|
|
43
|
+
"lib",
|
|
44
|
+
"native/cpp",
|
|
45
|
+
"native/ios",
|
|
46
|
+
"native/android",
|
|
47
|
+
"*.podspec",
|
|
48
|
+
"react-native.config.js",
|
|
49
|
+
"native/core/include",
|
|
50
|
+
"native/core/build",
|
|
51
|
+
"!native/core/build/web",
|
|
52
|
+
"!**/.*",
|
|
53
|
+
"!**/*.map",
|
|
54
|
+
"!src/**/__tests__",
|
|
55
|
+
"native/scripts/check-package.mjs"
|
|
56
|
+
],
|
|
57
|
+
"sideEffects": false,
|
|
58
|
+
"main": "./lib/module/index.js",
|
|
59
|
+
"browser": "./lib/web/index.js",
|
|
60
|
+
"types": "./lib/web/types/src/index.d.ts",
|
|
61
|
+
"exports": {
|
|
62
|
+
".": {
|
|
63
|
+
"react-native": {
|
|
64
|
+
"source": "./src/index.ts",
|
|
65
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
66
|
+
"default": "./lib/module/index.js"
|
|
67
|
+
},
|
|
68
|
+
"react-native-strict-api": {
|
|
69
|
+
"source": "./src/index.ts",
|
|
70
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
71
|
+
"default": "./lib/module/index.js"
|
|
72
|
+
},
|
|
73
|
+
"browser": {
|
|
74
|
+
"types": "./lib/web/types/src/index.d.ts",
|
|
75
|
+
"default": "./lib/web/index.js"
|
|
76
|
+
},
|
|
77
|
+
"source": "./src/index.ts",
|
|
78
|
+
"types": "./lib/web/types/src/index.d.ts",
|
|
79
|
+
"default": "./lib/web/index.js"
|
|
80
|
+
},
|
|
81
|
+
"./package.json": "./package.json",
|
|
82
|
+
"./web": {
|
|
83
|
+
"types": "./lib/web/types/src/index.d.ts",
|
|
84
|
+
"default": "./lib/web/index.js"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"publishConfig": {
|
|
88
|
+
"registry": "https://registry.npmjs.org/"
|
|
89
|
+
},
|
|
90
|
+
"scripts": {
|
|
91
|
+
"example": "bun run --cwd example",
|
|
92
|
+
"clean": "del-cli lib",
|
|
93
|
+
"build": "bun run build:web && bob build",
|
|
94
|
+
"typecheck": "bun check && bun check -p tsconfig.test.json",
|
|
95
|
+
"core:test": "cargo test --manifest-path native/core/Cargo.toml",
|
|
96
|
+
"core:bench": "cargo run --release --example bench --manifest-path native/core/Cargo.toml",
|
|
97
|
+
"core:build": "native/core/scripts/build-ios.sh && native/core/scripts/build-android.sh",
|
|
98
|
+
"core:build:ios": "native/core/scripts/build-ios.sh",
|
|
99
|
+
"core:build:android": "native/core/scripts/build-android.sh",
|
|
100
|
+
"test": "bun test --isolate src",
|
|
101
|
+
"test:coverage": "bun test --isolate --coverage src native/tests && bun native/scripts/check-coverage.mjs",
|
|
102
|
+
"codegen": "node native/scripts/codegen-cxx.js",
|
|
103
|
+
"lint": "bun lint --no-script .",
|
|
104
|
+
"lint:fix": "bun lint --no-script --fix .",
|
|
105
|
+
"core:build:web": "native/core/scripts/build-web.sh",
|
|
106
|
+
"build:web": "bun run core:build:web && bun native/scripts/build-web.mjs",
|
|
107
|
+
"test:web": "bun test native/tests/web.test.ts",
|
|
108
|
+
"prepack": "node native/scripts/check-package.mjs"
|
|
109
|
+
},
|
|
110
|
+
"devDependencies": {
|
|
111
|
+
"@types/react": "~19.3.0",
|
|
112
|
+
"@types/react-dom": "^19.3.0",
|
|
113
|
+
"bun-types": "latest",
|
|
114
|
+
"del-cli": "^7.0.0",
|
|
115
|
+
"fake-indexeddb": "^6.2.6",
|
|
116
|
+
"happy-dom": "^21.0.4",
|
|
117
|
+
"react": "19.3.0",
|
|
118
|
+
"react-dom": "19.3.0",
|
|
119
|
+
"react-native": "0.88.0",
|
|
120
|
+
"react-native-builder-bob": "^0.43.1",
|
|
121
|
+
"typescript": "~6.0.3"
|
|
122
|
+
},
|
|
123
|
+
"peerDependencies": {
|
|
124
|
+
"expo-asset": "*",
|
|
125
|
+
"react": "*",
|
|
126
|
+
"react-native": "*"
|
|
127
|
+
},
|
|
128
|
+
"peerDependenciesMeta": {
|
|
129
|
+
"expo-asset": {
|
|
130
|
+
"optional": true
|
|
131
|
+
},
|
|
132
|
+
"react-native": {
|
|
133
|
+
"optional": true
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"codegenConfig": {
|
|
137
|
+
"name": "NayanEngineSpec",
|
|
138
|
+
"type": "modules",
|
|
139
|
+
"jsSrcsDir": "src/native",
|
|
140
|
+
"ios": {
|
|
141
|
+
"modulesProvider": {
|
|
142
|
+
"NativeNayanEngine": "NayanEngineProvider"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"react-native-builder-bob": {
|
|
147
|
+
"source": "src",
|
|
148
|
+
"output": "lib",
|
|
149
|
+
"targets": [
|
|
150
|
+
[
|
|
151
|
+
"module",
|
|
152
|
+
{
|
|
153
|
+
"esm": true
|
|
154
|
+
}
|
|
155
|
+
],
|
|
156
|
+
[
|
|
157
|
+
"typescript",
|
|
158
|
+
{
|
|
159
|
+
"project": "tsconfig.build.json"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Autolinking. iOS uses NayanEngine.podspec; Android builds native/android/CMakeLists.txt into the app as a
|
|
2
|
+
// pure C++ TurboModule (the generated autolinking code instantiates NayanEngineModule).
|
|
3
|
+
module.exports = {
|
|
4
|
+
dependency: {
|
|
5
|
+
platforms: {
|
|
6
|
+
android: {
|
|
7
|
+
sourceDir: 'native/android',
|
|
8
|
+
// The EngineSurface view (native/android/src/main/java).
|
|
9
|
+
packageImportPath: 'import com.nayanui.engine.NayanEnginePackage;',
|
|
10
|
+
packageInstance: 'new NayanEnginePackage()',
|
|
11
|
+
cmakeListsPath: 'codegen/CMakeLists.txt',
|
|
12
|
+
cxxModuleCMakeListsModuleName: 'NayanEngine',
|
|
13
|
+
cxxModuleCMakeListsPath: 'CMakeLists.txt',
|
|
14
|
+
cxxModuleHeaderName: 'NayanEngineModule'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|