Compare commits

..

14 Commits

Author SHA1 Message Date
Robert Bragg bc177292d2 Release 0.3 2022-09-16 14:07:06 +01:00
Robert Bragg 8d30454c8d native-activity: InputEvent forward compatibility
When building with native-activity then we no longer directly use
the `ndk::InputEvent` type and instead have our own extensible,
`#[non_exhaustive]` enum that ensures we will be able to add an
event for Ime state changes without necessarily needing a semver
bump.

Addresses: #18
2022-09-15 17:12:08 +01:00
Robert Bragg feff63ae78 Add show/hide_soft_input methods
This adds `AndroidApp::show/hide_soft_input` APIs for showing or
hiding the user's on-screen keyboard. (supported for NativeActivity
and GameActivity)

Addresses: #18
2022-09-15 17:12:08 +01:00
Robert Bragg 48993acf58 Support changing window manager params
This enables support for changing the various WindowManager
parameters documented here:
https://developer.android.com/reference/android/view/WindowManager.LayoutParams

either via NativeActivity_setWindowFlags or GameActivity_setWindowFlags

Fixes: #25
2022-09-15 16:48:37 +01:00
Robert Bragg 7d73e57364 Extend compiler_error for missing feature to warn of duplicate implementations 2022-09-15 16:48:37 +01:00
Robert Bragg 781e1fd658 ci: string in expressions should use single quotes 2022-09-01 14:48:03 +01:00
Robert Bragg 16391c4956 ci: add missing quotes 2022-09-01 14:43:08 +01:00
Robert Bragg da29177b41 Only build examples with stable toolchain
Although we want to ensure android-activity itself builds with the
same MSRV as Winit there's no need to also check that the examples
build with an older toolchain, and in fact in the case of Egui based
examples they don't support being built with 1.60.0.

In addition to adding an `if: rust_version == "stable"` condition
for building agdk-egui, this also adds CI stages to build agdk-mainloop,
na-mainloop and agdk-eframe to cover at least one example based on
`NativeActivity` and cover the key examples that others are most
likely to be interested in.
2022-09-01 14:14:08 +01:00
Robert Bragg b29162d149 Revert "Support building with 1.57.0 compiler"
This reverts the changes from 66e3293f4d
to support the 1.57.0 compiler (leaving the rustdoc fixes).

Making the changes to support 1.57 felt disappointing to require for the
sake of Winit being able to better support Linux distro packaging. Even
with the changes we still wouldn't really support
1.57 without also upstreaming changes to `cargo ndk`.

The new plan is to bank on Winit bumping its own MSRV to at least
1.58 which seems more than reasonable considering that even 1.59
is already >6months old.

Ref: https://github.com/rust-windowing/winit/pull/2453

This updates ci.yml to now build with 1.60, assuming that the above
PR will be accepted.
2022-09-01 12:37:07 +01:00
Robert Bragg 3a2fa5d1fa CI: build docs and ensure support for 1.57.0 compiler 2022-08-31 23:05:24 +01:00
Robert Bragg 66e3293f4d Support building with 1.57.0 compiler
This is to support the same compiler versions as Winit
2022-08-31 23:04:09 +01:00
Robert Bragg d5ff06ffb2 Add OpenXR + Wgpu example
This tests being able to write an OpenXR application based on
Wgpu (using the Vulkan HAL backend) for the Oculus Quest.
2022-08-31 20:44:14 +01:00
Robert Bragg b7f01a43d9 Build fixes for Winit based examples
The latest branches for Winit (which update the Android backend to
use android-activity) now depend on the android-activity 0.2
release which broke the patching assumption for the Winit examples.
(they were patching based on the git url not crates.io)

It was also noticed that the latest android-activity-0.27 branch
isn't compatible with Egui currently because the (badly named) branch
is based on Winit master and there was recently a breaking API change
adding new window events which breaks Egui.

A note about the badly name branches has been added to the Cargo.toml
files for the Winit examples (they can't currently be fixes since
the -0.27 branch is part of a pull request).

For reference here:
- "android-activity" is based on Winit 0.27 (required for Egui compatibility)
- "android-activity-0.27" is based on Winit master

This patch adds Cargo.lock files for the Winit examples.

