added basic gesture system on Android
This commit is contained in:
@@ -373,20 +373,78 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
|
|||||||
// case AINPUT_SOURCE_TOUCHSCREEN:
|
// case AINPUT_SOURCE_TOUCHSCREEN:
|
||||||
{
|
{
|
||||||
int action = AKeyEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
|
int action = AKeyEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
|
||||||
float x = AMotionEvent_getX(event, 0);
|
int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
|
||||||
float y = AMotionEvent_getY(event, 0);
|
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||||
|
int pointer_id = AMotionEvent_getPointerId(event, index);
|
||||||
|
int32_t count = AMotionEvent_getPointerCount(event);
|
||||||
|
struct Pointer
|
||||||
|
{
|
||||||
|
int id = -1;
|
||||||
|
int idx;
|
||||||
|
glm::vec2 pos;
|
||||||
|
};
|
||||||
|
static Pointer p0, p1;
|
||||||
|
static int tracked = 0;
|
||||||
|
float x = AMotionEvent_getX(event, index);
|
||||||
|
float y = AMotionEvent_getY(event, index);
|
||||||
//LOG("event source: %d", AInputEvent_getSource(event));
|
//LOG("event source: %d", AInputEvent_getSource(event));
|
||||||
MouseEvent e;
|
MouseEvent e;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case AMOTION_EVENT_ACTION_DOWN:
|
case AMOTION_EVENT_ACTION_DOWN:
|
||||||
|
p0.id = AMotionEvent_getPointerId(event, 0);
|
||||||
|
p0.pos = {x, y};
|
||||||
App::I.mouse_down(0, x, y);
|
App::I.mouse_down(0, x, y);
|
||||||
|
tracked = 1;
|
||||||
|
LOG("first down");
|
||||||
|
return 1;
|
||||||
|
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||||
|
if (count == 2)
|
||||||
|
{
|
||||||
|
p1.id = AMotionEvent_getPointerId(event, index);
|
||||||
|
p1.idx = index;
|
||||||
|
p1.pos = {x, y};
|
||||||
|
tracked = 2;
|
||||||
|
LOG("second down");
|
||||||
|
App::I.mouse_cancel(0);
|
||||||
|
App::I.gesture_start(p0.pos, p1.pos);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
case AMOTION_EVENT_ACTION_UP:
|
case AMOTION_EVENT_ACTION_UP:
|
||||||
|
tracked = 0;
|
||||||
|
p0.id = -1;
|
||||||
|
p1.id = -1;
|
||||||
App::I.mouse_up(0, x, y);
|
App::I.mouse_up(0, x, y);
|
||||||
|
LOG("first up");
|
||||||
|
return 1;
|
||||||
|
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||||
|
if (p1.id == AMotionEvent_getPointerId(event, index))
|
||||||
|
{
|
||||||
|
p1.id = -1;
|
||||||
|
LOG("second up");
|
||||||
|
App::I.gesture_end();
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
case AMOTION_EVENT_ACTION_HOVER_MOVE: // pen move before touching
|
case AMOTION_EVENT_ACTION_HOVER_MOVE: // pen move before touching
|
||||||
case AMOTION_EVENT_ACTION_MOVE:
|
case AMOTION_EVENT_ACTION_MOVE:
|
||||||
App::I.mouse_move(x, y);
|
if (tracked == 1)
|
||||||
|
{
|
||||||
|
App::I.mouse_move(x, y);
|
||||||
|
LOG("single move");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p0.id == pointer_id)
|
||||||
|
{
|
||||||
|
LOG("first move");
|
||||||
|
p0.pos = {x, y};
|
||||||
|
}
|
||||||
|
if (p1.id == pointer_id)
|
||||||
|
{
|
||||||
|
LOG("second move");
|
||||||
|
p1.pos = {x, y};
|
||||||
|
}
|
||||||
|
App::I.gesture_move(p0.pos, p1.pos);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
//LOG("motion action: %d", action);
|
//LOG("motion action: %d", action);
|
||||||
|
|||||||
@@ -652,6 +652,48 @@ bool App::mouse_scroll(float x, float y, float delta)
|
|||||||
layout[main_id]->update();
|
layout[main_id]->update();
|
||||||
return ret == kEventResult::Consumed;
|
return ret == kEventResult::Consumed;
|
||||||
}
|
}
|
||||||
|
bool App::mouse_cancel(int button)
|
||||||
|
{
|
||||||
|
MouseEvent e;
|
||||||
|
e.m_type = kEventType::MouseCancel;
|
||||||
|
auto ret = layout[main_id]->on_event(&e);
|
||||||
|
layout[main_id]->update();
|
||||||
|
return ret == kEventResult::Consumed;
|
||||||
|
}
|
||||||
|
bool App::gesture_start(const glm::vec2& p0, const glm::vec2& p1)
|
||||||
|
{
|
||||||
|
GestureEvent e;
|
||||||
|
glm::vec2 p = glm::lerp(p0, p1, 0.5f);
|
||||||
|
e.m_type = kEventType::GestureStart;
|
||||||
|
e.m_pos = p;
|
||||||
|
e.m_distance = glm::distance(p0, p1);
|
||||||
|
gesture_p0 = p0;
|
||||||
|
gesture_p1 = p1;
|
||||||
|
auto ret = layout[main_id]->on_event(&e);
|
||||||
|
layout[main_id]->update();
|
||||||
|
return ret == kEventResult::Consumed;
|
||||||
|
}
|
||||||
|
bool App::gesture_move(const glm::vec2& p0, const glm::vec2& p1)
|
||||||
|
{
|
||||||
|
GestureEvent e;
|
||||||
|
glm::vec2 p = glm::lerp(p0, p1, 0.5f);
|
||||||
|
e.m_type = kEventType::GestureMove;
|
||||||
|
e.m_pos = p;
|
||||||
|
e.m_distance = glm::distance(p0, p1);
|
||||||
|
e.m_distance_delta = e.m_distance - glm::distance(gesture_p0, gesture_p1);
|
||||||
|
e.m_pos_delta = p - glm::lerp(gesture_p0, gesture_p1, 0.5f);
|
||||||
|
auto ret = layout[main_id]->on_event(&e);
|
||||||
|
layout[main_id]->update();
|
||||||
|
return ret == kEventResult::Consumed;
|
||||||
|
}
|
||||||
|
bool App::gesture_end()
|
||||||
|
{
|
||||||
|
GestureEvent e;
|
||||||
|
e.m_type = kEventType::GestureEnd;
|
||||||
|
auto ret = layout[main_id]->on_event(&e);
|
||||||
|
layout[main_id]->update();
|
||||||
|
return ret == kEventResult::Consumed;
|
||||||
|
}
|
||||||
bool App::key_down(kKey key)
|
bool App::key_down(kKey key)
|
||||||
{
|
{
|
||||||
KeyEvent e;
|
KeyEvent e;
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public:
|
|||||||
const uint16_t main_id = const_hash("main");
|
const uint16_t main_id = const_hash("main");
|
||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
|
glm::vec2 gesture_p0;
|
||||||
|
glm::vec2 gesture_p1;
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
float zoom = 3.0;
|
float zoom = 3.0;
|
||||||
#else
|
#else
|
||||||
@@ -52,6 +54,10 @@ public:
|
|||||||
bool mouse_move(float x, float y);
|
bool mouse_move(float x, float y);
|
||||||
bool mouse_up(int button, float x, float y);
|
bool mouse_up(int button, float x, float y);
|
||||||
bool mouse_scroll(float x, float y, float delta);
|
bool mouse_scroll(float x, float y, float delta);
|
||||||
|
bool mouse_cancel(int button);
|
||||||
|
bool gesture_start(const glm::vec2& p0, const glm::vec2& p1);
|
||||||
|
bool gesture_move(const glm::vec2& p0, const glm::vec2& p1);
|
||||||
|
bool gesture_end();
|
||||||
bool key_down(kKey key);
|
bool key_down(kKey key);
|
||||||
bool key_up(kKey key);
|
bool key_up(kKey key);
|
||||||
bool key_char(char key);
|
bool key_char(char key);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ enum class kEventCategory : uint8_t
|
|||||||
MouseEvent,
|
MouseEvent,
|
||||||
KeyEvent,
|
KeyEvent,
|
||||||
ButtonEvent,
|
ButtonEvent,
|
||||||
|
GestureEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class kEventType : uint8_t
|
enum class kEventType : uint8_t
|
||||||
@@ -33,6 +34,10 @@ enum class kEventType : uint8_t
|
|||||||
MouseEnter,
|
MouseEnter,
|
||||||
MouseLeave,
|
MouseLeave,
|
||||||
MouseScroll,
|
MouseScroll,
|
||||||
|
MouseCancel,
|
||||||
|
GestureStart,
|
||||||
|
GestureMove,
|
||||||
|
GestureEnd,
|
||||||
KeyDown,
|
KeyDown,
|
||||||
KeyUp,
|
KeyUp,
|
||||||
KeyChar,
|
KeyChar,
|
||||||
@@ -62,3 +67,15 @@ public:
|
|||||||
kKey m_key;
|
kKey m_key;
|
||||||
char m_char;
|
char m_char;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GestureEvent : public Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GestureEvent() { m_cat = kEventCategory::GestureEvent; }
|
||||||
|
float m_distance;
|
||||||
|
float m_distance_delta;
|
||||||
|
float m_angle;
|
||||||
|
float m_angle_delta;
|
||||||
|
glm::vec2 m_pos;
|
||||||
|
glm::vec2 m_pos_delta;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1860,6 +1860,7 @@ class NodeCanvas : public Node
|
|||||||
glm::vec2 m_pan_start;
|
glm::vec2 m_pan_start;
|
||||||
glm::vec2 m_pan;
|
glm::vec2 m_pan;
|
||||||
float m_zoom_canvas = 1.f;
|
float m_zoom_canvas = 1.f;
|
||||||
|
float m_zoom_start;
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<ui::Canvas> m_canvas;
|
std::unique_ptr<ui::Canvas> m_canvas;
|
||||||
ui::Brush m_brush;
|
ui::Brush m_brush;
|
||||||
@@ -1944,6 +1945,7 @@ public:
|
|||||||
Node::handle_event(e);
|
Node::handle_event(e);
|
||||||
MouseEvent* me = static_cast<MouseEvent*>(e);
|
MouseEvent* me = static_cast<MouseEvent*>(e);
|
||||||
KeyEvent* ke = static_cast<KeyEvent*>(e);
|
KeyEvent* ke = static_cast<KeyEvent*>(e);
|
||||||
|
GestureEvent* ge = static_cast<GestureEvent*>(e);
|
||||||
auto loc = me->m_pos - m_pos;
|
auto loc = me->m_pos - m_pos;
|
||||||
auto clip_space = glm::vec2(loc.x, m_size.y - loc.y - 1.f) / m_size * 2.f - 1.f;
|
auto clip_space = glm::vec2(loc.x, m_size.y - loc.y - 1.f) / m_size * 2.f - 1.f;
|
||||||
auto fb_space = glm::inverse(m_canvas->m_mvp) * glm::vec4(clip_space, 0, 1);
|
auto fb_space = glm::inverse(m_canvas->m_mvp) * glm::vec4(clip_space, 0, 1);
|
||||||
@@ -1982,6 +1984,10 @@ public:
|
|||||||
case kEventType::MouseScroll:
|
case kEventType::MouseScroll:
|
||||||
m_zoom_canvas += me->m_scroll_delta * 0.1f;
|
m_zoom_canvas += me->m_scroll_delta * 0.1f;
|
||||||
break;
|
break;
|
||||||
|
case kEventType::MouseCancel:
|
||||||
|
m_dragging = false;
|
||||||
|
mouse_release();
|
||||||
|
break;
|
||||||
case kEventType::KeyDown:
|
case kEventType::KeyDown:
|
||||||
if (ke->m_key == kKey::KeyE)
|
if (ke->m_key == kKey::KeyE)
|
||||||
m_canvas->m_erase = true;
|
m_canvas->m_erase = true;
|
||||||
@@ -1993,6 +1999,15 @@ public:
|
|||||||
case kEventType::KeyUp:
|
case kEventType::KeyUp:
|
||||||
if (ke->m_key == kKey::KeyE)
|
if (ke->m_key == kKey::KeyE)
|
||||||
m_canvas->m_erase = false;
|
m_canvas->m_erase = false;
|
||||||
|
break;
|
||||||
|
case kEventType::GestureStart:
|
||||||
|
m_pan_start = m_pan;
|
||||||
|
m_zoom_start = m_zoom_canvas;
|
||||||
|
break;
|
||||||
|
case kEventType::GestureMove:
|
||||||
|
m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(1, -1);
|
||||||
|
//m_zoom_canvas = m_zoom_start + ge->m_distance;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user