/*
-------------------------------------------------------------------------------
This file is part of OgreKit.
http://gamekit.googlecode.com/
Copyright (c) 2006-2010 zcube(JiSeop Moon).
Contributor(s): harkon.kr.
-------------------------------------------------------------------------------
gamekit\Samples\AndroidDemo\Shared\Main.cpp
-------------------------------------------------------------------------------
*/
#include "OgreKit.h"
#include "Ogre.h"
#include "android/AndroidInputManager.h"
#include <stdlib.h>
#include <pthread.h>
//extern static void onJavaDetach(void* arg);
#include <jni.h>
#include <stdlib.h>
#include "AndroidLogListener.h"
#include <android/log.h>
#define LOG_TAG "OgreKit"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOG_FOOT LOGI("%s %s %d", __FILE__, __FUNCTION__, __LINE__)
const gkString gkDefaultBlend = "/sdcard/gk_android.blend";
const gkString gkDefaultConfig = "/sdcard/OgreKitStartup.cfg";
class OgreKit : public gkCoreApplication, public gkMessageManager::GenericMessageListener
{
public:
gkString m_blend;
gkScene* m_scene;
OIS::AndroidInputManager* m_input;
public:
OgreKit(): m_blend(gkDefaultBlend), m_scene(0), m_input(0) { };
virtual ~OgreKit() {}
bool init(const gkString& blend,JavaVM* vm);
void keyReleased(const gkKeyboard& key, const gkScanCode& sc);
void injectKey(int action, int uniChar, int keyCode) { if (m_input) m_input->injectKey(action, uniChar, keyCode); }
void injectTouch(int action, float x, float y) { if (m_input) m_input->injectTouch(action, x, y); }
void injectAcceleration(float x,float y, float z) { if (m_input) m_input->injectAcceleration(x,y,z);}
void setOffsets(int x, int y) { if (m_input) m_input->setOffsets(x,y); }
void setWindowSize(int w, int h) { if (m_input) m_input->setWindowSize(w,h); }
void handleMessage(gkMessageManager::Message* message);
JNIEnv* GetEnv();
// jstring JNU_NewStringNative(JNIEnv *env, char *str);
private:
JavaVM* mJVM;
bool setup(void);
jmethodID mFireString;
};
//
//jstring OgreKit::JNU_NewStringNative(JNIEnv *env, char *str)
//{
// jstring result;
// jbyteArray bytes = 0;
// int len;
// if ((env)->EnsureLocalCapacity(2) < 0) {
// return NULL; /* out of memory error */
// }
// len = strlen(str);
// bytes = (env)->NewByteArray(len);
// if (bytes != NULL) {
// (env)->SetByteArrayRegion( bytes, 0, len,
// (jbyte *)str);
// result = (env)->NewObject( Class_java_lang_String,
// MID_String_init, bytes);
// (env)->DeleteLocalRef(bytes);
// return result;
// } /* else fall through */
// return NULL;
//}
void OgreKit::handleMessage(gkMessageManager::Message* message){
LOGI("HANDLE MSG %s ",message->m_subject.c_str());
JNIEnv* env = this->GetEnv();
jclass ANDROID_MAIN = (env)->FindClass( "org/gamekit/jni/Main");
if (!ANDROID_MAIN)
{
LOGI("COULDNT FIND MAIN!!!");
return ;
}
//调用Java静态方法
mFireString = (env)->GetStaticMethodID(ANDROID_MAIN, "fireStringMessage", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
// jstring from = this->JNU_NewStringNative(env,message->m_subject.c_str());
jstring from = env->NewStringUTF(message->m_from.c_str());
jstring to = env->NewStringUTF(message->m_to.c_str());
jstring subject = env->NewStringUTF(message->m_subject.c_str());
jstring body = env->NewStringUTF(message->m_body.c_str());
env->CallStaticVoidMethod(ANDROID_MAIN,mFireString, from,to,subject,body);
}
JNIEnv* OgreKit::GetEnv()
{
JNIEnv* env = NULL;
if (mJVM) (mJVM)->GetEnv((void**)&env, JNI_VERSION_1_2);
return env;
}
bool OgreKit::init(const gkString& blend,JavaVM* vm)
{
gkPrintf("----------- OgreKit Android Demo init -----------------");
LOG_FOOT;
gkString cfgfname;
mJVM = vm;
// Parse command line
m_blend = gkDefaultBlend;
if (!blend.empty()) m_blend = blend;
getPrefs().wintitle = gkString("OgreKit Demo (Press Escape to exit)[") + m_blend + gkString("]");
getPrefs().blendermat=true;
// getPrefs().viewportOrientation="portrait";
// m_prefs.disableSound=false;
gkPath path = cfgfname;
LOG_FOOT;
// overide settings if found
if (path.isFileInBundle())
getPrefs().load(path.getPath());
LOG_FOOT;
bool ok = initialize();
LOG_FOOT;
gkMessageManager::getSingleton().addListener(this);
return ok;
}
bool OgreKit::setup(void)
{
LOG_FOOT;
gkBlendFile* blend = gkBlendLoader::getSingleton().loadFile(gkUtils::getFile(m_blend), gkBlendLoader::LO_ALL_SCENES);
if (!blend)
{
LOGI("File loading failed.\n");
return false;
}
LOG_FOOT;
m_scene = blend->getMainScene();
if (!m_scene)
{
LOGI("No usable scenes found in blend.\n");
return false;
}
LOG_FOOT;
m_scene->createInstance();
LOG_FOOT;
// add input hooks
gkWindow* win = gkWindowSystem::getSingleton().getMainWindow();
m_input = static_cast<OIS::AndroidInputManager*>(win->getInputManager());
LOG_FOOT;
return true;
}
OgreKit okit;
//Ogre::LogManager gLogManager;
AndroidLogListener gLogListener;
gkString file;
jboolean init(JNIEnv* env, jobject thiz, jstring arg)
{
file = gkDefaultBlend;
const char* str = env->GetStringUTFChars(arg, 0);
if (str)
{
file = str;
env->ReleaseStringUTFChars(arg, str);
}
return JNI_TRUE;
}
JavaVM* vmPointer;
jboolean render(JNIEnv* env, jobject thiz, jint drawWidth, jint drawHeight, jboolean forceRedraw)
{
//LOG_FOOT;
static bool first = true;
if (first)
{
first = false;
LOG_FOOT;
okit.getPrefs().winsize.x = drawWidth;
okit.getPrefs().winsize.y = drawHeight;
gkLogger::enable("OgreKitDemo.log", true);
Ogre::LogManager::getSingleton().getDefaultLog()->addListener(&gLogListener);
LOG_FOOT;
// LOGI("****** %s ******", file.c_str());
LOG_FOOT;
okit.getPrefs().verbose = true;
if (!okit.init(file,vmPointer))
{
LOG_FOOT;
// error
return JNI_FALSE;
}
gkLogger::write("window");
gkWindow* win = gkWindowSystem::getSingleton().getMainWindow();
gkLogger::write("window");
okit.m_input = static_cast<OIS::AndroidInputManager*>(win->getInputManager());
gkLogger::write("window");
LOG_FOOT;
gkLogger::write("steploop");
gkEngine::getSingleton().initializeStepLoop();
gkLogger::write("window");
LOG_FOOT;
okit.setWindowSize(drawWidth, drawHeight);
gkLogger::write("window");
}
// gkLogger::write("steponeframe");
if (gkEngine::getSingleton().stepOneFrame())
return JNI_TRUE;
else
return JNI_FALSE;
}
void cleanup(JNIEnv* env)
{
LOG_FOOT;
gkEngine::getSingleton().finalizeStepLoop();
}
jboolean inputEvent(JNIEnv* env, jobject thiz, jint action, jfloat mx, jfloat my)
{
// LOG_FOOT;
okit.injectTouch(action, mx, my);
return JNI_TRUE;
}
jboolean keyEvent(JNIEnv* env, jobject thiz, jint action, jint unicodeChar, jint keyCode, jobject keyEvent)
{
// LOG_FOOT;
okit.injectKey(action, unicodeChar, keyCode);
return JNI_TRUE;
}
void setOffsets(JNIEnv* env, jobject thiz, jint x, jint y)
{
// LOGI("%s %d %d", __FUNCTION__, x, y);
okit.setOffsets(x,y);
}
void sendSensor(JNIEnv *env, jclass thiz, jint type, jfloat x, jfloat y, jfloat z) {
// LOGI("%d %f %f %f", __FUNCTION__, type,x, y,z);
okit.injectAcceleration(x,y,z);
}
/*
* Class: org_gamekit_jni_GameKitJNI
* Method: sendMessage
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
*/
void sendMessage
(JNIEnv *env, jclass thiz, jstring jfrom, jstring jto, jstring jsubject, jstring jbody){
const char* str = env->GetStringUTFChars(jfrom, 0);
gkString from = str;
env->ReleaseStringUTFChars(jfrom,str);
const char* str2 = env->GetStringUTFChars(jto, 0);
gkString to = str2;
env->ReleaseStringUTFChars(jto,str2);
const char* str3 = env->GetStringUTFChars(jsubject, 0);
gkString subject = str3;
env->ReleaseStringUTFChars(jsubject,str3);
const char* str4 = env->GetStringUTFChars(jbody, 0);
gkString body = str4;
env->ReleaseStringUTFChars(jbody,str4);
if (gkMessageManager::getSingletonPtr()) {
gkMessageManager::getSingletonPtr()->sendMessage(from,to,subject,body);
}
// LOGI("%s %s %s %s", from.c_str(),to.c_str(),subject.c_str(),body.c_str());
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
// EXPORT_JNI_OnLoad(vm,reserved);
JNIEnv *env;
vmPointer = vm;
LOGI("JNI_OnLoad called");
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
LOGE("Failed to get the environment using GetEnv()");
return -1;
}
JNINativeMethod methods[] =
{
{
"init",
"(Ljava/lang/String;)Z",
(void *) init
},
{
"render",
"(IIZ)Z",
(void *) render
},
{
"inputEvent",
"(IFFLandroid/view/MotionEvent;)Z",
(void *) inputEvent
},
{
"keyEvent",
"(IIILandroid/view/KeyEvent;)Z",
(void *) keyEvent
},
{
"cleanup",
"()V",
(void *) cleanup
},
{
"setOffsets",
"(II)V",
(void *) setOffsets
},
{
"sendSensor",
"(IFFF)V",
(void *) sendSensor
},
{
"sendMessage",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
(void *) sendMessage
}
};
jclass k;
k = (env)->FindClass ("org/gamekit/jni/Main");
(env)->RegisterNatives(k, methods, 8);
return JNI_VERSION_1_4;
}