@aguacerowx/react-native 0.0.36 → 0.0.38

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 (403) hide show
  1. package/README.md +126 -126
  2. package/aguacerowx-react-native.podspec +38 -38
  3. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  4. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  5. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  6. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/8.9/gc.properties +0 -0
  8. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  9. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  10. package/android/.gradle/vcs-1/gc.properties +0 -0
  11. package/android/build.gradle +107 -107
  12. package/android/src/main/AndroidManifest.xml +6 -6
  13. package/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
  14. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +688 -688
  15. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
  16. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
  17. package/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
  18. package/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
  19. package/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
  20. package/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
  21. package/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
  22. package/android/src/main/res/raw/fragment_shader.glsl +180 -180
  23. package/android/src/main/res/raw/vertex_shader.glsl +19 -19
  24. package/index.js +2 -2
  25. package/ios/AguaceroPackage.m +18 -18
  26. package/ios/FragmentUniforms.swift +15 -15
  27. package/ios/GridRenderLayer.swift +1107 -1004
  28. package/ios/GridRenderLayerBridge.swift +44 -36
  29. package/ios/GridRenderLayerManager.mm +171 -157
  30. package/ios/GridRenderLayerView.h +30 -30
  31. package/ios/GridRenderLayerView.m +200 -216
  32. package/ios/InspectorDataCache.swift +63 -65
  33. package/ios/InspectorModule.m +9 -9
  34. package/ios/InspectorModule.swift +112 -63
  35. package/ios/Shaders.metal +319 -319
  36. package/ios/WeatherFrameProcessorModule.m +15 -15
  37. package/ios/WeatherFrameProcessorModule.swift +152 -103
  38. package/lib/commonjs/README.md +126 -126
  39. package/lib/commonjs/aguacerowx-react-native.podspec +38 -38
  40. package/lib/commonjs/android/build.gradle +107 -107
  41. package/lib/commonjs/android/src/main/AndroidManifest.xml +6 -6
  42. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
  43. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +688 -688
  44. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
  45. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
  46. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
  47. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
  48. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
  49. package/lib/commonjs/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
  50. package/lib/commonjs/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
  51. package/lib/commonjs/android/src/main/res/raw/fragment_shader.glsl +180 -180
  52. package/lib/commonjs/android/src/main/res/raw/vertex_shader.glsl +19 -19
  53. package/lib/commonjs/babel.config.js.map +1 -1
  54. package/lib/commonjs/index.js.map +1 -1
  55. package/lib/commonjs/ios/AguaceroPackage.m +18 -18
  56. package/lib/commonjs/ios/FragmentUniforms.swift +15 -15
  57. package/lib/commonjs/ios/GridRenderLayer.swift +1107 -1004
  58. package/lib/commonjs/ios/GridRenderLayerBridge.swift +44 -36
  59. package/lib/commonjs/ios/GridRenderLayerManager.mm +171 -157
  60. package/lib/commonjs/ios/GridRenderLayerView.h +30 -30
  61. package/lib/commonjs/ios/GridRenderLayerView.m +200 -216
  62. package/lib/commonjs/ios/InspectorDataCache.swift +63 -65
  63. package/lib/commonjs/ios/InspectorModule.m +9 -9
  64. package/lib/commonjs/ios/InspectorModule.swift +112 -63
  65. package/lib/commonjs/ios/Shaders.metal +319 -319
  66. package/lib/commonjs/ios/WeatherFrameProcessorModule.m +15 -15
  67. package/lib/commonjs/ios/WeatherFrameProcessorModule.swift +152 -103
  68. package/lib/commonjs/package.json +72 -72
  69. package/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
  70. package/lib/commonjs/scripts/compile-shaders.js.map +1 -1
  71. package/lib/commonjs/scripts/compile-shaders.sh +38 -38
  72. package/lib/commonjs/src/AguaceroContext.js.map +1 -1
  73. package/lib/commonjs/src/GridRenderLayer.js.map +1 -1
  74. package/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
  75. package/lib/commonjs/src/MapManager.js.map +1 -1
  76. package/lib/commonjs/src/MapRegistry.js.map +1 -1
  77. package/lib/commonjs/src/StyleApplicator.js +6 -6
  78. package/lib/commonjs/src/StyleApplicator.js.map +1 -1
  79. package/lib/commonjs/src/WeatherLayerManager.js +57 -15
  80. package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  81. package/lib/commonjs/tsconfig.json +23 -23
  82. package/lib/module/README.md +126 -126
  83. package/lib/module/aguacerowx-react-native.podspec +38 -38
  84. package/lib/module/android/build.gradle +107 -107
  85. package/lib/module/android/src/main/AndroidManifest.xml +6 -6
  86. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
  87. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +688 -688
  88. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
  89. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
  90. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
  91. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
  92. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
  93. package/lib/module/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
  94. package/lib/module/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
  95. package/lib/module/android/src/main/res/raw/fragment_shader.glsl +180 -180
  96. package/lib/module/android/src/main/res/raw/vertex_shader.glsl +19 -19
  97. package/lib/module/babel.config.js.map +1 -1
  98. package/lib/module/index.js.map +1 -1
  99. package/lib/module/ios/AguaceroPackage.m +18 -18
  100. package/lib/module/ios/FragmentUniforms.swift +15 -15
  101. package/lib/module/ios/GridRenderLayer.swift +1107 -1004
  102. package/lib/module/ios/GridRenderLayerBridge.swift +44 -36
  103. package/lib/module/ios/GridRenderLayerManager.mm +171 -157
  104. package/lib/module/ios/GridRenderLayerView.h +30 -30
  105. package/lib/module/ios/GridRenderLayerView.m +200 -216
  106. package/lib/module/ios/InspectorDataCache.swift +63 -65
  107. package/lib/module/ios/InspectorModule.m +9 -9
  108. package/lib/module/ios/InspectorModule.swift +112 -63
  109. package/lib/module/ios/Shaders.metal +319 -319
  110. package/lib/module/ios/WeatherFrameProcessorModule.m +15 -15
  111. package/lib/module/ios/WeatherFrameProcessorModule.swift +152 -103
  112. package/lib/module/lib/commonjs/README.md +126 -126
  113. package/lib/module/lib/commonjs/aguacerowx-react-native.podspec +38 -38
  114. package/lib/module/lib/commonjs/babel.config.js.map +1 -1
  115. package/lib/module/lib/commonjs/index.js.map +1 -1
  116. package/lib/module/lib/commonjs/ios/AguaceroPackage.m +18 -18
  117. package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +15 -15
  118. package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +1107 -1004
  119. package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +44 -36
  120. package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +171 -157
  121. package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +30 -30
  122. package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +200 -216
  123. package/lib/module/lib/commonjs/ios/InspectorDataCache.swift +63 -65
  124. package/lib/module/lib/commonjs/ios/InspectorModule.m +9 -9
  125. package/lib/module/lib/commonjs/ios/InspectorModule.swift +112 -63
  126. package/lib/module/lib/commonjs/ios/Shaders.metal +319 -319
  127. package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.m +15 -15
  128. package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.swift +152 -103
  129. package/lib/module/lib/commonjs/package.json +72 -72
  130. package/lib/module/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
  131. package/lib/module/lib/commonjs/scripts/compile-shaders.js.map +1 -1
  132. package/lib/module/lib/commonjs/scripts/compile-shaders.sh +38 -38
  133. package/lib/module/lib/commonjs/src/AguaceroContext.js.map +1 -1
  134. package/lib/module/lib/commonjs/src/GridRenderLayer.js.map +1 -1
  135. package/lib/module/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
  136. package/lib/module/lib/commonjs/src/MapManager.js.map +1 -1
  137. package/lib/module/lib/commonjs/src/MapRegistry.js.map +1 -1
  138. package/lib/module/lib/commonjs/src/StyleApplicator.js +6 -6
  139. package/lib/module/lib/commonjs/src/StyleApplicator.js.map +1 -1
  140. package/lib/module/lib/commonjs/src/WeatherLayerManager.js +57 -15
  141. package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  142. package/lib/module/lib/commonjs/tsconfig.json +23 -23
  143. package/lib/module/package.json +72 -72
  144. package/lib/module/react-native-builder-bob.config.js.map +1 -1
  145. package/lib/module/scripts/compile-shaders.js.map +1 -1
  146. package/lib/module/scripts/compile-shaders.sh +38 -38
  147. package/lib/module/src/AguaceroContext.js.map +1 -1
  148. package/lib/module/src/GridRenderLayer.js.map +1 -1
  149. package/lib/module/src/GridRenderLayerNativeComponent.js.map +1 -1
  150. package/lib/module/src/MapManager.js.map +1 -1
  151. package/lib/module/src/MapRegistry.js.map +1 -1
  152. package/lib/module/src/StyleApplicator.js +6 -6
  153. package/lib/module/src/StyleApplicator.js.map +1 -1
  154. package/lib/module/src/WeatherLayerManager.js +59 -16
  155. package/lib/module/src/WeatherLayerManager.js.map +1 -1
  156. package/lib/module/tsconfig.json +23 -23
  157. package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
  158. package/package.json +72 -72
  159. package/src/AguaceroContext.js +3 -3
  160. package/src/GridRenderLayer.js +215 -215
  161. package/src/GridRenderLayerNativeComponent.ts +15 -15
  162. package/src/MapManager.js +218 -218
  163. package/src/MapRegistry.js +34 -34
  164. package/src/StyleApplicator.js +240 -240
  165. package/src/WeatherLayerManager.js +1191 -1137
  166. package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/results.bin +0 -1
  167. package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/transformed/classes/classes_dex/classes.dex +0 -0
  168. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/results.bin +0 -1
  169. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/AguaceroPackage.dex +0 -0
  170. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/BuildConfig.dex +0 -0
  171. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.dex +0 -0
  172. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer.dex +0 -0
  173. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayerView.dex +0 -0
  174. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderManager.dex +0 -0
  175. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/InspectorModule.dex +0 -0
  176. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/ShaderUtils.dex +0 -0
  177. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/WeatherFrameProcessorModule.dex +0 -0
  178. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.dex +0 -0
  179. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.dex +0 -0
  180. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  181. package/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
  182. package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
  183. package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
  184. package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
  185. package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
  186. package/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
  187. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
  188. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
  189. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
  190. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
  191. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
  192. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
  193. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
  194. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
  195. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
  196. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
  197. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
  198. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
  199. package/android/build/generated/source/codegen/schema.json +0 -1
  200. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
  201. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  202. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  203. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  204. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  205. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  206. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
  207. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
  208. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
  209. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  210. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
  211. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
  212. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  213. package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
  214. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  215. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  216. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  217. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  218. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  219. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  220. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  221. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  222. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  223. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  224. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  225. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  226. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  227. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
  228. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
  229. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
  230. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  231. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  232. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
  233. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
  234. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -181
  235. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
  236. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  237. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  238. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  239. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  240. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  241. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  242. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  243. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  244. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  245. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  246. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  247. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  248. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
  249. package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  250. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
  251. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
  252. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
  253. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  254. package/lib/commonjs/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
  255. package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
  256. package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
  257. package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
  258. package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
  259. package/lib/commonjs/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
  260. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
  261. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
  262. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
  263. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
  264. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
  265. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
  266. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
  267. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
  268. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
  269. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
  270. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
  271. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
  272. package/lib/commonjs/android/build/generated/source/codegen/schema.json +0 -1
  273. package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
  274. package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  275. package/lib/commonjs/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  276. package/lib/commonjs/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  277. package/lib/commonjs/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  278. package/lib/commonjs/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  279. package/lib/commonjs/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
  280. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
  281. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
  282. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  283. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
  284. package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
  285. package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  286. package/lib/commonjs/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
  287. package/lib/commonjs/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  288. package/lib/commonjs/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  289. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  290. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  291. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  292. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  293. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  294. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  295. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  296. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  297. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  298. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  299. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  300. package/lib/commonjs/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
  301. package/lib/commonjs/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
  302. package/lib/commonjs/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
  303. package/lib/commonjs/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  304. package/lib/commonjs/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  305. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
  306. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
  307. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -181
  308. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
  309. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  310. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  311. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  312. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  313. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  314. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  315. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  316. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  317. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  318. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  319. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  320. package/lib/commonjs/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  321. package/lib/commonjs/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
  322. package/lib/commonjs/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  323. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
  324. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
  325. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
  326. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  327. package/lib/module/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
  328. package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
  329. package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
  330. package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
  331. package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
  332. package/lib/module/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
  333. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
  334. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
  335. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
  336. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
  337. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
  338. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
  339. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
  340. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
  341. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
  342. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
  343. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
  344. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
  345. package/lib/module/android/build/generated/source/codegen/schema.json +0 -1
  346. package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
  347. package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  348. package/lib/module/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  349. package/lib/module/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  350. package/lib/module/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  351. package/lib/module/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  352. package/lib/module/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
  353. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
  354. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
  355. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  356. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
  357. package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
  358. package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  359. package/lib/module/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
  360. package/lib/module/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  361. package/lib/module/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  362. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  363. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  364. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  365. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  366. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  367. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  368. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  369. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  370. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  371. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  372. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  373. package/lib/module/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
  374. package/lib/module/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
  375. package/lib/module/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
  376. package/lib/module/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  377. package/lib/module/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  378. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
  379. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
  380. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -181
  381. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
  382. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  383. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  384. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  385. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  386. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  387. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  388. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  389. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  390. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  391. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  392. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  393. package/lib/module/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  394. package/lib/module/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
  395. package/lib/module/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  396. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
  397. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
  398. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
  399. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  400. package/lib/module/lib/commonjs/android/build.gradle +0 -108
  401. package/lib/module/lib/commonjs/android/src/main/AndroidManifest.xml +0 -7
  402. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
  403. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
