Interactive Map¶
Prerequisites¶
Touch event listener¶
Open the file CenterMap.cpp
and define a touch event listener class,
that is, add the following code before the main()
function:
1class CTouchEventListener : public ITouchEventsListener
2{
3 public:
4 void setMapViewPointer(std::shared_ptr<gem::MapView> pMapView)
5 {
6 m_mapView = pMapView;
7 lastXpos = 0; lastYpos = 0;
8 }
9 void handleTouchEvent(int eventType,int pointerId,int x,int y) override
10 {
11 lastXpos = x; lastYpos = y;
12 gem::Xy mousePos(x,y);
13 if(m_mapView.get()!=nullptr)
14 m_mapView->getScreen()->handleTouchEvent((gem::ETouchEvent)eventType,pointerId,mousePos);
15 }
16 void handleMouseScrollEvent(int delta,int x,int y) override
17 {
18 gem::Xy mousePos(x,y);
19 if(m_mapView.get()!=nullptr)
20 m_mapView->getScreen()->scrollEvent(delta,mousePos);
21 }
22 void getCursorPosition(int &x, int &y) override
23 {
24 x = lastXpos; y = lastYpos;
25 }
26 private:
27 std::shared_ptr<gem::MapView> m_mapView;
28 int lastXpos, lastYpos;
29};
The touch event listener instance keeps a pointer to the MapView
instance,
which is used to pass the user touch inputs to the SDK. The pointer to
the MapView instance is set via setMapViewPointer()
The main function to pass touch inputs to the SDK is handleTouchEvent()
,
whereas handleMouseScrollEvent()
is used to pass mouse scroll events to
the SDK.
The function getCursorPosition()
is a necessary convenience, to get the current
x,y mouse cursor position in pixels, as this position must be passed to the SDK with
all touch events, however, not all input callbacks contain the x,y position, so for
those events that do not have an explicit x,y position, the last x,y position is
stored and then retrieved using this funtion.
Replace the following line:
auto oglContext = env.ProduceOpenGLContext("centerMap");
with this code, to add the touch event listener:
CTouchEventListener pTouchEventListener;
auto oglContext = env.ProduceOpenGLContext("centerMap", &pTouchEventListener);
After the mapView = gem::MapView::produce()
line, add this line:
pTouchEventListener.setMapViewPointer(mapView);
to save a pointer to the mapView
in the touch event listener.
Environment.cpp¶
Open the file Environment.cpp
and add the touch event listener to the
ProduceOpenGLContext()
function so that the function looks as follows:
1gem::StrongPointer<OpenGLContext> Environment::ProduceOpenGLContext(
2 std::string windowName, ITouchEventsListener* pTouchEventListener)
3{
4 if (!m_openGLContext.get())
5 m_openGLContext = OpenGLContext::Produce(windowName, pTouchEventListener);
6 return m_openGLContext;
7}
Environment.h¶
Open the file Environment.h
and add the touch event listener to the
ProduceOpenGLContext()
function signature so that it looks as follows:
1gem::StrongPointer<OpenGLContext> ProduceOpenGLContext(std::string windowName = "",
2 ITouchEventsListener* pListener = nullptr);
OpenGLContext.cpp¶
Open the file OpenGLContext.cpp
and add the touch event listener to the
initialize()
function so that it looks as follows:
1bool OpenGLContext::initialize(GLFWwindow* pWindow, float nDPI,
2 ITouchEventsListener* pEventTouchListener = nullptr)
3{
4 m_window = pWindow;
5 m_dpi = nDPI;
6 m_initialized = true;
7 m_pTouchEventListener = pEventTouchListener;
8 glfwSetWindowUserPointer(pWindow,this);
9 return true;
10}
Also add a get function as shown, to return a pointer to the
touch events listener: GetTouchEventHandler()
1ITouchEventsListener* OpenGLContext::GetTouchEventHandler()
2{
3 return m_pTouchEventListener;
4}
Add the 3 mouse/touch input event callback functions which receive the input events from the GLFW library and then pass them to the SDK via the touch events listener.
1void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
2{
3 OpenGLContext* pOpenGLContext = (OpenGLContext*)glfwGetWindowUserPointer(window);
4 if (pOpenGLContext && pOpenGLContext->GetTouchEventHandler())
5 {
6 int xpos, ypos;
7 //get the stored cursor position because a button event does not include it
8 pOpenGLContext->GetTouchEventHandler()->getCursorPosition(xpos, ypos);
9 if (button == GLFW_MOUSE_BUTTON_LEFT)
10 {
11 if (action == GLFW_PRESS)
12 {
13 pOpenGLContext->GetTouchEventHandler()->handleTouchEvent(gem::ETouchEvent::TE_Down, 0, xpos, ypos);
14 }
15 else if (action == GLFW_RELEASE)
16 {
17 pOpenGLContext->GetTouchEventHandler()->handleTouchEvent(gem::ETouchEvent::TE_Up, 0, xpos, ypos);
18 }
19 }
20 }
21}
22void cursorPositionCallback(GLFWwindow* window, double xpos, double ypos)
23{
24 OpenGLContext* pOpenGLContext = (OpenGLContext*)glfwGetWindowUserPointer(window);
25 if (pOpenGLContext)
26 {
27 if (pOpenGLContext->GetTouchEventHandler())
28 {
29 pOpenGLContext->GetTouchEventHandler()->handleTouchEvent(gem::ETouchEvent::TE_Move, 0, (int)xpos, (int)ypos);
30 }
31 }
32}
33void mouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
34{
35 OpenGLContext* pOpenGLContext = (OpenGLContext*)glfwGetWindowUserPointer(window);
36 if (pOpenGLContext && pOpenGLContext->GetTouchEventHandler())
37 {
38 int xpos, ypos;
39 pOpenGLContext->GetTouchEventHandler()->getCursorPosition(xpos, ypos);
40 if (pOpenGLContext->GetTouchEventHandler())
41 {
42 pOpenGLContext->GetTouchEventHandler()->handleMouseScrollEvent((int)yoffset, (int)xpos, (int)ypos);
43 }
44 }
45}
mouseButtonCallback()
captures mouse button up or down events.cursorPositionCallback()
captures mouse motion events, regardless if a mouse button is up or down.mouseScrollCallback()
captures mouse scroll events, used for zooming the map.Change the Produce()
function signature by adding the touch event listener, so it looks like this:
gem::StrongPointer<OpenGLContext> OpenGLContext::Produce(std::string windowName, ITouchEventsListener* pEventTouchListener)
Set the 3 touch input GLFW callback functions defined above:
1glfwSetMouseButtonCallback(pDisplayWindow, mouseButtonCallback);
2glfwSetCursorPosCallback(pDisplayWindow, cursorPositionCallback);
3glfwSetScrollCallback(pDisplayWindow, mouseScrollCallback);
Also update the initialize()
function call at the bottom so it looks like this:
m_pOpenGLContext->initialize(pDisplayWindow, nDPI,pEventTouchListener);
OpenGLContext.h¶
Open the file OpenGLContext.h
and add the following include directive:
#include <API/GEM_Canvas.h> //gem::ETouchEvent
Add the touch events listener interface:
1class ITouchEventsListener
2{
3 public:
4 virtual void handleTouchEvent(int eventType,int pointerId,int x,int y) = 0;
5 virtual void handleMouseScrollEvent(int delta,int x,int y) = 0;
6 virtual void getCursorPosition(int& x, int& y) = 0;
7};
Update the initialize()
public function signature so it looks like this:
bool initialize(GLFWwindow* pWindow, float nDPI,ITouchEventsListener* pEventTouchListener);
Update the Produce()
public function signature by adding the touch event listener, so it looks like this:
static gem::StrongPointer<OpenGLContext> Produce(std::string windowName = "", ITouchEventsListener* pTouchEventListener = nullptr);
Add this public function signature:
ITouchEventsListener* GetTouchEventHandler();
Add this private member variable:
ITouchEventsListener* m_pTouchEventListener;
Try it out!¶
Click the green arrow play button at the top to compile and run the project. You can now pan the map and zoom in/out using the mouse scroll wheel.