diff --git a/include/mbgl/style/position.hpp b/include/mbgl/style/position.hpp index 3be8d1c55e0..078e62bda89 100644 --- a/include/mbgl/style/position.hpp +++ b/include/mbgl/style/position.hpp @@ -9,7 +9,7 @@ namespace style { class Position { public: Position() = default; - Position(std::array& position_) + Position(const std::array& position_) : radial(position_[0]), azimuthal(position_[1]), polar(position_[2]) { calculateCartesian(); }; diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 7efc8d441cf..5a4936c0ee9 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -149,6 +149,9 @@ global.mbglTestValue = function (property, layerType) { type = 'Alignment'; } let value = camelize(_.last(_.keys(property.values))); + if (property['light-property']) { + return `mbgl::style::Light${type}Type::${value}`; + } return `mbgl::style::${type}Type::${value}`; } case 'color': @@ -225,6 +228,9 @@ global.propertyDoc = function (propertyName, property, layerType, kind) { let doc = property.doc.replace(/`([^`]+?)` is set to `([^`]+?)`/g, function (m, peerPropertyName, propertyValue, offset, str) { let otherProperty = camelizeWithLeadingLowercase(peerPropertyName); let otherValue = objCType(layerType, peerPropertyName) + camelize(propertyValue); + if (property.type == 'array' && kind == 'light') { + otherValue = propertyValue; + } return '`' + `${otherProperty}` + '` is set to `' + `${otherValue}` + '`'; }); // Match references to our own property values. @@ -256,7 +262,7 @@ global.propertyDoc = function (propertyName, property, layerType, kind) { if (kind !== 'enum') { if ('default' in property) { doc += `\n\nThe default value of this property is ${propertyDefault(property, layerType)}.`; - if (!property.required) { + if (!property.required && kind != 'light') { doc += ' Set this property to `nil` to reset it to the default value.'; } } @@ -348,6 +354,8 @@ global.describeValue = function (value, property, layerType) { let objCType = global.objCType(layerType, property.name); return `${conjunction}\`${objCType}${camelize(possibleValue)}\``; }).join(separator); + } else if (property['light-property']) { + displayValue = `\`${prefix}Light${camelize(property.name)}${camelize(value)}\``; } else { let objCType = global.objCType(layerType, property.name); displayValue = `\`${objCType}${camelize(value)}\``; @@ -382,6 +390,8 @@ global.describeValue = function (value, property, layerType) { case 'offset': case 'translate': return 'an `NSValue` object containing a `CGVector` struct set to' + ` ${value[0]}${units} rightward and ${value[1]}${units} downward`; + case 'position': + return 'an `MGLSphericalPosition` struct set to' + ` ${value[0]} radial, ${value[1]} azimuthal and ${value[2]} polar`; default: return 'the array `' + value.join('`, `') + '`'; } @@ -418,6 +428,7 @@ global.propertyType = function (property) { return 'NSArray *'; case 'padding': return 'NSValue *'; + case 'position': case 'offset': case 'translate': return 'NSValue *'; @@ -457,6 +468,8 @@ global.valueTransformerArguments = function (property) { return ['std::vector', objCType, 'std::string']; case 'padding': return ['std::array', objCType]; + case 'position': + return ['mbgl::style::Position', objCType]; case 'offset': case 'translate': return ['std::array', objCType]; @@ -478,6 +491,9 @@ global.mbglType = function(property) { return 'std::string'; case 'enum': { let type = camelize(originalPropertyName(property)); + if (property['light-property']) { + return `mbgl::style::Light${type}Type`; + } if (/-translate-anchor$/.test(originalPropertyName(property))) { type = 'TranslateAnchor'; } @@ -499,6 +515,8 @@ global.mbglType = function(property) { case 'offset': case 'translate': return 'std::array'; + case 'position': + return 'mbgl::style::Position'; default: throw new Error(`unknown array type for ${property.name}`); } @@ -519,6 +537,17 @@ global.setSourceLayer = function() { return `_layer->setSourceLayer(sourceLayer.UTF8String);` }; +const lightProperties = Object.keys(spec['light']).reduce((memo, name) => { + var property = spec['light'][name]; + property.name = name; + property['light-property'] = true; + memo.push(property); + return memo; +}, []); + +const lightDoc = spec['light-cocoa-doc']; +const lightType = 'light'; + const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.ejs', 'utf8'), { strict: true }); const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true}); const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true}); @@ -526,6 +555,14 @@ const forStyleAuthorsMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guid const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs', 'utf8'), { strict: true }); const templatesMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Tile URL Templates.md.ejs', 'utf8'), { strict: true }); +const lightH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLLight.h.ejs', 'utf8'), {strict: true}); +const lightM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLLight.mm.ejs', 'utf8'), {strict: true}); +const testLight = ejs.compile(fs.readFileSync('platform/darwin/test/MGLLightTest.mm.ejs', 'utf8'), { strict: true}); +fs.writeFileSync(`platform/darwin/src/MGLLight.h`, duplicatePlatformDecls(lightH({ properties: lightProperties, doc: lightDoc, type: lightType }))); +fs.writeFileSync(`platform/darwin/src/MGLLight.mm`, lightM({ properties: lightProperties, doc: lightDoc, type: lightType })); +fs.writeFileSync(`platform/darwin/test/MGLLightTest.mm`, testLight({ properties: lightProperties, doc: lightDoc, type: lightType })); + + const layers = _(spec.layer.type.values).map((value, layerType) => { const layoutProperties = Object.keys(spec[`layout_${layerType}`]).reduce((memo, name) => { if (name !== 'visibility') { diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json index a594ef2957e..67a6641fe7b 100644 --- a/platform/darwin/scripts/style-spec-overrides-v8.json +++ b/platform/darwin/scripts/style-spec-overrides-v8.json @@ -1,4 +1,10 @@ { + "light-cocoa-doc": "An `MGLLight` object represents the light source for extruded geometries in `MGLStyle`.", + "light": { + "position": { + "doc": "Position of the `MGLLight` source relative to lit (extruded) geometries, in a `MGLSphericalPosition` struct [radial coordinate, azimuthal angle, polar angle] where radial indicates the distance from the center of the base of an object to its light, azimuthal indicates the position of the light relative to 0° (0° when `MGLLight.anchor` is set to `MGLLightAnchorViewport` corresponds to the top of the viewport, or 0° when `MGLLight.anchor` is set to `MGLLightAnchorMap` corresponds to due north, and degrees proceed clockwise), and polar indicates the height of the light (from 0°, directly above, to 180°, directly below)." + } + }, "layer": { "type": { "values": { diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h index ef9811bd33c..55b789f0432 100644 --- a/platform/darwin/src/MGLLight.h +++ b/platform/darwin/src/MGLLight.h @@ -1,3 +1,6 @@ +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. + #import #import "MGLFoundation.h" @@ -5,13 +8,19 @@ NS_ASSUME_NONNULL_BEGIN - -/** Options to specify extruded geometries are lit relative to the map or viewport. */ +/** + Whether 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. */ + /** + 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 + /** + The position of the light source is aligned to the rotation of the + viewport. + */ + MGLLightAnchorViewport, }; /** @@ -20,7 +29,7 @@ typedef NS_ENUM(NSUInteger, MGLLightAnchor) { */ typedef struct MGLSphericalPosition { /** Distance from the center of the base of an object to its light. */ - CLLocationDistance radial; + CGFloat 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). */ @@ -38,7 +47,7 @@ typedef struct MGLSphericalPosition { @return Returns a `MGLSphericalPosition` struct containing the position attributes. */ -NS_INLINE MGLSphericalPosition MGLSphericalPositionMake(CLLocationDistance radial, CLLocationDirection azimuthal, CLLocationDirection polar) { +NS_INLINE MGLSphericalPosition MGLSphericalPositionMake(CGFloat radial, CLLocationDirection azimuthal, CLLocationDirection polar) { MGLSphericalPosition position; position.radial = radial; position.azimuthal = azimuthal; @@ -54,8 +63,17 @@ MGL_EXPORT @interface MGLLight : NSObject /** - `anchor` Whether extruded geometries are lit relative to the map or viewport. + Whether extruded geometries are lit relative to the map or viewport. + + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLLightAnchorViewport`. + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of + `MGLInterpolationModeInterval` + This property corresponds to the anchor light property in the Mapbox Style Specification. @@ -63,14 +81,25 @@ MGL_EXPORT @property (nonatomic) MGLStyleValue *anchor; /** - Values describing animated transitions to `anchor` property. - */ -@property (nonatomic) MGLTransition anchorTransition; - - -/** - Position of the light source relative to lit (extruded) geometries. + Position of the `MGLLight` source relative to lit (extruded) geometries, in a + `MGLSphericalPosition` struct [radial coordinate, azimuthal angle, polar angle] + where radial indicates the distance from the center of the base of an object to + its light, azimuthal indicates the position of the light relative to 0° (0° + when `MGLLight.anchor` is set to `MGLLightAnchorViewport` corresponds to the + top of the viewport, or 0° when `MGLLight.anchor` is set to `MGLLightAnchorMap` + corresponds to due north, and degrees proceed clockwise), and polar indicates + the height of the light (from 0°, directly above, to 180°, directly below). + + The default value of this property is an `MGLStyleValue` object containing an + `MGLSphericalPosition` struct set to 1.15 radial, 210 azimuthal and 30 polar. + + You can set this property to an instance of: + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + This property corresponds to the position light property in the Mapbox Style Specification. @@ -78,48 +107,87 @@ MGL_EXPORT @property (nonatomic) MGLStyleValue *position; /** - Values describing animated transitions to `position` property. - */ -@property (nonatomic) MGLTransition positionTransiton; + The transition affecting any changes to this layer’s `position` property. + This property corresponds to the `position-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition positionTransition; #if TARGET_OS_IPHONE /** Color tint for lighting extruded geometries. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.whiteColor`. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + This property corresponds to the color light property in the Mapbox Style Specification. */ @property (nonatomic) MGLStyleValue *color; #else - /** Color tint for lighting extruded geometries. + + The default value of this property is an `MGLStyleValue` object containing + `NSColor.whiteColor`. + + You can set this property to an instance of: + + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + + This property corresponds to the color + light property in the Mapbox Style Specification. */ @property (nonatomic) MGLStyleValue *color; #endif /** - Values describing animated transitions to `color` property. - */ -@property (nonatomic) MGLTransition colorTransiton; + The transition affecting any changes to this layer’s `color` property. + This property corresponds to the `color-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition colorTransition; /** - Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as more extreme contrast. + Intensity of lighting (on a scale from 0 to 1). Higher numbers will present as + more extreme contrast. + + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0.5`. + + You can set this property to an instance of: + * `MGLConstantStyleValue` + * `MGLCameraStyleFunction` with an interpolation mode of: + * `MGLInterpolationModeExponential` + * `MGLInterpolationModeInterval` + This property corresponds to the intensity light property in the Mapbox Style Specification. */ -@property(nonatomic) MGLStyleValue *intensity; +@property (nonatomic) MGLStyleValue *intensity; /** - Values describing animated transitions to `intensity` property. - */ + The transition affecting any changes to this layer’s `intensity` property. + + This property corresponds to the `intensity-transition` property in the style JSON file format. +*/ @property (nonatomic) MGLTransition intensityTransition; + @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLLight.h.ejs b/platform/darwin/src/MGLLight.h.ejs new file mode 100644 index 00000000000..26ecefc3af6 --- /dev/null +++ b/platform/darwin/src/MGLLight.h.ejs @@ -0,0 +1,100 @@ +<% + const properties = locals.properties; + const type = locals.type; + const doc = locals.doc; +-%> +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. + +#import + +#import "MGLFoundation.h" +#import "MGLStyleValue.h" + +NS_ASSUME_NONNULL_BEGIN + +<% for (const property of properties) { -%> +<% if (property.type == "enum") { -%> +/** +<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %> + */ +typedef NS_ENUM(NSUInteger, MGLLight<%- camelize(property.name) %>) { +<% for (const value in property.values) { -%> + /** +<%- propertyDoc(property.name, property.values[value], type, 'enum').wrap(80, 4+1) %> + */ + MGLLightAnchor<%- camelize(value) %>, +<% } -%> +}; +<% } -%> +<% } -%> + +/** + 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. */ + CGFloat 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(CGFloat radial, CLLocationDirection azimuthal, CLLocationDirection polar) { + MGLSphericalPosition position; + position.radial = radial; + position.azimuthal = azimuthal; + position.polar = polar; + + return position; +} + +/** + <%- doc %> + */ +MGL_EXPORT +@interface MGLLight : NSObject +<% if (properties.length) { -%> + +<% for (const property of properties) { -%> +/** +<%- propertyDoc(property.name, property, type, 'light').wrap(80, 1) %> + + This property corresponds to the <%- originalPropertyName(property) %> + light property in the Mapbox Style Specification. + */ +@property (nonatomic<% if (property.getter) { %>, getter=<%- objCGetter(property) -%><% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; + +<% if (property.transition) { -%> +/** + The transition affecting any changes to this layer’s `<%- camelizeWithLeadingLowercase(property.name) %>` property. + + This property corresponds to the `<%- originalPropertyName(property) %>-transition` property in the style JSON file format. +*/ +@property (nonatomic) MGLTransition <%- camelizeWithLeadingLowercase(property.name) %>Transition; + +<% } -%> +<% if (property.original) { -%> +@property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> __attribute__((unavailable("Use <%- camelizeWithLeadingLowercase(property.name) %> instead."))); + +<% } -%> +<% } -%> +<% } -%> + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLLight.mm b/platform/darwin/src/MGLLight.mm index 262fad3b070..c83ef127a6c 100644 --- a/platform/darwin/src/MGLLight.mm +++ b/platform/darwin/src/MGLLight.mm @@ -1,3 +1,7 @@ +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. +// test + #import "MGLLight.h" #import "MGLTypes.h" @@ -9,7 +13,7 @@ #import namespace mbgl { - + MBGL_DEFINE_ENUM(MGLLightAnchor, { { MGLLightAnchorMap, "map" }, { MGLLightAnchorViewport, "viewport" }, @@ -47,11 +51,9 @@ - (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight } else { anchorStyleValue = MGLStyleValueTransformer().toEnumStyleValue(anchor); } - + _anchor = anchorStyleValue; - - _anchorTransition = MGLTransitionFromOptions(mbglLight->getAnchorTransition()); - + auto positionValue = mbglLight->getPosition(); if (positionValue.isUndefined()) { _position = MGLStyleValueTransformer().toStyleValue(mbglLight->getDefaultPosition()); @@ -59,8 +61,8 @@ - (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight _position = MGLStyleValueTransformer().toStyleValue(positionValue); } - _positionTransiton = MGLTransitionFromOptions(mbglLight->getPositionTransition()); - + _positionTransition = MGLTransitionFromOptions(mbglLight->getPositionTransition()); + auto colorValue = mbglLight->getColor(); if (colorValue.isUndefined()) { _color = MGLStyleValueTransformer().toStyleValue(mbglLight->getDefaultColor()); @@ -68,8 +70,8 @@ - (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight _color = MGLStyleValueTransformer().toStyleValue(colorValue); } - _colorTransiton = MGLTransitionFromOptions(mbglLight->getColorTransition()); - + _colorTransition = MGLTransitionFromOptions(mbglLight->getColorTransition()); + auto intensityValue = mbglLight->getIntensity(); if (intensityValue.isUndefined()) { _intensity = MGLStyleValueTransformer().toStyleValue(mbglLight->getDefaultIntensity()); @@ -78,6 +80,7 @@ - (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight } _intensityTransition = MGLTransitionFromOptions(mbglLight->getIntensityTransition()); + } return self; @@ -86,26 +89,24 @@ - (instancetype)initWithMBGLLight:(const mbgl::style::Light *)mbglLight - (mbgl::style::Light)mbglLight { mbgl::style::Light mbglLight; - auto anchor = MGLStyleValueTransformer().toEnumPropertyValue(self.anchor); mbglLight.setAnchor(anchor); - - mbglLight.setAnchorTransition(MGLOptionsFromTransition(self.anchorTransition)); - + auto position = MGLStyleValueTransformer().toInterpolatablePropertyValue(self.position); mbglLight.setPosition(position); - - mbglLight.setPositionTransition(MGLOptionsFromTransition(self.positionTransiton)); - + + mbglLight.setPositionTransition(MGLOptionsFromTransition(self.positionTransition)); + auto color = MGLStyleValueTransformer().toInterpolatablePropertyValue(self.color); mbglLight.setColor(color); - - mbglLight.setColorTransition(MGLOptionsFromTransition(self.colorTransiton)); - + + mbglLight.setColorTransition(MGLOptionsFromTransition(self.colorTransition)); + auto intensity = MGLStyleValueTransformer().toInterpolatablePropertyValue(self.intensity); mbglLight.setIntensity(intensity); - + mbglLight.setIntensityTransition(MGLOptionsFromTransition(self.intensityTransition)); + return mbglLight; } diff --git a/platform/darwin/src/MGLLight.mm.ejs b/platform/darwin/src/MGLLight.mm.ejs new file mode 100644 index 00000000000..0d0da124c8e --- /dev/null +++ b/platform/darwin/src/MGLLight.mm.ejs @@ -0,0 +1,114 @@ +<% + const properties = locals.properties; +-%> +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. +// test + +#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, { +<% for (const property of properties) { -%> +<% if (property.type == "enum") { -%> +<% for (const value in property.values) { -%> + { MGLLightAnchor<%- camelize(value) %>, "<%- value %>" }, +<% } -%> +<% } -%> +<% } -%> + }); + +} + +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]) { +<% if (properties.length) { -%> +<% for (const property of properties) { -%> +<% if (property.type == "enum") { -%> + auto <%- camelizeWithLeadingLowercase(property.name) -%> = mbglLight->get<%- camelize(property.name) -%>(); + MGLStyleValue *<%- camelizeWithLeadingLowercase(property.name) -%>StyleValue; + if (<%- camelizeWithLeadingLowercase(property.name) -%>.isUndefined()) { + mbgl::style::PropertyValueType> default<%- camelize(property.name) -%> = mbglLight->getDefault<%- camelize(property.name) -%>(); + <%- camelizeWithLeadingLowercase(property.name) -%>StyleValue = MGLStyleValueTransformerType, MGLLight<%- camelize(property.name) -%>>().toEnumStyleValue(default<%- camelize(property.name) -%>); + } else { + <%- camelizeWithLeadingLowercase(property.name) -%>StyleValue = MGLStyleValueTransformerType, NSValue *, mbgl::style::Light<%- camelize(property.name) -%>Type, MGLLight<%- camelize(property.name) -%>>().toEnumStyleValue(<%- camelizeWithLeadingLowercase(property.name) -%>); + } + + _<%- camelizeWithLeadingLowercase(property.name) -%> = <%- camelizeWithLeadingLowercase(property.name) -%>StyleValue; + +<% if (property.transition) { -%> + _<%- camelizeWithLeadingLowercase(property.name) -%>Transition = MGLTransitionFromOptions(mbglLight->get<%- camelize(property.name) -%>Transition()); + +<% } -%> +<% } else {-%> + auto <%- camelizeWithLeadingLowercase(property.name) -%>Value = mbglLight->get<%- camelize(property.name) -%>(); + if (<%- camelizeWithLeadingLowercase(property.name) -%>Value.isUndefined()) { + _<%- camelizeWithLeadingLowercase(property.name) -%> = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(mbglLight->getDefault<%- camelize(property.name) -%>()); + } else { + _<%- camelizeWithLeadingLowercase(property.name) -%> = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(<%- camelizeWithLeadingLowercase(property.name) -%>Value); + } +<% if (property.transition) { -%> + _<%- camelizeWithLeadingLowercase(property.name) -%>Transition = MGLTransitionFromOptions(mbglLight->get<%- camelize(property.name) -%>Transition()); +<% } -%> +<% } -%> +<% } -%> +<% } -%> + } + + return self; +} + +- (mbgl::style::Light)mbglLight +{ + mbgl::style::Light mbglLight; +<% if (properties.length) { -%> +<% for (const property of properties) { -%> +<% if (property.type == "enum") { -%> + auto <%- camelizeWithLeadingLowercase(property.name) -%> = MGLStyleValueTransformerType, NSValue *, mbgl::style::Light<%- camelize(property.name) -%>Type, MGLLight<%- camelize(property.name) -%>>().toEnumPropertyValue(self.<%- camelizeWithLeadingLowercase(property.name) -%>); + mbglLight.set<%- camelize(property.name) -%>(<%- camelizeWithLeadingLowercase(property.name) -%>); + +<% } else {-%> + auto <%- camelizeWithLeadingLowercase(property.name) -%> = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toInterpolatablePropertyValue(self.<%- camelizeWithLeadingLowercase(property.name) -%>); + mbglLight.set<%- camelize(property.name) -%>(<%- camelizeWithLeadingLowercase(property.name) -%>); + +<% } -%> +<% if (property.transition) { -%> + mbglLight.set<%- camelize(property.name) -%>Transition(MGLOptionsFromTransition(self.<%- camelizeWithLeadingLowercase(property.name) -%>Transition)); + +<% } -%> +<% } -%> +<% } -%> + + return mbglLight; +} + +@end diff --git a/platform/darwin/test/MGLLightTest.mm b/platform/darwin/test/MGLLightTest.mm index 2c3d1c7bd1e..b021bd1b73a 100644 --- a/platform/darwin/test/MGLLightTest.mm +++ b/platform/darwin/test/MGLLightTest.mm @@ -1,3 +1,5 @@ +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. #import #import @@ -20,186 +22,109 @@ - (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]; - - NSAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue."); + auto lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.getDefaultAnchor(), lightFromMGLlight.getAnchor()); + XCTAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue."); NSValue *anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue; XCTAssertEqual(anchorValue.MGLLightAnchorValue, 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); - - MGLStyleValue *anchorStyleValue = [MGLStyleValue valueWithRawValue:[NSValue valueWithMGLLightAnchor:MGLLightAnchorMap]]; - mglLight.anchor = anchorStyleValue; - mglLight.anchorTransition = transition; - NSAssert([mglLight.anchor isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.anchor isn’t a MGLConstantStyleValue."); - anchorValue = ((MGLConstantStyleValue *)mglLight.anchor).rawValue; - - XCTAssertEqual(anchorValue.MGLLightAnchorValue, 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); - + + mbgl::style::PropertyValue propertyValue = { mbgl::style::LightAnchorType::Viewport }; + + light.setAnchor(propertyValue); + + mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; 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); - + + XCTAssertEqual(light.getAnchor(), lightFromMGLlight.getAnchor()); } - + // 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()); + + XCTAssertEqual(light.getDefaultPosition(), lightFromMGLlight.getPosition()); 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 } }; + + const std::array positionArray = { { 6, 180, 90 } }; mbgl::style::Position position = { positionArray }; - mbgl::style::PropertyValue positionProperty = { position }; - light.setPosition(positionProperty); + mbgl::style::PropertyValue propertyValue = { position }; + + light.setPosition(propertyValue); light.setPositionTransition(transitionOptions); - XCTAssertEqual(positionArray, lightFromMGLlight.getPosition().asConstant().getSpherical()); + + mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.getPosition(), lightFromMGLlight.getPosition()); 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()); + + XCTAssertEqual(light.getDefaultColor(), lightFromMGLlight.getColor()); 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); + + mbgl::style::PropertyValue propertyValue = { { 1, 0, 0, 1 } }; + + light.setColor(propertyValue); light.setColorTransition(transitionOptions); - + + + mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; - - colorComponents = CGColorGetComponents(colorValue.CGColor); - color = lightFromMGLlight.getColor().asConstant(); - XCTAssertEqual(light.getColor().asConstant(),lightFromMGLlight.getColor().asConstant()); + + XCTAssertEqual(light.getColor(), lightFromMGLlight.getColor()); 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()); + + XCTAssertEqual(light.getDefaultIntensity(), lightFromMGLlight.getIntensity()); 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); + + mbgl::style::PropertyValue propertyValue = { 0xff }; + + light.setIntensity(propertyValue); light.setIntensityTransition(transitionOptions); + + mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; lightFromMGLlight = [mglLight mbglLight]; - - XCTAssertEqual(light.getIntensity().asConstant(), lightFromMGLlight.getIntensity().asConstant()); + + XCTAssertEqual(light.getIntensity(), lightFromMGLlight.getIntensity()); intensityTransition = lightFromMGLlight.getIntensityTransition(); XCTAssert(intensityTransition.delay && MGLTimeIntervalFromDuration(*intensityTransition.delay) == transition.delay); XCTAssert(intensityTransition.duration && MGLTimeIntervalFromDuration(*intensityTransition.duration) == transition.duration); - + } } diff --git a/platform/darwin/test/MGLLightTest.mm.ejs b/platform/darwin/test/MGLLightTest.mm.ejs new file mode 100644 index 00000000000..c1904d5ab85 --- /dev/null +++ b/platform/darwin/test/MGLLightTest.mm.ejs @@ -0,0 +1,92 @@ +<% + const type = locals.type; + const properties = locals.properties; +-%> +// This file is generated. +// Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`. +#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) } }; + +<% for (const property of properties) { -%> + // <%- property.name %> + { + mbgl::style::Light light; + MGLLight *mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + auto lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.getDefault<%- camelize(property.name) -%>(), lightFromMGLlight.get<%- camelize(property.name) -%>()); +<% if (property.transition) { -%> + auto <%- camelizeWithLeadingLowercase(property.name) -%>Transition = lightFromMGLlight.get<%- camelize(property.name) -%>Transition(); + XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay) == defaultTransition.delay); + XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration) == defaultTransition.duration); + +<% } -%> +<% if (property.type == "enum" && property.default) { -%> + XCTAssert([mglLight.<%- camelizeWithLeadingLowercase(property.name) -%> isKindOfClass:[MGLConstantStyleValue class]], @"mglLight.<%- camelizeWithLeadingLowercase(property.name) -%> isn’t a MGLConstantStyleValue."); + NSValue *<%- camelizeWithLeadingLowercase(property.name) -%>Value = ((MGLConstantStyleValue *)mglLight.<%- camelizeWithLeadingLowercase(property.name) -%>).rawValue; + XCTAssertEqual(<%- camelizeWithLeadingLowercase(property.name) -%>Value.MGLLight<%- camelize(property.name) -%>Value, MGLLight<%- camelize(property.name) -%><%- camelize(property.default) -%>); + +<% } -%> +<% if (property.type == "array") { -%> + const std::array positionArray = { { 6, 180, 90 } }; + mbgl::style::Position position = { positionArray }; + mbgl::style::PropertyValue propertyValue = { position }; +<% } else { -%> + mbgl::style::PropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> }; +<% } -%> + light.set<%- camelize(property.name) -%>(propertyValue); +<% if (property.transition) { -%> + light.set<%- camelize(property.name) -%>Transition(transitionOptions); + +<% } -%> + mglLight = [[MGLLight alloc] initWithMBGLLight:&light]; + lightFromMGLlight = [mglLight mbglLight]; + + XCTAssertEqual(light.get<%- camelize(property.name) -%>(), lightFromMGLlight.get<%- camelize(property.name) -%>()); +<% if (property.transition) { -%> + <%- camelizeWithLeadingLowercase(property.name) -%>Transition = lightFromMGLlight.get<%- camelize(property.name) -%>Transition(); + XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.delay) == transition.delay); + XCTAssert(<%- camelizeWithLeadingLowercase(property.name) -%>Transition.duration && MGLTimeIntervalFromDuration(*<%- camelizeWithLeadingLowercase(property.name) -%>Transition.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); +<% for (const property of properties) { -%> +<% if (property.type == "enum") { -%> +<% for (const value in property.values) { -%> + XCTAssertEqual([NSValue valueWithMGLLight<%- camelize(property.name) %>:MGLLight<%- camelize(property.name) %><%- camelize(value) %>].MGLLight<%- camelize(property.name) %>Value, MGLLight<%- camelize(property.name) %><%- camelize(value) %>); +<% } -%> +<% } -%> +<% } -%> +} + +@end