@@ -1,1004 +1,1107 @@
1
- import Foundation
2
- import MapboxMaps
3
- import Metal
4
- import libzstd
5
- import simd
6
-
7
- // MARK: - Swift-only wrapper for CustomLayerHost conformance
8
- @objc internal final class GridRenderLayerHost: NSObject, CustomLayerHost {
9
- weak var layer: GridRenderLayer?
10
-
11
- init(layer: GridRenderLayer) {
12
- self.layer = layer
13
- super.init()
14
- }
15
-
16
- func renderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
17
- layer?.internalRenderingWillStart(metalDevice, colorPixelFormat: colorPixelFormat, depthStencilPixelFormat: depthStencilPixelFormat)
18
- }
19
-
20
- func render(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
21
- layer?.internalRender(parameters, mtlCommandBuffer: mtlCommandBuffer, mtlRenderPassDescriptor: mtlRenderPassDescriptor)
22
- }
23
-
24
- func renderingWillEnd() {
25
- layer?.internalRenderingWillEnd()
26
- }
27
- }
28
-
29
- @objc(GridRenderLayer)
30
- public class GridRenderLayer: NSObject {
31
-
32
- // MARK: - Properties
33
-
34
- public var id: String
35
- @objc internal var hostWrapper: GridRenderLayerHost!
36
-
37
- // Metal objects
38
- private var device: MTLDevice!
39
- private var commandQueue: MTLCommandQueue!
40
- private var pipelineState: MTLRenderPipelineState!
41
- private var vertexBuffer: MTLBuffer?
42
- private var indexBuffer: MTLBuffer?
43
- private var dataTexture: MTLTexture?
44
- private var colormapTexture: MTLTexture?
45
- private var dataSamplerState: MTLSamplerState!
46
- private var colormapSamplerState: MTLSamplerState!
47
- private var isDataSamplerLinear: Bool = false
48
-
49
- private var pendingColormapUpdate: String?
50
- private var pendingDataUpdate: (data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String)?
51
- private var pendingGeometryUpdate: (corners: [String: Any], gridDef: [String: Any])?
52
-
53
- // Layer state
54
- private var indexCount: Int = 0
55
- private var uniforms = FragmentUniforms(
56
- opacity: 1.0,
57
- dataRange: SIMD2<Float>(0.0, 1.0),
58
- scale: 1.0,
59
- offset: 0.0,
60
- missingQuantized: 127.0,
61
- textureSize: SIMD2<Float>(0.0, 0.0),
62
- smoothing: 1,
63
- scaleType: 0,
64
- isPtype: 0,
65
- isMRMS: 0
66
- )
67
- private var isVisible = false
68
- private var pendingActiveFrameKey: String?
69
- private let inspectorCache = InspectorDataCache.shared
70
- private struct FrameMetadata {
71
- let scale: Float
72
- let offset: Float
73
- let missing: Float
74
- let scaleType: Int
75
- let nx: Float
76
- let ny: Float
77
- let filePath: String
78
- let originalScale: Float
79
- let originalOffset: Float
80
- }
81
- private var frameCache: [String: FrameMetadata] = [:]
82
- private let frameProcessingQueue = DispatchQueue(label: "com.aguacero.frame-processing", qos: .userInitiated, attributes: .concurrent)
83
- private let semaphore = DispatchSemaphore(value: 8)
84
-
85
- private struct VertexInfo {
86
- var mercX: Float
87
- var mercY: Float
88
- var texU: Float
89
- var texV: Float
90
- var index: UInt16
91
- }
92
- @objc
93
- public init(id: String) {
94
- self.id = id
95
- super.init()
96
- self.hostWrapper = GridRenderLayerHost(layer: self)
97
- }
98
-
99
- @objc public func getHostWrapper() -> Any {
100
- return self.hostWrapper as Any
101
- }
102
-
103
- // MARK: - Public Methods (called from Manager)
104
-
105
- @objc public func setOpacity(value: Float) {
106
- self.uniforms.opacity = value
107
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
108
- }
109
-
110
- @objc public func setDataRange(value: [NSNumber]) {
111
- self.uniforms.dataRange = SIMD2<Float>(value[0].floatValue, value[1].floatValue)
112
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
113
- }
114
-
115
- @objc public func setSmoothing(value: Bool) {
116
- self.uniforms.smoothing = value ? 1 : 0
117
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
118
- }
119
-
120
- @objc(setIsMRMSWithIsMRMS:)
121
- public func setIsMRMS(isMRMS: Bool) {
122
- self.uniforms.isMRMS = isMRMS ? 1 : 0
123
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
124
- }
125
-
126
- // ADD THIS METHOD
127
- @objc(setVariableWithVariable:)
128
- public func setVariable(variable: String) {
129
- let isPtypeVar = (variable == "ptypeRefl" || variable == "ptypeRate")
130
- self.uniforms.isPtype = isPtypeVar ? 1 : 0
131
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
132
- }
133
-
134
- @objc public func clear() {
135
- self.isVisible = false
136
- self.inspectorCache.clear()
137
- }
138
-
139
- @objc public func updateDataParameters(scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: NSNumber) { // ADD scaleType parameter
140
- // Update both the inspector cache AND the rendering uniforms
141
- self.uniforms.scale = scale.floatValue
142
- self.uniforms.offset = offset.floatValue
143
- self.uniforms.missingQuantized = missing.floatValue
144
- self.uniforms.scaleType = Int32(scaleType.intValue) // ADD THIS
145
-
146
- inspectorCache.update(
147
- data: inspectorCache.lastDecompressedData,
148
- nx: inspectorCache.nx,
149
- ny: inspectorCache.ny,
150
- scale: scale.floatValue,
151
- offset: offset.floatValue,
152
- missing: missing.floatValue,
153
- scaleType: scaleType.intValue // ADD THIS
154
- )
155
- }
156
-
157
- @objc public func updateColormapTexture(colormapAsBase64: String) {
158
- guard let device = self.device else {
159
- pendingColormapUpdate = colormapAsBase64
160
- return
161
- }
162
- guard let data = Data(base64Encoded: colormapAsBase64) else { return }
163
- let textureDescriptor = MTLTextureDescriptor()
164
- textureDescriptor.pixelFormat = .rgba8Unorm
165
- textureDescriptor.width = 256
166
- textureDescriptor.height = 1
167
- textureDescriptor.usage = .shaderRead
168
- guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return }
169
- texture.replace(
170
- region: MTLRegionMake2D(0, 0, 256, 1),
171
- mipmapLevel: 0,
172
- withBytes: (data as NSData).bytes,
173
- bytesPerRow: 256 * 4
174
- )
175
- self.colormapTexture = texture
176
- }
177
-
178
- @objc(clearGpuCache)
179
- public func clearGpuCache() {
180
- frameProcessingQueue.async { [weak self] in
181
- self?.frameCache.removeAll()
182
- }
183
- }
184
-
185
- private func processRawData(fileData: Data) -> Data? {
186
- guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
187
- print("❌ [GridRenderLayer] Failed to decompress zstd data")
188
- return nil
189
- }
190
- let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
191
- let finalTextureBytes = self.transformData(finalData: reconstructedData)
192
- return finalTextureBytes
193
- }
194
-
195
- private func createTextureFromBytes(bytes: Data, nx: Int, ny: Int) -> MTLTexture? {
196
- guard let device = self.device else { return nil }
197
- let textureDescriptor = MTLTextureDescriptor()
198
- textureDescriptor.pixelFormat = .r8Unorm
199
- textureDescriptor.width = nx
200
- textureDescriptor.height = ny
201
- textureDescriptor.usage = .shaderRead
202
-
203
- guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return nil }
204
- texture.replace(
205
- region: MTLRegionMake2D(0, 0, nx, ny),
206
- mipmapLevel: 0,
207
- withBytes: (bytes as NSData).bytes,
208
- bytesPerRow: nx
209
- )
210
- return texture
211
- }
212
-
213
- private func updateInspectorCache(filePath: String, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int) {
214
- // This is now called from frameProcessingQueue, so we can do the work synchronously
215
- guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
216
- print("❌ [Inspector] FATAL: Failed to read file data from path.")
217
- self.inspectorCache.clear()
218
- return
219
- }
220
-
221
- guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
222
- print("❌ [Inspector] FATAL: Failed to decompress Zstd data.")
223
- self.inspectorCache.clear()
224
- return
225
- }
226
-
227
- let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
228
-
229
- self.inspectorCache.update(
230
- data: reconstructedData,
231
- nx: nx,
232
- ny: ny,
233
- scale: scale,
234
- offset: offset,
235
- missing: missing,
236
- scaleType: scaleType
237
- )
238
- }
239
-
240
- @objc(setActiveFrameWithCacheKey:)
241
- public func setActiveFrame(cacheKey: String) {
242
- if let frame = frameCache[cacheKey] {
243
- frameProcessingQueue.async { [weak self] in
244
- guard let self = self else { return }
245
-
246
- guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: frame.filePath)),
247
- let finalTextureBytes = self.processRawData(fileData: fileData)
248
- else {
249
- print("❌ [GridRenderLayer] Failed to load texture data for active frame")
250
- return
251
- }
252
-
253
- DispatchQueue.main.async { [weak self] in
254
- guard let self = self,
255
- let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: Int(frame.nx), ny: Int(frame.ny))
256
- else { return }
257
-
258
- self.dataTexture = texture
259
- self.uniforms.scale = frame.scale
260
- self.uniforms.offset = frame.offset
261
- self.uniforms.missingQuantized = frame.missing
262
- self.uniforms.textureSize = SIMD2<Float>(frame.nx, frame.ny)
263
- self.uniforms.scaleType = Int32(frame.scaleType)
264
-
265
- self.isVisible = true
266
- self.pendingActiveFrameKey = nil
267
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
268
-
269
- // Update inspector cache
270
- self.frameProcessingQueue.async { [weak self] in
271
- self?.updateInspectorCache(
272
- filePath: frame.filePath,
273
- nx: Int(frame.nx),
274
- ny: Int(frame.ny),
275
- scale: frame.scale,
276
- offset: frame.offset,
277
- missing: frame.missing,
278
- scaleType: frame.scaleType
279
- )
280
- }
281
- }
282
- }
283
-
284
- } else {
285
- print("⚠️ [GridRenderLayer] setActiveFrame cache MISS for key: \(cacheKey). Will apply when primed.")
286
- self.pendingActiveFrameKey = cacheKey
287
- self.isVisible = false
288
- }
289
- }
290
-
291
- @objc(primeGpuCacheWithFrameInfo:)
292
- public func primeGpuCache(frameInfo: [String: [String: Any]]) {
293
- let group = DispatchGroup()
294
-
295
- for (cacheKey, info) in frameInfo {
296
- group.enter()
297
-
298
- frameProcessingQueue.async { [weak self] in
299
- guard let self = self else {
300
- group.leave()
301
- return
302
- }
303
-
304
- self.semaphore.wait()
305
- defer {
306
- self.semaphore.signal()
307
- group.leave()
308
- }
309
-
310
- if self.frameCache[cacheKey] != nil { return }
311
-
312
- guard let filePath = info["filePath"] as? String,
313
- let nx = info["nx"] as? NSNumber,
314
- let ny = info["ny"] as? NSNumber,
315
- let scale = info["scale"] as? NSNumber,
316
- let offset = info["offset"] as? NSNumber,
317
- let missing = info["missing"] as? NSNumber,
318
- let scaleTypeStr = info["scaleType"] as? String,
319
- let originalScale = info["originalScale"] as? NSNumber,
320
- let originalOffset = info["originalOffset"] as? NSNumber
321
- else {
322
- print("❌ [GridRenderLayer] Skipping prime for \(cacheKey), missing data.")
323
- return
324
- }
325
-
326
- let metadata = FrameMetadata(
327
- scale: scale.floatValue,
328
- offset: offset.floatValue,
329
- missing: missing.floatValue,
330
- scaleType: (scaleTypeStr == "sqrt") ? 1 : 0,
331
- nx: nx.floatValue,
332
- ny: ny.floatValue,
333
- filePath: filePath,
334
- originalScale: originalScale.floatValue,
335
- originalOffset: originalOffset.floatValue
336
- )
337
- self.frameCache[cacheKey] = metadata
338
-
339
- if let pendingKey = self.pendingActiveFrameKey, pendingKey == cacheKey {
340
- DispatchQueue.main.async {
341
- self.setActiveFrame(cacheKey: pendingKey)
342
- }
343
- }
344
- }
345
- }
346
- }
347
-
348
- @objc public func updateDataTexture(data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String) {
349
- let filePath = data
350
-
351
- frameProcessingQueue.async { [weak self] in
352
- guard let self = self else { return }
353
-
354
- guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
355
- let finalTextureBytes = self.processRawData(fileData: fileData)
356
- else {
357
- print("❌ [GridRenderLayer] FAST LANE: Failed to process initial frame data.")
358
- return
359
- }
360
-
361
- DispatchQueue.main.async { [weak self] in
362
- guard let self = self, let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) else {
363
- print("❌ [GridRenderLayer] FAST LANE: Failed to create texture")
364
- return
365
- }
366
-
367
- self.dataTexture = texture
368
- self.uniforms.scale = scale.floatValue
369
- self.uniforms.offset = offset.floatValue
370
- self.uniforms.missingQuantized = missing.floatValue
371
- self.uniforms.scaleType = Int32((scaleType == "sqrt") ? 1 : 0)
372
- self.uniforms.textureSize = SIMD2<Float>(nx.floatValue, ny.floatValue)
373
-
374
- self.isVisible = true
375
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
376
-
377
- self.updateInspectorCache(
378
- filePath: filePath,
379
- nx: nx.intValue,
380
- ny: ny.intValue,
381
- scale: scale.floatValue,
382
- offset: offset.floatValue,
383
- missing: missing.floatValue,
384
- scaleType: (scaleType == "sqrt") ? 1 : 0
385
- )
386
- }
387
- }
388
- }
389
-
390
- @objc public func updateGeometry(corners: [String: Any], gridDef: [String: Any]) {
391
- guard self.device != nil else {
392
- print("⚠️ [GridRenderLayer] Device not ready yet, storing geometry for later")
393
- pendingGeometryUpdate = (corners: corners, gridDef: gridDef)
394
- return
395
- }
396
-
397
- DispatchQueue.global(qos: .userInitiated).async {
398
-
399
- var vertices: [Float] = []
400
- var indices: [UInt16] = []
401
-
402
- self.generateGeometryData(gridDef: gridDef, vertices: &vertices, indices: &indices)
403
-
404
- if vertices.isEmpty || indices.isEmpty {
405
- print("❌ [GridRenderLayer] No geometry generated")
406
- return
407
- }
408
-
409
- self.indexCount = indices.count
410
-
411
- DispatchQueue.main.async {
412
- self.vertexBuffer = self.device.makeBuffer(bytes: vertices, length: vertices.count * MemoryLayout<Float>.size, options: [])
413
- self.indexBuffer = self.device.makeBuffer(bytes: indices, length: indices.count * MemoryLayout<UInt16>.size, options: [])
414
-
415
- NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
416
- }
417
- }
418
- }
419
-
420
- private func decompressZstd(data: Data) -> Data? {
421
- let decompressedSize = data.withUnsafeBytes { ptr in
422
- ZSTD_getFrameContentSize(ptr.baseAddress, data.count)
423
- }
424
-
425
- guard Int64(bitPattern: decompressedSize) > 0 else {
426
- print("❌ [GridRenderLayer] Could not determine decompressed size")
427
- return nil
428
- }
429
-
430
- var decompressedData = Data(count: Int(decompressedSize))
431
-
432
- let result = decompressedData.withUnsafeMutableBytes { decompressedPtr -> Int in
433
- data.withUnsafeBytes { compressedPtr -> Int in
434
- let returnValue = ZSTD_decompress(
435
- decompressedPtr.baseAddress,
436
- Int(decompressedSize),
437
- compressedPtr.baseAddress,
438
- data.count
439
- )
440
- return Int(returnValue)
441
- }
442
- }
443
-
444
- guard result > 0 && result == decompressedData.count else {
445
- if result > 0 {
446
- let size_t_result = size_t(result)
447
- if let errorName = ZSTD_getErrorName(size_t_result) {
448
- let errorString = String(cString: errorName)
449
- print("❌ [GridRenderLayer] Zstd decompression failed: \(errorString)")
450
- }
451
- }
452
- return nil
453
- }
454
- return decompressedData
455
- }
456
-
457
- // MARK: - Private Helper Methods
458
-
459
- private func reconstructData(decompressedDeltas: Data) -> Data {
460
- guard !decompressedDeltas.isEmpty else { return Data() }
461
- var reconstructedData = Data(count: decompressedDeltas.count)
462
- reconstructedData[0] = decompressedDeltas[0]
463
- for i in 1..<decompressedDeltas.count {
464
- reconstructedData[i] = UInt8(Int8(bitPattern: reconstructedData[i-1]) &+ Int8(bitPattern: decompressedDeltas[i]))
465
- }
466
- return reconstructedData
467
- }
468
-
469
- private func transformData(finalData: Data) -> Data {
470
- var transformedData = Data(count: finalData.count)
471
- for i in 0..<finalData.count {
472
- transformedData[i] = UInt8(Int16(Int8(bitPattern: finalData[i])) + 128)
473
- }
474
- return transformedData
475
- }
476
-
477
- private func isLCCType(gridDef: [String: Any]) -> Bool {
478
- if let type = gridDef["type"] as? String {
479
- return type == "lambert_conformal_conic"
480
- }
481
- return false
482
- }
483
-
484
- private func generateLCCGeometry(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
485
- guard let gridParams = gridDef["grid_params"] as? [String: Any],
486
- let projParams = gridDef["proj_params"] as? [String: Any],
487
- let nx = gridParams["nx"] as? Int,
488
- let ny = gridParams["ny"] as? Int,
489
- let dx = gridParams["dx"] as? Double,
490
- let dy = gridParams["dy"] as? Double,
491
- let x_origin = gridParams["x_origin"] as? Double,
492
- let y_origin = gridParams["y_origin"] as? Double else {
493
- return
494
- }
495
-
496
- let subdivisions = 60
497
- let TILE_SIZE: Double = 512.0
498
-
499
- let x_min = x_origin
500
- let y_max = y_origin
501
- let x_max = x_origin + Double(nx - 1) * dx
502
- let y_min = y_origin + Double(ny - 1) * dy
503
-
504
- var vertexGrid: [[VertexInfo?]] = Array(repeating: Array(repeating: nil, count: subdivisions + 1), count: subdivisions + 1)
505
- var validVertexCount: UInt16 = 0
506
-
507
- // Generate vertices
508
- for row in 0...subdivisions {
509
- for col in 0...subdivisions {
510
- let t_x = Double(col) / Double(subdivisions)
511
- let t_y = Double(row) / Double(subdivisions)
512
-
513
- let proj_x = x_min + t_x * (x_max - x_min)
514
- let proj_y = y_max + t_y * (y_min - y_max)
515
-
516
- // Convert LCC projection coordinates to lat/lon
517
- if let (lon, lat) = lccToLonLat(i: proj_x, j: proj_y, gridDef: gridDef) {
518
- // Convert lat/lon to Mercator
519
- let mercX_normalized = (lon + 180.0) / 360.0
520
- let clampedLat = max(-85.05112878, min(85.05112878, lat))
521
- let sinLatitude = sin(clampedLat * .pi / 180.0)
522
- let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
523
-
524
- let mercX = mercX_normalized * TILE_SIZE
525
- let mercY = mercY_normalized * TILE_SIZE
526
-
527
- // Check for invalid values
528
- if !mercX.isFinite || !mercY.isFinite {
529
- vertexGrid[row][col] = nil
530
- continue
531
- }
532
-
533
- let tex_u = Float(t_x)
534
- let tex_v = Float(t_y)
535
-
536
- let vInfo = VertexInfo(
537
- mercX: Float(mercX),
538
- mercY: Float(mercY),
539
- texU: tex_u,
540
- texV: tex_v,
541
- index: validVertexCount
542
- )
543
-
544
- vertexGrid[row][col] = vInfo
545
-
546
- vertices.append(Float(mercX))
547
- vertices.append(Float(mercY))
548
- vertices.append(tex_u)
549
- vertices.append(tex_v)
550
-
551
- validVertexCount += 1
552
- } else {
553
- vertexGrid[row][col] = nil
554
- }
555
- }
556
- }
557
-
558
- if vertices.isEmpty {
559
- print("❌ [LCC Geometry] No valid vertices generated")
560
- return
561
- }
562
-
563
- // Generate indices
564
- for row in 0..<subdivisions {
565
- for col in 0..<subdivisions {
566
- guard let topLeft = vertexGrid[row][col],
567
- let topRight = vertexGrid[row][col + 1],
568
- let bottomLeft = vertexGrid[row + 1][col],
569
- let bottomRight = vertexGrid[row + 1][col + 1] else {
570
- continue
571
- }
572
-
573
- indices.append(topLeft.index)
574
- indices.append(bottomLeft.index)
575
- indices.append(topRight.index)
576
-
577
- indices.append(topRight.index)
578
- indices.append(bottomLeft.index)
579
- indices.append(bottomRight.index)
580
- }
581
- }
582
- }
583
-
584
- private func lccToLonLat(i: Double, j: Double, gridDef: [String: Any]) -> (lon: Double, lat: Double)? {
585
- guard let projParams = gridDef["proj_params"] as? [String: Any],
586
- let lat_0 = (projParams["lat_0"] as? NSNumber)?.doubleValue,
587
- let lon_0 = (projParams["lon_0"] as? NSNumber)?.doubleValue,
588
- let lat_1 = (projParams["lat_1"] as? NSNumber)?.doubleValue,
589
- let lat_2 = (projParams["lat_2"] as? NSNumber)?.doubleValue,
590
- let r_earth = (projParams["R"] as? NSNumber)?.doubleValue else {
591
- print("❌ [LCC Geometry] Failed to extract LCC parameters.")
592
- return nil
593
- }
594
-
595
- let π = Double.pi
596
- let toRad = π / 180.0
597
- let toDeg = 180.0 / π
598
-
599
- let lat1_rad = lat_1 * toRad
600
- let lat2_rad = lat_2 * toRad
601
- let lat0_rad = lat_0 * toRad
602
- let lon0_rad = lon_0 * toRad
603
-
604
- let n: Double
605
- if abs(lat_1 - lat_2) < 1e-10 {
606
- n = sin(lat1_rad)
607
- } else {
608
- n = log(cos(lat1_rad) / cos(lat2_rad)) / log(tan(π/4.0 + lat2_rad/2.0) / tan(π/4.0 + lat1_rad/2.0))
609
- }
610
-
611
- let F = cos(lat1_rad) * pow(tan(π/4.0 + lat1_rad/2.0), n) / n
612
- let rho_0 = r_earth * F * pow(tan(π/4.0 + lat0_rad/2.0), -n)
613
-
614
- let x = i
615
- let y = j
616
-
617
- let rho = sqrt(x * x + (rho_0 - y) * (rho_0 - y))
618
- if rho < 1e-10 {
619
- return (lon: lon_0, lat: lat_0)
620
- }
621
-
622
- let theta = atan2(x, rho_0 - y)
623
-
624
- let lon = lon0_rad + theta / n
625
- let lat = 2.0 * atan(pow(r_earth * F / rho, 1.0 / n)) - π/2.0
626
-
627
- let lonDeg = lon * toDeg
628
- let latDeg = lat * toDeg
629
-
630
- if !lonDeg.isFinite || !latDeg.isFinite {
631
- return nil
632
- }
633
-
634
- return (lon: lonDeg, lat: latDeg)
635
- }
636
-
637
- private func generateGeometryData(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
638
- guard let gridParams = gridDef["grid_params"] as? [String: Any] else {
639
- print("❌ [generateGeometryData] No grid_params found")
640
- return
641
- }
642
-
643
- // Check grid type
644
- let isGFS = isGFSType(gridParams: gridParams)
645
- let isLCC = isLCCType(gridDef: gridDef)
646
-
647
- if isGFS {
648
- // GFS path remains unchanged
649
- let subdivisions = 120
650
- let verticesPerRow = (subdivisions * 3) + 1
651
- let TILE_SIZE: Double = 512.0
652
-
653
- for row in 0...subdivisions {
654
- for col in 0...(subdivisions * 3) {
655
- let v_interp = Float(row) / Float(subdivisions)
656
- let u_interp = Float(col) / Float(subdivisions)
657
- let lon = -540.0 + Double(u_interp) * 1080.0
658
- let lat = -90.0 + Double(v_interp) * 180.0
659
-
660
- let merc = lonLatToMercator(lon: lon, lat: lat, tileSize: TILE_SIZE)
661
- vertices.append(contentsOf: [merc.x, merc.y])
662
-
663
- let tex_u = Float((lon + 180.0) / 360.0)
664
- let tex_v = 1.0 - v_interp
665
- vertices.append(contentsOf: [tex_u, tex_v])
666
- }
667
- }
668
-
669
- for row in 0..<subdivisions {
670
- for col in 0..<(subdivisions * 3) {
671
- let tl = UInt16(row * verticesPerRow + col)
672
- let tr = tl + 1
673
- let bl = UInt16((row + 1) * verticesPerRow + col)
674
- let br = bl + 1
675
- indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
676
- }
677
- }
678
- return
679
- }
680
-
681
- if isLCC {
682
- generateLCCGeometry(gridDef: gridDef, vertices: &vertices, indices: &indices)
683
- return
684
- }
685
-
686
- let nx = gridParams["nx"] as? Int ?? 0
687
- let ny = gridParams["ny"] as? Int ?? 0
688
- let lon_first = gridParams["lon_first"] as? Double ?? 0.0
689
- let lat_first = gridParams["lat_first"] as? Double ?? 90.0
690
- let dx = gridParams["dx_degrees"] as? Double ?? 0.0
691
- let dy = gridParams["dy_degrees"] as? Double ?? 0.0
692
- let lon_last = gridParams["lon_last"] as? Double ?? (lon_first + Double(nx - 1) * dx)
693
- let lat_last = gridParams["lat_last"] as? Double ?? (lat_first + Double(ny - 1) * dy)
694
-
695
- let lat_span = lat_last - lat_first
696
- let isSouthToNorth = lat_span > 0
697
-
698
- // Check if this is ECMWF and normalize longitudes
699
- let isECMWF = isECMWFType(gridParams: gridParams)
700
- var data_lon_first_180 = lon_first
701
- var data_lon_last_180 = lon_last
702
-
703
- if isECMWF {
704
- // Convert ECMWF's 180 to -180 range to -180 to 180
705
- data_lon_first_180 = lon_first >= 180 ? lon_first - 360 : lon_first
706
- data_lon_last_180 = lon_last >= 180 ? lon_last - 360 : lon_last
707
- } else {
708
- // For GFS and other models
709
- data_lon_first_180 = lon_first > 180 ? lon_first - 360 : lon_first
710
- data_lon_last_180 = lon_last > 180 ? lon_last - 360 : lon_last
711
- }
712
-
713
- let data_lon_range = data_lon_last_180 - data_lon_first_180
714
-
715
- let subdivisions_x = 120
716
- let subdivisions_y = 60
717
- let verticesPerRow = subdivisions_x + 1
718
- let TILE_SIZE: Double = 512.0
719
-
720
- let worldCopies = (data_lon_range > 300) ? [-1, 0, 1] : [0]
721
-
722
- for world_copy in worldCopies {
723
- let vertexStartIndex = UInt16(vertices.count / 4)
724
- let lon_offset = Double(world_copy) * 360.0
725
-
726
- for row in 0...subdivisions_y {
727
- for col in 0...subdivisions_x {
728
- let v_interp = Float(row) / Float(subdivisions_y)
729
- let u_interp = Float(col) / Float(subdivisions_x)
730
-
731
- let vertex_lon = data_lon_first_180 + (Double(u_interp) * data_lon_range)
732
- let vertex_lat = lat_first + (Double(v_interp) * lat_span)
733
-
734
- let mercX_normalized = ((vertex_lon + lon_offset) + 180.0) / 360.0
735
- let clampedLat = max(-85.05112878, min(85.05112878, vertex_lat))
736
- let sinLatitude = sin(clampedLat * .pi / 180.0)
737
- let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
738
- let mercX = mercX_normalized * TILE_SIZE
739
- let mercY = mercY_normalized * TILE_SIZE
740
-
741
- vertices.append(contentsOf: [Float(mercX), Float(mercY)])
742
-
743
- let tex_u = u_interp
744
- let tex_v = isSouthToNorth ? (1.0 - v_interp) : v_interp
745
-
746
- vertices.append(contentsOf: [tex_u, tex_v])
747
- }
748
- }
749
-
750
- for row in 0..<UInt16(subdivisions_y) {
751
- for col in 0..<UInt16(subdivisions_x) {
752
- let tl = vertexStartIndex + row * UInt16(verticesPerRow) + col
753
- let tr = tl + 1
754
- let bl = vertexStartIndex + (row + 1) * UInt16(verticesPerRow) + col
755
- let br = bl + 1
756
-
757
- if isSouthToNorth {
758
- indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
759
- } else {
760
- indices.append(contentsOf: [tl, tr, bl, bl, tr, br])
761
- }
762
- }
763
- }
764
- }
765
- }
766
-
767
- private func isGFSType(gridParams: [String: Any]) -> Bool {
768
- return (gridParams["lon_first"] as? Double) == 0.0 &&
769
- abs((gridParams["lat_first"] as? Double) ?? -1) == 90.0
770
- }
771
-
772
- private func isECMWFType(gridParams: [String: Any]) -> Bool {
773
- return (gridParams["lon_first"] as? Double) == 180.0 &&
774
- (gridParams["lat_first"] as? Double) == 90.0
775
- }
776
-
777
- private func lonLatToMercator(lon: Double, lat: Double, tileSize: Double) -> (x: Float, y: Float) {
778
- let mercX_normalized = (lon + 180.0) / 360.0
779
- let clampedLat = max(-85.05112878, min(85.05112878, lat))
780
- let sinLatitude = sin(clampedLat * .pi / 180.0)
781
- let mercY_normalized = 0.5 - log((1.0 + sinLatitude) / (1.0 - sinLatitude)) / (4.0 * .pi)
782
-
783
- return (x: Float(mercX_normalized * tileSize), y: Float(mercY_normalized * tileSize))
784
- }
785
-
786
- // MARK: - Internal methods for CustomLayerHost (called by wrapper)
787
-
788
- internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
789
- self.device = metalDevice
790
- self.commandQueue = metalDevice.makeCommandQueue()
791
-
792
- let bundle = Bundle(for: GridRenderLayer.self)
793
-
794
- // Determine if we're running on simulator or device
795
- #if targetEnvironment(simulator)
796
- let metallibName = "Shaders-simulator"
797
- #else
798
- let metallibName = "Shaders-device"
799
- #endif
800
-
801
- // Try to load pre-compiled metallib for the current platform
802
- let defaultLibrary: MTLLibrary?
803
- if let metallibUrl = bundle.url(forResource: metallibName, withExtension: "metallib"),
804
- let library = try? metalDevice.makeLibrary(URL: metallibUrl) {
805
- defaultLibrary = library
806
- }
807
- // Fall back to compiling from .metal source (for development with npm link)
808
- else if let metalUrl = bundle.url(forResource: "Shaders", withExtension: "metal"),
809
- let source = try? String(contentsOf: metalUrl),
810
- let library = try? metalDevice.makeLibrary(source: source, options: nil) {
811
- defaultLibrary = library
812
- }
813
- // Neither worked
814
- else {
815
- print("❌ [GridRenderLayer] Could not find or compile Metal shaders")
816
- print(" Bundle path: \(bundle.bundlePath)")
817
- return
818
- }
819
-
820
- guard let library = defaultLibrary else {
821
- print("❌ [GridRenderLayer] Failed to create Metal library")
822
- return
823
- }
824
-
825
- let vertexFunction = library.makeFunction(name: "vertex_main")
826
- let fragmentFunction = library.makeFunction(name: "fragment_main")
827
-
828
- // Set up vertex descriptor
829
- let vertexDescriptor = MTLVertexDescriptor()
830
- vertexDescriptor.attributes[0].format = .float2 // position (x, y)
831
- vertexDescriptor.attributes[0].offset = 0
832
- vertexDescriptor.attributes[0].bufferIndex = 0
833
-
834
- vertexDescriptor.attributes[1].format = .float2 // texCoord (u, v)
835
- vertexDescriptor.attributes[1].offset = MemoryLayout<Float>.size * 2
836
- vertexDescriptor.attributes[1].bufferIndex = 0
837
-
838
- vertexDescriptor.layouts[0].stride = MemoryLayout<Float>.size * 4 // 2 floats for pos + 2 for texCoord
839
- vertexDescriptor.layouts[0].stepFunction = .perVertex
840
-
841
- let pipelineDescriptor = MTLRenderPipelineDescriptor()
842
- pipelineDescriptor.vertexDescriptor = vertexDescriptor
843
- pipelineDescriptor.vertexFunction = vertexFunction
844
- pipelineDescriptor.fragmentFunction = fragmentFunction
845
-
846
- pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat(rawValue: colorPixelFormat) ?? .bgra8Unorm
847
- pipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
848
- pipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
849
-
850
- pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
851
- pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
852
- pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
853
- pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
854
- pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
855
- pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
856
- pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
857
-
858
- do {
859
- self.pipelineState = try metalDevice.makeRenderPipelineState(descriptor: pipelineDescriptor)
860
- } catch {
861
- print("❌ [GridRenderLayer] Failed to create pipeline state: \(error)")
862
- return
863
- }
864
-
865
- let dataSamplerDesc = MTLSamplerDescriptor()
866
- dataSamplerDesc.minFilter = .nearest
867
- dataSamplerDesc.magFilter = .nearest
868
- self.dataSamplerState = metalDevice.makeSamplerState(descriptor: dataSamplerDesc)
869
-
870
- let colormapSamplerDesc = MTLSamplerDescriptor()
871
- colormapSamplerDesc.minFilter = .nearest
872
- colormapSamplerDesc.magFilter = .nearest
873
- colormapSamplerDesc.sAddressMode = .clampToEdge
874
- self.colormapSamplerState = metalDevice.makeSamplerState(descriptor: colormapSamplerDesc)
875
-
876
- // Process any pending updates that came in before Metal was ready
877
- if let pendingGeometry = pendingGeometryUpdate {
878
- updateGeometry(corners: pendingGeometry.corners, gridDef: pendingGeometry.gridDef)
879
- pendingGeometryUpdate = nil
880
- }
881
-
882
- if let pendingColormap = pendingColormapUpdate {
883
- updateColormapTexture(colormapAsBase64: pendingColormap)
884
- pendingColormapUpdate = nil
885
- }
886
-
887
- if let pendingData = pendingDataUpdate {
888
- updateDataTexture(data: pendingData.data, nx: pendingData.nx, ny: pendingData.ny,
889
- scale: pendingData.scale, offset: pendingData.offset,
890
- missing: pendingData.missing, scaleType: pendingData.scaleType)
891
- pendingDataUpdate = nil
892
- }
893
- }
894
- internal func internalRender(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
895
- guard isVisible,
896
- let pipeline = pipelineState,
897
- let vertices = vertexBuffer,
898
- let indices = indexBuffer,
899
- let dataTex = dataTexture,
900
- let colormapTex = colormapTexture,
901
- indexCount > 0,
902
- let encoder = mtlCommandBuffer.makeRenderCommandEncoder(descriptor: mtlRenderPassDescriptor) else {
903
-
904
- return
905
- }
906
-
907
- let needsLinear = (uniforms.smoothing != 0)
908
- if isDataSamplerLinear != needsLinear {
909
- let samplerDesc = MTLSamplerDescriptor()
910
- samplerDesc.minFilter = needsLinear ? .linear : .nearest
911
- samplerDesc.magFilter = needsLinear ? .linear : .nearest
912
- dataSamplerState = device.makeSamplerState(descriptor: samplerDesc)
913
- isDataSamplerLinear = needsLinear
914
- }
915
-
916
- // Apply zoom scale transformation
917
- let zoom = parameters.zoom
918
- let scale = Float(pow(2.0, zoom))
919
-
920
- let matrixArray = parameters.projectionMatrix
921
- var floatArray = matrixArray.map { $0.floatValue }
922
-
923
- floatArray[0] *= scale // X scale
924
- floatArray[1] *= scale // X rotation
925
- floatArray[2] *= scale // X Z-component
926
- floatArray[3] *= scale // X translation
927
- floatArray[4] *= scale // Y rotation
928
- floatArray[5] *= scale // Y scale
929
- floatArray[6] *= scale // Y Z-component
930
- floatArray[7] *= scale // Y translation
931
- floatArray[8] *= scale // Z X-component
932
- floatArray[9] *= scale // Z Y-component
933
- floatArray[10] *= scale // Z scale
934
- floatArray[11] *= scale // Z translation
935
-
936
- let mvp = matrix_float4x4(
937
- SIMD4<Float>(floatArray[0], floatArray[1], floatArray[2], floatArray[3]),
938
- SIMD4<Float>(floatArray[4], floatArray[5], floatArray[6], floatArray[7]),
939
- SIMD4<Float>(floatArray[8], floatArray[9], floatArray[10], floatArray[11]),
940
- SIMD4<Float>(floatArray[12], floatArray[13], floatArray[14], floatArray[15])
941
- )
942
-
943
- // Add depth state
944
- let depthStencilDescriptor = MTLDepthStencilDescriptor()
945
- depthStencilDescriptor.depthCompareFunction = .always
946
- depthStencilDescriptor.isDepthWriteEnabled = false
947
- let depthStencilState = device.makeDepthStencilState(descriptor: depthStencilDescriptor)
948
-
949
- encoder.setRenderPipelineState(pipeline)
950
- encoder.setDepthStencilState(depthStencilState!)
951
- encoder.setVertexBuffer(vertices, offset: 0, index: 0)
952
- encoder.setVertexBytes([mvp], length: MemoryLayout<matrix_float4x4>.size, index: 1)
953
-
954
- var mutableUniforms = uniforms
955
- encoder.setFragmentBytes(&mutableUniforms, length: MemoryLayout<FragmentUniforms>.stride, index: 0)
956
- encoder.setFragmentTexture(dataTex, index: 0)
957
- encoder.setFragmentTexture(colormapTex, index: 1)
958
- encoder.setFragmentSamplerState(dataSamplerState, index: 0)
959
- encoder.setFragmentSamplerState(colormapSamplerState, index: 1)
960
-
961
- encoder.drawIndexedPrimitives(type: .triangle, indexCount: indexCount, indexType: .uint16, indexBuffer: indices, indexBufferOffset: 0)
962
-
963
- encoder.endEncoding()
964
- }
965
-
966
- deinit {
967
- print("🔴 [GridRenderLayer] deinit called for layer: \(id)")
968
-
969
- // Clean up all resources
970
- frameCache.removeAll()
971
- vertexBuffer = nil
972
- indexBuffer = nil
973
- dataTexture = nil
974
- colormapTexture = nil
975
- device = nil
976
- commandQueue = nil
977
- pipelineState = nil
978
- dataSamplerState = nil
979
- colormapSamplerState = nil
980
-
981
- // Break the reference cycle
982
- hostWrapper = nil
983
- }
984
-
985
- internal func internalRenderingWillEnd() {
986
- vertexBuffer = nil
987
- indexBuffer = nil
988
- dataTexture = nil
989
- colormapTexture = nil
990
- }
991
- }
992
-
993
- extension GridRenderLayer {
994
- // Override to prevent KVC crashes during cleanup
995
- open override func value(forUndefinedKey key: String) -> Any? {
996
- print("⚠️ [GridRenderLayer] Attempted to access undefined key: \(key)")
997
- return nil
998
- }
999
-
1000
- open override func setValue(_ value: Any?, forUndefinedKey key: String) {
1001
- print("⚠️ [GridRenderLayer] Attempted to set undefined key: \(key)")
1002
- // Silently ignore instead of crashing
1003
- }
1004
- }
1
+ import Foundation
2
+ import MapboxMaps
3
+ import Metal
4
+ import libzstd
5
+ import simd
6
+
7
+ // MARK: - Swift-only wrapper for CustomLayerHost conformance
8
+ @objc internal final class GridRenderLayerHost: NSObject, CustomLayerHost {
9
+ weak var layer: GridRenderLayer?
10
+
11
+ init(layer: GridRenderLayer) {
12
+ self.layer = layer
13
+ super.init()
14
+ }
15
+
16
+ func renderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
17
+ layer?.internalRenderingWillStart(metalDevice, colorPixelFormat: colorPixelFormat, depthStencilPixelFormat: depthStencilPixelFormat)
18
+ }
19
+
20
+ func render(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
21
+ layer?.internalRender(parameters, mtlCommandBuffer: mtlCommandBuffer, mtlRenderPassDescriptor: mtlRenderPassDescriptor)
22
+ }
23
+
24
+ func renderingWillEnd() {
25
+ layer?.internalRenderingWillEnd()
26
+ }
27
+ }
28
+
29
+ @objc(GridRenderLayer)
30
+ public class GridRenderLayer: NSObject {
31
+
32
+ // MARK: - Properties
33
+
34
+ public var id: String
35
+ @objc internal var hostWrapper: GridRenderLayerHost!
36
+
37
+ // Metal objects
38
+ private var device: MTLDevice!
39
+ private var commandQueue: MTLCommandQueue!
40
+ private var pipelineState: MTLRenderPipelineState!
41
+ private var vertexBuffer: MTLBuffer?
42
+ private var indexBuffer: MTLBuffer?
43
+ private var dataTexture: MTLTexture?
44
+ private var colormapTexture: MTLTexture?
45
+ private var dataSamplerState: MTLSamplerState!
46
+ private var colormapSamplerState: MTLSamplerState!
47
+ private var isDataSamplerLinear: Bool = false
48
+
49
+ private var pendingColormapUpdate: String?
50
+ private var pendingDataUpdate: (data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String)?
51
+ private var pendingGeometryUpdate: (corners: [String: Any], gridDef: [String: Any])?
52
+
53
+ // Layer state
54
+ private var indexCount: Int = 0
55
+ private var uniforms = FragmentUniforms(
56
+ opacity: 1.0,
57
+ dataRange: SIMD2<Float>(0.0, 1.0),
58
+ scale: 1.0,
59
+ offset: 0.0,
60
+ missingQuantized: 127.0,
61
+ textureSize: SIMD2<Float>(0.0, 0.0),
62
+ smoothing: 1,
63
+ scaleType: 0,
64
+ isPtype: 0,
65
+ isMRMS: 0
66
+ )
67
+ private var isVisible = false
68
+ private var pendingActiveFrameKey: String?
69
+ private var lastRequestedCacheKey: String?
70
+ private let inspectorCache = InspectorDataCache.shared
71
+ private struct FrameMetadata {
72
+ let scale: Float
73
+ let offset: Float
74
+ let missing: Float
75
+ let scaleType: Int
76
+ let nx: Float
77
+ let ny: Float
78
+ let filePath: String
79
+ let originalScale: Float
80
+ let originalOffset: Float
81
+ }
82
+ private var frameCache: [String: FrameMetadata] = [:]
83
+ private let frameCacheQueue = DispatchQueue(label: "com.aguacero.frame-cache-queue")
84
+ private let frameProcessingQueue = DispatchQueue(label: "com.aguacero.frame-processing", qos: .userInitiated, attributes: .concurrent)
85
+ private let semaphore = DispatchSemaphore(value: 8)
86
+
87
+ private struct VertexInfo {
88
+ var mercX: Float
89
+ var mercY: Float
90
+ var texU: Float
91
+ var texV: Float
92
+ var index: UInt16
93
+ }
94
+
95
+ // MARK: - Performance Helper
96
+ private func logPerf(_ msg: String) {
97
+ var taskInfo = mach_task_basic_info()
98
+ var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
99
+ let kerr: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
100
+ $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
101
+ task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
102
+ }
103
+ }
104
+ let mem = (kerr == KERN_SUCCESS) ? Float(taskInfo.resident_size) / 1024.0 / 1024.0 : 0
105
+ print("⚡️ [PERF] [GridRenderLayer] \(msg) | RAM: \(String(format: "%.2f", mem)) MB")
106
+ }
107
+
108
+ @objc
109
+ public init(id: String) {
110
+ self.id = id
111
+ super.init()
112
+ self.hostWrapper = GridRenderLayerHost(layer: self)
113
+ }
114
+
115
+ @objc public func getHostWrapper() -> Any {
116
+ return self.hostWrapper as Any
117
+ }
118
+
119
+ // MARK: - Public Methods (called from Manager)
120
+
121
+ @objc public func setOpacity(value: Float) {
122
+ self.uniforms.opacity = value
123
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
124
+ }
125
+
126
+ @objc public func setDataRange(value: [NSNumber]) {
127
+ self.uniforms.dataRange = SIMD2<Float>(value[0].floatValue, value[1].floatValue)
128
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
129
+ }
130
+
131
+ @objc public func setSmoothing(value: Bool) {
132
+ self.uniforms.smoothing = value ? 1 : 0
133
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
134
+ }
135
+
136
+ @objc(setIsMRMSWithIsMRMS:)
137
+ public func setIsMRMS(isMRMS: Bool) {
138
+ self.uniforms.isMRMS = isMRMS ? 1 : 0
139
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
140
+ }
141
+
142
+ // ADD THIS METHOD
143
+ @objc(setVariableWithVariable:)
144
+ public func setVariable(variable: String) {
145
+ let isPtypeVar = (variable == "ptypeRefl" || variable == "ptypeRate")
146
+ self.uniforms.isPtype = isPtypeVar ? 1 : 0
147
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
148
+ }
149
+
150
+ @objc public func clear() {
151
+ self.isVisible = false
152
+ self.inspectorCache.clear()
153
+ }
154
+
155
+ @objc public func updateDataParameters(scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: NSNumber) { // ADD scaleType parameter
156
+ // Update both the inspector cache AND the rendering uniforms
157
+ self.uniforms.scale = scale.floatValue
158
+ self.uniforms.offset = offset.floatValue
159
+ self.uniforms.missingQuantized = missing.floatValue
160
+ self.uniforms.scaleType = Int32(scaleType.intValue) // ADD THIS
161
+
162
+ inspectorCache.update(
163
+ data: nil,
164
+ nx: inspectorCache.nx,
165
+ ny: inspectorCache.ny,
166
+ scale: scale.floatValue,
167
+ offset: offset.floatValue,
168
+ missing: missing.floatValue,
169
+ scaleType: scaleType.intValue
170
+ )
171
+ }
172
+
173
+ @objc public func updateColormapTexture(colormapAsBase64: String) {
174
+ guard let device = self.device else {
175
+ pendingColormapUpdate = colormapAsBase64
176
+ return
177
+ }
178
+ guard let data = Data(base64Encoded: colormapAsBase64) else { return }
179
+ let textureDescriptor = MTLTextureDescriptor()
180
+ textureDescriptor.pixelFormat = .rgba8Unorm
181
+ textureDescriptor.width = 256
182
+ textureDescriptor.height = 1
183
+ textureDescriptor.usage = .shaderRead
184
+ guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return }
185
+ texture.replace(
186
+ region: MTLRegionMake2D(0, 0, 256, 1),
187
+ mipmapLevel: 0,
188
+ withBytes: (data as NSData).bytes,
189
+ bytesPerRow: 256 * 4
190
+ )
191
+ self.colormapTexture = texture
192
+ }
193
+
194
+ @objc(clearGpuCache)
195
+ public func clearGpuCache() {
196
+ print("ℹ️ [GridRenderLayer] clearGpuCache called")
197
+ frameProcessingQueue.async { [weak self] in
198
+ guard let self = self else { return }
199
+ self.frameCacheQueue.async {
200
+ self.frameCache.removeAll()
201
+ }
202
+ }
203
+ }
204
+
205
+ private func reconstructAndTransformInPlace(data: inout Data) {
206
+ let count = data.count
207
+ if count == 0 { return }
208
+
209
+ // Get raw pointer to memory (Bypasses Swift Array bounds checking)
210
+ data.withUnsafeMutableBytes { rawBuffer in
211
+ guard let ptr = rawBuffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { return }
212
+
213
+ // 1. Setup first byte
214
+ // Cast to Int8 to handle the delta logic, then back to UInt8 for storage
215
+ var runningValue: Int8 = Int8(bitPattern: ptr[0])
216
+
217
+ // Transform first byte immediately: runningValue + 128
218
+ // We use &+ to allow overflow wrapping (which is exactly what we want for -128->0 mapping)
219
+ ptr[0] = UInt8(bitPattern: runningValue) &+ 128
220
+
221
+ // 2. Optimized Loop (One pass for everything)
222
+ for i in 1..<count {
223
+ let delta = Int8(bitPattern: ptr[i])
224
+
225
+ // Reconstruction: Add delta to previous value
226
+ runningValue = runningValue &+ delta
227
+
228
+ // Transformation: Add 128 to shift into UInt8 range for Texture
229
+ ptr[i] = UInt8(bitPattern: runningValue) &+ 128
230
+ }
231
+ }
232
+ }
233
+
234
+ private func processRawData(fileData: Data) -> Data? {
235
+ let start = CFAbsoluteTimeGetCurrent()
236
+
237
+ // 1. Decompress
238
+ // This allocates the only buffer we will use.
239
+ let t1 = CFAbsoluteTimeGetCurrent()
240
+ guard var workingData = self.decompressZstd(data: fileData) else {
241
+ print("❌ [GridRenderLayer] Failed to decompress zstd data")
242
+ return nil
243
+ }
244
+ let t1_diff = (CFAbsoluteTimeGetCurrent() - t1) * 1000
245
+
246
+ // 2. Reconstruct AND Transform (In-Place)
247
+ // No new memory allocation here.
248
+ let t2 = CFAbsoluteTimeGetCurrent()
249
+ self.reconstructAndTransformInPlace(data: &workingData)
250
+ let t2_diff = (CFAbsoluteTimeGetCurrent() - t2) * 1000
251
+
252
+ // 3. (Legacy Timer Placeholder to match logs)
253
+ // Since we combined them, this is effectively instant now
254
+ let t3_diff = 0.0
255
+
256
+ let total = (CFAbsoluteTimeGetCurrent() - start) * 1000
257
+
258
+ // Log CPU transformation metrics
259
+ // Expect Recon+Trans to drop from ~1000ms to ~10-20ms
260
+ logPerf("PROCESS RAW: Total \(String(format: "%.1f", total))ms (Zstd: \(String(format: "%.1f", t1_diff))ms, Recon+Trans: \(String(format: "%.1f", t2_diff))ms)")
261
+
262
+ return workingData
263
+ }
264
+
265
+ private func createTextureFromBytes(bytes: Data, nx: Int, ny: Int) -> MTLTexture? {
266
+ guard let device = self.device else { return nil }
267
+ let textureDescriptor = MTLTextureDescriptor()
268
+ textureDescriptor.pixelFormat = .r8Unorm
269
+ textureDescriptor.width = nx
270
+ textureDescriptor.height = ny
271
+ textureDescriptor.usage = .shaderRead
272
+
273
+ guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return nil }
274
+ texture.replace(
275
+ region: MTLRegionMake2D(0, 0, nx, ny),
276
+ mipmapLevel: 0,
277
+ withBytes: (bytes as NSData).bytes,
278
+ bytesPerRow: nx
279
+ )
280
+ return texture
281
+ }
282
+
283
+ private func updateInspectorCache(filePath: String, reconstructedData: Data?, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int) {
284
+ self.inspectorCache.updateWithFilePath(
285
+ filePath: filePath,
286
+ nx: nx,
287
+ ny: ny,
288
+ scale: scale,
289
+ offset: offset,
290
+ missing: missing,
291
+ scaleType: scaleType
292
+ )
293
+ }
294
+
295
+ @objc(setActiveFrameWithCacheKey:)
296
+ public func setActiveFrame(cacheKey: String) {
297
+ logPerf("setActiveFrame requested: \(cacheKey)")
298
+ setActiveFrameInternal(cacheKey: cacheKey, isExternalRequest: true)
299
+ }
300
+
301
+ private func setActiveFrameInternal(cacheKey: String, isExternalRequest: Bool) {
302
+ if isExternalRequest {
303
+ lastRequestedCacheKey = cacheKey
304
+ } else {
305
+ if lastRequestedCacheKey != cacheKey { return }
306
+ }
307
+
308
+ var frameResult: FrameMetadata?
309
+ frameCacheQueue.sync {
310
+ frameResult = frameCache[cacheKey]
311
+ }
312
+
313
+ if let frame = frameResult {
314
+ frameProcessingQueue.async { [weak self] in
315
+ guard let self = self else { return }
316
+ if self.lastRequestedCacheKey != cacheKey { return }
317
+
318
+ // ALWAYS load from disk. It is fast enough now (20ms).
319
+ // No caching needed.
320
+ let diskStart = CFAbsoluteTimeGetCurrent()
321
+ guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: frame.filePath)) else {
322
+ print("❌ [GridRenderLayer] Failed to load file: \(frame.filePath)")
323
+ return
324
+ }
325
+
326
+ // processRawData is now optimized (in-place) and takes ~20ms
327
+ guard let finalTextureBytes = self.processRawData(fileData: fileData) else {
328
+ print("❌ [GridRenderLayer] Failed to process data for: \(cacheKey)")
329
+ return
330
+ }
331
+
332
+ // Final check before jumping to main thread
333
+ if self.lastRequestedCacheKey != cacheKey { return }
334
+
335
+ DispatchQueue.main.async { [weak self] in
336
+ // ... (Keep existing Main Thread texture upload logic) ...
337
+ guard let self = self else { return }
338
+
339
+ if self.lastRequestedCacheKey != cacheKey { return }
340
+
341
+ let nx = Int(frame.nx)
342
+ let ny = Int(frame.ny)
343
+
344
+ if let existingTexture = self.dataTexture,
345
+ existingTexture.width == nx,
346
+ existingTexture.height == ny {
347
+ existingTexture.replace(
348
+ region: MTLRegionMake2D(0, 0, nx, ny),
349
+ mipmapLevel: 0,
350
+ withBytes: (finalTextureBytes as NSData).bytes,
351
+ bytesPerRow: nx
352
+ )
353
+ } else {
354
+ guard let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx, ny: ny) else { return }
355
+ self.dataTexture = texture
356
+ }
357
+
358
+ self.uniforms.scale = frame.scale
359
+ self.uniforms.offset = frame.offset
360
+ self.uniforms.missingQuantized = frame.missing
361
+ self.uniforms.textureSize = SIMD2<Float>(frame.nx, frame.ny)
362
+ self.uniforms.scaleType = Int32(frame.scaleType)
363
+
364
+ self.isVisible = true
365
+ self.pendingActiveFrameKey = nil
366
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
367
+
368
+ // Update inspector in background
369
+ self.frameProcessingQueue.async { [weak self] in
370
+ self?.updateInspectorCache(
371
+ filePath: frame.filePath,
372
+ reconstructedData: finalTextureBytes, // Pass the data we already processed!
373
+ nx: nx,
374
+ ny: ny,
375
+ scale: frame.scale,
376
+ offset: frame.offset,
377
+ missing: frame.missing,
378
+ scaleType: frame.scaleType
379
+ )
380
+ }
381
+ }
382
+ }
383
+ } else {
384
+ if isExternalRequest {
385
+ self.pendingActiveFrameKey = cacheKey
386
+ }
387
+ }
388
+ }
389
+
390
+ @objc(primeGpuCacheWithFrameInfo:)
391
+ public func primeGpuCache(frameInfo: [String: [String: Any]]) {
392
+ // logPerf("primeGpuCache called with \(frameInfo.count) items")
393
+
394
+ // We do NOT need the frameProcessingQueue here anymore because we are just storing metadata.
395
+ // Doing this synchronously on the caller thread (which is a background thread from Manager) is fine and much faster.
396
+
397
+ self.frameCacheQueue.async { [weak self] in
398
+ guard let self = self else { return }
399
+
400
+ for (cacheKey, info) in frameInfo {
401
+ if self.frameCache[cacheKey] != nil { continue }
402
+
403
+ guard let filePath = info["filePath"] as? String,
404
+ let nx = info["nx"] as? NSNumber,
405
+ let ny = info["ny"] as? NSNumber,
406
+ let scale = info["scale"] as? NSNumber,
407
+ let offset = info["offset"] as? NSNumber,
408
+ let missing = info["missing"] as? NSNumber,
409
+ let scaleTypeStr = info["scaleType"] as? String,
410
+ let originalScale = info["originalScale"] as? NSNumber,
411
+ let originalOffset = info["originalOffset"] as? NSNumber
412
+ else { continue }
413
+
414
+ let metadata = FrameMetadata(
415
+ scale: scale.floatValue,
416
+ offset: offset.floatValue,
417
+ missing: missing.floatValue,
418
+ scaleType: (scaleTypeStr == "sqrt") ? 1 : 0,
419
+ nx: nx.floatValue,
420
+ ny: ny.floatValue,
421
+ filePath: filePath,
422
+ originalScale: originalScale.floatValue,
423
+ originalOffset: originalOffset.floatValue
424
+ // processedData: nil <--- REMOVED
425
+ )
426
+
427
+ self.frameCache[cacheKey] = metadata
428
+ }
429
+ }
430
+ }
431
+
432
+ @objc public func updateDataTexture(data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String) {
433
+ let filePath = data
434
+ logPerf("updateDataTexture called for \(filePath)")
435
+
436
+ frameProcessingQueue.async { [weak self] in
437
+ guard let self = self else { return }
438
+
439
+ guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
440
+ let finalTextureBytes = self.processRawData(fileData: fileData)
441
+ else {
442
+ print("❌ [GridRenderLayer] FAST LANE: Failed to process initial frame data.")
443
+ return
444
+ }
445
+
446
+ DispatchQueue.main.async { [weak self] in
447
+ guard let self = self else { return }
448
+
449
+ let nxInt = nx.intValue
450
+ let nyInt = ny.intValue
451
+
452
+ // REUSE TEXTURE if dimensions match
453
+ if let existingTexture = self.dataTexture,
454
+ existingTexture.width == nxInt,
455
+ existingTexture.height == nyInt {
456
+ existingTexture.replace(
457
+ region: MTLRegionMake2D(0, 0, nxInt, nyInt),
458
+ mipmapLevel: 0,
459
+ withBytes: (finalTextureBytes as NSData).bytes,
460
+ bytesPerRow: nxInt
461
+ )
462
+ } else {
463
+ // Create new texture only if needed
464
+ guard let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nxInt, ny: nyInt) else {
465
+ print("❌ [GridRenderLayer] FAST LANE: Failed to create texture")
466
+ return
467
+ }
468
+ self.dataTexture = texture
469
+ }
470
+
471
+ self.uniforms.scale = scale.floatValue
472
+ self.uniforms.offset = offset.floatValue
473
+ self.uniforms.missingQuantized = missing.floatValue
474
+ self.uniforms.scaleType = Int32((scaleType == "sqrt") ? 1 : 0)
475
+ self.uniforms.textureSize = SIMD2<Float>(nx.floatValue, ny.floatValue)
476
+
477
+ self.isVisible = true
478
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
479
+
480
+ self.updateInspectorCache(
481
+ filePath: filePath,
482
+ reconstructedData: nil,
483
+ nx: nx.intValue,
484
+ ny: ny.intValue,
485
+ scale: scale.floatValue,
486
+ offset: offset.floatValue,
487
+ missing: missing.floatValue,
488
+ scaleType: (scaleType == "sqrt") ? 1 : 0
489
+ )
490
+ }
491
+ }
492
+ }
493
+
494
+ @objc public func updateGeometry(corners: [String: Any], gridDef: [String: Any]) {
495
+ guard self.device != nil else {
496
+ print("⚠️ [GridRenderLayer] Device not ready yet, storing geometry for later")
497
+ pendingGeometryUpdate = (corners: corners, gridDef: gridDef)
498
+ return
499
+ }
500
+
501
+ DispatchQueue.global(qos: .userInitiated).async {
502
+
503
+ var vertices: [Float] = []
504
+ var indices: [UInt16] = []
505
+
506
+ self.generateGeometryData(gridDef: gridDef, vertices: &vertices, indices: &indices)
507
+
508
+ if vertices.isEmpty || indices.isEmpty {
509
+ print("❌ [GridRenderLayer] No geometry generated")
510
+ return
511
+ }
512
+
513
+ self.indexCount = indices.count
514
+
515
+ DispatchQueue.main.async {
516
+ self.vertexBuffer = self.device.makeBuffer(bytes: vertices, length: vertices.count * MemoryLayout<Float>.size, options: [])
517
+ self.indexBuffer = self.device.makeBuffer(bytes: indices, length: indices.count * MemoryLayout<UInt16>.size, options: [])
518
+
519
+ NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
520
+ }
521
+ }
522
+ }
523
+
524
+ private func decompressZstd(data: Data) -> Data? {
525
+ let decompressedSize = data.withUnsafeBytes { ptr in
526
+ ZSTD_getFrameContentSize(ptr.baseAddress, data.count)
527
+ }
528
+
529
+ guard Int64(bitPattern: decompressedSize) > 0 else {
530
+ print("❌ [GridRenderLayer] Could not determine decompressed size")
531
+ return nil
532
+ }
533
+
534
+ var decompressedData = Data(count: Int(decompressedSize))
535
+
536
+ let result = decompressedData.withUnsafeMutableBytes { decompressedPtr -> Int in
537
+ data.withUnsafeBytes { compressedPtr -> Int in
538
+ let returnValue = ZSTD_decompress(
539
+ decompressedPtr.baseAddress,
540
+ Int(decompressedSize),
541
+ compressedPtr.baseAddress,
542
+ data.count
543
+ )
544
+ return Int(returnValue)
545
+ }
546
+ }
547
+
548
+ guard result > 0 && result == decompressedData.count else {
549
+ if result > 0 {
550
+ let size_t_result = size_t(result)
551
+ if let errorName = ZSTD_getErrorName(size_t_result) {
552
+ let errorString = String(cString: errorName)
553
+ print("❌ [GridRenderLayer] Zstd decompression failed: \(errorString)")
554
+ }
555
+ }
556
+ return nil
557
+ }
558
+ return decompressedData
559
+ }
560
+
561
+ private func isLCCType(gridDef: [String: Any]) -> Bool {
562
+ if let type = gridDef["type"] as? String {
563
+ return type == "lambert_conformal_conic"
564
+ }
565
+ return false
566
+ }
567
+
568
+ private func generateLCCGeometry(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
569
+ guard let gridParams = gridDef["grid_params"] as? [String: Any],
570
+ let projParams = gridDef["proj_params"] as? [String: Any],
571
+ let nx = gridParams["nx"] as? Int,
572
+ let ny = gridParams["ny"] as? Int,
573
+ let dx = gridParams["dx"] as? Double,
574
+ let dy = gridParams["dy"] as? Double,
575
+ let x_origin = gridParams["x_origin"] as? Double,
576
+ let y_origin = gridParams["y_origin"] as? Double else {
577
+ return
578
+ }
579
+
580
+ let subdivisions = 60
581
+ let TILE_SIZE: Double = 512.0
582
+
583
+ let x_min = x_origin
584
+ let y_max = y_origin
585
+ let x_max = x_origin + Double(nx - 1) * dx
586
+ let y_min = y_origin + Double(ny - 1) * dy
587
+
588
+ var vertexGrid: [[VertexInfo?]] = Array(repeating: Array(repeating: nil, count: subdivisions + 1), count: subdivisions + 1)
589
+ var validVertexCount: UInt16 = 0
590
+
591
+ // Generate vertices
592
+ for row in 0...subdivisions {
593
+ for col in 0...subdivisions {
594
+ let t_x = Double(col) / Double(subdivisions)
595
+ let t_y = Double(row) / Double(subdivisions)
596
+
597
+ let proj_x = x_min + t_x * (x_max - x_min)
598
+ let proj_y = y_max + t_y * (y_min - y_max)
599
+
600
+ // Convert LCC projection coordinates to lat/lon
601
+ if let (lon, lat) = lccToLonLat(i: proj_x, j: proj_y, gridDef: gridDef) {
602
+ // Convert lat/lon to Mercator
603
+ let mercX_normalized = (lon + 180.0) / 360.0
604
+ let clampedLat = max(-85.05112878, min(85.05112878, lat))
605
+ let sinLatitude = sin(clampedLat * .pi / 180.0)
606
+ let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
607
+
608
+ let mercX = mercX_normalized * TILE_SIZE
609
+ let mercY = mercY_normalized * TILE_SIZE
610
+
611
+ // Check for invalid values
612
+ if !mercX.isFinite || !mercY.isFinite {
613
+ vertexGrid[row][col] = nil
614
+ continue
615
+ }
616
+
617
+ let tex_u = Float(t_x)
618
+ let tex_v = Float(t_y)
619
+
620
+ let vInfo = VertexInfo(
621
+ mercX: Float(mercX),
622
+ mercY: Float(mercY),
623
+ texU: tex_u,
624
+ texV: tex_v,
625
+ index: validVertexCount
626
+ )
627
+
628
+ vertexGrid[row][col] = vInfo
629
+
630
+ vertices.append(Float(mercX))
631
+ vertices.append(Float(mercY))
632
+ vertices.append(tex_u)
633
+ vertices.append(tex_v)
634
+
635
+ validVertexCount += 1
636
+ } else {
637
+ vertexGrid[row][col] = nil
638
+ }
639
+ }
640
+ }
641
+
642
+ if vertices.isEmpty {
643
+ print("❌ [LCC Geometry] No valid vertices generated")
644
+ return
645
+ }
646
+
647
+ // Generate indices
648
+ for row in 0..<subdivisions {
649
+ for col in 0..<subdivisions {
650
+ guard let topLeft = vertexGrid[row][col],
651
+ let topRight = vertexGrid[row][col + 1],
652
+ let bottomLeft = vertexGrid[row + 1][col],
653
+ let bottomRight = vertexGrid[row + 1][col + 1] else {
654
+ continue
655
+ }
656
+
657
+ indices.append(topLeft.index)
658
+ indices.append(bottomLeft.index)
659
+ indices.append(topRight.index)
660
+
661
+ indices.append(topRight.index)
662
+ indices.append(bottomLeft.index)
663
+ indices.append(bottomRight.index)
664
+ }
665
+ }
666
+ }
667
+
668
+ private func lccToLonLat(i: Double, j: Double, gridDef: [String: Any]) -> (lon: Double, lat: Double)? {
669
+ guard let projParams = gridDef["proj_params"] as? [String: Any],
670
+ let lat_0 = (projParams["lat_0"] as? NSNumber)?.doubleValue,
671
+ let lon_0 = (projParams["lon_0"] as? NSNumber)?.doubleValue,
672
+ let lat_1 = (projParams["lat_1"] as? NSNumber)?.doubleValue,
673
+ let lat_2 = (projParams["lat_2"] as? NSNumber)?.doubleValue,
674
+ let r_earth = (projParams["R"] as? NSNumber)?.doubleValue else {
675
+ print("❌ [LCC Geometry] Failed to extract LCC parameters.")
676
+ return nil
677
+ }
678
+
679
+ let π = Double.pi
680
+ let toRad = π / 180.0
681
+ let toDeg = 180.0 / π
682
+
683
+ let lat1_rad = lat_1 * toRad
684
+ let lat2_rad = lat_2 * toRad
685
+ let lat0_rad = lat_0 * toRad
686
+ let lon0_rad = lon_0 * toRad
687
+
688
+ let n: Double
689
+ if abs(lat_1 - lat_2) < 1e-10 {
690
+ n = sin(lat1_rad)
691
+ } else {
692
+ n = log(cos(lat1_rad) / cos(lat2_rad)) / log(tan(π/4.0 + lat2_rad/2.0) / tan(π/4.0 + lat1_rad/2.0))
693
+ }
694
+
695
+ let F = cos(lat1_rad) * pow(tan(π/4.0 + lat1_rad/2.0), n) / n
696
+ let rho_0 = r_earth * F * pow(tan(π/4.0 + lat0_rad/2.0), -n)
697
+
698
+ let x = i
699
+ let y = j
700
+
701
+ let rho = sqrt(x * x + (rho_0 - y) * (rho_0 - y))
702
+ if rho < 1e-10 {
703
+ return (lon: lon_0, lat: lat_0)
704
+ }
705
+
706
+ let theta = atan2(x, rho_0 - y)
707
+
708
+ let lon = lon0_rad + theta / n
709
+ let lat = 2.0 * atan(pow(r_earth * F / rho, 1.0 / n)) - π/2.0
710
+
711
+ let lonDeg = lon * toDeg
712
+ let latDeg = lat * toDeg
713
+
714
+ if !lonDeg.isFinite || !latDeg.isFinite {
715
+ return nil
716
+ }
717
+
718
+ return (lon: lonDeg, lat: latDeg)
719
+ }
720
+
721
+ private func generateGeometryData(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
722
+ guard let gridParams = gridDef["grid_params"] as? [String: Any] else {
723
+ print("❌ [generateGeometryData] No grid_params found")
724
+ return
725
+ }
726
+
727
+ // Check grid type
728
+ let isGFS = isGFSType(gridParams: gridParams)
729
+ let isLCC = isLCCType(gridDef: gridDef)
730
+
731
+ if isGFS {
732
+ // GFS path remains unchanged
733
+ let subdivisions = 120
734
+ let verticesPerRow = (subdivisions * 3) + 1
735
+ let TILE_SIZE: Double = 512.0
736
+
737
+ for row in 0...subdivisions {
738
+ for col in 0...(subdivisions * 3) {
739
+ let v_interp = Float(row) / Float(subdivisions)
740
+ let u_interp = Float(col) / Float(subdivisions)
741
+ let lon = -540.0 + Double(u_interp) * 1080.0
742
+ let lat = -90.0 + Double(v_interp) * 180.0
743
+
744
+ let merc = lonLatToMercator(lon: lon, lat: lat, tileSize: TILE_SIZE)
745
+ vertices.append(contentsOf: [merc.x, merc.y])
746
+
747
+ let tex_u = Float((lon + 180.0) / 360.0)
748
+ let tex_v = 1.0 - v_interp
749
+ vertices.append(contentsOf: [tex_u, tex_v])
750
+ }
751
+ }
752
+
753
+ for row in 0..<subdivisions {
754
+ for col in 0..<(subdivisions * 3) {
755
+ let tl = UInt16(row * verticesPerRow + col)
756
+ let tr = tl + 1
757
+ let bl = UInt16((row + 1) * verticesPerRow + col)
758
+ let br = bl + 1
759
+ indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
760
+ }
761
+ }
762
+ return
763
+ }
764
+
765
+ if isLCC {
766
+ generateLCCGeometry(gridDef: gridDef, vertices: &vertices, indices: &indices)
767
+ return
768
+ }
769
+
770
+ let nx = gridParams["nx"] as? Int ?? 0
771
+ let ny = gridParams["ny"] as? Int ?? 0
772
+ let lon_first = gridParams["lon_first"] as? Double ?? 0.0
773
+ let lat_first = gridParams["lat_first"] as? Double ?? 90.0
774
+ let dx = gridParams["dx_degrees"] as? Double ?? 0.0
775
+ let dy = gridParams["dy_degrees"] as? Double ?? 0.0
776
+ let lon_last = gridParams["lon_last"] as? Double ?? (lon_first + Double(nx - 1) * dx)
777
+ let lat_last = gridParams["lat_last"] as? Double ?? (lat_first + Double(ny - 1) * dy)
778
+
779
+ let lat_span = lat_last - lat_first
780
+ let isSouthToNorth = lat_span > 0
781
+
782
+ // Check if this is ECMWF and normalize longitudes
783
+ let isECMWF = isECMWFType(gridParams: gridParams)
784
+ var data_lon_first_180 = lon_first
785
+ var data_lon_last_180 = lon_last
786
+
787
+ if isECMWF {
788
+ // Convert ECMWF's 180 to -180 range to -180 to 180
789
+ data_lon_first_180 = lon_first >= 180 ? lon_first - 360 : lon_first
790
+ data_lon_last_180 = lon_last >= 180 ? lon_last - 360 : lon_last
791
+ } else {
792
+ // For GFS and other models
793
+ data_lon_first_180 = lon_first > 180 ? lon_first - 360 : lon_first
794
+ data_lon_last_180 = lon_last > 180 ? lon_last - 360 : lon_last
795
+ }
796
+
797
+ let data_lon_range = data_lon_last_180 - data_lon_first_180
798
+
799
+ let subdivisions_x = 120
800
+ let subdivisions_y = 60
801
+ let verticesPerRow = subdivisions_x + 1
802
+ let TILE_SIZE: Double = 512.0
803
+
804
+ let worldCopies = (data_lon_range > 300) ? [-1, 0, 1] : [0]
805
+
806
+ for world_copy in worldCopies {
807
+ let vertexStartIndex = UInt16(vertices.count / 4)
808
+ let lon_offset = Double(world_copy) * 360.0
809
+
810
+ for row in 0...subdivisions_y {
811
+ for col in 0...subdivisions_x {
812
+ let v_interp = Float(row) / Float(subdivisions_y)
813
+ let u_interp = Float(col) / Float(subdivisions_x)
814
+
815
+ let vertex_lon = data_lon_first_180 + (Double(u_interp) * data_lon_range)
816
+ let vertex_lat = lat_first + (Double(v_interp) * lat_span)
817
+
818
+ let mercX_normalized = ((vertex_lon + lon_offset) + 180.0) / 360.0
819
+ let clampedLat = max(-85.05112878, min(85.05112878, vertex_lat))
820
+ let sinLatitude = sin(clampedLat * .pi / 180.0)
821
+ let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
822
+ let mercX = mercX_normalized * TILE_SIZE
823
+ let mercY = mercY_normalized * TILE_SIZE
824
+
825
+ vertices.append(contentsOf: [Float(mercX), Float(mercY)])
826
+
827
+ let tex_u = u_interp
828
+ let tex_v = isSouthToNorth ? (1.0 - v_interp) : v_interp
829
+
830
+ vertices.append(contentsOf: [tex_u, tex_v])
831
+ }
832
+ }
833
+
834
+ for row in 0..<UInt16(subdivisions_y) {
835
+ for col in 0..<UInt16(subdivisions_x) {
836
+ let tl = vertexStartIndex + row * UInt16(verticesPerRow) + col
837
+ let tr = tl + 1
838
+ let bl = vertexStartIndex + (row + 1) * UInt16(verticesPerRow) + col
839
+ let br = bl + 1
840
+
841
+ if isSouthToNorth {
842
+ indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
843
+ } else {
844
+ indices.append(contentsOf: [tl, tr, bl, bl, tr, br])
845
+ }
846
+ }
847
+ }
848
+ }
849
+ }
850
+
851
+ private func isGFSType(gridParams: [String: Any]) -> Bool {
852
+ return (gridParams["lon_first"] as? Double) == 0.0 &&
853
+ abs((gridParams["lat_first"] as? Double) ?? -1) == 90.0
854
+ }
855
+
856
+ private func isECMWFType(gridParams: [String: Any]) -> Bool {
857
+ return (gridParams["lon_first"] as? Double) == 180.0 &&
858
+ (gridParams["lat_first"] as? Double) == 90.0
859
+ }
860
+
861
+ private func lonLatToMercator(lon: Double, lat: Double, tileSize: Double) -> (x: Float, y: Float) {
862
+ let mercX_normalized = (lon + 180.0) / 360.0
863
+ let clampedLat = max(-85.05112878, min(85.05112878, lat))
864
+ let sinLatitude = sin(clampedLat * .pi / 180.0)
865
+ let mercY_normalized = 0.5 - log((1.0 + sinLatitude) / (1.0 - sinLatitude)) / (4.0 * .pi)
866
+
867
+ return (x: Float(mercX_normalized * tileSize), y: Float(mercY_normalized * tileSize))
868
+ }
869
+
870
+ // MARK: - Internal methods for CustomLayerHost (called by wrapper)
871
+
872
+ internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
873
+ self.device = metalDevice
874
+ self.commandQueue = metalDevice.makeCommandQueue()
875
+
876
+ let bundle = Bundle(for: GridRenderLayer.self)
877
+
878
+ // Determine if we're running on simulator or device
879
+ #if targetEnvironment(simulator)
880
+ let metallibName = "Shaders-simulator"
881
+ #else
882
+ let metallibName = "Shaders-device"
883
+ #endif
884
+
885
+ // Try to load pre-compiled metallib for the current platform
886
+ var defaultLibrary: MTLLibrary?
887
+
888
+ // 1. Look in the main bundle level
889
+ if let metallibUrl = bundle.url(forResource: metallibName, withExtension: "metallib") {
890
+ print("ℹ️ [GridRenderLayer] Found pre-compiled shaders at: \(metallibUrl.lastPathComponent)")
891
+ defaultLibrary = try? metalDevice.makeLibrary(URL: metallibUrl)
892
+ }
893
+
894
+ // 2. Fall back to compiled-shaders subdirectory
895
+ if defaultLibrary == nil {
896
+ if let metallibUrl = bundle.url(forResource: metallibName, withExtension: "metallib", subdirectory: "compiled-shaders") {
897
+ print("ℹ️ [GridRenderLayer] Found pre-compiled shaders in subdirectory: \(metallibUrl.lastPathComponent)")
898
+ defaultLibrary = try? metalDevice.makeLibrary(URL: metallibUrl)
899
+ }
900
+ }
901
+
902
+ // 3. Fall back to compiling from .metal source (for development with npm link)
903
+ if defaultLibrary == nil {
904
+ if let metalUrl = bundle.url(forResource: "Shaders", withExtension: "metal") {
905
+ print("⚠️ [GridRenderLayer] Pre-compiled shaders not found. Compiling from source: \(metalUrl.lastPathComponent)")
906
+ if let source = try? String(contentsOf: metalUrl),
907
+ let library = try? metalDevice.makeLibrary(source: source, options: nil) {
908
+ defaultLibrary = library
909
+ }
910
+ }
911
+ }
912
+
913
+ // Neither worked
914
+ if defaultLibrary == nil {
915
+ print("❌ [GridRenderLayer] Could not find or compile Metal shaders")
916
+ print(" Bundle path: \(bundle.bundlePath)")
917
+ return
918
+ }
919
+
920
+ guard let library = defaultLibrary else {
921
+ print("❌ [GridRenderLayer] Failed to create Metal library")
922
+ return
923
+ }
924
+
925
+ let vertexFunction = library.makeFunction(name: "vertex_main")
926
+ let fragmentFunction = library.makeFunction(name: "fragment_main")
927
+
928
+ // Set up vertex descriptor
929
+ let vertexDescriptor = MTLVertexDescriptor()
930
+ vertexDescriptor.attributes[0].format = .float2 // position (x, y)
931
+ vertexDescriptor.attributes[0].offset = 0
932
+ vertexDescriptor.attributes[0].bufferIndex = 0
933
+
934
+ vertexDescriptor.attributes[1].format = .float2 // texCoord (u, v)
935
+ vertexDescriptor.attributes[1].offset = MemoryLayout<Float>.size * 2
936
+ vertexDescriptor.attributes[1].bufferIndex = 0
937
+
938
+ vertexDescriptor.layouts[0].stride = MemoryLayout<Float>.size * 4 // 2 floats for pos + 2 for texCoord
939
+ vertexDescriptor.layouts[0].stepFunction = .perVertex
940
+
941
+ let pipelineDescriptor = MTLRenderPipelineDescriptor()
942
+ pipelineDescriptor.vertexDescriptor = vertexDescriptor
943
+ pipelineDescriptor.vertexFunction = vertexFunction
944
+ pipelineDescriptor.fragmentFunction = fragmentFunction
945
+
946
+ pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat(rawValue: colorPixelFormat) ?? .bgra8Unorm
947
+ pipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
948
+ pipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
949
+
950
+ pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
951
+ pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
952
+ pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
953
+ pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
954
+ pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
955
+ pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
956
+ pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
957
+
958
+ do {
959
+ self.pipelineState = try metalDevice.makeRenderPipelineState(descriptor: pipelineDescriptor)
960
+ } catch {
961
+ print("❌ [GridRenderLayer] Failed to create pipeline state: \(error)")
962
+ return
963
+ }
964
+
965
+ let dataSamplerDesc = MTLSamplerDescriptor()
966
+ dataSamplerDesc.minFilter = .nearest
967
+ dataSamplerDesc.magFilter = .nearest
968
+ self.dataSamplerState = metalDevice.makeSamplerState(descriptor: dataSamplerDesc)
969
+
970
+ let colormapSamplerDesc = MTLSamplerDescriptor()
971
+ colormapSamplerDesc.minFilter = .nearest
972
+ colormapSamplerDesc.magFilter = .nearest
973
+ colormapSamplerDesc.sAddressMode = .clampToEdge
974
+ self.colormapSamplerState = metalDevice.makeSamplerState(descriptor: colormapSamplerDesc)
975
+
976
+ // Process any pending updates that came in before Metal was ready
977
+ if let pendingGeometry = pendingGeometryUpdate {
978
+ updateGeometry(corners: pendingGeometry.corners, gridDef: pendingGeometry.gridDef)
979
+ pendingGeometryUpdate = nil
980
+ }
981
+
982
+ if let pendingColormap = pendingColormapUpdate {
983
+ updateColormapTexture(colormapAsBase64: pendingColormap)
984
+ pendingColormapUpdate = nil
985
+ }
986
+
987
+ if let pendingData = pendingDataUpdate {
988
+ updateDataTexture(data: pendingData.data, nx: pendingData.nx, ny: pendingData.ny,
989
+ scale: pendingData.scale, offset: pendingData.offset,
990
+ missing: pendingData.missing, scaleType: pendingData.scaleType)
991
+ pendingDataUpdate = nil
992
+ }
993
+ }
994
+ internal func internalRender(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
995
+ guard isVisible,
996
+ let pipeline = pipelineState,
997
+ let vertices = vertexBuffer,
998
+ let indices = indexBuffer,
999
+ let dataTex = dataTexture,
1000
+ let colormapTex = colormapTexture,
1001
+ indexCount > 0,
1002
+ let encoder = mtlCommandBuffer.makeRenderCommandEncoder(descriptor: mtlRenderPassDescriptor) else {
1003
+
1004
+ return
1005
+ }
1006
+
1007
+ let needsLinear = (uniforms.smoothing != 0)
1008
+ if isDataSamplerLinear != needsLinear {
1009
+ let samplerDesc = MTLSamplerDescriptor()
1010
+ samplerDesc.minFilter = needsLinear ? .linear : .nearest
1011
+ samplerDesc.magFilter = needsLinear ? .linear : .nearest
1012
+ dataSamplerState = device.makeSamplerState(descriptor: samplerDesc)
1013
+ isDataSamplerLinear = needsLinear
1014
+ }
1015
+
1016
+ // Apply zoom scale transformation
1017
+ let zoom = parameters.zoom
1018
+ let scale = Float(pow(2.0, zoom))
1019
+
1020
+ let matrixArray = parameters.projectionMatrix
1021
+ var floatArray = matrixArray.map { $0.floatValue }
1022
+
1023
+ floatArray[0] *= scale // X scale
1024
+ floatArray[1] *= scale // X rotation
1025
+ floatArray[2] *= scale // X Z-component
1026
+ floatArray[3] *= scale // X translation
1027
+ floatArray[4] *= scale // Y rotation
1028
+ floatArray[5] *= scale // Y scale
1029
+ floatArray[6] *= scale // Y Z-component
1030
+ floatArray[7] *= scale // Y translation
1031
+ floatArray[8] *= scale // Z X-component
1032
+ floatArray[9] *= scale // Z Y-component
1033
+ floatArray[10] *= scale // Z scale
1034
+ floatArray[11] *= scale // Z translation
1035
+
1036
+ let mvp = matrix_float4x4(
1037
+ SIMD4<Float>(floatArray[0], floatArray[1], floatArray[2], floatArray[3]),
1038
+ SIMD4<Float>(floatArray[4], floatArray[5], floatArray[6], floatArray[7]),
1039
+ SIMD4<Float>(floatArray[8], floatArray[9], floatArray[10], floatArray[11]),
1040
+ SIMD4<Float>(floatArray[12], floatArray[13], floatArray[14], floatArray[15])
1041
+ )
1042
+
1043
+ // Add depth state
1044
+ let depthStencilDescriptor = MTLDepthStencilDescriptor()
1045
+ depthStencilDescriptor.depthCompareFunction = .always
1046
+ depthStencilDescriptor.isDepthWriteEnabled = false
1047
+ let depthStencilState = device.makeDepthStencilState(descriptor: depthStencilDescriptor)
1048
+
1049
+ encoder.setRenderPipelineState(pipeline)
1050
+ encoder.setDepthStencilState(depthStencilState!)
1051
+ encoder.setVertexBuffer(vertices, offset: 0, index: 0)
1052
+ encoder.setVertexBytes([mvp], length: MemoryLayout<matrix_float4x4>.size, index: 1)
1053
+
1054
+ var mutableUniforms = uniforms
1055
+ encoder.setFragmentBytes(&mutableUniforms, length: MemoryLayout<FragmentUniforms>.stride, index: 0)
1056
+ encoder.setFragmentTexture(dataTex, index: 0)
1057
+ encoder.setFragmentTexture(colormapTex, index: 1)
1058
+ encoder.setFragmentSamplerState(dataSamplerState, index: 0)
1059
+ encoder.setFragmentSamplerState(colormapSamplerState, index: 1)
1060
+
1061
+ encoder.drawIndexedPrimitives(type: .triangle, indexCount: indexCount, indexType: .uint16, indexBuffer: indices, indexBufferOffset: 0)
1062
+
1063
+ encoder.endEncoding()
1064
+ }
1065
+
1066
+ deinit {
1067
+ print("🔴 [GridRenderLayer] deinit called for layer: \(id)")
1068
+
1069
+ // Clean up all resources
1070
+ frameCacheQueue.sync {
1071
+ frameCache.removeAll()
1072
+ }
1073
+ vertexBuffer = nil
1074
+ indexBuffer = nil
1075
+ dataTexture = nil
1076
+ colormapTexture = nil
1077
+ device = nil
1078
+ commandQueue = nil
1079
+ pipelineState = nil
1080
+ dataSamplerState = nil
1081
+ colormapSamplerState = nil
1082
+
1083
+ // Break the reference cycle
1084
+ hostWrapper = nil
1085
+ }
1086
+
1087
+ internal func internalRenderingWillEnd() {
1088
+ // DO NOT clear these here, otherwise the layer disappears during map transitions/resizing
1089
+ // vertexBuffer = nil
1090
+ // indexBuffer = nil
1091
+ // dataTexture = nil
1092
+ // colormapTexture = nil
1093
+ }
1094
+ }
1095
+
1096
+ extension GridRenderLayer {
1097
+ // Override to prevent KVC crashes during cleanup
1098
+ open override func value(forUndefinedKey key: String) -> Any? {
1099
+ print("⚠️ [GridRenderLayer] Attempted to access undefined key: \(key)")
1100
+ return nil
1101
+ }
1102
+
1103
+ open override func setValue(_ value: Any?, forUndefinedKey key: String) {
1104
+ print("⚠️ [GridRenderLayer] Attempted to set undefined key: \(key)")
1105
+ // Silently ignore instead of crashing
1106
+ }
1107
+ }