@aguacerowx/react-native 0.0.38 → 0.0.41
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/ios/GridRenderLayer.swift +73 -21
- package/lib/commonjs/ios/GridRenderLayer.swift +73 -21
- package/lib/commonjs/package.json +1 -1
- package/lib/module/ios/GridRenderLayer.swift +73 -21
- package/lib/module/lib/commonjs/package.json +1 -1
- package/lib/module/package.json +1 -1
- package/package.json +1 -1
- package/lib/module/lib/commonjs/ios/AguaceroPackage.m +0 -19
- package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +0 -16
- package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +0 -1107
- package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -45
- package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +0 -172
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +0 -31
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +0 -201
- package/lib/module/lib/commonjs/ios/InspectorDataCache.swift +0 -64
- package/lib/module/lib/commonjs/ios/InspectorModule.m +0 -10
- package/lib/module/lib/commonjs/ios/InspectorModule.swift +0 -113
- package/lib/module/lib/commonjs/ios/Shaders.metal +0 -320
- package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.m +0 -16
- package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.swift +0 -153
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec-generated.mm +0 -0
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec.h +0 -0
- package/lib/module/lib/commonjs/scripts/compile-shaders.sh +0 -39
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
@_spi(Experimental) import MapboxMaps
|
|
3
|
-
|
|
4
|
-
@objc public class GridRenderLayerBridge: NSObject {
|
|
5
|
-
|
|
6
|
-
@objc public static func addCustomLayer(
|
|
7
|
-
to mapView: MapView,
|
|
8
|
-
layerHost: CustomLayerHost,
|
|
9
|
-
layerId: String,
|
|
10
|
-
belowLayerId: String?
|
|
11
|
-
) -> Bool {
|
|
12
|
-
let position: LayerPosition? = belowLayerId.map { .below($0) }
|
|
13
|
-
var customLayer = CustomLayer(id: layerId, renderer: layerHost)
|
|
14
|
-
|
|
15
|
-
do {
|
|
16
|
-
try mapView.mapboxMap.addLayer(customLayer, layerPosition: position)
|
|
17
|
-
return true
|
|
18
|
-
} catch {
|
|
19
|
-
print("❌ [GridRenderLayerBridge] Failed to add layer: \(error)")
|
|
20
|
-
return false
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@objc public static func triggerRepaint(on mapView: MapView) {
|
|
25
|
-
mapView.mapboxMap.triggerRepaint()
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ADD THIS NEW METHOD
|
|
29
|
-
@objc public static func layerExists(in mapView: MapView, layerId: String) -> Bool {
|
|
30
|
-
do {
|
|
31
|
-
_ = try mapView.mapboxMap.layer(withId: layerId)
|
|
32
|
-
return true
|
|
33
|
-
} catch {
|
|
34
|
-
return false
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
@objc public static func removeCustomLayer(from mapView: MapView, layerId: String) {
|
|
39
|
-
do {
|
|
40
|
-
try mapView.mapboxMap.removeLayer(withId: layerId)
|
|
41
|
-
} catch {
|
|
42
|
-
print("❌ [GridRenderLayerBridge] Failed to remove layer \(layerId): \(error)")
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
#import <React/RCTViewManager.h>
|
|
2
|
-
#import <React/RCTUIManager.h>
|
|
3
|
-
#import <React/RCTLog.h>
|
|
4
|
-
#import "GridRenderLayerView.h"
|
|
5
|
-
|
|
6
|
-
// Import Swift bridging header here
|
|
7
|
-
#if __has_include("aguacerowx_react_native-Swift.h")
|
|
8
|
-
#import "aguacerowx_react_native-Swift.h"
|
|
9
|
-
#else
|
|
10
|
-
#import <aguacerowx_react_native/aguacerowx_react_native-Swift.h>
|
|
11
|
-
#endif
|
|
12
|
-
|
|
13
|
-
@interface GridRenderLayerManager : RCTViewManager
|
|
14
|
-
@end
|
|
15
|
-
|
|
16
|
-
@implementation GridRenderLayerManager
|
|
17
|
-
|
|
18
|
-
RCT_EXPORT_MODULE(GridRenderLayer)
|
|
19
|
-
|
|
20
|
-
+ (BOOL)requiresMainQueueSetup {
|
|
21
|
-
return YES;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
- (UIView *)view {
|
|
25
|
-
return [[GridRenderLayerView alloc] init];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// --- Props ---
|
|
29
|
-
RCT_EXPORT_VIEW_PROPERTY(opacity, float)
|
|
30
|
-
RCT_EXPORT_VIEW_PROPERTY(dataRange, NSArray)
|
|
31
|
-
RCT_EXPORT_VIEW_PROPERTY(smoothing, BOOL)
|
|
32
|
-
RCT_EXPORT_VIEW_PROPERTY(belowID, NSString)
|
|
33
|
-
|
|
34
|
-
// --- Commands ---
|
|
35
|
-
RCT_EXPORT_METHOD(updateGeometry:(nonnull NSNumber *)reactTag
|
|
36
|
-
corners:(NSDictionary *)corners
|
|
37
|
-
gridDef:(NSDictionary *)gridDef)
|
|
38
|
-
{
|
|
39
|
-
// OPTIMIZATION: Dispatch heavy geometry calculations to a high-priority background queue.
|
|
40
|
-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
41
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
42
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
43
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
44
|
-
[view.layerInstance updateGeometryWithCorners:corners gridDef:gridDef];
|
|
45
|
-
}
|
|
46
|
-
}];
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
RCT_EXPORT_METHOD(updateDataTexture:(nonnull NSNumber *)reactTag
|
|
52
|
-
data:(NSString *)data
|
|
53
|
-
nx:(nonnull NSNumber *)nx
|
|
54
|
-
ny:(nonnull NSNumber *)ny
|
|
55
|
-
scale:(nonnull NSNumber *)scale
|
|
56
|
-
offset:(nonnull NSNumber *)offset
|
|
57
|
-
missing:(nonnull NSNumber *)missing
|
|
58
|
-
scaleType:(NSString *)scaleType)
|
|
59
|
-
{
|
|
60
|
-
NSTimeInterval start = [[NSDate date] timeIntervalSince1970];
|
|
61
|
-
NSUInteger len = [data length];
|
|
62
|
-
RCTLogInfo(@"⚡️ [PERF] [Bridge] updateDataTexture called. Payload: %lu chars", (unsigned long)len);
|
|
63
|
-
|
|
64
|
-
// OPTIMIZATION: Dispatch to a high-priority background queue immediately.
|
|
65
|
-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
66
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
67
|
-
|
|
68
|
-
NSTimeInterval uiBlockTime = [[NSDate date] timeIntervalSince1970];
|
|
69
|
-
RCTLogInfo(@"⚡️ [PERF] [Bridge] updateDataTexture dispatched in %.2f ms", (uiBlockTime - start) * 1000);
|
|
70
|
-
|
|
71
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
72
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
73
|
-
[view.layerInstance updateDataTextureWithData:data nx:nx ny:ny scale:scale offset:offset missing:missing scaleType:scaleType];
|
|
74
|
-
}
|
|
75
|
-
}];
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
RCT_EXPORT_METHOD(updateColormapTexture:(nonnull NSNumber *)reactTag
|
|
80
|
-
colormapAsBase64:(NSString *)colormapAsBase64)
|
|
81
|
-
{
|
|
82
|
-
// Don't block the main thread - dispatch to background first
|
|
83
|
-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
84
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
85
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
86
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
87
|
-
[view.layerInstance updateColormapTextureWithColormapAsBase64:colormapAsBase64];
|
|
88
|
-
}
|
|
89
|
-
}];
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
RCT_EXPORT_METHOD(updateDataParameters:(nonnull NSNumber *)reactTag
|
|
94
|
-
scale:(nonnull NSNumber *)scale
|
|
95
|
-
offset:(nonnull NSNumber *)offset
|
|
96
|
-
missing:(nonnull NSNumber *)missing
|
|
97
|
-
scaleType:(nonnull NSNumber *)scaleType) // ADD THIS
|
|
98
|
-
{
|
|
99
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
100
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
101
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
102
|
-
[view.layerInstance updateDataParametersWithScale:scale offset:offset missing:missing scaleType:scaleType]; // ADD scaleType here
|
|
103
|
-
}
|
|
104
|
-
}];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
RCT_EXPORT_METHOD(clear:(nonnull NSNumber *)reactTag)
|
|
108
|
-
{
|
|
109
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
110
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
111
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
112
|
-
[view.layerInstance clear];
|
|
113
|
-
}
|
|
114
|
-
}];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
RCT_EXPORT_METHOD(primeGpuCache:(nonnull NSNumber *)reactTag
|
|
118
|
-
frameInfo:(NSDictionary *)frameInfo)
|
|
119
|
-
{
|
|
120
|
-
NSTimeInterval start = [[NSDate date] timeIntervalSince1970];
|
|
121
|
-
NSUInteger count = [frameInfo count];
|
|
122
|
-
RCTLogInfo(@"⚡️ [PERF] [Bridge] primeGpuCache called. Count: %lu", (unsigned long)count);
|
|
123
|
-
|
|
124
|
-
// OPTIMIZATION: Dispatch this immediately to a background thread to unblock JS.
|
|
125
|
-
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
126
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
127
|
-
|
|
128
|
-
NSTimeInterval uiBlockTime = [[NSDate date] timeIntervalSince1970];
|
|
129
|
-
RCTLogInfo(@"⚡️ [PERF] [Bridge] primeGpuCache handed to Swift in %.2f ms", (uiBlockTime - start) * 1000);
|
|
130
|
-
|
|
131
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
132
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
133
|
-
[view.layerInstance primeGpuCacheWithFrameInfo:frameInfo];
|
|
134
|
-
}
|
|
135
|
-
}];
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
RCT_EXPORT_METHOD(setActiveFrame:(nonnull NSNumber *)reactTag
|
|
140
|
-
cacheKey:(NSString *)cacheKey)
|
|
141
|
-
{
|
|
142
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
143
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
144
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
145
|
-
[view.layerInstance setActiveFrameWithCacheKey:cacheKey];
|
|
146
|
-
}
|
|
147
|
-
}];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
RCT_EXPORT_METHOD(clearGpuCache:(nonnull NSNumber *)reactTag)
|
|
151
|
-
{
|
|
152
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
153
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
154
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
155
|
-
[view.layerInstance clearGpuCache];
|
|
156
|
-
}
|
|
157
|
-
}];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// ADD THIS METHOD
|
|
161
|
-
RCT_EXPORT_METHOD(setVariable:(nonnull NSNumber *)reactTag
|
|
162
|
-
variable:(NSString *)variable)
|
|
163
|
-
{
|
|
164
|
-
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
165
|
-
GridRenderLayerView *view = (GridRenderLayerView *)viewRegistry[reactTag];
|
|
166
|
-
if ([view isKindOfClass:[GridRenderLayerView class]]) {
|
|
167
|
-
[view setVariable:variable];
|
|
168
|
-
}
|
|
169
|
-
}];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
@end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
#import <UIKit/UIKit.h>
|
|
2
|
-
#import <React/RCTComponent.h>
|
|
3
|
-
|
|
4
|
-
@class GridRenderLayer;
|
|
5
|
-
@class MapView;
|
|
6
|
-
|
|
7
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
-
|
|
9
|
-
@interface GridRenderLayerView : UIView
|
|
10
|
-
|
|
11
|
-
@property (nonatomic, strong) GridRenderLayer *layerInstance;
|
|
12
|
-
@property (nonatomic, weak) MapView *mapView;
|
|
13
|
-
@property (nonatomic, strong) NSString *layerId;
|
|
14
|
-
@property (nonatomic, strong, nullable) NSString *belowID;
|
|
15
|
-
|
|
16
|
-
// Property setters for React Native
|
|
17
|
-
- (void)setOpacity:(float)opacity;
|
|
18
|
-
- (void)setDataRange:(NSArray *)dataRange;
|
|
19
|
-
- (void)setSmoothing:(BOOL)smoothing;
|
|
20
|
-
- (void)setBelowID:(NSString *)belowID;
|
|
21
|
-
- (void)setVariable:(NSString *)variable;
|
|
22
|
-
|
|
23
|
-
// ADD THESE METHOD DECLARATIONS
|
|
24
|
-
- (void)waitForStyleLoadAndAddLayer;
|
|
25
|
-
- (void)pollForLayerExistence;
|
|
26
|
-
- (void)findMapViewAndAddLayerInView:(UIView *)view;
|
|
27
|
-
- (void)addLayerToMap;
|
|
28
|
-
|
|
29
|
-
@end
|
|
30
|
-
|
|
31
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
#import "GridRenderLayerView.h"
|
|
2
|
-
#import <React/RCTLog.h>
|
|
3
|
-
#import <objc/runtime.h>
|
|
4
|
-
|
|
5
|
-
// Import Swift bridging header
|
|
6
|
-
#if __has_include("aguacerowx_react_native-Swift.h")
|
|
7
|
-
#import "aguacerowx_react_native-Swift.h"
|
|
8
|
-
#else
|
|
9
|
-
#import <aguacerowx_react_native/aguacerowx_react_native-Swift.h>
|
|
10
|
-
#endif
|
|
11
|
-
|
|
12
|
-
// Import MapboxMaps to get MapView definition
|
|
13
|
-
@import MapboxMaps;
|
|
14
|
-
|
|
15
|
-
@interface GridRenderLayerView ()
|
|
16
|
-
@property (nonatomic, assign) BOOL isLayerAdded;
|
|
17
|
-
@end
|
|
18
|
-
|
|
19
|
-
@implementation GridRenderLayerView
|
|
20
|
-
- (instancetype)init {
|
|
21
|
-
self = [super init];
|
|
22
|
-
if (self) {
|
|
23
|
-
_layerId = [NSString stringWithFormat:@"weather-layer-%@", [[NSUUID UUID] UUIDString]];
|
|
24
|
-
_layerInstance = [[GridRenderLayer alloc] initWithId:_layerId];
|
|
25
|
-
_isLayerAdded = NO;
|
|
26
|
-
}
|
|
27
|
-
return self;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
#pragma mark - Property Setters
|
|
31
|
-
|
|
32
|
-
- (void)setOpacity:(float)opacity {
|
|
33
|
-
[self.layerInstance setOpacityWithValue:opacity];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
- (void)setDataRange:(NSArray *)dataRange {
|
|
37
|
-
if (dataRange && dataRange.count == 2) {
|
|
38
|
-
[self.layerInstance setDataRangeWithValue:dataRange];
|
|
39
|
-
} else {
|
|
40
|
-
RCTLogError(@"❌ [GridRenderLayerView] Invalid dataRange: %@", dataRange);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
- (void)setSmoothing:(BOOL)smoothing {
|
|
45
|
-
[self.layerInstance setSmoothingWithValue:smoothing];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
- (void)setBelowID:(NSString *)belowID {
|
|
49
|
-
_belowID = belowID;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ADD THIS METHOD
|
|
53
|
-
- (void)setVariable:(NSString *)variable {
|
|
54
|
-
[self.layerInstance setVariableWithVariable:variable];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
#pragma mark - View Lifecycle
|
|
58
|
-
|
|
59
|
-
- (void)didMoveToWindow {
|
|
60
|
-
[super didMoveToWindow];
|
|
61
|
-
if (self.window && !self.isLayerAdded) {
|
|
62
|
-
[self findMapViewAndAddLayerInView:self.window];
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
- (void)layoutSubviews {
|
|
67
|
-
[super layoutSubviews];
|
|
68
|
-
|
|
69
|
-
static dispatch_once_t onceToken;
|
|
70
|
-
dispatch_once(&onceToken, ^{
|
|
71
|
-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
72
|
-
if (!self.isLayerAdded) {
|
|
73
|
-
UIView *searchRoot = self.window ? self.window : self.superview;
|
|
74
|
-
if (searchRoot) {
|
|
75
|
-
[self findMapViewAndAddLayerInView:searchRoot];
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
- (void)findMapViewAndAddLayerInView:(UIView *)view {
|
|
83
|
-
if (!view || self.isLayerAdded) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
NSString *className = NSStringFromClass([view class]);
|
|
88
|
-
|
|
89
|
-
if ([className isEqualToString:@"RNMBXMapView"]) {
|
|
90
|
-
if (view.subviews.count > 0) {
|
|
91
|
-
UIView *firstSubview = view.subviews[0];
|
|
92
|
-
NSString *subviewClass = NSStringFromClass([firstSubview class]);
|
|
93
|
-
if ([subviewClass containsString:@"MapboxMaps.MapView"] || [subviewClass isEqualToString:@"MapView"]) {
|
|
94
|
-
self.mapView = (MapView *)firstSubview;
|
|
95
|
-
[self waitForStyleLoadAndAddLayer];
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
RCTLogError(@"❌ [GridRenderLayerView] RNMBXMapView found but MapboxMaps.MapView not in expected location");
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
for (UIView *subview in view.subviews) {
|
|
105
|
-
[self findMapViewAndAddLayerInView:subview];
|
|
106
|
-
if (self.isLayerAdded) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
- (void)waitForStyleLoadAndAddLayer {
|
|
113
|
-
if (!self.mapView) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
NSString *targetLayer = self.belowID ?: @"AML_-_terrain";
|
|
118
|
-
|
|
119
|
-
// Check if the target layer already exists
|
|
120
|
-
if ([GridRenderLayerBridge layerExistsIn:self.mapView layerId:targetLayer]) {
|
|
121
|
-
[self addLayerToMap];
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
[self pollForLayerExistence];
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
- (void)pollForLayerExistence {
|
|
129
|
-
if (self.isLayerAdded || !self.mapView) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
NSString *targetLayer = self.belowID ?: @"AML_-_terrain";
|
|
134
|
-
|
|
135
|
-
if ([GridRenderLayerBridge layerExistsIn:self.mapView layerId:targetLayer]) {
|
|
136
|
-
[self addLayerToMap];
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Try again in 100ms
|
|
141
|
-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
142
|
-
[self pollForLayerExistence];
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
- (void)addLayerToMap {
|
|
147
|
-
if (!self.mapView || self.isLayerAdded) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
id customLayer = [self.layerInstance getHostWrapper];
|
|
152
|
-
|
|
153
|
-
if (!customLayer) {
|
|
154
|
-
RCTLogError(@"❌ [GridRenderLayerView] Failed to get hostWrapper");
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
BOOL success = [GridRenderLayerBridge addCustomLayerTo:self.mapView
|
|
159
|
-
layerHost:customLayer
|
|
160
|
-
layerId:self.layerId
|
|
161
|
-
belowLayerId:self.belowID];
|
|
162
|
-
|
|
163
|
-
if (success) {
|
|
164
|
-
self.isLayerAdded = YES;
|
|
165
|
-
|
|
166
|
-
[[NSNotificationCenter defaultCenter] addObserverForName:@"TriggerMapRepaint"
|
|
167
|
-
object:nil
|
|
168
|
-
queue:[NSOperationQueue mainQueue]
|
|
169
|
-
usingBlock:^(NSNotification *note) {
|
|
170
|
-
if (self.mapView) {
|
|
171
|
-
[GridRenderLayerBridge triggerRepaintOn:self.mapView];
|
|
172
|
-
}
|
|
173
|
-
}];
|
|
174
|
-
} else {
|
|
175
|
-
RCTLogError(@"❌ [GridRenderLayerView] Failed to add layer via Swift bridge");
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
- (void)removeFromSuperview {
|
|
180
|
-
if (self.mapView && self.isLayerAdded) {
|
|
181
|
-
[GridRenderLayerBridge removeCustomLayerFrom:self.mapView layerId:self.layerId];
|
|
182
|
-
}
|
|
183
|
-
[super removeFromSuperview];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
- (void)dealloc {
|
|
187
|
-
RCTLogInfo(@"🔴 [GridRenderLayerView] dealloc called");
|
|
188
|
-
|
|
189
|
-
// Remove notification observer
|
|
190
|
-
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
191
|
-
|
|
192
|
-
// Clear the layer instance
|
|
193
|
-
if (_layerInstance) {
|
|
194
|
-
[_layerInstance clear];
|
|
195
|
-
_layerInstance = nil;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
_mapView = nil;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
@end
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
|
|
3
|
-
final class InspectorDataCache {
|
|
4
|
-
static let shared = InspectorDataCache()
|
|
5
|
-
private let queue = DispatchQueue(label: "com.aguacerowx.InspectorDataCacheQueue", attributes: .concurrent)
|
|
6
|
-
|
|
7
|
-
private var _filePath: String?
|
|
8
|
-
private var _nx: Int = 0
|
|
9
|
-
private var _ny: Int = 0
|
|
10
|
-
private var _scale: Float = 1.0
|
|
11
|
-
private var _offset: Float = 0.0
|
|
12
|
-
private var _missing: Float = 127.0
|
|
13
|
-
private var _scaleType: Int = 0
|
|
14
|
-
|
|
15
|
-
private init() {}
|
|
16
|
-
|
|
17
|
-
var filePath: String? { queue.sync { _filePath } }
|
|
18
|
-
var nx: Int { queue.sync { _nx } }
|
|
19
|
-
var ny: Int { queue.sync { _ny } }
|
|
20
|
-
var scale: Float { queue.sync { _scale } }
|
|
21
|
-
var offset: Float { queue.sync { _offset } }
|
|
22
|
-
var missing: Float { queue.sync { _missing } }
|
|
23
|
-
var scaleType: Int { queue.sync { _scaleType } }
|
|
24
|
-
|
|
25
|
-
// Keep this signature so existing callers don't break - just ignore the data param
|
|
26
|
-
func update(data: Data?, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int = 0) {
|
|
27
|
-
queue.async(flags: .barrier) {
|
|
28
|
-
self._nx = nx
|
|
29
|
-
self._ny = ny
|
|
30
|
-
self._scale = scale
|
|
31
|
-
self._offset = offset
|
|
32
|
-
self._missing = missing
|
|
33
|
-
self._scaleType = scaleType
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
func updateFilePath(_ path: String) {
|
|
38
|
-
queue.async(flags: .barrier) {
|
|
39
|
-
self._filePath = path
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Convenience: update everything at once
|
|
44
|
-
func updateWithFilePath(filePath: String, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int = 0) {
|
|
45
|
-
queue.async(flags: .barrier) {
|
|
46
|
-
self._filePath = filePath
|
|
47
|
-
self._nx = nx
|
|
48
|
-
self._ny = ny
|
|
49
|
-
self._scale = scale
|
|
50
|
-
self._offset = offset
|
|
51
|
-
self._missing = missing
|
|
52
|
-
self._scaleType = scaleType
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
func clear() {
|
|
57
|
-
queue.async(flags: .barrier) {
|
|
58
|
-
self._filePath = nil
|
|
59
|
-
self._nx = 0
|
|
60
|
-
self._ny = 0
|
|
61
|
-
self._scaleType = 0
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#import <React/RCTBridgeModule.h>
|
|
2
|
-
|
|
3
|
-
@interface RCT_EXTERN_MODULE(InspectorModule, NSObject)
|
|
4
|
-
|
|
5
|
-
RCT_EXTERN_METHOD(getValueAtGridIndex:(nonnull NSNumber *)i
|
|
6
|
-
j:(nonnull NSNumber *)j
|
|
7
|
-
resolver:(RCTPromiseResolveBlock)resolve
|
|
8
|
-
rejecter:(RCTPromiseRejectBlock)reject)
|
|
9
|
-
|
|
10
|
-
@end
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import React
|
|
3
|
-
import libzstd
|
|
4
|
-
|
|
5
|
-
@objc(InspectorModule)
|
|
6
|
-
class InspectorModule: NSObject {
|
|
7
|
-
|
|
8
|
-
@objc(getValueAtGridIndex:j:resolver:rejecter:)
|
|
9
|
-
func getValueAtGridIndex(
|
|
10
|
-
i: NSNumber,
|
|
11
|
-
j: NSNumber,
|
|
12
|
-
resolve: @escaping RCTPromiseResolveBlock,
|
|
13
|
-
reject: @escaping RCTPromiseRejectBlock
|
|
14
|
-
) {
|
|
15
|
-
DispatchQueue.global(qos: .userInitiated).async {
|
|
16
|
-
let cache = InspectorDataCache.shared
|
|
17
|
-
|
|
18
|
-
guard let filePath = cache.filePath else {
|
|
19
|
-
resolve(nil)
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let nx = cache.nx
|
|
24
|
-
let ny = cache.ny
|
|
25
|
-
let scale = cache.scale
|
|
26
|
-
let offset = cache.offset
|
|
27
|
-
let missing = cache.missing
|
|
28
|
-
let scaleType = cache.scaleType
|
|
29
|
-
|
|
30
|
-
let iVal = i.intValue
|
|
31
|
-
let jVal = j.intValue
|
|
32
|
-
let index = jVal * nx + iVal
|
|
33
|
-
|
|
34
|
-
guard index >= 0 && index < (nx * ny) else {
|
|
35
|
-
print("🔍 [Inspector] ERROR: Index out of bounds")
|
|
36
|
-
resolve(nil)
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Read and decompress the file
|
|
41
|
-
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
|
|
42
|
-
print("🔍 [Inspector] ERROR: Could not read file at \(filePath)")
|
|
43
|
-
resolve(nil)
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
guard var decompressed = self.decompressZstd(data: fileData) else {
|
|
48
|
-
print("🔍 [Inspector] ERROR: Failed to decompress")
|
|
49
|
-
resolve(nil)
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Reconstruct delta encoding (same as GridRenderLayer)
|
|
54
|
-
self.reconstructInPlace(data: &decompressed)
|
|
55
|
-
|
|
56
|
-
guard index < decompressed.count else {
|
|
57
|
-
resolve(nil)
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
let rawByte = decompressed[index]
|
|
62
|
-
// After reconstructInPlace, bytes are raw signed values stored as UInt8
|
|
63
|
-
// The value is the signed Int8 interpretation
|
|
64
|
-
let signedQuantizedValue = Int(Int8(bitPattern: rawByte))
|
|
65
|
-
let missingQuantized = Int(round(missing))
|
|
66
|
-
|
|
67
|
-
if abs(signedQuantizedValue - missingQuantized) < 1 {
|
|
68
|
-
resolve(nil)
|
|
69
|
-
return
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
let intermediateValue = Double(signedQuantizedValue) * Double(scale) + Double(offset)
|
|
73
|
-
let finalValue = scaleType == 1 ? intermediateValue * abs(intermediateValue) : intermediateValue
|
|
74
|
-
|
|
75
|
-
resolve(finalValue)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Reconstruct delta encoding only (no +128 shift, we want signed values)
|
|
80
|
-
private func reconstructInPlace(data: inout Data) {
|
|
81
|
-
let count = data.count
|
|
82
|
-
guard count > 0 else { return }
|
|
83
|
-
data.withUnsafeMutableBytes { rawBuffer in
|
|
84
|
-
guard let ptr = rawBuffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { return }
|
|
85
|
-
var running = Int8(bitPattern: ptr[0])
|
|
86
|
-
// Leave ptr[0] as-is (it's already the first value)
|
|
87
|
-
for i in 1..<count {
|
|
88
|
-
let delta = Int8(bitPattern: ptr[i])
|
|
89
|
-
running = running &+ delta
|
|
90
|
-
ptr[i] = UInt8(bitPattern: running)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private func decompressZstd(data: Data) -> Data? {
|
|
96
|
-
let decompressedSize = data.withUnsafeBytes { ptr in
|
|
97
|
-
ZSTD_getFrameContentSize(ptr.baseAddress, data.count)
|
|
98
|
-
}
|
|
99
|
-
guard Int64(bitPattern: decompressedSize) > 0 else { return nil }
|
|
100
|
-
|
|
101
|
-
var decompressedData = Data(count: Int(decompressedSize))
|
|
102
|
-
let result = decompressedData.withUnsafeMutableBytes { decompPtr in
|
|
103
|
-
data.withUnsafeBytes { compPtr in
|
|
104
|
-
Int(ZSTD_decompress(decompPtr.baseAddress, Int(decompressedSize), compPtr.baseAddress, data.count))
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
guard result > 0 && result == decompressedData.count else { return nil }
|
|
108
|
-
return decompressedData
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
@objc
|
|
112
|
-
static func requiresMainQueueSetup() -> Bool { return false }
|
|
113
|
-
}
|