Merge branch 'master' into road-poi-labels
This commit is contained in:
27
bin/style.js
27
bin/style.js
@@ -186,11 +186,18 @@ module.exports = {
|
||||
"value": "rock",
|
||||
"type": "fill"
|
||||
},
|
||||
"landuse_snow": {
|
||||
"source": "outdoors",
|
||||
"layer": "landuse",
|
||||
"field": "class",
|
||||
"value": "snow",
|
||||
"type": "fill"
|
||||
},
|
||||
"overlay_wetland": {
|
||||
"source": "outdoors",
|
||||
"layer": "landuse_overlay",
|
||||
"field": "class",
|
||||
"value": "wetland",
|
||||
"value": ["wetland", "wetland_noveg"],
|
||||
"type": "fill"
|
||||
},
|
||||
"overlay_breakwater_pier": {
|
||||
@@ -888,6 +895,10 @@ module.exports = {
|
||||
"name": "landuse_rock",
|
||||
"bucket": "landuse_rock"
|
||||
},
|
||||
{
|
||||
"name": "landuse_snow",
|
||||
"bucket": "landuse_snow"
|
||||
},
|
||||
{
|
||||
"name": "landuse_hospital",
|
||||
"bucket": "landuse_hospital"
|
||||
@@ -1322,9 +1333,9 @@ module.exports = {
|
||||
"water": "#cdd",
|
||||
"water_dark": "#185869",
|
||||
"crop": "#eeeed4",
|
||||
"grass": "#e7ebd1",
|
||||
"scrub": "#e0e8cd",
|
||||
"wood": "#d4e2c6",
|
||||
"grass": "#e6e6cc",
|
||||
"scrub": "#dfe5c8",
|
||||
"wood": "#cee2bd",
|
||||
"snow": "#f4f8ff",
|
||||
"rock": "#ddd",
|
||||
"sand": "#ffd",
|
||||
@@ -2257,6 +2268,10 @@ module.exports = {
|
||||
"translate": [0, 14]
|
||||
},
|
||||
"poi_aerodrome": {
|
||||
"opacity": ["stops",
|
||||
{"z": 13, "val": 0},
|
||||
{"z": 13.25, "val": 1}
|
||||
],
|
||||
"antialias": false
|
||||
}
|
||||
}
|
||||
@@ -2949,6 +2964,10 @@ module.exports = {
|
||||
"translate": [0, 14]
|
||||
},
|
||||
"poi_aerodrome": {
|
||||
"opacity": ["stops",
|
||||
{"z": 13, "val": 0},
|
||||
{"z": 13.25, "val": 1}
|
||||
],
|
||||
"antialias": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ private:
|
||||
void _clearRotating();
|
||||
void _clearScaling();
|
||||
|
||||
void constrain(double& scale, double& y);
|
||||
|
||||
private:
|
||||
mutable uv::rwlock mtx;
|
||||
|
||||
|
||||
@@ -5,12 +5,36 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <set>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
// Stores a premultiplied color, with all four channels ranging from 0..1
|
||||
typedef std::array<float, 4> Color;
|
||||
|
||||
struct PropertyTransition {
|
||||
uint16_t duration = 0;
|
||||
uint16_t delay = 0;
|
||||
};
|
||||
|
||||
enum class TransitionablePropertyKey {
|
||||
Translate = 1,
|
||||
FillColor = 2,
|
||||
StrokeColor = 3,
|
||||
Opacity = 4,
|
||||
Width = 5,
|
||||
Offset = 6,
|
||||
Color = 7,
|
||||
DashArray = 8,
|
||||
Radius = 9,
|
||||
Blur = 10,
|
||||
Halo = 11,
|
||||
HaloRadius = 12,
|
||||
HaloBlur = 13,
|
||||
};
|
||||
|
||||
enum class Winding {
|
||||
EvenOdd = 1,
|
||||
NonZero = 2
|
||||
@@ -61,15 +85,20 @@ struct FunctionProperty {
|
||||
};
|
||||
|
||||
struct IconClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchor translateAnchor = TranslateAnchor::Map;
|
||||
FunctionProperty size;
|
||||
Color color = {{ 1, 1, 1, 1 }};
|
||||
FunctionProperty opacity = 1;
|
||||
std::string image;
|
||||
FunctionProperty radius = 0;
|
||||
FunctionProperty blur = 0;
|
||||
boost::optional<FunctionProperty> enabled;
|
||||
boost::optional<std::array<FunctionProperty, 2>> translate;
|
||||
boost::optional<PropertyTransition> translate_transition;
|
||||
boost::optional<TranslateAnchor> translateAnchor;
|
||||
boost::optional<FunctionProperty> size;
|
||||
boost::optional<Color> color;
|
||||
boost::optional<PropertyTransition> color_transition;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
boost::optional<std::string> image;
|
||||
boost::optional<FunctionProperty> radius;
|
||||
boost::optional<PropertyTransition> radius_transition;
|
||||
boost::optional<FunctionProperty> blur;
|
||||
boost::optional<PropertyTransition> blur_transition;
|
||||
};
|
||||
|
||||
struct IconProperties {
|
||||
@@ -85,14 +114,20 @@ struct IconProperties {
|
||||
};
|
||||
|
||||
struct LineClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchor translateAnchor = TranslateAnchor::Map;
|
||||
FunctionProperty width;
|
||||
FunctionProperty offset;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
std::array<FunctionProperty, 2> dash_array = {{ 1, -1 }};
|
||||
FunctionProperty opacity = 1;
|
||||
boost::optional<FunctionProperty> enabled;
|
||||
boost::optional<std::array<FunctionProperty, 2>> translate;
|
||||
boost::optional<PropertyTransition> translate_transition;
|
||||
boost::optional<TranslateAnchor> translateAnchor;
|
||||
boost::optional<FunctionProperty> width;
|
||||
boost::optional<PropertyTransition> width_transition;
|
||||
boost::optional<FunctionProperty> offset;
|
||||
boost::optional<PropertyTransition> offset_transition;
|
||||
boost::optional<Color> color;
|
||||
boost::optional<PropertyTransition> color_transition;
|
||||
boost::optional<std::array<FunctionProperty, 2>> dash_array;
|
||||
boost::optional<PropertyTransition> dash_array_transition;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
};
|
||||
|
||||
struct LineProperties {
|
||||
@@ -107,15 +142,19 @@ struct LineProperties {
|
||||
};
|
||||
|
||||
struct FillClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchor translateAnchor = TranslateAnchor::Map;
|
||||
Winding winding = Winding::NonZero;
|
||||
FunctionProperty antialias = true;
|
||||
Color fill_color = {{ 0, 0, 0, 1 }};
|
||||
Color stroke_color = {{ 0, 0, 0, std::numeric_limits<float>::infinity() }};
|
||||
FunctionProperty opacity = 1;
|
||||
std::string image;
|
||||
boost::optional<FunctionProperty> enabled;
|
||||
boost::optional<std::array<FunctionProperty, 2>> translate;
|
||||
boost::optional<PropertyTransition> translate_transition;
|
||||
boost::optional<TranslateAnchor> translateAnchor;
|
||||
boost::optional<Winding> winding;
|
||||
boost::optional<FunctionProperty> antialias;
|
||||
boost::optional<Color> fill_color;
|
||||
boost::optional<PropertyTransition> fill_color_transition;
|
||||
boost::optional<Color> stroke_color;
|
||||
boost::optional<PropertyTransition> stroke_color_transition;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
boost::optional<std::string> image;
|
||||
};
|
||||
|
||||
struct FillProperties {
|
||||
@@ -131,17 +170,23 @@ struct FillProperties {
|
||||
};
|
||||
|
||||
struct TextClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchor translateAnchor = TranslateAnchor::Map;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
Color halo = {{ 1, 1, 1, 0.75 }};
|
||||
FunctionProperty halo_radius = 0.25f;
|
||||
FunctionProperty halo_blur = 1.0f;
|
||||
FunctionProperty size = 12.0f;
|
||||
FunctionProperty rotate = 0.0f;
|
||||
FunctionProperty alwaysVisible = false;
|
||||
FunctionProperty opacity = 1;
|
||||
boost::optional<FunctionProperty> enabled;
|
||||
boost::optional<std::array<FunctionProperty, 2>> translate;
|
||||
boost::optional<PropertyTransition> translate_transition;
|
||||
boost::optional<TranslateAnchor> translateAnchor;
|
||||
boost::optional<Color> color;
|
||||
boost::optional<PropertyTransition> color_transition;
|
||||
boost::optional<Color> halo;
|
||||
boost::optional<PropertyTransition> halo_transition;
|
||||
boost::optional<FunctionProperty> halo_radius;
|
||||
boost::optional<PropertyTransition> halo_radius_transition;
|
||||
boost::optional<FunctionProperty> halo_blur;
|
||||
boost::optional<PropertyTransition> halo_blur_transition;
|
||||
boost::optional<FunctionProperty> size;
|
||||
boost::optional<FunctionProperty> rotate;
|
||||
boost::optional<FunctionProperty> always_visible;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
};
|
||||
|
||||
struct TextProperties {
|
||||
@@ -154,13 +199,15 @@ struct TextProperties {
|
||||
float halo_blur = 1.0f;
|
||||
float size = 12.0f;
|
||||
float rotate = 0.0f;
|
||||
bool alwaysVisible = false;
|
||||
bool always_visible = false;
|
||||
float opacity = 1.0;
|
||||
};
|
||||
|
||||
struct BackgroundClass {
|
||||
Color color = {{ 1, 1, 1, 1 }};
|
||||
FunctionProperty opacity = 1;
|
||||
boost::optional<Color> color;
|
||||
boost::optional<PropertyTransition> color_transition;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
};
|
||||
|
||||
struct BackgroundProperties {
|
||||
@@ -169,9 +216,11 @@ struct BackgroundProperties {
|
||||
};
|
||||
|
||||
struct RasterClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
FunctionProperty opacity = 1;
|
||||
boost::optional<FunctionProperty> enabled;
|
||||
boost::optional<std::array<FunctionProperty, 2>> translate;
|
||||
boost::optional<PropertyTransition> translate_transition;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
};
|
||||
|
||||
struct RasterProperties {
|
||||
@@ -181,8 +230,9 @@ struct RasterProperties {
|
||||
};
|
||||
|
||||
struct CompositeClass {
|
||||
FunctionProperty enabled = true;
|
||||
FunctionProperty opacity = 1;
|
||||
boost::optional<FunctionProperty> enabled;
|
||||
boost::optional<FunctionProperty> opacity;
|
||||
boost::optional<PropertyTransition> opacity_transition;
|
||||
};
|
||||
|
||||
struct CompositeProperties {
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <llmr/style/layer_description.hpp>
|
||||
#include <llmr/style/class_description.hpp>
|
||||
#include <llmr/geometry/sprite_atlas.hpp>
|
||||
#include <llmr/util/transition.hpp>
|
||||
#include <llmr/util/uv.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@@ -32,6 +34,12 @@ public:
|
||||
size_t layerCount() const;
|
||||
void cascade(float z);
|
||||
|
||||
bool needsTransition() const;
|
||||
void updateTransitions(time now);
|
||||
void cancelTransitions();
|
||||
|
||||
void setDefaultTransitionDuration(uint64_t duration = 0);
|
||||
|
||||
public:
|
||||
std::shared_ptr<Sprite> sprite;
|
||||
|
||||
@@ -40,8 +48,7 @@ public:
|
||||
std::vector<LayerDescription> layers;
|
||||
std::map<std::string, ClassDescription> classes;
|
||||
|
||||
|
||||
// This are applied settings.
|
||||
// Currently applied settings.
|
||||
std::set<std::string> appliedClasses;
|
||||
struct {
|
||||
BackgroundProperties background;
|
||||
@@ -51,7 +58,47 @@ public:
|
||||
std::map<std::string, TextProperties> texts;
|
||||
std::map<std::string, RasterProperties> rasters;
|
||||
std::map<std::string, CompositeProperties> composites;
|
||||
std::map<std::string, std::map<TransitionablePropertyKey, std::string>> effective_classes;
|
||||
} computed;
|
||||
|
||||
private:
|
||||
bool transitionInProgress(std::string layer_name, TransitionablePropertyKey key);
|
||||
bool transitionExists(std::string layer_name, TransitionablePropertyKey key);
|
||||
bool inNeedOfTransition(std::string layer_name, TransitionablePropertyKey key);
|
||||
uint64_t transitionDuration(std::string layer_name, TransitionablePropertyKey key);
|
||||
uint64_t transitionDelay(std::string layer_name, TransitionablePropertyKey key);
|
||||
|
||||
private:
|
||||
// Last applied settings.
|
||||
struct {
|
||||
BackgroundProperties background;
|
||||
std::map<std::string, FillProperties> fills;
|
||||
std::map<std::string, LineProperties> lines;
|
||||
std::map<std::string, IconProperties> icons;
|
||||
std::map<std::string, TextProperties> texts;
|
||||
std::map<std::string, RasterProperties> rasters;
|
||||
std::map<std::string, CompositeProperties> composites;
|
||||
std::map<std::string, std::map<TransitionablePropertyKey, std::string>> effective_classes;
|
||||
} previous;
|
||||
|
||||
// Settings values currently being transitioned.
|
||||
struct {
|
||||
BackgroundProperties background;
|
||||
std::map<std::string, FillProperties> fills;
|
||||
std::map<std::string, LineProperties> lines;
|
||||
std::map<std::string, IconProperties> icons;
|
||||
std::map<std::string, TextProperties> texts;
|
||||
std::map<std::string, RasterProperties> rasters;
|
||||
std::map<std::string, CompositeProperties> composites;
|
||||
} transitioning;
|
||||
|
||||
std::map<std::string, std::map<TransitionablePropertyKey, PropertyTransition>> properties_to_transition;
|
||||
std::map<std::string, std::map<TransitionablePropertyKey, std::shared_ptr<util::transition>>> transitions;
|
||||
uint64_t default_transition_duration = 0;
|
||||
bool initial_render_complete = false;
|
||||
|
||||
mutable uv::rwlock mtx;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ private:
|
||||
Value parseValue(JSVal value);
|
||||
FunctionProperty::fn parseFunctionType(JSVal type);
|
||||
FunctionProperty parseFunction(JSVal value);
|
||||
PropertyTransition parseTransition(JSVal value, std::string property_name);
|
||||
|
||||
private:
|
||||
std::map<std::string, const rapidjson::Value *> constants;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <llmr/util/noncopyable.hpp>
|
||||
#include <llmr/util/time.hpp>
|
||||
#include <llmr/style/properties.hpp>
|
||||
|
||||
namespace llmr {
|
||||
namespace util {
|
||||
@@ -19,39 +20,45 @@ public:
|
||||
duration(duration) {}
|
||||
|
||||
inline float progress(time now) const {
|
||||
if (duration == 0) return 1;
|
||||
if (start > now) return 0;
|
||||
|
||||
return (float)(now - start) / duration;
|
||||
}
|
||||
|
||||
virtual state update(time now) const = 0;
|
||||
virtual ~transition();
|
||||
|
||||
protected:
|
||||
double interpolateDouble(double from, double to, double t) const;
|
||||
float interpolateFloat(float from, float to, double t) const;
|
||||
Color interpolateColor(Color from, Color to, double t) const;
|
||||
std::array<float, 2> interpolateFloatArray(std::array<float, 2> from, std::array<float, 2> to, double t) const;
|
||||
|
||||
protected:
|
||||
const time start, duration;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ease_transition : public transition {
|
||||
public:
|
||||
// Disable automatic casts.
|
||||
template <typename T1, typename T2>
|
||||
inline ease_transition(double from, double to, double& value, T1 start, T2 duration) = delete;
|
||||
ease_transition(T from, T to, T& value, time start, time duration)
|
||||
: transition(start, duration),
|
||||
from(from),
|
||||
to(to),
|
||||
value(value) {}
|
||||
|
||||
// Actual constructor.
|
||||
ease_transition(double from, double to, double& value, time start, time duration);
|
||||
state update(time now) const;
|
||||
|
||||
private:
|
||||
const double from, to;
|
||||
double& value;
|
||||
const T from, to;
|
||||
T& value;
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class timeout : public transition {
|
||||
public:
|
||||
// Disable automatic casts.
|
||||
template <typename T1, typename T2>
|
||||
inline timeout(T final_value, T& value, T1 start, T2 duration) = delete;
|
||||
|
||||
// Actual constructor.
|
||||
timeout(T final_value, T& value, time start, time duration)
|
||||
: transition(start, duration),
|
||||
final_value(final_value),
|
||||
|
||||
Submodule ios/MVKMapKit updated: a9a7fa3ab3...172218fa97
@@ -374,17 +374,15 @@ bool Map::getDebug() const {
|
||||
}
|
||||
|
||||
void Map::toggleRaster() {
|
||||
style.setDefaultTransitionDuration(300);
|
||||
style.cancelTransitions();
|
||||
|
||||
auto it = sources.find("satellite");
|
||||
if (it != sources.end()) {
|
||||
Source &satellite_source = *it->second;
|
||||
|
||||
if (satellite_source.enabled) {
|
||||
satellite_source.enabled = false;
|
||||
|
||||
auto style_class = style.appliedClasses.find("satellite");
|
||||
if (style_class != style.appliedClasses.end()) {
|
||||
style.appliedClasses.erase(style_class);
|
||||
}
|
||||
style.appliedClasses.erase("satellite");
|
||||
} else {
|
||||
satellite_source.enabled = true;
|
||||
style.appliedClasses.insert("satellite");
|
||||
@@ -427,23 +425,20 @@ void Map::updateRenderState() {
|
||||
void Map::prepare() {
|
||||
view.make_active();
|
||||
|
||||
// Update transitions
|
||||
// Update transform transitions.
|
||||
animationTime = util::now();
|
||||
if (transform.needsTransition()) {
|
||||
transform.updateTransitions(animationTime);
|
||||
}
|
||||
|
||||
|
||||
const TransformState oldState = state;
|
||||
state = transform.currentState();
|
||||
|
||||
bool pixelRatioChanged = oldState.getPixelRatio() != state.getPixelRatio();
|
||||
bool dimensionsChanged = oldState.getFramebufferWidth() != state.getFramebufferWidth() ||
|
||||
oldState.getFramebufferHeight() != state.getFramebufferHeight();
|
||||
bool zoomChanged = oldState.getNormalizedZoom() != state.getNormalizedZoom();
|
||||
|
||||
if (pixelRatioChanged) {
|
||||
// We have a pixelratio change
|
||||
style.sprite = std::make_shared<Sprite>(*this, state.getPixelRatio());
|
||||
style.sprite->load(kSpriteURL);
|
||||
|
||||
@@ -454,8 +449,13 @@ void Map::prepare() {
|
||||
painter.clearFramebuffers();
|
||||
}
|
||||
|
||||
if (zoomChanged) {
|
||||
style.cascade(state.getNormalizedZoom());
|
||||
style.cascade(state.getNormalizedZoom());
|
||||
|
||||
// Update style transitions.
|
||||
animationTime = util::now();
|
||||
if (style.needsTransition()) {
|
||||
style.updateTransitions(animationTime);
|
||||
update();
|
||||
}
|
||||
|
||||
// Allow the sprite atlas to potentially pull new sprite images if needed.
|
||||
|
||||
@@ -12,6 +12,7 @@ using namespace llmr;
|
||||
const double D2R = M_PI / 180.0;
|
||||
const double R2D = 180.0 / M_PI;
|
||||
const double M2PI = 2 * M_PI;
|
||||
const double MIN_ROTATE_SCALE = 8;
|
||||
|
||||
Transform::Transform() {
|
||||
setScale(current.scale);
|
||||
@@ -32,6 +33,8 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
current.pixelRatio = final.pixelRatio = ratio;
|
||||
current.framebuffer[0] = final.framebuffer[0] = fb_w;
|
||||
current.framebuffer[1] = final.framebuffer[1] = fb_h;
|
||||
constrain(current.scale, current.y);
|
||||
if (current.scale < MIN_ROTATE_SCALE && current.angle) _setAngle(0, 0);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -52,6 +55,8 @@ void Transform::_moveBy(const double dx, const double dy, const time duration) {
|
||||
final.x = current.x + std::cos(current.angle) * dx + std::sin(current.angle) * dy;
|
||||
final.y = current.y + std::cos(current.angle) * dy + std::sin(-current.angle) * dx;
|
||||
|
||||
constrain(final.scale, final.y);
|
||||
|
||||
if (duration == 0) {
|
||||
current.x = final.x;
|
||||
current.y = final.y;
|
||||
@@ -59,9 +64,9 @@ void Transform::_moveBy(const double dx, const double dy, const time duration) {
|
||||
// Use a common start time for all of the transitions to avoid divergent transitions.
|
||||
time start = util::now();
|
||||
transitions.emplace_front(
|
||||
std::make_shared<util::ease_transition>(current.x, final.x, current.x, start, duration));
|
||||
std::make_shared<util::ease_transition<double>>(current.x, final.x, current.x, start, duration));
|
||||
transitions.emplace_front(
|
||||
std::make_shared<util::ease_transition>(current.y, final.y, current.y, start, duration));
|
||||
std::make_shared<util::ease_transition<double>>(current.y, final.y, current.y, start, duration));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +248,11 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
final.x = xn;
|
||||
final.y = yn;
|
||||
|
||||
constrain(final.scale, final.y);
|
||||
|
||||
// Undo rotation at low zooms.
|
||||
if (final.scale < MIN_ROTATE_SCALE && current.angle) _setAngle(0, 500_milliseconds);
|
||||
|
||||
if (duration == 0) {
|
||||
current.scale = final.scale;
|
||||
current.x = final.x;
|
||||
@@ -250,12 +260,12 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
} else {
|
||||
// Use a common start time for all of the transitions to avoid divergent transitions.
|
||||
time start = util::now();
|
||||
transitions.emplace_front(std::make_shared<util::ease_transition>(
|
||||
transitions.emplace_front(std::make_shared<util::ease_transition<double>>(
|
||||
current.scale, final.scale, current.scale, start, duration));
|
||||
transitions.emplace_front(
|
||||
std::make_shared<util::ease_transition>(current.x, final.x, current.x, start, duration));
|
||||
std::make_shared<util::ease_transition<double>>(current.x, final.x, current.x, start, duration));
|
||||
transitions.emplace_front(
|
||||
std::make_shared<util::ease_transition>(current.y, final.y, current.y, start, duration));
|
||||
std::make_shared<util::ease_transition<double>>(current.y, final.y, current.y, start, duration));
|
||||
}
|
||||
|
||||
const double s = final.scale * util::tileSize;
|
||||
@@ -264,6 +274,19 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
Cc = s / (2 * M_PI);
|
||||
}
|
||||
|
||||
#pragma mark - Constraints
|
||||
|
||||
void Transform::constrain(double& scale, double& y) {
|
||||
// Constrain minimum zoom to avoid zooming out far enough to show off-world areas.
|
||||
if (scale < (current.height / util::tileSize)) scale = (current.height / util::tileSize);
|
||||
|
||||
// Constrain min/max vertical pan to avoid showing off-world areas.
|
||||
double max_y = ((scale * util::tileSize) - current.height) / 2;
|
||||
|
||||
if (y > max_y) y = max_y;
|
||||
if (y < -max_y) y = -max_y;
|
||||
}
|
||||
|
||||
#pragma mark - Angle
|
||||
|
||||
void Transform::rotateBy(const double start_x, const double start_y, const double end_x,
|
||||
@@ -331,11 +354,14 @@ void Transform::_setAngle(double new_angle, const time duration) {
|
||||
|
||||
final.angle = new_angle;
|
||||
|
||||
// Prevent rotation at low zooms.
|
||||
if (final.scale < MIN_ROTATE_SCALE) final.angle = 0;
|
||||
|
||||
if (duration == 0) {
|
||||
current.angle = final.angle;
|
||||
} else {
|
||||
time start = util::now();
|
||||
transitions.emplace_front(std::make_shared<util::ease_transition>(
|
||||
transitions.emplace_front(std::make_shared<util::ease_transition<double>>(
|
||||
current.angle, final.angle, current.angle, start, duration));
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -477,6 +477,29 @@ FunctionProperty StyleParser::parseFunction(JSVal value) {
|
||||
return property;
|
||||
}
|
||||
|
||||
PropertyTransition StyleParser::parseTransition(JSVal value, std::string property_name) {
|
||||
uint16_t duration = 0, delay = 0;
|
||||
std::string transition_property = std::string("transition-").append(property_name);
|
||||
if (value.HasMember(transition_property.c_str())) {
|
||||
JSVal elements = value[transition_property.c_str()];
|
||||
if (elements.IsObject()) {
|
||||
if (elements.HasMember("duration") && elements["duration"].IsNumber()) {
|
||||
duration = elements["duration"].GetUint();
|
||||
}
|
||||
if (elements.HasMember("delay") && elements["delay"].IsNumber()) {
|
||||
delay = elements["delay"].GetUint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PropertyTransition transition;
|
||||
|
||||
transition.duration = duration;
|
||||
transition.delay = delay;
|
||||
|
||||
return transition;
|
||||
}
|
||||
|
||||
FillClass StyleParser::parseFillClass(JSVal value) {
|
||||
FillClass klass;
|
||||
|
||||
@@ -487,18 +510,25 @@ FillClass StyleParser::parseFillClass(JSVal value) {
|
||||
if (value.HasMember("translate")) {
|
||||
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
|
||||
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
|
||||
klass.translate_transition = parseTransition(value, "translate");
|
||||
}
|
||||
|
||||
if (value.HasMember("translate-anchor")) {
|
||||
klass.translateAnchor = parseTranslateAnchor(value["translate-anchor"]);
|
||||
}
|
||||
|
||||
if (value.HasMember("winding")) {
|
||||
throw std::runtime_error("winding in stylesheets not yet supported");
|
||||
}
|
||||
|
||||
if (value.HasMember("color")) {
|
||||
klass.fill_color = parseColor(value["color"]);
|
||||
klass.fill_color_transition = parseTransition(value, "color");
|
||||
}
|
||||
|
||||
if (value.HasMember("stroke")) {
|
||||
klass.stroke_color = parseColor(value["stroke"]);
|
||||
klass.stroke_color_transition = parseTransition(value, "stroke");
|
||||
} else {
|
||||
klass.stroke_color = klass.fill_color;
|
||||
}
|
||||
@@ -513,6 +543,7 @@ FillClass StyleParser::parseFillClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -528,6 +559,7 @@ LineClass StyleParser::parseLineClass(JSVal value) {
|
||||
if (value.HasMember("translate")) {
|
||||
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
|
||||
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
|
||||
klass.translate_transition = parseTransition(value, "translate");
|
||||
}
|
||||
|
||||
if (value.HasMember("translate-anchor")) {
|
||||
@@ -536,19 +568,23 @@ LineClass StyleParser::parseLineClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("color")) {
|
||||
klass.color = parseColor(value["color"]);
|
||||
klass.color_transition = parseTransition(value, "color");
|
||||
}
|
||||
|
||||
if (value.HasMember("width")) {
|
||||
klass.width = parseFunction(value["width"]);
|
||||
klass.width_transition = parseTransition(value, "width");
|
||||
}
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
if (value.HasMember("dasharray")) {
|
||||
std::vector<FunctionProperty> values = parseArray(value["dasharray"], 2);
|
||||
klass.dash_array = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
|
||||
klass.dash_array_transition = parseTransition(value, "dasharray");
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -564,6 +600,7 @@ IconClass StyleParser::parseIconClass(JSVal value) {
|
||||
if (value.HasMember("translate")) {
|
||||
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
|
||||
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
|
||||
klass.translate_transition = parseTransition(value, "translate");
|
||||
}
|
||||
|
||||
if (value.HasMember("translate-anchor")) {
|
||||
@@ -572,10 +609,12 @@ IconClass StyleParser::parseIconClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("color")) {
|
||||
klass.color = parseColor(value["color"]);
|
||||
klass.color_transition = parseTransition(value, "color");
|
||||
}
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
if (value.HasMember("image")) {
|
||||
@@ -588,10 +627,12 @@ IconClass StyleParser::parseIconClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("radius")) {
|
||||
klass.radius = parseFunction(value["radius"]);
|
||||
klass.radius_transition = parseTransition(value, "radius");
|
||||
}
|
||||
|
||||
if (value.HasMember("blur")) {
|
||||
klass.blur = parseFunction(value["blur"]);
|
||||
klass.blur_transition = parseTransition(value, "blur");
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -607,6 +648,7 @@ TextClass StyleParser::parseTextClass(JSVal value) {
|
||||
if (value.HasMember("translate")) {
|
||||
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
|
||||
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
|
||||
klass.translate_transition = parseTransition(value, "translate");
|
||||
}
|
||||
|
||||
if (value.HasMember("translate-anchor")) {
|
||||
@@ -615,18 +657,22 @@ TextClass StyleParser::parseTextClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("color")) {
|
||||
klass.color = parseColor(value["color"]);
|
||||
klass.color_transition = parseTransition(value, "color");
|
||||
}
|
||||
|
||||
if (value.HasMember("stroke")) {
|
||||
klass.halo = parseColor(value["stroke"]);
|
||||
klass.halo_transition = parseTransition(value, "stroke");
|
||||
}
|
||||
|
||||
if (value.HasMember("strokeWidth")) {
|
||||
klass.halo_radius = parseFunction(value["strokeWidth"]);
|
||||
klass.halo_radius_transition = parseTransition(value, "strokeWidth");
|
||||
}
|
||||
|
||||
if (value.HasMember("strokeBlur")) {
|
||||
klass.halo_blur = parseFunction(value["strokeBlur"]);
|
||||
klass.halo_blur_transition = parseTransition(value, "strokeBlur");
|
||||
}
|
||||
|
||||
if (value.HasMember("size")) {
|
||||
@@ -638,7 +684,12 @@ TextClass StyleParser::parseTextClass(JSVal value) {
|
||||
}
|
||||
|
||||
if (value.HasMember("alwaysVisible")) {
|
||||
klass.alwaysVisible = parseFunction(value["alwaysVisible"]);
|
||||
klass.always_visible = parseFunction(value["alwaysVisible"]);
|
||||
}
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -653,6 +704,7 @@ RasterClass StyleParser::parseRasterClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -667,6 +719,7 @@ CompositeClass StyleParser::parseCompositeClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
return klass;
|
||||
@@ -677,10 +730,12 @@ BackgroundClass StyleParser::parseBackgroundClass(JSVal value) {
|
||||
|
||||
if (value.HasMember("color")) {
|
||||
klass.color = parseColor(value["color"]);
|
||||
klass.color_transition = parseTransition(value, "color");
|
||||
}
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
klass.opacity_transition = parseTransition(value, "opacity");
|
||||
}
|
||||
|
||||
return klass;
|
||||
|
||||
@@ -70,7 +70,7 @@ void Raster::bind(bool linear) {
|
||||
|
||||
void Raster::beginFadeInTransition() {
|
||||
time start = util::now();
|
||||
fade_transition = std::make_shared<util::ease_transition>(opacity, 1.0, opacity, start, 250_milliseconds);
|
||||
fade_transition = std::make_shared<util::ease_transition<double>>(opacity, 1.0, opacity, start, 250_milliseconds);
|
||||
}
|
||||
|
||||
bool Raster::needsTransition() const {
|
||||
|
||||
@@ -8,20 +8,69 @@ UnitBezier ease(0.25, 0.1, 0.25, 1);
|
||||
|
||||
transition::~transition() {}
|
||||
|
||||
ease_transition::ease_transition(double from, double to, double &value, time start, time duration)
|
||||
: transition(start, duration),
|
||||
from(from),
|
||||
to(to),
|
||||
value(value) {
|
||||
double transition::interpolateDouble(double from, double to, double t) const {
|
||||
return from + (to - from) * t;
|
||||
}
|
||||
|
||||
transition::state ease_transition::update(time now) const {
|
||||
float transition::interpolateFloat(float from, float to, double t) const {
|
||||
return from + (to - from) * (float)t;
|
||||
}
|
||||
|
||||
llmr::Color transition::interpolateColor(llmr::Color from, llmr::Color to, double t) const {
|
||||
return {{ interpolateFloat(from[0], to[0], t),
|
||||
interpolateFloat(from[1], to[1], t),
|
||||
interpolateFloat(from[2], to[2], t),
|
||||
interpolateFloat(from[3], to[3], t) }};
|
||||
}
|
||||
|
||||
std::array<float, 2> transition::interpolateFloatArray(std::array<float, 2> from, std::array<float, 2> to, double t) const {
|
||||
return {{ interpolateFloat(from[0], to[0], t), interpolateFloat(from[1], to[1], t) }};
|
||||
}
|
||||
|
||||
template <>
|
||||
transition::state ease_transition<double>::update(llmr::time now) const {
|
||||
float t = progress(now);
|
||||
if (t >= 1) {
|
||||
value = to;
|
||||
return complete;
|
||||
} else {
|
||||
value = from + (to - from) * ease.solve(t, 0.001);
|
||||
value = interpolateDouble(from, to, ease.solve(t, 0.001));
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
transition::state ease_transition<llmr::Color>::update(llmr::time now) const {
|
||||
float t = progress(now);
|
||||
if (t >= 1) {
|
||||
value = to;
|
||||
return complete;
|
||||
} else {
|
||||
value = interpolateColor(from, to, ease.solve(t, 0.001));
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
transition::state ease_transition<float>::update(llmr::time now) const {
|
||||
float t = progress(now);
|
||||
if (t >= 1) {
|
||||
value = to;
|
||||
return complete;
|
||||
} else {
|
||||
value = interpolateFloat(from, to, ease.solve(t, 0.001));
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
transition::state ease_transition<std::array<float, 2>>::update(llmr::time now) const {
|
||||
float t = progress(now);
|
||||
if (t >= 1) {
|
||||
value = to;
|
||||
return complete;
|
||||
} else {
|
||||
value = interpolateFloatArray(from, to, ease.solve(t, 0.001));
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user