merge(upgrade): port particle extensions onto official native 13.6.1 (unverified)

This commit is contained in:
tei
2026-10-09 09:37:07 +09:00
767 changed files with 85435 additions and 153 deletions

View File

@@ -3,6 +3,10 @@
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
#include <memory>
#include <list>
#include <tuple>
@@ -26,9 +30,15 @@
#include <mln/util/platform.hpp>
#include <mln/util/projection.hpp>
#include <mln/style/style.hpp>
#include <mln/style/layers/raster_particle_layer.hpp>
#include <mln/style/layers/weather_color_layer.hpp>
#include <mln/style/sources/raster_array_source.hpp>
#include <mln/style/image.hpp>
#include <mln/style/filter.hpp>
#include <mln/renderer/query.hpp>
#include <mln/renderer/render_segment_json.hpp>
#include <mln/particle/field/field_profile_contract_json.hpp>
#include <mln/particle/ingress/encoded_field_transport.hpp>
// Java -> C++ conversion
#include "style/android_conversion.hpp"
@@ -61,6 +71,8 @@
namespace mln {
namespace android {
namespace {}
NativeMapView::NativeMapView(jni::JNIEnv& _env,
const jni::Object<NativeMapView>& _obj,
const jni::Object<FileSource>& jFileSource,
@@ -704,6 +716,76 @@ jni::jboolean NativeMapView::getDebug(JNIEnv&) {
return map->getDebug() != DebugOptions::NoDebug;
}
void NativeMapView::setRetainedUnderlayEnabled(JNIEnv&, jni::jboolean enabled) {
map->setRetainedUnderlayEnabled(enabled);
}
jni::jboolean NativeMapView::setContinuousLayerRange(JNIEnv& env,
const jni::String& startLayerId,
const jni::String& endLayerId) {
return map->setContinuousLayerRange(jni::Make<std::string>(env, startLayerId),
jni::Make<std::string>(env, endLayerId));
}
jni::jboolean NativeMapView::setRenderSegmentPlan(JNIEnv& env, const jni::String& planJson) {
auto plan = renderSegmentPlanFromJSONOrInvalid(jni::Make<std::string>(env, planJson));
return map->setRenderSegmentPlan(std::move(plan));
}
jni::Local<jni::String> NativeMapView::getRenderSegmentDiagnostics(JNIEnv& env) {
return jni::Make<jni::String>(env, renderSegmentDiagnosticsToJSON(map->getRenderSegmentDiagnostics()));
}
jni::Local<jni::Array<jni::String>> NativeMapView::getRetainedUnderlayDiagnostics(JNIEnv& env) {
const auto snapshot = map->getRetainedUnderlayDiagnostics();
const std::array<std::string, 39> values = {
snapshot.enabled ? "true" : "false",
std::to_string(snapshot.build),
std::to_string(snapshot.reuse),
std::to_string(snapshot.fallback),
std::to_string(snapshot.invalidation),
snapshot.lastReason,
snapshot.rangeConfigured ? "true" : "false",
snapshot.rangeValid ? "true" : "false",
snapshot.startLayerId,
snapshot.endLayerId,
std::to_string(snapshot.startIndex),
std::to_string(snapshot.endIndex),
std::to_string(snapshot.continuousBegin),
std::to_string(snapshot.continuousEndExclusive),
snapshot.bottomPresent ? "true" : "false",
snapshot.bottomCacheState,
std::to_string(snapshot.bottomBuild),
std::to_string(snapshot.bottomReuse),
std::to_string(snapshot.bottomInvalidation),
snapshot.bottomLastInvalidationReason,
std::to_string(snapshot.bottomTextureCreate),
std::to_string(snapshot.bottomCompositeCreate),
std::to_string(snapshot.bottomResourceRelease),
snapshot.topPresent ? "true" : "false",
snapshot.topCacheState,
std::to_string(snapshot.topBuild),
std::to_string(snapshot.topReuse),
std::to_string(snapshot.topInvalidation),
snapshot.topLastInvalidationReason,
std::to_string(snapshot.topTextureCreate),
std::to_string(snapshot.topCompositeCreate),
std::to_string(snapshot.topResourceRelease),
snapshot.rangeFallback ? "true" : "false",
snapshot.fastPathEligible ? "true" : "false",
snapshot.fastPathActive ? "true" : "false",
snapshot.fastPathFallbackReason,
std::to_string(snapshot.fastPathHit),
std::to_string(snapshot.fastPathMiss),
std::to_string(snapshot.fullCpuFrame),
};
auto result = jni::Array<jni::String>::New(env, values.size());
for (std::size_t index = 0; index < values.size(); ++index) {
result.Set(env, index, jni::Make<jni::String>(env, values[index]));
}
return result;
}
jni::Local<jni::Array<jni::String>> NativeMapView::getActionJournalLogFiles(JNIEnv& env) {
const auto& actionJournal = map->getActionJournal();
if (!actionJournal) {
@@ -1104,6 +1186,340 @@ jni::Local<jni::Object<Layer>> NativeMapView::getLayer(JNIEnv& env, const jni::S
return LayerManagerAndroid::get()->createJavaLayerPeer(env, *coreLayer);
}
jni::jboolean NativeMapView::hasStyleLayer(JNIEnv& env, const jni::String& layerId) {
return map->getStyle().getLayer(jni::Make<std::string>(env, layerId)) != nullptr;
}
jni::jboolean NativeMapView::setStyleLayerFloatProperty(JNIEnv& env,
const jni::String& layerId,
const jni::String& propertyName,
const jni::jfloat value) {
auto* layer = map->getStyle().getLayer(jni::Make<std::string>(env, layerId));
if (!layer) return false;
const auto property = jni::Make<std::string>(env, propertyName);
if (property == "weather-color-field-value-source") {
auto* weatherColorLayer = dynamic_cast<mln::style::WeatherColorLayer*>(layer);
if (!weatherColorLayer || (value != 0.0f && value != 1.0f)) {
mln::Log::Error(mln::Event::JNI, "ParticleField: event=FIELD_VALUE_SOURCE_SET result=REJECTED");
return false;
}
weatherColorLayer->setFieldValueSource(value == 0.0f ? mln::style::FieldValueSource::Scalar
: mln::style::FieldValueSource::VectorMagnitude);
return true;
}
if (property != "raster-particle-time-mix" && property != "raster-particle-particle-count" &&
property != "raster-particle-line-width" && property != "raster-particle-particle-length" &&
property != "raster-particle-particle-opacity" && property != "raster-particle-trail-opacity" &&
property != "raster-particle-trail-fade" && property != "raster-particle-speed-color-enabled" &&
property != "raster-particle-advection-scale") {
mln::Log::Error(mln::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=UNSUPPORTED_PROPERTY");
return false;
}
auto* particleLayer = dynamic_cast<mln::style::RasterParticleLayer*>(layer);
if (!particleLayer) {
mln::Log::Error(mln::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=UNSUPPORTED_LAYER");
return false;
}
if (!std::isfinite(value)) {
mln::Log::Error(mln::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=INVALID_FLOAT");
return false;
}
if (property == "raster-particle-time-mix") {
particleLayer->setTimeMix(value);
} else if (property == "raster-particle-particle-count") {
if (value < 0.0f || std::floor(value) != value) {
mln::Log::Error(mln::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=INVALID_PARTICLE_COUNT");
return false;
}
const auto requestedCount = static_cast<uint32_t>(value);
particleLayer->setParticleCount(requestedCount);
if (particleLayer->getParticleCount() != requestedCount) {
mln::Log::Error(mln::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=INVALID_PARTICLE_COUNT");
return false;
}
} else if (property == "raster-particle-line-width") {
particleLayer->setLineWidth(value);
} else if (property == "raster-particle-particle-length") {
particleLayer->setParticleLength(value);
} else if (property == "raster-particle-particle-opacity") {
particleLayer->setParticleOpacity(value);
} else if (property == "raster-particle-trail-opacity") {
particleLayer->setTrailOpacity(value);
} else if (property == "raster-particle-trail-fade") {
particleLayer->setTrailFade(value);
} else if (property == "raster-particle-advection-scale") {
if (value <= 0.0f) return false;
particleLayer->setAdvectionScale(value);
} else {
if (value != 0.0f && value != 1.0f) {
mln::Log::Error(mln::Event::JNI, "ParticleGPU: event=STYLE_PROPERTY_SET result=INVALID_COLOR_MODE");
return false;
}
particleLayer->setSpeedColorEnabled(value > 0.5f);
}
mln::Log::Info(mln::Event::JNI,
"ParticleGPU: event=STYLE_PROPERTY_SET layerId=" + jni::Make<std::string>(env, layerId) +
" property=" + property + " value=" + std::to_string(value) + " result=SUCCESS");
return true;
}
jni::jboolean NativeMapView::setWeatherColorOpacity(JNIEnv& env,
const jni::String& layerId,
const jni::jfloat opacity) {
if (!std::isfinite(opacity)) return false;
auto* layer = dynamic_cast<mln::style::WeatherColorLayer*>(
map->getStyle().getLayer(jni::Make<std::string>(env, layerId)));
if (!layer) return false;
layer->setOpacity(opacity);
return true;
}
jni::jboolean NativeMapView::setStyleLayerVisibility(JNIEnv& env, const jni::String& layerId, const jni::jboolean visible) {
auto* layer = map->getStyle().getLayer(jni::Make<std::string>(env, layerId));
if (!layer) return false;
layer->setVisibility(visible ? mln::style::VisibilityType::Visible : mln::style::VisibilityType::None);
return true;
}
jni::jboolean NativeMapView::setRasterParticleColors(JNIEnv& env,
const jni::String& layerId,
const jni::Array<jni::jfloat>& particle,
const jni::Array<jni::jfloat>& trail) {
auto* layer = dynamic_cast<mln::style::RasterParticleLayer*>(map->getStyle().getLayer(jni::Make<std::string>(env, layerId)));
if (!layer || particle.Length(env) != 4 || trail.Length(env) != 4) return false;
std::array<float, 4> particleColor, trailColor;
particle.GetRegion(env, 0, particleColor);
trail.GetRegion(env, 0, trailColor);
if (!mln::style::validWeatherRGBA(particleColor) || !mln::style::validWeatherRGBA(trailColor)) return false;
layer->setParticleColor(particleColor);
layer->setTrailColor(trailColor);
return true;
}
jni::jboolean NativeMapView::setRasterParticleColor(JNIEnv& env,
const jni::String& layerId,
const jni::Array<jni::jfloat>& particle) {
auto* layer = dynamic_cast<mln::style::RasterParticleLayer*>(map->getStyle().getLayer(jni::Make<std::string>(env, layerId)));
if (!layer || particle.Length(env) != 4) return false;
std::array<float, 4> color;
particle.GetRegion(env, 0, color);
if (!mln::style::validWeatherRGBA(color)) return false;
layer->setParticleColor(color);
return true;
}
jni::jboolean NativeMapView::setRasterParticleTrailColor(JNIEnv& env,
const jni::String& layerId,
const jni::Array<jni::jfloat>& trail) {
auto* layer = dynamic_cast<mln::style::RasterParticleLayer*>(map->getStyle().getLayer(jni::Make<std::string>(env, layerId)));
if (!layer || trail.Length(env) != 4) return false;
std::array<float, 4> color;
trail.GetRegion(env, 0, color);
if (!mln::style::validWeatherRGBA(color)) return false;
layer->setTrailColor(color);
return true;
}
jni::jboolean NativeMapView::setRasterArraySourceTargetFps(JNIEnv& env,
const jni::String& sourceId,
const jni::jint targetFps) {
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env, sourceId)));
return source && source->setRuntimeTargetFps(static_cast<uint8_t>(targetFps));
}
jni::jint NativeMapView::getRasterArraySourceTargetFps(JNIEnv& env, const jni::String& sourceId) {
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env, sourceId)));
return source ? source->runtimeTargetFps() : 0;
}
jni::jboolean NativeMapView::setWeatherColorStops(JNIEnv& env,
const jni::String& layerId,
const jni::Array<jni::jfloat>& speeds,
const jni::Array<jni::jfloat>& rgba) {
auto* layer = dynamic_cast<mln::style::WeatherColorLayer*>(map->getStyle().getLayer(jni::Make<std::string>(env, layerId)));
const auto count = speeds.Length(env);
if (!layer || count < 2 || count > static_cast<jni::jsize>(mln::style::MaxWeatherColorStops) || rgba.Length(env) != count * 4) return false;
std::vector<float> speedValues(count), rgbaValues(static_cast<size_t>(count) * 4);
speeds.GetRegion(env, 0, speedValues);
rgba.GetRegion(env, 0, rgbaValues);
std::vector<mln::style::WeatherColorStop> stops;
stops.reserve(count);
for (jni::jsize i = 0; i < count; ++i) {
std::array<float, 4> color;
std::copy_n(rgbaValues.data() + i * 4, 4, color.data());
stops.push_back({speedValues[i], color});
}
return layer->setColorStops(std::move(stops));
}
jni::jint NativeMapView::getWeatherColorStopCapacity(JNIEnv&) {
return static_cast<jni::jint>(mln::style::MaxWeatherColorStops);
}
jni::jboolean NativeMapView::advanceRasterArraySourceFieldWindow(JNIEnv& env, const jni::String& sourceId) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = map->getStyle().getSource(id);
auto* rasterArraySource = dynamic_cast<mln::style::RasterArraySource*>(source);
if (!rasterArraySource) {
mln::Log::Error(mln::Event::JNI,
"ParticleField: event=FIELD_WINDOW_UPDATE_REJECTED reason=SOURCE_NOT_FOUND sourceId=" + id);
return false;
}
const auto result = rasterArraySource->advanceRuntimeFieldWindow();
const bool success = result == mln::style::RasterArrayRuntimeFieldUpdateResult::Applied ||
result == mln::style::RasterArrayRuntimeFieldUpdateResult::Noop;
mln::Log::Info(mln::Event::JNI,
"ParticleField: event=FIELD_WINDOW_UPDATE_BRIDGE sourceId=" + id +
" result=" + (success ? "SUCCESS" : "REJECTED"));
return success;
}
jni::jboolean NativeMapView::repeatRasterArraySourceFieldWindow(JNIEnv& env, const jni::String& sourceId) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = map->getStyle().getSource(id);
auto* rasterArraySource = dynamic_cast<mln::style::RasterArraySource*>(source);
if (!rasterArraySource) {
mln::Log::Error(mln::Event::JNI,
"ParticleField: event=FIELD_WINDOW_UPDATE_REJECTED reason=SOURCE_NOT_FOUND sourceId=" + id);
return false;
}
const auto result = rasterArraySource->repeatRuntimeFieldWindow();
const bool success = result == mln::style::RasterArrayRuntimeFieldUpdateResult::Noop;
mln::Log::Info(mln::Event::JNI,
"ParticleField: event=FIELD_WINDOW_UPDATE_DUPLICATE_BRIDGE sourceId=" + id +
" result=" + (success ? "NOOP" : "REJECTED"));
return success;
}
jni::jint NativeMapView::submitRasterArraySourceHostField(JNIEnv& env,
const jni::String& sourceId,
const jni::String& metadata,
const jni::Array<jbyte>& payload) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
if (!source) {
mln::Log::Error(mln::Event::JNI,
"ParticleField: event=HOST_FIELD_SUBMIT_REJECTED reason=SOURCE_NOT_FOUND sourceId=" + id);
return static_cast<jni::jint>(mln::style::RasterArrayHostFieldSubmitResult::RejectedSourceMode);
}
NullCheck(env, &payload);
std::vector<char> bytes(payload.Length(env));
if (!bytes.empty()) {
jni::GetArrayRegion(env, *payload, 0, bytes.size(), reinterpret_cast<jbyte*>(bytes.data()));
}
const auto result = source->submitHostField(jni::Make<std::string>(env, metadata), bytes);
mln::Log::Info(mln::Event::JNI,
"ParticleField: event=HOST_FIELD_SUBMIT_BRIDGE sourceId=" + id +
" result=" + mln::style::rasterArrayHostFieldSubmitResultName(result));
return static_cast<jni::jint>(result);
}
jni::jint NativeMapView::submitRasterArraySourceHostFieldV2(JNIEnv& env,
const jni::String& sourceId,
const jni::String& metadata,
const jni::Array<jbyte>& packedPlanes,
const jni::jboolean scalarPresent,
const jni::jint scalarLength,
const jni::jboolean vectorPresent,
const jni::jint vectorLength,
const jni::jint validityLength) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
if (!source) return static_cast<jni::jint>(mln::style::RasterArrayHostFieldSubmitResult::RejectedSourceMode);
NullCheck(env, &packedPlanes);
if (scalarLength < 0 || vectorLength < 0 || validityLength <= 0 || (!scalarPresent && scalarLength != 0) ||
(!vectorPresent && vectorLength != 0) || (scalarPresent && scalarLength == 0) ||
(vectorPresent && vectorLength == 0) || (!scalarPresent && !vectorPresent)) {
return static_cast<jni::jint>(mln::style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
}
const uint64_t total = static_cast<uint64_t>(scalarLength) + static_cast<uint64_t>(vectorLength) +
static_cast<uint64_t>(validityLength);
if (total != packedPlanes.Length(env)) {
return static_cast<jni::jint>(mln::style::RasterArrayHostFieldSubmitResult::RejectedAdapter);
}
std::vector<char> packed(total);
if (!packed.empty()) jni::GetArrayRegion(env, *packedPlanes, 0, packed.size(), reinterpret_cast<jbyte*>(packed.data()));
size_t offset = 0;
const auto take = [&packed, &offset](const size_t length) {
std::vector<char> result(packed.begin() + static_cast<std::ptrdiff_t>(offset),
packed.begin() + static_cast<std::ptrdiff_t>(offset + length));
offset += length;
return result;
};
mln::particle::ParticleFieldPayloadBundle payloads{
.scalar = scalarPresent ? std::optional<std::vector<char>>(take(static_cast<size_t>(scalarLength))) : std::nullopt,
.vector = vectorPresent ? std::optional<std::vector<char>>(take(static_cast<size_t>(vectorLength))) : std::nullopt,
.validity = take(static_cast<size_t>(validityLength)),
};
const auto result = source->submitHostField(jni::Make<std::string>(env, metadata), payloads);
mln::Log::Info(mln::Event::JNI,
"ParticleField: event=HOST_FIELD_V2_SUBMIT_BRIDGE sourceId=" + id + " scalar=" +
(scalarPresent ? "present" : "absent") + " vector=" + (vectorPresent ? "present" : "absent") +
" result=" + mln::style::rasterArrayHostFieldSubmitResultName(result));
return static_cast<jni::jint>(result);
}
jni::jboolean NativeMapView::clearRasterArraySourceHostFields(JNIEnv& env, const jni::String& sourceId) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
if (!source) return false;
const bool cleared = source->clearHostFields();
mln::Log::Info(mln::Event::JNI,
"WeatherRuntime: event=CLEAR_FIELDS sourceId=" + id + " result=" +
(cleared ? "SUCCESS" : "REJECTED"));
return cleared;
}
jni::jboolean NativeMapView::resetRasterArraySourceWeatherRuntime(JNIEnv& env, const jni::String& sourceId) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
if (!source) return false;
const bool reset = source->resetWeatherRuntimeState();
mln::Log::Info(mln::Event::JNI, "WeatherRuntime: event=TERMINAL_RESET sourceId=" + id +
" result=" + (reset ? "SUCCESS" : "REJECTED"));
return reset;
}
jni::jboolean NativeMapView::seekRasterArraySourceTimelineToTimestamp(JNIEnv& env,
const jni::String& sourceId,
const jni::jlong timestamp) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
return source && timestamp >= 0 && source->seekRuntimeTimelineToTimestamp(static_cast<uint64_t>(timestamp));
}
jni::jboolean NativeMapView::controlRasterArraySourceTimeline(JNIEnv& env,
const jni::String& sourceId,
const jni::jint command,
const jni::jfloat value) {
const auto id = jni::Make<std::string>(env, sourceId);
auto* source = dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
if (!source) return false;
const bool success = source->controlRuntimeTimeline(command, value);
mln::Log::Info(mln::Event::JNI,
"ParticleTimeline: event=COMMAND sourceId=" + id + " command=" + std::to_string(command) +
" result=" + (success ? "SUCCESS" : "REJECTED"));
return success;
}
jni::jint NativeMapView::submitRasterArraySourceEncodedField(JNIEnv& env, const jni::String& sourceId, const jni::String& fieldKey, const jni::String& fieldId, jni::jlong generation, jni::jlong dataVersion, const jni::String& contractJson, const jni::Array<jbyte>& qbin) {
const auto id=jni::Make<std::string>(env,sourceId); auto* source=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(id));
if(!source) return 0; // bridge-layer SOURCE_MISSING sentinel, never a Core result
if(generation<=0 || dataVersion<0 || !qbin || !mln::particle::ingress::isValidEncodedFieldTransportSize(qbin.Length(env))) return static_cast<jni::jint>(mln::style::RasterArrayEncodedFieldSubmitResult::RejectedDecode);
const auto contract=mln::particle::parseResolvedFieldProfileContractJson(jni::Make<std::string>(env,contractJson));
if(!contract) return static_cast<jni::jint>(mln::style::RasterArrayEncodedFieldSubmitResult::RejectedContract);
std::vector<uint8_t> bytes(qbin.Length(env)); if(!bytes.empty()) jni::GetArrayRegion(env,*qbin,0,bytes.size(),reinterpret_cast<jbyte*>(bytes.data()));
const auto result=source->submitEncodedField(jni::Make<std::string>(env,fieldKey), {jni::Make<std::string>(env,fieldId),static_cast<uint64_t>(generation),static_cast<uint64_t>(dataVersion)}, *contract, bytes);
return static_cast<jni::jint>(result);
}
jni::jint NativeMapView::clearRasterArraySourceEncodedField(JNIEnv& env,const jni::String& sourceId,const jni::String& fieldKey) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; return s->clearEncodedField(jni::Make<std::string>(env,fieldKey)) ? 1 : -1; }
jni::jint NativeMapView::clearAllRasterArraySourceEncodedFields(JNIEnv& env,const jni::String& sourceId) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; s->clearAllEncodedFields(); return 1; }
jni::jint NativeMapView::setRasterArraySourceEncodedColorBinding(JNIEnv& env, const jni::String& sourceId, const jni::String& fieldKey, jni::jint semanticID, jni::jint groupID, jni::jint valueClass, jni::jint unitID) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; if(semanticID<=0||semanticID>UINT16_MAX||groupID<0||groupID>UINT16_MAX||unitID<0||unitID>UINT16_MAX||(valueClass<0||valueClass>2))return -1; s->setColorBinding({jni::Make<std::string>(env,fieldKey),{static_cast<uint16_t>(semanticID),static_cast<uint16_t>(groupID)},static_cast<mln::particle::FieldValueClass>(valueClass),static_cast<uint16_t>(unitID)}); return 1; }
jni::jint NativeMapView::setRasterArraySourceEncodedParticleBinding(JNIEnv& env, const jni::String& sourceId, const jni::String& fieldKey, jni::jint mode, jni::jint uSemanticID, jni::jint uGroupID, jni::jint vSemanticID, jni::jint vGroupID, jni::jint directionSemanticID, jni::jint directionGroupID, jni::jint unitID) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; const auto valid=[](jni::jint semantic,jni::jint group){return semantic>0&&semantic<=UINT16_MAX&&group>=0&&group<=UINT16_MAX;}; const auto inactive=[](jni::jint semantic,jni::jint group){return semantic==0&&group==0;}; if(unitID<0||unitID>UINT16_MAX)return -1; mln::particle::ParticleBinding binding; binding.fieldKey=jni::Make<std::string>(env,fieldKey); binding.expectedUnitID=static_cast<uint16_t>(unitID); if(mode==0&&valid(uSemanticID,uGroupID)&&valid(vSemanticID,vGroupID)&&inactive(directionSemanticID,directionGroupID)){binding.mode=mln::particle::ParticleBindingMode::VectorComponents;binding.uPlane={static_cast<uint16_t>(uSemanticID),static_cast<uint16_t>(uGroupID)};binding.vPlane={static_cast<uint16_t>(vSemanticID),static_cast<uint16_t>(vGroupID)};} else if(mode==1&&inactive(uSemanticID,uGroupID)&&inactive(vSemanticID,vGroupID)&&valid(directionSemanticID,directionGroupID)){binding.mode=mln::particle::ParticleBindingMode::DirectionAngle;binding.directionPlane={static_cast<uint16_t>(directionSemanticID),static_cast<uint16_t>(directionGroupID)};} else return -1; s->setParticleBinding(std::move(binding)); return 1; }
jni::jint NativeMapView::setRasterArraySourceEncodedForecastTime(JNIEnv& env,const jni::String& sourceId,jni::jlong timestamp) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; return timestamp>=0&&s->setRequestedForecastTime(static_cast<uint64_t>(timestamp))?1:-1; }
jni::jint NativeMapView::setRasterArraySourceEncodedForecastPlaybackState(JNIEnv& env,const jni::String& sourceId,jni::jboolean playing) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; s->setForecastPlaybackState(playing ? mln::particle::ForecastPlaybackState::Playing : mln::particle::ForecastPlaybackState::Paused); return 1; }
jni::jint NativeMapView::setRasterArraySourceEncodedForecastPlaybackSpeed(JNIEnv& env,const jni::String& sourceId,jni::jfloat speed) { auto* s=dynamic_cast<mln::style::RasterArraySource*>(map->getStyle().getSource(jni::Make<std::string>(env,sourceId))); if(!s)return 0; return s->setForecastPlaybackSpeed(speed)?1:-1; }
void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, const jni::String& before) {
assert(nativeLayerPtr != 0);
@@ -1255,6 +1671,10 @@ jni::Local<jni::Object<Source>> NativeMapView::getSource(JNIEnv& env, const jni:
return jni::NewLocal(env, Source::peerForCoreSource(env, *coreSource, *rendererFrontend, *map));
}
jni::jboolean NativeMapView::hasStyleSource(JNIEnv& env, const jni::String& sourceId) {
return map->getStyle().getSource(jni::Make<std::string>(env, sourceId)) != nullptr;
}
void NativeMapView::addSource(JNIEnv& env, const jni::Object<Source>& obj, jlong sourcePtr) {
assert(sourcePtr != 0);
@@ -1454,6 +1874,11 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::addMarkers, "nativeAddMarkers"),
METHOD(&NativeMapView::setDebug, "nativeSetDebug"),
METHOD(&NativeMapView::getDebug, "nativeGetDebug"),
METHOD(&NativeMapView::setRetainedUnderlayEnabled, "nativeSetRetainedUnderlayEnabled"),
METHOD(&NativeMapView::setContinuousLayerRange, "nativeSetContinuousLayerRange"),
METHOD(&NativeMapView::setRenderSegmentPlan, "nativeSetRenderSegmentPlan"),
METHOD(&NativeMapView::getRenderSegmentDiagnostics, "nativeGetRenderSegmentDiagnostics"),
METHOD(&NativeMapView::getRetainedUnderlayDiagnostics, "nativeGetRetainedUnderlayDiagnostics"),
METHOD(&NativeMapView::getActionJournalLogFiles, "nativeGetActionJournalLogFiles"),
METHOD(&NativeMapView::getActionJournalLog, "nativeGetActionJournalLog"),
METHOD(&NativeMapView::clearActionJournalLog, "nativeClearActionJournalLog"),
@@ -1487,6 +1912,33 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::getLight, "nativeGetLight"),
METHOD(&NativeMapView::getLayers, "nativeGetLayers"),
METHOD(&NativeMapView::getLayer, "nativeGetLayer"),
METHOD(&NativeMapView::hasStyleLayer, "nativeHasStyleLayer"),
METHOD(&NativeMapView::setStyleLayerFloatProperty, "nativeSetStyleLayerFloatProperty"),
METHOD(&NativeMapView::setWeatherColorOpacity, "nativeSetWeatherColorOpacity"),
METHOD(&NativeMapView::setStyleLayerVisibility, "nativeSetStyleLayerVisibility"),
METHOD(&NativeMapView::setRasterParticleColors, "nativeSetRasterParticleColors"),
METHOD(&NativeMapView::setRasterParticleColor, "nativeSetRasterParticleColor"),
METHOD(&NativeMapView::setRasterParticleTrailColor, "nativeSetRasterParticleTrailColor"),
METHOD(&NativeMapView::setRasterArraySourceTargetFps, "nativeSetRasterArraySourceTargetFps"),
METHOD(&NativeMapView::getRasterArraySourceTargetFps, "nativeGetRasterArraySourceTargetFps"),
METHOD(&NativeMapView::setWeatherColorStops, "nativeSetWeatherColorStops"),
METHOD(&NativeMapView::getWeatherColorStopCapacity, "nativeGetWeatherColorStopCapacity"),
METHOD(&NativeMapView::advanceRasterArraySourceFieldWindow, "nativeAdvanceRasterArraySourceFieldWindow"),
METHOD(&NativeMapView::repeatRasterArraySourceFieldWindow, "nativeRepeatRasterArraySourceFieldWindow"),
METHOD(&NativeMapView::submitRasterArraySourceHostField, "nativeSubmitRasterArraySourceHostField"),
METHOD(&NativeMapView::submitRasterArraySourceHostFieldV2, "nativeSubmitRasterArraySourceHostFieldV2"),
METHOD(&NativeMapView::clearRasterArraySourceHostFields, "nativeClearRasterArraySourceHostFields"),
METHOD(&NativeMapView::resetRasterArraySourceWeatherRuntime, "nativeResetRasterArraySourceWeatherRuntime"),
METHOD(&NativeMapView::seekRasterArraySourceTimelineToTimestamp, "nativeSeekRasterArraySourceTimelineToTimestamp"),
METHOD(&NativeMapView::controlRasterArraySourceTimeline, "nativeControlRasterArraySourceTimeline"),
METHOD(&NativeMapView::submitRasterArraySourceEncodedField, "nativeSubmitRasterArraySourceEncodedField"),
METHOD(&NativeMapView::clearRasterArraySourceEncodedField, "nativeClearRasterArraySourceEncodedField"),
METHOD(&NativeMapView::clearAllRasterArraySourceEncodedFields, "nativeClearAllRasterArraySourceEncodedFields"),
METHOD(&NativeMapView::setRasterArraySourceEncodedColorBinding, "nativeSetRasterArraySourceEncodedColorBinding"),
METHOD(&NativeMapView::setRasterArraySourceEncodedParticleBinding, "nativeSetRasterArraySourceEncodedParticleBinding"),
METHOD(&NativeMapView::setRasterArraySourceEncodedForecastTime, "nativeSetRasterArraySourceEncodedForecastTime"),
METHOD(&NativeMapView::setRasterArraySourceEncodedForecastPlaybackState, "nativeSetRasterArraySourceEncodedForecastPlaybackState"),
METHOD(&NativeMapView::setRasterArraySourceEncodedForecastPlaybackSpeed, "nativeSetRasterArraySourceEncodedForecastPlaybackSpeed"),
METHOD(&NativeMapView::addLayer, "nativeAddLayer"),
METHOD(&NativeMapView::addLayerAbove, "nativeAddLayerAbove"),
METHOD(&NativeMapView::addLayerAt, "nativeAddLayerAt"),
@@ -1494,6 +1946,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::removeLayer, "nativeRemoveLayer"),
METHOD(&NativeMapView::getSources, "nativeGetSources"),
METHOD(&NativeMapView::getSource, "nativeGetSource"),
METHOD(&NativeMapView::hasStyleSource, "nativeHasStyleSource"),
METHOD(&NativeMapView::addSource, "nativeAddSource"),
METHOD(&NativeMapView::removeSource, "nativeRemoveSource"),
METHOD(&NativeMapView::addImage, "nativeAddImage"),