Add basic pinch zoom support on Android

This commit is contained in:
Patrick Walton 2019-04-26 22:29:38 -07:00
parent 6c31e1bc01
commit b85dc2f001
7 changed files with 91 additions and 38 deletions

21
Cargo.lock generated
View File

@ -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"

View File

@ -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;
} }
}); });

View File

@ -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();
} }

View File

@ -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;

View File

@ -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();

View File

@ -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),

View File

@ -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,
} }
} }