summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/src/MGLLight.h125
-rw-r--r--platform/darwin/src/MGLLight.mm117
-rw-r--r--platform/darwin/src/MGLLight_Private.h23
-rw-r--r--platform/darwin/src/MGLStyle.h9
-rw-r--r--platform/darwin/src/MGLStyle.mm17
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h14
-rw-r--r--platform/darwin/src/MGLTypes.h1
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.h29
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.m23
-rw-r--r--platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h1
-rw-r--r--platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm15
-rw-r--r--platform/darwin/test/MGLLightTest.mm211
12 files changed, 584 insertions, 1 deletions
diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h
new file mode 100644
index 0000000000..d9a22d60fa
--- /dev/null
+++ b/platform/darwin/src/MGLLight.h
@@ -0,0 +1,125 @@
+#import <CoreLocation/CoreLocation.h>
+
+#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 <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-anchor"><code>anchor</code></a>
+ 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 <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-position"><code>position</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<NSValue *> * 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 <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-color"><code>color</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) MGLStyleValue<UIColor *> *color;
+#else
+
+/**
+ Color tint for lighting extruded geometries.
+ */
+@property (nonatomic) MGLStyleValue<NSColor *> *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 <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-intensity"><code>intensity</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property(nonatomic) MGLStyleValue<NSNumber *> *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 0000000000..02d55e76ed
--- /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 <mbgl/style/light.hpp>
+#import <mbgl/style/types.hpp>
+
+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<NSValue *> *anchorStyleValue;
+ if (anchor.isUndefined()) {
+ mbgl::style::PropertyValue<mbgl::style::LightAnchorType> defaultAnchor = mbglLight->getDefaultAnchor();
+ anchorStyleValue = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumStyleValue(defaultAnchor);
+ } else {
+ anchorStyleValue = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().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<mbgl::style::Position, NSValue *>().toStyleValue(mbglLight->getDefaultPosition());
+ } else {
+ _position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toStyleValue(positionValue);
+ }
+
+ _positionTransiton = MGLTransitionFromOptions(mbglLight->getPositionTransition());
+
+ auto colorValue = mbglLight->getColor();
+ if (colorValue.isUndefined()) {
+ _color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(mbglLight->getDefaultColor());
+ } else {
+ _color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(colorValue);
+ }
+
+ _colorTransiton = MGLTransitionFromOptions(mbglLight->getColorTransition());
+
+ auto intensityValue = mbglLight->getIntensity();
+ if (intensityValue.isUndefined()) {
+ _intensity = MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(mbglLight->getDefaultIntensity());
+ } else {
+ _intensity = MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(intensityValue);
+ }
+
+ _intensityTransition = MGLTransitionFromOptions(mbglLight->getIntensityTransition());
+ }
+
+ return self;
+}
+
+- (mbgl::style::Light)mbglLight
+{
+ mbgl::style::Light mbglLight;
+
+ MGLStyleValue<NSValue *> *anchorType = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLLightAnchor:self.anchor]];
+ auto anchor = MGLStyleValueTransformer<mbgl::style::LightAnchorType, NSValue *, mbgl::style::LightAnchorType, MGLLightAnchor>().toEnumPropertyValue(anchorType);
+ mbglLight.setAnchor(anchor);
+
+
+ mbglLight.setAnchorTransition(MGLOptionsFromTransition(self.anchorTransition));
+
+ auto position = MGLStyleValueTransformer<mbgl::style::Position, NSValue *>().toInterpolatablePropertyValue(self.position);
+ mbglLight.setPosition(position);
+
+ mbglLight.setPositionTransition(MGLOptionsFromTransition(self.positionTransiton));
+
+ auto color = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toInterpolatablePropertyValue(self.color);
+ mbglLight.setColor(color);
+
+ mbglLight.setColorTransition(MGLOptionsFromTransition(self.colorTransiton));
+
+ auto intensity = MGLStyleValueTransformer<float, NSNumber *>().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 0000000000..dbc29c1eff
--- /dev/null
+++ b/platform/darwin/src/MGLLight_Private.h
@@ -0,0 +1,23 @@
+#import <Foundation/Foundation.h>
+
+#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 26434eb492..08c6c047f1 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 af02c31b6d..eb838085d7 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 <mbgl/map/map.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/style/image.hpp>
+#include <mbgl/style/light.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
@@ -584,6 +586,21 @@ static NSURL *MGLStyleURL_emerald;
return transition;
}
+#pragma mark Style light
+
+- (void)setLight:(MGLLight *)light
+{
+ std::unique_ptr<mbgl::style::Light> mbglLight = std::make_unique<mbgl::style::Light>([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 263b54d7e5..2155c657bd 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 <mbgl/style/conversion/data_driven_property_value.hpp>
#include <mbgl/style/conversion.hpp>
+#import <mbgl/style/types.hpp>
#import <mbgl/util/enum.hpp>
@@ -415,6 +417,12 @@ private: // Private utilities for converting from mgl to mbgl values
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 <typename MBGLEnum = MBGLType,
@@ -473,6 +481,12 @@ private: // Private utilities for converting from mbgl to mgl values
}
return array;
}
+
+ static NSValue *toMGLRawStyleValue(const mbgl::style::Position &mbglStopValue) {
+ std::array<float, 3> spherical = mbglStopValue.getSpherical();
+ MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]);
+ return [NSValue valueWithMGLSphericalPosition:position];
+ }
// Enumerations
template <typename MBGLEnum = MBGLType, typename MGLEnum = ObjCEnum>
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index c06fd8b0e7..16f510b5a6 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -1,4 +1,5 @@
#import <Foundation/Foundation.h>
+#import <CoreGraphics/CoreGraphics.h>
#import "MGLFoundation.h"
diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h
index e6755021d0..0aaa2a337a 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.h
+++ b/platform/darwin/src/NSValue+MGLAdditions.h
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#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 a95ef23941..ef894f0eb4 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.m
+++ b/platform/darwin/src/NSValue+MGLAdditions.m
@@ -58,4 +58,27 @@
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 60c1ee4075..0f1e511694 100644
--- a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
+++ b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h
@@ -9,5 +9,6 @@
- (std::array<float, 2>)mgl_offsetArrayValue;
- (std::array<float, 4>)mgl_paddingArrayValue;
+- (std::array<float, 3>)mgl_lightPositionArrayValue;
@end
diff --git a/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm b/platform/darwin/src/NSValue+MGLStyleAttributeAdditions.mm
index e66145aec1..a41950b6b3 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 <UIKit/UIKit.h>
#define MGLEdgeInsets UIEdgeInsets
@@ -61,4 +61,17 @@
};
}
+- (std::array<float, 3>)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<float>(lightPosition.radial),
+ static_cast<float>(lightPosition.azimuthal),
+ static_cast<float>(lightPosition.polar),
+ };
+}
+
@end
diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm
new file mode 100644
index 0000000000..4639b13cde
--- /dev/null
+++ b/platform/darwin/test/MGLLightTest.mm
@@ -0,0 +1,211 @@
+#import <XCTest/XCTest.h>
+#import <Mapbox/Mapbox.h>
+
+#import "MGLLight_Private.h"
+
+#import "../../darwin/src/NSDate+MGLAdditions.h"
+
+#import <mbgl/style/light.hpp>
+#import <mbgl/style/types.hpp>
+#include <mbgl/style/transition_options.hpp>
+
+@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<mbgl::style::LightAnchorType> 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<NSValue *> *positionStyleValue = [MGLStyleValue<NSValue *> 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<mbgl::style::Position> 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<MGLColor *> *colorStyleValue = [MGLStyleValue<MGLColor *> 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<mbgl::Color> 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<NSNumber *> *intensityStyleValue = [MGLStyleValue<NSNumber *> 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<float> 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