Get the magicleap immersive demo to respond to new file name arguments

This commit is contained in:
Alan Jeffrey 2019-04-04 17:09:34 -05:00 committed by Josh Matthews
parent 3bd825196e
commit 1c1eaf20d1
3 changed files with 120 additions and 88 deletions

View File

@ -12,7 +12,7 @@
<uses-privilege ml:name="ControllerPose"/>
<component
ml:name=".universe"
ml:visible_name="Pathfinder Landscape Demo"
ml:visible_name="PF Landscape Demo"
ml:binary_name="bin/PathfinderLandscapeDemo"
ml:type="Universe">
<icon
@ -21,7 +21,7 @@
</component>
<component
ml:name=".fullscreen"
ml:visible_name="Pathfinder Immersive Demo"
ml:visible_name="PF Immersive Demo"
ml:binary_name="bin/PathfinderImmersiveDemo"
ml:type="Fullscreen">
<mime-type ml:name="image/svg"/>

View File

@ -45,6 +45,7 @@ use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::sync::mpsc;
use usvg::Options as UsvgOptions;
use usvg::Tree;
@ -55,8 +56,14 @@ mod magicleap;
#[cfg(feature = "mocked")]
mod mocked_c_api;
struct ImmersiveApp {
sender: mpsc::Sender<Event>,
receiver: mpsc::Receiver<Event>,
demo: DemoApp<MagicLeapWindow>,
}
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_context: EGLContext, file_name: *const c_char) {
pub unsafe extern "C" fn magicleap_pathfinder_demo_init(egl_display: EGLDisplay, egl_context: EGLContext) -> *mut c_void {
unsafe { c_api::MLLoggingLog(c_api::MLLogLevel::Info, &b"Pathfinder Demo\0"[0], &b"Initializing\0"[0]) };
let tag = CString::new("Pathfinder Demo").unwrap();
@ -64,7 +71,7 @@ pub unsafe extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_
let logger = MagicLeapLogger::new(tag, level);
log::set_boxed_logger(Box::new(logger)).unwrap();
log::set_max_level(level);
debug!("Initialized logging");
info!("Initialized logging");
let window = MagicLeapWindow::new(egl_display, egl_context);
let window_size = window.size();
@ -75,25 +82,42 @@ pub unsafe extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_
options.mode = Mode::VR;
options.jobs = Some(3);
options.pipeline = 0;
if let Some(file_name) = file_name.as_ref() {
let file_name = CStr::from_ptr(file_name).to_string_lossy().into_owned();
options.input_path = SVGPath::Resource(file_name);
}
let mut app = DemoApp::new(window, window_size, options);
debug!("Initialized app");
let demo = DemoApp::new(window, window_size, options);
info!("Initialized app");
while app.window.running() {
let mut events = Vec::new();
while let Some(event) = app.window.try_get_event() {
events.push(event);
}
let (sender, receiver) = mpsc::channel();
Box::into_raw(Box::new(ImmersiveApp { sender, receiver, demo })) as *mut c_void
}
let scene_count = app.prepare_frame(events);
for scene_index in 0..scene_count {
app.draw_scene(scene_index);
}
app.finish_drawing_frame();
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_demo_run(app: *mut c_void) {
let app = app as *mut ImmersiveApp;
if let Some(app) = app.as_mut() {
while app.demo.window.running() {
let mut events = Vec::new();
while let Some(event) = app.demo.window.try_get_event() {
events.push(event);
}
while let Ok(event) = app.receiver.try_recv() {
events.push(event);
}
let scene_count = app.demo.prepare_frame(events);
for scene_index in 0..scene_count {
app.demo.draw_scene(scene_index);
}
app.demo.finish_drawing_frame();
}
}
}
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_demo_load(app: *mut c_void, svg_filename: *const c_char) {
let app = app as *mut ImmersiveApp;
if let Some(app) = app.as_mut() {
let svg_filename = CStr::from_ptr(svg_filename).to_string_lossy().into_owned();
info!("Loading {}.", svg_filename);
let _ = app.sender.send(Event::OpenSVG(SVGPath::Resource(svg_filename)));
}
}

View File

@ -29,8 +29,10 @@
#include <ml_logging.h>
#include <ml_privileges.h>
// Entry point to the Rust code
extern "C" MLResult magicleap_pathfinder_demo(EGLDisplay egl_display, EGLContext egl_context, const char* file_name);
// Entry points to the Rust code
extern "C" void* magicleap_pathfinder_demo_init(EGLDisplay egl_display, EGLContext egl_context);
extern "C" void magicleap_pathfinder_demo_load(void* app, const char* file_name);
extern "C" void magicleap_pathfinder_demo_run(void* app);
// Initialization of the scene thread
extern "C" void init_scene_thread(uint64_t id) {
@ -47,10 +49,6 @@ extern "C" void init_scene_thread(uint64_t id) {
const char application_name[] = "com.mozilla.pathfinder.demo";
// Structures
struct application_context_t {
int dummy_value;
};
struct graphics_context_t {
EGLDisplay egl_display;
@ -116,24 +114,72 @@ graphics_context_t::~graphics_context_t() {
}
// Callbacks
static void onStop(void* application_context)
static void onStop(void* app)
{
((struct application_context_t*)application_context)->dummy_value = 0;
ML_LOG(Info, "%s: On stop called.", application_name);
}
static void onPause(void* application_context)
static void onPause(void* app)
{
((struct application_context_t*)application_context)->dummy_value = 1;
ML_LOG(Info, "%s: On pause called.", application_name);
}
static void onResume(void* application_context)
static void onResume(void* app)
{
((struct application_context_t*)application_context)->dummy_value = 2;
ML_LOG(Info, "%s: On resume called.", application_name);
}
static void onNewInitArg(void* app)
{
ML_LOG(Info, "%s: On new init arg called.", application_name);
// Get the file argument if there is one
MLLifecycleInitArgList* arg_list = nullptr;
const MLLifecycleInitArg* arg = nullptr;
const MLFileInfo* file_info = nullptr;
const char* file_name = nullptr;
int64_t arg_list_len = 0;
int64_t file_list_len = 0;
if (MLResult_Ok != MLLifecycleGetInitArgList(&arg_list)) {
ML_LOG(Error, "%s: Failed to get init args.", application_name);
return;
}
if (MLResult_Ok != MLLifecycleGetInitArgListLength(arg_list, &arg_list_len)) {
ML_LOG(Error, "%s: Failed to get init arg length.", application_name);
return;
}
if (arg_list_len) {
if (MLResult_Ok != MLLifecycleGetInitArgByIndex(arg_list, 0, &arg)) {
ML_LOG(Error, "%s: Failed to get init arg.", application_name);
return;
}
if (MLResult_Ok != MLLifecycleGetFileInfoListLength(arg, &file_list_len)) {
ML_LOG(Error, "%s: Failed to get file list length.", application_name);
return;
}
}
if (file_list_len) {
if (MLResult_Ok != MLLifecycleGetFileInfoByIndex(arg, 0, &file_info)) {
ML_LOG(Error, "%s: Failed to get file info.", application_name);
return;
}
if (MLResult_Ok != MLFileInfoGetFileName(file_info, &file_name)) {
ML_LOG(Error, "%s: Failed to get file name.", application_name);
return;
}
}
// Tell pathfinder to load the file
magicleap_pathfinder_demo_load(app, file_name);
MLLifecycleFreeInitArgList(&arg_list);
}
extern "C" void logMessage(MLLogLevel lvl, char* msg) {
if (MLLoggingLogLevelIsEnabled(lvl)) {
MLLoggingLog(lvl, ML_DEFAULT_LOG_TAG, msg);
@ -144,20 +190,7 @@ int main() {
// set up host-specific graphics surface
graphics_context_t graphics_context;
// let system know our app has started
MLLifecycleCallbacks lifecycle_callbacks = {};
lifecycle_callbacks.on_stop = onStop;
lifecycle_callbacks.on_pause = onPause;
lifecycle_callbacks.on_resume = onResume;
struct application_context_t application_context;
application_context.dummy_value = 2;
if (MLResult_Ok != MLLifecycleInit(&lifecycle_callbacks, (void*)&application_context)) {
ML_LOG(Error, "%s: Failed to initialize lifecycle.", application_name);
return -1;
}
// Check privileges
if (MLResult_Ok != MLPrivilegesStartup()) {
ML_LOG(Error, "%s: Failed to initialize privileges.", application_name);
return -1;
@ -182,56 +215,31 @@ int main() {
return -1;
}
// Get the file argument if there is one
MLLifecycleInitArgList* arg_list = nullptr;
const MLLifecycleInitArg* arg = nullptr;
const MLFileInfo* file_info = nullptr;
const char* file_name = nullptr;
int64_t arg_list_len = 0;
int64_t file_list_len = 0;
if (MLResult_Ok != MLLifecycleGetInitArgList(&arg_list)) {
ML_LOG(Error, "%s: Failed to get init args.", application_name);
// Initialize pathfinder
void* app = magicleap_pathfinder_demo_init(graphics_context.egl_display, graphics_context.egl_context);
// let system know our app has started
MLLifecycleCallbacks lifecycle_callbacks = {};
lifecycle_callbacks.on_stop = onStop;
lifecycle_callbacks.on_pause = onPause;
lifecycle_callbacks.on_resume = onResume;
lifecycle_callbacks.on_new_initarg = onNewInitArg;
if (MLResult_Ok != MLLifecycleInit(&lifecycle_callbacks, app)) {
ML_LOG(Error, "%s: Failed to initialize lifecycle.", application_name);
return -1;
}
if (MLResult_Ok != MLLifecycleGetInitArgListLength(arg_list, &arg_list_len)) {
ML_LOG(Error, "%s: Failed to get init arg length.", application_name);
return -1;
}
if (arg_list_len) {
if (MLResult_Ok != MLLifecycleGetInitArgByIndex(arg_list, 0, &arg)) {
ML_LOG(Error, "%s: Failed to get init arg.", application_name);
return -1;
}
if (MLResult_Ok != MLLifecycleGetFileInfoListLength(arg, &file_list_len)) {
ML_LOG(Error, "%s: Failed to get file list length.", application_name);
return -1;
}
}
if (file_list_len) {
if (MLResult_Ok != MLLifecycleGetFileInfoByIndex(arg, 0, &file_info)) {
ML_LOG(Error, "%s: Failed to get file info.", application_name);
return -1;
}
if (MLResult_Ok != MLFileInfoGetFileName(file_info, &file_name)) {
ML_LOG(Error, "%s: Failed to get file name.", application_name);
return -1;
}
}
// Get the initial argument if there is one.
onNewInitArg(app);
// Run the demo!
ML_LOG(Info, "%s: Begin demo (%s).", application_name, file_name);
MLResult status = magicleap_pathfinder_demo(graphics_context.egl_display, graphics_context.egl_context, file_name);
ML_LOG(Info, "%s: End demo (%d).", application_name, status);
ML_LOG(Info, "%s: Begin demo.", application_name);
magicleap_pathfinder_demo_run(app);
ML_LOG(Info, "%s: End demo.", application_name);
// Shut down
MLPerceptionShutdown();
MLLifecycleFreeInitArgList(&arg_list);
return 0;
}