diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h new file mode 100644 index 00000000000..d9a22d60fae --- /dev/null +++ b/platform/darwin/src/MGLLight.h @@ -0,0 +1,125 @@ +#import + +#import "MGLFoundation.h" +#import "MGLStyleValue.h" + +NS_ASSUME_NONNULL_BEGIN + + +/** Options to specify extruded geometries are lit relative to the map or viewport. */ +typedef NS_ENUM(NSUInteger, MGLLightAnchor) { + /** The position of the light source is aligned to the rotation of the map. */ + MGLLightAnchorMap, + /** The position of the light source is aligned to the rotation of the viewport. */ + MGLLightAnchorViewport +}; + +/** + A structure containing information about the position of the light source + relative to lit geometries. + */ +typedef struct MGLSphericalPosition { + /** Distance from the center of the base of an object to its light. */ + CLLocationDistance radial; + /** Position of the light relative to 0° (0° when `MGLLight.anchor` is set to viewport corresponds + to the top of the viewport, or 0° when `MGLLight.anchor` is set to map corresponds to due north, + and degrees proceed clockwise). */ + CLLocationDirection azimuthal; + /** Indicates the height of the light (from 0°, directly above, to 180°, directly below). */ + CLLocationDirection polar; +} MGLSphericalPosition; + +/** + Creates a new `MGLSphericalPosition` from the given radial, azimuthal, polar. + + @param radial The radial coordinate. + @param azimuthal The azimuthal angle. + @param polar The polar angle. + + @return Returns a `MGLSphericalPosition` struct containing the position attributes. + */ +NS_INLINE MGLSphericalPosition MGLSphericalPositionMake(CLLocationDistance radial, CLLocationDirection azimuthal, CLLocationDirection polar) { + MGLSphericalPosition position; + position.radial = radial; + position.azimuthal = azimuthal; + position.polar = polar; + + return position; +} + +/** + An `MGLLight` object represents the light source for extruded geometries in `MGLStyle`. + */ +MGL_EXPORT +@interface MGLLight : NSObject + +/** + `anchor` Whether extruded geometries are lit relative to the map or viewport. + + This property corresponds to the anchor + light property in the Mapbox Style Specification. + */ +@property (nonatomic) MGLLightAnchor anchor; + +/** + Values describing animated transitions to `anchor` property. + */ +@property (nonatomic) MGLTransition anchorTransition; + + +/** + Position of the light source relative to lit (extruded) geometries. + + This property corresponds to the position + light property in the Mapbox Style Specification. + */ +@property (nonatomic) MGLStyleValue * position; + +/** + Values describing animated transitions to `position` property. + */ +@property (nonatomic) MGLTransition positionTransiton; + + +#if TARGET_OS_IPHONE +/** + Color tint for lighting extruded geometries. + + This property corresponds to the color + light property in the Mapbox Style Specification. + */ +@property (nonatomic) MGLStyleValue *color; +#else + +/** + Color tint for lighting extruded geometries. + */ +@property (nonatomic) MGLStyleValue *color; +#endif + +/** + Values describing animated transitions to `color` property. + */ +@property (nonatomic) MGLTransition colorTransiton; + + +/** + Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as more extreme contrast. + + This property corresponds to the intensity + light property in the Mapbox Style Specification. + */ +@property(nonatomic) MGLStyleValue *intensity; + +/** + Values describing animated transitions to `intensity` property. + */ +@property (nonatomic) MGLTransition intensityTransition; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLLight.mm b/platform/darwin/src/MGLLight.mm new file mode 100644 index 00000000000..02d55e76ed8 --- /dev/null +++ b/platform/darwin/src/MGLLight.mm @@ -0,0 +1,117 @@ +#import "MGLLight.h" + +#import "MGLTypes.h" +#import "NSDate+MGLAdditions.h" +#import "MGLStyleValue_Private.h" +#import "NSValue+MGLAdditions.h" + +#import +#import + +namespace mbgl { + + MBGL_DEFINE_ENUM(MGLLightAnchor, { + { MGLLightAnchorMap, "map" }, + { MGLLightAnchorViewport, "viewport" }, + }); + +} + +NS_INLINE MGLTransition MGLTransitionFromOptions(const mbgl::style::TransitionOptions& options) { + MGLTransition transition; + transition.duration = MGLTimeIntervalFromDuration(options.duration.value_or(mbgl::Duration::zero())); + transition.delay = MGLTimeIntervalFromDuration(options.delay.value_or(mbgl::Duration::zero())); + + return transition; +} + +NS_INLINE mbgl::style::TransitionOptions MGLOptionsFromTransition(MGLTransition transition) { + mbgl::style::TransitionOptions options { { MGLDurationFromTimeInterval(transition.duration) }, { MGLDurationFromTimeInterval(transition.delay) } }; + return options; +} + +@interface MGLLight() + +@end + +@implementation MGLLight + +- (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight +{ + if (self = [super init]) { + auto anchor = mbglLight->getAnchor(); + MGLStyleValue *anchorStyleValue; + if (anchor.isUndefined()) { + mbgl::style::PropertyValue defaultAnchor = mbglLight->getDefaultAnchor(); + anchorStyleValue = MGLStyleValueTransformer().toEnumStyleValue(defaultAnchor); + } else { + anchorStyleValue = MGLStyleValueTransformer().toEnumStyleValue(anchor); + } + + NSAssert([anchorStyleValue isKindOfClass:[MGLConstantStyleValue class]], @"Anchor isn’t a constant."); + NSValue *anchorValue = ((MGLConstantStyleValue *)anchorStyleValue).rawValue; + _anchor = [anchorValue MGLLightAnchorValue]; + + _anchorTransition = MGLTransitionFromOptions(mbglLight->getAnchorTransition()); + + auto positionValue = mbglLight->getPosition(); + if (positionValue.isUndefined()) { + _position = MGLStyleValueTransformer().toStyleValue(mbglLight->getDefaultPosition()); + } else { + _position = MGLStyleValueTransformer().toStyleValue(positionValue); + } + + _positionTransiton = MGLTransitionFromOptions(mbglLight->getPositionTransition()); + + auto colorValue = mbglLight->getColor(); + if (colorValue.isUndefined()) { + _color = MGLStyleValueTransformer().toStyleValue(mbglLight->getDefaultColor()); + } else { + _color = MGLStyleValueTransformer().toStyleValue(colorValue); + } + + _colorTransiton = MGLTransitionFromOptions(mbglLight->getColorTransition()); + + auto intensityValue = mbglLight->getIntensity(); + if (intensityValue.isUndefined()) { + _intensity = MGLStyleValueTransformer().toStyleValue(mbglLight->getDefaultIntensity()); + } else { + _intensity = MGLStyleValueTransformer().toStyleValue(intensityValue); + } + + _intensityTransition = MGLTransitionFromOptions(mbglLight->getIntensityTransition()); + } + + return self; +} + +- (mbgl::style::Light)mbglLight +{ + mbgl::style::Light mbglLight; + + MGLStyleValue *anchorType = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLightAnchor:self.anchor]]; + auto anchor = MGLStyleValueTransformer().toEnumPropertyValue(anchorType); + mbglLight.setAnchor(anchor); + + + mbglLight.setAnchorTransition(MGLOptionsFromTransition(self.anchorTransition)); + + auto position = MGLStyleValueTransformer().toInterpolatablePropertyValue(self.position); + mbglLight.setPosition(position); + + mbglLight.setPositionTransition(MGLOptionsFromTransition(self.positionTransiton)); + + auto color = MGLStyleValueTransformer().toInterpolatablePropertyValue(self.color); + mbglLight.setColor(color); + + mbglLight.setColorTransition(MGLOptionsFromTransition(self.colorTransiton)); + + auto intensity = MGLStyleValueTransformer().toInterpolatablePropertyValue(self.intensity); + mbglLight.setIntensity(intensity); + + mbglLight.setIntensityTransition(MGLOptionsFromTransition(self.intensityTransition)); + + return mbglLight; +} + +@end diff --git a/platform/darwin/src/MGLLight_Private.h b/platform/darwin/src/MGLLight_Private.h new file mode 100644 index 00000000000..dbc29c1eff7 --- /dev/null +++ b/platform/darwin/src/MGLLight_Private.h @@ -0,0 +1,23 @@ +#import + +#import "MGLLight.h" + +namespace mbgl { + namespace style { + class Light; + } +} + +@interface MGLLight (Private) + +/** + Initializes and returns a `MGLLight` associated with a style's light. + */ +- (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight; + +/** + Returns an `mbgl::style::Light` representation of the `MGLLight`. + */ +- (mbgl::style::Light)mbglLight; + +@end diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index 26434eb4927..08c6c047f18 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -6,6 +6,7 @@ #import "MGLTypes.h" @class MGLSource; +@class MGLLight; NS_ASSUME_NONNULL_BEGIN @@ -564,6 +565,14 @@ MGL_EXPORT */ - (void)removeImageForName:(NSString *)name; + +#pragma mark Managing the Style's Light + +/** + Provides global light source for the style. + */ +@property (nonatomic, strong) MGLLight *light; + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index af02c31b6d2..eb838085d72 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -14,6 +14,7 @@ #import "MGLStyle_Private.h" #import "MGLStyleLayer_Private.h" #import "MGLSource_Private.h" +#import "MGLLight_Private.h" #import "NSDate+MGLAdditions.h" @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -584,6 +586,21 @@ - (MGLTransition)transition return transition; } +#pragma mark Style light + +- (void)setLight:(MGLLight *)light +{ + std::unique_ptr mbglLight = std::make_unique([light mbglLight]); + self.mapView.mbglMap->setLight(std::move(mbglLight)); +} + +- (MGLLight *)light +{ + auto mbglLight = self.mapView.mbglMap->getLight(); + MGLLight *light = [[MGLLight alloc] initWithMBGLLight:mbglLight]; + return light; +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; name = %@, URL = %@>", diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h index 263b54d7e52..2155c657bd0 100644 --- a/platform/darwin/src/MGLStyleValue_Private.h +++ b/platform/darwin/src/MGLStyleValue_Private.h @@ -3,11 +3,13 @@ #import "MGLStyleValue.h" #import "NSValue+MGLStyleAttributeAdditions.h" +#import "NSValue+MGLAdditions.h" #import "MGLTypes.h" #import "MGLConversion.h" #include #include +#import #import @@ -415,6 +417,12 @@ class MGLStyleValueTransformer { mbglValue.push_back(mbglElement); } } + + void getMBGLValue(NSValue *rawValue, mbgl::style::Position &mbglValue) { + auto spherical = rawValue.mgl_lightPositionArrayValue; + mbgl::style::Position position(spherical); + mbglValue = position; + } // Enumerations template spherical = mbglStopValue.getSpherical(); + MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]); + return [NSValue valueWithMGLSphericalPosition:position]; + } // Enumerations template diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h index c06fd8b0e7f..16f510b5a6e 100644 --- a/platform/darwin/src/MGLTypes.h +++ b/platform/darwin/src/MGLTypes.h @@ -1,4 +1,5 @@ #import +#import #import "MGLFoundation.h" diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h index e6755021d00..0aaa2a337a4 100644 --- a/platform/darwin/src/NSValue+MGLAdditions.h +++ b/platform/darwin/src/NSValue+MGLAdditions.h @@ -1,6 +1,7 @@ #import #import "MGLGeometry.h" +#import "MGLLight.h" #import "MGLOfflinePack.h" #import "MGLTypes.h" @@ -87,6 +88,34 @@ NS_ASSUME_NONNULL_BEGIN */ @property (readonly) MGLTransition MGLTransitionValue; +/** + Creates a new value object containing the given `MGLSphericalPosition` + structure. + + @param lightPosition The value for the new object. + @return A new value object that contains the light position information. + */ ++ (instancetype)valueWithMGLSphericalPosition:(MGLSphericalPosition)lightPosition; + +/** + The `MGLSphericalPosition` structure representation of the value. + */ +@property (readonly) MGLSphericalPosition MGLSphericalPositionValue; + +/** + Creates a new value object containing the given `MGLLightAnchor` + enum. + + @param lightAnchor The value for the new object. + @return A new value object that contains the light anchor information. + */ ++ (NSValue *)valueWithMGLLightAnchor:(MGLLightAnchor)lightAnchor; + +/** + The `MGLLightAnchor` enum representation of the value. + */ +@property (readonly) MGLLightAnchor MGLLightAnchorValue; + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m index a95ef239417..ef894f0eb47 100644 --- a/platform/darwin/src/NSValue+MGLAdditions.m +++ b/platform/darwin/src/NSValue+MGLAdditions.m @@ -58,4 +58,27 @@ - (MGLTransition)MGLTransitionValue { return transition; } ++ (NSValue *)valueWithMGLSphericalPosition:(MGLSphericalPosition)lightPosition +{ + return [NSValue value:&lightPosition withObjCType:@encode(MGLSphericalPosition)]; +} + +- (MGLSphericalPosition)MGLSphericalPositionValue +{ + MGLSphericalPosition lightPosition; + [self getValue:&lightPosition]; + return lightPosition; +} + ++ (NSValue *)valueWithMGLLightAnchor:(MGLLightAnchor)lightAnchor { + return [NSValue value:&lightAnchor withObjCType:@encode(MGLLightAnchor)]; +} + +- (MGLLightAnchor)MGLLightAnchorValue +{ + MGLLightAnchor achorType; + [self getValue:&achorType]; + return achorType; +} + @end diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h index 60c1ee4075b..0f1e5116947 100644 --- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h +++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h @@ -9,5 +9,6 @@ - (std::array)mgl_offsetArrayValue; - (std::array)mgl_paddingArrayValue; +- (std::array)mgl_lightPositionArrayValue; @end diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm index e66145aec15..a41950b6b3e 100644 --- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm +++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm @@ -1,5 +1,5 @@ #import "NSValue+MGLStyleAttributeAdditions.h" - +#import "MGLLight.h" #if TARGET_OS_IPHONE #import #define MGLEdgeInsets UIEdgeInsets @@ -61,4 +61,17 @@ + (instancetype)mgl_valueWithPaddingArray:(std::array)paddingArray }; } +- (std::array)mgl_lightPositionArrayValue +{ + NSAssert(strcmp(self.objCType, @encode(MGLSphericalPosition)) == 0, @"Value does not represent an MGLSphericalPosition"); + MGLSphericalPosition lightPosition; + [self getValue:&lightPosition]; + // Style specification defines padding in clockwise order: top, right, bottom, left. + return { + static_cast(lightPosition.radial), + static_cast(lightPosition.azimuthal), + static_cast(lightPosition.polar), + }; +} + @end diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm new file mode 100644 index 00000000000..4639b13cded --- /dev/null +++ b/platform/darwin/test/MGLLightTest.mm @@ -0,0 +1,211 @@ +#import +#import + +#import "MGLLight_Private.h" + +#import "../../darwin/src/NSDate+MGLAdditions.h" + +#import +#import +#include + +@interface MGLLightTest : XCTestCase + +@end + +@implementation MGLLightTest + +- (void)testProperties { + + MGLTransition defaultTransition = MGLTransitionMake(0, 0); + MGLTransition transition = MGLTransitionMake(6, 3); + mbgl::style::TransitionOptions transitionOptions { { MGLDurationFromTimeInterval(6) }, { MGLDurationFromTimeInterval(3) } }; + + // anchor + { + mbgl::style::Light light; + MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + XCTAssertEqual(mglLight.anchor, MGLLightAnchorViewport); + XCTAssertEqual(mglLight.anchorTransition.delay, defaultTransition.delay); + XCTAssertEqual(mglLight.anchorTransition.duration, defaultTransition.duration); + + auto lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.getDefaultAnchor(), lightFromMGLlight.getAnchor().asConstant()); + auto anchorTransition = lightFromMGLlight.getAnchorTransition(); + XCTAssert(anchorTransition.delay && MGLTimeIntervalFromDuration(*anchorTransition.delay) == defaultTransition.delay); + XCTAssert(anchorTransition.duration && MGLTimeIntervalFromDuration(*anchorTransition.duration) == defaultTransition.duration); + + mglLight.anchor = MGLLightAnchorMap; + mglLight.anchorTransition = transition; + + XCTAssertEqual(mglLight.anchor, MGLLightAnchorMap); + XCTAssertEqual(mglLight.anchorTransition.delay, transition.delay); + XCTAssertEqual(mglLight.anchorTransition.duration, transition.duration); + + mbgl::style::PropertyValue anchorProperty = { mbgl::style::LightAnchorType::Map }; + light.setAnchor(anchorProperty); + light.setAnchorTransition(transitionOptions); + + lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.getAnchor().asConstant(), lightFromMGLlight.getAnchor().asConstant()); + anchorTransition = lightFromMGLlight.getAnchorTransition(); + XCTAssert(anchorTransition.delay && MGLTimeIntervalFromDuration(*anchorTransition.delay) == transition.delay); + XCTAssert(anchorTransition.duration && MGLTimeIntervalFromDuration(*anchorTransition.duration) == transition.duration); + + } + + // position + { + mbgl::style::Light light; + MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + NSAssert([mglLight.position isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.position isn’t a MGLConstantStyleValue."); + NSValue *positionValue = ((MGLConstantStyleValue *)mglLight.position).rawValue; + auto positionArray = light.getDefaultPosition().getSpherical(); + MGLSphericalPosition defaultPosition = MGLSphericalPositionMake(positionArray[0], positionArray[1], positionArray[2]); + + XCTAssert(defaultPosition.radial == positionValue.MGLSphericalPositionValue.radial); + XCTAssert(defaultPosition.azimuthal == positionValue.MGLSphericalPositionValue.azimuthal); + XCTAssert(defaultPosition.polar == positionValue.MGLSphericalPositionValue.polar); + XCTAssertEqual(mglLight.positionTransiton.delay, defaultTransition.delay); + XCTAssertEqual(mglLight.positionTransiton.duration, defaultTransition.duration); + + auto lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical()); + auto positionTransition = lightFromMGLlight.getPositionTransition(); + XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == defaultTransition.delay); + XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == defaultTransition.duration); + + defaultPosition = MGLSphericalPositionMake(6, 180, 90); + MGLStyleValue *positionStyleValue = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLSphericalPosition:defaultPosition]]; + mglLight.position = positionStyleValue; + mglLight.positionTransiton = transition; + + NSAssert([mglLight.position isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.position isn’t a MGLConstantStyleValue."); + positionValue = ((MGLConstantStyleValue *)mglLight.position).rawValue; + + XCTAssert(defaultPosition.radial == positionValue.MGLSphericalPositionValue.radial); + XCTAssert(defaultPosition.azimuthal == positionValue.MGLSphericalPositionValue.azimuthal); + XCTAssert(defaultPosition.polar == positionValue.MGLSphericalPositionValue.polar); + XCTAssertEqual(mglLight.positionTransiton.delay, transition.delay); + XCTAssertEqual(mglLight.positionTransiton.duration, transition.duration); + + lightFromMGLlight = [mglLight mbglLight]; + + positionArray = { { 6, 180, 90 } }; + mbgl::style::Position position = { positionArray }; + mbgl::style::PropertyValue positionProperty = { position }; + light.setPosition(positionProperty); + light.setPositionTransition(transitionOptions); + + XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical()); + positionTransition = lightFromMGLlight.getPositionTransition(); + XCTAssert(positionTransition.delay && MGLTimeIntervalFromDuration(*positionTransition.delay) == transition.delay); + XCTAssert(positionTransition.duration && MGLTimeIntervalFromDuration(*positionTransition.duration) == transition.duration); + + } + + // color + { + mbgl::style::Light light; + MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + NSAssert([mglLight.color isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.color isn’t a MGLConstantStyleValue."); + MGLColor *colorValue = ((MGLConstantStyleValue *)mglLight.color).rawValue; + auto color = light.getDefaultColor(); + const CGFloat *colorComponents = CGColorGetComponents(colorValue.CGColor); + + XCTAssert(color.r == colorComponents[0] && color.g == colorComponents[1] && color.b == colorComponents[2] && + color.a == colorComponents[3]); + XCTAssertEqual(mglLight.colorTransiton.delay, defaultTransition.delay); + XCTAssertEqual(mglLight.colorTransiton.duration, defaultTransition.duration); + + auto lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(color, lightFromMGLlight.getColor().asConstant()); + auto colorTransition = lightFromMGLlight.getColorTransition(); + XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == defaultTransition.delay); + XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == defaultTransition.duration); + + MGLStyleValue *colorStyleValue = [MGLStyleValue valueWithRawValue:[MGLColor blackColor]]; + mglLight.color = colorStyleValue; + mglLight.colorTransiton = transition; + + NSAssert([mglLight.color isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.color isn’t a MGLConstantStyleValue."); + colorValue = ((MGLConstantStyleValue *)mglLight.color).rawValue; + + XCTAssertEqual([MGLColor blackColor], colorValue); + XCTAssertEqual(mglLight.colorTransiton.delay, transition.delay); + XCTAssertEqual(mglLight.colorTransiton.duration, transition.duration); + + mbgl::style::PropertyValue colorProperty = { { 0, 0, 0, 1 } }; + light.setColor(colorProperty); + light.setColorTransition(transitionOptions); + + lightFromMGLlight = [mglLight mbglLight]; + + colorComponents = CGColorGetComponents(colorValue.CGColor); + color = lightFromMGLlight.getColor().asConstant(); + XCTAssertEqual(light.getColor().asConstant(),lightFromMGLlight.getColor().asConstant()); + colorTransition = lightFromMGLlight.getColorTransition(); + XCTAssert(colorTransition.delay && MGLTimeIntervalFromDuration(*colorTransition.delay) == transition.delay); + XCTAssert(colorTransition.duration && MGLTimeIntervalFromDuration(*colorTransition.duration) == transition.duration); + } + + // intensity + { + mbgl::style::Light light; + MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + NSAssert([mglLight.intensity isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.intensity isn’t a MGLConstantStyleValue."); + NSNumber *intensityNumber = ((MGLConstantStyleValue *)mglLight.intensity).rawValue; + auto intensity = light.getDefaultIntensity(); + + XCTAssert(intensityNumber.floatValue == intensity); + XCTAssertEqual(mglLight.intensityTransition.delay, defaultTransition.delay); + XCTAssertEqual(mglLight.intensityTransition.duration, defaultTransition.duration); + + auto lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(intensity, lightFromMGLlight.getIntensity().asConstant()); + auto intensityTransition = lightFromMGLlight.getIntensityTransition(); + XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == defaultTransition.delay); + XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == defaultTransition.duration); + + NSNumber *intensityValue = @0.4; + MGLStyleValue *intensityStyleValue = [MGLStyleValue valueWithRawValue:intensityValue]; + mglLight.intensity = intensityStyleValue; + mglLight.intensityTransition = transition; + + NSAssert([mglLight.intensity isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.intensity isn’t a MGLConstantStyleValue."); + intensityNumber = ((MGLConstantStyleValue *)mglLight.intensity).rawValue; + XCTAssert(intensityNumber.floatValue == intensityValue.floatValue); + XCTAssertEqual(mglLight.intensityTransition.delay, transition.delay); + XCTAssertEqual(mglLight.intensityTransition.duration, transition.duration); + + mbgl::style::PropertyValue intensityProperty = { 0.4 }; + light.setIntensity(intensityProperty); + light.setIntensityTransition(transitionOptions); + + lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.getIntensity().asConstant(), lightFromMGLlight.getIntensity().asConstant()); + intensityTransition = lightFromMGLlight.getIntensityTransition(); + XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == transition.delay); + XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == transition.duration); + + } + +} + +- (void)testValueAdditions { + MGLSphericalPosition position = MGLSphericalPositionMake(1.15, 210, 30); + + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.radial, position.radial); + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.azimuthal, position.azimuthal); + XCTAssertEqual([NSValue valueWithMGLSphericalPosition:position].MGLSphericalPositionValue.polar, position.polar); + XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorMap].MGLLightAnchorValue, MGLLightAnchorMap); + XCTAssertEqual([NSValue valueWithMGLLightAnchor:MGLLightAnchorViewport].MGLLightAnchorValue, MGLLightAnchorViewport); +} + +@end diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 215d31810dc..27582c1acfb 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -9,6 +9,13 @@ /* Begin PBXBuildFile section */ 1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; }; 1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; }; + 1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; }; + 1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; }; + 1F7454931ECBB43F00021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F7454961ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; }; + 1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; }; + 1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */; }; 1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */; }; 30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; }; 30E578181DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; }; @@ -545,6 +552,10 @@ /* Begin PBXFileReference section */ 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = ""; }; + 1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = ""; }; + 1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = ""; }; + 1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = ""; }; + 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLLightTest.mm; path = ../../darwin/test/MGLLightTest.mm; sourceTree = ""; }; 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = ""; }; 20DABE861DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Foundation.strings"; sourceTree = ""; }; 20DABE881DF78148007AC5FF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; @@ -1039,6 +1050,9 @@ 35599DB81D46AD7F0048254D /* Categories */, 353933F01D3FB6BA003F57D7 /* Layers */, 35136D491D4277EA00C20EFD /* Sources */, + 1F0666881EC64F8E001C16D7 /* MGLLight.h */, + 1F0666891EC64F8E001C16D7 /* MGLLight.mm */, + 1F7454941ECD450D00021D39 /* MGLLight_Private.h */, DAAF72291DA903C700312FA4 /* MGLStyleValue.h */, DAAF722A1DA903C700312FA4 /* MGLStyleValue_Private.h */, 35599DEA1D46F14E0048254D /* MGLStyleValue.mm */, @@ -1069,6 +1083,7 @@ children = ( 3575798F1D513EF1000B822E /* Layers */, 40CFA64E1D78754A008103BD /* Sources */, + 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */, 357F09091DF84F3800941873 /* MGLStyleValueTests.h */, 3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */, DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */, @@ -1657,6 +1672,7 @@ DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */, 7E016D841D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */, 400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */, + 1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */, 4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */, 40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */, 4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */, @@ -1705,6 +1721,7 @@ 353933F21D3FB753003F57D7 /* MGLCircleStyleLayer.h in Headers */, DA8847F31CBAFA5100AB86E3 /* MGLMultiPoint.h in Headers */, 30E578171DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */, + 1F7454961ECD450D00021D39 /* MGLLight_Private.h in Headers */, DAD1656C1CF41981001FF4B9 /* MGLFeature.h in Headers */, 40EDA1C01CFE0E0200D9EA68 /* MGLAnnotationContainerView.h in Headers */, 9620BB381E69FE1700705A1D /* MGLSDKUpdateChecker.h in Headers */, @@ -1783,6 +1800,7 @@ 35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */, DABFB8671CBE99E500D62B32 /* MGLPolygon.h in Headers */, 404C26E81D89C55D000AA13D /* MGLTileSource_Private.h in Headers */, + 1F7454931ECBB43F00021D39 /* MGLLight.h in Headers */, DAAF722C1DA903C700312FA4 /* MGLStyleValue.h in Headers */, DABFB8651CBE99E500D62B32 /* MGLOverlay.h in Headers */, 35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */, @@ -1816,6 +1834,7 @@ DA35A2BC1CCA9A6900E826B2 /* MGLClockDirectionFormatter.h in Headers */, 35D13AC41D3D19DD00AFB4E0 /* MGLFillStyleLayer.h in Headers */, DABFB86E1CBE9A0F00D62B32 /* MGLCalloutView.h in Headers */, + 1F7454971ECD450D00021D39 /* MGLLight_Private.h in Headers */, DABFB8601CBE99E500D62B32 /* MGLMapCamera.h in Headers */, DA737EE21D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */, DAF0D8191DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */, @@ -2166,6 +2185,7 @@ DAE7DEC21E245455007505A6 /* MGLNSStringAdditionsTests.m in Sources */, 4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */, DAEDC4341D603417000224FF /* MGLAttributionInfoTests.m in Sources */, + 1F7454A91ED08AB400021D39 /* MGLLightTest.mm in Sources */, 357579851D502AF5000B822E /* MGLSymbolStyleLayerTests.mm in Sources */, 357579871D502AFE000B822E /* MGLLineStyleLayerTests.mm in Sources */, 357579891D502B06000B822E /* MGLCircleStyleLayerTests.mm in Sources */, @@ -2221,6 +2241,7 @@ 3566C76E1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */, DA88488C1CBB037E00AB86E3 /* SMCalloutView.m in Sources */, 35136D4E1D4277FC00C20EFD /* MGLSource.mm in Sources */, + 1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */, DA35A2B81CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */, DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */, 35136D451D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */, @@ -2328,6 +2349,7 @@ DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */, DAA4E41E1CBB730400178DFB /* MGLMapCamera.mm in Sources */, FA68F14E1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.mm in Sources */, + 1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */, 404C26E51D89B877000AA13D /* MGLTileSource.mm in Sources */, 355AE0021E9281DA00F3939D /* MGLScaleBar.mm in Sources */, 4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index 9a9dc702cab..67a26e8ed48 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -19,6 +19,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[]; #import "MGLDistanceFormatter.h" #import "MGLFeature.h" #import "MGLGeometry.h" +#import "MGLLight.h" #import "MGLMapCamera.h" #import "MGLMapView.h" #import "MGLMapView+IBAdditions.h" diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 9a18ce4a0e0..11275240981 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -8,6 +8,10 @@ /* Begin PBXBuildFile section */ 1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */; }; + 1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */; }; + 1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A11ECFB00300021D39 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A21ECFB00300021D39 /* MGLLight.mm */; }; + 1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */; }; 1F95931B1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */; }; 30E5781B1DAA857E0050F07E /* NSImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */; }; 3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */; }; @@ -268,6 +272,10 @@ /* Begin PBXFileReference section */ 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = ""; }; + 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = ""; }; + 1F7454A11ECFB00300021D39 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = ""; }; + 1F7454A21ECFB00300021D39 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = ""; }; + 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLightTest.mm; sourceTree = ""; }; 1F95931A1E6DE2B600D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = ""; }; 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSImage+MGLAdditions.h"; path = "src/NSImage+MGLAdditions.h"; sourceTree = SOURCE_ROOT; }; 3508EC621D749D39009B0EE4 /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = ""; }; @@ -670,6 +678,9 @@ 352742771D4C220900A1ECE6 /* MGLStyleValue.h */, DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */, 3527429E1D4C25BD00A1ECE6 /* MGLStyleValue.mm */, + 1F7454A11ECFB00300021D39 /* MGLLight.h */, + 1F7454A21ECFB00300021D39 /* MGLLight.mm */, + 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */, ); name = Styling; sourceTree = ""; @@ -810,6 +821,7 @@ children = ( DA8F257C1D51C5F40010E6B5 /* Layers */, DA87A99A1DC9D88800810D09 /* Sources */, + 1F7454AA1ED1DDBD00021D39 /* MGLLightTest.mm */, 353722EB1DF850ED004D2F3F /* MGLStyleValueTests.h */, 3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */, DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */, @@ -1133,6 +1145,7 @@ DA8F258B1D51CA540010E6B5 /* MGLLineStyleLayer.h in Headers */, 35C6DF841E214C0400ACA483 /* MGLDistanceFormatter.h in Headers */, DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */, + 1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */, 359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */, DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */, 408AA8661DAEEE3600022900 /* MGLPolyline+MGLAdditions.h in Headers */, @@ -1166,6 +1179,7 @@ DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */, DA6408D71DA4E5DA00908C90 /* MGLVectorStyleLayer.h in Headers */, 352742891D4C245800A1ECE6 /* MGLShapeSource.h in Headers */, + 1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */, 408AA8671DAEEE3900022900 /* NSDictionary+MGLAdditions.h in Headers */, DAE6C3671CC31E0400DB3429 /* MGLStyle.h in Headers */, ); @@ -1380,6 +1394,7 @@ DAE6C38C1CC31E2A00DB3429 /* MGLOfflinePack.mm in Sources */, 35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */, DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */, + 1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */, DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */, 3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */, DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */, @@ -1446,6 +1461,7 @@ DA35A2C21CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m in Sources */, DAE6C3D41CC34C9900DB3429 /* MGLOfflineRegionTests.m in Sources */, DAE6C3D61CC34C9900DB3429 /* MGLStyleTests.mm in Sources */, + 1F7454AB1ED1DDBD00021D39 /* MGLLightTest.mm in Sources */, DAEDC4371D606291000224FF /* MGLAttributionButtonTests.m in Sources */, 920A3E591E6F859D00C16EFC /* MGLSourceQueryTests.m in Sources */, DA35A2B61CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */, diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h index dcb5b50b8f2..0f47dace708 100644 --- a/platform/macos/src/Mapbox.h +++ b/platform/macos/src/Mapbox.h @@ -17,6 +17,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[]; #import "MGLDistanceFormatter.h" #import "MGLFeature.h" #import "MGLGeometry.h" +#import "MGLLight.h" #import "MGLMapCamera.h" #import "MGLMapView.h" #import "MGLMapView+IBAdditions.h"