@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.
- package/README.md +126 -126
- package/aguacerowx-react-native.podspec +38 -38
- package/android/build.gradle +107 -107
- package/android/src/main/AndroidManifest.xml +6 -6
- package/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
- package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +672 -664
- package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
- package/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
- package/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
- package/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
- package/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
- package/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
- package/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
- package/android/src/main/res/raw/fragment_shader.glsl +161 -161
- package/android/src/main/res/raw/vertex_shader.glsl +19 -19
- package/index.js +2 -2
- package/ios/AguaceroPackage.m +18 -18
- package/ios/FragmentUniforms.swift +15 -15
- package/ios/GridRenderLayer.swift +1043 -1003
- package/ios/GridRenderLayerBridge.swift +37 -37
- package/ios/GridRenderLayerManager.mm +157 -157
- package/ios/GridRenderLayerView.h +30 -30
- package/ios/GridRenderLayerView.m +256 -241
- package/ios/InspectorDataCache.swift +65 -65
- package/ios/InspectorModule.m +9 -9
- package/ios/InspectorModule.swift +63 -63
- package/ios/Shaders.metal +190 -190
- package/ios/WeatherFrameProcessorModule.m +15 -15
- package/ios/WeatherFrameProcessorModule.swift +103 -103
- package/lib/commonjs/README.md +126 -126
- package/lib/commonjs/aguacerowx-react-native.podspec +38 -38
- package/lib/commonjs/android/build.gradle +107 -107
- package/lib/commonjs/android/src/main/AndroidManifest.xml +6 -6
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +672 -664
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
- package/lib/commonjs/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
- package/lib/commonjs/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
- package/lib/commonjs/android/src/main/res/raw/fragment_shader.glsl +161 -161
- package/lib/commonjs/android/src/main/res/raw/vertex_shader.glsl +19 -19
- package/lib/commonjs/babel.config.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ios/AguaceroPackage.m +18 -18
- package/lib/commonjs/ios/FragmentUniforms.swift +15 -15
- package/lib/commonjs/ios/GridRenderLayer.swift +1043 -1003
- package/lib/commonjs/ios/GridRenderLayerBridge.swift +37 -37
- package/lib/commonjs/ios/GridRenderLayerManager.mm +157 -157
- package/lib/commonjs/ios/GridRenderLayerView.h +30 -30
- package/lib/commonjs/ios/GridRenderLayerView.m +256 -241
- package/lib/commonjs/ios/InspectorDataCache.swift +65 -65
- package/lib/commonjs/ios/InspectorModule.m +9 -9
- package/lib/commonjs/ios/InspectorModule.swift +63 -63
- package/lib/commonjs/ios/Shaders.metal +190 -190
- package/lib/commonjs/ios/WeatherFrameProcessorModule.m +15 -15
- package/lib/commonjs/ios/WeatherFrameProcessorModule.swift +103 -103
- package/lib/commonjs/package.json +72 -72
- package/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
- package/lib/commonjs/scripts/compile-shaders.js.map +1 -1
- package/lib/commonjs/scripts/compile-shaders.sh +38 -38
- package/lib/commonjs/src/AguaceroContext.js.map +1 -1
- package/lib/commonjs/src/GridRenderLayer.js.map +1 -1
- package/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
- package/lib/commonjs/src/MapManager.js.map +1 -1
- package/lib/commonjs/src/MapRegistry.js.map +1 -1
- package/lib/commonjs/src/StyleApplicator.js +6 -6
- package/lib/commonjs/src/StyleApplicator.js.map +1 -1
- package/lib/commonjs/src/WeatherLayerManager.js +2 -2
- package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/commonjs/tsconfig.json +23 -23
- package/lib/module/README.md +126 -126
- package/lib/module/aguacerowx-react-native.podspec +38 -38
- package/lib/module/android/build.gradle +107 -107
- package/lib/module/android/src/main/AndroidManifest.xml +6 -6
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +672 -664
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
- package/lib/module/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
- package/lib/module/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
- package/lib/module/android/src/main/res/raw/fragment_shader.glsl +161 -161
- package/lib/module/android/src/main/res/raw/vertex_shader.glsl +19 -19
- package/lib/module/babel.config.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ios/AguaceroPackage.m +18 -18
- package/lib/module/ios/FragmentUniforms.swift +15 -15
- package/lib/module/ios/GridRenderLayer.swift +1043 -1003
- package/lib/module/ios/GridRenderLayerBridge.swift +37 -37
- package/lib/module/ios/GridRenderLayerManager.mm +157 -157
- package/lib/module/ios/GridRenderLayerView.h +30 -30
- package/lib/module/ios/GridRenderLayerView.m +256 -241
- package/lib/module/ios/InspectorDataCache.swift +65 -65
- package/lib/module/ios/InspectorModule.m +9 -9
- package/lib/module/ios/InspectorModule.swift +63 -63
- package/lib/module/ios/Shaders.metal +190 -190
- package/lib/module/ios/WeatherFrameProcessorModule.m +15 -15
- package/lib/module/ios/WeatherFrameProcessorModule.swift +103 -103
- package/lib/module/lib/commonjs/README.md +126 -126
- package/lib/module/lib/commonjs/aguacerowx-react-native.podspec +38 -38
- package/lib/module/lib/commonjs/babel.config.js.map +1 -1
- package/lib/module/lib/commonjs/index.js.map +1 -1
- package/lib/module/lib/commonjs/package.json +72 -72
- package/lib/module/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
- package/lib/module/lib/commonjs/scripts/compile-shaders.js.map +1 -1
- package/lib/module/lib/commonjs/src/AguaceroContext.js.map +1 -1
- package/lib/module/lib/commonjs/src/GridRenderLayer.js.map +1 -1
- package/lib/module/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
- package/lib/module/lib/commonjs/src/MapManager.js.map +1 -1
- package/lib/module/lib/commonjs/src/MapRegistry.js.map +1 -1
- package/lib/module/lib/commonjs/src/StyleApplicator.js +6 -6
- package/lib/module/lib/commonjs/src/StyleApplicator.js.map +1 -1
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js +2 -2
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/lib/commonjs/tsconfig.json +23 -23
- package/lib/module/package.json +72 -72
- package/lib/module/react-native-builder-bob.config.js.map +1 -1
- package/lib/module/scripts/compile-shaders.js.map +1 -1
- package/lib/module/scripts/compile-shaders.sh +38 -38
- package/lib/module/src/AguaceroContext.js.map +1 -1
- package/lib/module/src/GridRenderLayer.js.map +1 -1
- package/lib/module/src/GridRenderLayerNativeComponent.js.map +1 -1
- package/lib/module/src/MapManager.js.map +1 -1
- package/lib/module/src/MapRegistry.js.map +1 -1
- package/lib/module/src/StyleApplicator.js +6 -6
- package/lib/module/src/StyleApplicator.js.map +1 -1
- package/lib/module/src/WeatherLayerManager.js +2 -2
- package/lib/module/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/tsconfig.json +23 -23
- package/package.json +72 -72
- package/src/AguaceroContext.js +3 -3
- package/src/GridRenderLayer.js +217 -217
- package/src/GridRenderLayerNativeComponent.ts +15 -15
- package/src/MapManager.js +155 -155
- package/src/MapRegistry.js +34 -34
- package/src/StyleApplicator.js +240 -240
- package/src/WeatherLayerManager.js +951 -951
- package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/results.bin +0 -1
- package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/results.bin +0 -1
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/AguaceroPackage.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/BuildConfig.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayerView.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderManager.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/InspectorModule.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/ShaderUtils.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/WeatherFrameProcessorModule.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
- package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
- package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
- package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
- package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
- package/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
- package/android/build/generated/source/codegen/schema.json +0 -1
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
- package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/lib/commonjs/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
- package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
- package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
- package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
- package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
- package/lib/commonjs/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
- package/lib/commonjs/android/build/generated/source/codegen/schema.json +0 -1
- package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
- package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/lib/commonjs/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/lib/commonjs/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/lib/commonjs/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/lib/commonjs/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/lib/commonjs/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
- package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/commonjs/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
- package/lib/commonjs/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
- package/lib/commonjs/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
- package/lib/commonjs/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/lib/commonjs/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/lib/commonjs/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
- package/lib/commonjs/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/lib/module/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
- package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
- package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
- package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
- package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
- package/lib/module/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
- package/lib/module/android/build/generated/source/codegen/schema.json +0 -1
- package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
- package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/lib/module/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/lib/module/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/lib/module/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/lib/module/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/lib/module/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
- package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/lib/module/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/lib/module/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/lib/module/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/module/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
- package/lib/module/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
- package/lib/module/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
- package/lib/module/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/lib/module/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/lib/module/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
- package/lib/module/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/lib/module/lib/commonjs/android/build.gradle +0 -108
- package/lib/module/lib/commonjs/android/src/main/AndroidManifest.xml +0 -7
- package/lib/module/lib/commonjs/ios/AguaceroPackage.m +0 -19
- package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +0 -16
- package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +0 -1003
- package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -38
- package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +0 -158
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +0 -31
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +0 -242
- package/lib/module/lib/commonjs/ios/InspectorDataCache.swift +0 -66
- package/lib/module/lib/commonjs/ios/InspectorModule.m +0 -10
- package/lib/module/lib/commonjs/ios/InspectorModule.swift +0 -64
- package/lib/module/lib/commonjs/ios/Shaders.metal +0 -191
- package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.m +0 -16
- package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.swift +0 -104
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec-generated.mm +0 -0
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec.h +0 -0
- package/lib/module/lib/commonjs/scripts/compile-shaders.sh +0 -39
|
@@ -1,952 +1,952 @@
|
|
|
1
|
-
// packages/react-native/src/WeatherLayerManager.js
|
|
2
|
-
|
|
3
|
-
import React, { useState, useRef, useContext, useEffect, forwardRef, useImperativeHandle, useMemo } from 'react';
|
|
4
|
-
import { AguaceroCore, getUnitConversionFunction } from '@aguacerowx/javascript-sdk';
|
|
5
|
-
import { AguaceroContext } from './AguaceroContext';
|
|
6
|
-
import { GridRenderLayer } from './GridRenderLayer';
|
|
7
|
-
import { fromByteArray } from 'base64-js';
|
|
8
|
-
import { Platform, NativeModules } from 'react-native';
|
|
9
|
-
import { mapRegistry } from './MapRegistry';
|
|
10
|
-
|
|
11
|
-
console.log("--- Aguacero Native Module Initial State Check ---");
|
|
12
|
-
console.log("All NativeModules:", Object.keys(NativeModules));
|
|
13
|
-
console.log("WeatherFrameProcessorModule available?:", !!NativeModules.WeatherFrameProcessorModule);
|
|
14
|
-
console.log("InspectorModule available?:", !!NativeModules.InspectorModule);
|
|
15
|
-
console.log("GridRenderLayerManager available?:", !!NativeModules.GridRenderLayerManager);
|
|
16
|
-
console.log("-------------------------------------------------");
|
|
17
|
-
|
|
18
|
-
const { WeatherFrameProcessorModule, InspectorModule } = NativeModules;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* A helper function to generate the raw RGBA byte buffer for the colormap texture.
|
|
22
|
-
*/
|
|
23
|
-
const _generateColormapBytes = (colormap) => {
|
|
24
|
-
const width = 256;
|
|
25
|
-
const data = new Uint8Array(width * 4);
|
|
26
|
-
const stops = colormap.reduce((acc, _, i) => (i % 2 === 0 ? [...acc, { value: colormap[i], color: colormap[i + 1] }] : acc), []);
|
|
27
|
-
|
|
28
|
-
if (stops.length === 0) return data;
|
|
29
|
-
|
|
30
|
-
const minVal = stops[0].value;
|
|
31
|
-
const maxVal = stops[stops.length - 1].value;
|
|
32
|
-
|
|
33
|
-
const hexToRgb = (hex) => {
|
|
34
|
-
const r = parseInt(hex.slice(1, 3), 16);
|
|
35
|
-
const g = parseInt(hex.slice(3, 5), 16);
|
|
36
|
-
const b = parseInt(hex.slice(5, 7), 16);
|
|
37
|
-
return [r, g, b];
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
for (let i = 0; i < width; i++) {
|
|
41
|
-
const val = minVal + (i / (width - 1)) * (maxVal - minVal);
|
|
42
|
-
let lower = stops[0];
|
|
43
|
-
let upper = stops[stops.length - 1];
|
|
44
|
-
for (let j = 0; j < stops.length - 1; j++) {
|
|
45
|
-
if (val >= stops[j].value && val <= stops[j + 1].value) {
|
|
46
|
-
lower = stops[j];
|
|
47
|
-
upper = stops[j + 1];
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const t = (val - lower.value) / (upper.value - lower.value || 1);
|
|
52
|
-
const lowerRgb = hexToRgb(lower.color);
|
|
53
|
-
const upperRgb = hexToRgb(upper.color);
|
|
54
|
-
const rgb = lowerRgb.map((c, idx) => c * (1 - t) + upperRgb[idx] * t);
|
|
55
|
-
|
|
56
|
-
const offset = i * 4;
|
|
57
|
-
data[offset + 0] = Math.round(rgb[0]);
|
|
58
|
-
data[offset + 1] = Math.round(rgb[1]);
|
|
59
|
-
data[offset + 2] = Math.round(rgb[2]);
|
|
60
|
-
data[offset + 3] = 255;
|
|
61
|
-
}
|
|
62
|
-
return data;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
AguaceroCore.prototype.setMapCenter = function(center) {
|
|
66
|
-
this.emit('map:move', center);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
70
|
-
// EDIT: Destructure the new props
|
|
71
|
-
const { inspectorEnabled, onInspect, apiKey, customColormaps, initialMode, initialVariable, ...restProps } = props;
|
|
72
|
-
const context = useContext(AguaceroContext);
|
|
73
|
-
|
|
74
|
-
// Create the core here instead of getting it from context
|
|
75
|
-
const core = useMemo(() => new AguaceroCore({
|
|
76
|
-
apiKey: apiKey,
|
|
77
|
-
customColormaps: customColormaps,
|
|
78
|
-
// ADD: Pass layerOptions to the core's constructor
|
|
79
|
-
layerOptions: {
|
|
80
|
-
mode: initialMode,
|
|
81
|
-
variable: initialVariable
|
|
82
|
-
}
|
|
83
|
-
}), [apiKey]);
|
|
84
|
-
|
|
85
|
-
const gridLayerRef = useRef(null);
|
|
86
|
-
const currentGridDataRef = useRef(null);
|
|
87
|
-
|
|
88
|
-
// Cache for preloaded grid data - stores the processed data ready for GPU upload
|
|
89
|
-
const preloadedDataCache = useRef(new Map());
|
|
90
|
-
|
|
91
|
-
// Track what we're currently preloading to avoid duplicates
|
|
92
|
-
const preloadingSet = useRef(new Set());
|
|
93
|
-
|
|
94
|
-
// Store geometry and colormap that don't change with forecast hour
|
|
95
|
-
const cachedGeometry = useRef(null);
|
|
96
|
-
const cachedColormap = useRef(null);
|
|
97
|
-
const cachedDataRange = useRef([0, 1]);
|
|
98
|
-
|
|
99
|
-
// Track if we've done the initial load
|
|
100
|
-
const hasInitialLoad = useRef(false);
|
|
101
|
-
const hasPreloadedRef = useRef(false);
|
|
102
|
-
|
|
103
|
-
// Track the last state we processed to avoid redundant updates
|
|
104
|
-
const lastProcessedState = useRef(null);
|
|
105
|
-
const previousStateRef = useRef(null);
|
|
106
|
-
|
|
107
|
-
const [renderProps, setRenderProps] = useState({
|
|
108
|
-
opacity: 1,
|
|
109
|
-
dataRange: [0, 1]
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
useImperativeHandle(ref, () => {
|
|
113
|
-
return {
|
|
114
|
-
play: () => {
|
|
115
|
-
core.play();
|
|
116
|
-
},
|
|
117
|
-
pause: () => {
|
|
118
|
-
core.pause();
|
|
119
|
-
},
|
|
120
|
-
togglePlay: () => {
|
|
121
|
-
core.togglePlay();
|
|
122
|
-
},
|
|
123
|
-
step: (direction) => {
|
|
124
|
-
core.step(direction);
|
|
125
|
-
},
|
|
126
|
-
setPlaybackSpeed: (speed) => core.setPlaybackSpeed(speed),
|
|
127
|
-
setOpacity: (opacity) => core.setOpacity(opacity),
|
|
128
|
-
setUnits: (units) => core.setUnits(units),
|
|
129
|
-
switchMode: (options) => core.switchMode(options),
|
|
130
|
-
getAvailableVariables: (model) => core.getAvailableVariables(model),
|
|
131
|
-
getVariableDisplayName: (code) => core.getVariableDisplayName(code),
|
|
132
|
-
setRun: (runString) => core.setState({ run: runString.split(':')[1] }),
|
|
133
|
-
setState: (newState) => core.setState(newState),
|
|
134
|
-
setMRMSTimestamp: (timestamp) => core.setMRMSTimestamp(timestamp),
|
|
135
|
-
setSmoothing: (enabled) => {
|
|
136
|
-
if (gridLayerRef.current) {
|
|
137
|
-
gridLayerRef.current.setSmoothing(enabled);
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
}, [core]);
|
|
142
|
-
|
|
143
|
-
const preloadAllFramesToDisk = (state) => {
|
|
144
|
-
|
|
145
|
-
if (hasPreloadedRef.current) {
|
|
146
|
-
console.log('✅ [Preload] Gating preload; already initiated for this dataset.');
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
hasPreloadedRef.current = true;
|
|
150
|
-
console.log('🚀 [Preload] Initiating parallel preload for new dataset...');
|
|
151
|
-
|
|
152
|
-
const { isMRMS, model, date, run, variable, units, availableHours, availableTimestamps, forecastHour, mrmsTimestamp } = state;
|
|
153
|
-
|
|
154
|
-
// NEW: Fix the current forecast hour if it's invalid for this variable/model combo
|
|
155
|
-
let effectiveForecastHour = forecastHour;
|
|
156
|
-
if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && forecastHour === 0) {
|
|
157
|
-
const validHours = availableHours.filter(hour => hour !== 0);
|
|
158
|
-
effectiveForecastHour = validHours.length > 0 ? validHours[0] : 0;
|
|
159
|
-
console.log(`⚠️ [Preload] Correcting invalid hour 0 to ${effectiveForecastHour} for HRRR ptypeRefl`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (!cachedGeometry.current || !cachedColormap.current) {
|
|
163
|
-
const gridModel = isMRMS ? 'mrms' : model;
|
|
164
|
-
const { corners, gridDef } = core._getGridCornersAndDef(gridModel);
|
|
165
|
-
gridLayerRef.current.updateGeometry(corners, gridDef);
|
|
166
|
-
cachedGeometry.current = { model: gridModel, variable };
|
|
167
|
-
|
|
168
|
-
const { colormap, baseUnit } = core._getColormapForVariable(variable);
|
|
169
|
-
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
170
|
-
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
171
|
-
let dataRange;
|
|
172
|
-
if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
|
|
173
|
-
if (isMRMS) {
|
|
174
|
-
console.log('🔧 Using MRMS ptype data range: 5-380');
|
|
175
|
-
dataRange = [5, 380];
|
|
176
|
-
} else {
|
|
177
|
-
console.log('🔧 Using Model ptype data range: 5-380');
|
|
178
|
-
dataRange = [5, 380];
|
|
179
|
-
}
|
|
180
|
-
} else {
|
|
181
|
-
dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
182
|
-
}
|
|
183
|
-
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
184
|
-
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
185
|
-
|
|
186
|
-
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
187
|
-
cachedColormap.current = { key: `${variable}-${units}` };
|
|
188
|
-
cachedDataRange.current = dataRange;
|
|
189
|
-
|
|
190
|
-
setRenderProps({ opacity: state.opacity, dataRange: dataRange });
|
|
191
|
-
hasInitialLoad.current = true;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Apply the same filtering logic as in AguaceroCore._emitStateChange
|
|
195
|
-
let filteredHours = availableHours;
|
|
196
|
-
if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && availableHours && availableHours.length > 0) {
|
|
197
|
-
filteredHours = availableHours.filter(hour => hour !== 0);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const allFrames = isMRMS ? availableTimestamps : filteredHours;
|
|
201
|
-
if (!allFrames || allFrames.length === 0) {
|
|
202
|
-
console.warn('🟡 [preloadAllFramesToDisk] No frames available to download.');
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const currentFrame = isMRMS ? mrmsTimestamp : effectiveForecastHour;
|
|
207
|
-
|
|
208
|
-
// --- EDIT: Reverse the frame order to load from last to first ---
|
|
209
|
-
const reversedFrames = [...allFrames].reverse();
|
|
210
|
-
const framesToPreload = reversedFrames.filter(frame => frame !== currentFrame);
|
|
211
|
-
|
|
212
|
-
// The final array will process the current frame first, then the rest in reverse chronological order.
|
|
213
|
-
const prioritizedFrames = [
|
|
214
|
-
currentFrame,
|
|
215
|
-
...framesToPreload
|
|
216
|
-
];
|
|
217
|
-
// --- END EDIT ---
|
|
218
|
-
|
|
219
|
-
console.log(`[Preload] Prioritizing frame: ${currentFrame}. Total frames: ${prioritizedFrames.length}`);
|
|
220
|
-
|
|
221
|
-
const { corners, gridDef } = core._getGridCornersAndDef(isMRMS ? 'mrms' : model);
|
|
222
|
-
const { nx, ny } = gridDef.grid_params;
|
|
223
|
-
|
|
224
|
-
prioritizedFrames.forEach((frame, index) => {
|
|
225
|
-
const cacheKey = isMRMS ? `mrms-${frame}-${variable}` : `${model}-${date}-${run}-${frame}-${variable}`;
|
|
226
|
-
if (preloadedDataCache.current.has(cacheKey)) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
let resourcePath;
|
|
231
|
-
if (isMRMS) {
|
|
232
|
-
const frameDate = new Date(frame * 1000);
|
|
233
|
-
const y = frameDate.getUTCFullYear();
|
|
234
|
-
const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
|
|
235
|
-
const d = frameDate.getUTCDate().toString().padStart(2, '0');
|
|
236
|
-
resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${variable}/0`;
|
|
237
|
-
} else {
|
|
238
|
-
resourcePath = `/grids/${model}/${date}/${run}/${frame}/${variable}/0`;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
|
|
242
|
-
const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
|
|
243
|
-
|
|
244
|
-
WeatherFrameProcessorModule.processFrame(options)
|
|
245
|
-
.then(result => {
|
|
246
|
-
if (!result || !result.filePath) {
|
|
247
|
-
console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}: No filePath`);
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const { baseUnit } = core._getColormapForVariable(variable);
|
|
252
|
-
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
253
|
-
|
|
254
|
-
let dataScale = result.scale;
|
|
255
|
-
let dataOffset = result.offset;
|
|
256
|
-
|
|
257
|
-
let convertedScale = dataScale;
|
|
258
|
-
let convertedOffset = dataOffset;
|
|
259
|
-
|
|
260
|
-
if (baseUnit !== toUnit) {
|
|
261
|
-
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
262
|
-
if (conversionFunc) {
|
|
263
|
-
if (result.scaleType === 'sqrt') {
|
|
264
|
-
const physicalAtOffset = dataOffset * dataOffset;
|
|
265
|
-
const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
|
|
266
|
-
const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
|
|
267
|
-
const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
|
|
268
|
-
convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
|
|
269
|
-
const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
|
|
270
|
-
convertedScale = newOffsetPlusScale - convertedOffset;
|
|
271
|
-
} else {
|
|
272
|
-
convertedOffset = conversionFunc(dataOffset);
|
|
273
|
-
const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
|
|
274
|
-
convertedScale = convertedOffsetPlusScale - convertedOffset;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const frameData = {
|
|
280
|
-
filePath: result.filePath,
|
|
281
|
-
nx, ny,
|
|
282
|
-
scale: convertedScale,
|
|
283
|
-
offset: convertedOffset,
|
|
284
|
-
missing: result.missing,
|
|
285
|
-
corners,
|
|
286
|
-
gridDef,
|
|
287
|
-
scaleType: result.scaleType,
|
|
288
|
-
originalScale: result.scale,
|
|
289
|
-
originalOffset: result.offset
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
preloadedDataCache.current.set(cacheKey, frameData);
|
|
293
|
-
|
|
294
|
-
const isCurrentFrame = index === 0;
|
|
295
|
-
|
|
296
|
-
if (isCurrentFrame) {
|
|
297
|
-
console.log(`🎯 [Preload] Using FAST LANE to process and draw current frame (${frame}) immediately.`);
|
|
298
|
-
gridLayerRef.current.updateDataTextureFromFile(
|
|
299
|
-
frameData.filePath,
|
|
300
|
-
frameData.nx, frameData.ny,
|
|
301
|
-
frameData.scale, frameData.offset, frameData.missing,
|
|
302
|
-
frameData.scaleType
|
|
303
|
-
);
|
|
304
|
-
|
|
305
|
-
currentGridDataRef.current = {
|
|
306
|
-
nx: frameData.nx,
|
|
307
|
-
ny: frameData.ny,
|
|
308
|
-
scale: frameData.scale,
|
|
309
|
-
offset: frameData.offset,
|
|
310
|
-
missing: frameData.missing,
|
|
311
|
-
gridDef: frameData.gridDef,
|
|
312
|
-
variable: variable,
|
|
313
|
-
units: units
|
|
314
|
-
};
|
|
315
|
-
} else {
|
|
316
|
-
if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
|
|
317
|
-
const frameInfoForGpu = {
|
|
318
|
-
[cacheKey]: {
|
|
319
|
-
filePath: frameData.filePath,
|
|
320
|
-
nx: frameData.nx,
|
|
321
|
-
ny: frameData.ny,
|
|
322
|
-
scale: frameData.scale,
|
|
323
|
-
offset: frameData.offset,
|
|
324
|
-
missing: frameData.missing,
|
|
325
|
-
scaleType: frameData.scaleType || 'linear',
|
|
326
|
-
originalScale: frameData.originalScale,
|
|
327
|
-
originalOffset: frameData.originalOffset
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
gridLayerRef.current.primeGpuCache(frameInfoForGpu);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
})
|
|
334
|
-
.catch(error => {
|
|
335
|
-
console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}:`, error);
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
const updateGPUWithCachedData = (state) => {
|
|
341
|
-
const { model, date, run, forecastHour, variable, units, isMRMS, mrmsTimestamp } = state;
|
|
342
|
-
|
|
343
|
-
const cacheKey = isMRMS
|
|
344
|
-
? `mrms-${mrmsTimestamp}-${variable}`
|
|
345
|
-
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
346
|
-
|
|
347
|
-
if (Platform.OS === 'ios' && gridLayerRef.current.setActiveFrame) {
|
|
348
|
-
// Get the cached data BEFORE calling setActiveFrame
|
|
349
|
-
const cachedData = preloadedDataCache.current.get(cacheKey);
|
|
350
|
-
|
|
351
|
-
if (cachedData) {
|
|
352
|
-
currentGridDataRef.current = {
|
|
353
|
-
nx: cachedData.nx,
|
|
354
|
-
ny: cachedData.ny,
|
|
355
|
-
scale: cachedData.scale,
|
|
356
|
-
offset: cachedData.offset,
|
|
357
|
-
missing: cachedData.missing,
|
|
358
|
-
gridDef: cachedData.gridDef,
|
|
359
|
-
variable: variable,
|
|
360
|
-
units: units,
|
|
361
|
-
scaleType: cachedData.scaleType
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
console.log('📱 [iOS] Updated currentGridDataRef for inspector:', {
|
|
365
|
-
scale: cachedData.scale,
|
|
366
|
-
offset: cachedData.offset,
|
|
367
|
-
scaleType: cachedData.scaleType // ADD THIS
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Now call setActiveFrame (which will async update the native cache)
|
|
372
|
-
gridLayerRef.current.setActiveFrame(cacheKey);
|
|
373
|
-
return true;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const cachedData = preloadedDataCache.current.get(cacheKey);
|
|
377
|
-
|
|
378
|
-
if (!cachedData) {
|
|
379
|
-
const timeKey = isMRMS ? `timestamp ${mrmsTimestamp}` : `hour +${forecastHour}`;
|
|
380
|
-
console.log(`⏳ [updateGPUWithCachedData] Frame not ready yet for ${timeKey}. Still preloading...`); // CHANGED
|
|
381
|
-
return false;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (!gridLayerRef.current) {
|
|
385
|
-
console.warn(`⚠️ [updateGPUWithCachedData] GridLayer ref not available`); // CHANGED
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (!cachedGeometry.current || cachedGeometry.current.model !== (isMRMS ? 'mrms' : model) || cachedGeometry.current.variable !== variable) {
|
|
390
|
-
gridLayerRef.current.updateGeometry(cachedData.corners, cachedData.gridDef);
|
|
391
|
-
cachedGeometry.current = { model: (isMRMS ? 'mrms' : model), variable };
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const colormapKey = `${variable}-${units}`;
|
|
395
|
-
if (!cachedColormap.current || cachedColormap.current.key !== colormapKey) {
|
|
396
|
-
const { colormap, baseUnit } = core._getColormapForVariable(variable);
|
|
397
|
-
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
398
|
-
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
399
|
-
let dataRange;
|
|
400
|
-
if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
|
|
401
|
-
if (isMRMS) {
|
|
402
|
-
dataRange = [5, 380];
|
|
403
|
-
} else {
|
|
404
|
-
dataRange = [5, 380];
|
|
405
|
-
}
|
|
406
|
-
} else {
|
|
407
|
-
dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
408
|
-
}
|
|
409
|
-
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
410
|
-
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
411
|
-
|
|
412
|
-
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
413
|
-
cachedColormap.current = { key: colormapKey };
|
|
414
|
-
cachedDataRange.current = dataRange;
|
|
415
|
-
|
|
416
|
-
setRenderProps(prev => ({ ...prev, dataRange }));
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
if (cachedData.filePath) {
|
|
420
|
-
gridLayerRef.current.updateDataTextureFromFile(
|
|
421
|
-
cachedData.filePath,
|
|
422
|
-
cachedData.nx, cachedData.ny,
|
|
423
|
-
cachedData.scale, cachedData.offset, cachedData.missing,
|
|
424
|
-
cachedData.scaleType
|
|
425
|
-
);
|
|
426
|
-
|
|
427
|
-
// ADD THIS: Update inspector cache for file-based data too
|
|
428
|
-
currentGridDataRef.current = {
|
|
429
|
-
nx: cachedData.nx,
|
|
430
|
-
ny: cachedData.ny,
|
|
431
|
-
scale: cachedData.scale,
|
|
432
|
-
offset: cachedData.offset,
|
|
433
|
-
missing: cachedData.missing,
|
|
434
|
-
gridDef: cachedData.gridDef,
|
|
435
|
-
variable: variable,
|
|
436
|
-
units: units
|
|
437
|
-
};
|
|
438
|
-
} else if (cachedData.dataAsBase64) {
|
|
439
|
-
gridLayerRef.current.updateDataTexture(
|
|
440
|
-
cachedData.dataAsBase64,
|
|
441
|
-
cachedData.nx, cachedData.ny,
|
|
442
|
-
cachedData.scale, cachedData.offset, cachedData.missing,
|
|
443
|
-
cachedData.scaleType
|
|
444
|
-
);
|
|
445
|
-
|
|
446
|
-
// Update the inspector cache when using dataAsBase64
|
|
447
|
-
const binaryString = atob(cachedData.dataAsBase64);
|
|
448
|
-
const uint8Array = new Uint8Array(binaryString.length);
|
|
449
|
-
|
|
450
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
451
|
-
uint8Array[i] = binaryString.charCodeAt(i);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
currentGridDataRef.current = {
|
|
455
|
-
data: uint8Array,
|
|
456
|
-
nx: cachedData.nx,
|
|
457
|
-
ny: cachedData.ny,
|
|
458
|
-
scale: cachedData.scale,
|
|
459
|
-
offset: cachedData.offset,
|
|
460
|
-
missing: cachedData.missing,
|
|
461
|
-
gridDef: cachedData.gridDef,
|
|
462
|
-
variable: variable,
|
|
463
|
-
units: units
|
|
464
|
-
};
|
|
465
|
-
} else {
|
|
466
|
-
console.error(`❌ [updateGPUWithCachedData] Cached data has no filePath or dataAsBase64!`);
|
|
467
|
-
console.error('❌ [updateGPUWithCachedData] Cached data keys:', Object.keys(cachedData));
|
|
468
|
-
return false;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Update inspector parameters for file-based data too
|
|
472
|
-
if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
|
|
473
|
-
gridLayerRef.current.updateDataParameters(cachedData.scale, cachedData.offset, cachedData.missing);
|
|
474
|
-
}
|
|
475
|
-
return true;
|
|
476
|
-
};
|
|
477
|
-
|
|
478
|
-
const handleStateChangeRef = useRef(null);
|
|
479
|
-
const debounceTimeoutRef = useRef(null);
|
|
480
|
-
|
|
481
|
-
useEffect(() => {
|
|
482
|
-
if (core && props.customColormaps) {
|
|
483
|
-
core.customColormaps = props.customColormaps;
|
|
484
|
-
// Trigger a re-render if we already have data loaded
|
|
485
|
-
if (hasInitialLoad.current) {
|
|
486
|
-
core._emitStateChange();
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}, [core, props.customColormaps]);
|
|
490
|
-
|
|
491
|
-
const getValueAtPoint = async (lng, lat) => {
|
|
492
|
-
if (!core) {
|
|
493
|
-
console.warn('🔍 [Inspector] Core not available');
|
|
494
|
-
return null;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// ADD THIS: Check if we have valid data before attempting inspection
|
|
498
|
-
if (!currentGridDataRef.current) {
|
|
499
|
-
console.log('🔍 [Inspector] No grid data available');
|
|
500
|
-
return null;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
try {
|
|
504
|
-
const gridIndices = core._getGridIndexFromLngLat(lng, lat);
|
|
505
|
-
if (!gridIndices) return null;
|
|
506
|
-
|
|
507
|
-
const { i, j } = gridIndices;
|
|
508
|
-
|
|
509
|
-
const value = await InspectorModule.getValueAtGridIndex(i, j);
|
|
510
|
-
|
|
511
|
-
if (value === null) {
|
|
512
|
-
return null;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
const { colormap, baseUnit } = core._getColormapForVariable(core.state.variable);
|
|
516
|
-
const displayUnit = core._getTargetUnit(baseUnit, core.state.units);
|
|
517
|
-
const finalColormap = core._convertColormapUnits(colormap, baseUnit, displayUnit);
|
|
518
|
-
const minThreshold = finalColormap[0];
|
|
519
|
-
|
|
520
|
-
if (value < minThreshold) {
|
|
521
|
-
console.log('🔍 [Inspector] Rejected: below threshold'); // ADD THIS LOG
|
|
522
|
-
return null;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
// Filter out values below the minimum threshold (matching shader behavior)
|
|
526
|
-
if (value < minThreshold) {
|
|
527
|
-
return null;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// Also check if value is NaN or effectively missing
|
|
531
|
-
if (!isFinite(value)) {
|
|
532
|
-
return null;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return {
|
|
536
|
-
value: value,
|
|
537
|
-
unit: displayUnit,
|
|
538
|
-
variable: {
|
|
539
|
-
code: core.state.variable,
|
|
540
|
-
name: core.getVariableDisplayName(core.state.variable)
|
|
541
|
-
},
|
|
542
|
-
lngLat: { lng, lat }
|
|
543
|
-
};
|
|
544
|
-
} catch (error) {
|
|
545
|
-
console.error('🔍 [Inspector] Error:', error);
|
|
546
|
-
return null;
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
useEffect(() => {
|
|
551
|
-
if (!core) {
|
|
552
|
-
console.warn('⚠️ [useEffect] Core is not available yet');
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
const handleStateChange = async (newState) => {
|
|
557
|
-
if (!previousStateRef.current) {
|
|
558
|
-
previousStateRef.current = core.state;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
const variableChanged = !previousStateRef.current || newState.variable !== previousStateRef.current.variable;
|
|
562
|
-
|
|
563
|
-
if (variableChanged && gridLayerRef.current?.setVariable) {
|
|
564
|
-
gridLayerRef.current.setVariable(newState.variable);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
const stateKey = `${newState.model}-${newState.variable}-${newState.date}-${newState.run}-${newState.forecastHour}-${newState.units}-${newState.mrmsTimestamp}`;
|
|
568
|
-
|
|
569
|
-
const isOpacityOnlyChange =
|
|
570
|
-
hasInitialLoad.current &&
|
|
571
|
-
newState.opacity !== renderProps.opacity &&
|
|
572
|
-
newState.variable === previousStateRef.current?.variable &&
|
|
573
|
-
newState.forecastHour === previousStateRef.current?.forecastHour &&
|
|
574
|
-
newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
|
|
575
|
-
newState.model === previousStateRef.current?.model &&
|
|
576
|
-
newState.units === previousStateRef.current?.units;
|
|
577
|
-
|
|
578
|
-
// ADD: Check for play state only change
|
|
579
|
-
const isPlayStateOnlyChange =
|
|
580
|
-
hasInitialLoad.current &&
|
|
581
|
-
newState.isPlaying !== previousStateRef.current?.isPlaying &&
|
|
582
|
-
newState.variable === previousStateRef.current?.variable &&
|
|
583
|
-
newState.forecastHour === previousStateRef.current?.forecastHour &&
|
|
584
|
-
newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
|
|
585
|
-
newState.model === previousStateRef.current?.model &&
|
|
586
|
-
newState.units === previousStateRef.current?.units &&
|
|
587
|
-
newState.opacity === previousStateRef.current?.opacity;
|
|
588
|
-
|
|
589
|
-
if (!isOpacityOnlyChange && !isPlayStateOnlyChange && lastProcessedState.current === stateKey) {
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
if (!isOpacityOnlyChange && !isPlayStateOnlyChange) {
|
|
594
|
-
lastProcessedState.current = stateKey;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// MOVE THIS TO THE TOP - Always notify the parent component of state changes
|
|
598
|
-
props.onStateChange?.(newState);
|
|
599
|
-
|
|
600
|
-
if (isOpacityOnlyChange) {
|
|
601
|
-
setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
|
|
602
|
-
previousStateRef.current = newState;
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// ADD: Handle play state only change
|
|
607
|
-
if (isPlayStateOnlyChange) {
|
|
608
|
-
previousStateRef.current = newState;
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
// Check if only units changed
|
|
613
|
-
const isUnitsOnlyChange =
|
|
614
|
-
hasInitialLoad.current &&
|
|
615
|
-
newState.model === previousStateRef.current.model &&
|
|
616
|
-
newState.isMRMS === previousStateRef.current.isMRMS &&
|
|
617
|
-
newState.variable === previousStateRef.current.variable &&
|
|
618
|
-
newState.date === previousStateRef.current.date &&
|
|
619
|
-
newState.run === previousStateRef.current.run &&
|
|
620
|
-
newState.forecastHour === previousStateRef.current.forecastHour &&
|
|
621
|
-
newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
|
|
622
|
-
newState.units !== previousStateRef.current.units;
|
|
623
|
-
|
|
624
|
-
if (isUnitsOnlyChange) {
|
|
625
|
-
const { variable, units, isMRMS, mrmsTimestamp, model, date, run, forecastHour } = newState;
|
|
626
|
-
const oldCacheKey = isMRMS
|
|
627
|
-
? `mrms-${mrmsTimestamp}-${variable}`
|
|
628
|
-
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
629
|
-
|
|
630
|
-
const cachedData = preloadedDataCache.current.get(oldCacheKey);
|
|
631
|
-
|
|
632
|
-
if (cachedData && cachedData.originalScale !== undefined && cachedData.originalOffset !== undefined) {
|
|
633
|
-
const { baseUnit } = core._getColormapForVariable(variable);
|
|
634
|
-
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
635
|
-
|
|
636
|
-
let dataScale = cachedData.originalScale;
|
|
637
|
-
let dataOffset = cachedData.originalOffset;
|
|
638
|
-
|
|
639
|
-
if (baseUnit !== toUnit) {
|
|
640
|
-
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
641
|
-
console.log('🔧 [Unit Conversion] Conversion function exists:', !!conversionFunc);
|
|
642
|
-
|
|
643
|
-
if (conversionFunc) {
|
|
644
|
-
if (cachedData.scaleType === 'sqrt') {
|
|
645
|
-
// Calculate what the physical values would be at offset and offset+scale
|
|
646
|
-
const physicalAtOffset = dataOffset * dataOffset;
|
|
647
|
-
const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
|
|
648
|
-
|
|
649
|
-
// Convert these physical values to the new unit
|
|
650
|
-
const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
|
|
651
|
-
const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
|
|
652
|
-
|
|
653
|
-
// Take sqrt to get back to intermediate values
|
|
654
|
-
const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
|
|
655
|
-
const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
|
|
656
|
-
|
|
657
|
-
dataScale = newOffsetPlusScale - newOffset;
|
|
658
|
-
dataOffset = newOffset;
|
|
659
|
-
} else {
|
|
660
|
-
const convertedOffset = conversionFunc(dataOffset);
|
|
661
|
-
const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
|
|
662
|
-
|
|
663
|
-
dataScale = convertedOffsetPlusScale - convertedOffset;
|
|
664
|
-
dataOffset = convertedOffset;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// Update the colormap AND data range
|
|
670
|
-
const { colormap } = core._getColormapForVariable(variable);
|
|
671
|
-
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
672
|
-
let dataRange;
|
|
673
|
-
if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
|
|
674
|
-
if (isMRMS) {
|
|
675
|
-
dataRange = [5, 380];
|
|
676
|
-
} else {
|
|
677
|
-
dataRange = [5, 380];
|
|
678
|
-
}
|
|
679
|
-
} else {
|
|
680
|
-
dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
684
|
-
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
685
|
-
|
|
686
|
-
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
687
|
-
cachedColormap.current = { key: `${variable}-${units}` };
|
|
688
|
-
cachedDataRange.current = dataRange;
|
|
689
|
-
|
|
690
|
-
setRenderProps(prev => ({ ...prev, dataRange, opacity: newState.opacity }));
|
|
691
|
-
|
|
692
|
-
if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
|
|
693
|
-
const scaleTypeValue = cachedData.scaleType === 'sqrt' ? 1 : 0; // Convert to number
|
|
694
|
-
|
|
695
|
-
console.log('🔄 [Unit Conversion] Calling updateDataParameters with:', {
|
|
696
|
-
scale: dataScale,
|
|
697
|
-
offset: dataOffset,
|
|
698
|
-
missing: cachedData.missing,
|
|
699
|
-
scaleType: scaleTypeValue
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
gridLayerRef.current.updateDataParameters(dataScale, dataOffset, cachedData.missing, scaleTypeValue); // Pass scaleType
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
const newCacheKey = isMRMS
|
|
706
|
-
? `mrms-${mrmsTimestamp}-${variable}`
|
|
707
|
-
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
708
|
-
|
|
709
|
-
preloadedDataCache.current.set(newCacheKey, {
|
|
710
|
-
...cachedData,
|
|
711
|
-
scale: dataScale,
|
|
712
|
-
offset: dataOffset
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
} else {
|
|
716
|
-
console.warn('⚠️ [Unit Conversion] No cached data found for key:', oldCacheKey);
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
previousStateRef.current = newState;
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
const needsFullLoad =
|
|
724
|
-
!hasInitialLoad.current ||
|
|
725
|
-
newState.model !== previousStateRef.current.model ||
|
|
726
|
-
newState.isMRMS !== previousStateRef.current.isMRMS ||
|
|
727
|
-
newState.variable !== previousStateRef.current.variable ||
|
|
728
|
-
newState.date !== previousStateRef.current.date ||
|
|
729
|
-
newState.run !== previousStateRef.current.run;
|
|
730
|
-
|
|
731
|
-
if (needsFullLoad) {
|
|
732
|
-
|
|
733
|
-
if (gridLayerRef.current) {
|
|
734
|
-
gridLayerRef.current.setVariable(newState.variable);
|
|
735
|
-
gridLayerRef.current.clear();
|
|
736
|
-
// --- OPTIMIZATION: Clear the native GPU cache on iOS ---
|
|
737
|
-
if (Platform.OS === 'ios' && gridLayerRef.current.clearGpuCache) {
|
|
738
|
-
gridLayerRef.current.clearGpuCache();
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
hasPreloadedRef.current = false;
|
|
742
|
-
|
|
743
|
-
preloadedDataCache.current.clear();
|
|
744
|
-
cachedGeometry.current = null;
|
|
745
|
-
cachedColormap.current = null;
|
|
746
|
-
|
|
747
|
-
// ADD THIS: Clear the inspector cache too
|
|
748
|
-
currentGridDataRef.current = null;
|
|
749
|
-
|
|
750
|
-
WeatherFrameProcessorModule.cancelAllFrames();
|
|
751
|
-
|
|
752
|
-
if (!newState.variable) {
|
|
753
|
-
previousStateRef.current = newState;
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
preloadAllFramesToDisk(newState);
|
|
758
|
-
} else if (newState.forecastHour !== previousStateRef.current.forecastHour || (newState.isMRMS && newState.mrmsTimestamp !== previousStateRef.current.mrmsTimestamp)) {
|
|
759
|
-
const success = updateGPUWithCachedData(newState);
|
|
760
|
-
|
|
761
|
-
if (!success) {
|
|
762
|
-
// CHANGED: Don't error, just log and wait for preload
|
|
763
|
-
const timeKey = newState.isMRMS ? `timestamp ${newState.mrmsTimestamp}` : `hour +${newState.forecastHour}`;
|
|
764
|
-
console.log(`⏳ [handleStateChange] Frame ${timeKey} not ready yet, waiting for preload...`);
|
|
765
|
-
// Don't clear the layer - keep showing the previous frame until new one is ready
|
|
766
|
-
// The preload will eventually complete and trigger a re-render
|
|
767
|
-
} else {
|
|
768
|
-
// Only update inspector cache when we successfully loaded new data
|
|
769
|
-
if (newState.opacity !== renderProps.opacity) {
|
|
770
|
-
setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
previousStateRef.current = newState;
|
|
776
|
-
};
|
|
777
|
-
|
|
778
|
-
handleStateChangeRef.current = handleStateChange;
|
|
779
|
-
|
|
780
|
-
const stableHandler = (newState) => {
|
|
781
|
-
const isOpacityOnlyChange =
|
|
782
|
-
previousStateRef.current &&
|
|
783
|
-
newState.opacity !== previousStateRef.current.opacity &&
|
|
784
|
-
newState.variable === previousStateRef.current.variable &&
|
|
785
|
-
newState.forecastHour === previousStateRef.current.forecastHour &&
|
|
786
|
-
newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
|
|
787
|
-
newState.model === previousStateRef.current.model &&
|
|
788
|
-
newState.units === previousStateRef.current.units &&
|
|
789
|
-
newState.date === previousStateRef.current.date &&
|
|
790
|
-
newState.run === previousStateRef.current.run;
|
|
791
|
-
|
|
792
|
-
if (isOpacityOnlyChange) {
|
|
793
|
-
if (handleStateChangeRef.current) {
|
|
794
|
-
handleStateChangeRef.current(newState);
|
|
795
|
-
}
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
if (debounceTimeoutRef.current) {
|
|
800
|
-
clearTimeout(debounceTimeoutRef.current);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
debounceTimeoutRef.current = setTimeout(() => {
|
|
804
|
-
if (handleStateChangeRef.current) {
|
|
805
|
-
handleStateChangeRef.current(newState);
|
|
806
|
-
}
|
|
807
|
-
debounceTimeoutRef.current = null;
|
|
808
|
-
}, 50);
|
|
809
|
-
};
|
|
810
|
-
|
|
811
|
-
core.on('state:change', stableHandler);
|
|
812
|
-
|
|
813
|
-
return () => {
|
|
814
|
-
core.off('state:change', stableHandler);
|
|
815
|
-
if (debounceTimeoutRef.current) {
|
|
816
|
-
clearTimeout(debounceTimeoutRef.current);
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
|
-
}, [core]);
|
|
820
|
-
|
|
821
|
-
useEffect(() => {
|
|
822
|
-
return () => {
|
|
823
|
-
preloadedDataCache.current.clear();
|
|
824
|
-
hasInitialLoad.current = false;
|
|
825
|
-
lastProcessedState.current = null;
|
|
826
|
-
};
|
|
827
|
-
}, []);
|
|
828
|
-
|
|
829
|
-
const lastInspectorUpdateRef = useRef(0);
|
|
830
|
-
const INSPECTOR_THROTTLE_MS = 50;
|
|
831
|
-
|
|
832
|
-
useEffect(() => {
|
|
833
|
-
if (!core || !inspectorEnabled) {
|
|
834
|
-
return;
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
const handleMapMove = async (center) => {
|
|
838
|
-
if (!center || !Array.isArray(center) || center.length !== 2) {
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
// Throttle updates
|
|
843
|
-
const now = Date.now();
|
|
844
|
-
if (now - lastInspectorUpdateRef.current < INSPECTOR_THROTTLE_MS) {
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
lastInspectorUpdateRef.current = now;
|
|
848
|
-
|
|
849
|
-
const [longitude, latitude] = center;
|
|
850
|
-
|
|
851
|
-
const payload = await getValueAtPoint(longitude, latitude);
|
|
852
|
-
onInspect?.(payload);
|
|
853
|
-
};
|
|
854
|
-
|
|
855
|
-
core.on('map:move', handleMapMove);
|
|
856
|
-
|
|
857
|
-
if (context && context.getCenter) {
|
|
858
|
-
const center = context.getCenter();
|
|
859
|
-
if (center) {
|
|
860
|
-
handleMapMove(center);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
return () => {
|
|
865
|
-
core.off('map:move', handleMapMove);
|
|
866
|
-
};
|
|
867
|
-
}, [inspectorEnabled, onInspect, core, context]);
|
|
868
|
-
|
|
869
|
-
// Add this new useEffect after the existing inspector useEffect
|
|
870
|
-
useEffect(() => {
|
|
871
|
-
// Trigger re-inspection when state changes (variable, model, forecast hour, etc.)
|
|
872
|
-
if (!core || !inspectorEnabled) {
|
|
873
|
-
return;
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
const triggerReinspection = () => {
|
|
877
|
-
const mapRef = mapRegistry.getMap();
|
|
878
|
-
const center = mapRef?._currentCenter;
|
|
879
|
-
|
|
880
|
-
if (center && Array.isArray(center) && center.length === 2) {
|
|
881
|
-
const [longitude, latitude] = center;
|
|
882
|
-
|
|
883
|
-
getValueAtPoint(longitude, latitude).then(payload => {
|
|
884
|
-
onInspect?.(payload);
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
};
|
|
888
|
-
|
|
889
|
-
// Small delay to ensure data is loaded before re-inspecting
|
|
890
|
-
const timer = setTimeout(triggerReinspection, 100);
|
|
891
|
-
|
|
892
|
-
return () => clearTimeout(timer);
|
|
893
|
-
}, [
|
|
894
|
-
core?.state?.variable,
|
|
895
|
-
core?.state?.model,
|
|
896
|
-
core?.state?.forecastHour,
|
|
897
|
-
core?.state?.mrmsTimestamp,
|
|
898
|
-
core?.state?.units,
|
|
899
|
-
inspectorEnabled,
|
|
900
|
-
onInspect
|
|
901
|
-
]);
|
|
902
|
-
|
|
903
|
-
useEffect(() => {
|
|
904
|
-
if (!core) {
|
|
905
|
-
return;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
const handleCameraChange = (center) => {
|
|
909
|
-
if (core && center) {
|
|
910
|
-
core.setMapCenter(center);
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
|
|
914
|
-
// Register with the global registry
|
|
915
|
-
mapRegistry.addCameraListener(handleCameraChange);
|
|
916
|
-
|
|
917
|
-
// Try to get initial center
|
|
918
|
-
const mapRef = mapRegistry.getMap();
|
|
919
|
-
if (mapRef?._currentCenter) {
|
|
920
|
-
handleCameraChange(mapRef._currentCenter);
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
return () => {
|
|
924
|
-
mapRegistry.removeCameraListener(handleCameraChange);
|
|
925
|
-
};
|
|
926
|
-
}, [core]);
|
|
927
|
-
|
|
928
|
-
useEffect(() => {
|
|
929
|
-
core.initialize();
|
|
930
|
-
return () => {
|
|
931
|
-
core.destroy();
|
|
932
|
-
};
|
|
933
|
-
}, [core]);
|
|
934
|
-
|
|
935
|
-
return (
|
|
936
|
-
<GridRenderLayer
|
|
937
|
-
ref={gridLayerRef}
|
|
938
|
-
opacity={renderProps.opacity}
|
|
939
|
-
dataRange={renderProps.dataRange}
|
|
940
|
-
belowID="AML_-_terrain"
|
|
941
|
-
/>
|
|
942
|
-
);
|
|
943
|
-
});
|
|
944
|
-
|
|
945
|
-
WeatherLayerManager.getAvailableVariables = (options) => {
|
|
946
|
-
if (!options || !options.apiKey) {
|
|
947
|
-
console.error("API key must be provided to get available variables.");
|
|
948
|
-
return [];
|
|
949
|
-
}
|
|
950
|
-
const core = new AguaceroCore({ apiKey: options.apiKey });
|
|
951
|
-
return core.getAvailableVariables('mrms');
|
|
1
|
+
// packages/react-native/src/WeatherLayerManager.js
|
|
2
|
+
|
|
3
|
+
import React, { useState, useRef, useContext, useEffect, forwardRef, useImperativeHandle, useMemo } from 'react';
|
|
4
|
+
import { AguaceroCore, getUnitConversionFunction } from '@aguacerowx/javascript-sdk';
|
|
5
|
+
import { AguaceroContext } from './AguaceroContext';
|
|
6
|
+
import { GridRenderLayer } from './GridRenderLayer';
|
|
7
|
+
import { fromByteArray } from 'base64-js';
|
|
8
|
+
import { Platform, NativeModules } from 'react-native';
|
|
9
|
+
import { mapRegistry } from './MapRegistry';
|
|
10
|
+
|
|
11
|
+
console.log("--- Aguacero Native Module Initial State Check ---");
|
|
12
|
+
console.log("All NativeModules:", Object.keys(NativeModules));
|
|
13
|
+
console.log("WeatherFrameProcessorModule available?:", !!NativeModules.WeatherFrameProcessorModule);
|
|
14
|
+
console.log("InspectorModule available?:", !!NativeModules.InspectorModule);
|
|
15
|
+
console.log("GridRenderLayerManager available?:", !!NativeModules.GridRenderLayerManager);
|
|
16
|
+
console.log("-------------------------------------------------");
|
|
17
|
+
|
|
18
|
+
const { WeatherFrameProcessorModule, InspectorModule } = NativeModules;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A helper function to generate the raw RGBA byte buffer for the colormap texture.
|
|
22
|
+
*/
|
|
23
|
+
const _generateColormapBytes = (colormap) => {
|
|
24
|
+
const width = 256;
|
|
25
|
+
const data = new Uint8Array(width * 4);
|
|
26
|
+
const stops = colormap.reduce((acc, _, i) => (i % 2 === 0 ? [...acc, { value: colormap[i], color: colormap[i + 1] }] : acc), []);
|
|
27
|
+
|
|
28
|
+
if (stops.length === 0) return data;
|
|
29
|
+
|
|
30
|
+
const minVal = stops[0].value;
|
|
31
|
+
const maxVal = stops[stops.length - 1].value;
|
|
32
|
+
|
|
33
|
+
const hexToRgb = (hex) => {
|
|
34
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
35
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
36
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
37
|
+
return [r, g, b];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
for (let i = 0; i < width; i++) {
|
|
41
|
+
const val = minVal + (i / (width - 1)) * (maxVal - minVal);
|
|
42
|
+
let lower = stops[0];
|
|
43
|
+
let upper = stops[stops.length - 1];
|
|
44
|
+
for (let j = 0; j < stops.length - 1; j++) {
|
|
45
|
+
if (val >= stops[j].value && val <= stops[j + 1].value) {
|
|
46
|
+
lower = stops[j];
|
|
47
|
+
upper = stops[j + 1];
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const t = (val - lower.value) / (upper.value - lower.value || 1);
|
|
52
|
+
const lowerRgb = hexToRgb(lower.color);
|
|
53
|
+
const upperRgb = hexToRgb(upper.color);
|
|
54
|
+
const rgb = lowerRgb.map((c, idx) => c * (1 - t) + upperRgb[idx] * t);
|
|
55
|
+
|
|
56
|
+
const offset = i * 4;
|
|
57
|
+
data[offset + 0] = Math.round(rgb[0]);
|
|
58
|
+
data[offset + 1] = Math.round(rgb[1]);
|
|
59
|
+
data[offset + 2] = Math.round(rgb[2]);
|
|
60
|
+
data[offset + 3] = 255;
|
|
61
|
+
}
|
|
62
|
+
return data;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
AguaceroCore.prototype.setMapCenter = function(center) {
|
|
66
|
+
this.emit('map:move', center);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
70
|
+
// EDIT: Destructure the new props
|
|
71
|
+
const { inspectorEnabled, onInspect, apiKey, customColormaps, initialMode, initialVariable, ...restProps } = props;
|
|
72
|
+
const context = useContext(AguaceroContext);
|
|
73
|
+
|
|
74
|
+
// Create the core here instead of getting it from context
|
|
75
|
+
const core = useMemo(() => new AguaceroCore({
|
|
76
|
+
apiKey: apiKey,
|
|
77
|
+
customColormaps: customColormaps,
|
|
78
|
+
// ADD: Pass layerOptions to the core's constructor
|
|
79
|
+
layerOptions: {
|
|
80
|
+
mode: initialMode,
|
|
81
|
+
variable: initialVariable
|
|
82
|
+
}
|
|
83
|
+
}), [apiKey]);
|
|
84
|
+
|
|
85
|
+
const gridLayerRef = useRef(null);
|
|
86
|
+
const currentGridDataRef = useRef(null);
|
|
87
|
+
|
|
88
|
+
// Cache for preloaded grid data - stores the processed data ready for GPU upload
|
|
89
|
+
const preloadedDataCache = useRef(new Map());
|
|
90
|
+
|
|
91
|
+
// Track what we're currently preloading to avoid duplicates
|
|
92
|
+
const preloadingSet = useRef(new Set());
|
|
93
|
+
|
|
94
|
+
// Store geometry and colormap that don't change with forecast hour
|
|
95
|
+
const cachedGeometry = useRef(null);
|
|
96
|
+
const cachedColormap = useRef(null);
|
|
97
|
+
const cachedDataRange = useRef([0, 1]);
|
|
98
|
+
|
|
99
|
+
// Track if we've done the initial load
|
|
100
|
+
const hasInitialLoad = useRef(false);
|
|
101
|
+
const hasPreloadedRef = useRef(false);
|
|
102
|
+
|
|
103
|
+
// Track the last state we processed to avoid redundant updates
|
|
104
|
+
const lastProcessedState = useRef(null);
|
|
105
|
+
const previousStateRef = useRef(null);
|
|
106
|
+
|
|
107
|
+
const [renderProps, setRenderProps] = useState({
|
|
108
|
+
opacity: 1,
|
|
109
|
+
dataRange: [0, 1]
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
useImperativeHandle(ref, () => {
|
|
113
|
+
return {
|
|
114
|
+
play: () => {
|
|
115
|
+
core.play();
|
|
116
|
+
},
|
|
117
|
+
pause: () => {
|
|
118
|
+
core.pause();
|
|
119
|
+
},
|
|
120
|
+
togglePlay: () => {
|
|
121
|
+
core.togglePlay();
|
|
122
|
+
},
|
|
123
|
+
step: (direction) => {
|
|
124
|
+
core.step(direction);
|
|
125
|
+
},
|
|
126
|
+
setPlaybackSpeed: (speed) => core.setPlaybackSpeed(speed),
|
|
127
|
+
setOpacity: (opacity) => core.setOpacity(opacity),
|
|
128
|
+
setUnits: (units) => core.setUnits(units),
|
|
129
|
+
switchMode: (options) => core.switchMode(options),
|
|
130
|
+
getAvailableVariables: (model) => core.getAvailableVariables(model),
|
|
131
|
+
getVariableDisplayName: (code) => core.getVariableDisplayName(code),
|
|
132
|
+
setRun: (runString) => core.setState({ run: runString.split(':')[1] }),
|
|
133
|
+
setState: (newState) => core.setState(newState),
|
|
134
|
+
setMRMSTimestamp: (timestamp) => core.setMRMSTimestamp(timestamp),
|
|
135
|
+
setSmoothing: (enabled) => {
|
|
136
|
+
if (gridLayerRef.current) {
|
|
137
|
+
gridLayerRef.current.setSmoothing(enabled);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}, [core]);
|
|
142
|
+
|
|
143
|
+
const preloadAllFramesToDisk = (state) => {
|
|
144
|
+
|
|
145
|
+
if (hasPreloadedRef.current) {
|
|
146
|
+
console.log('✅ [Preload] Gating preload; already initiated for this dataset.');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
hasPreloadedRef.current = true;
|
|
150
|
+
console.log('🚀 [Preload] Initiating parallel preload for new dataset...');
|
|
151
|
+
|
|
152
|
+
const { isMRMS, model, date, run, variable, units, availableHours, availableTimestamps, forecastHour, mrmsTimestamp } = state;
|
|
153
|
+
|
|
154
|
+
// NEW: Fix the current forecast hour if it's invalid for this variable/model combo
|
|
155
|
+
let effectiveForecastHour = forecastHour;
|
|
156
|
+
if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && forecastHour === 0) {
|
|
157
|
+
const validHours = availableHours.filter(hour => hour !== 0);
|
|
158
|
+
effectiveForecastHour = validHours.length > 0 ? validHours[0] : 0;
|
|
159
|
+
console.log(`⚠️ [Preload] Correcting invalid hour 0 to ${effectiveForecastHour} for HRRR ptypeRefl`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!cachedGeometry.current || !cachedColormap.current) {
|
|
163
|
+
const gridModel = isMRMS ? 'mrms' : model;
|
|
164
|
+
const { corners, gridDef } = core._getGridCornersAndDef(gridModel);
|
|
165
|
+
gridLayerRef.current.updateGeometry(corners, gridDef);
|
|
166
|
+
cachedGeometry.current = { model: gridModel, variable };
|
|
167
|
+
|
|
168
|
+
const { colormap, baseUnit } = core._getColormapForVariable(variable);
|
|
169
|
+
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
170
|
+
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
171
|
+
let dataRange;
|
|
172
|
+
if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
|
|
173
|
+
if (isMRMS) {
|
|
174
|
+
console.log('🔧 Using MRMS ptype data range: 5-380');
|
|
175
|
+
dataRange = [5, 380];
|
|
176
|
+
} else {
|
|
177
|
+
console.log('🔧 Using Model ptype data range: 5-380');
|
|
178
|
+
dataRange = [5, 380];
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
182
|
+
}
|
|
183
|
+
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
184
|
+
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
185
|
+
|
|
186
|
+
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
187
|
+
cachedColormap.current = { key: `${variable}-${units}` };
|
|
188
|
+
cachedDataRange.current = dataRange;
|
|
189
|
+
|
|
190
|
+
setRenderProps({ opacity: state.opacity, dataRange: dataRange });
|
|
191
|
+
hasInitialLoad.current = true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Apply the same filtering logic as in AguaceroCore._emitStateChange
|
|
195
|
+
let filteredHours = availableHours;
|
|
196
|
+
if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && availableHours && availableHours.length > 0) {
|
|
197
|
+
filteredHours = availableHours.filter(hour => hour !== 0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const allFrames = isMRMS ? availableTimestamps : filteredHours;
|
|
201
|
+
if (!allFrames || allFrames.length === 0) {
|
|
202
|
+
console.warn('🟡 [preloadAllFramesToDisk] No frames available to download.');
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const currentFrame = isMRMS ? mrmsTimestamp : effectiveForecastHour;
|
|
207
|
+
|
|
208
|
+
// --- EDIT: Reverse the frame order to load from last to first ---
|
|
209
|
+
const reversedFrames = [...allFrames].reverse();
|
|
210
|
+
const framesToPreload = reversedFrames.filter(frame => frame !== currentFrame);
|
|
211
|
+
|
|
212
|
+
// The final array will process the current frame first, then the rest in reverse chronological order.
|
|
213
|
+
const prioritizedFrames = [
|
|
214
|
+
currentFrame,
|
|
215
|
+
...framesToPreload
|
|
216
|
+
];
|
|
217
|
+
// --- END EDIT ---
|
|
218
|
+
|
|
219
|
+
console.log(`[Preload] Prioritizing frame: ${currentFrame}. Total frames: ${prioritizedFrames.length}`);
|
|
220
|
+
|
|
221
|
+
const { corners, gridDef } = core._getGridCornersAndDef(isMRMS ? 'mrms' : model);
|
|
222
|
+
const { nx, ny } = gridDef.grid_params;
|
|
223
|
+
|
|
224
|
+
prioritizedFrames.forEach((frame, index) => {
|
|
225
|
+
const cacheKey = isMRMS ? `mrms-${frame}-${variable}` : `${model}-${date}-${run}-${frame}-${variable}`;
|
|
226
|
+
if (preloadedDataCache.current.has(cacheKey)) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
let resourcePath;
|
|
231
|
+
if (isMRMS) {
|
|
232
|
+
const frameDate = new Date(frame * 1000);
|
|
233
|
+
const y = frameDate.getUTCFullYear();
|
|
234
|
+
const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
|
|
235
|
+
const d = frameDate.getUTCDate().toString().padStart(2, '0');
|
|
236
|
+
resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${variable}/0`;
|
|
237
|
+
} else {
|
|
238
|
+
resourcePath = `/grids/${model}/${date}/${run}/${frame}/${variable}/0`;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
|
|
242
|
+
const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
|
|
243
|
+
|
|
244
|
+
WeatherFrameProcessorModule.processFrame(options)
|
|
245
|
+
.then(result => {
|
|
246
|
+
if (!result || !result.filePath) {
|
|
247
|
+
console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}: No filePath`);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const { baseUnit } = core._getColormapForVariable(variable);
|
|
252
|
+
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
253
|
+
|
|
254
|
+
let dataScale = result.scale;
|
|
255
|
+
let dataOffset = result.offset;
|
|
256
|
+
|
|
257
|
+
let convertedScale = dataScale;
|
|
258
|
+
let convertedOffset = dataOffset;
|
|
259
|
+
|
|
260
|
+
if (baseUnit !== toUnit) {
|
|
261
|
+
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
262
|
+
if (conversionFunc) {
|
|
263
|
+
if (result.scaleType === 'sqrt') {
|
|
264
|
+
const physicalAtOffset = dataOffset * dataOffset;
|
|
265
|
+
const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
|
|
266
|
+
const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
|
|
267
|
+
const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
|
|
268
|
+
convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
|
|
269
|
+
const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
|
|
270
|
+
convertedScale = newOffsetPlusScale - convertedOffset;
|
|
271
|
+
} else {
|
|
272
|
+
convertedOffset = conversionFunc(dataOffset);
|
|
273
|
+
const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
|
|
274
|
+
convertedScale = convertedOffsetPlusScale - convertedOffset;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const frameData = {
|
|
280
|
+
filePath: result.filePath,
|
|
281
|
+
nx, ny,
|
|
282
|
+
scale: convertedScale,
|
|
283
|
+
offset: convertedOffset,
|
|
284
|
+
missing: result.missing,
|
|
285
|
+
corners,
|
|
286
|
+
gridDef,
|
|
287
|
+
scaleType: result.scaleType,
|
|
288
|
+
originalScale: result.scale,
|
|
289
|
+
originalOffset: result.offset
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
preloadedDataCache.current.set(cacheKey, frameData);
|
|
293
|
+
|
|
294
|
+
const isCurrentFrame = index === 0;
|
|
295
|
+
|
|
296
|
+
if (isCurrentFrame) {
|
|
297
|
+
console.log(`🎯 [Preload] Using FAST LANE to process and draw current frame (${frame}) immediately.`);
|
|
298
|
+
gridLayerRef.current.updateDataTextureFromFile(
|
|
299
|
+
frameData.filePath,
|
|
300
|
+
frameData.nx, frameData.ny,
|
|
301
|
+
frameData.scale, frameData.offset, frameData.missing,
|
|
302
|
+
frameData.scaleType
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
currentGridDataRef.current = {
|
|
306
|
+
nx: frameData.nx,
|
|
307
|
+
ny: frameData.ny,
|
|
308
|
+
scale: frameData.scale,
|
|
309
|
+
offset: frameData.offset,
|
|
310
|
+
missing: frameData.missing,
|
|
311
|
+
gridDef: frameData.gridDef,
|
|
312
|
+
variable: variable,
|
|
313
|
+
units: units
|
|
314
|
+
};
|
|
315
|
+
} else {
|
|
316
|
+
if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
|
|
317
|
+
const frameInfoForGpu = {
|
|
318
|
+
[cacheKey]: {
|
|
319
|
+
filePath: frameData.filePath,
|
|
320
|
+
nx: frameData.nx,
|
|
321
|
+
ny: frameData.ny,
|
|
322
|
+
scale: frameData.scale,
|
|
323
|
+
offset: frameData.offset,
|
|
324
|
+
missing: frameData.missing,
|
|
325
|
+
scaleType: frameData.scaleType || 'linear',
|
|
326
|
+
originalScale: frameData.originalScale,
|
|
327
|
+
originalOffset: frameData.originalOffset
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
gridLayerRef.current.primeGpuCache(frameInfoForGpu);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
})
|
|
334
|
+
.catch(error => {
|
|
335
|
+
console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}:`, error);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const updateGPUWithCachedData = (state) => {
|
|
341
|
+
const { model, date, run, forecastHour, variable, units, isMRMS, mrmsTimestamp } = state;
|
|
342
|
+
|
|
343
|
+
const cacheKey = isMRMS
|
|
344
|
+
? `mrms-${mrmsTimestamp}-${variable}`
|
|
345
|
+
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
346
|
+
|
|
347
|
+
if (Platform.OS === 'ios' && gridLayerRef.current.setActiveFrame) {
|
|
348
|
+
// Get the cached data BEFORE calling setActiveFrame
|
|
349
|
+
const cachedData = preloadedDataCache.current.get(cacheKey);
|
|
350
|
+
|
|
351
|
+
if (cachedData) {
|
|
352
|
+
currentGridDataRef.current = {
|
|
353
|
+
nx: cachedData.nx,
|
|
354
|
+
ny: cachedData.ny,
|
|
355
|
+
scale: cachedData.scale,
|
|
356
|
+
offset: cachedData.offset,
|
|
357
|
+
missing: cachedData.missing,
|
|
358
|
+
gridDef: cachedData.gridDef,
|
|
359
|
+
variable: variable,
|
|
360
|
+
units: units,
|
|
361
|
+
scaleType: cachedData.scaleType
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
console.log('📱 [iOS] Updated currentGridDataRef for inspector:', {
|
|
365
|
+
scale: cachedData.scale,
|
|
366
|
+
offset: cachedData.offset,
|
|
367
|
+
scaleType: cachedData.scaleType // ADD THIS
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Now call setActiveFrame (which will async update the native cache)
|
|
372
|
+
gridLayerRef.current.setActiveFrame(cacheKey);
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const cachedData = preloadedDataCache.current.get(cacheKey);
|
|
377
|
+
|
|
378
|
+
if (!cachedData) {
|
|
379
|
+
const timeKey = isMRMS ? `timestamp ${mrmsTimestamp}` : `hour +${forecastHour}`;
|
|
380
|
+
console.log(`⏳ [updateGPUWithCachedData] Frame not ready yet for ${timeKey}. Still preloading...`); // CHANGED
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!gridLayerRef.current) {
|
|
385
|
+
console.warn(`⚠️ [updateGPUWithCachedData] GridLayer ref not available`); // CHANGED
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (!cachedGeometry.current || cachedGeometry.current.model !== (isMRMS ? 'mrms' : model) || cachedGeometry.current.variable !== variable) {
|
|
390
|
+
gridLayerRef.current.updateGeometry(cachedData.corners, cachedData.gridDef);
|
|
391
|
+
cachedGeometry.current = { model: (isMRMS ? 'mrms' : model), variable };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const colormapKey = `${variable}-${units}`;
|
|
395
|
+
if (!cachedColormap.current || cachedColormap.current.key !== colormapKey) {
|
|
396
|
+
const { colormap, baseUnit } = core._getColormapForVariable(variable);
|
|
397
|
+
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
398
|
+
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
399
|
+
let dataRange;
|
|
400
|
+
if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
|
|
401
|
+
if (isMRMS) {
|
|
402
|
+
dataRange = [5, 380];
|
|
403
|
+
} else {
|
|
404
|
+
dataRange = [5, 380];
|
|
405
|
+
}
|
|
406
|
+
} else {
|
|
407
|
+
dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
408
|
+
}
|
|
409
|
+
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
410
|
+
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
411
|
+
|
|
412
|
+
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
413
|
+
cachedColormap.current = { key: colormapKey };
|
|
414
|
+
cachedDataRange.current = dataRange;
|
|
415
|
+
|
|
416
|
+
setRenderProps(prev => ({ ...prev, dataRange }));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (cachedData.filePath) {
|
|
420
|
+
gridLayerRef.current.updateDataTextureFromFile(
|
|
421
|
+
cachedData.filePath,
|
|
422
|
+
cachedData.nx, cachedData.ny,
|
|
423
|
+
cachedData.scale, cachedData.offset, cachedData.missing,
|
|
424
|
+
cachedData.scaleType
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
// ADD THIS: Update inspector cache for file-based data too
|
|
428
|
+
currentGridDataRef.current = {
|
|
429
|
+
nx: cachedData.nx,
|
|
430
|
+
ny: cachedData.ny,
|
|
431
|
+
scale: cachedData.scale,
|
|
432
|
+
offset: cachedData.offset,
|
|
433
|
+
missing: cachedData.missing,
|
|
434
|
+
gridDef: cachedData.gridDef,
|
|
435
|
+
variable: variable,
|
|
436
|
+
units: units
|
|
437
|
+
};
|
|
438
|
+
} else if (cachedData.dataAsBase64) {
|
|
439
|
+
gridLayerRef.current.updateDataTexture(
|
|
440
|
+
cachedData.dataAsBase64,
|
|
441
|
+
cachedData.nx, cachedData.ny,
|
|
442
|
+
cachedData.scale, cachedData.offset, cachedData.missing,
|
|
443
|
+
cachedData.scaleType
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
// Update the inspector cache when using dataAsBase64
|
|
447
|
+
const binaryString = atob(cachedData.dataAsBase64);
|
|
448
|
+
const uint8Array = new Uint8Array(binaryString.length);
|
|
449
|
+
|
|
450
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
451
|
+
uint8Array[i] = binaryString.charCodeAt(i);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
currentGridDataRef.current = {
|
|
455
|
+
data: uint8Array,
|
|
456
|
+
nx: cachedData.nx,
|
|
457
|
+
ny: cachedData.ny,
|
|
458
|
+
scale: cachedData.scale,
|
|
459
|
+
offset: cachedData.offset,
|
|
460
|
+
missing: cachedData.missing,
|
|
461
|
+
gridDef: cachedData.gridDef,
|
|
462
|
+
variable: variable,
|
|
463
|
+
units: units
|
|
464
|
+
};
|
|
465
|
+
} else {
|
|
466
|
+
console.error(`❌ [updateGPUWithCachedData] Cached data has no filePath or dataAsBase64!`);
|
|
467
|
+
console.error('❌ [updateGPUWithCachedData] Cached data keys:', Object.keys(cachedData));
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Update inspector parameters for file-based data too
|
|
472
|
+
if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
|
|
473
|
+
gridLayerRef.current.updateDataParameters(cachedData.scale, cachedData.offset, cachedData.missing);
|
|
474
|
+
}
|
|
475
|
+
return true;
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
const handleStateChangeRef = useRef(null);
|
|
479
|
+
const debounceTimeoutRef = useRef(null);
|
|
480
|
+
|
|
481
|
+
useEffect(() => {
|
|
482
|
+
if (core && props.customColormaps) {
|
|
483
|
+
core.customColormaps = props.customColormaps;
|
|
484
|
+
// Trigger a re-render if we already have data loaded
|
|
485
|
+
if (hasInitialLoad.current) {
|
|
486
|
+
core._emitStateChange();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}, [core, props.customColormaps]);
|
|
490
|
+
|
|
491
|
+
const getValueAtPoint = async (lng, lat) => {
|
|
492
|
+
if (!core) {
|
|
493
|
+
console.warn('🔍 [Inspector] Core not available');
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ADD THIS: Check if we have valid data before attempting inspection
|
|
498
|
+
if (!currentGridDataRef.current) {
|
|
499
|
+
console.log('🔍 [Inspector] No grid data available');
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
try {
|
|
504
|
+
const gridIndices = core._getGridIndexFromLngLat(lng, lat);
|
|
505
|
+
if (!gridIndices) return null;
|
|
506
|
+
|
|
507
|
+
const { i, j } = gridIndices;
|
|
508
|
+
|
|
509
|
+
const value = await InspectorModule.getValueAtGridIndex(i, j);
|
|
510
|
+
|
|
511
|
+
if (value === null) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const { colormap, baseUnit } = core._getColormapForVariable(core.state.variable);
|
|
516
|
+
const displayUnit = core._getTargetUnit(baseUnit, core.state.units);
|
|
517
|
+
const finalColormap = core._convertColormapUnits(colormap, baseUnit, displayUnit);
|
|
518
|
+
const minThreshold = finalColormap[0];
|
|
519
|
+
|
|
520
|
+
if (value < minThreshold) {
|
|
521
|
+
console.log('🔍 [Inspector] Rejected: below threshold'); // ADD THIS LOG
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Filter out values below the minimum threshold (matching shader behavior)
|
|
526
|
+
if (value < minThreshold) {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Also check if value is NaN or effectively missing
|
|
531
|
+
if (!isFinite(value)) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
value: value,
|
|
537
|
+
unit: displayUnit,
|
|
538
|
+
variable: {
|
|
539
|
+
code: core.state.variable,
|
|
540
|
+
name: core.getVariableDisplayName(core.state.variable)
|
|
541
|
+
},
|
|
542
|
+
lngLat: { lng, lat }
|
|
543
|
+
};
|
|
544
|
+
} catch (error) {
|
|
545
|
+
console.error('🔍 [Inspector] Error:', error);
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
useEffect(() => {
|
|
551
|
+
if (!core) {
|
|
552
|
+
console.warn('⚠️ [useEffect] Core is not available yet');
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const handleStateChange = async (newState) => {
|
|
557
|
+
if (!previousStateRef.current) {
|
|
558
|
+
previousStateRef.current = core.state;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const variableChanged = !previousStateRef.current || newState.variable !== previousStateRef.current.variable;
|
|
562
|
+
|
|
563
|
+
if (variableChanged && gridLayerRef.current?.setVariable) {
|
|
564
|
+
gridLayerRef.current.setVariable(newState.variable);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const stateKey = `${newState.model}-${newState.variable}-${newState.date}-${newState.run}-${newState.forecastHour}-${newState.units}-${newState.mrmsTimestamp}`;
|
|
568
|
+
|
|
569
|
+
const isOpacityOnlyChange =
|
|
570
|
+
hasInitialLoad.current &&
|
|
571
|
+
newState.opacity !== renderProps.opacity &&
|
|
572
|
+
newState.variable === previousStateRef.current?.variable &&
|
|
573
|
+
newState.forecastHour === previousStateRef.current?.forecastHour &&
|
|
574
|
+
newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
|
|
575
|
+
newState.model === previousStateRef.current?.model &&
|
|
576
|
+
newState.units === previousStateRef.current?.units;
|
|
577
|
+
|
|
578
|
+
// ADD: Check for play state only change
|
|
579
|
+
const isPlayStateOnlyChange =
|
|
580
|
+
hasInitialLoad.current &&
|
|
581
|
+
newState.isPlaying !== previousStateRef.current?.isPlaying &&
|
|
582
|
+
newState.variable === previousStateRef.current?.variable &&
|
|
583
|
+
newState.forecastHour === previousStateRef.current?.forecastHour &&
|
|
584
|
+
newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
|
|
585
|
+
newState.model === previousStateRef.current?.model &&
|
|
586
|
+
newState.units === previousStateRef.current?.units &&
|
|
587
|
+
newState.opacity === previousStateRef.current?.opacity;
|
|
588
|
+
|
|
589
|
+
if (!isOpacityOnlyChange && !isPlayStateOnlyChange && lastProcessedState.current === stateKey) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (!isOpacityOnlyChange && !isPlayStateOnlyChange) {
|
|
594
|
+
lastProcessedState.current = stateKey;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// MOVE THIS TO THE TOP - Always notify the parent component of state changes
|
|
598
|
+
props.onStateChange?.(newState);
|
|
599
|
+
|
|
600
|
+
if (isOpacityOnlyChange) {
|
|
601
|
+
setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
|
|
602
|
+
previousStateRef.current = newState;
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// ADD: Handle play state only change
|
|
607
|
+
if (isPlayStateOnlyChange) {
|
|
608
|
+
previousStateRef.current = newState;
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Check if only units changed
|
|
613
|
+
const isUnitsOnlyChange =
|
|
614
|
+
hasInitialLoad.current &&
|
|
615
|
+
newState.model === previousStateRef.current.model &&
|
|
616
|
+
newState.isMRMS === previousStateRef.current.isMRMS &&
|
|
617
|
+
newState.variable === previousStateRef.current.variable &&
|
|
618
|
+
newState.date === previousStateRef.current.date &&
|
|
619
|
+
newState.run === previousStateRef.current.run &&
|
|
620
|
+
newState.forecastHour === previousStateRef.current.forecastHour &&
|
|
621
|
+
newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
|
|
622
|
+
newState.units !== previousStateRef.current.units;
|
|
623
|
+
|
|
624
|
+
if (isUnitsOnlyChange) {
|
|
625
|
+
const { variable, units, isMRMS, mrmsTimestamp, model, date, run, forecastHour } = newState;
|
|
626
|
+
const oldCacheKey = isMRMS
|
|
627
|
+
? `mrms-${mrmsTimestamp}-${variable}`
|
|
628
|
+
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
629
|
+
|
|
630
|
+
const cachedData = preloadedDataCache.current.get(oldCacheKey);
|
|
631
|
+
|
|
632
|
+
if (cachedData && cachedData.originalScale !== undefined && cachedData.originalOffset !== undefined) {
|
|
633
|
+
const { baseUnit } = core._getColormapForVariable(variable);
|
|
634
|
+
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
635
|
+
|
|
636
|
+
let dataScale = cachedData.originalScale;
|
|
637
|
+
let dataOffset = cachedData.originalOffset;
|
|
638
|
+
|
|
639
|
+
if (baseUnit !== toUnit) {
|
|
640
|
+
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
641
|
+
console.log('🔧 [Unit Conversion] Conversion function exists:', !!conversionFunc);
|
|
642
|
+
|
|
643
|
+
if (conversionFunc) {
|
|
644
|
+
if (cachedData.scaleType === 'sqrt') {
|
|
645
|
+
// Calculate what the physical values would be at offset and offset+scale
|
|
646
|
+
const physicalAtOffset = dataOffset * dataOffset;
|
|
647
|
+
const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
|
|
648
|
+
|
|
649
|
+
// Convert these physical values to the new unit
|
|
650
|
+
const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
|
|
651
|
+
const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
|
|
652
|
+
|
|
653
|
+
// Take sqrt to get back to intermediate values
|
|
654
|
+
const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
|
|
655
|
+
const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
|
|
656
|
+
|
|
657
|
+
dataScale = newOffsetPlusScale - newOffset;
|
|
658
|
+
dataOffset = newOffset;
|
|
659
|
+
} else {
|
|
660
|
+
const convertedOffset = conversionFunc(dataOffset);
|
|
661
|
+
const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
|
|
662
|
+
|
|
663
|
+
dataScale = convertedOffsetPlusScale - convertedOffset;
|
|
664
|
+
dataOffset = convertedOffset;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Update the colormap AND data range
|
|
670
|
+
const { colormap } = core._getColormapForVariable(variable);
|
|
671
|
+
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
672
|
+
let dataRange;
|
|
673
|
+
if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
|
|
674
|
+
if (isMRMS) {
|
|
675
|
+
dataRange = [5, 380];
|
|
676
|
+
} else {
|
|
677
|
+
dataRange = [5, 380];
|
|
678
|
+
}
|
|
679
|
+
} else {
|
|
680
|
+
dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
684
|
+
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
685
|
+
|
|
686
|
+
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
687
|
+
cachedColormap.current = { key: `${variable}-${units}` };
|
|
688
|
+
cachedDataRange.current = dataRange;
|
|
689
|
+
|
|
690
|
+
setRenderProps(prev => ({ ...prev, dataRange, opacity: newState.opacity }));
|
|
691
|
+
|
|
692
|
+
if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
|
|
693
|
+
const scaleTypeValue = cachedData.scaleType === 'sqrt' ? 1 : 0; // Convert to number
|
|
694
|
+
|
|
695
|
+
console.log('🔄 [Unit Conversion] Calling updateDataParameters with:', {
|
|
696
|
+
scale: dataScale,
|
|
697
|
+
offset: dataOffset,
|
|
698
|
+
missing: cachedData.missing,
|
|
699
|
+
scaleType: scaleTypeValue
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
gridLayerRef.current.updateDataParameters(dataScale, dataOffset, cachedData.missing, scaleTypeValue); // Pass scaleType
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const newCacheKey = isMRMS
|
|
706
|
+
? `mrms-${mrmsTimestamp}-${variable}`
|
|
707
|
+
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
708
|
+
|
|
709
|
+
preloadedDataCache.current.set(newCacheKey, {
|
|
710
|
+
...cachedData,
|
|
711
|
+
scale: dataScale,
|
|
712
|
+
offset: dataOffset
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
} else {
|
|
716
|
+
console.warn('⚠️ [Unit Conversion] No cached data found for key:', oldCacheKey);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
previousStateRef.current = newState;
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
const needsFullLoad =
|
|
724
|
+
!hasInitialLoad.current ||
|
|
725
|
+
newState.model !== previousStateRef.current.model ||
|
|
726
|
+
newState.isMRMS !== previousStateRef.current.isMRMS ||
|
|
727
|
+
newState.variable !== previousStateRef.current.variable ||
|
|
728
|
+
newState.date !== previousStateRef.current.date ||
|
|
729
|
+
newState.run !== previousStateRef.current.run;
|
|
730
|
+
|
|
731
|
+
if (needsFullLoad) {
|
|
732
|
+
|
|
733
|
+
if (gridLayerRef.current) {
|
|
734
|
+
gridLayerRef.current.setVariable(newState.variable);
|
|
735
|
+
gridLayerRef.current.clear();
|
|
736
|
+
// --- OPTIMIZATION: Clear the native GPU cache on iOS ---
|
|
737
|
+
if (Platform.OS === 'ios' && gridLayerRef.current.clearGpuCache) {
|
|
738
|
+
gridLayerRef.current.clearGpuCache();
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
hasPreloadedRef.current = false;
|
|
742
|
+
|
|
743
|
+
preloadedDataCache.current.clear();
|
|
744
|
+
cachedGeometry.current = null;
|
|
745
|
+
cachedColormap.current = null;
|
|
746
|
+
|
|
747
|
+
// ADD THIS: Clear the inspector cache too
|
|
748
|
+
currentGridDataRef.current = null;
|
|
749
|
+
|
|
750
|
+
WeatherFrameProcessorModule.cancelAllFrames();
|
|
751
|
+
|
|
752
|
+
if (!newState.variable) {
|
|
753
|
+
previousStateRef.current = newState;
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
preloadAllFramesToDisk(newState);
|
|
758
|
+
} else if (newState.forecastHour !== previousStateRef.current.forecastHour || (newState.isMRMS && newState.mrmsTimestamp !== previousStateRef.current.mrmsTimestamp)) {
|
|
759
|
+
const success = updateGPUWithCachedData(newState);
|
|
760
|
+
|
|
761
|
+
if (!success) {
|
|
762
|
+
// CHANGED: Don't error, just log and wait for preload
|
|
763
|
+
const timeKey = newState.isMRMS ? `timestamp ${newState.mrmsTimestamp}` : `hour +${newState.forecastHour}`;
|
|
764
|
+
console.log(`⏳ [handleStateChange] Frame ${timeKey} not ready yet, waiting for preload...`);
|
|
765
|
+
// Don't clear the layer - keep showing the previous frame until new one is ready
|
|
766
|
+
// The preload will eventually complete and trigger a re-render
|
|
767
|
+
} else {
|
|
768
|
+
// Only update inspector cache when we successfully loaded new data
|
|
769
|
+
if (newState.opacity !== renderProps.opacity) {
|
|
770
|
+
setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
previousStateRef.current = newState;
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
handleStateChangeRef.current = handleStateChange;
|
|
779
|
+
|
|
780
|
+
const stableHandler = (newState) => {
|
|
781
|
+
const isOpacityOnlyChange =
|
|
782
|
+
previousStateRef.current &&
|
|
783
|
+
newState.opacity !== previousStateRef.current.opacity &&
|
|
784
|
+
newState.variable === previousStateRef.current.variable &&
|
|
785
|
+
newState.forecastHour === previousStateRef.current.forecastHour &&
|
|
786
|
+
newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
|
|
787
|
+
newState.model === previousStateRef.current.model &&
|
|
788
|
+
newState.units === previousStateRef.current.units &&
|
|
789
|
+
newState.date === previousStateRef.current.date &&
|
|
790
|
+
newState.run === previousStateRef.current.run;
|
|
791
|
+
|
|
792
|
+
if (isOpacityOnlyChange) {
|
|
793
|
+
if (handleStateChangeRef.current) {
|
|
794
|
+
handleStateChangeRef.current(newState);
|
|
795
|
+
}
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (debounceTimeoutRef.current) {
|
|
800
|
+
clearTimeout(debounceTimeoutRef.current);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
debounceTimeoutRef.current = setTimeout(() => {
|
|
804
|
+
if (handleStateChangeRef.current) {
|
|
805
|
+
handleStateChangeRef.current(newState);
|
|
806
|
+
}
|
|
807
|
+
debounceTimeoutRef.current = null;
|
|
808
|
+
}, 50);
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
core.on('state:change', stableHandler);
|
|
812
|
+
|
|
813
|
+
return () => {
|
|
814
|
+
core.off('state:change', stableHandler);
|
|
815
|
+
if (debounceTimeoutRef.current) {
|
|
816
|
+
clearTimeout(debounceTimeoutRef.current);
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
}, [core]);
|
|
820
|
+
|
|
821
|
+
useEffect(() => {
|
|
822
|
+
return () => {
|
|
823
|
+
preloadedDataCache.current.clear();
|
|
824
|
+
hasInitialLoad.current = false;
|
|
825
|
+
lastProcessedState.current = null;
|
|
826
|
+
};
|
|
827
|
+
}, []);
|
|
828
|
+
|
|
829
|
+
const lastInspectorUpdateRef = useRef(0);
|
|
830
|
+
const INSPECTOR_THROTTLE_MS = 50;
|
|
831
|
+
|
|
832
|
+
useEffect(() => {
|
|
833
|
+
if (!core || !inspectorEnabled) {
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
const handleMapMove = async (center) => {
|
|
838
|
+
if (!center || !Array.isArray(center) || center.length !== 2) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// Throttle updates
|
|
843
|
+
const now = Date.now();
|
|
844
|
+
if (now - lastInspectorUpdateRef.current < INSPECTOR_THROTTLE_MS) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
lastInspectorUpdateRef.current = now;
|
|
848
|
+
|
|
849
|
+
const [longitude, latitude] = center;
|
|
850
|
+
|
|
851
|
+
const payload = await getValueAtPoint(longitude, latitude);
|
|
852
|
+
onInspect?.(payload);
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
core.on('map:move', handleMapMove);
|
|
856
|
+
|
|
857
|
+
if (context && context.getCenter) {
|
|
858
|
+
const center = context.getCenter();
|
|
859
|
+
if (center) {
|
|
860
|
+
handleMapMove(center);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
return () => {
|
|
865
|
+
core.off('map:move', handleMapMove);
|
|
866
|
+
};
|
|
867
|
+
}, [inspectorEnabled, onInspect, core, context]);
|
|
868
|
+
|
|
869
|
+
// Add this new useEffect after the existing inspector useEffect
|
|
870
|
+
useEffect(() => {
|
|
871
|
+
// Trigger re-inspection when state changes (variable, model, forecast hour, etc.)
|
|
872
|
+
if (!core || !inspectorEnabled) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const triggerReinspection = () => {
|
|
877
|
+
const mapRef = mapRegistry.getMap();
|
|
878
|
+
const center = mapRef?._currentCenter;
|
|
879
|
+
|
|
880
|
+
if (center && Array.isArray(center) && center.length === 2) {
|
|
881
|
+
const [longitude, latitude] = center;
|
|
882
|
+
|
|
883
|
+
getValueAtPoint(longitude, latitude).then(payload => {
|
|
884
|
+
onInspect?.(payload);
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// Small delay to ensure data is loaded before re-inspecting
|
|
890
|
+
const timer = setTimeout(triggerReinspection, 100);
|
|
891
|
+
|
|
892
|
+
return () => clearTimeout(timer);
|
|
893
|
+
}, [
|
|
894
|
+
core?.state?.variable,
|
|
895
|
+
core?.state?.model,
|
|
896
|
+
core?.state?.forecastHour,
|
|
897
|
+
core?.state?.mrmsTimestamp,
|
|
898
|
+
core?.state?.units,
|
|
899
|
+
inspectorEnabled,
|
|
900
|
+
onInspect
|
|
901
|
+
]);
|
|
902
|
+
|
|
903
|
+
useEffect(() => {
|
|
904
|
+
if (!core) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
const handleCameraChange = (center) => {
|
|
909
|
+
if (core && center) {
|
|
910
|
+
core.setMapCenter(center);
|
|
911
|
+
}
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
// Register with the global registry
|
|
915
|
+
mapRegistry.addCameraListener(handleCameraChange);
|
|
916
|
+
|
|
917
|
+
// Try to get initial center
|
|
918
|
+
const mapRef = mapRegistry.getMap();
|
|
919
|
+
if (mapRef?._currentCenter) {
|
|
920
|
+
handleCameraChange(mapRef._currentCenter);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
return () => {
|
|
924
|
+
mapRegistry.removeCameraListener(handleCameraChange);
|
|
925
|
+
};
|
|
926
|
+
}, [core]);
|
|
927
|
+
|
|
928
|
+
useEffect(() => {
|
|
929
|
+
core.initialize();
|
|
930
|
+
return () => {
|
|
931
|
+
core.destroy();
|
|
932
|
+
};
|
|
933
|
+
}, [core]);
|
|
934
|
+
|
|
935
|
+
return (
|
|
936
|
+
<GridRenderLayer
|
|
937
|
+
ref={gridLayerRef}
|
|
938
|
+
opacity={renderProps.opacity}
|
|
939
|
+
dataRange={renderProps.dataRange}
|
|
940
|
+
belowID="AML_-_terrain"
|
|
941
|
+
/>
|
|
942
|
+
);
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
WeatherLayerManager.getAvailableVariables = (options) => {
|
|
946
|
+
if (!options || !options.apiKey) {
|
|
947
|
+
console.error("API key must be provided to get available variables.");
|
|
948
|
+
return [];
|
|
949
|
+
}
|
|
950
|
+
const core = new AguaceroCore({ apiKey: options.apiKey });
|
|
951
|
+
return core.getAvailableVariables('mrms');
|
|
952
952
|
};
|