Fixes: #22
2022-08-31 20:43:45 +01:00
Robert Bragg f673662316 Add a minimal OpenXR Info example 2022-08-26 17:27:03 +01:00
66 changed files with 10497 additions and 162 deletions
+136 -91
View File
@@ -1,91 +1,136 @@
name: ci
on:
push:
branches: [main]
pull_request:
env:
CARGO_INCREMENTAL: 0
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Install Rust targets
run: >
rustup target add
aarch64-linux-android
armv7-linux-androideabi
x86_64-linux-android
i686-linux-android
- name: Install cargo-ndk
run: cargo install cargo-ndk
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Build game-activity
working-directory: android-activity
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
build --features game-activity
- name: Build native-activity
working-directory: android-activity
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
build --features native-activity
- name: Build agdk-egui example
working-directory: examples/agdk-egui
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
-o app/src/main/jniLibs/ -- build
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt
- name: Format
run: cargo fmt --all -- --check
working-directory: android-activity
- name: Format agdk-egui example
run: cargo fmt --all -- --check
working-directory: examples/agdk-egui
name: ci
on:
push:
branches: [main]
pull_request:
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: "-C debuginfo=0 --deny warnings"
RUSTDOCFLAGS: -Dwarnings
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# We need to support the same MSRV as Winit which we are currently
# assuming will be bumped to 1.60.0 soon:
# https://github.com/rust-windowing/winit/pull/2453
rust_version: [1.60.0, stable]
steps:
- uses: actions/checkout@v2
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust_version }}
- name: Install Rust targets
run: >
rustup target add
aarch64-linux-android
armv7-linux-androideabi
x86_64-linux-android
i686-linux-android
- name: Install cargo-ndk
run: cargo install cargo-ndk
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: Build game-activity
working-directory: android-activity
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
build --features game-activity
- name: Build native-activity
working-directory: android-activity
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
build --features native-activity
- name: Build agdk-mainloop example
if: matrix.rust_version == 'stable'
working-directory: examples/agdk-mainloop
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
-o app/src/main/jniLibs/ -- build
- name: Build na-mainloop example
if: matrix.rust_version == 'stable'
working-directory: examples/na-mainloop
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
-o app/src/main/jniLibs/ -- build
- name: Build agdk-egui example
if: matrix.rust_version == 'stable'
working-directory: examples/agdk-egui
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
-o app/src/main/jniLibs/ -- build
- name: Build agdk-eframe example
if: matrix.rust_version == 'stable'
working-directory: examples/agdk-eframe
run: >
cargo ndk
-t arm64-v8a
-t armeabi-v7a
-t x86_64
-t x86
-o app/src/main/jniLibs/ -- build
- name: Documentation
run: >
cargo ndk -t arm64-v8a doc --no-deps
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt
- name: Format
run: cargo fmt --all -- --check
working-directory: android-activity
- name: Format agdk-egui example
run: cargo fmt --all -- --check
working-directory: examples/agdk-egui
+3 -1
View File
@@ -12,5 +12,7 @@ exclude = [
"examples/agdk-cpal",
"examples/na-mainloop",
"examples/na-winit-wgpu",
"examples/na-subclass-jni"
"examples/na-subclass-jni",
"examples/na-openxr-info",
"examples/na-openxr-wgpu"
]
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "android-activity"
version = "0.2.0"
version = "0.3.0"
edition = "2021"
keywords = ["android", "ndk"]
readme = "../README.md"
+38 -1
View File
@@ -23,7 +23,7 @@ use ndk::asset::AssetManager;
use ndk::configuration::Configuration;
use ndk::native_window::NativeWindow;
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect};
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect, WindowManagerFlags};
mod ffi;
@@ -309,6 +309,43 @@ impl AndroidAppInner {
}
}
pub fn set_window_flags(
&self,
add_flags: WindowManagerFlags,
remove_flags: WindowManagerFlags,
) {
unsafe {
let activity = (*self.native_app.as_ptr()).activity;
ffi::GameActivity_setWindowFlags(activity, add_flags.bits(), remove_flags.bits())
}
}
// TODO: move into a trait
pub fn show_soft_input(&self, show_implicit: bool) {
unsafe {
let activity = (*self.native_app.as_ptr()).activity;
let flags = if show_implicit {
ffi::ShowImeFlags_SHOW_IMPLICIT
} else {
0
};
ffi::GameActivity_showSoftInput(activity, flags);
}
}
// TODO: move into a trait
pub fn hide_soft_input(&self, hide_implicit_only: bool) {
unsafe {
let activity = (*self.native_app.as_ptr()).activity;
let flags = if hide_implicit_only {
ffi::HideImeFlags_HIDE_IMPLICIT_ONLY
} else {
0
};
ffi::GameActivity_hideSoftInput(activity, flags);
}
}
pub fn enable_motion_axis(&mut self, axis: Axis) {
unsafe { ffi::GameActivityPointerAxes_enableAxis(axis as i32) }
}
+248 -9
View File
@@ -6,6 +6,8 @@ use std::time::Duration;
use ndk::asset::AssetManager;
use ndk::native_window::NativeWindow;
use bitflags::bitflags;
#[cfg(not(target_os = "android"))]
compile_error!("android-activity only supports compiling for Android");
@@ -17,7 +19,23 @@ compile_error!(
not(any(feature = "game-activity", feature = "native-activity")),
not(doc)
))]
compile_error!("Either \"game-activity\" or \"native-activity\" must be enabled as features");
compile_error!(
r#"Either \"game-activity\" or \"native-activity\" must be enabled as features
If you have set one of these features then this error indicates that Cargo is trying to
link together multiple implementations of android-activity (with incompatible versions)
which is not supported.
Since android-activity is responsible for the `android_main` entrypoint of your application
then there can only be a single implementation of android-activity linked with your application.
You can use `cargo tree` (e.g. via `cargo ndk -t arm64-v8a tree`) to identify why multiple
versions have been resolved.
You may need to add a `[patch]` into your Cargo.toml to ensure a specific version of
android-activity is used across all of your application's crates.
"#
);
#[cfg(any(feature = "native-activity", doc))]
mod native_activity;
@@ -68,14 +86,14 @@ pub enum MainEvent<'a> {
InputAvailable,
/// Command from main thread: a new [`NativeWindow`] is ready for use. Upon
/// receiving this command, [`native_window()`] will return the new window
/// receiving this command, [`AndroidApp::native_window()`] will return the new window
#[non_exhaustive]
InitWindow {},
/// Command from main thread: the existing [`NativeWindow`] needs to be
/// terminated. Upon receiving this command, [`native_window()`] still
/// terminated. Upon receiving this command, [`AndroidApp::native_window()`] still
/// returns the existing window; after returning from the [`AndroidApp::poll_events()`]
/// callback then [`native_window()`] will return `None`.
/// callback then [`AndroidApp::native_window()`] will return `None`.
#[non_exhaustive]
TerminateWindow {},
@@ -106,7 +124,7 @@ pub enum MainEvent<'a> {
LostFocus,
/// Command from main thread: the current device configuration has changed.
/// You can get a copy of the latest [Configuration] by calling
/// You can get a copy of the latest [`ndk::configuration::Configuration`] by calling
/// [`AndroidApp::config()`]
#[non_exhaustive]
ConfigChanged {},
@@ -154,9 +172,174 @@ pub enum PollEvent<'a> {
}
use activity_impl::AndroidAppInner;
pub use activity_impl::AndroidAppWaker;
bitflags! {
/// Flags for [`AndroidApp::set_window_flags`]
/// as per the [android.view.WindowManager.LayoutParams Java API](https://developer.android.com/reference/android/view/WindowManager.LayoutParams)
pub struct WindowManagerFlags: u32 {
/// As long as this window is visible to the user, allow the lock
/// screen to activate while the screen is on. This can be used
/// independently, or in combination with
/// [`Self::KEEP_SCREEN_ON`] and/or [`Self::SHOW_WHEN_LOCKED`]
const ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
/// Everything behind this window will be dimmed. */
const DIM_BEHIND = 0x00000002;
/// Blur everything behind this window.
#[deprecated = "Blurring is no longer supported"]
const BLUR_BEHIND = 0x00000004;
/// This window won't ever get key input focus, so the
/// user can not send key or other button events to it. Those will
/// instead go to whatever focusable window is behind it. This flag
/// will also enable [`Self::NOT_TOUCH_MODAL`] whether or not
/// that is explicitly set.
///
/// Setting this flag also implies that the window will not need to
/// interact with
/// a soft input method, so it will be Z-ordered and positioned
/// independently of any active input method (typically this means it
/// gets Z-ordered on top of the input method, so it can use the full
/// screen for its content and cover the input method if needed. You
/// can use [`Self::ALT_FOCUSABLE_IM`] to modify this
/// behavior.
const NOT_FOCUSABLE = 0x00000008;
/// This window can never receive touch events.
const NOT_TOUCHABLE = 0x00000010;
/// Even when this window is focusable (if
/// [`Self::NOT_FOCUSABLE`] is not set), allow any pointer
/// events outside of the window to be sent to the windows behind it.
/// Otherwise it will consume all pointer events itself, regardless of
/// whether they are inside of the window.
const NOT_TOUCH_MODAL = 0x00000020;
/// When set, if the device is asleep when the touch
/// screen is pressed, you will receive this first touch event. Usually
/// the first touch event is consumed by the system since the user can
/// not see what they are pressing on.
#[deprecated]
const TOUCHABLE_WHEN_WAKING = 0x00000040;
/// As long as this window is visible to the user, keep
/// the device's screen turned on and bright.
const KEEP_SCREEN_ON = 0x00000080;
/// Place the window within the entire screen, ignoring
/// decorations around the border (such as the status bar). The
/// window must correctly position its contents to take the screen
/// decoration into account.
const LAYOUT_IN_SCREEN = 0x00000100;
/// Allows the window to extend outside of the screen.
const LAYOUT_NO_LIMITS = 0x00000200;
/// Hide all screen decorations (such as the status
/// bar) while this window is displayed. This allows the window to
/// use the entire display space for itself -- the status bar will
/// be hidden when an app window with this flag set is on the top
/// layer. A fullscreen window will ignore a value of
/// [`Self::SOFT_INPUT_ADJUST_RESIZE`] the window will stay
/// fullscreen and will not resize.
const FULLSCREEN = 0x00000400;
/// Override [`Self::FULLSCREEN`] and force the
/// screen decorations (such as the status bar) to be shown.
const FORCE_NOT_FULLSCREEN = 0x00000800;
/// Turn on dithering when compositing this window to
/// the screen.
#[deprecated="This flag is no longer used"]
const DITHER = 0x00001000;
/// Treat the content of the window as secure, preventing
/// it from appearing in screenshots or from being viewed on non-secure
/// displays.
const SECURE = 0x00002000;
/// A special mode where the layout parameters are used
/// to perform scaling of the surface when it is composited to the
/// screen.
const SCALED = 0x00004000;
/// Intended for windows that will often be used when the user is
/// holding the screen against their face, it will aggressively
/// filter the event stream to prevent unintended presses in this
/// situation that may not be desired for a particular window, when
/// such an event stream is detected, the application will receive
/// a `AMOTION_EVENT_ACTION_CANCEL` to indicate this so
/// applications can handle this accordingly by taking no action on
/// the event until the finger is released.
const IGNORE_CHEEK_PRESSES = 0x00008000;
/// A special option only for use in combination with
/// [`Self::LAYOUT_IN_SCREEN`]. When requesting layout in
/// the screen your window may appear on top of or behind screen decorations
/// such as the status bar. By also including this flag, the window
/// manager will report the inset rectangle needed to ensure your
/// content is not covered by screen decorations.
const LAYOUT_INSET_DECOR = 0x00010000;
/// Invert the state of [`Self::NOT_FOCUSABLE`] with
/// respect to how this window interacts with the current method.
/// That is, if [`Self::NOT_FOCUSABLE`] is set and this flag is set,
/// then the window will behave as if it needs to interact with the
/// input method and thus be placed behind/away from it; if
/// [`Self::NOT_FOCUSABLE`] is not set and this flag is set,
/// then the window will behave as if it doesn't need to interact
/// with the input method and can be placed to use more space and
/// cover the input method.
const ALT_FOCUSABLE_IM = 0x00020000;
/// If you have set [`Self::NOT_TOUCH_MODAL`], you
/// can set this flag to receive a single special MotionEvent with
/// the action
/// `AMOTION_EVENT_ACTION_OUTSIDE` for
/// touches that occur outside of your window. Note that you will not
/// receive the full down/move/up gesture, only the location of the
/// first down as an `AMOTION_EVENT_ACTION_OUTSIDE`.
const WATCH_OUTSIDE_TOUCH = 0x00040000;
/// Special flag to let windows be shown when the screen
/// is locked. This will let application windows take precedence over
/// key guard or any other lock screens. Can be used with
/// [`Self::KEEP_SCREEN_ON`] to turn screen on and display
/// windows directly before showing the key guard window. Can be used with
/// [`Self::DISMISS_KEYGUARD`] to automatically fully
/// dismiss non-secure key guards. This flag only applies to the top-most
/// full-screen window.
const SHOW_WHEN_LOCKED = 0x00080000;
/// Ask that the system wallpaper be shown behind
/// your window. The window surface must be translucent to be able
/// to actually see the wallpaper behind it; this flag just ensures
/// that the wallpaper surface will be there if this window actually
/// has translucent regions.
const SHOW_WALLPAPER = 0x00100000;
/// When set as a window is being added or made
/// visible, once the window has been shown then the system will
/// poke the power manager's user activity (as if the user had woken
/// up the device) to turn the screen on.
const TURN_SCREEN_ON = 0x00200000;
/// When set the window will cause the key guard to
/// be dismissed, only if it is not a secure lock key guard. Because such
/// a key guard is not needed for security, it will never re-appear if
/// the user navigates to another window (in contrast to
/// [`Self::SHOW_WHEN_LOCKED`], which will only temporarily
/// hide both secure and non-secure key guards but ensure they reappear
/// when the user moves to another UI that doesn't hide them).
/// If the key guard is currently active and is secure (requires an
/// unlock pattern) then the user will still need to confirm it before
/// seeing this window, unless [`Self::SHOW_WHEN_LOCKED`] has
/// also been set.
const DISMISS_KEYGUARD = 0x00400000;
}
}
#[derive(Debug, Clone)]
pub struct AndroidApp {
pub(crate) inner: Arc<RwLock<AndroidAppInner>>,
@@ -185,7 +368,7 @@ impl AndroidApp {
/// Queries the current [`NativeWindow`] for the application.
///
/// This will only return `Some(window)` between
/// [`AndroidAppMainEvent::InitWindow`] and [`AndroidAppMainEvent::TerminateWindow`]
/// [`MainEvent::InitWindow`] and [`MainEvent::TerminateWindow`]
/// events.
pub fn native_window<'a>(&self) -> Option<NativeWindow> {
self.inner.read().unwrap().native_window()
@@ -202,6 +385,8 @@ impl AndroidApp {
/// set to `None` once the callback returns, and this is also synchronized with the Java
/// main thread. The [`MainEvent::SaveState`] event is also synchronized with the
/// Java main thread.
///
/// [`ALooper_pollAll`]: ndk::looper::ThreadLooper::poll_all
pub fn poll_events<F>(&self, timeout: Option<Duration>, callback: F)
where
F: FnMut(PollEvent),
@@ -210,12 +395,12 @@ impl AndroidApp {
}
/// Creates a means to wake up the main loop while it is blocked waiting for
/// events within [`poll_events()`].
/// events within [`AndroidApp::poll_events()`].
pub fn create_waker(&self) -> activity_impl::AndroidAppWaker {
self.inner.read().unwrap().create_waker()
}
/// Returns a (cheaply clonable) reference to this application's [`Configuration`]
/// Returns a (cheaply clonable) reference to this application's [`ndk::configuration::Configuration`]
pub fn config(&self) -> ConfigurationRef {
self.inner.read().unwrap().config()
}
@@ -233,14 +418,68 @@ impl AndroidApp {
self.inner.read().unwrap().asset_manager()
}
/// Change the window flags of the given activity.
///
/// Note that some flags must be set before the window decoration is created,
/// see
/// `<https://developer.android.com/reference/android/view/Window#setFlags(int,%20int)>`.
pub fn set_window_flags(
&self,
add_flags: WindowManagerFlags,
remove_flags: WindowManagerFlags,
) {
self.inner
.write()
.unwrap()
.set_window_flags(add_flags, remove_flags);
}
/// Enable additional input axis
///
/// To reduce overhead, by default only [`input::Axis::X`] and [`input::Axis::Y`] are enabled
/// and other axis should be enabled explicitly.
pub fn enable_motion_axis(&self, axis: input::Axis) {
self.inner.write().unwrap().enable_motion_axis(axis);
}
/// Disable input axis
///
/// To reduce overhead, by default only [`input::Axis::X`] and [`input::Axis::Y`] are enabled
/// and other axis should be enabled explicitly.
pub fn disable_motion_axis(&self, axis: input::Axis) {
self.inner.write().unwrap().disable_motion_axis(axis);
}
/// Explicitly request that the current input method's soft input area be
/// shown to the user, if needed.
///
/// Call this if the user interacts with your view in such a way that they
/// have expressed they would like to start performing input into it.
pub fn show_soft_input(&self, show_implicit: bool) {
self.inner.read().unwrap().show_soft_input(show_implicit);
}
/// Request to hide the soft input window from the context of the window
/// that is currently accepting input.
///
/// This should be called as a result of the user doing some action that
/// fairly explicitly requests to have the input window hidden.
pub fn hide_soft_input(&self, hide_implicit_only: bool) {
self.inner
.read()
.unwrap()
.hide_soft_input(hide_implicit_only);
}
/// Query and process all out-standing input event
///
/// Applications are generally either expected to call this in-sync with their rendering or
/// in response to a [`MainEvent::InputAvailable`] event being delivered. _Note though that your
/// application is will only be delivered a single [`MainEvent::InputAvailable`] event between calls
/// to this API._
///
/// To reduce overhead, by default only [`input::Axis::X`] and [`input::Axis::Y`] are enabled
/// and other axis should be enabled explicitly via [`Self::enable_motion_axis`].
pub fn input_events<'b, F>(&self, callback: F)
where
F: FnMut(&input::InputEvent),
+66 -5
View File
@@ -21,15 +21,25 @@ use ndk::configuration::Configuration;
use ndk::input_queue::InputQueue;
use ndk::native_window::NativeWindow;
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect};
use crate::{util, AndroidApp, ConfigurationRef, MainEvent, PollEvent, Rect, WindowManagerFlags};
mod ffi;
pub mod input {
pub use ndk::event::{
Axis, ButtonState, EdgeFlags, InputEvent, KeyAction, KeyEvent, KeyEventFlags, Keycode,
MetaState, MotionAction, MotionEvent, MotionEventFlags, Pointer, Source,
Axis, ButtonState, EdgeFlags, KeyAction, KeyEvent, KeyEventFlags, Keycode, MetaState,
MotionAction, MotionEvent, MotionEventFlags, Pointer, Source,
};
// We use our own wrapper type for input events to have better consistency
// with GameActivity and ensure the enum can be extended without needing a
// semver bump
#[derive(Debug)]
#[non_exhaustive]
pub enum InputEvent {
MotionEvent(self::MotionEvent),
KeyEvent(self::KeyEvent),
}
}
// The only time it's safe to update the android_app->savedState pointer is
@@ -353,6 +363,48 @@ impl AndroidAppInner {
}
}
pub fn set_window_flags(
&self,
add_flags: WindowManagerFlags,
remove_flags: WindowManagerFlags,
) {
let na = self.native_activity();
let na_mut = na as *mut ndk_sys::ANativeActivity;
unsafe {
ffi::ANativeActivity_setWindowFlags(
na_mut.cast(),
add_flags.bits(),
remove_flags.bits(),
);
}
}
// TODO: move into a trait
pub fn show_soft_input(&self, show_implicit: bool) {
let na = self.native_activity();
unsafe {
let flags = if show_implicit {
ffi::ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT
} else {
0
};
ffi::ANativeActivity_showSoftInput(na as *mut _, flags);
}
}
// TODO: move into a trait
pub fn hide_soft_input(&self, hide_implicit_only: bool) {
let na = self.native_activity();
unsafe {
let flags = if hide_implicit_only {
ffi::ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY
} else {
0
};
ffi::ANativeActivity_hideSoftInput(na as *mut _, flags);
}
}
pub fn enable_motion_axis(&self, _axis: input::Axis) {
// NOP - The InputQueue API doesn't let us optimize which axis values are read
}
@@ -387,16 +439,25 @@ impl AndroidAppInner {
// ref: https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/jni/android_view_InputQueue.cpp
//
while let Ok(Some(event)) = queue.get_event() {
if let Some(event) = queue.pre_dispatch(event) {
if let Some(ndk_event) = queue.pre_dispatch(event) {
let event = match ndk_event {
ndk::event::InputEvent::MotionEvent(e) => input::InputEvent::MotionEvent(e),
ndk::event::InputEvent::KeyEvent(e) => input::InputEvent::KeyEvent(e),
};
callback(&event);
let ndk_event = match event {
input::InputEvent::MotionEvent(e) => ndk::event::InputEvent::MotionEvent(e),
input::InputEvent::KeyEvent(e) => ndk::event::InputEvent::KeyEvent(e),
};
// Always report events as 'handled'. This means we won't get
// so called 'fallback' events generated (such as converting trackball
// events into emulated keypad events), but we could conceivably
// implement similar emulation somewhere else in the stack if
// necessary, and this will be more consistent with the GameActivity
// input handling that doesn't do any kind of emulation.
queue.finish_event(event, true);
queue.finish_event(ndk_event, true);
}
}
}
-1
View File
@@ -19,4 +19,3 @@ local.properties
# Added by cargo
/target
Cargo.lock
+2398
View File
File diff suppressed because it is too large Load Diff
+28 -13
View File
@@ -15,9 +15,36 @@ egui = "0.19"
eframe = { version = "0.19", features = [ "wgpu" ] }
egui_demo_lib = "0.19"
[target.'cfg(not(target_os = "android"))'.dependencies]
env_logger = "0.9"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { version = "0.3", features = [ "game-activity" ] }
[patch.crates-io]
winit = { git = "https://github.com/rib/winit", branch = "android-activity-0.27" }
# This branch of Winit has an updated Android backend based on android-activity
# Note: The winit branches are current misnamed:
# - "android-activity" is based on Winit 0.27 (required for Egui compatibility)
# - "android-activity-0.27" is based on Winit master
# The -0.27 branch is currently associated with a pull request so we'll just
# stick with these names for now
winit = { git = "https://github.com/rib/winit", branch = "android-activity" }
#winit = { path = "../../../winit" }
# Note:
# Since android-activity is responsible for invoking the `android_main`
# entrypoint for a native Rust application there can only be a single
# implementation of the crate linked with the application.
#
# Since Winit also depends on android-activity (version = "0.2") but we'd like
# to build against the local version of android-activity in this repo then we
# use a [patch] to ensure we only end up with a single implementation.
android-activity = { path = "../../android-activity" }
# Egui 0.19 is missing some fixes for Android so we need to build against
# git master for now
egui = { git = "https://github.com/emilk/egui" }
eframe = { git = "https://github.com/emilk/egui" }
egui_demo_lib = { git = "https://github.com/emilk/egui" }
@@ -25,18 +52,6 @@ egui_demo_lib = { git = "https://github.com/emilk/egui" }
#eframe = { path = "../../../egui/crates/eframe" }
#egui_demo_lib = { path = "../../../egui/crates/egui_demo_lib" }
[target.'cfg(not(target_os = "android"))'.dependencies]
env_logger = "0.9"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { git = "https://github.com/rib/android-activity", features = [ "game-activity" ] }
# Since Winit also depends on android-activity (via a github url) we need to
# make sure we only resolve a single implementation.
[patch.'https://github.com/rib/android-activity']
android-activity = { path = "../../android-activity" }
[features]
default = []
desktop = []
-1
View File
@@ -19,4 +19,3 @@ local.properties
# Added by cargo
/target
Cargo.lock
+1888
View File
File diff suppressed because it is too large Load Diff
+21 -21
View File
@@ -16,33 +16,33 @@ egui-wgpu = { version = "0.19", features = [ "winit" ] }
egui-winit = { version = "0.19", default-features = false }
egui_demo_lib = "0.19"
[patch.crates-io]
winit = { git = "https://github.com/rib/winit", branch = "android-activity-0.27" }
#winit = { path="../../../winit" }
#egui = { git = "https://github.com/emilk/egui" }
#egui-wgpu = { git = "https://github.com/emilk/egui" }
#egui-winit = { git = "https://github.com/emilk/egui" }
#egui_extras = { git = "https://github.com/emilk/egui" }
#egui_demo_lib = { git = "https://github.com/emilk/egui" }
#egui = { path = "../../../egui/egui" }
#egui-wgpu = { path = "../../../egui/egui-wgpu" }
#egui-winit = { path = "../../../egui/egui-winit" }
#egui_extras = { path = "../../../egui/egui_extras" }
#egui_demo_lib = { path = "../../../egui/egui_demo_lib" }
[target.'cfg(not(target_os = "android"))'.dependencies]
env_logger = "0.9"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { path="../../android-activity", features = [ "game-activity" ] }
android-activity = { version = "0.3", features = [ "game-activity" ] }
# Since Winit also depends on android-activity (via a github url) we need to
# make sure we only resolve a single implementation.
[patch.'https://github.com/rib/android-activity']
android-activity = { path="../../android-activity", features = [ "game-activity" ] }
[patch.crates-io]
# This branch of Winit has an updated Android backend based on android-activity
# Note: The winit branches are current misnamed:
# - "android-activity" is based on Winit 0.27 (required for Egui compatibility)
# - "android-activity-0.27" is based on Winit master
# The -0.27 branch is currently associated with a pull request so we'll just
# stick with these names for now
winit = { git = "https://github.com/rib/winit", branch = "android-activity" }
#winit = { path = "../../../winit" }
# Note:
# Since android-activity is responsible for invoking the `android_main`
# entrypoint for a native Rust application there can only be a single
# implementation of the crate linked with the application.
#
# Since Winit also depends on android-activity (version = "0.2") but we'd like
# to build against the local version of android-activity in this repo then we
# use a [patch] to ensure we only end up with a single implementation.
android-activity = { path = "../../android-activity" }
[features]
default = []
-1
View File
@@ -13,7 +13,6 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
-1
View File
@@ -19,4 +19,3 @@ local.properties
# Added by cargo
/target
Cargo.lock
+1558
View File
File diff suppressed because it is too large Load Diff
+22 -7
View File
@@ -7,8 +7,7 @@ edition = "2021"
[dependencies]
log = "0.4"
winit = { git = "https://github.com/rib/winit", branch = "android-activity-0.27"}
#winit = { path="../../../winit" }
winit = "0.27"
wgpu = "0.13.0"
pollster = "0.2"
@@ -17,12 +16,28 @@ env_logger = "0.9"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { path="../../android-activity", features = [ "game-activity" ] }
android-activity = { version = "0.3", features = [ "game-activity" ] }
# Since Winit also depends on android-activity (via a github url) we need to
# make sure we only resolve a single implementation.
[patch.'https://github.com/rib/android-activity']
android-activity = { path="../../android-activity", features = [ "game-activity" ] }
[patch.crates-io]
# This branch of Winit has an updated Android backend based on android-activity
# Note: The winit branches are current misnamed:
# - "android-activity" is based on Winit 0.27 (required for Egui compatibility)
# - "android-activity-0.27" is based on Winit master
# The -0.27 branch is currently associated with a pull request so we'll just
# stick with these names for now
winit = { git = "https://github.com/rib/winit", branch = "android-activity-0.27" }
#winit = { path = "../../../winit" }
# Note:
# Since android-activity is responsible for invoking the `android_main`
# entrypoint for a native Rust application there can only be a single
# implementation of the crate linked with the application.
#
# Since Winit also depends on android-activity (version = "0.2") but we'd like
# to build against the local version of android-activity in this repo then we
# use a [patch] to ensure we only end up with a single implementation.
android-activity = { path="../../android-activity" }
[features]
default = []
+21
View File
@@ -0,0 +1,21 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
*.so
# Added by cargo
/target
Cargo.lock
+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+37
View File
@@ -0,0 +1,37 @@
[package]
name = "na-openxr-info"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
openxr = { version = "0.16" }
[target.'cfg(not(target_os = "android"))'.dependencies]
env_logger = "0.9"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { path="../../android-activity", features = ["native-activity"] }
[patch.crates-io]
# openxr 0.16 uses ndk-glue, but master uses ndk-context which is compatible with android-activity
openxr = { git = "https://github.com/Ralith/openxrs" }
[features]
default = [ "linked" ]
android = [ "openxr/linked" ]
desktop = [ "linked", "openxr/static"]
linked = []
[lib]
name="main"
crate_type=["cdylib"]
[[bin]]
path="src/lib.rs"
name="test-winit-wgpu"
required-features = [ "desktop" ]
+43
View File
@@ -0,0 +1,43 @@
This is a minimal OpenXR application that builds for desktop or
Android and simply prints out extension information for the OpenXR
library.
This is based on the [hello](https://github.com/Ralith/openxrs/blob/master/openxr/examples/hello.rs)
example from the [openxrs](https://github.com/Ralith/openxrs) repo.
# Oculus Quest
To build for the Oculus Quest then you first need to download
the Oculus OpenXR Mobile SDK from:
https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/
and after unpacking the zip file you need to copy a suitable `libopenxr_loader.so`
library to `app/src/main/jniLibs/<abi>`
For example if building for arm64-v8a:
`cp path/to/ovr_openxr_mobile_sdk_42.0/OpenXR/Libs/Android/arm64-v8a/Debug/libopenxr_loader.so app/src/main/jniLibs/arm64-v8a`
```
export ANDROID_NDK_HOME="path/to/ndk"
export ANDROID_HOME="path/to/sdk"
rustup target add aarch64-linux-android
cargo install cargo-ndk
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
./gradlew build
./gradlew installDebug
```
# Oculus Quest: Vulkan Validation Layer
To enable the Vulkan validation layer on the Oculus Quest run:
```
adb shell setprop debug.oculus.loadandinjectpackagedvvl.co.realfit.naopenxrwgpu 1
```
# Desktop
To build for PC you need to build with the "desktop" feature
`cargo run --features=desktop`
+1
View File
@@ -0,0 +1 @@
/build
+42
View File
@@ -0,0 +1,42 @@
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
applicationId "co.realfit.naopenxrinfo"
minSdk 24
targetSdk 25
compileSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
//packagingOptions {
// doNotStrip '**/*.so'
//}
//debuggable true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
}
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.realfit.naopenxrinfo"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="false"
android:label="OpenXR Info">
<meta-data android:name="com.oculus.intent.category.VR" android:value="vr_only"/>
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
<activity
android:name=".MainActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
android:launchMode="singleTask"
android:resizeableActivity="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.oculus.intent.category.VR" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="main" />
</activity>
</application>
<uses-sdk android:minSdkVersion="24"/>
<uses-feature android:glEsVersion="0x00030001" />
<uses-feature android:name="android.hardware.vr.headtracking" android:required="true" android:version="1" />
<uses-feature android:name="oculus.software.handtracking" android:required="false" />
<uses-permission android:name="com.oculus.permission.HAND_TRACKING" />
</manifest>
@@ -0,0 +1,8 @@
package co.realfit.naopenxrinfo;
public class MainActivity extends android.app.NativeActivity {
static {
System.loadLibrary("openxr_loader");
System.loadLibrary("main");
}
}
+10
View File
@@ -0,0 +1,10 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
+17
View File
@@ -0,0 +1,17 @@
fn main() {
if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
let android_abi = match std::env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
"aarch64" => "arm64-v8a",
"arm" => "armeabi-v7a",
"x86" => "x86",
"x86_64" => "x86_64",
arch => {
panic!("Unsupported architecture for Android {arch}");
}
};
let libdir = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
.join(format!("app/src/main/jniLibs/{android_abi}/lib"));
println!("cargo:rustc-link-search={}", libdir.to_string_lossy());
}
}
+21
View File
@@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
Binary file not shown.
@@ -0,0 +1,6 @@
#Mon May 02 15:39:12 BST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
+89
View File
@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+16
View File
@@ -0,0 +1,16 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
//rootProject.name = "Rust Template"
include ':app'
+79
View File
@@ -0,0 +1,79 @@
///! Based on https://github.com/Ralith/openxrs/blob/master/openxr/examples/hello.rs
use openxr as xr;
#[cfg(target_os = "android")]
use android_activity::AndroidApp;
fn _main() {
println!("OpenXR Info");
#[cfg(feature = "linked")]
let entry = xr::Entry::linked();
#[cfg(not(feature = "linked"))]
let entry = unsafe {
xr::Entry::load()
.expect("couldn't find the OpenXR loader; try enabling the \"static\" feature")
};
#[cfg(target_os = "android")]
entry.initialize_android_loader().unwrap();
let extensions = entry.enumerate_extensions().unwrap();
println!("supported extensions: {:#?}", extensions);
let layers = entry.enumerate_layers().unwrap();
println!("supported layers: {:?}", layers);
let instance = entry
.create_instance(
&xr::ApplicationInfo {
application_name: "hello openxrs",
..Default::default()
},
&xr::ExtensionSet::default(),
&[],
)
.unwrap();
let instance_props = instance.properties().unwrap();
println!(
"loaded instance: {} v{}",
instance_props.runtime_name, instance_props.runtime_version
);
let system = instance
.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY)
.unwrap();
let system_props = instance.system_properties(system).unwrap();
println!(
"selected system {}: {}",
system_props.system_id.into_raw(),
if system_props.system_name.is_empty() {
"<unnamed>"
} else {
&system_props.system_name
}
);
let view_config_views = instance
.enumerate_view_configuration_views(system, xr::ViewConfigurationType::PRIMARY_STEREO)
.unwrap();
println!("view configuration views: {:#?}", view_config_views);
}
#[allow(dead_code)]
#[cfg(target_os = "android")]
#[no_mangle]
fn android_main(_app: AndroidApp) {
android_logger::init_once(android_logger::Config::default().with_min_level(log::Level::Trace));
_main();
}
#[allow(dead_code)]
#[cfg(not(target_os = "android"))]
fn main() {
env_logger::builder()
.filter_level(log::LevelFilter::Warn) // Default Log Level
.parse_default_env()
.init();
_main();
}
+22
View File
@@ -0,0 +1,22 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
*.so
# Added by cargo
/target
Cargo.lock
+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/Users/Robert/src/agdk-rust/examples/agdk-winit-wgpu/app/src/main/res/layout/activity_main.xml" value="0.5546875" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+49
View File
@@ -0,0 +1,49 @@
[package]
name = "na-openxr-wgpu"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
ash = "0.37"
wgpu-hal = { version = "0.13", features = [ "vulkan" ] }
wgpu = "0.13"
wgpu-types = "0.13"
anyhow = "1"
bitflags = "1"
[target.'cfg(not(target_os = "android"))'.dependencies]
openxr = { version = "0.16", features = [ "static" ] }
env_logger = "0.9"
ctrlc = "3"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { version = "0.3", features = [ "native-activity" ] }
openxr = { version = "0.16", features = [ "linked" ] }
[patch.crates-io]
# openxr 0.16 uses ndk-glue, but master uses ndk-context which is compatible with android-activity
openxr = { git = "https://github.com/Ralith/openxrs" }
# Since Winit also depends on android-activity we need to
# make sure we only resolve a single implementation.
android-activity = { path="../../android-activity" }
[features]
default = []
#default = [ "android" ]
#android = [ "openxr/linked" ]
desktop = []
[lib]
name="main"
crate_type=["cdylib"]
[[bin]]
path="src/lib.rs"
name="test-openxr-wgpu"
required-features = [ "desktop" ]
+47
View File
@@ -0,0 +1,47 @@
This is an example OpenXR application that builds for desktop or
Android and simply renders a head-locked gradient using Wgpu
(via Vulkan).
This borrows heavily from [here](https://github.com/Ralith/openxrs/blob/master/openxr/examples/vulkan.rs) and
[here](https://github.com/zarik5/openxrs/blob/wgpu-test/openxr/examples/vulkan.rs),
although updated to run with Wgpu 0.13 and with most of the
boilerplate for initializing OpenXR and Vulkan + Wgpu factored
into a re-usable `XrShell` that could potentially be a helpful
starting point for building more complex applications.
# Oculus Quest
To build for the Oculus Quest then you first need to download
the Oculus OpenXR Mobile SDK from:
https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/
and after unpacking the zip file you need to copy a suitable `libopenxr_loader.so`
library to `app/src/main/jniLibs/<abi>`
For example if building for arm64-v8a:
`cp path/to/ovr_openxr_mobile_sdk_42.0/OpenXR/Libs/Android/arm64-v8a/Debug/libopenxr_loader.so app/src/main/jniLibs/arm64-v8a`
```
export ANDROID_NDK_HOME="path/to/ndk"
export ANDROID_HOME="path/to/sdk"
rustup target add aarch64-linux-android
cargo install cargo-ndk
cargo ndk -t arm64-v8a -o app/src/main/jniLibs/ build
./gradlew build
./gradlew installDebug
```
# Oculus Quest: Vulkan Validation Layer
To enable the Vulkan validation layer on the Oculus Quest run:
```
adb shell setprop debug.oculus.loadandinjectpackagedvvl.co.realfit.naopenxrwgpu 1
```
# Desktop
To build for PC you need to build with the "desktop" feature
`cargo run --features=desktop`
+1
View File
@@ -0,0 +1 @@
/build
+41
View File
@@ -0,0 +1,41 @@
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
applicationId "co.realfit.naopenxrwgpu"
minSdk 24
targetSdk 25
compileSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
//packagingOptions {
// doNotStrip '**/*.so'
//}
//debuggable true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
}
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.realfit.naopenxrwgpu"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto">
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="false"
android:label="OpenXR Wgpu">
<meta-data android:name="com.oculus.intent.category.VR" android:value="vr_only"/>
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
<activity
android:name=".MainActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:configChanges="density|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|uiMode"
android:launchMode="singleTask"
android:resizeableActivity="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.oculus.intent.category.VR" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="main" />
</activity>
</application>
<uses-sdk android:minSdkVersion="24"/>
<!-- <uses-feature android:glEsVersion="0x00030001" /> -->
<uses-feature android:name="android.hardware.vr.headtracking" android:required="true" android:version="1" />
<uses-feature android:name="oculus.software.handtracking" android:required="false" />
<uses-permission android:name="com.oculus.permission.HAND_TRACKING" />
</manifest>
@@ -0,0 +1,8 @@
package co.realfit.naopenxrwgpu;
public class MainActivity extends android.app.NativeActivity {
static {
System.loadLibrary("openxr_loader");
System.loadLibrary("main");
}
}
+10
View File
@@ -0,0 +1,10 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
+17
View File
@@ -0,0 +1,17 @@
fn main() {
if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
let android_abi = match std::env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() {
"aarch64" => "arm64-v8a",
"arm" => "armeabi-v7a",
"x86" => "x86",
"x86_64" => "x86_64",
arch => {
panic!("Unsupported architecture for Android {arch}");
}
};
let libdir = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
.join(format!("app/src/main/jniLibs/{android_abi}/lib"));
println!("cargo:rustc-link-search={}", libdir.to_string_lossy());
}
}
+21
View File
@@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
Binary file not shown.
@@ -0,0 +1,6 @@
#Mon May 02 15:39:12 BST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
+89
View File
@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+16
View File
@@ -0,0 +1,16 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
include ':app'
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
let x = f32(i32(in_vertex_index) - 1);
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
return vec4<f32>(x, y, 0.0, 1.0);
}
@fragment
fn fs_main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
-1
View File
@@ -19,4 +19,3 @@ local.properties
# Added by cargo
/target
Cargo.lock
+1558
View File
File diff suppressed because it is too large Load Diff
+23 -8
View File
@@ -7,9 +7,8 @@ edition = "2021"
[dependencies]
log = "0.4"
winit = { git = "https://github.com/rib/winit", branch = "android-activity" }
#winit = { path="../../../winit" }
wgpu = "0.12.0"
winit = "0.27"
wgpu = "0.13"
pollster = "0.2"
[target.'cfg(not(target_os = "android"))'.dependencies]
@@ -17,12 +16,28 @@ env_logger = "0.9"
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.11.0"
android-activity = { path="../../android-activity", features = [ "native-activity" ] }
android-activity = { version = "0.3", features = [ "game-activity" ] }
# Since Winit also depends on android-activity (via a github url) we need to
# make sure we only resolve a single implementation.
[patch.'https://github.com/rib/android-activity']
android-activity = { path="../../android-activity", features = [ "native-activity" ] }
[patch.crates-io]
# This branch of Winit has an updated Android backend based on android-activity
# Note: The winit branches are current misnamed:
# - "android-activity" is based on Winit 0.27 (required for Egui compatibility)
# - "android-activity-0.27" is based on Winit master
# The -0.27 branch is currently associated with a pull request so we'll just
# stick with these names for now
winit = { git = "https://github.com/rib/winit", branch = "android-activity-0.27" }
#winit = { path = "../../../winit" }
# Note:
# Since android-activity is responsible for invoking the `android_main`
# entrypoint for a native Rust application there can only be a single
# implementation of the crate linked with the application.
#
# Since Winit also depends on android-activity (version = "0.2") but we'd like
# to build against the local version of android-activity in this repo then we
# use a [patch] to ensure we only end up with a single implementation.
android-activity = { path="../../android-activity" }
[features]
default = []