@@ -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>;
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -277,6 +277,16 @@ public class CircleLayer extends Layer {
|
||||
return (PropertyValue<String>) new PropertyValue("circle-pitch-scale", nativeGetCirclePitchScale());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
/**
|
||||
|
||||
@@ -952,6 +952,28 @@ public class PropertyFactory {
|
||||
return new PaintPropertyValue<>("circle-pitch-scale", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*
|
||||
|
||||
@@ -1047,6 +1047,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();
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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&);
|
||||
|
||||
@@ -7,6 +7,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.
|
||||
|
||||
@@ -220,6 +237,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.
|
||||
|
||||
@@ -490,6 +522,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.
|
||||
|
||||
|
||||
@@ -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)];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
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);
|
||||
}
|
||||
|
||||
if (u_scale_with_map) {
|
||||
gl_Position.xy += extrude * (radius + stroke_width) * u_extrude_scale;
|
||||
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
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user