Add basic pinch zoom support on Android
This commit is contained in:
parent
6c31e1bc01
commit
b85dc2f001
|
@ -280,6 +280,15 @@ dependencies = [
|
||||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -311,6 +320,15 @@ dependencies = [
|
||||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deflate"
|
name = "deflate"
|
||||||
version = "0.7.19"
|
version = "0.7.19"
|
||||||
|
@ -1029,6 +1047,7 @@ dependencies = [
|
||||||
name = "pathfinder_magicleap_demo"
|
name = "pathfinder_magicleap_demo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1958,9 +1977,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
||||||
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
|
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
|
||||||
"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
|
"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
|
||||||
|
"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
|
||||||
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
|
||||||
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
|
||||||
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
|
||||||
|
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
|
||||||
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
|
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
|
||||||
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||||
"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
|
"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
|
||||||
|
|
|
@ -12,14 +12,15 @@ import android.hardware.SensorEvent;
|
||||||
import android.hardware.SensorEventListener;
|
import android.hardware.SensorEventListener;
|
||||||
import android.hardware.SensorManager;
|
import android.hardware.SensorManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ScaleGestureDetector;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +36,9 @@ public class PathfinderDemoActivity extends Activity {
|
||||||
*/
|
*/
|
||||||
private PathfinderDemoSurfaceView mContentView;
|
private PathfinderDemoSurfaceView mContentView;
|
||||||
|
|
||||||
|
private GestureDetector mGestureDetector;
|
||||||
|
private ScaleGestureDetector mScaleGestureDetector;
|
||||||
|
|
||||||
ComponentName mVRListenerComponentName;
|
ComponentName mVRListenerComponentName;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,20 +85,47 @@ public class PathfinderDemoActivity extends Activity {
|
||||||
mRenderer = new PathfinderDemoRenderer(this);
|
mRenderer = new PathfinderDemoRenderer(this);
|
||||||
mContentView.setRenderer(mRenderer);
|
mContentView.setRenderer(mRenderer);
|
||||||
|
|
||||||
|
GestureDetector.SimpleOnGestureListener gestureListener =
|
||||||
|
new GestureDetector.SimpleOnGestureListener() {
|
||||||
|
public boolean onScroll(final MotionEvent from,
|
||||||
|
final MotionEvent to,
|
||||||
|
final float deltaX,
|
||||||
|
final float deltaY) {
|
||||||
|
final int x = Math.round(to.getX());
|
||||||
|
final int y = Math.round(to.getY());
|
||||||
|
PathfinderDemoRenderer.pushMouseDraggedEvent(x, y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onDown(final MotionEvent event) {
|
||||||
|
final int x = Math.round(event.getX());
|
||||||
|
final int y = Math.round(event.getY());
|
||||||
|
PathfinderDemoRenderer.pushMouseDownEvent(x, y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mGestureDetector = new GestureDetector(getApplicationContext(), gestureListener);
|
||||||
|
|
||||||
|
ScaleGestureDetector.SimpleOnScaleGestureListener scaleGestureListener =
|
||||||
|
new ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||||
|
public boolean onScale(final ScaleGestureDetector detector) {
|
||||||
|
int focusX = Math.round(detector.getFocusX());
|
||||||
|
int focusY = Math.round(detector.getFocusY());
|
||||||
|
float factor = (detector.getScaleFactor() - 1.0f) * 0.5f;
|
||||||
|
PathfinderDemoRenderer.pushZoomEvent(factor, focusX, focusY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mScaleGestureDetector = new ScaleGestureDetector(getApplicationContext(),
|
||||||
|
scaleGestureListener);
|
||||||
|
|
||||||
mContentView.setOnTouchListener(new View.OnTouchListener() {
|
mContentView.setOnTouchListener(new View.OnTouchListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(final View view, final MotionEvent event) {
|
public boolean onTouch(final View view, final MotionEvent event) {
|
||||||
final int x = Math.round(event.getX());
|
boolean result = mScaleGestureDetector.onTouchEvent(event);
|
||||||
final int y = Math.round(event.getY());
|
if (!mScaleGestureDetector.isInProgress())
|
||||||
switch (event.getActionMasked()) {
|
result = mGestureDetector.onTouchEvent(event) || result;
|
||||||
case MotionEvent.ACTION_DOWN:
|
return result;
|
||||||
PathfinderDemoRenderer.pushMouseDownEvent(x, y);
|
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
PathfinderDemoRenderer.pushMouseDraggedEvent(x, y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class PathfinderDemoRenderer extends Object implements GvrView.Renderer {
|
||||||
|
|
||||||
private static native int prepareFrame();
|
private static native int prepareFrame();
|
||||||
|
|
||||||
private static native void drawScene(int sceneIndex);
|
private static native void drawScene();
|
||||||
|
|
||||||
private static native void finishDrawingFrame();
|
private static native void finishDrawingFrame();
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@ public class PathfinderDemoRenderer extends Object implements GvrView.Renderer {
|
||||||
|
|
||||||
public static native void pushMouseDraggedEvent(int x, int y);
|
public static native void pushMouseDraggedEvent(int x, int y);
|
||||||
|
|
||||||
|
public static native void pushZoomEvent(float scale, int centerX, int centerY);
|
||||||
|
|
||||||
public static native void pushLookEvent(float pitch, float yaw);
|
public static native void pushLookEvent(float pitch, float yaw);
|
||||||
|
|
||||||
public static native void pushOpenSVGEvent(String path);
|
public static native void pushOpenSVGEvent(String path);
|
||||||
|
@ -59,8 +61,7 @@ public class PathfinderDemoRenderer extends Object implements GvrView.Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int sceneIndex = 0; sceneIndex < (inVR ? 2 : 1); sceneIndex++)
|
drawScene();
|
||||||
drawScene(sceneIndex);
|
|
||||||
finishDrawingFrame();
|
finishDrawingFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,10 @@ pub unsafe extern "system" fn
|
||||||
pub unsafe extern "system" fn
|
pub unsafe extern "system" fn
|
||||||
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_drawScene(
|
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_drawScene(
|
||||||
env: JNIEnv,
|
env: JNIEnv,
|
||||||
class: JClass,
|
class: JClass) {
|
||||||
scene_index: i32) {
|
|
||||||
DEMO_APP.with(|demo_app| {
|
DEMO_APP.with(|demo_app| {
|
||||||
if let Some(ref mut demo_app) = *demo_app.borrow_mut() {
|
if let Some(ref mut demo_app) = *demo_app.borrow_mut() {
|
||||||
demo_app.draw_scene(scene_index as u32)
|
demo_app.draw_scene()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -138,6 +137,17 @@ pub unsafe extern "system" fn
|
||||||
EVENT_QUEUE.lock().unwrap().push(Event::MouseDragged(Point2DI32::new(x, y)))
|
EVENT_QUEUE.lock().unwrap().push(Event::MouseDragged(Point2DI32::new(x, y)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "system" fn
|
||||||
|
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushZoomEvent(
|
||||||
|
_: JNIEnv,
|
||||||
|
_: JClass,
|
||||||
|
factor: f32,
|
||||||
|
center_x: i32,
|
||||||
|
center_y: i32) {
|
||||||
|
EVENT_QUEUE.lock().unwrap().push(Event::Zoom(factor, Point2DI32::new(center_x, center_y)))
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "system" fn
|
pub unsafe extern "system" fn
|
||||||
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushLookEvent(
|
Java_graphics_pathfinder_pathfinderdemo_PathfinderDemoRenderer_pushLookEvent(
|
||||||
|
@ -167,10 +177,6 @@ impl Window for WindowImpl {
|
||||||
GLVersion::GLES3
|
GLVersion::GLES3
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_position(&self) -> Point2DI32 {
|
|
||||||
Point2DI32::new(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn viewport(&self, view: View) -> RectI32 {
|
fn viewport(&self, view: View) -> RectI32 {
|
||||||
let mut width = self.size.x();
|
let mut width = self.size.x();
|
||||||
let mut offset_x = 0;
|
let mut offset_x = 0;
|
||||||
|
|
|
@ -331,10 +331,10 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
ui_events.push(UIEvent::MouseDragged(mouse_position));
|
ui_events.push(UIEvent::MouseDragged(mouse_position));
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
Event::Zoom(d_dist) => {
|
Event::Zoom(d_dist, position) => {
|
||||||
if let Camera::TwoD(ref mut transform) = self.camera {
|
if let Camera::TwoD(ref mut transform) = self.camera {
|
||||||
let position = get_mouse_position(&self.window,
|
let backing_scale_factor = self.window_size.backing_scale_factor;
|
||||||
self.window_size.backing_scale_factor);
|
let position = position.to_f32().scale(backing_scale_factor);
|
||||||
*transform = transform.post_translate(-position);
|
*transform = transform.post_translate(-position);
|
||||||
let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
|
let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
|
||||||
*transform = transform.post_scale(Point2DF32::splat(scale_delta));
|
*transform = transform.post_scale(Point2DF32::splat(scale_delta));
|
||||||
|
@ -566,7 +566,7 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.renderer.debug_ui.ui.mouse_position =
|
self.renderer.debug_ui.ui.mouse_position =
|
||||||
get_mouse_position(&self.window, self.window_size.backing_scale_factor);
|
self.last_mouse_position.to_f32().scale(self.window_size.backing_scale_factor);
|
||||||
self.ui.show_text_effects = self.monochrome_scene_color.is_some();
|
self.ui.show_text_effects = self.monochrome_scene_color.is_some();
|
||||||
|
|
||||||
let mut ui_action = UIAction::None;
|
let mut ui_action = UIAction::None;
|
||||||
|
@ -1189,10 +1189,6 @@ fn scale_factor_for_view_box(view_box: RectF32) -> f32 {
|
||||||
1.0 / f32::min(view_box.size().x(), view_box.size().y())
|
1.0 / f32::min(view_box.size().x(), view_box.size().y())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mouse_position<W>(window: &W, scale_factor: f32) -> Point2DF32 where W: Window {
|
|
||||||
window.mouse_position().to_f32().scale(scale_factor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_svg_building_message(built_svg: &BuiltSVG) -> String {
|
fn get_svg_building_message(built_svg: &BuiltSVG) -> String {
|
||||||
if built_svg.result_flags.is_empty() {
|
if built_svg.result_flags.is_empty() {
|
||||||
return String::new();
|
return String::new();
|
||||||
|
|
|
@ -23,7 +23,6 @@ use std::path::PathBuf;
|
||||||
pub trait Window {
|
pub trait Window {
|
||||||
fn gl_version(&self) -> GLVersion;
|
fn gl_version(&self) -> GLVersion;
|
||||||
fn gl_default_framebuffer(&self) -> GLuint { 0 }
|
fn gl_default_framebuffer(&self) -> GLuint { 0 }
|
||||||
fn mouse_position(&self) -> Point2DI32;
|
|
||||||
fn viewport(&self, view: View) -> RectI32;
|
fn viewport(&self, view: View) -> RectI32;
|
||||||
fn make_current(&mut self, view: View);
|
fn make_current(&mut self, view: View);
|
||||||
fn present(&mut self);
|
fn present(&mut self);
|
||||||
|
@ -51,7 +50,7 @@ pub enum Event {
|
||||||
MouseDown(Point2DI32),
|
MouseDown(Point2DI32),
|
||||||
MouseMoved(Point2DI32),
|
MouseMoved(Point2DI32),
|
||||||
MouseDragged(Point2DI32),
|
MouseDragged(Point2DI32),
|
||||||
Zoom(f32),
|
Zoom(f32, Point2DI32),
|
||||||
Look { pitch: f32, yaw: f32 },
|
Look { pitch: f32, yaw: f32 },
|
||||||
SetEyeTransforms(Vec<OcularTransform>),
|
SetEyeTransforms(Vec<OcularTransform>),
|
||||||
OpenSVG(SVGPath),
|
OpenSVG(SVGPath),
|
||||||
|
|
|
@ -80,11 +80,6 @@ impl Window for WindowImpl {
|
||||||
GLVersion::GL3
|
GLVersion::GL3
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_position(&self) -> Point2DI32 {
|
|
||||||
let mouse_state = self.event_pump.mouse_state();
|
|
||||||
Point2DI32::new(mouse_state.x(), mouse_state.y())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn viewport(&self, view: View) -> RectI32 {
|
fn viewport(&self, view: View) -> RectI32 {
|
||||||
let (width, height) = self.window.drawable_size();
|
let (width, height) = self.window.drawable_size();
|
||||||
let mut width = width as i32;
|
let mut width = width as i32;
|
||||||
|
@ -242,7 +237,11 @@ impl WindowImpl {
|
||||||
SDLEvent::KeyUp { keycode: Some(sdl_keycode), .. } => {
|
SDLEvent::KeyUp { keycode: Some(sdl_keycode), .. } => {
|
||||||
self.convert_sdl_keycode(sdl_keycode).map(Event::KeyUp)
|
self.convert_sdl_keycode(sdl_keycode).map(Event::KeyUp)
|
||||||
}
|
}
|
||||||
SDLEvent::MultiGesture { d_dist, .. } => Some(Event::Zoom(d_dist)),
|
SDLEvent::MultiGesture { d_dist, .. } => {
|
||||||
|
let mouse_state = self.event_pump.mouse_state();
|
||||||
|
let center = Point2DI32::new(mouse_state.x(), mouse_state.y());
|
||||||
|
Some(Event::Zoom(d_dist, center))
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue