feat: add STEP-093 iPad validation menu
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
tei
2026-09-24 15:28:29 +09:00
parent 66690b460e
commit 0dd475c22f

View File

@@ -59,6 +59,19 @@ static const MLNCoordinateBounds colorado = {
static NSString *const MBXViewControllerAnnotationViewReuseIdentifer = static NSString *const MBXViewControllerAnnotationViewReuseIdentifer =
@"MBXViewControllerAnnotationViewReuseIdentifer"; @"MBXViewControllerAnnotationViewReuseIdentifer";
static NSString *const MBXStep093SourceBottom = @"step093-bottom-source";
static NSString *const MBXStep093SourceTopSemi = @"step093-top-semi-source";
static NSString *const MBXStep093SourceTopOpaque = @"step093-top-opaque-source";
static NSString *const MBXStep093SourceTopLine = @"step093-top-line-source";
static NSString *const MBXStep093SourceCross = @"step093-cross-source";
static NSString *const MBXStep093LayerBottom = @"step093-bottom-fill";
static NSString *const MBXStep093LayerTopSemi = @"step093-top-semi";
static NSString *const MBXStep093LayerTopOpaque = @"step093-top-opaque";
static NSString *const MBXStep093LayerTopLine = @"step093-top-line";
static NSString *const MBXStep093LayerCross = @"step093-cross-layer";
static NSString *const MBXStep093WeatherLayer = @"particle-qbin-v4-smoke-weather";
static NSString *const MBXStep093ParticleLayer = @"particle-qbin-v4-smoke-particles";
typedef NS_ENUM(NSInteger, MBXSettingsSections) { typedef NS_ENUM(NSInteger, MBXSettingsSections) {
MBXSettingsDebugTools = 0, MBXSettingsDebugTools = 0,
MBXSettingsAnnotations, MBXSettingsAnnotations,
@@ -129,7 +142,22 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
MBXSettingsRuntimeStylingAddFoursquarePOIsPMTiles, MBXSettingsRuntimeStylingAddFoursquarePOIsPMTiles,
MBXSettingsRuntimeStylingHeatmapLayer, MBXSettingsRuntimeStylingHeatmapLayer,
MBXSettingsRuntimeStylingParticleCoreValidation, MBXSettingsRuntimeStylingParticleCoreValidation,
MBXSettingsRuntimeStylingParticleQbinV4Smoke MBXSettingsRuntimeStylingParticleQbinV4Smoke,
MBXSettingsRuntimeStylingStep093
};
typedef NS_ENUM(NSInteger, MBXStep093Scenario) {
MBXStep093ScenarioBottomContinuousTop = 0,
MBXStep093ScenarioBottomContinuous,
MBXStep093ScenarioContinuousTop,
MBXStep093ScenarioContinuousOnly,
MBXStep093ScenarioSingleLayer
};
typedef NS_ENUM(NSInteger, MBXStep093CrossPosition) {
MBXStep093CrossPositionBottom = 0,
MBXStep093CrossPositionContinuous,
MBXStep093CrossPositionTop
}; };
typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@@ -262,6 +290,27 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
- (void)showParticleQbinV4SmokeMenu; - (void)showParticleQbinV4SmokeMenu;
- (void)installParticleQbinV4SmokeAtTime:(uint64_t)requestedTime label:(NSString *)label; - (void)installParticleQbinV4SmokeAtTime:(uint64_t)requestedTime label:(NSString *)label;
- (void)clearParticleQbinV4Smoke; - (void)clearParticleQbinV4Smoke;
- (void)showStep093Menu;
- (void)showStep093InvalidRangeMenu;
- (void)showStep093EndpointMenu;
- (void)showStep093MutationMenu;
- (void)installStep093Scenario:(MBXStep093Scenario)scenario;
- (void)installStep093OrdinarySources;
- (void)removeStep093BaseStyleLayers;
- (void)clearStep093OrdinaryLayers;
- (void)setStep093RangeStart:(NSString *)start end:(NSString *)end label:(NSString *)label;
- (void)deleteStep093Endpoint:(NSString *)identifier;
- (void)toggleStep093EndpointVisibility:(NSString *)identifier;
- (void)moveStep093CrossLayer:(MBXStep093CrossPosition)position;
- (void)showStep093Diagnostics;
- (MLNFillStyleLayer *)step093FillLayer:(NSString *)identifier
source:(NSString *)sourceIdentifier
color:(UIColor *)color
opacity:(CGFloat)opacity;
- (MLNLineStyleLayer *)step093LineLayer:(NSString *)identifier
source:(NSString *)sourceIdentifier
color:(UIColor *)color
width:(CGFloat)width;
@end @end
@interface MLNMapView (MBXViewController) @interface MLNMapView (MBXViewController)
@@ -523,7 +572,8 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
@"Add FourSquare POIs PMTiles Layer", @"Add FourSquare POIs PMTiles Layer",
@"Add Earthquake Heatmap", @"Add Earthquake Heatmap",
@"Particle Core Validation (Fixtures)", @"Particle Core Validation (Fixtures)",
@"Particle / QBIN V4 Smoke (T0)" @"Particle / QBIN V4 Smoke (T0)",
@"STEP-093 Continuous Range"
]]; ]];
break; break;
case MBXSettingsMiscellaneous: case MBXSettingsMiscellaneous:
@@ -763,6 +813,9 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
case MBXSettingsRuntimeStylingParticleQbinV4Smoke: case MBXSettingsRuntimeStylingParticleQbinV4Smoke:
[self showParticleQbinV4SmokeMenu]; [self showParticleQbinV4SmokeMenu];
break; break;
case MBXSettingsRuntimeStylingStep093:
[self showStep093Menu];
break;
default: default:
NSAssert(NO, @"All runtime styling setting rows should be implemented"); NSAssert(NO, @"All runtime styling setting rows should be implemented");
break; break;
@@ -1391,6 +1444,7 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
} }
- (void)clearParticleQbinV4Smoke { - (void)clearParticleQbinV4Smoke {
[self clearStep093OrdinaryLayers];
auto& style = [self.mapView mbglMap].getStyle(); auto& style = [self.mapView mbglMap].getStyle();
if (style.getLayer("particle-qbin-v4-smoke-particles")) style.removeLayer("particle-qbin-v4-smoke-particles"); if (style.getLayer("particle-qbin-v4-smoke-particles")) style.removeLayer("particle-qbin-v4-smoke-particles");
if (style.getLayer("particle-qbin-v4-smoke-weather")) style.removeLayer("particle-qbin-v4-smoke-weather"); if (style.getLayer("particle-qbin-v4-smoke-weather")) style.removeLayer("particle-qbin-v4-smoke-weather");
@@ -1399,6 +1453,452 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
NSLog(@"ParticleQbinV4Smoke: event=CLEAR_RELEASED"); NSLog(@"ParticleQbinV4Smoke: event=CLEAR_RELEASED");
} }
// MARK: - STEP-093 Continuous Range runtime validation (test app only)
- (void)showStep093Menu {
UIAlertController *menu =
[UIAlertController alertControllerWithTitle:@"STEP-093 Continuous Range"
message:@"Style order remains the only Z-order. Select a topology, then use the submenus to mutate it and refresh diagnostics."
preferredStyle:UIAlertControllerStyleAlert];
__weak MBXViewController *weakSelf = self;
void (^scenario)(NSString *, MBXStep093Scenario) = ^(NSString *title,
MBXStep093Scenario value) {
[menu addAction:[UIAlertAction actionWithTitle:title
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf installStep093Scenario:value];
}]];
};
scenario(@"A Bottom + Continuous + Top", MBXStep093ScenarioBottomContinuousTop);
scenario(@"B Bottom + Continuous", MBXStep093ScenarioBottomContinuous);
scenario(@"C Continuous + Top", MBXStep093ScenarioContinuousTop);
scenario(@"D Continuous-only", MBXStep093ScenarioContinuousOnly);
scenario(@"E Single-layer Continuous", MBXStep093ScenarioSingleLayer);
[menu addAction:[UIAlertAction actionWithTitle:@"Invalid / Missing / Reversed"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093InvalidRangeMenu];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Endpoint / Visibility"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093EndpointMenu];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Mutation / Cross-boundary"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093MutationMenu];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Diagnostics / Refresh"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093Diagnostics];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Restore Default A"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf installStep093Scenario:
MBXStep093ScenarioBottomContinuousTop];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
[self presentViewController:menu animated:YES completion:nil];
}
- (void)showStep093InvalidRangeMenu {
UIAlertController *menu =
[UIAlertController alertControllerWithTitle:@"STEP-093 Invalid Range"
message:@"Each action first restores default A when its endpoints are unavailable."
preferredStyle:UIAlertControllerStyleAlert];
__weak MBXViewController *weakSelf = self;
void (^ensureDefault)(void) = ^{
if (![weakSelf.mapView.style layerWithIdentifier:MBXStep093WeatherLayer] ||
![weakSelf.mapView.style layerWithIdentifier:MBXStep093ParticleLayer]) {
[weakSelf installStep093Scenario:MBXStep093ScenarioBottomContinuousTop];
}
};
[menu addAction:[UIAlertAction actionWithTitle:@"Missing start"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
ensureDefault();
[weakSelf setStep093RangeStart:@"step093-missing-start"
end:MBXStep093ParticleLayer
label:@"MISSING_START"];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Missing end"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
ensureDefault();
[weakSelf setStep093RangeStart:MBXStep093WeatherLayer
end:@"step093-missing-end"
label:@"MISSING_END"];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Reversed endpoints"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
ensureDefault();
[weakSelf setStep093RangeStart:MBXStep093ParticleLayer
end:MBXStep093WeatherLayer
label:@"REVERSED"];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Empty start ID (API reject)"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
ensureDefault();
[weakSelf setStep093RangeStart:@""
end:MBXStep093ParticleLayer
label:@"EMPTY_START"];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Restore valid A"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf installStep093Scenario:
MBXStep093ScenarioBottomContinuousTop];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Back"
style:UIAlertActionStyleCancel
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093Menu];
}]];
[self presentViewController:menu animated:YES completion:nil];
}
- (void)showStep093EndpointMenu {
UIAlertController *menu =
[UIAlertController alertControllerWithTitle:@"STEP-093 Endpoints"
message:@"Visibility changes content only; deletion must invalidate the configured endpoint. Restore rebuilds default A without replacing MLNMapView."
preferredStyle:UIAlertControllerStyleAlert];
__weak MBXViewController *weakSelf = self;
[menu addAction:[UIAlertAction actionWithTitle:@"Toggle start visibility"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf toggleStep093EndpointVisibility:
MBXStep093WeatherLayer];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Toggle end visibility"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf toggleStep093EndpointVisibility:
MBXStep093ParticleLayer];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Delete start endpoint"
style:UIAlertActionStyleDestructive
handler:^(__unused UIAlertAction *action) {
[weakSelf deleteStep093Endpoint:MBXStep093WeatherLayer];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Restore start (default A)"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf installStep093Scenario:
MBXStep093ScenarioBottomContinuousTop];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Delete end endpoint"
style:UIAlertActionStyleDestructive
handler:^(__unused UIAlertAction *action) {
[weakSelf deleteStep093Endpoint:MBXStep093ParticleLayer];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Restore end (default A)"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf installStep093Scenario:
MBXStep093ScenarioBottomContinuousTop];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Back"
style:UIAlertActionStyleCancel
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093Menu];
}]];
[self presentViewController:menu animated:YES completion:nil];
}
- (void)showStep093MutationMenu {
UIAlertController *menu =
[UIAlertController alertControllerWithTitle:@"STEP-093 Cross-boundary"
message:@"The same ordinary fill layer ID is removed and re-added at three Style-order positions."
preferredStyle:UIAlertControllerStyleAlert];
__weak MBXViewController *weakSelf = self;
void (^move)(NSString *, MBXStep093CrossPosition) = ^(NSString *title,
MBXStep093CrossPosition position) {
[menu addAction:[UIAlertAction actionWithTitle:title
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf moveStep093CrossLayer:position];
}]];
};
move(@"Move cross layer → Bottom", MBXStep093CrossPositionBottom);
move(@"Move cross layer → Continuous", MBXStep093CrossPositionContinuous);
move(@"Move cross layer → Top", MBXStep093CrossPositionTop);
[menu addAction:[UIAlertAction actionWithTitle:@"Remove cross layer"
style:UIAlertActionStyleDestructive
handler:^(__unused UIAlertAction *action) {
[weakSelf removeLayer:MBXStep093LayerCross];
[weakSelf.mapView setNeedsRerender];
NSLog(@"STEP093_IOS event=MUTATION cross=REMOVED");
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Restore Default A"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf installStep093Scenario:
MBXStep093ScenarioBottomContinuousTop];
}]];
[menu addAction:[UIAlertAction actionWithTitle:@"Back"
style:UIAlertActionStyleCancel
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093Menu];
}]];
[self presentViewController:menu animated:YES completion:nil];
}
- (void)installStep093Scenario:(MBXStep093Scenario)scenario {
[self clearStep093OrdinaryLayers];
[self installParticleQbinV4SmokeAtTime:1789241400000ULL label:@"STEP093_MIDPOINT"];
if (![self.mapView.style layerWithIdentifier:MBXStep093WeatherLayer] ||
![self.mapView.style layerWithIdentifier:MBXStep093ParticleLayer]) {
NSLog(@"STEP093_IOS event=SCENE_FAILED reason=QBIN_ENDPOINTS_UNAVAILABLE");
return;
}
[self removeStep093BaseStyleLayers];
[self installStep093OrdinarySources];
MLNStyle *style = self.mapView.style;
MLNStyleLayer *weather = [style layerWithIdentifier:MBXStep093WeatherLayer];
MLNStyleLayer *particle = [style layerWithIdentifier:MBXStep093ParticleLayer];
const BOOL hasBottom = scenario == MBXStep093ScenarioBottomContinuousTop ||
scenario == MBXStep093ScenarioBottomContinuous ||
scenario == MBXStep093ScenarioSingleLayer;
const BOOL hasTop = scenario == MBXStep093ScenarioBottomContinuousTop ||
scenario == MBXStep093ScenarioContinuousTop ||
scenario == MBXStep093ScenarioSingleLayer;
if (hasBottom) {
MLNFillStyleLayer *bottom =
[self step093FillLayer:MBXStep093LayerBottom
source:MBXStep093SourceBottom
color:[UIColor colorWithRed:0.05 green:0.48 blue:0.58 alpha:1.0]
opacity:0.72];
[style insertLayer:bottom belowLayer:weather];
}
if (hasTop) {
[style addLayer:[self step093FillLayer:MBXStep093LayerTopSemi
source:MBXStep093SourceTopSemi
color:[UIColor colorWithRed:1.0 green:0.82 blue:0.27 alpha:1.0]
opacity:0.42]];
[style addLayer:[self step093FillLayer:MBXStep093LayerTopOpaque
source:MBXStep093SourceTopOpaque
color:[UIColor colorWithRed:0.94 green:0.20 blue:0.34 alpha:1.0]
opacity:1.0]];
[style addLayer:[self step093LineLayer:MBXStep093LayerTopLine
source:MBXStep093SourceTopLine
color:UIColor.whiteColor
width:6.0]];
}
NSString *start = MBXStep093WeatherLayer;
NSString *end = MBXStep093ParticleLayer;
if (scenario == MBXStep093ScenarioSingleLayer) {
start = MBXStep093ParticleLayer;
end = MBXStep093ParticleLayer;
}
self.mapView.retainedUnderlayEnabled = YES;
NSString *labels[] = {@"BOTTOM_CONTINUOUS_TOP", @"BOTTOM_CONTINUOUS",
@"CONTINUOUS_TOP", @"CONTINUOUS_ONLY", @"SINGLE_LAYER"};
[self setStep093RangeStart:start end:end label:labels[scenario]];
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(27.8882865, 135.0)
zoomLevel:3.0
animated:NO];
[self.mapView setNeedsRerender];
}
- (void)installStep093OrdinarySources {
MLNStyle *style = self.mapView.style;
MLNShapeSource *(^polygonSource)(NSString *, CLLocationCoordinate2D *, NSUInteger) =
^MLNShapeSource *(NSString *identifier, CLLocationCoordinate2D *coordinates,
NSUInteger count) {
MLNPolygon *polygon = [MLNPolygon polygonWithCoordinates:coordinates count:count];
return [[MLNShapeSource alloc] initWithIdentifier:identifier shape:polygon options:nil];
};
CLLocationCoordinate2D bottom[] = {{4.0, 114.0}, {4.0, 157.0}, {53.0, 157.0},
{53.0, 114.0}, {4.0, 114.0}};
CLLocationCoordinate2D semi[] = {{8.0, 136.0}, {8.0, 152.0}, {49.0, 152.0},
{49.0, 136.0}, {8.0, 136.0}};
CLLocationCoordinate2D opaque[] = {{18.0, 124.0}, {18.0, 136.0}, {42.0, 136.0},
{42.0, 124.0}, {18.0, 124.0}};
CLLocationCoordinate2D cross[] = {{14.0, 128.0}, {14.0, 145.0}, {37.0, 145.0},
{37.0, 128.0}, {14.0, 128.0}};
CLLocationCoordinate2D line[] = {{6.0, 116.0}, {50.0, 154.0}, {6.0, 154.0},
{50.0, 116.0}};
[style addSource:polygonSource(MBXStep093SourceBottom, bottom, 5)];
[style addSource:polygonSource(MBXStep093SourceTopSemi, semi, 5)];
[style addSource:polygonSource(MBXStep093SourceTopOpaque, opaque, 5)];
[style addSource:[[MLNShapeSource alloc]
initWithIdentifier:MBXStep093SourceTopLine
shape:[MLNPolyline polylineWithCoordinates:line count:4]
options:nil]];
[style addSource:polygonSource(MBXStep093SourceCross, cross, 5)];
}
- (void)removeStep093BaseStyleLayers {
// The demo style normally contains many pre-existing layers. Remove them from this private
// validation scene so A/B/C/D describe the complete Style topology rather than only a suffix.
// The QBIN source and the two existing dynamic endpoints remain untouched.
for (MLNStyleLayer *layer in [self.mapView.style.layers copy]) {
if (![layer.identifier isEqualToString:MBXStep093WeatherLayer] &&
![layer.identifier isEqualToString:MBXStep093ParticleLayer]) {
[self.mapView.style removeLayer:layer];
}
}
}
- (void)clearStep093OrdinaryLayers {
for (NSString *identifier in @[ MBXStep093LayerCross, MBXStep093LayerTopLine,
MBXStep093LayerTopOpaque, MBXStep093LayerTopSemi,
MBXStep093LayerBottom ]) {
[self removeLayer:identifier];
}
for (NSString *identifier in @[ MBXStep093SourceCross, MBXStep093SourceTopLine,
MBXStep093SourceTopOpaque, MBXStep093SourceTopSemi,
MBXStep093SourceBottom ]) {
[self removeSource:identifier];
}
}
- (void)setStep093RangeStart:(NSString *)start end:(NSString *)end label:(NSString *)label {
BOOL accepted = [self.mapView setContinuousLayerRangeFromLayerIdentifier:start
toLayerIdentifier:end];
[self.mapView setNeedsRerender];
NSLog(@"STEP093_IOS event=RANGE label=%@ accepted=%d start=%@ end=%@", label, accepted,
start, end);
}
- (void)deleteStep093Endpoint:(NSString *)identifier {
if (![self.mapView.style layerWithIdentifier:MBXStep093WeatherLayer] ||
![self.mapView.style layerWithIdentifier:MBXStep093ParticleLayer]) {
[self installStep093Scenario:MBXStep093ScenarioBottomContinuousTop];
}
[self removeLayer:identifier];
[self.mapView setNeedsRerender];
NSLog(@"STEP093_IOS event=ENDPOINT_DELETE id=%@", identifier);
}
- (void)toggleStep093EndpointVisibility:(NSString *)identifier {
MLNStyleLayer *layer = [self.mapView.style layerWithIdentifier:identifier];
if (!layer) {
[self installStep093Scenario:MBXStep093ScenarioBottomContinuousTop];
layer = [self.mapView.style layerWithIdentifier:identifier];
}
layer.visible = !layer.visible;
[self.mapView setNeedsRerender];
NSLog(@"STEP093_IOS event=ENDPOINT_VISIBILITY id=%@ visible=%d", identifier,
layer.visible);
}
- (void)moveStep093CrossLayer:(MBXStep093CrossPosition)position {
if (![self.mapView.style sourceWithIdentifier:MBXStep093SourceCross] ||
![self.mapView.style layerWithIdentifier:MBXStep093WeatherLayer] ||
![self.mapView.style layerWithIdentifier:MBXStep093ParticleLayer]) {
[self installStep093Scenario:MBXStep093ScenarioBottomContinuousTop];
}
[self removeLayer:MBXStep093LayerCross];
MLNFillStyleLayer *cross =
[self step093FillLayer:MBXStep093LayerCross
source:MBXStep093SourceCross
color:[UIColor colorWithRed:0.62 green:0.25 blue:0.78 alpha:1.0]
opacity:0.28];
MLNStyle *style = self.mapView.style;
MLNStyleLayer *weather = [style layerWithIdentifier:MBXStep093WeatherLayer];
MLNStyleLayer *particle = [style layerWithIdentifier:MBXStep093ParticleLayer];
NSString *label = nil;
switch (position) {
case MBXStep093CrossPositionBottom:
[style insertLayer:cross belowLayer:weather];
label = @"BOTTOM";
break;
case MBXStep093CrossPositionContinuous:
[style insertLayer:cross belowLayer:particle];
label = @"CONTINUOUS";
break;
case MBXStep093CrossPositionTop:
[style insertLayer:cross aboveLayer:particle];
label = @"TOP";
break;
}
[self.mapView setNeedsRerender];
NSLog(@"STEP093_IOS event=MUTATION cross=%@", label);
}
- (void)showStep093Diagnostics {
MLNRetainedUnderlayDiagnostics *value = self.mapView.retainedUnderlayDiagnostics;
NSUInteger cacheCount = (value.bottomPresent ? 1 : 0) + (value.topPresent ? 1 : 0);
NSString *message = [NSString
stringWithFormat:
@"Range configured=%d valid=%d fallback=%d\n%@[%ld] … %@[%ld]\nContinuous=[%ld,%ld) caches=%lu\nreason=%@\n\nBottom present=%d state=%@\nb/r/i=%llu/%llu/%llu\ntex/comp/release=%llu/%llu/%llu\nlast=%@\n\nTop present=%d state=%@\nb/r/i=%llu/%llu/%llu\ntex/comp/release=%llu/%llu/%llu\nlast=%@\n\nFast eligible=%d active=%d\nhit/miss/full=%llu/%llu/%llu\nreason=%@",
value.rangeConfigured, value.rangeValid, value.rangeFallback, value.startLayerId,
(long)value.startIndex, value.endLayerId, (long)value.endIndex,
(long)value.continuousBegin, (long)value.continuousEndExclusive,
(unsigned long)cacheCount, value.lastReason, value.bottomPresent,
value.bottomCacheState, (unsigned long long)value.bottomBuild,
(unsigned long long)value.bottomReuse, (unsigned long long)value.bottomInvalidation,
(unsigned long long)value.bottomTextureCreate,
(unsigned long long)value.bottomCompositeCreate,
(unsigned long long)value.bottomResourceRelease, value.bottomLastInvalidationReason,
value.topPresent, value.topCacheState, (unsigned long long)value.topBuild,
(unsigned long long)value.topReuse, (unsigned long long)value.topInvalidation,
(unsigned long long)value.topTextureCreate,
(unsigned long long)value.topCompositeCreate,
(unsigned long long)value.topResourceRelease, value.topLastInvalidationReason,
value.fastPathEligible, value.fastPathActive, (unsigned long long)value.fastPathHit,
(unsigned long long)value.fastPathMiss, (unsigned long long)value.fullCpuFrame,
value.fastPathFallbackReason];
NSLog(@"STEP093_IOS_DIAGNOSTICS %@", [message stringByReplacingOccurrencesOfString:@"\n"
withString:@" "]);
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"STEP-093 Diagnostics"
message:message
preferredStyle:UIAlertControllerStyleAlert];
__weak MBXViewController *weakSelf = self;
[alert addAction:[UIAlertAction actionWithTitle:@"Refresh"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093Diagnostics];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Back to STEP-093"
style:UIAlertActionStyleDefault
handler:^(__unused UIAlertAction *action) {
[weakSelf showStep093Menu];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Close"
style:UIAlertActionStyleCancel
handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
- (MLNFillStyleLayer *)step093FillLayer:(NSString *)identifier
source:(NSString *)sourceIdentifier
color:(UIColor *)color
opacity:(CGFloat)opacity {
MLNSource *source = [self.mapView.style sourceWithIdentifier:sourceIdentifier];
MLNFillStyleLayer *layer = [[MLNFillStyleLayer alloc] initWithIdentifier:identifier
source:source];
layer.fillColor = [NSExpression expressionForConstantValue:color];
layer.fillOpacity = [NSExpression expressionForConstantValue:@(opacity)];
return layer;
}
- (MLNLineStyleLayer *)step093LineLayer:(NSString *)identifier
source:(NSString *)sourceIdentifier
color:(UIColor *)color
width:(CGFloat)width {
MLNSource *source = [self.mapView.style sourceWithIdentifier:sourceIdentifier];
MLNLineStyleLayer *layer = [[MLNLineStyleLayer alloc] initWithIdentifier:identifier
source:source];
layer.lineColor = [NSExpression expressionForConstantValue:color];
layer.lineWidth = [NSExpression expressionForConstantValue:@(width)];
layer.lineOpacity = [NSExpression expressionForConstantValue:@0.95];
return layer;
}
// Earthquake Heatmap // Earthquake Heatmap
- (void)addEarthquakeHeatmap { - (void)addEarthquakeHeatmap {