feat: add STEP-093 iPad validation menu
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user