Copy to clipboard
#include <jni.h> #include <stdlib.h> #include <iostream> #include <stdexcept> #include <string> #include "ogrewrapper.h" #include <OIS.h> #include <android/log.h> #include "OgreADPArchive.h" #define LOG_TAG "libogresamplebrowser" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) class AndroidMultiTouch : public OIS::MultiTouch { public: AndroidMultiTouch():OIS::MultiTouch("DWM", false, 0, 0){} /** @copydoc Object::setBuffered */ virtual void setBuffered(bool buffered){} /** @copydoc Object::capture */ virtual void capture(){} /** @copydoc Object::queryInterface */ virtual OIS::Interface* queryInterface(OIS::Interface::IType type) {return 0;} /** @copydoc Object::_initialize */ virtual void _initialize(){} OIS::MultiTouchState &getMultiTouchState(int i){ while(i >= mStates.size()){ OIS::MultiTouchState state; state.width = getRenderWindow()->getWidth(); state.height = getRenderWindow()->getHeight(); mStates.push_back(state); } return mStates[i]; } }; class AndroidKeyboard : public OIS::Keyboard { public: AndroidKeyboard():OIS::Keyboard("DWM", false, 1, 0){} /** @copydoc Object::setBuffered */ virtual void setBuffered(bool buffered){} /** @copydoc Object::capture */ virtual void capture(){} /** @copydoc Object::queryInterface */ virtual OIS::Interface* queryInterface(OIS::Interface::IType type) {return 0;} /** @copydoc Object::_initialize */ virtual void _initialize(){} virtual bool isKeyDown( OIS::KeyCode key ) const{ return false; } virtual const std::string& getAsString( OIS::KeyCode kc ){ static std::string defstr = ""; return defstr; } virtual void copyKeyStates( char keys[256] ) const{ } }; #include "SampleBrowser.h" static AndroidMultiTouch *g_multiTouch = 0; static AndroidKeyboard *g_keyboard = 0; static OgreBites::SampleBrowser *g_browser = 0; static bool g_rootInit = false; static int g_xOffset = 0, g_yOffset = 0; static void injectTouchEvent(int pointerId, int action, float x, float y){ if(g_browser){ OIS::MultiTouchState &state = g_multiTouch->getMultiTouchState(pointerId); switch(action){ case 0: state.touchType = OIS::MT_Pressed; break; case 1: state.touchType = OIS::MT_Released; break; case 2: state.touchType = OIS::MT_Moved; break; case 3: state.touchType = OIS::MT_Cancelled; break; default: state.touchType = OIS::MT_None; } if(state.touchType != OIS::MT_None){ int last = state.X.abs; state.X.abs = g_xOffset + (int)x; state.X.rel = state.X.abs - last; last = state.Y.abs; state.Y.abs = g_yOffset + (int)y; state.Y.rel = state.Y.abs - last; //last = state.Z.abs; state.Z.abs = 0; state.Z.rel = 0; OIS::MultiTouchEvent evt(g_multiTouch, state); switch(state.touchType){ case OIS::MT_Pressed: g_browser->touchPressed(evt); break; case OIS::MT_Released: g_browser->touchReleased(evt); break; case OIS::MT_Moved: g_browser->touchMoved(evt); break; case OIS::MT_Cancelled: g_browser->touchCancelled(evt); break; } } } } static void injectKeyEvent(int action, int keyCode){ if(g_browser){ OIS::KeyCode kc = OIS::KC_UNASSIGNED; unsigned int txt = 0; switch(keyCode){ case 7: kc = OIS::KC_0; txt = '0'; break; case 8: kc = OIS::KC_1; txt = '1'; break; case 9: kc = OIS::KC_2; txt = '2'; break; case 10: kc = OIS::KC_3; txt = '3'; break; case 11: kc = OIS::KC_4; txt = '4'; break; case 12: kc = OIS::KC_5; txt = '5'; break; case 13: kc = OIS::KC_6; txt = '6'; break; case 14: kc = OIS::KC_7; txt = '7'; break; case 15: kc = OIS::KC_8; txt = '8'; break; case 16: kc = OIS::KC_9; txt = '9'; break; case 69: kc = OIS::KC_MINUS; txt = '-'; break; case 70: kc = OIS::KC_EQUALS; txt = '='; break; case 61: kc = OIS::KC_TAB; txt = '\t'; break; case 67: kc = OIS::KC_BACK; txt = '\b'; break; case 29: kc = OIS::KC_A; txt = 'A'; break; case 30: kc = OIS::KC_B; txt = 'B'; break; case 31: kc = OIS::KC_C; txt = 'C'; break; case 32: kc = OIS::KC_D; txt = 'D'; break; case 33: kc = OIS::KC_E; txt = 'E'; break; case 34: kc = OIS::KC_F; txt = 'F'; break; case 35: kc = OIS::KC_G; txt = 'G'; break; case 36: kc = OIS::KC_H; txt = 'H'; break; case 37: kc = OIS::KC_I; txt = 'I'; break; case 38: kc = OIS::KC_J; txt = 'J'; break; case 39: kc = OIS::KC_K; txt = 'K'; break; case 40: kc = OIS::KC_L; txt = 'L'; break; case 41: kc = OIS::KC_M; txt = 'M'; break; case 42: kc = OIS::KC_N; txt = 'N'; break; case 43: kc = OIS::KC_O; txt = 'O'; break; case 44: kc = OIS::KC_P; txt = 'P'; break; case 45: kc = OIS::KC_Q; txt = 'Q'; break; case 46: kc = OIS::KC_R; txt = 'R'; break; case 47: kc = OIS::KC_S; txt = 'S'; break; case 48: kc = OIS::KC_T; txt = 'T'; break; case 49: kc = OIS::KC_U; txt = 'U'; break; case 50: kc = OIS::KC_V; txt = 'V'; break; case 51: kc = OIS::KC_W; txt = 'W'; break; case 52: kc = OIS::KC_X; txt = 'X'; break; case 53: kc = OIS::KC_Y; txt = 'Y'; break; case 54: kc = OIS::KC_Z; txt = 'Z'; break; case 71: kc = OIS::KC_LBRACKET; txt = '['; break; case 72: kc = OIS::KC_RBRACKET; txt = ']'; break; case 66: kc = OIS::KC_RETURN; txt = '\n'; break; case 74: kc = OIS::KC_SEMICOLON; txt = ';'; break; case 75: kc = OIS::KC_APOSTROPHE; txt = '\''; break; case 73: kc = OIS::KC_BACKSLASH; txt = '\\'; break; case 55: kc = OIS::KC_COMMA; txt = ','; break; case 56: kc = OIS::KC_PERIOD; txt = '.'; break; case 76: kc = OIS::KC_SLASH; txt = '/'; break; case 19: kc = OIS::KC_UP; break; case 20: kc = OIS::KC_DOWN; break; case 21: kc = OIS::KC_LEFT; break; case 22: kc = OIS::KC_RIGHT; break; } OIS::KeyEvent evt(g_keyboard, kc, txt); if(action == 0) { g_browser->keyPressed(evt); } else { g_browser->keyReleased(evt); } } } static bool hasFile(JNIEnv *env, const char *name){ // Get the asset manager jclass cls = env->FindClass("org/ogre/ADPManager"); jmethodID hasFile_method = env->GetMethodID(cls, "hasFile", "(Ljava/lang/String;)Z"); jmethodID getInstance_method = env->GetStaticMethodID(cls, "getInstance", "()Lorg/ogre/ADPManager;"); jobject obj = env->CallStaticObjectMethod(cls, getInstance_method); jstring str = env->NewStringUTF(name); jboolean result = env->CallBooleanMethod(obj, hasFile_method, str); return (result == JNI_TRUE); } static void loadFile(JNIEnv* env, const char *name, void **ptr, size_t *size){ // Get the asset manager jclass cls = env->FindClass("org/ogre/ADPManager"); jmethodID getFileSize_method = env->GetMethodID(cls, "getFileSize", "(Ljava/lang/String;)I"); jmethodID beginStream_method = env->GetMethodID(cls, "beginStream", "(Ljava/lang/String;)V"); jmethodID endStream_method = env->GetMethodID(cls, "endStream", "()V"); jmethodID readStream_method = env->GetMethodID(cls, "readStream", "()Lorg/ogre/ADPManager$RawData;"); jmethodID getInstance_method = env->GetStaticMethodID(cls, "getInstance", "()Lorg/ogre/ADPManager;"); jobject obj = env->CallStaticObjectMethod(cls, getInstance_method); jstring filename = env->NewStringUTF(name); // Get the total file size jint filesize = env->CallIntMethod(obj, getFileSize_method, filename); if(filesize > 0){ // Allocate the buffer *size = filesize; *ptr = OGRE_MALLOC(filesize, Ogre::MEMCATEGORY_GENERAL); unsigned char *ptr2 = (unsigned char*)*ptr; // Start the streaming static jclass RawData_class = env->FindClass("org/ogre/ADPManager$RawData"); static jfieldID lengthId = env->GetFieldID(RawData_class, "length", "I"); static jfieldID dataId = env->GetFieldID(RawData_class, "data", "[B"); env->CallVoidMethod(obj, beginStream_method, filename); int offset = 0; // Store where into the buffer we're writing to while(offset < filesize){ jobject rawData = env->CallObjectMethod(obj, readStream_method); if(rawData != 0){ jbyteArray buffer = (jbyteArray) env->GetObjectField(rawData, dataId); int length = env->GetIntField(rawData, lengthId); env->GetByteArrayRegion(buffer, 0, length, (jbyte*)(ptr2 + offset)); // Copy the bytes offset += length; } } env->CallVoidMethod(obj, endStream_method); } } class JavaADPSource : public Ogre::ADPSource{ private: JNIEnv* mEnv; public: JavaADPSource(JNIEnv* env):mEnv(env){} Ogre::DataStreamPtr getPackage(const Ogre::String &name){ if(!hasFile(mEnv, name.c_str())){ return Ogre::DataStreamPtr(); } void *data = 0; size_t size = 0; loadFile(mEnv, name.c_str(), &data, &size); Ogre::DataStreamPtr stream; if(data) stream = Ogre::DataStreamPtr(new Ogre::MemoryDataStream(data, size, true)); return stream; } }; static JavaADPSource *g_adpSource = 0; static Ogre::ADPArchiveFactory *g_archiveFactory = 0; jboolean init(JNIEnv* env, jobject thiz) { bool ret = initOgreRoot(); if(!ret) return JNI_FALSE; g_rootInit = true; g_adpSource = OGRE_NEW JavaADPSource(env); g_archiveFactory = OGRE_NEW Ogre::ADPArchiveFactory(g_adpSource); Ogre::ArchiveManager::getSingleton().addArchiveFactory(g_archiveFactory); LOGI("Adding resource locations"); Ogre::ResourceGroupManager::getSingleton().createResourceGroup("Popular"); Ogre::ResourceGroupManager::getSingleton().createResourceGroup("Essential"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("rtss.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("cubemap.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("cubemapJS.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("fonts.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("fresneldemo.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("materials.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("meshes.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("skybox.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("textures.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("particle.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("sinbad.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("dragon.mp3", "ADP", "Popular"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("SdkTrays.mp3", "ADP", "Essential"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("thumbnails.mp3", "ADP", "Essential"); } jboolean render(JNIEnv* env, jobject thiz, jint drawWidth, jint drawHeight, jboolean forceRedraw) { // Check that a render window even exists if(getRenderWindow() == 0){ initRenderWindow(0, drawWidth, drawHeight, 0); } // Initialize the sample browser if(g_multiTouch == 0){ g_multiTouch = new AndroidMultiTouch(); } if(g_keyboard == 0){ g_keyboard = new AndroidKeyboard(); } if(g_browser == 0){ LOGI("Initializing the sample browser"); g_browser = OGRE_NEW OgreBites::SampleBrowser(); g_browser->initAppForAndroid(getRenderWindow(), g_multiTouch, g_keyboard); g_browser->initApp(); LOGI("Browser initialized"); Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); } renderOneFrame(); return JNI_TRUE; } void cleanup(JNIEnv* env) { if(g_browser){ g_browser->closeApp(); OGRE_DELETE g_browser; g_browser = 0; } if(g_multiTouch){ delete g_multiTouch; g_multiTouch = 0; } if(g_keyboard){ delete g_keyboard; g_keyboard = 0; } if(getRenderWindow()){ destroyRenderWindow(); } LOGI("deleting ogre root"); if(g_rootInit){ destroyOgreRoot(); g_rootInit = false; } LOGI("deleting ADP stuff"); if(g_archiveFactory){ OGRE_DELETE g_archiveFactory; g_archiveFactory = 0; } if(g_adpSource){ OGRE_DELETE g_adpSource; g_adpSource = 0; } } jboolean inputEvent(JNIEnv* env, jobject thiz, jint action, jfloat mx, jfloat my) { injectTouchEvent(0, action, mx, my); return JNI_TRUE; } jboolean keyEvent(JNIEnv* env, jobject thiz, jint action, jint unicodeChar, jint keyCode, jobject keyEvent) { injectKeyEvent(action, keyCode); return JNI_TRUE; } void setOffsets(JNIEnv* env, jobject thiz, jint x, jint y) { g_xOffset = x; g_yOffset = y; } jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv *env; 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", "()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 }, }; jclass k; k = (env)->FindClass ("org/ogre/samples/OgreSampleBrowserActivity"); (env)->RegisterNatives(k, methods, 6); return JNI_VERSION_1_4; }