@aguacerowx/react-native 0.0.21 β†’ 0.0.23

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 (100) hide show
  1. package/aguacerowx-react-native.podspec +5 -20
  2. package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/transformed/classes/classes_dex/classes.dex +0 -0
  3. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.dex +0 -0
  4. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer.dex +0 -0
  5. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  6. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  7. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  8. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  9. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  10. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +18 -8
  11. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  12. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  13. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  14. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
  15. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
  16. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  17. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +8 -1
  18. package/android/src/main/res/raw/fragment_shader.glsl +18 -8
  19. package/ios/FragmentUniforms.swift +1 -0
  20. package/ios/GridRenderLayer.swift +117 -109
  21. package/ios/GridRenderLayerBridge.swift +11 -3
  22. package/ios/GridRenderLayerView.h +15 -1
  23. package/ios/GridRenderLayerView.m +65 -28
  24. package/ios/Shaders.metal +25 -13
  25. package/ios/compiled-shaders/Shaders-device.metallib +0 -0
  26. package/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  27. package/lib/commonjs/aguacerowx-react-native.podspec +5 -20
  28. package/lib/commonjs/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  29. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  30. package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  31. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  32. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  33. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +18 -8
  34. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  35. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  36. package/lib/commonjs/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  37. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
  38. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
  39. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  40. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +8 -1
  41. package/lib/commonjs/android/src/main/res/raw/fragment_shader.glsl +18 -8
  42. package/lib/commonjs/ios/FragmentUniforms.swift +1 -0
  43. package/lib/commonjs/ios/GridRenderLayer.swift +117 -109
  44. package/lib/commonjs/ios/GridRenderLayerBridge.swift +11 -3
  45. package/lib/commonjs/ios/GridRenderLayerView.h +15 -1
  46. package/lib/commonjs/ios/GridRenderLayerView.m +65 -28
  47. package/lib/commonjs/ios/Shaders.metal +25 -13
  48. package/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
  49. package/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  50. package/lib/commonjs/package.json +2 -2
  51. package/lib/commonjs/scripts/compile-shaders.js.map +1 -1
  52. package/lib/commonjs/src/WeatherLayerManager.js +50 -5
  53. package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  54. package/lib/module/aguacerowx-react-native.podspec +5 -20
  55. package/lib/module/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  56. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  57. package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  58. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  59. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  60. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +18 -8
  61. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  62. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  63. package/lib/module/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  64. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
  65. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
  66. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  67. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +8 -1
  68. package/lib/module/android/src/main/res/raw/fragment_shader.glsl +18 -8
  69. package/lib/module/ios/FragmentUniforms.swift +1 -0
  70. package/lib/module/ios/GridRenderLayer.swift +117 -109
  71. package/lib/module/ios/GridRenderLayerBridge.swift +11 -3
  72. package/lib/module/ios/GridRenderLayerView.h +15 -1
  73. package/lib/module/ios/GridRenderLayerView.m +65 -28
  74. package/lib/module/ios/Shaders.metal +25 -13
  75. package/lib/module/ios/compiled-shaders/Shaders-device.metallib +0 -0
  76. package/lib/module/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  77. package/lib/module/lib/commonjs/aguacerowx-react-native.podspec +5 -20
  78. package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +1 -0
  79. package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +117 -109
  80. package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +11 -3
  81. package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +15 -1
  82. package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +65 -28
  83. package/lib/module/lib/commonjs/ios/Shaders.metal +25 -13
  84. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
  85. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  86. package/lib/module/lib/commonjs/package.json +2 -2
  87. package/lib/module/lib/commonjs/scripts/compile-shaders.js.map +1 -1
  88. package/lib/module/lib/commonjs/src/WeatherLayerManager.js +50 -5
  89. package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  90. package/lib/module/package.json +2 -2
  91. package/lib/module/scripts/compile-shaders.js.map +1 -1
  92. package/lib/module/src/WeatherLayerManager.js +50 -5
  93. package/lib/module/src/WeatherLayerManager.js.map +1 -1
  94. package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
  95. package/package.json +2 -2
  96. package/src/WeatherLayerManager.js +208 -165
  97. package/ios/compiled-shaders/Shaders.metallib +0 -0
  98. package/lib/commonjs/ios/compiled-shaders/Shaders.metallib +0 -0
  99. package/lib/module/ios/compiled-shaders/Shaders.metallib +0 -0
  100. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders.metallib +0 -0
