diff --git a/CMakeLists.txt b/CMakeLists.txt index 93ccd98f..bbb1d517 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,20 +31,18 @@ endif() add_definitions(-D"VERSION=\\"${VERSION}\\"") +set(executable_SOURCES + src/main.cpp +) if(ANDROID) - include_directories($ENV{ANDROID_NDK}/sources/android/native_app_glue) - set(executable_SOURCES - "android/android.cpp" - "$ENV{ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c" - ) + set( sdl_main + android/SDL_android_main.c + ${executable_SOURCES} ) # add shared library for android - add_library(${PROJECT_NAME} SHARED ${framework_SOURCES} ${client_SOURCES} ${executable_SOURCES}) + add_library(${PROJECT_NAME} SHARED ${framework_SOURCES} ${client_SOURCES} ${sdl_main}) else() - set(executable_SOURCES - src/main.cpp - ) # add client executable add_executable(${PROJECT_NAME} ${framework_SOURCES} ${client_SOURCES} ${executable_SOURCES}) endif() diff --git a/android/SDL_android_main.c b/android/SDL_android_main.c new file mode 100644 index 00000000..4b1fe024 --- /dev/null +++ b/android/SDL_android_main.c @@ -0,0 +1,40 @@ +/* + SDL_android_main.c, placed in the public domain by Sam Lantinga 3/13/14 +*/ +#include "SDL_internal.h" + +#ifdef __ANDROID__ + +/* Include the SDL main definition header */ +#include "SDL_main.h" + +/******************************************************************************* + Functions called by JNI +*******************************************************************************/ +#include + +/* Called before SDL_main() to initialize JNI bindings in SDL library */ +extern void SDL_Android_Init(JNIEnv* env, jclass cls); + +/* Start up the SDL app */ +void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj) +{ + /* This interface could expand with ABI negotiation, calbacks, etc. */ + SDL_Android_Init(env, cls); + + SDL_SetMainReady(); + + /* Run the application code! */ + int status; + char *argv[2]; + argv[0] = SDL_strdup("SDL_app"); + argv[1] = NULL; + status = SDL_main(1, argv); + + /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */ + /* exit(status); */ +} + +#endif /* __ANDROID__ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/android/android.cpp b/android/main.cpp similarity index 100% rename from android/android.cpp rename to android/main.cpp diff --git a/android/project/res/drawable-hdpi/ic_launcher.png b/android/project/res/drawable-hdpi/ic_launcher.png index 96a442e5..49ebe533 100644 Binary files a/android/project/res/drawable-hdpi/ic_launcher.png and b/android/project/res/drawable-hdpi/ic_launcher.png differ diff --git a/android/project/res/drawable-mdpi/ic_launcher.png b/android/project/res/drawable-mdpi/ic_launcher.png index 359047df..085c93b9 100644 Binary files a/android/project/res/drawable-mdpi/ic_launcher.png and b/android/project/res/drawable-mdpi/ic_launcher.png differ diff --git a/android/project/res/drawable-xhdpi/ic_launcher.png b/android/project/res/drawable-xhdpi/ic_launcher.png index 71c6d760..ac3bc4e8 100644 Binary files a/android/project/res/drawable-xhdpi/ic_launcher.png and b/android/project/res/drawable-xhdpi/ic_launcher.png differ diff --git a/android/project/res/drawable-xxhdpi/ic_launcher.png b/android/project/res/drawable-xxhdpi/ic_launcher.png index 4df18946..44b55e64 100644 Binary files a/android/project/res/drawable-xxhdpi/ic_launcher.png and b/android/project/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/android/project/res/drawable-xxxhdpi/ic_launcher.png b/android/project/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..7e4dc416 Binary files /dev/null and b/android/project/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/src/client/client.cpp b/src/client/client.cpp index b02e22a4..5f66df04 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -33,7 +33,7 @@ #include #include -Client::Client(int argc, const char* argv[]) { +Client::Client(int argc, char* argv[]) { std::vector args(argv, argv + argc); initAppFrameworkAndOTClient(args); } @@ -99,8 +99,8 @@ void Client::setupAppNameAndVersion() { void Client::findLuaInitScript() { if(!g_resources.discoverWorkDir("init.lua")) g_logger.fatal("Unable to find work directory, the application cannot be initialized."); - else - runLuaInitScript(); + + runLuaInitScript(); } void Client::runLuaInitScript() { diff --git a/src/client/client.h b/src/client/client.h index b010dc66..e6192788 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -33,7 +33,7 @@ class Client void runLuaInitScript(); void registerLuaFunctions(); public: - Client(int argc, const char* argv[]); + Client(int argc, char* argv[]); void terminateAndFreeMemory(); }; diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index aa555466..01b1fab4 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -228,11 +228,11 @@ message(STATUS "LuaJIT: " ${LUAJIT}) find_package(PhysFS REQUIRED) find_package(OpenSSL REQUIRED) +find_package(ZLIB REQUIRED) -if(NOT ANDROID) - find_package(ZLIB REQUIRED) -else() - set(framework_LIBRARIES ${framework_LIBRARIES} z android log) +if(ANDROID) + set(framework_LIBRARIES ${framework_LIBRARIES} android log) + find_package(SDL2 REQUIRED) endif() set(framework_LIBRARIES ${framework_LIBRARIES} @@ -251,6 +251,11 @@ set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${framework_INCLUDE_DIRS} ) +if(ANDROID) + set(framework_LIBRARIES ${framework_LIBRARIES} ${SDL2_LIBRARY}) + set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${SDL2_INCLUDE_DIR}) +endif() + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") message(STATUS "Debug information: ON") else() @@ -306,25 +311,17 @@ endif() if(FRAMEWORK_GRAPHICS) set(OPENGLES "OFF" CACHE "Use OpenGL ES 1.0 or 2.0 (for mobiles devices)" STRING) if(OPENGLES STREQUAL "2.0" OR (ANDROID_NATIVE_API_LEVEL AND ANDROID_NATIVE_API_LEVEL VERSION_GREATER 7)) - if(NOT ANDROID) - find_package(OpenGLES2 REQUIRED) - find_package(EGL REQUIRED) - set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR}) - set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY}) - else() - set(framework_LIBRARIES ${framework_LIBRARIES} GLESv2) - endif() + find_package(OpenGLES2 REQUIRED) + find_package(EGL REQUIRED) set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=2) + set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR}) + set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES2_LIBRARY}) ELSEif(OPENGLES STREQUAL "1.0" OR (ANDROID_NATIVE_API_LEVEL AND ANDROID_NATIVE_API_LEVEL VERSION_LESS 8)) - if(NOT ANDROID) - find_package(OpenGLES1 REQUIRED) - find_package(EGL REQUIRED) - set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR}) - set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY}) - else() - set(framework_LIBRARIES ${framework_LIBRARIES} GLESv1_CM) - endif() + find_package(OpenGLES1 REQUIRED) + find_package(EGL REQUIRED) set(framework_DEFINITIONS ${framework_DEFINITIONS} -DOPENGL_ES=1) + set(framework_INCLUDE_DIRS ${framework_INCLUDE_DIRS} ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR}) + set(framework_LIBRARIES ${framework_LIBRARIES} ${EGL_LIBRARY} ${OPENGLES1_LIBRARY}) else() ## TODO: CMake Documentation says that this is not the right # Thing for Mac OS X, but it works for now. @@ -361,7 +358,7 @@ if(FRAMEWORK_GRAPHICS) ${CMAKE_CURRENT_LIST_DIR}/graphics/dx/painterdx9.h ) endif() - + elseif(NOT ANDROID) set(framework_LIBRARIES ${framework_LIBRARIES} X11) endif() diff --git a/src/framework/cmake/FindSDL2.cmake b/src/framework/cmake/FindSDL2.cmake new file mode 100644 index 00000000..daabc049 --- /dev/null +++ b/src/framework/cmake/FindSDL2.cmake @@ -0,0 +1,12 @@ +# Try to find the SDL2 library +# SDL2_FOUND - system has SDL2 +# SDL2_INCLUDE_DIR - the SDL2 include directory +# SDL2_LIBRARY - the SDL2 library + +FIND_PATH(SDL2_INCLUDE_DIR NAMES SDL.h PATH_SUFFIXES sdl2) +SET(_SDL2_STATIC_LIBS libSDL2.a) +SET(_SDL2_SHARED_LIBS libSDL2.so SDL2) +FIND_LIBRARY(SDL2_LIBRARY NAMES ${_SDL2_SHARED_LIBS} ${_SDL2_STATIC_LIBS}) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDE_DIR) +MARK_AS_ADVANCED(SDL2_LIBRARY SDL2_INCLUDE_DIR) diff --git a/src/framework/core/application.cpp b/src/framework/core/application.cpp index d54dec1e..1939429e 100644 --- a/src/framework/core/application.cpp +++ b/src/framework/core/application.cpp @@ -177,6 +177,8 @@ std::string Application::getOs() return "mac"; #elif __linux return "linux"; +#elif defined ANDROID + return "android"; #else return "unknown"; #endif diff --git a/src/framework/core/logger.cpp b/src/framework/core/logger.cpp index 22936d62..91fe9158 100644 --- a/src/framework/core/logger.cpp +++ b/src/framework/core/logger.cpp @@ -32,6 +32,10 @@ #include #endif +#ifdef ANDROID +#include +#endif // ANDROID + Logger g_logger; void Logger::log(Fw::LogLevel level, const std::string& message) @@ -66,6 +70,9 @@ void Logger::log(Fw::LogLevel level, const std::string& message) outmsg = tmp.str(); #endif */ +#ifdef ANDROID + __android_log_print(ANDROID_LOG_INFO, "OTClientMobile", outmsg.c_str()); +#endif // ANDROID std::cout << outmsg << std::endl; diff --git a/src/framework/core/resourcemanager.cpp b/src/framework/core/resourcemanager.cpp index 9dbe18ac..67d43b68 100644 --- a/src/framework/core/resourcemanager.cpp +++ b/src/framework/core/resourcemanager.cpp @@ -48,7 +48,8 @@ bool ResourceManager::discoverWorkDir(const std::string& existentFile) std::string possiblePaths[] = { g_platform.getCurrentDir(), g_resources.getBaseDir(), g_resources.getBaseDir() + "../", - g_resources.getBaseDir() + "../share/" + g_app.getCompactName() + "/" }; + g_resources.getBaseDir() + "../share/" + g_app.getCompactName() + "/", + "/sdcard/OTClient/" }; bool found = false; for(const std::string& dir : possiblePaths) { @@ -71,12 +72,20 @@ bool ResourceManager::setupUserWriteDir(const std::string& appWriteDirName) { std::string userDir = getUserDir(); std::string dirName; + #ifndef WIN32 dirName = stdext::format(".%s", appWriteDirName); #else dirName = appWriteDirName; #endif - std::string writeDir = userDir + dirName; + + std::string writeDir; + +#ifdef ANDROID + writeDir = getWorkDir(); +#else + writeDir = userDir + dirName; +#endif if(!PHYSFS_setWriteDir(writeDir.c_str())) { if(!PHYSFS_setWriteDir(userDir.c_str()) || !PHYSFS_mkdir(dirName.c_str())) { diff --git a/src/framework/platform/sdlwindow.cpp b/src/framework/platform/sdlwindow.cpp index 3d43ed56..6c674f7d 100644 --- a/src/framework/platform/sdlwindow.cpp +++ b/src/framework/platform/sdlwindow.cpp @@ -1,16 +1,120 @@ +/* + * Copyright (c) 2010-2014 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef ANDROID + #include "sdlwindow.h" SDLWindow::SDLWindow() { - m_window = 0; - m_cursor = 0; m_minimumSize = Size(600,480); m_size = Size(600,480); } void SDLWindow::init() { + window = 0; + gl = 0; + + initializeSDL(); +} + +void SDLWindow::initializeSDL() { + if(SDL_Init(SDL_INIT_VIDEO) != 0 ) { + g_logger.fatal( stdext::format("Unable to initialize SDL: %s", SDL_GetError()) ); + terminate(); + } + + setSDLAttributes(); + + SDL_GetDisplayMode( 0, 0, &mode ); + int width = mode.w; + int height = mode.h; + + window = SDL_CreateWindow( NULL, 0, 0, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE ); + + if( window == 0 ) { + g_logger.fatal("Failed to create window"); + terminate(); + } + + gl = SDL_GL_CreateContext(window); +} + +void SDLWindow::setSDLAttributes() { + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 4); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 4); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 4); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_ES); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); } void SDLWindow::terminate() { + SDL_Quit(); +} + +void SDLWindow::hide() { + // TODO? +} + +void SDLWindow::poll() { + // TODO +} + +void SDLWindow::swapBuffers() { + SDL_GL_SwapWindow(window); +} + +void SDLWindow::setVerticalSync(bool enable) { + // TODO +} + +std::string SDLWindow::getClipboardText() { + return SDL_GetClipboardText(); +} + +void SDLWindow::setClipboardText(const std::string& text) { + SDL_SetClipboardText(text.c_str()); +} + +Size SDLWindow::getDisplaySize() { + Size size(mode.w, mode.h); + return size; +} + +std::string SDLWindow::getPlatformType() { + return "Android"; +} + +void SDLWindow::show() { + // android doesn't need to show activity, it's open automatically +} + +void SDLWindow::maximize() { + // android doesn't has window } void SDLWindow::move(const Point& pos) { @@ -21,25 +125,6 @@ void SDLWindow::resize(const Size& size) { // android doesn't resize window } -void SDLWindow::show() { - // android doesn't need to show activity, it's open automacally -} - -void SDLWindow::hide() { - -} - -void SDLWindow::maximize() { - // android doesn't has window -} - -void SDLWindow::poll() { - -} - -void SDLWindow::swapBuffers() { -} - void SDLWindow::showMouse() { // android doesn't has mouse } @@ -73,26 +158,8 @@ void SDLWindow::setFullscreen(bool fullscreen) { // android doesn't has window } -void SDLWindow::setVerticalSync(bool enable) { - // TODO -} - void SDLWindow::setIcon(const std::string& iconFile) { // android doesn't has window } -void SDLWindow::setClipboardText(const std::string& text) { -} - -Size SDLWindow::getDisplaySize() { - Size TODO; - return TODO; -} - -std::string SDLWindow::getClipboardText() { - return ""; -} - -std::string SDLWindow::getPlatformType() { - return "Android"; -} +#endif // ANDROID diff --git a/src/framework/platform/sdlwindow.h b/src/framework/platform/sdlwindow.h index 9757b67f..f966c13c 100644 --- a/src/framework/platform/sdlwindow.h +++ b/src/framework/platform/sdlwindow.h @@ -1,15 +1,37 @@ +/* + * Copyright (c) 2010-2014 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + #ifndef SDL_PLATFORM_H #define SDL_PLATFORM_H #include "platformwindow.h" - -#ifdef OPENGL_ES #include -#endif +#include class SDLWindow : public PlatformWindow { public: + SDLWindow(); + void init(); void terminate(); @@ -36,8 +58,15 @@ public: Size getDisplaySize(); std::string getClipboardText(); std::string getPlatformType(); + + void initializeSDL(); + void setSDLAttributes(); protected: int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot); +private: + SDL_Window* window; + SDL_GLContext gl; + SDL_DisplayMode mode; }; #endif diff --git a/src/main.cpp b/src/main.cpp index a7b3f80d..29fa63f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,9 +20,14 @@ * THE SOFTWARE. */ +// The only way that the android sdl library can link a main function it's including SDL.h +#ifdef ANDROID +#include +#endif + #include -int main(int argc, const char* argv[]) +int main(int argc, char* argv[]) { Client client(argc, argv); client.terminateAndFreeMemory();