@aguacerowx/react-native 0.0.24 → 0.0.25

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