From: Varun Date: Mon, 29 Aug 2016 21:30:09 +0000 (-0400) Subject: Implements all on_view_object handling X-Git-Tag: submit/tizen_3.0/20161108.012559~32 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=519cc73e684f6b6af278a29389ea83d53afb69c5;p=platform%2Fcore%2Flocation%2Fmaps-plugin-mapzen.git Implements all on_view_object handling - also uses UI scale from elm_config_scale Change-Id: I785f7ec2d83677c6d3135cf154159c1de1b68d03 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 38f0f11..448761e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ SET(CMAKE_INSTALL_PREFIX /usr) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) # Dependencies -SET(dependents "glib-2.0 gmodule-2.0 dlog libcurl capi-network-connection capi-maps-service evas ecore-evas") +SET(dependents "glib-2.0 gmodule-2.0 dlog libcurl capi-network-connection capi-maps-service evas ecore-evas elementary") INCLUDE(FindPkgConfig) pkg_check_modules(pkgs REQUIRED ${dependents}) diff --git a/lib/arm/libtangram.so b/lib/arm/libtangram.so index 3dd3742..60116a1 100755 Binary files a/lib/arm/libtangram.so and b/lib/arm/libtangram.so differ diff --git a/lib/i586/libtangram.so b/lib/i586/libtangram.so index f4ba918..2f36e9f 100755 Binary files a/lib/i586/libtangram.so and b/lib/i586/libtangram.so differ diff --git a/packaging/maps-plugin-mapzen.spec b/packaging/maps-plugin-mapzen.spec index c1a021e..41faf3e 100644 --- a/packaging/maps-plugin-mapzen.spec +++ b/packaging/maps-plugin-mapzen.spec @@ -19,6 +19,7 @@ BuildRequires: capi-maps-service-plugin-devel BuildRequires: pkgconfig(json-glib-1.0) BuildRequires: pkgconfig(ecore) BuildRequires: pkgconfig(evas) +BuildRequires: pkgconfig(elementary) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig diff --git a/src/mapzen/mapzen_api.cpp b/src/mapzen/mapzen_api.cpp index 7b6c594..dfe1ac5 100644 --- a/src/mapzen/mapzen_api.cpp +++ b/src/mapzen/mapzen_api.cpp @@ -168,7 +168,7 @@ int mapzen_get_scalebar(maps_view_h hView, bool *enabled) return error; } -int mapzen_on_object(maps_view_h hView, const maps_view_object_h object, maps_view_object_operation_e operation) +int mapzen_on_view_object(maps_view_h hView, const maps_view_object_h object, maps_view_object_operation_e operation) { TangramView* tv = nullptr; int maps_error = maps_view_get_maps_plugin_view_handle(hView, (void**)&tv); diff --git a/src/mapzen/mapzen_api.hpp b/src/mapzen/mapzen_api.hpp index 33f70b3..a87b97c 100644 --- a/src/mapzen/mapzen_api.hpp +++ b/src/mapzen/mapzen_api.hpp @@ -82,7 +82,7 @@ int mapzen_set_scalebar(maps_view_h hView, bool enable); int mapzen_get_scalebar(maps_view_h hView, bool *enabled); -int mapzen_on_object(maps_view_h hView, const maps_view_object_h object, maps_view_object_operation_e operation); +int mapzen_on_view_object(maps_view_h hView, const maps_view_object_h object, maps_view_object_operation_e operation); int mapzen_screen_to_geography(maps_view_h hView, int x, int y, maps_coordinates_h *mapsCoord); diff --git a/src/mapzen/tangram/tangram.h b/src/mapzen/tangram/tangram.h index af000ca..8477f04 100644 --- a/src/mapzen/tangram/tangram.h +++ b/src/mapzen/tangram/tangram.h @@ -1,6 +1,7 @@ #pragma once #include "properties.h" +#include "types.h" #include #include #include @@ -29,7 +30,6 @@ enum class EaseType : char { }; class Map { - public: // Create an empty map object. To display a map, call either loadScene() or loadSceneAsync(). @@ -149,6 +149,52 @@ public: void clearDataSource(DataSource& _source, bool _data, bool _tiles); + // Add a marker object to the map and return an ID for it; an ID of 0 indicates an invalid marker; + // the marker will not be drawn until both styling and geometry are set using the functions below. + MarkerID markerAdd(); + + // Remove a marker object from the map; returns true if the marker ID was found and successfully + // removed, otherwise returns false. + bool markerRemove(MarkerID _marker); + + // Set the styling for a marker object; _styling is a string of YAML that specifies a 'draw rule' + // according to the scene file syntax; returns true if the marker ID was found and successfully + // updated, otherwise returns false. + bool markerSetStyling(MarkerID _marker, const char* _styling); + + // Set the geometry of a marker to a point at the given coordinates; markers can have their + // geometry set multiple times with possibly different geometry types; returns true if the + // marker ID was found and successfully updated, otherwise returns false. + bool markerSetPoint(MarkerID _marker, LngLat _lngLat); + + // Set the geometry of a marker to a point at the given coordinates; if the marker was previously + // set to a point, this eases the position over the given duration in seconds with the given EaseType; + // returns true if the marker ID was found and successfully updated, otherwise returns false. + bool markerSetPointEased(MarkerID _marker, LngLat _lngLat, float _duration, EaseType _ease); + + // Set the geometry of a marker to a polyline along the given coordinates; _coordinates is a + // pointer to a sequence of _count LngLats; markers can have their geometry set multiple times + // with possibly different geometry types; returns true if the marker ID was found and + // successfully updated, otherwise returns false. + bool markerSetPolyline(MarkerID _marker, LngLat* _coordinates, int _count); + + // Set the geometry of a marker to a polygon with the given coordinates; _counts is a pointer + // to a sequence of _rings integers and _coordinates is a pointer to a sequence of LngLats with + // a total length equal to the sum of _counts; for each integer n in _counts, a polygon is created + // by taking the next n LngLats from _coordinates, with winding order and internal polygons + // behaving according to the GeoJSON specification; markers can have their geometry set multiple + // times with possibly different geometry types; returns true if the marker ID was found and + // successfully updated, otherwise returns false. + bool markerSetPolygon(MarkerID _marker, LngLat* _coordinates, int* _counts, int _rings); + + // Set the visibility of a marker object; returns true if the marker ID was found and successfully + // updated, otherwise returns false. + bool markerSetVisible(MarkerID _marker, bool _visible); + + // Remove all marker objects from the map; Any marker IDs previously returned from 'markerAdd' + // are invalidated after this. + void markerRemoveAll(); + // Respond to a tap at the given screen coordinates (x right, y down) void handleTapGesture(float _posX, float _posY); @@ -184,7 +230,6 @@ private: class Impl; std::unique_ptr impl; - }; enum DebugFlags { @@ -194,7 +239,7 @@ enum DebugFlags { tile_infos, // Debug tile infos labels, // Debug label bounding boxes tangram_infos, // Various text tangram debug info printed on the screen - all_labels, // Draw all labels + draw_all_labels, // Draw all labels tangram_stats, // Tangram frame graph stats }; diff --git a/src/mapzen/tangram/types.h b/src/mapzen/tangram/types.h new file mode 100644 index 0000000..6913e1c --- /dev/null +++ b/src/mapzen/tangram/types.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +namespace Tangram { + +struct Range { + int start; + int length; + + int end() const { return start + length; } + + Range(int _start, int _length) : start(_start), length(_length) {} + + Range() : start(0), length(0) {} +}; + +struct LngLat { + LngLat() {} + LngLat(double _lon, double _lat) : longitude(_lon), latitude(_lat) {} + + LngLat(const LngLat& _other) = default; + LngLat(LngLat&& _other) = default; + LngLat& operator=(const LngLat& _other) = default; + LngLat& operator=(LngLat&& _other) = default; + + bool operator==(const LngLat& _other) { + return longitude == _other.longitude && + latitude == _other.latitude; + } + + double longitude = 0.0; + double latitude = 0.0; +}; + +typedef std::vector Coordinates; + +typedef uint32_t MarkerID; + +} diff --git a/src/mapzen/tangram_view.cpp b/src/mapzen/tangram_view.cpp index 4a93929..1529bbf 100644 --- a/src/mapzen/tangram_view.cpp +++ b/src/mapzen/tangram_view.cpp @@ -25,6 +25,10 @@ extern "C" { #include "tangram_view.hpp" #include "tangram/tangram.h" #include "tangram/platform_tizen.h" +#include + +#include +#include #define NORMAL_SCENE_FILE_PATH "/usr/share/maps/mapzen/scenes/bubble-wrap/bubble-wrap.yaml" #define TERRAIN_SCENE_FILE_PATH "/usr/share/maps/mapzen/scenes/walkabout-style/walkabout-style.yaml" @@ -118,11 +122,17 @@ mapzen_error_e TangramView::create(maps_view_h view, maps_plugin_map_view_ready_ // Set up the tangram map. m_map = new Tangram::Map(); + + float scaleFactor = elm_config_scale_get(); + MAPS_LOGD("evas_gl_context_create() set PixelScale %f", scaleFactor); + m_map->setPixelScale(scaleFactor); + m_map->loadScene(NORMAL_SCENE_FILE_PATH); // Make the GL context current and perform GL setup. evas_gl_make_current(m_gl, m_surface, m_context); m_map->setupGL(); + m_map->resize(m_w, m_h); readyMapCb((void*)view); @@ -206,6 +216,7 @@ mapzen_error_e TangramView::destroy(maps_view_h view) } if (m_map) { + removeAllObjects(); delete m_map; m_map = nullptr; } @@ -396,8 +407,282 @@ mapzen_error_e TangramView::getMaxZoomLevel(maps_view_h view, int *zoom) mapzen_error_e TangramView::onViewObject(maps_view_h view, const maps_view_object_h object, maps_view_object_operation_e operation) { - // TODO - return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE; + if (!view || !object || operation < MAPS_VIEW_OBJECT_ADD || operation > MAPS_VIEW_OBJECT_REMOVE) { + return MAPZEN_ERROR_INVALID_PARAMETER; + } + + if (!m_isInitialized || !m_map) { + return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE; + } + + return processViewObject(view, object, operation); +} + +mapzen_error_e TangramView::processViewObject(maps_view_h view, const maps_view_object_h object, maps_view_object_operation_e operation) +{ + mapzen_error_e error = MAPZEN_ERROR_NONE; + + TangramView *tv = nullptr; + int maps_error = maps_view_get_maps_plugin_view_handle(view, (void**)&tv); + if (maps_error != MAPS_ERROR_NONE || !tv) { return MAPZEN_ERROR_INVALID_PARAMETER; } + + maps_view_object_type_e type = MAPS_VIEW_OBJECT_POLYLINE; + maps_view_object_get_type(object, &type); + + if (type < MAPS_VIEW_OBJECT_POLYLINE || type > MAPS_VIEW_OBJECT_MARKER) { return MAPZEN_ERROR_INVALID_PARAMETER; } + if (operation < MAPS_VIEW_OBJECT_ADD || operation > MAPS_VIEW_OBJECT_REMOVE) { return MAPZEN_ERROR_INVALID_PARAMETER; } + + auto& mapViewObjs = tv->mapViewObjects(); + auto& mutex = tv->viewObjectMutex(); + MapViewObjects::iterator iter; + MapViewObjects::iterator end; + { + std::lock_guard lock(mutex); + iter = mapViewObjs.find(object); + end = mapViewObjs.end(); + } + + switch(operation) { + case MAPS_VIEW_OBJECT_ADD: + error = tv->addObject(object); + break; + case MAPS_VIEW_OBJECT_SET_VISIBLE: + if (iter != end) { + error = tv->setObjectVisible(object, iter->second); + } + break; + case MAPS_VIEW_OBJECT_CHANGE: + if (iter != end) { + error = tv->updateObject(object, iter->second); + } + break; + case MAPS_VIEW_OBJECT_REMOVE: + error = tv->removeObject(object); + break; + default: break; + } + + const char *oper_str[20] = { "ADD", "SET_VISIBLE", "MOVE", "CHANGE", "REMOVE"}; + const char *type_str[20] = { "POLYLINE", "POLYGON", "MARKER", "UNKNOWN"}; + + MAPS_LOGD("Done Processing View Object: type=%s, operation=%s, object=%p", + (type >= MAPS_VIEW_OBJECT_POLYLINE && type <= MAPS_VIEW_OBJECT_MARKER) ? type_str[type] : "?", + (operation >= MAPS_VIEW_OBJECT_ADD && operation <= MAPS_VIEW_OBJECT_REMOVE) ? oper_str[operation] : "?", + object); + + if (error != MAPZEN_ERROR_NONE) { + MAPS_LOGD("Something went wrong in processing this ViewObject operation"); + } + + return error; +} + +mapzen_error_e TangramView::addObject(maps_view_object_h object) +{ + if (!object || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; } + + mapzen_error_e error = MAPZEN_ERROR_NONE; + Tangram::MarkerID tvMarker = 0; + maps_view_object_type_e type = MAPS_VIEW_OBJECT_POLYLINE; + + maps_view_object_get_type(object, &type); + + MapViewObjects::iterator iter; + MapViewObjects::iterator end; + + switch(type) { + case MAPS_VIEW_OBJECT_MARKER: + case MAPS_VIEW_OBJECT_POLYGON: + case MAPS_VIEW_OBJECT_POLYLINE: + { + std::lock_guard lock(m_viewObjectMutex); + iter = m_mapViewObjs.find(object); + end = m_mapViewObjs.end(); + } + if (iter == end) { + tvMarker = m_map->markerAdd(); + if (tvMarker) { + error = updateObject(object, tvMarker); + if (error == MAPZEN_ERROR_NONE) { + std::lock_guard lock(m_viewObjectMutex); + m_mapViewObjs.insert(std::make_pair(object, tvMarker)); + } else { + m_map->markerRemove(tvMarker); + tvMarker = 0; + } + } + } + break; + default: + break; + } + + return error; +} + +mapzen_error_e TangramView::setObjectVisible(maps_view_object_h object, Tangram::MarkerID tvMarker) +{ + if (!object || !tvMarker || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; } + + bool visible = true; + maps_view_object_get_visible(object, &visible); + + m_map->markerSetVisible(tvMarker, visible); + return MAPZEN_ERROR_NONE; +} + +mapzen_error_e TangramView::updateObject(maps_view_object_h object, Tangram::MarkerID tvMarker) +{ + if (!object || !tvMarker || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; } + + int error = MAPS_ERROR_NONE; + maps_view_object_type_e type = MAPS_VIEW_OBJECT_POLYLINE; + + maps_view_object_get_type(object, &type); + + std::string styleString = ""; + + Tangram::Coordinates coords = {}; + unsigned char r = 0, g = 0, b = 0, a = 0; + + switch(type) { + case MAPS_VIEW_OBJECT_MARKER: + { + // TODO: distinguish between MAPS_VIEW_MARKER_PIN and MAPS_VIEW_MARKER_STICKER (pin vs billboard?) + // TODO: use image passed with the view object, not available in tangram yet! + maps_coordinates_h mapsCoord = nullptr; + double lat = 0.0, lng = 0.0; + int markerWidth = 0, markerHeight = 0; + + const char* styleFormat = "{ style: 'ux-icons-overlay', sprite: 'ux-search-active', size: [%dpx, %dpx], collide: false, anchor: top, transition: { [show, hide]: { time: 0s } } }"; + + error = maps_view_object_marker_get_size(object, &markerWidth, &markerHeight); + if (error != MAPS_ERROR_NONE) { break; } + + int sz = std::snprintf(nullptr, 0, styleFormat, markerWidth, markerHeight); + styleString.resize(sz+1); + std::snprintf(&styleString[0], styleString.size(), styleFormat, markerWidth, markerHeight); + + m_map->markerSetStyling(tvMarker, styleString.c_str()); + + error = maps_view_object_marker_get_coordinates(object, &mapsCoord); + if (error != MAPS_ERROR_NONE) { break; } + + error = maps_coordinates_get_longitude(mapsCoord, &lng); + if (error != MAPS_ERROR_NONE) { + maps_coordinates_destroy(mapsCoord); + break; + } + + error = maps_coordinates_get_latitude(mapsCoord, &lat); + if (error != MAPS_ERROR_NONE) { + maps_coordinates_destroy(mapsCoord); + break; + } + + maps_coordinates_destroy(mapsCoord); + m_map->markerSetPoint(tvMarker, Tangram::LngLat(lng, lat)); + } + break; + case MAPS_VIEW_OBJECT_POLYLINE: + { + int width = 0; + const char* styleFormat = "{ style: 'ux-route-line-overlay', color: [%d, %d, %d, %d], width: %dpx, order: 500 }"; + + error = maps_view_object_polyline_get_color(object, &r, &g, &b, &a); + if (error != MAPS_ERROR_NONE) { break; } + + error = maps_view_object_polyline_get_width(object, &width); + if (error != MAPS_ERROR_NONE) { break; } + + int sz = std::snprintf(nullptr, 0, styleFormat, r, g, b, a, width); + styleString.resize(sz+1); + std::snprintf(&styleString[0], styleString.size(), styleFormat, r, g, b, a, width); + + m_map->markerSetStyling(tvMarker, styleString.c_str()); + + error = maps_view_object_polyline_foreach_point(object, emplaceCoord, &coords); + if (error != MAPS_ERROR_NONE) { break; } + + m_map->markerSetPolyline(tvMarker, coords.data(), static_cast(coords.size())); + } + break; + case MAPS_VIEW_OBJECT_POLYGON: + { + const char* styleFormat = "{ style: 'polygons', color: [%d, %d, %d, %d] }"; + + error = maps_view_object_polygon_get_fill_color(object, &r, &g, &b, &a); + if (error != MAPS_ERROR_NONE) { break; } + + int sz = std::snprintf(nullptr, 0, styleFormat, r, g, b, a); + styleString.resize(sz+1); + std::snprintf(&styleString[0], styleString.size(), styleFormat, r, g, b, a); + + m_map->markerSetStyling(tvMarker, styleString.c_str()); + + error = maps_view_object_polygon_foreach_point(object, emplaceCoord, &coords); + if (error != MAPS_ERROR_NONE) { break; } + + int count = (int)coords.size(); + m_map->markerSetPolygon(tvMarker, coords.data(), &count, 1); + } + break; + default: + break; + } + + return (mapzen_error_e)convert_maps_error_to_mapzen_error(error); +} + +mapzen_error_e TangramView::removeObject(maps_view_object_h object) +{ + if (!object || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; } + + mapzen_error_e error = MAPZEN_ERROR_NONE; + + std::lock_guard lock(m_viewObjectMutex); + auto iter = m_mapViewObjs.find(object); + if (iter != m_mapViewObjs.end()) { + if (iter->second) { + m_map->markerRemove(iter->second); + } + iter = m_mapViewObjs.erase(iter); + error = MAPZEN_ERROR_NONE; + } + + return error; +} + +void TangramView::removeAllObjects() +{ + std::lock_guard lock(m_viewObjectMutex); + m_mapViewObjs.clear(); + m_map->markerRemoveAll(); +} + +bool TangramView::emplaceCoord(int index, maps_coordinates_h coordinate, void *user_data) +{ + if (!coordinate || !user_data) { return false; } + + int error = 0; + double lng = 0.0, lat = 0.0; + + error = maps_coordinates_get_longitude(coordinate, &lng); + if (error != MAPS_ERROR_NONE) { + MAPS_LOGD("Not able to extract longitude from coordiate"); + return false; + } + error = maps_coordinates_get_latitude(coordinate, &lat); + if (error != MAPS_ERROR_NONE) { + MAPS_LOGD("Not able to extract longitude from coordiate"); + return false; + } + + MAPS_LOGD("[%d] %f, %f", index+1, lng, lat); + + Tangram::Coordinates *coords = static_cast(user_data); + coords->emplace_back(lng, lat); + return true; } mapzen_error_e TangramView::captureSnapshot(maps_view_h view, void **data, int *width, int *height, maps_view_colorspace_type_e *cs) diff --git a/src/mapzen/tangram_view.hpp b/src/mapzen/tangram_view.hpp index 3dab34c..490b795 100644 --- a/src/mapzen/tangram_view.hpp +++ b/src/mapzen/tangram_view.hpp @@ -23,12 +23,18 @@ #include #include #include +#include +#include + #include "mapzen_types.h" +#include "tangram/types.h" namespace Tangram { class Map; } +typedef std::map MapViewObjects; + class TangramView { public: @@ -55,11 +61,21 @@ public: private: mapzen_error_e setupOpenGlSurface(maps_view_h view); void setMapType(maps_view_h view); + + mapzen_error_e addObject(maps_view_object_h object); + mapzen_error_e setObjectVisible(maps_view_object_h object, Tangram::MarkerID tvMarker); + mapzen_error_e updateObject(maps_view_object_h object, Tangram::MarkerID tvMarker); + mapzen_error_e removeObject(maps_view_object_h object); + MapViewObjects& mapViewObjects() { return m_mapViewObjs; } + std::mutex& viewObjectMutex() { return m_viewObjectMutex; } + void removeAllObjects(); + static void readyMapCb(void *view); static void renderingCb(void *data); static void pixelGetCb(void *data, Evas_Object *obj); - -private: + static mapzen_error_e processViewObject(maps_view_h view, const maps_view_object_h object, maps_view_object_operation_e operation); + // Emplaces the lng/lat from `coordinate` to `user_data` (Tangram::Coordinates) + static bool emplaceCoord(int index, maps_coordinates_h coordinate, void *user_data); Tangram::Map *m_map = nullptr; Evas_Object *m_image = nullptr; @@ -80,6 +96,10 @@ private: double m_zoom = 0.; double m_angle = 0.; + std::mutex m_viewObjectMutex; + maps_plugin_map_view_ready_cb m_readyCb = nullptr; tangram_view_type m_viewType = TANGRAM_VIEW_NORMAL; + + MapViewObjects m_mapViewObjs; //current set of map objects }; diff --git a/src/mapzen_plugin.c b/src/mapzen_plugin.c index 4ff1214..fb9859c 100644 --- a/src/mapzen_plugin.c +++ b/src/mapzen_plugin.c @@ -89,7 +89,8 @@ EXPORT_API int maps_plugin_get_scalebar(maps_view_h hView, bool *enabled) EXPORT_API int maps_plugin_on_object(maps_view_h hView, const maps_view_object_h object, maps_view_object_operation_e operation) { - return MAPS_ERROR_NOT_SUPPORTED; + int ret = mapzen_on_view_object(hView, object, operation); + return convert_mapzen_error_to_maps_error(ret); } EXPORT_API int maps_plugin_screen_to_geography(maps_view_h hView, int x, int y, maps_coordinates_h *mapsCoord)