test: validate particle camera wrap and ocean mask

This commit is contained in:
OpenAI Codex
2026-08-30 10:27:24 +08:00
parent 3b5a147bba
commit 8b4c5c6d71
16 changed files with 572 additions and 55 deletions

View File

@@ -10,6 +10,7 @@ import org.maplibre.android.geometry.LatLng
import org.maplibre.android.maps.MapView
import org.maplibre.android.maps.MapLibreMap
import org.maplibre.android.maps.Style
import org.maplibre.android.style.layers.PaintPropertyValue
import org.maplibre.android.testapp.R
/** VALIDATION ONLY: Android OpenGL host for the 30-01/30-02 Core RenderLayer experiments. */
@@ -19,14 +20,16 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
private lateinit var status: TextView
private var active = true
private var enabled = true
private var maskMode = MASK_GLOBAL
override fun onCreate(savedInstanceState: Bundle?) {
active = savedInstanceState?.getBoolean(STATE_ACTIVE, true) ?: true
enabled = savedInstanceState?.getBoolean(STATE_ENABLED, true) ?: true
maskMode = savedInstanceState?.getInt(STATE_MASK_MODE, MASK_GLOBAL) ?: MASK_GLOBAL
super.onCreate(savedInstanceState)
Log.i(
TAG,
"ParticleValidation30_02: Activity state restored active=$active enabled=$enabled " +
"ParticleValidation30_03: Activity state restored active=$active enabled=$enabled maskMode=$maskMode " +
"recreated=${savedInstanceState != null}"
)
setContentView(R.layout.activity_particle_core_layer_validation)
@@ -46,10 +49,10 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
}
findViewById<Button>(R.id.validationActive).setOnClickListener {
if (this::maplibreMap.isInitialized) loadValidationStyle(active = true, enabled = enabled)
if (this::maplibreMap.isInitialized) setValidationProperties(active = true, maskMode = maskMode)
}
findViewById<Button>(R.id.validationStatic).setOnClickListener {
if (this::maplibreMap.isInitialized) loadValidationStyle(active = false, enabled = enabled)
if (this::maplibreMap.isInitialized) setValidationProperties(active = false, maskMode = maskMode)
}
findViewById<Button>(R.id.validationDisable).setOnClickListener {
if (this::maplibreMap.isInitialized) loadValidationStyle(active = active, enabled = false)
@@ -57,28 +60,63 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
findViewById<Button>(R.id.validationEnable).setOnClickListener {
if (this::maplibreMap.isInitialized) loadValidationStyle(active = active, enabled = true)
}
findViewById<Button>(R.id.validationGlobal).setOnClickListener {
if (this::maplibreMap.isInitialized) setValidationProperties(active = active, maskMode = MASK_GLOBAL)
}
findViewById<Button>(R.id.validationOceanA).setOnClickListener {
if (this::maplibreMap.isInitialized) setValidationProperties(active = active, maskMode = MASK_OCEAN_A)
}
findViewById<Button>(R.id.validationOceanB).setOnClickListener {
if (this::maplibreMap.isInitialized) setValidationProperties(active = active, maskMode = MASK_OCEAN_B)
}
findViewById<Button>(R.id.validationDateline).setOnClickListener {
maplibreMap.cameraPosition = CameraPosition.Builder().target(LatLng(0.0, 179.0)).zoom(2.0).build()
Log.i(TAG, "ParticleValidation30_03: DATELINE preset center=0,179 zoom=2")
}
findViewById<Button>(R.id.validationWorldWrap).setOnClickListener {
maplibreMap.cameraPosition = CameraPosition.Builder().target(LatLng(0.0, 0.0)).zoom(0.0).build()
Log.i(TAG, "ParticleValidation30_03: WORLD_WRAP preset center=0,0 zoom=0")
}
}
private fun loadValidationStyle(active: Boolean, enabled: Boolean) {
this.active = active
this.enabled = enabled
val state = if (!enabled) "DISABLED" else if (active) "ACTIVE" else "STATIC"
Log.i(TAG, "ParticleValidation30_02: Test App switching to $state")
val state = statusText()
Log.i(TAG, "ParticleValidation30_03: Test App switching to $state")
maplibreMap.setStyle(Style.Builder().fromJson(validationStyle(active, enabled))) {
status.text = getString(
when {
!enabled -> R.string.particle_validation_disabled_status
active -> R.string.particle_validation_active_status
else -> R.string.particle_validation_static_status
}
)
status.text = state
}
}
private fun setValidationProperties(active: Boolean, maskMode: Int) {
this.active = active
this.maskMode = maskMode
val layer = maplibreMap.style?.getLayer(PARTICLE_LAYER_ID)
if (layer == null || !enabled) {
loadValidationStyle(active, enabled)
return
}
layer.setProperties(
PaintPropertyValue("particle-validation-active", active),
PaintPropertyValue("particle-validation-mask-mode", maskMode)
)
status.text = statusText()
Log.i(TAG, "ParticleValidation30_03: property update active=$active maskMode=$maskMode resourceReuseExpected=true")
}
private fun statusText(): String = when {
!enabled -> getString(R.string.particle_validation_disabled_status)
maskMode == MASK_OCEAN_A -> getString(R.string.particle_validation_ocean_a_status)
maskMode == MASK_OCEAN_B -> getString(R.string.particle_validation_ocean_b_status)
active -> getString(R.string.particle_validation_global_active_status)
else -> getString(R.string.particle_validation_global_static_status)
}
private fun validationStyle(active: Boolean, enabled: Boolean): String {
val particleLayer = if (enabled) {
"""{"id":"particle-validation-core","type":"particle-validation",
"paint":{"particle-validation-active":$active}},"""
"paint":{"particle-validation-active":$active,"particle-validation-mask-mode":$maskMode}},"""
} else {
""
}
@@ -114,6 +152,7 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(STATE_ACTIVE, active)
outState.putBoolean(STATE_ENABLED, enabled)
outState.putInt(STATE_MASK_MODE, maskMode)
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
@@ -122,5 +161,10 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
private const val TAG = "ParticleValidation"
private const val STATE_ACTIVE = "particle_validation.active"
private const val STATE_ENABLED = "particle_validation.enabled"
private const val STATE_MASK_MODE = "particle_validation.mask_mode"
private const val PARTICLE_LAYER_ID = "particle-validation-core"
private const val MASK_GLOBAL = 0
private const val MASK_OCEAN_A = 1
private const val MASK_OCEAN_B = 2
}
}

View File

@@ -63,6 +63,53 @@
android:layout_weight="1"
android:text="@string/particle_validation_enable" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/validationGlobal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/particle_validation_global" />
<Button
android:id="@+id/validationOceanA"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/particle_validation_ocean_a" />
<Button
android:id="@+id/validationOceanB"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/particle_validation_ocean_b" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/validationDateline"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/particle_validation_dateline" />
<Button
android:id="@+id/validationWorldWrap"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/particle_validation_world_wrap" />
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -17,4 +17,13 @@
<string name="particle_validation_active_status">30-02 ACTIVE: GPU State/Trail ping-pong requests frames. Move, zoom, rotate, pitch and resize.</string>
<string name="particle_validation_static_status">30-02 STATIC: GPU ping-pong stopped requesting frames. Gestures must still render normally.</string>
<string name="particle_validation_disabled_status">30-02 DISABLED: validation layer and its GPU resources were removed. Tap ENABLE to recreate them.</string>
<string name="particle_validation_global">GLOBAL</string>
<string name="particle_validation_ocean_a">OCEAN A</string>
<string name="particle_validation_ocean_b">OCEAN B</string>
<string name="particle_validation_dateline">DATELINE</string>
<string name="particle_validation_world_wrap">WORLD WRAP</string>
<string name="particle_validation_global_active_status">30-03 GLOBAL ACTIVE: current-frame Camera/world-wrap validation and GPU simulation.</string>
<string name="particle_validation_global_static_status">30-03 GLOBAL STATIC: simulation frozen; Camera redraw must keep the world mask aligned.</string>
<string name="particle_validation_ocean_a_status">30-03 OCEAN_ONLY_A: blue shared coastal-mask consumer.</string>
<string name="particle_validation_ocean_b_status">30-03 OCEAN_ONLY_B: green shared coastal-mask consumer.</string>
</resources>