summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2017-07-05 13:59:45 -0700
committerChris Loer <chris.loer@mapbox.com>2017-07-06 09:39:26 -0700
commitd5fbcb242acff2ab270b4018b01c2c6be9c4955f (patch)
tree8ced368c0026c8fa3cdeee174fa8e17b2a2a61e9
parent3800edb133ea0bbeb7fc613dc8f6975d0d6b6513 (diff)
downloadqtlocation-mapboxgl-d5fbcb242acff2ab270b4018b01c2c6be9c4955f.tar.gz
[core] Implement circle-pitch-alignment property
Closes issue #9349.
-rw-r--r--include/mbgl/style/conversion/make_property_setters.hpp2
-rw-r--r--include/mbgl/style/layers/circle_layer.hpp6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java38
-rw-r--r--platform/android/src/style/layers/circle_layer.cpp7
-rw-r--r--platform/android/src/style/layers/circle_layer.hpp2
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.h45
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.mm32
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.mm42
-rw-r--r--src/mbgl/programs/circle_program.hpp4
-rw-r--r--src/mbgl/programs/symbol_program.hpp1
-rw-r--r--src/mbgl/programs/uniforms.hpp2
-rw-r--r--src/mbgl/renderer/painters/painter_circle.cpp12
-rw-r--r--src/mbgl/shaders/circle.cpp28
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp27
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.hpp5
18 files changed, 296 insertions, 12 deletions
diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp
index eaea2e89dc..1c26aeb5e4 100644
--- a/include/mbgl/style/conversion/make_property_setters.hpp
+++ b/include/mbgl/style/conversion/make_property_setters.hpp
@@ -155,6 +155,8 @@ auto makePaintPropertySetters() {
result["circle-translate-anchor-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>;
result["circle-pitch-scale"] = &setProperty<V, CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale>;
result["circle-pitch-scale-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchScaleTransition>;
+ result["circle-pitch-alignment"] = &setProperty<V, CircleLayer, PropertyValue<AlignmentType>, &CircleLayer::setCirclePitchAlignment>;
+ result["circle-pitch-alignment-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCirclePitchAlignmentTransition>;
result["circle-stroke-width"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<float>, &CircleLayer::setCircleStrokeWidth>;
result["circle-stroke-width-transition"] = &setTransition<V, CircleLayer, &CircleLayer::setCircleStrokeWidthTransition>;
result["circle-stroke-color"] = &setProperty<V, CircleLayer, DataDrivenPropertyValue<Color>, &CircleLayer::setCircleStrokeColor>;
diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp
index 275a2e67a5..942dd67503 100644
--- a/include/mbgl/style/layers/circle_layer.hpp
+++ b/include/mbgl/style/layers/circle_layer.hpp
@@ -78,6 +78,12 @@ public:
void setCirclePitchScaleTransition(const TransitionOptions&);
TransitionOptions getCirclePitchScaleTransition() const;
+ static PropertyValue<AlignmentType> getDefaultCirclePitchAlignment();
+ PropertyValue<AlignmentType> getCirclePitchAlignment() const;
+ void setCirclePitchAlignment(PropertyValue<AlignmentType>);
+ void setCirclePitchAlignmentTransition(const TransitionOptions&);
+ TransitionOptions getCirclePitchAlignmentTransition() const;
+
static DataDrivenPropertyValue<float> getDefaultCircleStrokeWidth();
DataDrivenPropertyValue<float> getCircleStrokeWidth() const;
void setCircleStrokeWidth(DataDrivenPropertyValue<float>);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
index 1a7df06031..10663142b5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java
@@ -278,6 +278,16 @@ public class CircleLayer extends Layer {
}
/**
+ * Get the CirclePitchAlignment property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getCirclePitchAlignment() {
+ return (PropertyValue<String>) new PropertyValue("circle-pitch-alignment", nativeGetCirclePitchAlignment());
+ }
+
+ /**
* Get the CircleStrokeWidth property
*
* @return property wrapper value around Float
@@ -411,6 +421,8 @@ public class CircleLayer extends Layer {
private native Object nativeGetCirclePitchScale();
+ private native Object nativeGetCirclePitchAlignment();
+
private native Object nativeGetCircleStrokeWidth();
private native TransitionOptions nativeGetCircleStrokeWidthTransition();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
index 5e345268f9..d3d0e060dc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java
@@ -446,6 +446,27 @@ public final class Property {
@Retention(RetentionPolicy.SOURCE)
public @interface CIRCLE_PITCH_SCALE {}
+ // CIRCLE_PITCH_ALIGNMENT: Orientation of circle when map is pitched.
+
+ /**
+ * The circle is aligned to the plane of the map.
+ */
+ public static final String CIRCLE_PITCH_ALIGNMENT_MAP = "map";
+ /**
+ * The circle is aligned to the plane of the viewport.
+ */
+ public static final String CIRCLE_PITCH_ALIGNMENT_VIEWPORT = "viewport";
+
+ /**
+ * Orientation of circle when map is pitched.
+ */
+ @StringDef({
+ CIRCLE_PITCH_ALIGNMENT_MAP,
+ CIRCLE_PITCH_ALIGNMENT_VIEWPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CIRCLE_PITCH_ALIGNMENT {}
+
// FILL_EXTRUSION_TRANSLATE_ANCHOR: Controls the translation reference point.
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
index 73896b7901..c12d6b7133 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java
@@ -953,6 +953,28 @@ public class PropertyFactory {
}
/**
+ * Orientation of circle when map is pitched.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<String> circlePitchAlignment(@Property.CIRCLE_PITCH_ALIGNMENT String value) {
+ return new PaintPropertyValue<>("circle-pitch-alignment", value);
+ }
+
+
+ /**
+ * Orientation of circle when map is pitched.
+ *
+ * @param <Z> the zoom parameter type
+ * @param function a wrapper {@link CameraFunction} for String
+ * @return property wrapper around a String function
+ */
+ public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circlePitchAlignment(CameraFunction<Z, String> function) {
+ return new PaintPropertyValue<>("circle-pitch-alignment", function);
+ }
+
+ /**
* The width of the circle's stroke. Strokes are placed outside of the {@link PropertyFactory#circleRadius}.
*
* @param value a Float value
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
index c8f9640433..84f4c16801 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
@@ -1048,6 +1048,44 @@ public class CircleLayerTest extends BaseActivityTest {
}
@Test
+ public void testCirclePitchAlignmentAsConstant() {
+ validateTestSetup();
+ setupLayer();
+ Timber.i("circle-pitch-alignment");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getCirclePitchAlignment().getValue(), (String) CIRCLE_PITCH_ALIGNMENT_MAP);
+ }
+
+ @Test
+ public void testCirclePitchAlignmentAsCameraFunction() {
+ validateTestSetup();
+ setupLayer();
+ Timber.i("circle-pitch-alignment");
+ assertNotNull(layer);
+
+ // Set
+ layer.setProperties(
+ circlePitchAlignment(
+ zoom(
+ interval(
+ stop(2, circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP))
+ )
+ )
+ )
+ );
+
+ // Verify
+ assertNotNull(layer.getCirclePitchAlignment());
+ assertNotNull(layer.getCirclePitchAlignment().getFunction());
+ assertEquals(CameraFunction.class, layer.getCirclePitchAlignment().getFunction().getClass());
+ assertEquals(IntervalStops.class, layer.getCirclePitchAlignment().getFunction().getStops().getClass());
+ assertEquals(1, ((IntervalStops) layer.getCirclePitchAlignment().getFunction().getStops()).size());
+ }
+
+ @Test
public void testCircleStrokeWidthTransition() {
validateTestSetup();
setupLayer();
diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp
index 96a9356679..4c7f69e956 100644
--- a/platform/android/src/style/layers/circle_layer.cpp
+++ b/platform/android/src/style/layers/circle_layer.cpp
@@ -142,6 +142,12 @@ namespace android {
return jni::Object<jni::ObjectTag>(*converted);
}
+ jni::Object<jni::ObjectTag> CircleLayer::getCirclePitchAlignment(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCirclePitchAlignment());
+ return jni::Object<jni::ObjectTag>(*converted);
+ }
+
jni::Object<jni::ObjectTag> CircleLayer::getCircleStrokeWidth(jni::JNIEnv& env) {
using namespace mbgl::android::conversion;
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::CircleLayer>()->CircleLayer::getCircleStrokeWidth());
@@ -236,6 +242,7 @@ namespace android {
METHOD(&CircleLayer::getCircleTranslate, "nativeGetCircleTranslate"),
METHOD(&CircleLayer::getCircleTranslateAnchor, "nativeGetCircleTranslateAnchor"),
METHOD(&CircleLayer::getCirclePitchScale, "nativeGetCirclePitchScale"),
+ METHOD(&CircleLayer::getCirclePitchAlignment, "nativeGetCirclePitchAlignment"),
METHOD(&CircleLayer::getCircleStrokeWidthTransition, "nativeGetCircleStrokeWidthTransition"),
METHOD(&CircleLayer::setCircleStrokeWidthTransition, "nativeSetCircleStrokeWidthTransition"),
METHOD(&CircleLayer::getCircleStrokeWidth, "nativeGetCircleStrokeWidth"),
diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp
index 81737e8996..9d323e92bb 100644
--- a/platform/android/src/style/layers/circle_layer.hpp
+++ b/platform/android/src/style/layers/circle_layer.hpp
@@ -53,6 +53,8 @@ public:
jni::Object<jni::ObjectTag> getCirclePitchScale(jni::JNIEnv&);
+ jni::Object<jni::ObjectTag> getCirclePitchAlignment(jni::JNIEnv&);
+
jni::Object<jni::ObjectTag> getCircleStrokeWidth(jni::JNIEnv&);
void setCircleStrokeWidthTransition(jni::JNIEnv&, jlong duration, jlong delay);
jni::Object<TransitionOptions> getCircleStrokeWidthTransition(jni::JNIEnv&);
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h
index 789ff7a258..ea95f6beef 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.h
+++ b/platform/darwin/src/MGLCircleStyleLayer.h
@@ -8,6 +8,23 @@
NS_ASSUME_NONNULL_BEGIN
/**
+ Orientation of circle when map is pitched.
+
+ Values of this type are used in the `MGLCircleStyleLayer.circlePitchAlignment`
+ property.
+ */
+typedef NS_ENUM(NSUInteger, MGLCirclePitchAlignment) {
+ /**
+ The circle is aligned to the plane of the map.
+ */
+ MGLCirclePitchAlignmentMap,
+ /**
+ The circle is aligned to the plane of the viewport.
+ */
+ MGLCirclePitchAlignmentViewport,
+};
+
+/**
Controls the scaling behavior of the circle when the map is pitched.
Values of this type are used in the `MGLCircleStyleLayer.circleScaleAlignment`
@@ -221,6 +238,21 @@ MGL_EXPORT
@property (nonatomic) MGLTransition circleOpacityTransition;
/**
+ Orientation of circle when map is pitched.
+
+ The default value of this property is an `MGLStyleValue` object containing an
+ `NSValue` object containing `MGLCirclePitchAlignmentViewport`. Set this
+ property to `nil` to reset it to the default value.
+
+ You can set this property to an instance of:
+
+ * `MGLConstantStyleValue`
+ * `MGLCameraStyleFunction` with an interpolation mode of
+ `MGLInterpolationModeInterval`
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circlePitchAlignment;
+
+/**
Circle radius.
This property is measured in points.
@@ -491,6 +523,19 @@ MGL_EXPORT
#pragma mark Working with Circle Style Layer Attribute Values
/**
+ Creates a new value object containing the given `MGLCirclePitchAlignment` enumeration.
+
+ @param circlePitchAlignment The value for the new object.
+ @return A new value object that contains the enumeration value.
+ */
++ (instancetype)valueWithMGLCirclePitchAlignment:(MGLCirclePitchAlignment)circlePitchAlignment;
+
+/**
+ The `MGLCirclePitchAlignment` enumeration representation of the value.
+ */
+@property (readonly) MGLCirclePitchAlignment MGLCirclePitchAlignmentValue;
+
+/**
Creates a new value object containing the given `MGLCircleScaleAlignment` enumeration.
@param circleScaleAlignment The value for the new object.
diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm
index 42961f2e12..71ae37035e 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.mm
+++ b/platform/darwin/src/MGLCircleStyleLayer.mm
@@ -13,6 +13,11 @@
namespace mbgl {
+ MBGL_DEFINE_ENUM(MGLCirclePitchAlignment, {
+ { MGLCirclePitchAlignmentMap, "map" },
+ { MGLCirclePitchAlignmentViewport, "viewport" },
+ });
+
MBGL_DEFINE_ENUM(MGLCircleScaleAlignment, {
{ MGLCircleScaleAlignmentMap, "map" },
{ MGLCircleScaleAlignmentViewport, "viewport" },
@@ -187,6 +192,23 @@ namespace mbgl {
return transition;
}
+- (void)setCirclePitchAlignment:(MGLStyleValue<NSValue *> *)circlePitchAlignment {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLCirclePitchAlignment>().toEnumPropertyValue(circlePitchAlignment);
+ self.rawLayer->setCirclePitchAlignment(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)circlePitchAlignment {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = self.rawLayer->getCirclePitchAlignment();
+ if (propertyValue.isUndefined()) {
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLCirclePitchAlignment>().toEnumStyleValue(self.rawLayer->getDefaultCirclePitchAlignment());
+ }
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLCirclePitchAlignment>().toEnumStyleValue(propertyValue);
+}
+
- (void)setCircleRadius:(MGLStyleValue<NSNumber *> *)circleRadius {
MGLAssertStyleLayerIsValid();
@@ -421,6 +443,16 @@ namespace mbgl {
@implementation NSValue (MGLCircleStyleLayerAdditions)
++ (NSValue *)valueWithMGLCirclePitchAlignment:(MGLCirclePitchAlignment)circlePitchAlignment {
+ return [NSValue value:&circlePitchAlignment withObjCType:@encode(MGLCirclePitchAlignment)];
+}
+
+- (MGLCirclePitchAlignment)MGLCirclePitchAlignmentValue {
+ MGLCirclePitchAlignment circlePitchAlignment;
+ [self getValue:&circlePitchAlignment];
+ return circlePitchAlignment;
+}
+
+ (NSValue *)valueWithMGLCircleScaleAlignment:(MGLCircleScaleAlignment)circleScaleAlignment {
return [NSValue value:&circleScaleAlignment withObjCType:@encode(MGLCircleScaleAlignment)];
}
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.mm b/platform/darwin/test/MGLCircleStyleLayerTests.mm
index 2a2e9f2d4a..c0c503153a 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.mm
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.mm
@@ -246,6 +246,45 @@
XCTAssertEqual(circleOpacityTransition.duration, transitionTest.duration);
}
+ // circle-pitch-alignment
+ {
+ XCTAssertTrue(rawLayer->getCirclePitchAlignment().isUndefined(),
+ @"circle-pitch-alignment should be unset initially.");
+ MGLStyleValue<NSValue *> *defaultStyleValue = layer.circlePitchAlignment;
+
+ MGLStyleValue<NSValue *> *constantStyleValue = [MGLStyleValue<NSValue *> valueWithRawValue:[NSValue valueWithMGLCirclePitchAlignment:MGLCirclePitchAlignmentViewport]];
+ layer.circlePitchAlignment = constantStyleValue;
+ mbgl::style::PropertyValue<mbgl::style::AlignmentType> propertyValue = { mbgl::style::AlignmentType::Viewport };
+ XCTAssertEqual(rawLayer->getCirclePitchAlignment(), propertyValue,
+ @"Setting circlePitchAlignment to a constant value should update circle-pitch-alignment.");
+ XCTAssertEqualObjects(layer.circlePitchAlignment, constantStyleValue,
+ @"circlePitchAlignment should round-trip constant values.");
+
+ MGLStyleValue<NSValue *> * functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval cameraStops:@{@18: constantStyleValue} options:nil];
+ layer.circlePitchAlignment = functionStyleValue;
+
+ mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = { {{18, mbgl::style::AlignmentType::Viewport}} };
+ propertyValue = mbgl::style::CameraFunction<mbgl::style::AlignmentType> { intervalStops };
+
+ XCTAssertEqual(rawLayer->getCirclePitchAlignment(), propertyValue,
+ @"Setting circlePitchAlignment to a camera function should update circle-pitch-alignment.");
+ XCTAssertEqualObjects(layer.circlePitchAlignment, functionStyleValue,
+ @"circlePitchAlignment should round-trip camera functions.");
+
+
+
+ layer.circlePitchAlignment = nil;
+ XCTAssertTrue(rawLayer->getCirclePitchAlignment().isUndefined(),
+ @"Unsetting circlePitchAlignment should return circle-pitch-alignment to the default value.");
+ XCTAssertEqualObjects(layer.circlePitchAlignment, defaultStyleValue,
+ @"circlePitchAlignment should return the default value after being unset.");
+
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeIdentity sourceStops:nil attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ functionStyleValue = [MGLStyleValue<NSValue *> valueWithInterpolationMode:MGLInterpolationModeInterval compositeStops:@{@18: constantStyleValue} attributeName:@"" options:nil];
+ XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
+ }
+
// circle-radius
{
XCTAssertTrue(rawLayer->getCircleRadius().isUndefined(),
@@ -638,6 +677,7 @@
[self testPropertyName:@"circle-blur" isBoolean:NO];
[self testPropertyName:@"circle-color" isBoolean:NO];
[self testPropertyName:@"circle-opacity" isBoolean:NO];
+ [self testPropertyName:@"circle-pitch-alignment" isBoolean:NO];
[self testPropertyName:@"circle-radius" isBoolean:NO];
[self testPropertyName:@"circle-scale-alignment" isBoolean:NO];
[self testPropertyName:@"circle-stroke-color" isBoolean:NO];
@@ -648,6 +688,8 @@
}
- (void)testValueAdditions {
+ XCTAssertEqual([NSValue valueWithMGLCirclePitchAlignment:MGLCirclePitchAlignmentMap].MGLCirclePitchAlignmentValue, MGLCirclePitchAlignmentMap);
+ XCTAssertEqual([NSValue valueWithMGLCirclePitchAlignment:MGLCirclePitchAlignmentViewport].MGLCirclePitchAlignmentValue, MGLCirclePitchAlignmentViewport);
XCTAssertEqual([NSValue valueWithMGLCircleScaleAlignment:MGLCircleScaleAlignmentMap].MGLCircleScaleAlignmentValue, MGLCircleScaleAlignmentMap);
XCTAssertEqual([NSValue valueWithMGLCircleScaleAlignment:MGLCircleScaleAlignmentViewport].MGLCircleScaleAlignmentValue, MGLCircleScaleAlignmentViewport);
XCTAssertEqual([NSValue valueWithMGLCircleTranslationAnchor:MGLCircleTranslationAnchorMap].MGLCircleTranslationAnchorValue, MGLCircleTranslationAnchorMap);
diff --git a/src/mbgl/programs/circle_program.hpp b/src/mbgl/programs/circle_program.hpp
index 8f056048b1..3590acbeef 100644
--- a/src/mbgl/programs/circle_program.hpp
+++ b/src/mbgl/programs/circle_program.hpp
@@ -21,7 +21,9 @@ class CircleProgram : public Program<
gl::Uniforms<
uniforms::u_matrix,
uniforms::u_scale_with_map,
- uniforms::u_extrude_scale>,
+ uniforms::u_extrude_scale,
+ uniforms::u_camera_to_center_distance,
+ uniforms::u_pitch_with_map>,
style::CirclePaintProperties>
{
public:
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index e7c428034b..c11e0b5ca1 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -30,7 +30,6 @@ class TransformState;
namespace uniforms {
MBGL_DEFINE_UNIFORM_SCALAR(bool, u_rotate_with_map);
-MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_texture);
MBGL_DEFINE_UNIFORM_SCALAR(gl::TextureUnit, u_fadetexture);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_aspect_ratio);
diff --git a/src/mbgl/programs/uniforms.hpp b/src/mbgl/programs/uniforms.hpp
index f1b2c2fb54..c8f8684ba1 100644
--- a/src/mbgl/programs/uniforms.hpp
+++ b/src/mbgl/programs/uniforms.hpp
@@ -33,6 +33,8 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_gapwidth);
MBGL_DEFINE_UNIFORM_SCALAR(float, u_offset);
MBGL_DEFINE_UNIFORM_SCALAR(Size, u_world);
MBGL_DEFINE_UNIFORM_SCALAR(Size, u_texsize);
+MBGL_DEFINE_UNIFORM_SCALAR(bool, u_pitch_with_map);
+MBGL_DEFINE_UNIFORM_SCALAR(float, u_camera_to_center_distance);
MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_extrude_scale);
diff --git a/src/mbgl/renderer/painters/painter_circle.cpp b/src/mbgl/renderer/painters/painter_circle.cpp
index 58e384979d..a077f557fc 100644
--- a/src/mbgl/renderer/painters/painter_circle.cpp
+++ b/src/mbgl/renderer/painters/painter_circle.cpp
@@ -22,6 +22,7 @@ void Painter::renderCircle(PaintParameters& parameters,
const CirclePaintProperties::PossiblyEvaluated& properties = layer.evaluated;
const bool scaleWithMap = properties.get<CirclePitchScale>() == CirclePitchScaleType::Map;
+ const bool pitchWithMap = properties.get<CirclePitchAlignment>() == AlignmentType::Map;
parameters.programs.circle.get(properties).draw(
context,
@@ -38,12 +39,13 @@ void Painter::renderCircle(PaintParameters& parameters,
state)
},
uniforms::u_scale_with_map::Value{ scaleWithMap },
- uniforms::u_extrude_scale::Value{ scaleWithMap
+ uniforms::u_extrude_scale::Value{ pitchWithMap
? std::array<float, 2> {{
- pixelsToGLUnits[0] * state.getCameraToCenterDistance(),
- pixelsToGLUnits[1] * state.getCameraToCenterDistance()
- }}
- : pixelsToGLUnits }
+ tile.id.pixelsToTileUnits(1, state.getZoom()),
+ tile.id.pixelsToTileUnits(1, state.getZoom()) }}
+ : pixelsToGLUnits },
+ uniforms::u_camera_to_center_distance::Value{ state.getCameraToCenterDistance() },
+ uniforms::u_pitch_with_map::Value{ pitchWithMap }
},
*bucket.vertexBuffer,
*bucket.indexBuffer,
diff --git a/src/mbgl/shaders/circle.cpp b/src/mbgl/shaders/circle.cpp
index 2e0c76122c..953e750776 100644
--- a/src/mbgl/shaders/circle.cpp
+++ b/src/mbgl/shaders/circle.cpp
@@ -9,7 +9,9 @@ const char* circle::name = "circle";
const char* circle::vertexSource = R"MBGL_SHADER(
uniform mat4 u_matrix;
uniform bool u_scale_with_map;
+uniform bool u_pitch_with_map;
uniform vec2 u_extrude_scale;
+uniform highp float u_camera_to_center_distance;
attribute vec2 a_pos;
@@ -121,12 +123,28 @@ void main(void) {
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
// in extrusion data
- gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0, 1);
-
- if (u_scale_with_map) {
- gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale;
+ vec2 circle_center = floor(a_pos * 0.5);
+ if (u_pitch_with_map) {
+ vec2 corner_position = circle_center;
+ if (u_scale_with_map) {
+ corner_position += extrude * (radius + stroke_width) * u_extrude_scale;
+ } else {
+ // Pitching the circle with the map effectively scales it with the map
+ // To counteract the effect for pitch-scale: viewport, we rescale the
+ // whole circle based on the pitch scaling effect at its central point
+ vec4 projected_center = u_matrix * vec4(circle_center, 0, 1);
+ corner_position += extrude * (radius + stroke_width) * u_extrude_scale * (projected_center.w / u_camera_to_center_distance);
+ }
+
+ gl_Position = u_matrix * vec4(corner_position, 0, 1);
} else {
- gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * gl_Position.w;
+ gl_Position = u_matrix * vec4(circle_center, 0, 1);
+
+ if (u_scale_with_map) {
+ gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * u_camera_to_center_distance;
+ } else {
+ gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale * gl_Position.w;
+ }
}
// This is a minimum blur distance that serves as a faux-antialiasing for
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index 3bba135c84..9854932699 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -283,6 +283,33 @@ TransitionOptions CircleLayer::getCirclePitchScaleTransition() const {
return impl().paint.template get<CirclePitchScale>().options;
}
+PropertyValue<AlignmentType> CircleLayer::getDefaultCirclePitchAlignment() {
+ return { AlignmentType::Viewport };
+}
+
+PropertyValue<AlignmentType> CircleLayer::getCirclePitchAlignment() const {
+ return impl().paint.template get<CirclePitchAlignment>().value;
+}
+
+void CircleLayer::setCirclePitchAlignment(PropertyValue<AlignmentType> value) {
+ if (value == getCirclePitchAlignment())
+ return;
+ auto impl_ = mutableImpl();
+ impl_->paint.template get<CirclePitchAlignment>().value = value;
+ baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
+}
+
+void CircleLayer::setCirclePitchAlignmentTransition(const TransitionOptions& options) {
+ auto impl_ = mutableImpl();
+ impl_->paint.template get<CirclePitchAlignment>().options = options;
+ baseImpl = std::move(impl_);
+}
+
+TransitionOptions CircleLayer::getCirclePitchAlignmentTransition() const {
+ return impl().paint.template get<CirclePitchAlignment>().options;
+}
+
DataDrivenPropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() {
return { 0 };
}
diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp
index 73b7028465..bc0c961e75 100644
--- a/src/mbgl/style/layers/circle_layer_properties.hpp
+++ b/src/mbgl/style/layers/circle_layer_properties.hpp
@@ -40,6 +40,10 @@ struct CirclePitchScale : PaintProperty<CirclePitchScaleType> {
static CirclePitchScaleType defaultValue() { return CirclePitchScaleType::Map; }
};
+struct CirclePitchAlignment : PaintProperty<AlignmentType> {
+ static AlignmentType defaultValue() { return AlignmentType::Viewport; }
+};
+
struct CircleStrokeWidth : DataDrivenPaintProperty<float, attributes::a_stroke_width, uniforms::u_stroke_width> {
static float defaultValue() { return 0; }
};
@@ -60,6 +64,7 @@ class CirclePaintProperties : public Properties<
CircleTranslate,
CircleTranslateAnchor,
CirclePitchScale,
+ CirclePitchAlignment,
CircleStrokeWidth,
CircleStrokeColor,
CircleStrokeOpacity