Fixed typo
This commit is contained in:
parent
62bcf52f9c
commit
803eba5d5c
17
.gitignore
vendored
17
.gitignore
vendored
@ -51,3 +51,20 @@ packets_log.txt
|
||||
history.dat
|
||||
README.dependencies
|
||||
xx
|
||||
|
||||
android/android-ndk*
|
||||
android/android-sdk*
|
||||
android/assets
|
||||
android/bin
|
||||
android/obj
|
||||
android/libs
|
||||
android-*
|
||||
*.apk
|
||||
|
||||
lib/curl
|
||||
lib/freetype
|
||||
lib/ifaddrs
|
||||
lib/libogg
|
||||
lib/libvorbis
|
||||
lib/openal
|
||||
lib/openssl
|
||||
|
174
android/Android.mk
Normal file
174
android/Android.mk
Normal file
@ -0,0 +1,174 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# OpenAL
|
||||
LOCAL_MODULE := openal
|
||||
LOCAL_SRC_FILES := obj/openal/libopenal.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# OGG
|
||||
LOCAL_MODULE := ogg
|
||||
LOCAL_SRC_FILES := obj/libogg/src/.libs/libogg.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# Vorbis
|
||||
LOCAL_MODULE := vorbis
|
||||
LOCAL_SRC_FILES := obj/libvorbis/lib/.libs/libvorbis.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# Vorbisfile
|
||||
LOCAL_MODULE := vorbisfile
|
||||
LOCAL_SRC_FILES := obj/libvorbis/lib/.libs/libvorbisfile.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# CURL
|
||||
LOCAL_MODULE := curl
|
||||
LOCAL_SRC_FILES := obj/curl/lib/.libs/libcurl.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# libcrypto
|
||||
LOCAL_MODULE := libcrypto
|
||||
LOCAL_SRC_FILES := obj/openssl/libcrypto.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# libssl
|
||||
LOCAL_MODULE := libssl
|
||||
LOCAL_SRC_FILES := obj/openssl/libssl.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# JPEG
|
||||
LOCAL_MODULE := jpeglib
|
||||
LOCAL_SRC_FILES := obj/jpeglib/libjpeglib.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# Freetype
|
||||
LOCAL_MODULE := freetype
|
||||
LOCAL_SRC_FILES := obj/freetype/objs/.libs/libfreetype.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# zlib
|
||||
LOCAL_MODULE := zlib
|
||||
LOCAL_SRC_FILES := obj/zlib/libz.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# PNG
|
||||
LOCAL_MODULE := png
|
||||
LOCAL_SRC_FILES := obj/libpng/libpng.a
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# ifaddrs
|
||||
LOCAL_MODULE := ifaddrs
|
||||
LOCAL_PATH := .
|
||||
LOCAL_SRC_FILES := ../lib/ifaddrs/ifaddrs.c
|
||||
LOCAL_CFLAGS := -I../lib/ifaddrs
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# AngelScript
|
||||
LOCAL_MODULE := angelscript
|
||||
LOCAL_PATH := .
|
||||
LOCAL_CPP_FEATURES += rtti exceptions
|
||||
LOCAL_SRC_FILES := $(wildcard ../lib/angelscript/source/*.S) \
|
||||
$(wildcard ../lib/angelscript/source/*.cpp)
|
||||
LOCAL_CFLAGS := -I../lib/angelscript/source/
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# ENET
|
||||
LOCAL_MODULE := enet
|
||||
LOCAL_PATH := .
|
||||
LOCAL_CPP_FEATURES += rtti
|
||||
LOCAL_SRC_FILES := $(wildcard ../lib/enet/*.c)
|
||||
LOCAL_CFLAGS := -I../lib/enet/include/ -DHAS_SOCKLEN_T
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# Bullet
|
||||
LOCAL_MODULE := bullet
|
||||
LOCAL_PATH := .
|
||||
LOCAL_CPP_FEATURES += rtti
|
||||
LOCAL_SRC_FILES := $(wildcard ../lib/bullet/src/*/*.cpp) \
|
||||
$(wildcard ../lib/bullet/src/*/*/*.cpp)
|
||||
LOCAL_CFLAGS := -I../lib/bullet/src/
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# Irrlicht
|
||||
LOCAL_MODULE := irrlicht
|
||||
LOCAL_PATH := .
|
||||
LOCAL_CPP_FEATURES += rtti
|
||||
LOCAL_SRC_FILES := $(wildcard ../lib/irrlicht/source/Irrlicht/*.cpp) \
|
||||
$(wildcard ../lib/irrlicht/source/Irrlicht/Android/*.cpp)
|
||||
LOCAL_CFLAGS := -I../lib/irrlicht/source/Irrlicht/ \
|
||||
-I../lib/irrlicht/include/ \
|
||||
-Iobj/jpeglib/ \
|
||||
-Iobj/libpng/ \
|
||||
-Iobj/zlib/ \
|
||||
-I$(call my-dir)/../../sources/android/native_app_glue
|
||||
-std=gnu++0x
|
||||
LOCAL_STATIC_LIBRARIES := jpeglib png zlib
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
# STK
|
||||
LOCAL_MODULE := main
|
||||
LOCAL_PATH := .
|
||||
LOCAL_CPP_FEATURES += rtti exceptions
|
||||
LOCAL_SRC_FILES := $(wildcard ../src/*.cpp) \
|
||||
$(wildcard ../src/*/*.cpp) \
|
||||
$(wildcard ../src/*/*/*.cpp)
|
||||
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv3 -lOpenSLES
|
||||
LOCAL_CFLAGS := -I../lib/angelscript/include \
|
||||
-I../lib/bullet/src \
|
||||
-I../lib/enet/include \
|
||||
-I../lib/ifaddrs \
|
||||
-I../lib/irrlicht/include \
|
||||
-I../lib/irrlicht/source/Irrlicht \
|
||||
-I../src \
|
||||
-Iobj/curl/include \
|
||||
-Iobj/freetype/include \
|
||||
-Iobj/libogg/include \
|
||||
-Iobj/libvorbis/include \
|
||||
-Iobj/openal/include \
|
||||
-I$(call my-dir)/../../sources/android/native_app_glue \
|
||||
-DUSE_GLES2 \
|
||||
-DHAVE_OGGVORBIS \
|
||||
-DNDEBUG \
|
||||
-std=gnu++0x
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := irrlicht bullet enet freetype ifaddrs angelscript \
|
||||
vorbisfile vorbis ogg openal curl libssl libcrypto \
|
||||
gnustl_static android_native_app_glue
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
$(call import-module,android/native_app_glue)
|
38
android/AndroidManifest.xml
Normal file
38
android/AndroidManifest.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.supertuxkart.stk"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||
<application android:debuggable="true"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:hasCode="false"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:hardwareAccelerated="true">
|
||||
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:screenOrientation="sensorLandscape">
|
||||
|
||||
<!-- Tell NativeActivity the name of or .so -->
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="main" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<uses-sdk android:minSdkVersion="19" />
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
134
android/README.ANDROID
Normal file
134
android/README.ANDROID
Normal file
@ -0,0 +1,134 @@
|
||||
================================================================================
|
||||
|
||||
SUPERTUXKART
|
||||
|
||||
================================================================================
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
SYSTEM REQUIREMENTS
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
To run SuperTuxKart on Android, you need a device that meets following
|
||||
requirements:
|
||||
|
||||
- Android 4.4 or later
|
||||
- Processor compatible with armv7 or x86
|
||||
- GPU that supports OpenGL ES 3.0
|
||||
- 1 GB RAM (STK uses ~150 MB in minimal configuration)
|
||||
- 300 MB of free space on internal storage
|
||||
- Touch screen or external keyboard
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
COMPILATION
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
The build scripts are designed to run under linux. They may work under cygwin
|
||||
after some tweaks, but atm. only linux is supported.
|
||||
|
||||
Dependencies list (may be incomplete):
|
||||
|
||||
autoconf, automake, make, python, ant, imagemagick, cmake, vorbis-tools
|
||||
|
||||
Additionally some dependencies for optimize_data script:
|
||||
|
||||
advancecomp, libjpeg-progs, optipng
|
||||
|
||||
Before compilation you must download the package with dependencies from:
|
||||
https://github.com/supertuxkart/dependencies
|
||||
and extract it to stk-code/lib. It contains sources of libraries that are used
|
||||
in STK, but are not availiable in stk-code repository (curl, freetype, openal).
|
||||
|
||||
You need also Android SDK for android-19 platform (the API for Android 4.4) and
|
||||
Android NDK (versions r12b and r13b have been tested).
|
||||
|
||||
You need to create proper "android-sdk" and "android-ndk" symlinks in the
|
||||
directory with Android project, so that the compilation script will have access
|
||||
to the SDK and NDK.
|
||||
|
||||
These paths can be also set in SDK_PATH and NDK_PATH environmental variables.
|
||||
|
||||
Before running the compilation, run the generate_assets script, so that
|
||||
selected assets will be copied to "assets" directory, and then included in the
|
||||
apk file.
|
||||
|
||||
You can select different karts and tracks by setting KARTS and TRACKS variables
|
||||
in the generate_assets.sh script at the beginning of file.
|
||||
|
||||
When you are creating the assets directory manually, note that the
|
||||
directories.txt file is urgently needed and it is used by the application for
|
||||
extracting assets.
|
||||
|
||||
If the assets directory is already prepared, you can run "./make.sh" command to
|
||||
build the project and create an apk file. Note that all arguments are passed to
|
||||
the make command, so that you can run "./make.sh -j5" for multi-threaded build.
|
||||
|
||||
If you want to prepare a package for particular architecture, you can choose it
|
||||
by setting the COMPILE_ARCH environmental variable. At this stage, supported
|
||||
architectures are "armv7", "x86" and "aarch64". The default is "armv7".
|
||||
|
||||
Basically if all dependencies are installed in the system, it should be enough
|
||||
to just run:
|
||||
|
||||
export SDK_PATH=/path/to/your/android/sdk
|
||||
export NDK_PATH=/path/to/your/android/ndk
|
||||
./generate_assets.sh
|
||||
./make.sh -j5
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
KNOWN ISSUES
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1. At this stage only shader-based (OpenGL ES 3.0) pipeline works. The fixed
|
||||
pipeline (GLES 2.0) could work (it works under linux), but it doesn't look
|
||||
good and is generally broken. It means that it's not possible to run STK on
|
||||
Android 4.2 or older. It is technically possible to do - check GLES context
|
||||
version, load OpenGL functions dynamically using EGL, and if they are not
|
||||
loaded properly, then fallback to GLES 2.0. But these devices may be too
|
||||
slow to run STK anyway.
|
||||
|
||||
2. It never ocurred for me, but it's possible that EGL context is lost in some
|
||||
cases. SuperTuxKart is not designed to re-create all textures at any moment,
|
||||
so this is a "Wontfix", at least for now.
|
||||
|
||||
3. Some bright tracks (Farm, Gran Paradiso) seem to be a bit darker in GLES
|
||||
renderer than in original OpenGL 3.x renderer. It can be easily hacked by
|
||||
adding few lines to object pass shader, but we should rather try to find the
|
||||
real reason.
|
||||
|
||||
4. Explosion effect has poor performance and causes fps drop for a while.
|
||||
Though it can be easily tweaked, so that less particles per second is
|
||||
generated.
|
||||
|
||||
5. Touch steering needs nice button icons.
|
||||
|
||||
6. We use "exit(0)" at the end of main function. We shouldn't do it and we
|
||||
should just return from the main function. But STK uses some global
|
||||
variables and their values are remembered when the game is restarted. We
|
||||
should properly clear them or re-initialize on startup. Using the "exit(0)"
|
||||
is not-that-bad workaround, but it may cause a crash on exit sometimes.
|
||||
It seems to affect only Android 5.0. More information about the crash:
|
||||
https://code.google.com/p/android/issues/detail?id=160824
|
||||
|
||||
7. STK crashes on Qualcomm with Adreno 305 when trying to draw menu interface.
|
||||
Backtrace shows glDrawElements function, and internally crashed in vbo
|
||||
allocation.
|
||||
|
||||
8. STK crashes on startup on some devices when aarch64 build is made using
|
||||
Android r13 NDK. The r13 version has rather big modifications (it uses clang
|
||||
instead of gcc by default). This is probably a bug in NDK/compiler/OS, but
|
||||
for this reason using NDK r12 for 64-bit arm compilation is preferred.
|
||||
|
||||
9. Angelscript doesn't have full support for aarch64 builds, so that scripting
|
||||
won't work on this platform.
|
||||
|
||||
10. Steering with accelerometer is not available yet. It needs some work to do
|
||||
it properly because tablets have different screen orientation than phones,
|
||||
so that they receive events from different axies during rotating the device.
|
||||
As far as I see it's not possible to read default screen orientation using
|
||||
NDK functions.
|
6
android/build.xml
Normal file
6
android/build.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="SuperTuxKart" default="help">
|
||||
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
240
android/generate_assets.sh
Executable file
240
android/generate_assets.sh
Executable file
@ -0,0 +1,240 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# (C) 2016-2017 Dawid Gan, under the GPLv3
|
||||
#
|
||||
# A script that generates data files for Android apk
|
||||
|
||||
|
||||
# Below are simple configuration variables
|
||||
# It's allowed to set "all" for KARTS and TRACKS if it's intended to create
|
||||
# package with full data.
|
||||
# The karts and tracks directories shouldn't exist in ASSETS_DIRS variable
|
||||
# because they are handled separately
|
||||
# The TEXTURE_SIZE and SOUND_QUALITY take effect only if DECREASE_QUALITY has
|
||||
# value greater than 0
|
||||
# The script needs imagemagick and ogg utils installed to use DECREASE_QUALITY
|
||||
# feature
|
||||
|
||||
################################################################################
|
||||
|
||||
export KARTS="tux nolok xue"
|
||||
export TRACKS="battleisland cornfield_crossing featunlocked gplose gpwin \
|
||||
hacienda introcutscene introcutscene2 lighthouse olivermath \
|
||||
overworld snowmountain snowtuxpeak soccer_field tutorial"
|
||||
|
||||
export ASSETS_PATHS="../data \
|
||||
../../stk-assets \
|
||||
../../supertuxkart-assets"
|
||||
|
||||
export ASSETS_DIRS="library models music sfx textures"
|
||||
|
||||
export TEXTURE_SIZE=256
|
||||
export SOUND_QUALITY=64
|
||||
|
||||
export RUN_OPTIMIZE_SCRIPT=0
|
||||
export DECREASE_QUALITY=1
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Find assets path
|
||||
for ASSETS_PATH in $ASSETS_PATHS; do
|
||||
if [ -d $ASSETS_PATH ] && [ `ls $ASSETS_PATH | grep -c tracks` -gt 0 ]; then
|
||||
echo "Assets found in $ASSETS_PATH"
|
||||
ASSETS_PATH_FOUND=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z $ASSETS_PATH_FOUND ]; then
|
||||
echo "Couldn't find assets path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "../data" ]; then
|
||||
echo "Couldn't find data directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Clear previous assets directory
|
||||
echo "Clear previous assets directory"
|
||||
rm -rf assets
|
||||
|
||||
|
||||
# Copy all assets
|
||||
echo "Copy all assets"
|
||||
|
||||
mkdir -p assets/data
|
||||
|
||||
for DIR in `ls $ASSETS_PATH`; do
|
||||
CAN_BE_COPIED=0
|
||||
|
||||
for ASSETS_DIR in $ASSETS_DIRS; do
|
||||
if [ $DIR = $ASSETS_DIR ]; then
|
||||
CAN_BE_COPIED=1
|
||||
break
|
||||
fi
|
||||
done;
|
||||
|
||||
# Don't copy karts and tracks. It will be handled later
|
||||
BLACKLIST_ASSETS="karts tracks"
|
||||
for ASSETS_DIR in $BLACKLIST_ASSETS; do
|
||||
if [ $DIR = $ASSETS_DIR ]; then
|
||||
CAN_BE_COPIED=0
|
||||
break
|
||||
fi
|
||||
done;
|
||||
|
||||
if [ $CAN_BE_COPIED -gt 0 ]; then
|
||||
cp -a "$ASSETS_PATH/$DIR" assets/data/
|
||||
fi
|
||||
done;
|
||||
|
||||
|
||||
# Copy selected tracks
|
||||
echo "Copy selected tracks"
|
||||
|
||||
mkdir -p assets/data/tracks
|
||||
|
||||
for DIR in `ls $ASSETS_PATH/tracks`; do
|
||||
CAN_BE_COPIED=0
|
||||
|
||||
if [ "$TRACKS" != "all" ]; then
|
||||
for TRACK in $TRACKS; do
|
||||
if [ $DIR = $TRACK ]; then
|
||||
CAN_BE_COPIED=1
|
||||
break
|
||||
fi
|
||||
done;
|
||||
else
|
||||
CAN_BE_COPIED=1
|
||||
fi
|
||||
|
||||
if [ $CAN_BE_COPIED -gt 0 ]; then
|
||||
cp -a "$ASSETS_PATH/tracks/$DIR" assets/data/tracks/
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# Copy selected karts
|
||||
echo "Copy selected karts"
|
||||
|
||||
mkdir -p assets/data/karts
|
||||
|
||||
for DIR in `ls $ASSETS_PATH/karts`; do
|
||||
CAN_BE_COPIED=0
|
||||
|
||||
if [ "$KARTS" != "all" ]; then
|
||||
for KART in $KARTS; do
|
||||
if [ $DIR = $KART ]; then
|
||||
CAN_BE_COPIED=1
|
||||
break
|
||||
fi
|
||||
done;
|
||||
else
|
||||
CAN_BE_COPIED=1
|
||||
fi
|
||||
|
||||
if [ $CAN_BE_COPIED -gt 0 ]; then
|
||||
cp -a "$ASSETS_PATH/karts/$DIR" assets/data/karts/
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# Decrease assets quality in order to save some disk space and RAM
|
||||
echo "Decrease assets quality"
|
||||
|
||||
convert_image()
|
||||
{
|
||||
if [ -z "$1" ]; then
|
||||
echo "No file to convert"
|
||||
return
|
||||
fi
|
||||
|
||||
FILE="$1"
|
||||
|
||||
W=`identify -format "%[fx:w]" "$FILE"`
|
||||
H=`identify -format "%[fx:h]" "$FILE"`
|
||||
|
||||
if [ -z $W ] || [ -z $H ]; then
|
||||
echo "Couldn't convert $FILE file"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ $W -le $TEXTURE_SIZE ] && [ $H -le $TEXTURE_SIZE ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ $W -gt $H ]; then
|
||||
SCALED_W=$TEXTURE_SIZE
|
||||
SCALED_H=$(($TEXTURE_SIZE * $H / $W))
|
||||
else
|
||||
SCALED_W=$(($TEXTURE_SIZE * $W / $H))
|
||||
SCALED_H=$TEXTURE_SIZE
|
||||
fi
|
||||
|
||||
convert -scale $SCALED_WE\x$SCALED_H "$FILE" "$FILE"
|
||||
}
|
||||
|
||||
convert_sound()
|
||||
{
|
||||
if [ -z "$1" ]; then
|
||||
echo "No file to convert"
|
||||
return
|
||||
fi
|
||||
|
||||
FILE="$1"
|
||||
|
||||
oggdec "$FILE" -o tmp.wav
|
||||
|
||||
if [ -s tmp.wav ]; then
|
||||
oggenc --downmix -b $SOUND_QUALITY tmp.wav -o tmp.ogg
|
||||
fi
|
||||
|
||||
if [ -s tmp.ogg ]; then
|
||||
SIZE_OLD=`du -k "$FILE" | cut -f1`
|
||||
SIZE_NEW=`du -k "tmp.ogg" | cut -f1`
|
||||
|
||||
if [ $SIZE_NEW -lt $SIZE_OLD ]; then
|
||||
mv tmp.ogg "$FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f tmp.wav tmp.ogg
|
||||
}
|
||||
|
||||
if [ $DECREASE_QUALITY -gt 0 ]; then
|
||||
find assets/data -iname "*.png" | while read f; do convert_image "$f"; done
|
||||
find assets/data -iname "*.jpg" | while read f; do convert_image "$f"; done
|
||||
find assets/data -iname "*.ogg" | while read f; do convert_sound "$f"; done
|
||||
fi
|
||||
|
||||
|
||||
# Copy data directory
|
||||
echo "Copy data directory"
|
||||
cp -a ../data/* assets/data/
|
||||
|
||||
|
||||
# Run optimize_data.sh script
|
||||
if [ $RUN_OPTIMIZE_SCRIPT -gt 0 ]; then
|
||||
echo "Run optimize_data.sh script"
|
||||
sh -c 'cd assets/data; ../../../data/optimize_data.sh'
|
||||
fi
|
||||
|
||||
|
||||
# Generate directories list
|
||||
echo "Generate directories list"
|
||||
find assets/* -type d > assets/directories.txt
|
||||
sed -i s/'.\/assets\/'// assets/directories.txt
|
||||
sed -i s/'assets\/'// assets/directories.txt
|
||||
|
||||
|
||||
# It will be probably ignored by ant, but create it anyway...
|
||||
touch assets/.nomedia
|
||||
|
||||
|
||||
echo "Done."
|
||||
exit 0
|
288
android/make.sh
Executable file
288
android/make.sh
Executable file
@ -0,0 +1,288 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# (C) 2016-2017 Dawid Gan, under the GPLv3
|
||||
#
|
||||
# A script that creates the apk build
|
||||
|
||||
|
||||
export DIRNAME=$(realpath "$(dirname "$0")")
|
||||
|
||||
export NDK_PATH_DEFAULT="$DIRNAME/android-ndk"
|
||||
export SDK_PATH_DEFAULT="$DIRNAME/android-sdk"
|
||||
|
||||
export NDK_TOOLCHAIN_PATH="$DIRNAME/obj/bin"
|
||||
export NDK_BUILD_SCRIPT="$DIRNAME/Android.mk"
|
||||
export PATH="$DIRNAME/obj/bin:$PATH"
|
||||
export CROSS_SYSROOT="$DIRNAME/obj/sysroot"
|
||||
|
||||
#export NDK_CCACHE=ccache
|
||||
export NDK_CPPFLAGS="-O3 -g"
|
||||
|
||||
export NDK_ABI_ARMV7=armeabi-v7a
|
||||
export ARCH_ARMV7=arm
|
||||
export HOST_ARMV7=arm-linux-androideabi
|
||||
export NDK_PLATFORM_ARMV7=android-19
|
||||
|
||||
export NDK_ABI_X86=x86
|
||||
export ARCH_X86=x86
|
||||
export HOST_X86=i686-linux-android
|
||||
export NDK_PLATFORM_X86=android-19
|
||||
|
||||
export NDK_ABI_AARCH64=arm64-v8a
|
||||
export ARCH_AARCH64=arm64
|
||||
export HOST_AARCH64=aarch64-linux-android
|
||||
export NDK_PLATFORM_AARCH64=android-21
|
||||
|
||||
|
||||
# A helper function that checks if error ocurred
|
||||
check_error()
|
||||
{
|
||||
if [ $? -gt 0 ]; then
|
||||
echo "Error ocurred."
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle clean command
|
||||
if [ ! -z "$1" ] && [ "$1" = "clean" ]; then
|
||||
rm -rf bin
|
||||
rm -rf libs
|
||||
rm -rf obj
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check if compilation for different platform has been started before
|
||||
if [ -f "$DIRNAME/obj/compile_arch" ]; then
|
||||
PROJECT_ARCH=$(cat "$DIRNAME/obj/compile_arch")
|
||||
|
||||
if [ -z "$COMPILE_ARCH" ]; then
|
||||
COMPILE_ARCH="$PROJECT_ARCH"
|
||||
elif [ "$PROJECT_ARCH" != "$COMPILE_ARCH" ]; then
|
||||
echo "Error: Compilation for different platform has been already made."
|
||||
echo "Run './make.sh clean' first or set COMPILE_ARCH variable" \
|
||||
"to '$PROJECT_ARCH.'"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$COMPILE_ARCH" ]; then
|
||||
COMPILE_ARCH="armv7"
|
||||
fi
|
||||
|
||||
# Update variables for selected architecture
|
||||
if [ "$COMPILE_ARCH" = "armv7" ]; then
|
||||
export NDK_PLATFORM=$NDK_PLATFORM_ARMV7
|
||||
export NDK_ABI=$NDK_ABI_ARMV7
|
||||
export ARCH=$ARCH_ARMV7
|
||||
export HOST=$HOST_ARMV7
|
||||
elif [ "$COMPILE_ARCH" = "x86" ]; then
|
||||
export NDK_PLATFORM=$NDK_PLATFORM_X86
|
||||
export NDK_ABI=$NDK_ABI_X86
|
||||
export ARCH=$ARCH_X86
|
||||
export HOST=$HOST_X86
|
||||
elif [ "$COMPILE_ARCH" = "aarch64" ]; then
|
||||
export NDK_PLATFORM=$NDK_PLATFORM_AARCH64
|
||||
export NDK_ABI=$NDK_ABI_AARCH64
|
||||
export ARCH=$ARCH_AARCH64
|
||||
export HOST=$HOST_AARCH64
|
||||
else
|
||||
echo "Unknow COMPILE_ARCH: $COMPILE_ARCH. Possible values are: " \
|
||||
"armv7, aarch64, x86"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check if we have access to the Android NDK and SDK
|
||||
if [ -z "$NDK_PATH" ]; then
|
||||
export NDK_PATH="$NDK_PATH_DEFAULT"
|
||||
fi
|
||||
|
||||
if [ -z "$SDK_PATH" ]; then
|
||||
export SDK_PATH="$SDK_PATH_DEFAULT"
|
||||
fi
|
||||
|
||||
NDK_PATH=$(realpath "$NDK_PATH")
|
||||
SDK_PATH=$(realpath "$SDK_PATH")
|
||||
|
||||
if [ ! -d "$NDK_PATH" ]; then
|
||||
echo "Error: Couldn't find $NDK_PATH directory. Please create a symlink" \
|
||||
"to your Android NDK installation in the $NDK_PATH_DEFAULT or set" \
|
||||
"proper path in the NDK_PATH variable"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! -d "$SDK_PATH" ]; then
|
||||
echo "Error: Couldn't find $SDK_PATH directory. Please create a symlink" \
|
||||
"to your Android SDK installation in the $SDK_PATH_DEFAULT or set" \
|
||||
"proper path in the SDK_PATH variable"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Standalone toolchain
|
||||
if [ ! -f "$DIRNAME/obj/make_standalone_toolchain.stamp" ]; then
|
||||
echo "Creating standalone toolchain"
|
||||
rm -rf "$DIRNAME/obj"
|
||||
${NDK_PATH}/build/tools/make-standalone-toolchain.sh \
|
||||
--platform=$NDK_PLATFORM \
|
||||
--install-dir="$DIRNAME/obj/" \
|
||||
--arch=$ARCH
|
||||
check_error
|
||||
touch "$DIRNAME/obj/make_standalone_toolchain.stamp"
|
||||
echo $COMPILE_ARCH > "$DIRNAME/obj/compile_arch"
|
||||
fi
|
||||
|
||||
# Freetype
|
||||
if [ ! -f "$DIRNAME/obj/freetype.stamp" ]; then
|
||||
echo "Compiling freetype"
|
||||
mkdir -p "$DIRNAME/obj/freetype"
|
||||
cp -a -f "$DIRNAME/../lib/freetype/"* "$DIRNAME/obj/freetype"
|
||||
|
||||
cd "$DIRNAME/obj/freetype"
|
||||
./configure --host=$HOST \
|
||||
--without-zlib \
|
||||
--without-png \
|
||||
--without-harfbuzz &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/freetype.stamp"
|
||||
fi
|
||||
|
||||
# Zlib
|
||||
if [ ! -f "$DIRNAME/obj/zlib.stamp" ]; then
|
||||
echo "Compiling zlib"
|
||||
mkdir -p "$DIRNAME/obj/zlib"
|
||||
cp -a -f "$DIRNAME/../lib/zlib/"* "$DIRNAME/obj/zlib"
|
||||
|
||||
cd "$DIRNAME/obj/zlib"
|
||||
cmake . -DCMAKE_TOOLCHAIN_FILE=../../../cmake/Toolchain-android.cmake \
|
||||
-DHOST=$HOST &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/zlib.stamp"
|
||||
fi
|
||||
|
||||
# Libpng
|
||||
if [ ! -f "$DIRNAME/obj/libpng.stamp" ]; then
|
||||
echo "Compiling libpng"
|
||||
mkdir -p "$DIRNAME/obj/libpng"
|
||||
mkdir -p "$DIRNAME/obj/libpng/lib"
|
||||
cp -a -f "$DIRNAME/../lib/libpng/"* "$DIRNAME/obj/libpng"
|
||||
|
||||
cd "$DIRNAME/obj/libpng"
|
||||
cmake . -DCMAKE_TOOLCHAIN_FILE=../../../cmake/Toolchain-android.cmake \
|
||||
-DHOST=$HOST \
|
||||
-DZLIB_LIBRARY="$DIRNAME/obj/zlib/libz.a" \
|
||||
-DZLIB_INCLUDE_DIR="$DIRNAME/obj/zlib/" \
|
||||
-DPNG_TESTS=0 &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/libpng.stamp"
|
||||
fi
|
||||
|
||||
# Openal
|
||||
if [ ! -f "$DIRNAME/obj/openal.stamp" ]; then
|
||||
echo "Compiling openal"
|
||||
mkdir -p "$DIRNAME/obj/openal"
|
||||
cp -a -f "$DIRNAME/../lib/openal/"* "$DIRNAME/obj/openal"
|
||||
|
||||
cd "$DIRNAME/obj/openal"
|
||||
cmake . -DCMAKE_TOOLCHAIN_FILE=../../../cmake/Toolchain-android.cmake \
|
||||
-DHOST=$HOST \
|
||||
-DALSOFT_UTILS=0 \
|
||||
-DALSOFT_EXAMPLES=0 \
|
||||
-DALSOFT_TESTS=0 \
|
||||
-DLIBTYPE=STATIC &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/openal.stamp"
|
||||
fi
|
||||
|
||||
# OpenSSL
|
||||
if [ ! -f "$DIRNAME/obj/openssl.stamp" ]; then
|
||||
echo "Compiling openssl"
|
||||
mkdir -p "$DIRNAME/obj/openssl"
|
||||
cp -a -f "$DIRNAME/../lib/openssl/"* "$DIRNAME/obj/openssl"
|
||||
|
||||
cd "$DIRNAME/obj/openssl"
|
||||
./Configure android --cross-compile-prefix="$HOST-"
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/openssl.stamp"
|
||||
fi
|
||||
|
||||
# Curl
|
||||
if [ ! -f "$DIRNAME/obj/curl.stamp" ]; then
|
||||
echo "Compiling curl"
|
||||
mkdir -p "$DIRNAME/obj/curl"
|
||||
cp -a -f "$DIRNAME/../lib/curl/"* "$DIRNAME/obj/curl"
|
||||
|
||||
cd "$DIRNAME/obj/curl"
|
||||
CPPFLAGS="-I$DIRNAME/obj/openssl/include $CPPFLAGS" \
|
||||
LDFLAGS="-L$DIRNAME/obj/openssl/ $LDFLAGS" \
|
||||
./configure --host=$HOST \
|
||||
--with-ssl \
|
||||
--disable-shared \
|
||||
--enable-static \
|
||||
--enable-threaded-resolver &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/curl.stamp"
|
||||
fi
|
||||
|
||||
# Jpeglib
|
||||
if [ ! -f "$DIRNAME/obj/jpeglib.stamp" ]; then
|
||||
echo "Compiling jpeglib"
|
||||
mkdir -p "$DIRNAME/obj/jpeglib"
|
||||
cp -a -f "$DIRNAME/../lib/jpeglib/"* "$DIRNAME/obj/jpeglib"
|
||||
|
||||
cd "$DIRNAME/obj/jpeglib"
|
||||
cmake . -DCMAKE_TOOLCHAIN_FILE=../../../cmake/Toolchain-android.cmake \
|
||||
-DHOST=$HOST &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/jpeglib.stamp"
|
||||
fi
|
||||
|
||||
# Libogg
|
||||
if [ ! -f "$DIRNAME/obj/libogg.stamp" ]; then
|
||||
echo "Compiling libogg"
|
||||
mkdir -p "$DIRNAME/obj/libogg"
|
||||
cp -a -f "$DIRNAME/../lib/libogg/"* "$DIRNAME/obj/libogg"
|
||||
|
||||
cd "$DIRNAME/obj/libogg"
|
||||
./configure --host=$HOST &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/libogg.stamp"
|
||||
fi
|
||||
|
||||
# Libvorbis
|
||||
if [ ! -f "$DIRNAME/obj/libvorbis.stamp" ]; then
|
||||
echo "Compiling libvorbis"
|
||||
mkdir -p "$DIRNAME/obj/libvorbis"
|
||||
cp -a -f "$DIRNAME/../lib/libvorbis/"* "$DIRNAME/obj/libvorbis"
|
||||
|
||||
cd "$DIRNAME/obj/libvorbis"
|
||||
CPPFLAGS="-I$DIRNAME/obj/libogg/include $CPPFLAGS" \
|
||||
LDFLAGS="-L$DIRNAME/obj/libogg/src/.libs $LDFLAGS" \
|
||||
./configure --host=$HOST &&
|
||||
make $@
|
||||
check_error
|
||||
touch "$DIRNAME/obj/libvorbis.stamp"
|
||||
fi
|
||||
|
||||
# STK
|
||||
echo "Compiling STK"
|
||||
cd "$DIRNAME"
|
||||
${NDK_PATH}/ndk-build $@ \
|
||||
APP_BUILD_SCRIPT="$NDK_BUILD_SCRIPT" \
|
||||
APP_ABI="$NDK_ABI" \
|
||||
APP_PLATFORM="$NDK_PLATFORM" \
|
||||
APP_CPPFLAGS="$NDK_CPPFLAGS" \
|
||||
APP_STL=gnustl_static
|
||||
|
||||
check_error
|
||||
|
||||
# Build apk
|
||||
echo "Building APK"
|
||||
ant debug -Dsdk.dir="$SDK_PATH" -Dtarget=$NDK_PLATFORM
|
||||
check_error
|
BIN
android/res/drawable-hdpi/icon.png
Normal file
BIN
android/res/drawable-hdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
BIN
android/res/drawable-mdpi/icon.png
Normal file
BIN
android/res/drawable-mdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
android/res/drawable-xhdpi/icon.png
Normal file
BIN
android/res/drawable-xhdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
BIN
android/res/drawable-xxhdpi/icon.png
Normal file
BIN
android/res/drawable-xxhdpi/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
android/res/drawable/icon.png
Normal file
BIN
android/res/drawable/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
4
android/res/values/strings.xml
Normal file
4
android/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">SuperTuxKart</string>
|
||||
</resources>
|
32
cmake/Toolchain-android.cmake
Normal file
32
cmake/Toolchain-android.cmake
Normal file
@ -0,0 +1,32 @@
|
||||
# Cross-compiling requires CMake 2.6 or newer. Example:
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile-Android.txt -DHOST=arm-linux-androideabi
|
||||
# Where 'arm-linux-androideabi' is the host prefix for the cross-compiler. If
|
||||
# you already have a toolchain file setup, you may use that instead of this
|
||||
# file. Make sure to set CMAKE_FIND_ROOT_PATH to where the NDK toolchain was
|
||||
# installed (e.g. "$ENV{HOME}/toolchains/arm-linux-androideabi-r10c-21").
|
||||
|
||||
# the name of the target operating system
|
||||
SET(CMAKE_SYSTEM_NAME Linux)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
SET(CMAKE_C_COMPILER "${HOST}-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "${HOST}-g++")
|
||||
SET(CMAKE_RC_COMPILER "${HOST}-windres")
|
||||
|
||||
# here is the target environment located
|
||||
SET(CMAKE_FIND_ROOT_PATH $ENV{NDK_TOOLCHAIN_PATH})
|
||||
|
||||
# here is where stuff gets installed to
|
||||
SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
|
||||
|
||||
# adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
# programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
# set env vars so that pkg-config will look in the appropriate directory for
|
||||
# .pc files (as there seems to be no way to force using ${HOST}-pkg-config)
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
|
||||
set(ENV{PKG_CONFIG_PATH} "")
|
@ -112,6 +112,7 @@ source/Irrlicht/CImageLoaderPNG.cpp
|
||||
source/Irrlicht/CImageWriterBMP.cpp
|
||||
source/Irrlicht/CImageWriterJPG.cpp
|
||||
source/Irrlicht/CImageWriterPNG.cpp
|
||||
source/Irrlicht/CIrrDeviceAndroid.cpp
|
||||
source/Irrlicht/CIrrDeviceConsole.cpp
|
||||
source/Irrlicht/CIrrDeviceFB.cpp
|
||||
source/Irrlicht/CIrrDeviceLinux.cpp
|
||||
@ -243,6 +244,7 @@ source/Irrlicht/CImageLoaderPNG.h
|
||||
source/Irrlicht/CImageWriterBMP.h
|
||||
source/Irrlicht/CImageWriterJPG.h
|
||||
source/Irrlicht/CImageWriterPNG.h
|
||||
source/Irrlicht/CIrrDeviceAndroid.h
|
||||
source/Irrlicht/CIrrDeviceConsole.h
|
||||
source/Irrlicht/CIrrDeviceFB.h
|
||||
source/Irrlicht/CIrrDeviceLinux.h
|
||||
|
963
lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp
Normal file
963
lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp
Normal file
@ -0,0 +1,963 @@
|
||||
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
||||
// Copyright (C) 2007-2011 Christian Stehno
|
||||
// Copyright (C) 2016-2017 Dawid Gan
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CIrrDeviceAndroid.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include <assert.h>
|
||||
#include "os.h"
|
||||
#include "CFileSystem.h"
|
||||
#include "COGLES2Driver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
IVideoDriver* createOGLES1Driver(const SIrrlichtCreationParameters& params,
|
||||
video::SExposedVideoData& data, io::IFileSystem* io);
|
||||
|
||||
IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
|
||||
video::SExposedVideoData& data, io::IFileSystem* io);
|
||||
}
|
||||
}
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
// These variables must be global. Otherwise initialization will reach infinite
|
||||
// loop after creating the device second time (i.e. the NULL driver and then
|
||||
// GLES2 driver). We get initialization events from Android only once.
|
||||
bool CIrrDeviceAndroid::IsPaused = true;
|
||||
bool CIrrDeviceAndroid::IsFocused = false;
|
||||
bool CIrrDeviceAndroid::IsStarted = false;
|
||||
bool CIrrDeviceAndroid::IsClosing = false;
|
||||
|
||||
//! constructor
|
||||
CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param)
|
||||
: CIrrDeviceStub(param),
|
||||
Accelerometer(0),
|
||||
Gyroscope(0),
|
||||
IsMousePressed(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CIrrDeviceAndroid");
|
||||
#endif
|
||||
|
||||
Android = (android_app *)(param.PrivateData);
|
||||
|
||||
IsClosing = Android->destroyRequested;
|
||||
|
||||
Android->userData = this;
|
||||
Android->onAppCmd = handleAndroidCommand;
|
||||
Android->onInputEvent = handleInput;
|
||||
|
||||
SensorManager = ASensorManager_getInstance();
|
||||
SensorEventQueue = ASensorManager_createEventQueue(SensorManager,
|
||||
Android->looper, LOOPER_ID_USER, NULL, NULL);
|
||||
|
||||
ANativeActivity_setWindowFlags(Android->activity,
|
||||
AWINDOW_FLAG_KEEP_SCREEN_ON |
|
||||
AWINDOW_FLAG_FULLSCREEN, 0);
|
||||
|
||||
createKeyMap();
|
||||
|
||||
// Create cursor control
|
||||
CursorControl = new CCursorControl();
|
||||
|
||||
os::Printer::log("Waiting for Android activity window to be created.", ELL_DEBUG);
|
||||
|
||||
while ((!IsStarted || !IsFocused || IsPaused) && !IsClosing)
|
||||
{
|
||||
s32 events = 0;
|
||||
android_poll_source* source = 0;
|
||||
|
||||
s32 id = ALooper_pollAll(-1, NULL, &events, (void**)&source);
|
||||
|
||||
if (id >=0 && source != NULL)
|
||||
{
|
||||
source->process(Android, source);
|
||||
}
|
||||
}
|
||||
|
||||
assert(Android->window);
|
||||
os::Printer::log("Done", ELL_DEBUG);
|
||||
|
||||
ExposedVideoData.OGLESAndroid.Window = Android->window;
|
||||
|
||||
getVideoModeList();
|
||||
|
||||
createDriver();
|
||||
|
||||
if (VideoDriver)
|
||||
createGUIAndScene();
|
||||
}
|
||||
|
||||
|
||||
CIrrDeviceAndroid::~CIrrDeviceAndroid()
|
||||
{
|
||||
Android->userData = NULL;
|
||||
}
|
||||
|
||||
video::IVideoModeList* CIrrDeviceAndroid::getVideoModeList()
|
||||
{
|
||||
if (Android == NULL || Android->window == NULL)
|
||||
return NULL;
|
||||
|
||||
core::dimension2d<u32> size = core::dimension2d<u32>(
|
||||
ANativeWindow_getWidth(Android->window),
|
||||
ANativeWindow_getHeight(Android->window));
|
||||
|
||||
CreationParams.WindowSize.Width = size.Width;
|
||||
CreationParams.WindowSize.Height = size.Height;
|
||||
|
||||
if (!VideoModeList.getVideoModeCount())
|
||||
{
|
||||
VideoModeList.addMode(size, 32);
|
||||
VideoModeList.setDesktop(32, size);
|
||||
}
|
||||
|
||||
return &VideoModeList;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::createDriver()
|
||||
{
|
||||
// Create the driver.
|
||||
switch(CreationParams.DriverType)
|
||||
{
|
||||
case video::EDT_OGLES1:
|
||||
#ifdef _IRR_COMPILE_WITH_OGLES1_
|
||||
VideoDriver = video::createOGLES1Driver(CreationParams, ExposedVideoData, FileSystem);
|
||||
#else
|
||||
os::Printer::log("No OpenGL ES 1.0 support compiled in.", ELL_ERROR);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case video::EDT_OGLES2:
|
||||
#ifdef _IRR_COMPILE_WITH_OGLES2_
|
||||
VideoDriver = video::createOGLES2Driver(CreationParams, ExposedVideoData, FileSystem);
|
||||
#else
|
||||
os::Printer::log("No OpenGL ES 2.0 support compiled in.", ELL_ERROR);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case video::EDT_NULL:
|
||||
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
|
||||
break;
|
||||
|
||||
default:
|
||||
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::run()
|
||||
{
|
||||
os::Timer::tick();
|
||||
|
||||
while (!IsClosing)
|
||||
{
|
||||
s32 Events = 0;
|
||||
android_poll_source* Source = 0;
|
||||
bool should_run = (IsStarted && IsFocused && !IsPaused) || IsClosing;
|
||||
s32 id = ALooper_pollAll(should_run ? 0 : -1, NULL, &Events,
|
||||
(void**)&Source);
|
||||
|
||||
if (id < 0)
|
||||
break;
|
||||
|
||||
if (Source)
|
||||
{
|
||||
Source->process(Android, Source);
|
||||
}
|
||||
|
||||
// if a sensor has data, we'll process it now.
|
||||
if (id == LOOPER_ID_USER)
|
||||
{
|
||||
ASensorEvent event;
|
||||
while (ASensorEventQueue_getEvents(SensorEventQueue, &event, 1) > 0)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case ASENSOR_TYPE_ACCELEROMETER:
|
||||
SEvent accEvent;
|
||||
accEvent.EventType = EET_ACCELEROMETER_EVENT;
|
||||
accEvent.AccelerometerEvent.X = event.acceleration.x;
|
||||
accEvent.AccelerometerEvent.Y = event.acceleration.y;
|
||||
accEvent.AccelerometerEvent.Z = event.acceleration.z;
|
||||
|
||||
postEventFromUser(accEvent);
|
||||
break;
|
||||
|
||||
case ASENSOR_TYPE_GYROSCOPE:
|
||||
SEvent gyroEvent;
|
||||
gyroEvent.EventType = EET_GYROSCOPE_EVENT;
|
||||
gyroEvent.GyroscopeEvent.X = event.vector.x;
|
||||
gyroEvent.GyroscopeEvent.Y = event.vector.y;
|
||||
gyroEvent.GyroscopeEvent.Z = event.vector.z;
|
||||
|
||||
postEventFromUser(gyroEvent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !IsClosing;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::yield()
|
||||
{
|
||||
struct timespec ts = {0,1};
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::sleep(u32 timeMs, bool pauseTimer)
|
||||
{
|
||||
const bool wasStopped = Timer ? Timer->isStopped() : true;
|
||||
|
||||
struct timespec ts;
|
||||
ts.tv_sec = (time_t) (timeMs / 1000);
|
||||
ts.tv_nsec = (long) (timeMs % 1000) * 1000000;
|
||||
|
||||
if (pauseTimer && !wasStopped)
|
||||
Timer->stop();
|
||||
|
||||
nanosleep(&ts, NULL);
|
||||
|
||||
if (pauseTimer && !wasStopped)
|
||||
Timer->start();
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::setWindowCaption(const wchar_t* text)
|
||||
{
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::present(video::IImage* surface, void* windowId,
|
||||
core::rect<s32>* srcClip)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isWindowActive() const
|
||||
{
|
||||
return (IsFocused && !IsPaused);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isWindowFocused() const
|
||||
{
|
||||
return IsFocused;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isWindowMinimized() const
|
||||
{
|
||||
return IsPaused;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::closeDevice()
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::setResizable(bool resize)
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::minimizeWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::maximizeWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::restoreWindow()
|
||||
{
|
||||
}
|
||||
|
||||
E_DEVICE_TYPE CIrrDeviceAndroid::getType() const
|
||||
{
|
||||
return EIDT_ANDROID;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::handleAndroidCommand(android_app* app, int32_t cmd)
|
||||
{
|
||||
CIrrDeviceAndroid* device = (CIrrDeviceAndroid *)app->userData;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case APP_CMD_SAVE_STATE:
|
||||
os::Printer::log("Android command APP_CMD_SAVE_STATE", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
os::Printer::log("Android command APP_CMD_INIT_WINDOW", ELL_DEBUG);
|
||||
|
||||
if (device != NULL)
|
||||
{
|
||||
device->getExposedVideoData().OGLESAndroid.Window = app->window;
|
||||
|
||||
// If the Android app is resumed, we need to re-create EGL surface
|
||||
// to allow to draw something on it again.
|
||||
if (device->VideoDriver != NULL &&
|
||||
device->CreationParams.DriverType == video::EDT_OGLES2)
|
||||
{
|
||||
video::COGLES2Driver* driver = (video::COGLES2Driver*)(device->VideoDriver);
|
||||
driver->reloadEGLSurface(app->window);
|
||||
}
|
||||
}
|
||||
|
||||
IsStarted = true;
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
os::Printer::log("Android command APP_CMD_TERM_WINDOW", ELL_DEBUG);
|
||||
IsStarted = false;
|
||||
break;
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
os::Printer::log("Android command APP_CMD_GAINED_FOCUS", ELL_DEBUG);
|
||||
IsFocused = true;
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
os::Printer::log("Android command APP_CMD_LOST_FOCUS", ELL_DEBUG);
|
||||
IsFocused = false;
|
||||
break;
|
||||
case APP_CMD_DESTROY:
|
||||
os::Printer::log("Android command APP_CMD_DESTROY", ELL_DEBUG);
|
||||
IsClosing = true;
|
||||
// Make sure that state variables are set to the default state
|
||||
// when the app is destroyed
|
||||
IsPaused = true;
|
||||
IsFocused = false;
|
||||
IsStarted = false;
|
||||
break;
|
||||
case APP_CMD_PAUSE:
|
||||
os::Printer::log("Android command APP_CMD_PAUSE", ELL_DEBUG);
|
||||
IsPaused = true;
|
||||
break;
|
||||
case APP_CMD_RESUME:
|
||||
os::Printer::log("Android command APP_CMD_RESUME", ELL_DEBUG);
|
||||
IsPaused = false;
|
||||
break;
|
||||
case APP_CMD_START:
|
||||
os::Printer::log("Android command APP_CMD_START", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_STOP:
|
||||
os::Printer::log("Android command APP_CMD_STOP", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_WINDOW_RESIZED:
|
||||
os::Printer::log("Android command APP_CMD_WINDOW_RESIZED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_CONFIG_CHANGED:
|
||||
os::Printer::log("Android command APP_CMD_CONFIG_CHANGED", ELL_DEBUG);
|
||||
break;
|
||||
case APP_CMD_LOW_MEMORY:
|
||||
os::Printer::log("Android command APP_CMD_LOW_MEMORY", ELL_DEBUG);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (device != NULL)
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_SYSTEM_EVENT;
|
||||
event.SystemEvent.EventType = ESET_ANDROID_CMD;
|
||||
event.SystemEvent.AndroidCmd.Cmd = cmd;
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
}
|
||||
|
||||
s32 CIrrDeviceAndroid::handleInput(android_app* app, AInputEvent* androidEvent)
|
||||
{
|
||||
CIrrDeviceAndroid* device = (CIrrDeviceAndroid*)app->userData;
|
||||
s32 status = 0;
|
||||
|
||||
if (device == NULL)
|
||||
return status;
|
||||
|
||||
|
||||
switch (AInputEvent_getType(androidEvent))
|
||||
{
|
||||
case AINPUT_EVENT_TYPE_MOTION:
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_TOUCH_INPUT_EVENT;
|
||||
|
||||
s32 eventAction = AMotionEvent_getAction(androidEvent);
|
||||
|
||||
#if 0
|
||||
// Useful for debugging. We might have to pass some of those infos on at some point.
|
||||
// but preferably device independent (so iphone can use same irrlicht flags).
|
||||
int32_t flags = AMotionEvent_getFlags(androidEvent);
|
||||
os::Printer::log("flags: ", core::stringc(flags).c_str(), ELL_DEBUG);
|
||||
int32_t metaState = AMotionEvent_getMetaState(androidEvent);
|
||||
os::Printer::log("metaState: ", core::stringc(metaState).c_str(), ELL_DEBUG);
|
||||
int32_t edgeFlags = AMotionEvent_getEdgeFlags(androidEvent);
|
||||
os::Printer::log("edgeFlags: ", core::stringc(flags).c_str(), ELL_DEBUG);
|
||||
#endif
|
||||
|
||||
bool touchReceived = true;
|
||||
bool simulate_mouse = false;
|
||||
core::position2d<s32> mouse_pos = core::position2d<s32>(0, 0);
|
||||
|
||||
switch (eventAction & AMOTION_EVENT_ACTION_MASK)
|
||||
{
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
event.TouchInput.Event = ETIE_PRESSED_DOWN;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
event.TouchInput.Event = ETIE_MOVED;
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
event.TouchInput.Event = ETIE_LEFT_UP;
|
||||
break;
|
||||
default:
|
||||
touchReceived = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (touchReceived)
|
||||
{
|
||||
s32 count = 1;
|
||||
s32 idx = (eventAction & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
|
||||
AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
// Process all touches for move action.
|
||||
if (event.TouchInput.Event == ETIE_MOVED)
|
||||
{
|
||||
count = AMotionEvent_getPointerCount(androidEvent);
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
for (s32 i = 0; i < count; ++i)
|
||||
{
|
||||
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i + idx);
|
||||
event.TouchInput.X = AMotionEvent_getX(androidEvent, i + idx);
|
||||
event.TouchInput.Y = AMotionEvent_getY(androidEvent, i + idx);
|
||||
|
||||
device->postEventFromUser(event);
|
||||
|
||||
if (event.TouchInput.ID == 0)
|
||||
{
|
||||
simulate_mouse = true;
|
||||
mouse_pos.X = event.TouchInput.X;
|
||||
mouse_pos.Y = event.TouchInput.Y;
|
||||
}
|
||||
}
|
||||
|
||||
status = 1;
|
||||
}
|
||||
|
||||
// Simulate mouse event for first finger on multitouch device.
|
||||
// This allows to click on GUI elements.
|
||||
if (simulate_mouse)
|
||||
{
|
||||
device->CursorControl->setPosition(mouse_pos);
|
||||
|
||||
SEvent irrevent;
|
||||
bool send_event = true;
|
||||
|
||||
switch (event.TouchInput.Event)
|
||||
{
|
||||
case ETIE_PRESSED_DOWN:
|
||||
irrevent.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
|
||||
device->IsMousePressed = true;
|
||||
break;
|
||||
case ETIE_LEFT_UP:
|
||||
irrevent.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
|
||||
device->IsMousePressed = false;
|
||||
break;
|
||||
case ETIE_MOVED:
|
||||
irrevent.MouseInput.Event = EMIE_MOUSE_MOVED;
|
||||
break;
|
||||
default:
|
||||
send_event = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (send_event)
|
||||
{
|
||||
irrevent.MouseInput.Control = false;
|
||||
irrevent.MouseInput.Shift = false;
|
||||
irrevent.MouseInput.ButtonStates = device->IsMousePressed ?
|
||||
irr::EMBSM_LEFT : 0;
|
||||
irrevent.EventType = EET_MOUSE_INPUT_EVENT;
|
||||
irrevent.MouseInput.X = mouse_pos.X;
|
||||
irrevent.MouseInput.Y = mouse_pos.Y;
|
||||
|
||||
device->postEventFromUser(irrevent);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case AINPUT_EVENT_TYPE_KEY:
|
||||
{
|
||||
bool ignore_event = false;
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_KEY_INPUT_EVENT;
|
||||
event.KeyInput.Char = 0;
|
||||
event.KeyInput.PressedDown = false;
|
||||
event.KeyInput.Key = KEY_UNKNOWN;
|
||||
|
||||
int32_t keyCode = AKeyEvent_getKeyCode(androidEvent);
|
||||
int32_t keyAction = AKeyEvent_getAction(androidEvent);
|
||||
int32_t keyMetaState = AKeyEvent_getMetaState(androidEvent);
|
||||
int32_t keyRepeat = AKeyEvent_getRepeatCount(androidEvent);
|
||||
|
||||
if (keyAction == AKEY_EVENT_ACTION_DOWN)
|
||||
{
|
||||
event.KeyInput.PressedDown = true;
|
||||
}
|
||||
else if (keyAction == AKEY_EVENT_ACTION_UP)
|
||||
{
|
||||
event.KeyInput.PressedDown = false;
|
||||
}
|
||||
else if (keyAction == AKEY_EVENT_ACTION_MULTIPLE)
|
||||
{
|
||||
// TODO: Multiple duplicate key events have occurred in a row,
|
||||
// or a complex string is being delivered. The repeat_count
|
||||
// property of the key event contains the number of times the
|
||||
// given key code should be executed.
|
||||
// I guess this might necessary for more complicated i18n key input,
|
||||
// but don't see yet how to handle this correctly.
|
||||
}
|
||||
|
||||
event.KeyInput.Shift = (keyMetaState & AMETA_SHIFT_ON ||
|
||||
keyMetaState & AMETA_SHIFT_LEFT_ON ||
|
||||
keyMetaState & AMETA_SHIFT_RIGHT_ON);
|
||||
|
||||
event.KeyInput.Control = (keyMetaState & AMETA_CTRL_ON ||
|
||||
keyMetaState & AMETA_CTRL_LEFT_ON ||
|
||||
keyMetaState & AMETA_CTRL_RIGHT_ON);
|
||||
|
||||
event.KeyInput.SystemKeyCode = (u32)keyCode;
|
||||
|
||||
if (keyCode >= 0 && (u32)keyCode < device->KeyMap.size())
|
||||