extern crate libc;
use std;
use std::mem::{transmute, transmute_copy};
use std::ptr::null_mut;
use self::libc::{c_void, size_t};
use super::super::super::core::application::ApplicationTrait;
use super::super::super::core::asset::manager::Manager as AssetManager;
use super::super::super::render::engine::{EngineTrait as RenderEngineTrait, RenderEngine};
use super::super::file::File;
use super::super::os::ApplicationTrait as OsApplicationTrait;
use super::activity::ANativeActivity;
use super::glue;
use super::glue::{AndroidApp, AndroidPollSource, AppCmd};
use super::window::ANativeWindow;
use super::looper::ALooper_pollAll;
#[derive(Clone, Copy)]
pub struct Args {
pub activity: *mut ANativeActivity,
pub saved_state: *mut c_void,
pub saved_state_size: size_t,
}
pub struct Application<CoreApp>
where
CoreApp: 'static + ApplicationTrait,
{
pub asset_manager: AssetManager,
pub core_app: &'static mut CoreApp,
pub render_engine: &'static mut RenderEngine<CoreApp>,
pub window: *mut ANativeWindow,
pub window_initialized: bool,
pub args: Args,
}
impl<CoreApp> OsApplicationTrait<CoreApp> for Application<CoreApp>
where
CoreApp: 'static + ApplicationTrait,
{
fn new(args: *const std::os::raw::c_void) -> Self {
let args: *mut Args = unsafe { transmute(args) };
let args = unsafe { (*args).clone() };
let activity = args.activity;
logi!("Creating: {:?}", activity);
let app = Application {
asset_manager: AssetManager::new(File::new(
&"data.gx3d".to_string(),
unsafe { (*activity).assetManager },
)),
core_app: unsafe { transmute(0usize) },
render_engine: unsafe { transmute(0usize) },
window: null_mut(),
window_initialized: false,
args: args,
};
unsafe {
(*(*activity).callbacks).onDestroy = glue::on_destroy;
(*(*activity).callbacks).onStart = glue::on_start;
(*(*activity).callbacks).onResume = glue::on_resume;
(*(*activity).callbacks).onSaveInstanceState = glue::on_save_instance_state;
(*(*activity).callbacks).onPause = glue::on_pause;
(*(*activity).callbacks).onStop = glue::on_stop;
(*(*activity).callbacks).onConfigurationChanged = glue::on_configuration_changed;
(*(*activity).callbacks).onLowMemory = glue::on_low_memory;
(*(*activity).callbacks).onWindowFocusChanged = glue::on_window_focus_changed;
(*(*activity).callbacks).onNativeWindowCreated = glue::on_native_window_created;
(*(*activity).callbacks).onNativeWindowDestroyed = glue::on_native_window_destroyed;
(*(*activity).callbacks).onInputQueueCreated = glue::on_input_queue_created;
(*(*activity).callbacks).onInputQueueDestroyed = glue::on_input_queue_destroyed;
}
app
}
fn set_core_app(&mut self, c: &'static mut CoreApp) {
self.core_app = c;
}
fn set_rnd_eng(&mut self, r: &'static mut RenderEngine<CoreApp>) {
self.render_engine = r;
}
fn initialize(&mut self) -> bool {
unsafe {
(*self.args.activity).instance = glue::android_app_create::<CoreApp>(
self.args.activity,
self.args.saved_state,
self.args.saved_state_size,
transmute_copy(self.render_engine.os_app),
)
}
self.asset_manager.initialize();
return true;
}
fn execute(&mut self) -> bool {
return true;
}
fn get_mouse_position(&self) -> (f64, f64) {
return (0.0, 0.0);
}
fn get_window_ratio(&self) -> f64 {
1.7
}
}
impl<CoreApp> Application<CoreApp>
where
CoreApp: ApplicationTrait,
{
pub fn main(&mut self, android_app: *mut AndroidApp) {
logi!("I'm in");
unsafe {
(*android_app).on_app_cmd = handle_cmd::<CoreApp>;
}
let mut events = 0 as libc::c_int;
let mut source = 0 as *mut AndroidPollSource;
while unsafe { (*android_app).destroy_requested } == 0 {
if unsafe {
ALooper_pollAll(
if self.window_initialized { 0 } else { 0 },
null_mut(),
&mut events,
transmute(&mut source),
)
} >= 0
{
if source != null_mut() {
unsafe {
((*source).process)(android_app, source);
}
}
if self.window_initialized {
unsafe {
(*self.render_engine).update();
}
}
}
}
loge!("Unexpected flow.");
}
fn handle_cmd(&mut self, app: *mut AndroidApp, cmd: i32) {
match unsafe { transmute::<i8, AppCmd>(cmd as i8) } {
AppCmd::InitWindow => {
logi!("Window has been shown!");
self.window_initialized = true;
self.window = unsafe { (*app).window };
loge!("{:?}", self.window);
self.render_engine.initialize();
unsafe {
self.core_app.initialize(
transmute_copy(self.render_engine.os_app),
transmute_copy(self.render_engine));
}
}
AppCmd::TermWindow => {
logi!("Window has been terminated!");
}
c @ _ => {
let _ = c;
logi!("event {:?} not handled in app {:?} ", c, app);
}
}
}
}
unsafe extern "C" fn handle_cmd<CoreApp>(android_app: *mut AndroidApp, cmd: i32)
where
CoreApp: 'static + ApplicationTrait,
{
let app: &'static mut Application<CoreApp> = transmute((*android_app).user_data);
app.handle_cmd(android_app, cmd);
}
impl<CoreApp> Drop for Application<CoreApp>
where
CoreApp: ApplicationTrait,
{
fn drop(&mut self) {
loge!("Error unexpected deletion of Os Application.");
}
}