merge(upgrade): port particle extensions onto official native 13.6.1 (unverified)
This commit is contained in:
@@ -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"),
|
||||
|
||||
Reference in New Issue
Block a user