@@ -22,8 +22,9 @@ struct FragmentUniforms {
22
22
  float missingQuantized;
23
23
  float2 textureSize;
24
24
  int smoothing;
25
- int scaleType; // 0 for linear, 1 for sqrt
26
- int isPtype; // ADD THIS
25
+ int scaleType;
26
+ int isPtype;
27
+ int isMRMS;
27
28
  };
28
29
 
29
30
  // --- Vertex Shader (Unchanged) ---
@@ -64,15 +65,26 @@ float get_value(texture2d<float, access::sample> dataTexture, sampler dataSample
64
65
  }
65
66
 
66
67
  // Maps a physical value to a precipitation type category
67
- float get_ptype_from_physical(float val) {
68
- if (val < 0.0) return -1.0; // Missing/Invalid
69
- if (val < 100.0) return 0.0; // Rain
70
- if (val < 200.0) return 1.0; // Mix
71
- if (val < 300.0) return 2.0; // Snow
72
- return 3.0; // Pellets
68
+ // Maps a physical value to a precipitation type category
69
+ float get_ptype_from_physical(float val, constant FragmentUniforms &uniforms) { // ADD uniforms parameter
70
+ if (val < 0.0) return -1.0;
71
+
72
+ if (uniforms.isMRMS == 1) { // ADD THIS BRANCH
73
+ // MRMS: 0-100 rain, 100-200 snow, 200-300 freezing rain
74
+ if (val < 100.0) return 0.0;
75
+ if (val < 200.0) return 1.0;
76
+ if (val < 300.0) return 2.0;
77
+ return -1.0;
78
+ } else {
79
+ // Models: 0-100 rain, 100-200 snow, 200-300 freezing rain, 300-400 ice pellets
80
+ if (val < 100.0) return 0.0;
81
+ if (val < 200.0) return 1.0;
82
+ if (val < 300.0) return 2.0;
83
+ if (val < 400.0) return 3.0;
84
+ return -1.0;
85
+ }
73
86
  }
74
87
 
75
-
76
88
  // --- Main Fragment Shader ---
77
89
  fragment float4 fragment_main(RasterizerData in [[stage_in]],
78
90
  constant FragmentUniforms &uniforms [[buffer(0)]],
@@ -110,10 +122,10 @@ fragment float4 fragment_main(RasterizerData in [[stage_in]],
110
122
  float v01 = dequantize_val(get_value(dataTexture, dataSampler, v01_coord, uniforms), uniforms);
111
123
  float v11 = dequantize_val(get_value(dataTexture, dataSampler, v11_coord, uniforms), uniforms);
112
124
 
113
- float p00 = get_ptype_from_physical(v00);
114
- float p10 = get_ptype_from_physical(v10);
115
- float p01 = get_ptype_from_physical(v01);
116
- float p11 = get_ptype_from_physical(v11);
125
+ float p00 = get_ptype_from_physical(v00, uniforms);
126
+ float p10 = get_ptype_from_physical(v10, uniforms);
127
+ float p01 = get_ptype_from_physical(v01, uniforms);
128
+ float p11 = get_ptype_from_physical(v11, uniforms);
117
129
 
118
130
  // Determine the dominant precipitation type for this pixel
119
131
  float dominant_ptype = -1.0;
@@ -24,26 +24,11 @@ Pod::Spec.new do |s|
24
24
  'DEFINES_MODULE' => 'YES'
25
25
  }
26
26
 
27
- s.resources = ['ios/compiled-shaders/*.metallib', 'ios/*.metal']
28
-
29
- s.script_phases = [
30
- {
31
- :name => 'Copy Metal Shaders',
32
- :script => 'echo "πŸ”¨ Copying Metal shaders..."
33
- SHADER_DIR="${PODS_TARGET_SRCROOT}/ios/compiled-shaders"
34
- METAL_SOURCE="${PODS_TARGET_SRCROOT}/ios/Shaders.metal"
35
-
36
- if [ -f "$SHADER_DIR/Shaders.metallib" ]; then
37
- cp -v "$SHADER_DIR/Shaders.metallib" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/" || true
38
- echo "βœ… Pre-compiled Metal shader copied"
39
- elif [ -f "$METAL_SOURCE" ]; then
40
- echo "⚠️ No pre-compiled shader found, will compile from source"
41
- cp -v "$METAL_SOURCE" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/" || true
42
- else
43
- echo "❌ No Metal shaders found!"
44
- fi',
45
- :execution_position => :before_compile
46
- }
27
+ # Include both pre-compiled shaders AND source as fallback
28
+ s.resources = [
29
+ 'ios/compiled-shaders/Shaders-simulator.metallib',
30
+ 'ios/compiled-shaders/Shaders-device.metallib',
31
+ 'ios/Shaders.metal'
47
32
  ]
48
33
 
49
34
  s.source_files = "ios/**/*.{h,m,mm,swift}", "ios/generated/**/*.{h,m,mm,cpp}"
@@ -12,4 +12,5 @@ struct FragmentUniforms {
12
12
  var smoothing: Int32
13
13
  var scaleType: Int32
14
14
  var isPtype: Int32
15
+ var isMRMS: Int32
15
16
  }
@@ -61,7 +61,8 @@ public class GridRenderLayer: NSObject {
61
61
  textureSize: SIMD2<Float>(0.0, 0.0),
62
62
  smoothing: 1,
63
63
  scaleType: 0,
64
- isPtype: 0 // ADD THIS
64
+ isPtype: 0,
65
+ isMRMS: 0
65
66
  )
66
67
  private var isVisible = false
67
68
  private var pendingActiveFrameKey: String?
@@ -75,15 +76,13 @@ public class GridRenderLayer: NSObject {
75
76
  let nx: Float
76
77
  let ny: Float
77
78
  let filePath: String
78
- let originalScale: Float // ADD THIS
79
- let originalOffset: Float // ADD THIS
79
+ let originalScale: Float
80
+ let originalOffset: Float
80
81
  }
81
82
  private var frameCache: [String: FrameMetadata] = [:]
82
- private let highPriorityTextureQueue = DispatchQueue(label: "com.aguacero.texture-processing-high-priority", qos: .userInitiated)
83
+ private let frameProcessingQueue = DispatchQueue(label: "com.aguacero.frame-processing", qos: .userInitiated, attributes: .concurrent)
84
+ private let semaphore = DispatchSemaphore(value: 8)
83
85
 
84
- // The concurrent queue for background preloading all other frames.
85
- private let backgroundTextureQueue = DispatchQueue(label: "com.aguacero.texture-processing-background", qos: .utility, attributes: .concurrent)
86
- // MARK: - Initializer
87
86
  private struct VertexInfo {
88
87
  var mercX: Float
89
88
  var mercY: Float
@@ -125,6 +124,13 @@ public class GridRenderLayer: NSObject {
125
124
  // ADD THIS: Force the map to repaint to show the smoothing change immediately.
126
125
  NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
127
126
  }
127
+
128
+ @objc(setIsMRMSWithIsMRMS:)
129
+ public func setIsMRMS(isMRMS: Bool) {
130
+ self.uniforms.isMRMS = isMRMS ? 1 : 0
131
+ print("🟒 [GridRenderLayer] Set isMRMS: \(isMRMS)")
132
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
133
+ }
128
134
 
129
135
  // ADD THIS METHOD
130
136
  @objc(setVariableWithVariable:)
@@ -182,11 +188,10 @@ public class GridRenderLayer: NSObject {
182
188
  self.colormapTexture = texture
183
189
  }
184
190
 
185
- @objc(clearGpuCache) // Explicitly name the Obj-C selector
191
+ @objc(clearGpuCache)
186
192
  public func clearGpuCache() {
187
- backgroundTextureQueue.async {
188
- self.frameCache.removeAll()
189
- print("🟒 [GridRenderLayer] GPU frame cache cleared.")
193
+ frameProcessingQueue.async { [weak self] in
194
+ self?.frameCache.removeAll()
190
195
  }
191
196
  }
192
197
 
@@ -219,42 +224,39 @@ public class GridRenderLayer: NSObject {
219
224
  }
220
225
 
221
226
  private func updateInspectorCache(filePath: String, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int) {
222
- highPriorityTextureQueue.async {
223
-
224
- guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
225
- print("❌ [Inspector] FATAL: Failed to read file data from path.")
226
- self.inspectorCache.clear()
227
- return
228
- }
229
- print("πŸ’‘ [Inspector] 2. Successfully read \(fileData.count) bytes from file.")
230
-
231
- guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
232
- print("❌ [Inspector] FATAL: Failed to decompress Zstd data.")
233
- self.inspectorCache.clear()
234
- return
235
- }
236
- print("πŸ’‘ [Inspector] 3. Successfully decompressed data.")
237
-
238
- let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
239
- print("πŸ’‘ [Inspector] 4. Reconstructed data with \(reconstructedData.count) bytes.")
240
-
241
- self.inspectorCache.update(
242
- data: reconstructedData,
243
- nx: nx,
244
- ny: ny,
245
- scale: scale,
246
- offset: offset,
247
- missing: missing,
248
- scaleType: scaleType
249
- )
250
-
251
- print("πŸ’‘ [Inspector] 5. βœ… Cache updated successfully with scaleType=\(scaleType)")
227
+ // This is now called from frameProcessingQueue, so we can do the work synchronously
228
+ guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
229
+ print("❌ [Inspector] FATAL: Failed to read file data from path.")
230
+ self.inspectorCache.clear()
231
+ return
232
+ }
233
+ print("πŸ’‘ [Inspector] 2. Successfully read \(fileData.count) bytes from file.")
234
+
235
+ guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
236
+ print("❌ [Inspector] FATAL: Failed to decompress Zstd data.")
237
+ self.inspectorCache.clear()
238
+ return
252
239
  }
240
+ print("πŸ’‘ [Inspector] 3. Successfully decompressed data.")
241
+
242
+ let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
243
+ print("πŸ’‘ [Inspector] 4. Reconstructed data with \(reconstructedData.count) bytes.")
244
+
245
+ self.inspectorCache.update(
246
+ data: reconstructedData,
247
+ nx: nx,
248
+ ny: ny,
249
+ scale: scale,
250
+ offset: offset,
251
+ missing: missing,
252
+ scaleType: scaleType
253
+ )
254
+
255
+ print("πŸ’‘ [Inspector] 5. βœ… Cache updated successfully with scaleType=\(scaleType)")
253
256
  }
254
257
 
255
258
  @objc(setActiveFrameWithCacheKey:)
256
259
  public func setActiveFrame(cacheKey: String) {
257
- // First, check if the frame is already in the cache.
258
260
  if let frame = frameCache[cacheKey] {
259
261
  print("⚑️ [GridRenderLayer] Cache HIT for key: \(cacheKey). Swapping texture.")
260
262
 
@@ -266,42 +268,51 @@ public class GridRenderLayer: NSObject {
266
268
  self.uniforms.scaleType = Int32(frame.scaleType)
267
269
 
268
270
  self.isVisible = true
269
- self.pendingActiveFrameKey = nil // Clear any pending key
271
+ self.pendingActiveFrameKey = nil
270
272
  NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
271
273
 
272
- // --- ADD THIS ---
273
- // Now that the frame is active, update the inspector cache with its data.
274
- self.updateInspectorCache(
275
- filePath: frame.filePath,
276
- nx: Int(frame.nx),
277
- ny: Int(frame.ny),
278
- scale: frame.scale,
279
- offset: frame.offset,
280
- missing: frame.missing,
281
- scaleType: frame.scaleType
282
- )
274
+ // Update inspector cache on background thread since we already have the frame data
275
+ frameProcessingQueue.async { [weak self] in
276
+ self?.updateInspectorCache(
277
+ filePath: frame.filePath,
278
+ nx: Int(frame.nx),
279
+ ny: Int(frame.ny),
280
+ scale: frame.scale,
281
+ offset: frame.offset,
282
+ missing: frame.missing,
283
+ scaleType: frame.scaleType
284
+ )
285
+ }
283
286
 
284
287
  } else {
285
- // --- FIX: If it's a miss, store the key and wait for it to be primed. ---
286
288
  print("⚠️ [GridRenderLayer] setActiveFrame cache MISS for key: \(cacheKey). Will apply when primed.")
287
289
  self.pendingActiveFrameKey = cacheKey
288
- self.isVisible = false // Hide the layer until the frame is ready
290
+ self.isVisible = false
289
291
  }
290
292
  }
291
-
292
293
  @objc(primeGpuCacheWithFrameInfo:)
293
294
  public func primeGpuCache(frameInfo: [String: [String: Any]]) {
294
295
  let group = DispatchGroup()
295
296
 
296
297
  if (frameInfo.count > 1) {
297
- print("🟑 [GridRenderLayer] Starting to prime \(frameInfo.count) textures concurrently...")
298
+ print("🟑 [GridRenderLayer] Starting to prime \(frameInfo.count) textures with concurrent processing...")
298
299
  }
299
300
 
300
301
  for (cacheKey, info) in frameInfo {
301
302
  group.enter()
302
303
 
303
- backgroundTextureQueue.async {
304
- defer { group.leave() }
304
+ frameProcessingQueue.async { [weak self] in
305
+ guard let self = self else {
306
+ group.leave()
307
+ return
308
+ }
309
+
310
+ self.semaphore.wait()
311
+ defer {
312
+ self.semaphore.signal()
313
+ group.leave()
314
+ }
315
+
305
316
  if self.frameCache[cacheKey] != nil { return }
306
317
 
307
318
  guard let filePath = info["filePath"] as? String,
@@ -311,16 +322,25 @@ public class GridRenderLayer: NSObject {
311
322
  let offset = info["offset"] as? NSNumber,
312
323
  let missing = info["missing"] as? NSNumber,
313
324
  let scaleTypeStr = info["scaleType"] as? String,
314
- let originalScale = info["originalScale"] as? NSNumber, // ADD THIS
315
- let originalOffset = info["originalOffset"] as? NSNumber, // ADD THIS
316
- let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
317
- let finalTextureBytes = self.processRawData(fileData: fileData)
325
+ let originalScale = info["originalScale"] as? NSNumber,
326
+ let originalOffset = info["originalOffset"] as? NSNumber
318
327
  else {
319
328
  print("❌ [GridRenderLayer] Skipping prime for \(cacheKey), missing data.")
320
329
  return
321
330
  }
322
331
 
323
- DispatchQueue.main.sync {
332
+ // Process data OFF the main thread
333
+ guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
334
+ let finalTextureBytes = self.processRawData(fileData: fileData)
335
+ else {
336
+ print("❌ [GridRenderLayer] Failed to process data for \(cacheKey)")
337
+ return
338
+ }
339
+
340
+ // Create texture on main thread
341
+ DispatchQueue.main.async { [weak self] in
342
+ guard let self = self else { return }
343
+
324
344
  if let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) {
325
345
  let metadata = FrameMetadata(
326
346
  texture: texture,
@@ -331,11 +351,10 @@ public class GridRenderLayer: NSObject {
331
351
  nx: nx.floatValue,
332
352
  ny: ny.floatValue,
333
353
  filePath: filePath,
334
- originalScale: originalScale.floatValue, // ADD THIS
335
- originalOffset: originalOffset.floatValue // ADD THIS
354
+ originalScale: originalScale.floatValue,
355
+ originalOffset: originalOffset.floatValue
336
356
  )
337
357
  self.frameCache[cacheKey] = metadata
338
- print(" βœ… [GridRenderLayer] Primed and cached frame for key: \(cacheKey)")
339
358
 
340
359
  if let pendingKey = self.pendingActiveFrameKey, pendingKey == cacheKey {
341
360
  print("πŸ‘ [GridRenderLayer] The pending frame is now ready. Activating it.")
@@ -348,7 +367,7 @@ public class GridRenderLayer: NSObject {
348
367
 
349
368
  group.notify(queue: .main) {
350
369
  if (frameInfo.count > 1) {
351
- print("πŸŽ‰ [GridRenderLayer] All \(frameInfo.count) frames have been processed and cached to the GPU.")
370
+ print("πŸŽ‰ [GridRenderLayer] All \(frameInfo.count) frames have been processed and cached.")
352
371
  }
353
372
  }
354
373
  }
@@ -356,19 +375,20 @@ public class GridRenderLayer: NSObject {
356
375
  @objc public func updateDataTexture(data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String) {
357
376
  print("πŸš€ [GridRenderLayer] FAST LANE: updateDataTexture called for initial frame...")
358
377
 
359
- let filePath = data // Assuming 'data' is always the file path for this method.
378
+ let filePath = data
360
379
 
361
- // USE THE HIGH-PRIORITY QUEUE
362
- highPriorityTextureQueue.async {
363
- guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else { return }
380
+ frameProcessingQueue.async { [weak self] in
381
+ guard let self = self else { return }
364
382
 
365
- guard let finalTextureBytes = self.processRawData(fileData: fileData) else {
383
+ guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
384
+ let finalTextureBytes = self.processRawData(fileData: fileData)
385
+ else {
366
386
  print("❌ [GridRenderLayer] FAST LANE: Failed to process initial frame data.")
367
387
  return
368
388
  }
369
389
 
370
- DispatchQueue.main.async {
371
- guard let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) else {
390
+ DispatchQueue.main.async { [weak self] in
391
+ guard let self = self, let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) else {
372
392
  return
373
393
  }
374
394
 
@@ -383,8 +403,6 @@ public class GridRenderLayer: NSObject {
383
403
  print("βœ… [GridRenderLayer] FAST LANE: Initial frame processed and displayed.")
384
404
  NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
385
405
 
386
- // --- ADD THIS ---
387
- // Update the inspector cache for the initial frame.
388
406
  self.updateInspectorCache(
389
407
  filePath: filePath,
390
408
  nx: nx.intValue,
@@ -399,9 +417,6 @@ public class GridRenderLayer: NSObject {
399
417
  }
400
418
 
401
419
  @objc public func updateGeometry(corners: [String: Any], gridDef: [String: Any]) {
402
- print("🟒 [GridRenderLayer] updateGeometry called")
403
- print(" device: \(self.device != nil)")
404
-
405
420
  guard self.device != nil else {
406
421
  print("⚠️ [GridRenderLayer] Device not ready yet, storing geometry for later")
407
422
  pendingGeometryUpdate = (corners: corners, gridDef: gridDef)
@@ -423,8 +438,6 @@ public class GridRenderLayer: NSObject {
423
438
  return
424
439
  }
425
440
 
426
- print(" βœ… Generated \(vertices.count/4) vertices, \(indices.count/3) triangles")
427
-
428
441
  self.indexCount = indices.count
429
442
 
430
443
  DispatchQueue.main.async {
@@ -438,7 +451,6 @@ public class GridRenderLayer: NSObject {
438
451
  print(" indexBuffer: \(self.indexBuffer != nil)")
439
452
  print(" indexCount: \(self.indexCount)")
440
453
 
441
- // TRIGGER A REPAINT - ADD THIS:
442
454
  NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
443
455
  }
444
456
  }
@@ -610,11 +622,11 @@ public class GridRenderLayer: NSObject {
610
622
 
611
623
  private func lccToLonLat(i: Double, j: Double, gridDef: [String: Any]) -> (lon: Double, lat: Double)? {
612
624
  guard let projParams = gridDef["proj_params"] as? [String: Any],
613
- let lat_0 = projParams["lat_0"] as? Double, // latitude of origin
614
- let lon_0 = projParams["lon_0"] as? Double, // longitude of origin
615
- let lat_1 = projParams["lat_1"] as? Double, // first standard parallel
616
- let lat_2 = projParams["lat_2"] as? Double, // second standard parallel (HRRR uses two!)
617
- let r_earth = projParams["R"] as? Double else {
625
+ let lat_0 = (projParams["lat_0"] as? NSNumber)?.doubleValue,
626
+ let lon_0 = (projParams["lon_0"] as? NSNumber)?.doubleValue,
627
+ let lat_1 = (projParams["lat_1"] as? NSNumber)?.doubleValue,
628
+ let lat_2 = (projParams["lat_2"] as? NSNumber)?.doubleValue,
629
+ let r_earth = (projParams["R"] as? NSNumber)?.doubleValue else {
618
630
  print("❌ [LCC Geometry] Failed to extract LCC parameters.")
619
631
  return nil
620
632
  }
@@ -628,10 +640,9 @@ public class GridRenderLayer: NSObject {
628
640
  let lat0_rad = lat_0 * toRad
629
641
  let lon0_rad = lon_0 * toRad
630
642
 
631
- // Calculate cone constant (n) using two standard parallels
632
643
  let n: Double
633
644
  if abs(lat_1 - lat_2) < 1e-10 {
634
- n = sin(lat1_rad) // Single parallel case
645
+ n = sin(lat1_rad)
635
646
  } else {
636
647
  n = log(cos(lat1_rad) / cos(lat2_rad)) / log(tan(Ο€/4.0 + lat2_rad/2.0) / tan(Ο€/4.0 + lat1_rad/2.0))
637
648
  }
@@ -639,7 +650,6 @@ public class GridRenderLayer: NSObject {
639
650
  let F = cos(lat1_rad) * pow(tan(Ο€/4.0 + lat1_rad/2.0), n) / n
640
651
  let rho_0 = r_earth * F * pow(tan(Ο€/4.0 + lat0_rad/2.0), -n)
641
652
 
642
- // i, j are the x, y projection coordinates
643
653
  let x = i
644
654
  let y = j
645
655
 
@@ -665,11 +675,16 @@ public class GridRenderLayer: NSObject {
665
675
 
666
676
  private func generateGeometryData(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
667
677
  guard let gridParams = gridDef["grid_params"] as? [String: Any] else {
678
+ print("❌ [generateGeometryData] No grid_params found")
668
679
  return
669
680
  }
670
681
 
671
- // GFS Global Grid Path
672
- if isGFSType(gridParams: gridParams) {
682
+ // Check grid type
683
+ let isGFS = isGFSType(gridParams: gridParams)
684
+ let isLCC = isLCCType(gridDef: gridDef)
685
+
686
+ if isGFS {
687
+ // GFS path remains unchanged
673
688
  let subdivisions = 120
674
689
  let verticesPerRow = (subdivisions * 3) + 1
675
690
  let TILE_SIZE: Double = 512.0
@@ -701,12 +716,16 @@ public class GridRenderLayer: NSObject {
701
716
  }
702
717
  return
703
718
  }
704
- if isLCCType(gridDef: gridDef) {
719
+
720
+ if isLCC {
721
+ print("πŸ—ΊοΈ [generateGeometryData] Using LCC projection path")
705
722
  generateLCCGeometry(gridDef: gridDef, vertices: &vertices, indices: &indices)
706
723
  return
707
724
  }
708
725
 
709
- // Generic Grid Path (MRMS, etc.)
726
+ // Generic Grid Path (MRMS, regional models, etc.)
727
+ print("πŸ—ΊοΈ [generateGeometryData] Using generic regional grid path")
728
+
710
729
  let nx = gridParams["nx"] as? Int ?? 0
711
730
  let ny = gridParams["ny"] as? Int ?? 0
712
731
  let lon_first = gridParams["lon_first"] as? Double ?? 0.0
@@ -715,6 +734,7 @@ public class GridRenderLayer: NSObject {
715
734
  let dy = gridParams["dy_degrees"] as? Double ?? 0.0
716
735
  let lon_last = gridParams["lon_last"] as? Double ?? (lon_first + Double(nx - 1) * dx)
717
736
  let lat_last = gridParams["lat_last"] as? Double ?? (lat_first + Double(ny - 1) * dy)
737
+
718
738
  let lat_span = lat_last - lat_first
719
739
  let isSouthToNorth = lat_span > 0
720
740
 
@@ -727,14 +747,12 @@ public class GridRenderLayer: NSObject {
727
747
  let verticesPerRow = subdivisions_x + 1
728
748
  let TILE_SIZE: Double = 512.0
729
749
 
730
- // πŸ”‘ FIX: Only create ONE world copy for regional data, THREE for global data
731
- let worldCopies = (data_lon_range > 300) ? [-1, 0, 1] : [0] // Only wrap if nearly global
750
+ let worldCopies = (data_lon_range > 300) ? [-1, 0, 1] : [0]
732
751
 
733
752
  for world_copy in worldCopies {
734
753
  let vertexStartIndex = UInt16(vertices.count / 4)
735
754
  let lon_offset = Double(world_copy) * 360.0
736
755
 
737
- // Generate vertices for this world copy
738
756
  for row in 0...subdivisions_y {
739
757
  for col in 0...subdivisions_x {
740
758
  let v_interp = Float(row) / Float(subdivisions_y)
@@ -759,7 +777,6 @@ public class GridRenderLayer: NSObject {
759
777
  }
760
778
  }
761
779
 
762
- // Generate indices (same as before)
763
780
  for row in 0..<UInt16(subdivisions_y) {
764
781
  for col in 0..<UInt16(subdivisions_x) {
765
782
  let tl = vertexStartIndex + row * UInt16(verticesPerRow) + col
@@ -925,9 +942,6 @@ internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFor
925
942
  return
926
943
  }
927
944
 
928
- print("βœ… [GridRenderLayer] Past guards, about to render!")
929
- print(" 🎨 About to draw \(indexCount) indices (\(indexCount/3) triangles)")
930
-
931
945
  let needsLinear = (uniforms.smoothing != 0)
932
946
  if isDataSamplerLinear != needsLinear {
933
947
  let samplerDesc = MTLSamplerDescriptor()
@@ -956,9 +970,6 @@ internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFor
956
970
  SIMD4<Float>(floatArray[12], floatArray[13], floatArray[14], floatArray[15])
957
971
  )
958
972
 
959
- print(" πŸ“ MVP matrix after scaling: \(mvp)")
960
- print(" πŸ“ Zoom: \(zoom), Scale factor: \(scale)")
961
-
962
973
  // Add depth state
963
974
  let depthStencilDescriptor = MTLDepthStencilDescriptor()
964
975
  depthStencilDescriptor.depthCompareFunction = .always
@@ -977,12 +988,9 @@ internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFor
977
988
  encoder.setFragmentSamplerState(dataSamplerState, index: 0)
978
989
  encoder.setFragmentSamplerState(colormapSamplerState, index: 1)
979
990
 
980
- print(" 🎨 Drawing indexed primitives now...")
981
991
  encoder.drawIndexedPrimitives(type: .triangle, indexCount: indexCount, indexType: .uint16, indexBuffer: indices, indexBufferOffset: 0)
982
- print(" βœ… Draw call completed")
983
992
 
984
993
  encoder.endEncoding()
985
- print(" βœ… Encoder ended")
986
994
  }
987
995
 
988
996
  internal func internalRenderingWillEnd() {
@@ -10,8 +10,6 @@ import Foundation
10
10
  belowLayerId: String?
11
11
  ) -> Bool {
12
12
  let position: LayerPosition? = belowLayerId.map { .below($0) }
13
-
14
- // Create a CustomLayer object
15
13
  var customLayer = CustomLayer(id: layerId, renderer: layerHost)
16
14
 
17
15
  do {
@@ -23,8 +21,18 @@ import Foundation
23
21
  return false
24
22
  }
25
23
  }
26
-
24
+
27
25
  @objc public static func triggerRepaint(on mapView: MapView) {
28
26
  mapView.mapboxMap.triggerRepaint()
29
27
  }
28
+
29
+ // ADD THIS NEW METHOD
30
+ @objc public static func layerExists(in mapView: MapView, layerId: String) -> Bool {
31
+ do {
32
+ _ = try mapView.mapboxMap.layer(withId: layerId)
33
+ return true
34
+ } catch {
35
+ return false
36
+ }
37
+ }
30
38
  }
@@ -1,17 +1,31 @@
1
1
  #import <UIKit/UIKit.h>
2
+ #import <React/RCTComponent.h>
3
+
2
4
  @class GridRenderLayer;
3
5
  @class MapView;
6
+
4
7
  NS_ASSUME_NONNULL_BEGIN
8
+
5
9
  @interface GridRenderLayerView : UIView
10
+
6
11
  @property (nonatomic, strong) GridRenderLayer *layerInstance;
7
12
  @property (nonatomic, weak) MapView *mapView;
8
13
  @property (nonatomic, strong) NSString *layerId;
9
14
  @property (nonatomic, strong, nullable) NSString *belowID;
15
+
10
16
  // Property setters for React Native
11
17
  - (void)setOpacity:(float)opacity;
12
18
  - (void)setDataRange:(NSArray *)dataRange;
13
19
  - (void)setSmoothing:(BOOL)smoothing;
14
20
  - (void)setBelowID:(NSString *)belowID;
15
- - (void)setVariable:(NSString *)variable; // ADD THIS LINE
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
+
16
29
  @end
30
+
17
31
  NS_ASSUME_NONNULL_END