react-native-cesium 1.0.6 → 1.2.0
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 +64 -11
- package/ReactNativeCesium.podspec +1 -1
- package/android/CMakeLists.txt +5 -3
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +197 -227
- package/android/src/main/cpp/CesiumBridgeAndroid.h +48 -49
- package/android/src/main/cpp/cpp-adapter.cpp +2 -2
- package/android/src/main/cpp/vulkan/VulkanBackend.cpp +1010 -569
- package/android/src/main/cpp/vulkan/VulkanBackend.h +121 -12
- package/android/src/main/cpp/vulkan/shaders/sky.frag +20 -10
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +28 -0
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +295 -58
- package/cpp/engine/CameraSmoother.cpp +99 -0
- package/cpp/engine/CameraSmoother.hpp +29 -0
- package/cpp/engine/CameraTargetState.cpp +49 -0
- package/cpp/engine/CameraTargetState.hpp +121 -0
- package/cpp/engine/CesiumEngine.cpp +206 -60
- package/cpp/engine/CesiumEngine.hpp +77 -10
- package/cpp/engine/EngineTunables.hpp +79 -0
- package/cpp/engine/GeoidConverter.cpp +36 -0
- package/cpp/engine/GeoidConverter.hpp +10 -0
- package/cpp/engine/GlobeCamera.cpp +7 -2
- package/cpp/engine/MetricsAggregator.cpp +71 -0
- package/cpp/engine/MetricsAggregator.hpp +54 -0
- package/cpp/engine/TileLifecycleManager.cpp +0 -12
- package/cpp/engine/TileLifecycleManager.hpp +0 -3
- package/cpp/third_party/egm96/EGM96.c +289 -0
- package/cpp/third_party/egm96/EGM96.h +45 -0
- package/cpp/third_party/egm96/EGM96_data.h +65372 -0
- package/ios/CesiumBridge.h +24 -5
- package/ios/CesiumBridge.mm +149 -271
- package/ios/HybridCesiumView.swift +197 -40
- package/ios/metal/MetalBackend.mm +72 -23
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +26 -0
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JCesiumMetrics.hpp +5 -1
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +109 -1
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +24 -0
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +48 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CameraState.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CesiumMetrics.kt +32 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/Quaternion.kt +19 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +30 -0
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +85 -1
- package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +60 -0
- package/nitrogen/generated/ios/swift/CesiumMetrics.swift +7 -2
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +12 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +288 -0
- package/nitrogen/generated/shared/c++/CesiumMetrics.hpp +5 -1
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +25 -1
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +132 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +13 -1
- package/nitrogen/generated/shared/json/CesiumViewConfig.json +12 -0
- package/package.json +4 -4
- package/scripts/cesium/clone.mjs +1 -1
- package/src/specs/cesium-view.nitro.ts +29 -0
- package/cpp/engine/DeletionQueue.cpp +0 -28
- package/cpp/engine/DeletionQueue.hpp +0 -28
|
@@ -8,15 +8,23 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
8
8
|
// MARK: - Props
|
|
9
9
|
|
|
10
10
|
var ionAccessToken: String = "" {
|
|
11
|
-
didSet {
|
|
11
|
+
didSet {
|
|
12
|
+
let token = ionAccessToken
|
|
13
|
+
let assetId = Int64(ionAssetId)
|
|
14
|
+
postToRender { [weak self] in self?.bridge?.updateIonAccessToken(token, assetId: assetId) }
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
var ionAssetId: Double = 1 {
|
|
14
|
-
didSet {
|
|
18
|
+
didSet {
|
|
19
|
+
let token = ionAccessToken
|
|
20
|
+
let assetId = Int64(ionAssetId)
|
|
21
|
+
postToRender { [weak self] in self?.bridge?.updateIonAccessToken(token, assetId: assetId) }
|
|
22
|
+
}
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
/// Construction-time seed camera.
|
|
18
|
-
///
|
|
19
|
-
///
|
|
25
|
+
/// Construction-time seed camera. Used exactly once when the native bridge
|
|
26
|
+
/// is created; subsequent prop writes are ignored. Use `setCamera(_:)` to
|
|
27
|
+
/// drive the camera at runtime — it does NOT mutate this value.
|
|
20
28
|
var initialCamera: CameraState = CameraState(
|
|
21
29
|
latitude: 46.15,
|
|
22
30
|
longitude: 7.35,
|
|
@@ -28,32 +36,82 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
28
36
|
)
|
|
29
37
|
var pauseRendering: Bool = false {
|
|
30
38
|
didSet {
|
|
31
|
-
displayLink?.isPaused = pauseRendering
|
|
39
|
+
displayLink?.isPaused = pauseRendering // UIKit-ish, must stay on main
|
|
32
40
|
if !pauseRendering {
|
|
33
|
-
bridge?.markNeedsRender()
|
|
41
|
+
postToRender { [weak self] in self?.bridge?.markNeedsRender() }
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
var maximumScreenSpaceError: Double = 32 {
|
|
39
|
-
didSet { bridge?.setMaximumScreenSpaceError(
|
|
47
|
+
didSet { let v = maximumScreenSpaceError; postToRender { [weak self] in self?.bridge?.setMaximumScreenSpaceError(v) } }
|
|
40
48
|
}
|
|
41
49
|
var maximumSimultaneousTileLoads: Double = 12 {
|
|
42
|
-
didSet { bridge?.setMaximumSimultaneousTileLoads(
|
|
50
|
+
didSet { let v = Int32(maximumSimultaneousTileLoads); postToRender { [weak self] in self?.bridge?.setMaximumSimultaneousTileLoads(v) } }
|
|
43
51
|
}
|
|
44
52
|
var loadingDescendantLimit: Double = 20 {
|
|
45
|
-
didSet { bridge?.setLoadingDescendantLimit(
|
|
53
|
+
didSet { let v = Int32(loadingDescendantLimit); postToRender { [weak self] in self?.bridge?.setLoadingDescendantLimit(v) } }
|
|
46
54
|
}
|
|
47
55
|
var msaaSampleCount: Double = 1 {
|
|
48
56
|
didSet {
|
|
49
57
|
let s = Int32(msaaSampleCount)
|
|
50
|
-
|
|
58
|
+
// applyMtkViewMsaa touches MTKView/UIKit so it stays on main.
|
|
51
59
|
applyMtkViewMsaa(Int(s))
|
|
60
|
+
postToRender { [weak self] in self?.bridge?.setMsaaSampleCount(s) }
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
var ionImageryAssetId: Double = 1 {
|
|
55
|
-
didSet { bridge?.updateImageryAssetId(
|
|
64
|
+
didSet { let v = Int64(ionImageryAssetId); postToRender { [weak self] in self?.bridge?.updateImageryAssetId(v) } }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── Optional perf / quality knobs ────────────────────────────────────────
|
|
68
|
+
var maximumCachedMiB: Double? {
|
|
69
|
+
didSet { if let v = maximumCachedMiB { postToRender { [weak self] in self?.bridge?.setMaximumCachedMiB(Int32(v)) } } }
|
|
70
|
+
}
|
|
71
|
+
var preloadAncestors: Bool? {
|
|
72
|
+
didSet { if let v = preloadAncestors { postToRender { [weak self] in self?.bridge?.setPreloadAncestors(v) } } }
|
|
73
|
+
}
|
|
74
|
+
var preloadSiblings: Bool? {
|
|
75
|
+
didSet { if let v = preloadSiblings { postToRender { [weak self] in self?.bridge?.setPreloadSiblings(v) } } }
|
|
76
|
+
}
|
|
77
|
+
var forbidHoles: Bool? {
|
|
78
|
+
didSet { if let v = forbidHoles { postToRender { [weak self] in self?.bridge?.setForbidHoles(v) } } }
|
|
79
|
+
}
|
|
80
|
+
var enableWaterMask: Bool? {
|
|
81
|
+
didSet { if let v = enableWaterMask { postToRender { [weak self] in self?.bridge?.setEnableWaterMask(v) } } }
|
|
82
|
+
}
|
|
83
|
+
var enableFogCulling: Bool? {
|
|
84
|
+
didSet { if let v = enableFogCulling { postToRender { [weak self] in self?.bridge?.setEnableFogCulling(v) } } }
|
|
85
|
+
}
|
|
86
|
+
var enforceCulledScreenSpaceError: Bool? {
|
|
87
|
+
didSet { if let v = enforceCulledScreenSpaceError { postToRender { [weak self] in self?.bridge?.setEnforceCulledScreenSpaceError(v) } } }
|
|
56
88
|
}
|
|
89
|
+
var culledScreenSpaceError: Double? {
|
|
90
|
+
didSet { if let v = culledScreenSpaceError { postToRender { [weak self] in self?.bridge?.setCulledScreenSpaceError(v) } } }
|
|
91
|
+
}
|
|
92
|
+
var enableLodTransitionPeriod: Bool? {
|
|
93
|
+
didSet { if let v = enableLodTransitionPeriod { postToRender { [weak self] in self?.bridge?.setEnableLodTransitionPeriod(v) } } }
|
|
94
|
+
}
|
|
95
|
+
var lodTransitionLength: Double? {
|
|
96
|
+
didSet { if let v = lodTransitionLength { postToRender { [weak self] in self?.bridge?.setLodTransitionLength(v) } } }
|
|
97
|
+
}
|
|
98
|
+
var sqliteCacheMaxRows: Double? {
|
|
99
|
+
didSet { if let v = sqliteCacheMaxRows { postToRender { [weak self] in self?.bridge?.setSqliteCacheMaxRows(Int32(v)) } } }
|
|
100
|
+
}
|
|
101
|
+
var taskProcessorThreads: Double? {
|
|
102
|
+
didSet { if let v = taskProcessorThreads { postToRender { [weak self] in self?.bridge?.setTaskProcessorThreads(Int32(v)) } } }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// MARK: - Render-thread dispatch helper
|
|
106
|
+
|
|
107
|
+
/// Posts a closure to the dedicated render queue. Used by every prop setter
|
|
108
|
+
/// that mutates engine state, so the EngineConfig + GPU resources are only
|
|
109
|
+
/// ever touched from one thread (renderQueue) — the render path itself, the
|
|
110
|
+
/// surface init, and bridge teardown all run there.
|
|
111
|
+
private func postToRender(_ action: @escaping () -> Void) {
|
|
112
|
+
renderQueue.async { action() }
|
|
113
|
+
}
|
|
114
|
+
|
|
57
115
|
var onMetrics: ((CesiumMetrics) -> Void)?
|
|
58
116
|
|
|
59
117
|
// MARK: - Methods
|
|
@@ -81,15 +139,19 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
81
139
|
}
|
|
82
140
|
|
|
83
141
|
func setCamera(camera: CameraState) throws {
|
|
84
|
-
// Runtime camera updates flow through this method
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
142
|
+
// Runtime camera updates flow through this method. We do *not* mutate
|
|
143
|
+
// `initialCamera` (it is construction-time only). If the view is not
|
|
144
|
+
// ready yet, the value is buffered in `pendingRuntimeCamera` and pushed
|
|
145
|
+
// during initialization.
|
|
146
|
+
pendingRuntimeCamera = camera
|
|
147
|
+
pendingRuntimeViewCorrection = nil
|
|
148
|
+
postToRender { [weak self] in self?.pushCameraStateIfChanged(camera) }
|
|
88
149
|
}
|
|
89
150
|
|
|
90
151
|
func setCameraQuaternion(camera: CameraState, viewCorrection: Quaternion) throws {
|
|
91
|
-
|
|
92
|
-
|
|
152
|
+
pendingRuntimeCamera = camera
|
|
153
|
+
pendingRuntimeViewCorrection = viewCorrection
|
|
154
|
+
postToRender { [weak self] in self?.pushCameraQuaternionIfChanged(camera, viewCorrection: viewCorrection) }
|
|
93
155
|
}
|
|
94
156
|
|
|
95
157
|
func getViewCorrection() throws -> Promise<Quaternion> {
|
|
@@ -120,8 +182,28 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
120
182
|
private var lastPushedCameraState: CameraState?
|
|
121
183
|
/// Last quaternion pushed via `setCameraQuaternion`; `nil` if only `setCamera` has been used.
|
|
122
184
|
private var lastPushedViewCorrection: Quaternion?
|
|
185
|
+
/// Camera state requested by `setCamera` before the bridge was ready.
|
|
186
|
+
private var pendingRuntimeCamera: CameraState?
|
|
187
|
+
private var pendingRuntimeViewCorrection: Quaternion?
|
|
123
188
|
private var lastBridgePixelSize: CGSize = .zero
|
|
124
189
|
|
|
190
|
+
/// Dedicated serial render queue. CADisplayLink fires on `.main`, but the
|
|
191
|
+
/// actual `bridge.shouldRenderNextFrame()` / `bridge.renderFrame(...)` work
|
|
192
|
+
/// is dispatched here so the main thread is never blocked on Cesium tile
|
|
193
|
+
/// loading or Metal command-buffer encoding. All bridge prop setters also
|
|
194
|
+
/// dispatch here so they serialize with rendering and never race with
|
|
195
|
+
/// engine state.
|
|
196
|
+
private let renderQueue = DispatchQueue(
|
|
197
|
+
label: "com.margelo.cesium.render",
|
|
198
|
+
qos: .userInteractive
|
|
199
|
+
)
|
|
200
|
+
/// Drops a CADisplayLink tick if the render queue is still finishing the
|
|
201
|
+
/// previous frame — keeps it from queuing up an unbounded backlog under
|
|
202
|
+
/// stutter (Metal's frameSemaphore would already throttle, but this saves
|
|
203
|
+
/// the dispatch hop and keeps `dt` accurate).
|
|
204
|
+
private var renderInFlight = false
|
|
205
|
+
private let renderInFlightLock = NSLock()
|
|
206
|
+
|
|
125
207
|
var view: UIView { metalView }
|
|
126
208
|
|
|
127
209
|
override init() {
|
|
@@ -185,7 +267,17 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
185
267
|
if !ionAccessToken.isEmpty {
|
|
186
268
|
bridge?.updateIonAccessToken(ionAccessToken, assetId: Int64(ionAssetId))
|
|
187
269
|
}
|
|
270
|
+
// Apply construction-time seed first; if the consumer already invoked
|
|
271
|
+
// setCamera / setCameraQuaternion before we were ready, replay it last so
|
|
272
|
+
// the runtime value wins.
|
|
188
273
|
pushCameraStateIfChanged(initialCamera)
|
|
274
|
+
if let runtime = pendingRuntimeCamera {
|
|
275
|
+
if let q = pendingRuntimeViewCorrection {
|
|
276
|
+
pushCameraQuaternionIfChanged(runtime, viewCorrection: q)
|
|
277
|
+
} else {
|
|
278
|
+
pushCameraStateIfChanged(runtime)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
189
281
|
if ionImageryAssetId != 1 {
|
|
190
282
|
bridge?.updateImageryAssetId(Int64(ionImageryAssetId))
|
|
191
283
|
}
|
|
@@ -215,6 +307,18 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
215
307
|
bridge?.setMaximumScreenSpaceError(maximumScreenSpaceError)
|
|
216
308
|
bridge?.setMaximumSimultaneousTileLoads(Int32(maximumSimultaneousTileLoads))
|
|
217
309
|
bridge?.setLoadingDescendantLimit(Int32(loadingDescendantLimit))
|
|
310
|
+
if let v = maximumCachedMiB { bridge?.setMaximumCachedMiB(Int32(v)) }
|
|
311
|
+
if let v = preloadAncestors { bridge?.setPreloadAncestors(v) }
|
|
312
|
+
if let v = preloadSiblings { bridge?.setPreloadSiblings(v) }
|
|
313
|
+
if let v = forbidHoles { bridge?.setForbidHoles(v) }
|
|
314
|
+
if let v = enableWaterMask { bridge?.setEnableWaterMask(v) }
|
|
315
|
+
if let v = enableFogCulling { bridge?.setEnableFogCulling(v) }
|
|
316
|
+
if let v = enforceCulledScreenSpaceError { bridge?.setEnforceCulledScreenSpaceError(v) }
|
|
317
|
+
if let v = culledScreenSpaceError { bridge?.setCulledScreenSpaceError(v) }
|
|
318
|
+
if let v = enableLodTransitionPeriod { bridge?.setEnableLodTransitionPeriod(v) }
|
|
319
|
+
if let v = lodTransitionLength { bridge?.setLodTransitionLength(v) }
|
|
320
|
+
if let v = sqliteCacheMaxRows { bridge?.setSqliteCacheMaxRows(Int32(v)) }
|
|
321
|
+
if let v = taskProcessorThreads { bridge?.setTaskProcessorThreads(Int32(v)) }
|
|
218
322
|
}
|
|
219
323
|
|
|
220
324
|
/// Pushes camera state into native bridge only when values changed.
|
|
@@ -302,54 +406,107 @@ class HybridCesiumView: HybridCesiumViewSpec {
|
|
|
302
406
|
|
|
303
407
|
let dt = max(dl.targetTimestamp - dl.timestamp, 1.0 / 120.0)
|
|
304
408
|
|
|
409
|
+
// metalView.bounds / drawableSize are UIKit, must stay on main.
|
|
305
410
|
let scale = metalView.contentScaleFactor
|
|
306
411
|
let w = Int(metalView.bounds.width * scale)
|
|
307
412
|
let h = Int(metalView.bounds.height * scale)
|
|
308
|
-
|
|
413
|
+
var didResize = false
|
|
309
414
|
if w > 0 && h > 0 {
|
|
310
415
|
let pixelSize = CGSize(width: w, height: h)
|
|
311
416
|
if lastBridgePixelSize != pixelSize {
|
|
312
417
|
metalView.drawableSize = pixelSize
|
|
313
418
|
lastBridgePixelSize = pixelSize
|
|
314
|
-
|
|
315
|
-
bridge.markNeedsRender()
|
|
419
|
+
didResize = true
|
|
316
420
|
}
|
|
317
421
|
}
|
|
318
422
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
423
|
+
// Throttle: drop the tick if the render queue hasn't finished the previous
|
|
424
|
+
// frame yet. This keeps the dispatch backlog at zero and lets the next
|
|
425
|
+
// CADisplayLink fire pick up a fresh dt.
|
|
426
|
+
renderInFlightLock.lock()
|
|
427
|
+
if renderInFlight {
|
|
428
|
+
renderInFlightLock.unlock()
|
|
429
|
+
return
|
|
430
|
+
}
|
|
431
|
+
renderInFlight = true
|
|
432
|
+
renderInFlightLock.unlock()
|
|
433
|
+
|
|
434
|
+
let resizedW = w
|
|
435
|
+
let resizedH = h
|
|
436
|
+
let weakSelf = self // captured for main-thread post-frame work
|
|
437
|
+
renderQueue.async { [weak self, weak bridge] in
|
|
438
|
+
guard let self = self, let bridge = bridge else {
|
|
439
|
+
weakSelf.renderInFlightLock.lock()
|
|
440
|
+
weakSelf.renderInFlight = false
|
|
441
|
+
weakSelf.renderInFlightLock.unlock()
|
|
442
|
+
return
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if didResize {
|
|
446
|
+
bridge.resize(Int32(resizedW), height: Int32(resizedH))
|
|
330
447
|
bridge.markNeedsRender()
|
|
331
448
|
}
|
|
332
|
-
}
|
|
333
449
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
450
|
+
let shouldRenderNow = bridge.shouldRenderNextFrame()
|
|
451
|
+
let nextIsIdle: Bool
|
|
452
|
+
if shouldRenderNow {
|
|
453
|
+
self.idleProbeAccumulator = 0
|
|
454
|
+
bridge.renderFrame(withDt: dt)
|
|
455
|
+
nextIsIdle = false
|
|
456
|
+
} else {
|
|
457
|
+
self.idleProbeAccumulator += dt
|
|
458
|
+
if self.idleProbeAccumulator >= 0.25 {
|
|
459
|
+
// Safety probe: occasionally tick engine state for late tile completions.
|
|
460
|
+
self.idleProbeAccumulator = 0
|
|
461
|
+
bridge.markNeedsRender()
|
|
462
|
+
}
|
|
463
|
+
nextIsIdle = true
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
self.metricsFrameCounter += 1
|
|
467
|
+
let shouldEmitMetrics =
|
|
468
|
+
self.metricsFrameCounter >= 20 && self.onMetrics != nil
|
|
469
|
+
let metricsSnapshot: CesiumMetrics? = shouldEmitMetrics ? CesiumMetrics(
|
|
338
470
|
fps: bridge.metricsFps,
|
|
339
471
|
tilesRendered: Double(bridge.metricsTilesRendered),
|
|
340
472
|
tilesLoading: Double(bridge.metricsTilesLoading),
|
|
341
473
|
tilesVisited: Double(bridge.metricsTilesVisited),
|
|
342
474
|
ionTokenConfigured: bridge.metricsIonTokenConfigured,
|
|
475
|
+
tlsConfigured: bridge.metricsTlsConfigured,
|
|
343
476
|
tilesetReady: bridge.metricsTilesetReady,
|
|
344
477
|
creditsPlainText: bridge.metricsCreditsPlainText
|
|
345
|
-
)
|
|
346
|
-
|
|
478
|
+
) : nil
|
|
479
|
+
if shouldEmitMetrics { self.metricsFrameCounter = 0 }
|
|
480
|
+
|
|
481
|
+
// Hop back to main to update CADisplayLink rate (UIKit) and emit the
|
|
482
|
+
// metrics callback (consumer may touch UI from it).
|
|
483
|
+
DispatchQueue.main.async { [weak self] in
|
|
484
|
+
guard let self = self else { return }
|
|
485
|
+
self.setDisplayLinkFrameRate(idle: nextIsIdle)
|
|
486
|
+
if let m = metricsSnapshot, let cb = self.onMetrics {
|
|
487
|
+
cb(m)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
self.renderInFlightLock.lock()
|
|
492
|
+
self.renderInFlight = false
|
|
493
|
+
self.renderInFlightLock.unlock()
|
|
347
494
|
}
|
|
348
495
|
}
|
|
349
496
|
|
|
350
497
|
deinit {
|
|
351
498
|
layoutPollTimer?.invalidate()
|
|
352
499
|
displayLink?.invalidate()
|
|
353
|
-
|
|
500
|
+
|
|
501
|
+
// Drain the render queue so we don't release `bridge` while it's
|
|
502
|
+
// mid-encode. `sync` here is bounded by Metal's frameSemaphore wait —
|
|
503
|
+
// which itself is already bounded to 1 s in MetalBackend::shutdown().
|
|
504
|
+
let bridgeRef = bridge
|
|
505
|
+
bridge = nil
|
|
506
|
+
if let b = bridgeRef {
|
|
507
|
+
renderQueue.sync {
|
|
508
|
+
b.shutdown()
|
|
509
|
+
}
|
|
510
|
+
}
|
|
354
511
|
}
|
|
355
512
|
}
|
|
@@ -304,15 +304,19 @@ fragment float4 skyFragment(SkyVOut in [[stage_in]],
|
|
|
304
304
|
float3 org=u.cameraEcef.xyz;
|
|
305
305
|
float2 at=rsi(org,rd,AR);
|
|
306
306
|
if(at.y<0)return float4(0,0,0,1);
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
// No earth-surface tmax clamp — that creates a visible band discontinuity
|
|
308
|
+
// at the geometric horizon. Integrate full atmospheric path and clamp
|
|
309
|
+
// underground sample heights to zero (ground-level density).
|
|
310
|
+
float tmax=at.y;
|
|
309
311
|
float tmin=max(at.x,0.f);if(tmin>=tmax)return float4(0,0,0,1);
|
|
310
|
-
|
|
312
|
+
// Halved from 16/4 to 8/2 — visually negligible at typical phone DPI
|
|
313
|
+
// (atmospheric scattering banding is sub-pixel at this sample count).
|
|
314
|
+
const int S=8,L=2;
|
|
311
315
|
float ss=(tmax-tmin)/float(S);
|
|
312
316
|
float3 rayl=0,miel=0;float oR=0,oM=0;
|
|
313
317
|
for(int i=0;i<S;++i){
|
|
314
318
|
float t=tmin+(float(i)+.5f)*ss;
|
|
315
|
-
float3 sp=org+rd*t;float h=length(sp)-ER;
|
|
319
|
+
float3 sp=org+rd*t;float h=max(0.f,length(sp)-ER);
|
|
316
320
|
float hr=exp(-h/10000.f)*ss,hm=exp(-h/3200.f)*ss;
|
|
317
321
|
oR+=hr;oM+=hm;
|
|
318
322
|
float2 lh=rsi(sp,u.lightDir.xyz,AR);
|
|
@@ -330,11 +334,16 @@ fragment float4 skyFragment(SkyVOut in [[stage_in]],
|
|
|
330
334
|
float rPh=.75f*(1+cos2);
|
|
331
335
|
float g2=MG*MG,mPh=1.5f*((1-g2)/(2+g2))*(1+cos2)/pow(1+g2-2*MG*cosT,1.5f);
|
|
332
336
|
float3 col=LINT*(rayl*RAY*rPh+miel*MIE3*mPh);
|
|
333
|
-
col=1-exp(-col*1.1f);
|
|
334
|
-
float3
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
337
|
+
col=1-exp(-col*1.1f);
|
|
338
|
+
col*=float3(.30f,.55f,1.f);
|
|
339
|
+
// Single-scatter atmosphere produces sunset-like yellow at horizons with
|
|
340
|
+
// long path lengths (because blue out-scatters faster). Real daytime sky
|
|
341
|
+
// appears whitish-blue at horizon thanks to multiple scattering, which we
|
|
342
|
+
// approximate here by blending toward a natural blue based on the
|
|
343
|
+
// total atmospheric path length traversed by the view ray.
|
|
344
|
+
float pathLen=tmax-tmin;
|
|
345
|
+
float hazeFactor=smoothstep(100000.f,600000.f,pathLen);
|
|
346
|
+
col=mix(col,float3(.35f,.58f,.90f),hazeFactor*.65f);
|
|
338
347
|
return float4(col,1.f);
|
|
339
348
|
}
|
|
340
349
|
)MSL";
|
|
@@ -409,8 +418,6 @@ void MetalBackend::buildRenderPipelines() {
|
|
|
409
418
|
CAMetalLayer* layer = (__bridge CAMetalLayer*)metalLayer_;
|
|
410
419
|
const MTLPixelFormat colorFmt = layer.pixelFormat;
|
|
411
420
|
|
|
412
|
-
NSError* err = nil;
|
|
413
|
-
|
|
414
421
|
if (terrainPipeline_) {
|
|
415
422
|
CFRelease(terrainPipeline_);
|
|
416
423
|
terrainPipeline_ = nullptr;
|
|
@@ -420,9 +427,16 @@ void MetalBackend::buildRenderPipelines() {
|
|
|
420
427
|
skyPipeline_ = nullptr;
|
|
421
428
|
}
|
|
422
429
|
|
|
430
|
+
// Use a separate NSError* per compile + a strict result check. Sharing a
|
|
431
|
+
// single `err` across multiple operations conflated unrelated failures
|
|
432
|
+
// (P2-error-handling).
|
|
433
|
+
NSError* terrainLibErr = nil;
|
|
423
434
|
id<MTLLibrary> tLib = [dev newLibraryWithSource:kTerrainShaderSrc
|
|
424
|
-
options:nil error:&
|
|
425
|
-
if (
|
|
435
|
+
options:nil error:&terrainLibErr];
|
|
436
|
+
if (!tLib) {
|
|
437
|
+
NSLog(@"[MetalBackend] terrain shader compilation FAILED: %@", terrainLibErr);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
426
440
|
|
|
427
441
|
MTLRenderPipelineDescriptor* tDesc = [MTLRenderPipelineDescriptor new];
|
|
428
442
|
tDesc.vertexFunction = [tLib newFunctionWithName:@"terrainVertex"];
|
|
@@ -430,13 +444,22 @@ void MetalBackend::buildRenderPipelines() {
|
|
|
430
444
|
tDesc.colorAttachments[0].pixelFormat = colorFmt;
|
|
431
445
|
tDesc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
|
|
432
446
|
tDesc.rasterSampleCount = (NSUInteger)std::max(1, sampleCount_);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
447
|
+
NSError* terrainPipelineErr = nil;
|
|
448
|
+
id<MTLRenderPipelineState> terrainPipeline =
|
|
449
|
+
[dev newRenderPipelineStateWithDescriptor:tDesc error:&terrainPipelineErr];
|
|
450
|
+
if (!terrainPipeline) {
|
|
451
|
+
NSLog(@"[MetalBackend] terrain pipeline build FAILED: %@", terrainPipelineErr);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
terrainPipeline_ = (__bridge_retained void*)terrainPipeline;
|
|
436
455
|
|
|
456
|
+
NSError* skyLibErr = nil;
|
|
437
457
|
id<MTLLibrary> sLib = [dev newLibraryWithSource:kSkyShaderSrc
|
|
438
|
-
options:nil error:&
|
|
439
|
-
if (
|
|
458
|
+
options:nil error:&skyLibErr];
|
|
459
|
+
if (!sLib) {
|
|
460
|
+
NSLog(@"[MetalBackend] sky shader compilation FAILED: %@", skyLibErr);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
440
463
|
|
|
441
464
|
MTLRenderPipelineDescriptor* sDesc = [MTLRenderPipelineDescriptor new];
|
|
442
465
|
sDesc.vertexFunction = [sLib newFunctionWithName:@"skyVertex"];
|
|
@@ -444,9 +467,14 @@ void MetalBackend::buildRenderPipelines() {
|
|
|
444
467
|
sDesc.colorAttachments[0].pixelFormat = colorFmt;
|
|
445
468
|
sDesc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
|
|
446
469
|
sDesc.rasterSampleCount = (NSUInteger)std::max(1, sampleCount_);
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
470
|
+
NSError* skyPipelineErr = nil;
|
|
471
|
+
id<MTLRenderPipelineState> skyPipeline =
|
|
472
|
+
[dev newRenderPipelineStateWithDescriptor:sDesc error:&skyPipelineErr];
|
|
473
|
+
if (!skyPipeline) {
|
|
474
|
+
NSLog(@"[MetalBackend] sky pipeline build FAILED: %@", skyPipelineErr);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
skyPipeline_ = (__bridge_retained void*)skyPipeline;
|
|
450
478
|
|
|
451
479
|
if (!terrainDepthState_) {
|
|
452
480
|
MTLDepthStencilDescriptor* dd = [MTLDepthStencilDescriptor new];
|
|
@@ -473,8 +501,20 @@ void MetalBackend::setMsaaSampleCount(int sc) {
|
|
|
473
501
|
|
|
474
502
|
if (frameSemaphore_) {
|
|
475
503
|
dispatch_semaphore_t sem = (__bridge dispatch_semaphore_t)frameSemaphore_;
|
|
504
|
+
// Bound the wait per slot at 1 second so a stuck GPU encode (the only
|
|
505
|
+
// realistic cause of a missed completion handler) cannot wedge the UI
|
|
506
|
+
// thread forever. On timeout we proceed regardless: the worst that can
|
|
507
|
+
// happen is one frame's worth of pipeline rebuild lands on a slot the
|
|
508
|
+
// GPU is still using, which Metal handles gracefully (the prior
|
|
509
|
+
// pipeline stays alive via ARC until the encoder finishes).
|
|
476
510
|
for (int i = 0; i < kMaxFramesInFlight; ++i) {
|
|
477
|
-
|
|
511
|
+
dispatch_time_t deadline = dispatch_time(DISPATCH_TIME_NOW,
|
|
512
|
+
(int64_t)NSEC_PER_SEC);
|
|
513
|
+
if (dispatch_semaphore_wait(sem, deadline) != 0) {
|
|
514
|
+
NSLog(@"[CesiumMetal] MSAA-change semaphore timed out (slot %d); "
|
|
515
|
+
@"proceeding with rebuild", i);
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
478
518
|
}
|
|
479
519
|
}
|
|
480
520
|
|
|
@@ -499,10 +539,19 @@ void MetalBackend::resize(int width, int height) {
|
|
|
499
539
|
void MetalBackend::shutdown() {
|
|
500
540
|
// Drain in-flight frames: wait until all GPU completion handlers have fired
|
|
501
541
|
// before releasing the semaphore and the persistent buffers they reference.
|
|
542
|
+
// Bounded wait — if a slot doesn't release in 1 s we are almost certainly
|
|
543
|
+
// looking at a hung GPU command. Forcing release lets the app exit/teardown
|
|
544
|
+
// cleanly rather than ANRing on backgrounding.
|
|
502
545
|
if (frameSemaphore_) {
|
|
503
546
|
dispatch_semaphore_t sem = (__bridge dispatch_semaphore_t)frameSemaphore_;
|
|
504
547
|
for (int i = 0; i < kMaxFramesInFlight; ++i) {
|
|
505
|
-
|
|
548
|
+
dispatch_time_t deadline = dispatch_time(DISPATCH_TIME_NOW,
|
|
549
|
+
(int64_t)NSEC_PER_SEC);
|
|
550
|
+
if (dispatch_semaphore_wait(sem, deadline) != 0) {
|
|
551
|
+
NSLog(@"[CesiumMetal] shutdown semaphore wait timed out at slot %d; "
|
|
552
|
+
@"force-releasing and continuing teardown", i);
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
506
555
|
}
|
|
507
556
|
CFRelease(frameSemaphore_);
|
|
508
557
|
frameSemaphore_ = nullptr;
|
|
@@ -26,6 +26,8 @@ export interface CesiumMetrics {
|
|
|
26
26
|
tilesLoading: number;
|
|
27
27
|
tilesVisited: number;
|
|
28
28
|
ionTokenConfigured: boolean;
|
|
29
|
+
/** True when a CA bundle has been resolved for libcurl TLS. */
|
|
30
|
+
tlsConfigured: boolean;
|
|
29
31
|
tilesetReady: boolean;
|
|
30
32
|
creditsPlainText: string;
|
|
31
33
|
}
|
|
@@ -41,6 +43,30 @@ export interface CesiumViewProps extends HybridViewProps {
|
|
|
41
43
|
/** 1 = off; 2 or 4 = MSAA when supported. */
|
|
42
44
|
msaaSampleCount: number;
|
|
43
45
|
ionImageryAssetId: number;
|
|
46
|
+
/** RAM budget for live tileset, in mebibytes. Default 256. */
|
|
47
|
+
maximumCachedMiB?: number;
|
|
48
|
+
/** Pre-load ancestor tiles around the visible set (smoother panning, more loads). Default true. */
|
|
49
|
+
preloadAncestors?: boolean;
|
|
50
|
+
/** Pre-load sibling tiles around the visible set. Default true. */
|
|
51
|
+
preloadSiblings?: boolean;
|
|
52
|
+
/** Refuse to render holes in the terrain. Default true. Relax for fast pans. */
|
|
53
|
+
forbidHoles?: boolean;
|
|
54
|
+
/** Decode water-mask textures (coastline shading). Default true. */
|
|
55
|
+
enableWaterMask?: boolean;
|
|
56
|
+
/** Cull tiles fully inside the fog volume. Default false. */
|
|
57
|
+
enableFogCulling?: boolean;
|
|
58
|
+
/** When fog culling is on, override SSE for fogged tiles. Default true. */
|
|
59
|
+
enforceCulledScreenSpaceError?: boolean;
|
|
60
|
+
/** SSE applied to fogged tiles when `enforceCulledScreenSpaceError` is true. Default 64. */
|
|
61
|
+
culledScreenSpaceError?: number;
|
|
62
|
+
/** Cross-fade between LODs when refining (smoother pop-in). Default false. */
|
|
63
|
+
enableLodTransitionPeriod?: boolean;
|
|
64
|
+
/** Length (s) of the LOD cross-fade. Default 1. */
|
|
65
|
+
lodTransitionLength?: number;
|
|
66
|
+
/** Sqlite asset cache row budget. Default 4096. */
|
|
67
|
+
sqliteCacheMaxRows?: number;
|
|
68
|
+
/** Worker thread count. 0 = auto (hardware_concurrency-1, clamped 2..8). */
|
|
69
|
+
taskProcessorThreads?: number;
|
|
44
70
|
onMetrics?: (metrics: CesiumMetrics) => void;
|
|
45
71
|
}
|
|
46
72
|
export interface CesiumViewMethods extends HybridViewMethods {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cesium-view.nitro.d.ts","sourceRoot":"","sources":["../../../../src/specs/cesium-view.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,4BAA4B,CAAA;AAEnC,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,YAAY,EAAE,OAAO,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,aAAa,EAAE,WAAW,CAAA;IAC1B,cAAc,EAAE,OAAO,CAAA;IACvB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,4BAA4B,EAAE,MAAM,CAAA;IACpC,sBAAsB,EAAE,MAAM,CAAA;IAC9B,6CAA6C;IAC7C,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;CAC7C;AAED,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,+CAA+C;IAC/C,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAAA;IACtC;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACpC;;;OAGG;IACH,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1E,4FAA4F;IAC5F,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA;CACzC;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"cesium-view.nitro.d.ts","sourceRoot":"","sources":["../../../../src/specs/cesium-view.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,4BAA4B,CAAA;AAEnC,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,+DAA+D;IAC/D,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,aAAa,EAAE,WAAW,CAAA;IAC1B,cAAc,EAAE,OAAO,CAAA;IACvB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,4BAA4B,EAAE,MAAM,CAAA;IACpC,sBAAsB,EAAE,MAAM,CAAA;IAC9B,6CAA6C;IAC7C,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IAGzB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,mEAAmE;IACnE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,2EAA2E;IAC3E,6BAA6B,CAAC,EAAE,OAAO,CAAA;IACvC,4FAA4F;IAC5F,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,8EAA8E;IAC9E,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,mDAAmD;IACnD,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,4EAA4E;IAC5E,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAE7B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;CAC7C;AAED,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,+CAA+C;IAC/C,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAAA;IACtC;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACpC;;;OAGG;IACH,mBAAmB,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1E,4FAA4F;IAC5F,iBAAiB,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA;CACzC;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA"}
|
|
@@ -41,6 +41,8 @@ namespace margelo::nitro::reactnativecesium {
|
|
|
41
41
|
double tilesVisited = this->getFieldValue(fieldTilesVisited);
|
|
42
42
|
static const auto fieldIonTokenConfigured = clazz->getField<jboolean>("ionTokenConfigured");
|
|
43
43
|
jboolean ionTokenConfigured = this->getFieldValue(fieldIonTokenConfigured);
|
|
44
|
+
static const auto fieldTlsConfigured = clazz->getField<jboolean>("tlsConfigured");
|
|
45
|
+
jboolean tlsConfigured = this->getFieldValue(fieldTlsConfigured);
|
|
44
46
|
static const auto fieldTilesetReady = clazz->getField<jboolean>("tilesetReady");
|
|
45
47
|
jboolean tilesetReady = this->getFieldValue(fieldTilesetReady);
|
|
46
48
|
static const auto fieldCreditsPlainText = clazz->getField<jni::JString>("creditsPlainText");
|
|
@@ -51,6 +53,7 @@ namespace margelo::nitro::reactnativecesium {
|
|
|
51
53
|
tilesLoading,
|
|
52
54
|
tilesVisited,
|
|
53
55
|
static_cast<bool>(ionTokenConfigured),
|
|
56
|
+
static_cast<bool>(tlsConfigured),
|
|
54
57
|
static_cast<bool>(tilesetReady),
|
|
55
58
|
creditsPlainText->toStdString()
|
|
56
59
|
);
|
|
@@ -62,7 +65,7 @@ namespace margelo::nitro::reactnativecesium {
|
|
|
62
65
|
*/
|
|
63
66
|
[[maybe_unused]]
|
|
64
67
|
static jni::local_ref<JCesiumMetrics::javaobject> fromCpp(const CesiumMetrics& value) {
|
|
65
|
-
using JSignature = JCesiumMetrics(double, double, double, double, jboolean, jboolean, jni::alias_ref<jni::JString>);
|
|
68
|
+
using JSignature = JCesiumMetrics(double, double, double, double, jboolean, jboolean, jboolean, jni::alias_ref<jni::JString>);
|
|
66
69
|
static const auto clazz = javaClassStatic();
|
|
67
70
|
static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
|
|
68
71
|
return create(
|
|
@@ -72,6 +75,7 @@ namespace margelo::nitro::reactnativecesium {
|
|
|
72
75
|
value.tilesLoading,
|
|
73
76
|
value.tilesVisited,
|
|
74
77
|
value.ionTokenConfigured,
|
|
78
|
+
value.tlsConfigured,
|
|
75
79
|
value.tilesetReady,
|
|
76
80
|
jni::make_jstring(value.creditsPlainText)
|
|
77
81
|
);
|