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())
|
||||
{
|
||||
event.KeyInput.Key = device->KeyMap[keyCode];
|
||||
}
|
||||
|
||||
if (event.KeyInput.Key > 0)
|
||||
{
|
||||
device->getKeyChar(event);
|
||||
}
|
||||
|
||||
// Handle an event when back button in pressed just like an escape key
|
||||
// and also avoid repeating the event to avoid some strange behaviour
|
||||
if (event.KeyInput.SystemKeyCode == AKEYCODE_BACK)
|
||||
{
|
||||
status = 1;
|
||||
|
||||
if (event.KeyInput.PressedDown == false || keyRepeat > 0)
|
||||
{
|
||||
ignore_event = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark escape key event as handled by application to avoid receiving
|
||||
// AKEYCODE_BACK key event
|
||||
if (event.KeyInput.SystemKeyCode == AKEYCODE_ESCAPE)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (!ignore_event)
|
||||
{
|
||||
device->postEventFromUser(event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
video::SExposedVideoData& CIrrDeviceAndroid::getExposedVideoData()
|
||||
{
|
||||
return ExposedVideoData;
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::createKeyMap()
|
||||
{
|
||||
KeyMap.set_used(223);
|
||||
|
||||
KeyMap[0] = KEY_UNKNOWN; // AKEYCODE_UNKNOWN
|
||||
KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT
|
||||
KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT
|
||||
KeyMap[3] = KEY_HOME; // AKEYCODE_HOME
|
||||
KeyMap[4] = KEY_ESCAPE; // AKEYCODE_BACK
|
||||
KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL
|
||||
KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL
|
||||
KeyMap[7] = KEY_KEY_0; // AKEYCODE_0
|
||||
KeyMap[8] = KEY_KEY_1; // AKEYCODE_1
|
||||
KeyMap[9] = KEY_KEY_2; // AKEYCODE_2
|
||||
KeyMap[10] = KEY_KEY_3; // AKEYCODE_3
|
||||
KeyMap[11] = KEY_KEY_4; // AKEYCODE_4
|
||||
KeyMap[12] = KEY_KEY_5; // AKEYCODE_5
|
||||
KeyMap[13] = KEY_KEY_6; // AKEYCODE_6
|
||||
KeyMap[14] = KEY_KEY_7; // AKEYCODE_7
|
||||
KeyMap[15] = KEY_KEY_8; // AKEYCODE_8
|
||||
KeyMap[16] = KEY_KEY_9; // AKEYCODE_9
|
||||
KeyMap[17] = KEY_UNKNOWN; // AKEYCODE_STAR
|
||||
KeyMap[18] = KEY_UNKNOWN; // AKEYCODE_POUND
|
||||
KeyMap[19] = KEY_UP; // AKEYCODE_DPAD_UP
|
||||
KeyMap[20] = KEY_DOWN; // AKEYCODE_DPAD_DOWN
|
||||
KeyMap[21] = KEY_LEFT; // AKEYCODE_DPAD_LEFT
|
||||
KeyMap[22] = KEY_RIGHT; // AKEYCODE_DPAD_RIGHT
|
||||
KeyMap[23] = KEY_SELECT; // AKEYCODE_DPAD_CENTER
|
||||
KeyMap[24] = KEY_VOLUME_DOWN; // AKEYCODE_VOLUME_UP
|
||||
KeyMap[25] = KEY_VOLUME_UP; // AKEYCODE_VOLUME_DOWN
|
||||
KeyMap[26] = KEY_UNKNOWN; // AKEYCODE_POWER
|
||||
KeyMap[27] = KEY_UNKNOWN; // AKEYCODE_CAMERA
|
||||
KeyMap[28] = KEY_CLEAR; // AKEYCODE_CLEAR
|
||||
KeyMap[29] = KEY_KEY_A; // AKEYCODE_A
|
||||
KeyMap[30] = KEY_KEY_B; // AKEYCODE_B
|
||||
KeyMap[31] = KEY_KEY_C; // AKEYCODE_C
|
||||
KeyMap[32] = KEY_KEY_D; // AKEYCODE_D
|
||||
KeyMap[33] = KEY_KEY_E; // AKEYCODE_E
|
||||
KeyMap[34] = KEY_KEY_F; // AKEYCODE_F
|
||||
KeyMap[35] = KEY_KEY_G; // AKEYCODE_G
|
||||
KeyMap[36] = KEY_KEY_H; // AKEYCODE_H
|
||||
KeyMap[37] = KEY_KEY_I; // AKEYCODE_I
|
||||
KeyMap[38] = KEY_KEY_J; // AKEYCODE_J
|
||||
KeyMap[39] = KEY_KEY_K; // AKEYCODE_K
|
||||
KeyMap[40] = KEY_KEY_L; // AKEYCODE_L
|
||||
KeyMap[41] = KEY_KEY_M; // AKEYCODE_M
|
||||
KeyMap[42] = KEY_KEY_N; // AKEYCODE_N
|
||||
KeyMap[43] = KEY_KEY_O; // AKEYCODE_O
|
||||
KeyMap[44] = KEY_KEY_P; // AKEYCODE_P
|
||||
KeyMap[45] = KEY_KEY_Q; // AKEYCODE_Q
|
||||
KeyMap[46] = KEY_KEY_R; // AKEYCODE_R
|
||||
KeyMap[47] = KEY_KEY_S; // AKEYCODE_S
|
||||
KeyMap[48] = KEY_KEY_T; // AKEYCODE_T
|
||||
KeyMap[49] = KEY_KEY_U; // AKEYCODE_U
|
||||
KeyMap[50] = KEY_KEY_V; // AKEYCODE_V
|
||||
KeyMap[51] = KEY_KEY_W; // AKEYCODE_W
|
||||
KeyMap[52] = KEY_KEY_X; // AKEYCODE_X
|
||||
KeyMap[53] = KEY_KEY_Y; // AKEYCODE_Y
|
||||
KeyMap[54] = KEY_KEY_Z; // AKEYCODE_Z
|
||||
KeyMap[55] = KEY_COMMA; // AKEYCODE_COMMA
|
||||
KeyMap[56] = KEY_PERIOD; // AKEYCODE_PERIOD
|
||||
KeyMap[57] = KEY_MENU; // AKEYCODE_ALT_LEFT
|
||||
KeyMap[58] = KEY_MENU; // AKEYCODE_ALT_RIGHT
|
||||
KeyMap[59] = KEY_LSHIFT; // AKEYCODE_SHIFT_LEFT
|
||||
KeyMap[60] = KEY_RSHIFT; // AKEYCODE_SHIFT_RIGHT
|
||||
KeyMap[61] = KEY_TAB; // AKEYCODE_TAB
|
||||
KeyMap[62] = KEY_SPACE; // AKEYCODE_SPACE
|
||||
KeyMap[63] = KEY_UNKNOWN; // AKEYCODE_SYM
|
||||
KeyMap[64] = KEY_UNKNOWN; // AKEYCODE_EXPLORER
|
||||
KeyMap[65] = KEY_UNKNOWN; // AKEYCODE_ENVELOPE
|
||||
KeyMap[66] = KEY_RETURN; // AKEYCODE_ENTER
|
||||
KeyMap[67] = KEY_BACK; // AKEYCODE_DEL
|
||||
KeyMap[68] = KEY_OEM_3; // AKEYCODE_GRAVE
|
||||
KeyMap[69] = KEY_MINUS; // AKEYCODE_MINUS
|
||||
KeyMap[70] = KEY_UNKNOWN; // AKEYCODE_EQUALS
|
||||
KeyMap[71] = KEY_UNKNOWN; // AKEYCODE_LEFT_BRACKET
|
||||
KeyMap[72] = KEY_UNKNOWN; // AKEYCODE_RIGHT_BRACKET
|
||||
KeyMap[73] = KEY_UNKNOWN; // AKEYCODE_BACKSLASH
|
||||
KeyMap[74] = KEY_UNKNOWN; // AKEYCODE_SEMICOLON
|
||||
KeyMap[75] = KEY_UNKNOWN; // AKEYCODE_APOSTROPHE
|
||||
KeyMap[76] = KEY_UNKNOWN; // AKEYCODE_SLASH
|
||||
KeyMap[77] = KEY_UNKNOWN; // AKEYCODE_AT
|
||||
KeyMap[78] = KEY_UNKNOWN; // AKEYCODE_NUM
|
||||
KeyMap[79] = KEY_UNKNOWN; // AKEYCODE_HEADSETHOOK
|
||||
KeyMap[80] = KEY_UNKNOWN; // AKEYCODE_FOCUS (*Camera* focus)
|
||||
KeyMap[81] = KEY_PLUS; // AKEYCODE_PLUS
|
||||
KeyMap[82] = KEY_MENU; // AKEYCODE_MENU
|
||||
KeyMap[83] = KEY_UNKNOWN; // AKEYCODE_NOTIFICATION
|
||||
KeyMap[84] = KEY_UNKNOWN; // AKEYCODE_SEARCH
|
||||
KeyMap[85] = KEY_MEDIA_PLAY_PAUSE; // AKEYCODE_MEDIA_PLAY_PAUSE
|
||||
KeyMap[86] = KEY_MEDIA_STOP; // AKEYCODE_MEDIA_STOP
|
||||
KeyMap[87] = KEY_MEDIA_NEXT_TRACK; // AKEYCODE_MEDIA_NEXT
|
||||
KeyMap[88] = KEY_MEDIA_PREV_TRACK; // AKEYCODE_MEDIA_PREVIOUS
|
||||
KeyMap[89] = KEY_UNKNOWN; // AKEYCODE_MEDIA_REWIND
|
||||
KeyMap[90] = KEY_UNKNOWN; // AKEYCODE_MEDIA_FAST_FORWARD
|
||||
KeyMap[91] = KEY_VOLUME_MUTE; // AKEYCODE_MUTE
|
||||
KeyMap[92] = KEY_PRIOR; // AKEYCODE_PAGE_UP
|
||||
KeyMap[93] = KEY_NEXT; // AKEYCODE_PAGE_DOWN
|
||||
KeyMap[94] = KEY_UNKNOWN; // AKEYCODE_PICTSYMBOLS
|
||||
KeyMap[95] = KEY_UNKNOWN; // AKEYCODE_SWITCH_CHARSET
|
||||
|
||||
// following look like controller inputs
|
||||
KeyMap[96] = KEY_UNKNOWN; // AKEYCODE_BUTTON_A
|
||||
KeyMap[97] = KEY_UNKNOWN; // AKEYCODE_BUTTON_B
|
||||
KeyMap[98] = KEY_UNKNOWN; // AKEYCODE_BUTTON_C
|
||||
KeyMap[99] = KEY_UNKNOWN; // AKEYCODE_BUTTON_X
|
||||
KeyMap[100] = KEY_UNKNOWN; // AKEYCODE_BUTTON_Y
|
||||
KeyMap[101] = KEY_UNKNOWN; // AKEYCODE_BUTTON_Z
|
||||
KeyMap[102] = KEY_UNKNOWN; // AKEYCODE_BUTTON_L1
|
||||
KeyMap[103] = KEY_UNKNOWN; // AKEYCODE_BUTTON_R1
|
||||
KeyMap[104] = KEY_UNKNOWN; // AKEYCODE_BUTTON_L2
|
||||
KeyMap[105] = KEY_UNKNOWN; // AKEYCODE_BUTTON_R2
|
||||
KeyMap[106] = KEY_UNKNOWN; // AKEYCODE_BUTTON_THUMBL
|
||||
KeyMap[107] = KEY_UNKNOWN; // AKEYCODE_BUTTON_THUMBR
|
||||
KeyMap[108] = KEY_UNKNOWN; // AKEYCODE_BUTTON_START
|
||||
KeyMap[109] = KEY_UNKNOWN; // AKEYCODE_BUTTON_SELECT
|
||||
KeyMap[110] = KEY_UNKNOWN; // AKEYCODE_BUTTON_MODE
|
||||
|
||||
KeyMap[111] = KEY_ESCAPE; // AKEYCODE_ESCAPE
|
||||
KeyMap[112] = KEY_DELETE; // AKEYCODE_FORWARD_DEL
|
||||
KeyMap[113] = KEY_CONTROL; // AKEYCODE_CTRL_LEFT
|
||||
KeyMap[114] = KEY_CONTROL; // AKEYCODE_CTRL_RIGHT
|
||||
KeyMap[115] = KEY_CAPITAL; // AKEYCODE_CAPS_LOCK
|
||||
KeyMap[116] = KEY_SCROLL; // AKEYCODE_SCROLL_LOCK
|
||||
KeyMap[117] = KEY_UNKNOWN; // AKEYCODE_META_LEFT
|
||||
KeyMap[118] = KEY_UNKNOWN; // AKEYCODE_META_RIGHT
|
||||
KeyMap[119] = KEY_UNKNOWN; // AKEYCODE_FUNCTION
|
||||
KeyMap[120] = KEY_SNAPSHOT; // AKEYCODE_SYSRQ
|
||||
KeyMap[121] = KEY_PAUSE; // AKEYCODE_BREAK
|
||||
KeyMap[122] = KEY_HOME; // AKEYCODE_MOVE_HOME
|
||||
KeyMap[123] = KEY_END; // AKEYCODE_MOVE_END
|
||||
KeyMap[124] = KEY_INSERT; // AKEYCODE_INSERT
|
||||
KeyMap[125] = KEY_UNKNOWN; // AKEYCODE_FORWARD
|
||||
KeyMap[126] = KEY_PLAY; // AKEYCODE_MEDIA_PLAY
|
||||
KeyMap[127] = KEY_MEDIA_PLAY_PAUSE; // AKEYCODE_MEDIA_PAUSE
|
||||
KeyMap[128] = KEY_UNKNOWN; // AKEYCODE_MEDIA_CLOSE
|
||||
KeyMap[129] = KEY_UNKNOWN; // AKEYCODE_MEDIA_EJECT
|
||||
KeyMap[130] = KEY_UNKNOWN; // AKEYCODE_MEDIA_RECORD
|
||||
KeyMap[131] = KEY_F1; // AKEYCODE_F1
|
||||
KeyMap[132] = KEY_F2; // AKEYCODE_F2
|
||||
KeyMap[133] = KEY_F3; // AKEYCODE_F3
|
||||
KeyMap[134] = KEY_F4; // AKEYCODE_F4
|
||||
KeyMap[135] = KEY_F5; // AKEYCODE_F5
|
||||
KeyMap[136] = KEY_F6; // AKEYCODE_F6
|
||||
KeyMap[137] = KEY_F7; // AKEYCODE_F7
|
||||
KeyMap[138] = KEY_F8; // AKEYCODE_F8
|
||||
KeyMap[139] = KEY_F9; // AKEYCODE_F9
|
||||
KeyMap[140] = KEY_F10; // AKEYCODE_F10
|
||||
KeyMap[141] = KEY_F11; // AKEYCODE_F11
|
||||
KeyMap[142] = KEY_F12; // AKEYCODE_F12
|
||||
KeyMap[143] = KEY_NUMLOCK; // AKEYCODE_NUM_LOCK
|
||||
KeyMap[144] = KEY_NUMPAD0; // AKEYCODE_NUMPAD_0
|
||||
KeyMap[145] = KEY_NUMPAD1; // AKEYCODE_NUMPAD_1
|
||||
KeyMap[146] = KEY_NUMPAD2; // AKEYCODE_NUMPAD_2
|
||||
KeyMap[147] = KEY_NUMPAD3; // AKEYCODE_NUMPAD_3
|
||||
KeyMap[148] = KEY_NUMPAD4; // AKEYCODE_NUMPAD_4
|
||||
KeyMap[149] = KEY_NUMPAD5; // AKEYCODE_NUMPAD_5
|
||||
KeyMap[150] = KEY_NUMPAD6; // AKEYCODE_NUMPAD_6
|
||||
KeyMap[151] = KEY_NUMPAD7; // AKEYCODE_NUMPAD_7
|
||||
KeyMap[152] = KEY_NUMPAD8; // AKEYCODE_NUMPAD_8
|
||||
KeyMap[153] = KEY_NUMPAD9; // AKEYCODE_NUMPAD_9
|
||||
KeyMap[154] = KEY_DIVIDE; // AKEYCODE_NUMPAD_DIVIDE
|
||||
KeyMap[155] = KEY_MULTIPLY; // AKEYCODE_NUMPAD_MULTIPLY
|
||||
KeyMap[156] = KEY_SUBTRACT; // AKEYCODE_NUMPAD_SUBTRACT
|
||||
KeyMap[157] = KEY_ADD; // AKEYCODE_NUMPAD_ADD
|
||||
KeyMap[158] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_DOT
|
||||
KeyMap[159] = KEY_COMMA; // AKEYCODE_NUMPAD_COMMA
|
||||
KeyMap[160] = KEY_RETURN; // AKEYCODE_NUMPAD_ENTER
|
||||
KeyMap[161] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_EQUALS
|
||||
KeyMap[162] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_LEFT_PAREN
|
||||
KeyMap[163] = KEY_UNKNOWN; // AKEYCODE_NUMPAD_RIGHT_PAREN
|
||||
KeyMap[164] = KEY_VOLUME_MUTE; // AKEYCODE_VOLUME_MUTE
|
||||
KeyMap[165] = KEY_UNKNOWN; // AKEYCODE_INFO
|
||||
KeyMap[166] = KEY_UNKNOWN; // AKEYCODE_CHANNEL_UP
|
||||
KeyMap[167] = KEY_UNKNOWN; // AKEYCODE_CHANNEL_DOWN
|
||||
KeyMap[168] = KEY_ZOOM; // AKEYCODE_ZOOM_IN
|
||||
KeyMap[169] = KEY_UNKNOWN; // AKEYCODE_ZOOM_OUT
|
||||
KeyMap[170] = KEY_UNKNOWN; // AKEYCODE_TV
|
||||
KeyMap[171] = KEY_UNKNOWN; // AKEYCODE_WINDOW
|
||||
KeyMap[172] = KEY_UNKNOWN; // AKEYCODE_GUIDE
|
||||
KeyMap[173] = KEY_UNKNOWN; // AKEYCODE_DVR
|
||||
KeyMap[174] = KEY_UNKNOWN; // AKEYCODE_BOOKMARK
|
||||
KeyMap[175] = KEY_UNKNOWN; // AKEYCODE_CAPTIONS
|
||||
KeyMap[176] = KEY_UNKNOWN; // AKEYCODE_SETTINGS
|
||||
KeyMap[177] = KEY_UNKNOWN; // AKEYCODE_TV_POWER
|
||||
KeyMap[178] = KEY_UNKNOWN; // AKEYCODE_TV_INPUT
|
||||
KeyMap[179] = KEY_UNKNOWN; // AKEYCODE_STB_POWER
|
||||
KeyMap[180] = KEY_UNKNOWN; // AKEYCODE_STB_INPUT
|
||||
KeyMap[181] = KEY_UNKNOWN; // AKEYCODE_AVR_POWER
|
||||
KeyMap[182] = KEY_UNKNOWN; // AKEYCODE_AVR_INPUT
|
||||
KeyMap[183] = KEY_UNKNOWN; // AKEYCODE_PROG_RED
|
||||
KeyMap[184] = KEY_UNKNOWN; // AKEYCODE_PROG_GREEN
|
||||
KeyMap[185] = KEY_UNKNOWN; // AKEYCODE_PROG_YELLOW
|
||||
KeyMap[186] = KEY_UNKNOWN; // AKEYCODE_PROG_BLUE
|
||||
KeyMap[187] = KEY_UNKNOWN; // AKEYCODE_APP_SWITCH
|
||||
KeyMap[188] = KEY_UNKNOWN; // AKEYCODE_BUTTON_1
|
||||
KeyMap[189] = KEY_UNKNOWN; // AKEYCODE_BUTTON_2
|
||||
KeyMap[190] = KEY_UNKNOWN; // AKEYCODE_BUTTON_3
|
||||
KeyMap[191] = KEY_UNKNOWN; // AKEYCODE_BUTTON_4
|
||||
KeyMap[192] = KEY_UNKNOWN; // AKEYCODE_BUTTON_5
|
||||
KeyMap[193] = KEY_UNKNOWN; // AKEYCODE_BUTTON_6
|
||||
KeyMap[194] = KEY_UNKNOWN; // AKEYCODE_BUTTON_7
|
||||
KeyMap[195] = KEY_UNKNOWN; // AKEYCODE_BUTTON_8
|
||||
KeyMap[196] = KEY_UNKNOWN; // AKEYCODE_BUTTON_9
|
||||
KeyMap[197] = KEY_UNKNOWN; // AKEYCODE_BUTTON_10
|
||||
KeyMap[198] = KEY_UNKNOWN; // AKEYCODE_BUTTON_11
|
||||
KeyMap[199] = KEY_UNKNOWN; // AKEYCODE_BUTTON_12
|
||||
KeyMap[200] = KEY_UNKNOWN; // AKEYCODE_BUTTON_13
|
||||
KeyMap[201] = KEY_UNKNOWN; // AKEYCODE_BUTTON_14
|
||||
KeyMap[202] = KEY_UNKNOWN; // AKEYCODE_BUTTON_15
|
||||
KeyMap[203] = KEY_UNKNOWN; // AKEYCODE_BUTTON_16
|
||||
KeyMap[204] = KEY_UNKNOWN; // AKEYCODE_LANGUAGE_SWITCH
|
||||
KeyMap[205] = KEY_UNKNOWN; // AKEYCODE_MANNER_MODE
|
||||
KeyMap[206] = KEY_UNKNOWN; // AKEYCODE_3D_MODE
|
||||
KeyMap[207] = KEY_UNKNOWN; // AKEYCODE_CONTACTS
|
||||
KeyMap[208] = KEY_UNKNOWN; // AKEYCODE_CALENDAR
|
||||
KeyMap[209] = KEY_UNKNOWN; // AKEYCODE_MUSIC
|
||||
KeyMap[210] = KEY_UNKNOWN; // AKEYCODE_CALCULATOR
|
||||
KeyMap[211] = KEY_UNKNOWN; // AKEYCODE_ZENKAKU_HANKAKU
|
||||
KeyMap[212] = KEY_UNKNOWN; // AKEYCODE_EISU
|
||||
KeyMap[213] = KEY_UNKNOWN; // AKEYCODE_MUHENKAN
|
||||
KeyMap[214] = KEY_UNKNOWN; // AKEYCODE_HENKAN
|
||||
KeyMap[215] = KEY_UNKNOWN; // AKEYCODE_KATAKANA_HIRAGANA
|
||||
KeyMap[216] = KEY_UNKNOWN; // AKEYCODE_YEN
|
||||
KeyMap[217] = KEY_UNKNOWN; // AKEYCODE_RO
|
||||
KeyMap[218] = KEY_UNKNOWN; // AKEYCODE_KANA
|
||||
KeyMap[219] = KEY_UNKNOWN; // AKEYCODE_ASSIST
|
||||
KeyMap[220] = KEY_UNKNOWN; // AKEYCODE_BRIGHTNESS_DOWN
|
||||
KeyMap[221] = KEY_UNKNOWN; // AKEYCODE_BRIGHTNESS_UP ,
|
||||
KeyMap[222] = KEY_UNKNOWN; // AKEYCODE_MEDIA_AUDIO_TRACK
|
||||
}
|
||||
|
||||
void CIrrDeviceAndroid::getKeyChar(SEvent& event)
|
||||
{
|
||||
// Handle ASCII chars
|
||||
|
||||
event.KeyInput.Char = 0;
|
||||
|
||||
// A-Z
|
||||
if (event.KeyInput.SystemKeyCode > 28 && event.KeyInput.SystemKeyCode < 55)
|
||||
{
|
||||
if (event.KeyInput.Shift)
|
||||
{
|
||||
event.KeyInput.Char = event.KeyInput.SystemKeyCode + 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
event.KeyInput.Char = event.KeyInput.SystemKeyCode + 68;
|
||||
}
|
||||
}
|
||||
|
||||
// 0-9
|
||||
else if (event.KeyInput.SystemKeyCode > 6 && event.KeyInput.SystemKeyCode < 17)
|
||||
{
|
||||
event.KeyInput.Char = event.KeyInput.SystemKeyCode + 41;
|
||||
}
|
||||
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_BACK)
|
||||
{
|
||||
event.KeyInput.Char = 8;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_DEL)
|
||||
{
|
||||
event.KeyInput.Char = 8;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_TAB)
|
||||
{
|
||||
event.KeyInput.Char = 9;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_ENTER)
|
||||
{
|
||||
event.KeyInput.Char = 13;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_SPACE)
|
||||
{
|
||||
event.KeyInput.Char = 32;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_COMMA)
|
||||
{
|
||||
event.KeyInput.Char = 44;
|
||||
}
|
||||
else if (event.KeyInput.SystemKeyCode == AKEYCODE_PERIOD)
|
||||
{
|
||||
event.KeyInput.Char = 46;
|
||||
}
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::activateAccelerometer(float updateInterval)
|
||||
{
|
||||
if (!isAccelerometerAvailable())
|
||||
return false;
|
||||
|
||||
ASensorEventQueue_enableSensor(SensorEventQueue, Accelerometer);
|
||||
ASensorEventQueue_setEventRate(SensorEventQueue, Accelerometer,
|
||||
(int32_t)(updateInterval*1000.f*1000.f)); // in microseconds
|
||||
|
||||
os::Printer::log("Activated accelerometer", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::deactivateAccelerometer()
|
||||
{
|
||||
if (!Accelerometer)
|
||||
return false;
|
||||
|
||||
ASensorEventQueue_disableSensor(SensorEventQueue, Accelerometer);
|
||||
Accelerometer = 0;
|
||||
os::Printer::log("Deactivated accelerometer", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isAccelerometerActive()
|
||||
{
|
||||
return (Accelerometer != NULL);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isAccelerometerAvailable()
|
||||
{
|
||||
if (!Accelerometer)
|
||||
{
|
||||
Accelerometer = ASensorManager_getDefaultSensor(SensorManager,
|
||||
ASENSOR_TYPE_ACCELEROMETER);
|
||||
}
|
||||
|
||||
return (Accelerometer != NULL);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::activateGyroscope(float updateInterval)
|
||||
{
|
||||
if (!isGyroscopeAvailable())
|
||||
return false;
|
||||
|
||||
ASensorEventQueue_enableSensor(SensorEventQueue, Gyroscope);
|
||||
ASensorEventQueue_setEventRate(SensorEventQueue, Gyroscope,
|
||||
(int32_t)(updateInterval*1000.f*1000.f)); // in microseconds
|
||||
|
||||
os::Printer::log("Activated gyroscope", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::deactivateGyroscope()
|
||||
{
|
||||
if (!Gyroscope)
|
||||
return false;
|
||||
|
||||
ASensorEventQueue_disableSensor(SensorEventQueue, Gyroscope);
|
||||
Gyroscope = 0;
|
||||
os::Printer::log("Deactivated gyroscope", ELL_DEBUG);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isGyroscopeActive()
|
||||
{
|
||||
return (Gyroscope != NULL);
|
||||
}
|
||||
|
||||
bool CIrrDeviceAndroid::isGyroscopeAvailable()
|
||||
{
|
||||
if (!Gyroscope)
|
||||
{
|
||||
Gyroscope = ASensorManager_getDefaultSensor(SensorManager,
|
||||
ASENSOR_TYPE_GYROSCOPE);
|
||||
}
|
||||
|
||||
return (Gyroscope != NULL);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
|
126
lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h
Normal file
126
lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2002-2011 Nikolaus Gebhardt
|
||||
// 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
|
||||
|
||||
#ifndef __C_IRR_DEVICE_ANDROID_H_INCLUDED__
|
||||
#define __C_IRR_DEVICE_ANDROID_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
|
||||
#include <android/window.h>
|
||||
#include <android/sensor.h>
|
||||
#include <android_native_app_glue.h>
|
||||
#include "CIrrDeviceStub.h"
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "IImagePresenter.h"
|
||||
#include "ICursorControl.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
class CIrrDeviceAndroid : public CIrrDeviceStub, video::IImagePresenter
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CIrrDeviceAndroid(const SIrrlichtCreationParameters& param);
|
||||
|
||||
//! destructor
|
||||
virtual ~CIrrDeviceAndroid();
|
||||
|
||||
virtual bool run();
|
||||
virtual void yield();
|
||||
virtual void sleep(u32 timeMs, bool pauseTimer=false);
|
||||
virtual void setWindowCaption(const wchar_t* text);
|
||||
virtual bool present(video::IImage* surface, void* windowId, core::rect<s32>* srcClip);
|
||||
virtual bool isWindowActive() const;
|
||||
virtual bool isWindowFocused() const;
|
||||
virtual bool isWindowMinimized() const;
|
||||
virtual void closeDevice();
|
||||
virtual void setResizable( bool resize=false );
|
||||
virtual void minimizeWindow();
|
||||
virtual void maximizeWindow();
|
||||
virtual void restoreWindow();
|
||||
virtual E_DEVICE_TYPE getType() const;
|
||||
virtual bool activateAccelerometer(float updateInterval);
|
||||
virtual bool deactivateAccelerometer();
|
||||
virtual bool isAccelerometerActive();
|
||||
virtual bool isAccelerometerAvailable();
|
||||
virtual bool activateGyroscope(float updateInterval);
|
||||
virtual bool deactivateGyroscope();
|
||||
virtual bool isGyroscopeActive();
|
||||
virtual bool isGyroscopeAvailable();
|
||||
video::IVideoModeList* getVideoModeList();
|
||||
|
||||
class CCursorControl : public gui::ICursorControl
|
||||
{
|
||||
public:
|
||||
|
||||
CCursorControl() : CursorPos(core::position2d<s32>(0, 0)) {}
|
||||
virtual void setVisible(bool visible) {}
|
||||
virtual bool isVisible() const {return false;}
|
||||
virtual void setPosition(const core::position2d<f32> &pos)
|
||||
{
|
||||
setPosition(pos.X, pos.Y);
|
||||
}
|
||||
virtual void setPosition(f32 x, f32 y)
|
||||
{
|
||||
CursorPos.X = x;
|
||||
CursorPos.Y = y;
|
||||
}
|
||||
virtual void setPosition(const core::position2d<s32> &pos)
|
||||
{
|
||||
setPosition(pos.X, pos.Y);
|
||||
}
|
||||
virtual void setPosition(s32 x, s32 y)
|
||||
{
|
||||
CursorPos.X = x;
|
||||
CursorPos.Y = y;
|
||||
}
|
||||
virtual const core::position2d<s32>& getPosition()
|
||||
{
|
||||
return CursorPos;
|
||||
}
|
||||
virtual core::position2d<f32> getRelativePosition()
|
||||
{
|
||||
return core::position2d<f32>(0, 0);
|
||||
}
|
||||
virtual void setReferenceRect(core::rect<s32>* rect=0) {}
|
||||
private:
|
||||
core::position2d<s32> CursorPos;
|
||||
};
|
||||
|
||||
private:
|
||||
android_app* Android;
|
||||
ASensorManager* SensorManager;
|
||||
ASensorEventQueue* SensorEventQueue;
|
||||
const ASensor* Accelerometer;
|
||||
const ASensor* Gyroscope;
|
||||
|
||||
static bool IsPaused;
|
||||
static bool IsFocused;
|
||||
static bool IsStarted;
|
||||
static bool IsClosing;
|
||||
|
||||
bool IsMousePressed;
|
||||
|
||||
video::SExposedVideoData ExposedVideoData;
|
||||
|
||||
core::array<EKEY_CODE> KeyMap;
|
||||
|
||||
void createDriver();
|
||||
void createKeyMap();
|
||||
void getKeyChar(SEvent& event);
|
||||
video::SExposedVideoData& getExposedVideoData();
|
||||
|
||||
static void handleAndroidCommand(android_app* app, int32_t cmd);
|
||||
static s32 handleInput(android_app* app, AInputEvent* event);
|
||||
};
|
||||
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_ANDROID_DEVICE_
|
||||
#endif // __C_IRR_DEVICE_ANDROID_H_INCLUDED__
|
@ -60,6 +60,7 @@ if(NOT WIN32)
|
||||
if(NOT M_LIBRARY)
|
||||
message(STATUS
|
||||
"math library 'libm' not found - floating point support disabled")
|
||||
set(M_LIBRARY "")
|
||||
endif()
|
||||
else()
|
||||
# not needed on windows
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
|
433
src/io/assets_android.cpp
Normal file
433
src/io/assets_android.cpp
Normal file
@ -0,0 +1,433 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014-2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "io/assets_android.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/progress_bar_android.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/asset_manager.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Assets Android constructor
|
||||
*/
|
||||
AssetsAndroid::AssetsAndroid(FileManager* file_manager)
|
||||
{
|
||||
m_file_manager = file_manager;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A function that detects a path where data directory is placed and that
|
||||
* sets some environment variables that are used for finding data and
|
||||
* home directory in a common code.
|
||||
*/
|
||||
void AssetsAndroid::init()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (m_file_manager == NULL)
|
||||
return;
|
||||
|
||||
bool needs_extract_data = false;
|
||||
const std::string version = std::string("supertuxkart.") + STK_VERSION;
|
||||
|
||||
// Add some paths to check
|
||||
std::vector<std::string> paths;
|
||||
|
||||
if (getenv("SUPERTUXKART_DATADIR"))
|
||||
paths.push_back(getenv("SUPERTUXKART_DATADIR"));
|
||||
|
||||
if (getenv("EXTERNAL_STORAGE"))
|
||||
paths.push_back(getenv("EXTERNAL_STORAGE"));
|
||||
|
||||
if (getenv("SECONDARY_STORAGE"))
|
||||
paths.push_back(getenv("SECONDARY_STORAGE"));
|
||||
|
||||
if (global_android_app->activity->externalDataPath)
|
||||
paths.push_back(global_android_app->activity->externalDataPath);
|
||||
|
||||
if (global_android_app->activity->internalDataPath)
|
||||
paths.push_back(global_android_app->activity->internalDataPath);
|
||||
|
||||
paths.push_back("/sdcard/");
|
||||
paths.push_back("/storage/sdcard0/");
|
||||
paths.push_back("/storage/sdcard1/");
|
||||
paths.push_back("/data/data/org.supertuxkart.stk/files/");
|
||||
|
||||
// Check if STK data is available somewhere
|
||||
for (std::string path : paths)
|
||||
{
|
||||
Log::info("AssetsAndroid", "Check data files in: %s", path.c_str());
|
||||
|
||||
if (m_file_manager->fileExists(path + "/stk/data/" + version))
|
||||
{
|
||||
Log::info("AssetsAndroid", "Data files found in: %s", path.c_str());
|
||||
m_stk_dir = path + "/stk";
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_file_manager->fileExists(path + "/supertuxkart/data/" + version))
|
||||
{
|
||||
Log::info("AssetsAndroid", "Data files found in: %s", path.c_str());
|
||||
m_stk_dir = path + "/supertuxkart";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create data dir if it's not available anywhere
|
||||
if (m_stk_dir.size() == 0)
|
||||
{
|
||||
for (std::string path : paths)
|
||||
{
|
||||
if (m_file_manager->checkAndCreateDirectoryP(path + "/stk/data"))
|
||||
{
|
||||
Log::info("AssetsAndroid", "Data directory created in: %s",
|
||||
path.c_str());
|
||||
m_stk_dir = path + "/stk";
|
||||
needs_extract_data = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can't continue if STK dir has not been found
|
||||
if (m_stk_dir.size() == 0)
|
||||
{
|
||||
Log::fatal("AssetsAndroid", "Fatal error: Couldn't find Supertuxkart "
|
||||
"data directory");
|
||||
}
|
||||
|
||||
// Check if assets were extracted properly
|
||||
if (!m_file_manager->fileExists(m_stk_dir + "/.extracted") &&
|
||||
!needs_extract_data)
|
||||
{
|
||||
needs_extract_data = true;
|
||||
Log::warn("AssetsAndroid", "Assets seem to be not extracted properly, "
|
||||
"because the .extracted file doesn't exist. Force "
|
||||
"extracting assets...");
|
||||
}
|
||||
|
||||
if (!m_file_manager->checkAndCreateDirectoryP(m_stk_dir + "/home"))
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Couldn't create home directory");
|
||||
}
|
||||
|
||||
// Set some useful variables
|
||||
setenv("SUPERTUXKART_DATADIR", m_stk_dir.c_str(), 1);
|
||||
setenv("HOME", (m_stk_dir + "/home").c_str(), 1);
|
||||
setenv("XDG_CONFIG_HOME", (m_stk_dir + "/home").c_str(), 1);
|
||||
|
||||
// Extract data directory from apk if it's needed
|
||||
if (needs_extract_data)
|
||||
{
|
||||
removeData();
|
||||
extractData();
|
||||
|
||||
if (!m_file_manager->fileExists(m_stk_dir + "/.extracted"))
|
||||
{
|
||||
Log::fatal("AssetsAndroid", "Fatal error: Assets were not "
|
||||
"extracted properly");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A function that extracts whole data directory from apk file to a real
|
||||
* path in the filesystem
|
||||
*/
|
||||
void AssetsAndroid::extractData()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
const std::string dirs_list = "directories.txt";
|
||||
|
||||
bool success = true;
|
||||
|
||||
// Create .nomedia file
|
||||
touchFile(m_stk_dir + "/.nomedia");
|
||||
|
||||
// Extract base directory first, so that we will be able to open the file
|
||||
// with dir names
|
||||
success = extractDir("");
|
||||
|
||||
if (!success)
|
||||
{
|
||||
Log::error("AssetsAndroid", "Error: Couldn't extract main directory.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::fstream file(m_stk_dir + "/" + dirs_list, std::ios::in);
|
||||
|
||||
if (file.good())
|
||||
{
|
||||
unsigned int lines_count = 0;
|
||||
|
||||
while (!file.eof())
|
||||
{
|
||||
std::string dir_name;
|
||||
getline(file, dir_name);
|
||||
|
||||
if (dir_name.length() == 0 || dir_name.at(0) == '#')
|
||||
continue;
|
||||
|
||||
lines_count++;
|
||||
}
|
||||
|
||||
if (lines_count > 0)
|
||||
{
|
||||
file.clear();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
ProgressBarAndroid* progress_bar = new ProgressBarAndroid();
|
||||
progress_bar->draw(0.0f);
|
||||
unsigned int current_line = 1;
|
||||
|
||||
while (!file.eof())
|
||||
{
|
||||
std::string dir_name;
|
||||
getline(file, dir_name);
|
||||
|
||||
if (dir_name.length() == 0 || dir_name.at(0) == '#')
|
||||
continue;
|
||||
|
||||
success = extractDir(dir_name);
|
||||
|
||||
assert(lines_count > 0);
|
||||
progress_bar->draw((float)(current_line) / lines_count);
|
||||
current_line++;
|
||||
|
||||
if (progress_bar->closeEventReceived())
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
break;
|
||||
}
|
||||
|
||||
delete progress_bar;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Warning: Cannot open %s file. Ignoring "
|
||||
"extraction of other directories.", dirs_list.c_str());
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
// Mark the extraction as successful if everything is ok
|
||||
if (success)
|
||||
{
|
||||
touchFile(m_stk_dir + "/.extracted");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A function that extracts selected directory from apk file
|
||||
* \param dir_name Directory to extract from assets
|
||||
* \return True if successfully extracted
|
||||
*/
|
||||
bool AssetsAndroid::extractDir(std::string dir_name)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
AAssetManager* amgr = global_android_app->activity->assetManager;
|
||||
|
||||
Log::info("AssetsAndroid", "Extracting %s directory",
|
||||
dir_name.length() > 0 ? dir_name.c_str() : "main");
|
||||
|
||||
std::string output_dir = dir_name;
|
||||
|
||||
if (m_stk_dir.length() > 0)
|
||||
{
|
||||
output_dir = m_stk_dir + "/" + dir_name;
|
||||
}
|
||||
|
||||
AAssetDir* asset_dir = AAssetManager_openDir(amgr, dir_name.c_str());
|
||||
|
||||
if (asset_dir == NULL)
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Couldn't get asset dir: %s",
|
||||
dir_name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_file_manager->checkAndCreateDirectoryP(output_dir))
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Couldn't create %s directory",
|
||||
output_dir.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const int buf_size = 65536;
|
||||
char* buf = new char[buf_size]();
|
||||
bool extraction_failed = false;
|
||||
|
||||
while (!extraction_failed)
|
||||
{
|
||||
const char* filename = AAssetDir_getNextFileName(asset_dir);
|
||||
|
||||
// Check if finished
|
||||
if (filename == NULL)
|
||||
break;
|
||||
|
||||
if (strlen(filename) == 0)
|
||||
continue;
|
||||
|
||||
std::string file_path = std::string(filename);
|
||||
|
||||
if (dir_name.length() > 0)
|
||||
{
|
||||
file_path = dir_name + "/" + std::string(filename);
|
||||
}
|
||||
|
||||
AAsset* asset = AAssetManager_open(amgr, file_path.c_str(),
|
||||
AASSET_MODE_STREAMING);
|
||||
|
||||
if (asset == NULL)
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Asset is null: %s", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string output_path = output_dir + "/" + std::string(filename);
|
||||
std::fstream out_file(output_path, std::ios::out | std::ios::binary);
|
||||
|
||||
if (!out_file.good())
|
||||
{
|
||||
extraction_failed = true;
|
||||
Log::error("AssetsAndroid", "Couldn't create a file: %s", filename);
|
||||
AAsset_close(asset);
|
||||
break;
|
||||
}
|
||||
|
||||
int nb_read = 0;
|
||||
while ((nb_read = AAsset_read(asset, buf, buf_size)) > 0)
|
||||
{
|
||||
out_file.write(buf, nb_read);
|
||||
|
||||
if (out_file.fail())
|
||||
{
|
||||
extraction_failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out_file.close();
|
||||
|
||||
if (out_file.fail() || extraction_failed)
|
||||
{
|
||||
extraction_failed = true;
|
||||
Log::error("AssetsAndroid", "Extraction failed for file: %s",
|
||||
filename);
|
||||
}
|
||||
|
||||
AAsset_close(asset);
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
|
||||
AAssetDir_close(asset_dir);
|
||||
|
||||
return !extraction_failed;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A function that removes whole STK data directory
|
||||
*/
|
||||
void AssetsAndroid::removeData()
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (m_stk_dir.length() == 0)
|
||||
return;
|
||||
|
||||
// Make sure that we are not accidentally removing wrong directory
|
||||
if (m_stk_dir.find("/stk") == std::string::npos &&
|
||||
m_stk_dir.find("/supertuxkart") == std::string::npos)
|
||||
{
|
||||
Log::error("AssetsAndroid", "Invalid data directory: %s",
|
||||
m_stk_dir.c_str());
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<std::string> files;
|
||||
m_file_manager->listFiles(files, m_stk_dir, true);
|
||||
|
||||
for (std::string file : files)
|
||||
{
|
||||
if (file == m_stk_dir + "/." || file == m_stk_dir + "/..")
|
||||
continue;
|
||||
|
||||
// Don't delete home directory that contains configuration files
|
||||
// and add-ons
|
||||
if (file == m_stk_dir + "/home")
|
||||
continue;
|
||||
|
||||
// Don't delete .nomedia file. It has a sense to keep it for home
|
||||
// directory, i.e. for textures of add-on karts etc.
|
||||
if (file == m_stk_dir + "/.nomedia")
|
||||
continue;
|
||||
|
||||
Log::info("AssetsAndroid", "Deleting file: %s\n", file.c_str());
|
||||
|
||||
if (m_file_manager->isDirectory(file))
|
||||
{
|
||||
m_file_manager->removeDirectory(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_file_manager->removeFile(file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A function that creates empty file
|
||||
* \param path A path to the file that should be created
|
||||
*/
|
||||
void AssetsAndroid::touchFile(std::string path)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
if (m_file_manager->fileExists(path))
|
||||
return;
|
||||
|
||||
std::fstream file(path, std::ios::out | std::ios::binary);
|
||||
|
||||
if (!file.good())
|
||||
{
|
||||
Log::warn("AssetsAndroid", "Error: Cannot create %s file.",
|
||||
path.c_str());
|
||||
}
|
||||
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
44
src/io/assets_android.hpp
Normal file
44
src/io/assets_android.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014-2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_ASSETS_ANDROID_HPP
|
||||
#define HEADER_ASSETS_ANDROID_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
class FileManager;
|
||||
|
||||
class AssetsAndroid
|
||||
{
|
||||
private:
|
||||
FileManager* m_file_manager;
|
||||
std::string m_stk_dir;
|
||||
|
||||
void extractData();
|
||||
bool extractDir(std::string dir_name);
|
||||
void removeData();
|
||||
void touchFile(std::string path);
|
||||
|
||||
public:
|
||||
AssetsAndroid(FileManager* file_manager);
|
||||
~AssetsAndroid() {};
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
62
src/main_android.cpp
Normal file
62
src/main_android.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
|
||||
extern int main(int argc, char *argv[]);
|
||||
|
||||
void override_default_params()
|
||||
{
|
||||
// It has an effect only on the first run, when config file is created.
|
||||
// So that we can still modify these params in STK options and user's
|
||||
// choice will be then remembered.
|
||||
|
||||
// Set smaller texture size to avoid high RAM usage
|
||||
UserConfigParams::m_max_texture_size = 256;
|
||||
UserConfigParams::m_high_definition_textures = false;
|
||||
|
||||
// Disable advanced lighting by default to make the game playable
|
||||
UserConfigParams::m_dynamic_lights = false;
|
||||
|
||||
// Enable touch steering and screen keyboard
|
||||
UserConfigParams::m_multitouch_enabled = true;
|
||||
UserConfigParams::m_screen_keyboard = true;
|
||||
|
||||
// It shouldn't matter, but STK is always run in fullscreen on android
|
||||
UserConfigParams::m_fullscreen = true;
|
||||
|
||||
// Make sure that user can play every track even if there are installed
|
||||
// only few tracks and it's impossible to finish overworld challenges
|
||||
UserConfigParams::m_everything_unlocked = true;
|
||||
|
||||
// Create default user istead of showing login screen to make life easier
|
||||
UserConfigParams::m_enforce_current_player = true;
|
||||
|
||||
// Just for debugging
|
||||
UserConfigParams::m_log_errors_to_console = true;
|
||||
}
|
||||
|
||||
void android_main(struct android_app* app)
|
||||
{
|
||||
Log::info("AndroidMain", "Loading application...");
|
||||
|
||||
app_dummy();
|
||||
|
||||
override_default_params();
|
||||
|
||||
global_android_app = app;
|
||||
main(0, {});
|
||||
|
||||
Log::info("AndroidMain", "Closing STK...");
|
||||
|
||||
// TODO: Irrlicht device is properly waiting for destroy event, but
|
||||
// some global variables are not initialized/cleared in functions and thus
|
||||
// its state is remembered when the window is restored. We will use exit
|
||||
// call to make sure that all variables are cleared until a proper fix will
|
||||
// be done.
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif
|
205
src/utils/progress_bar_android.cpp
Normal file
205
src/utils/progress_bar_android.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014-2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/progress_bar_android.hpp"
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
ProgressBarAndroid::ProgressBarAndroid()
|
||||
{
|
||||
m_program = 0;
|
||||
m_vertex_shader = 0;
|
||||
m_fragment_shader = 0;
|
||||
m_position = 0;
|
||||
m_progress = 0;
|
||||
m_vbo = 0;
|
||||
m_device = NULL;
|
||||
m_initialized = false;
|
||||
m_close_event_received = false;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
ProgressBarAndroid::~ProgressBarAndroid()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
bool ProgressBarAndroid::compileShaders()
|
||||
{
|
||||
const GLchar* vsh =
|
||||
"precision mediump float;"
|
||||
"attribute vec2 position;"
|
||||
"uniform float progress;"
|
||||
"void main(void)"
|
||||
"{"
|
||||
" float pos_x = (position.x + 1.0) * progress - 1.0;"
|
||||
" float pos_y = position.y * 0.1 - 0.6;"
|
||||
" gl_Position = vec4(pos_x, pos_y, 0.0, 1.0);"
|
||||
"}";
|
||||
|
||||
const GLchar* fsh =
|
||||
"precision mediump float;"
|
||||
"void main(void)"
|
||||
"{"
|
||||
" gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);"
|
||||
"}";
|
||||
|
||||
m_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(m_vertex_shader, 1, &vsh, NULL);
|
||||
glCompileShader(m_vertex_shader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(m_vertex_shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
Log::error("ProgressBarAndroid", "Failed to compile vertex shader.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(m_fragment_shader, 1, &fsh, NULL);
|
||||
glCompileShader(m_fragment_shader);
|
||||
|
||||
glGetShaderiv(m_fragment_shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
Log::error("ProgressBarAndroid", "Failed to compile fragment shader.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_program = glCreateProgram();
|
||||
|
||||
glAttachShader(m_program, m_vertex_shader);
|
||||
glAttachShader(m_program, m_fragment_shader);
|
||||
glLinkProgram(m_program);
|
||||
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
Log::error("ProgressBarAndroid", "Failed to link program.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_position = glGetAttribLocation(m_program, "position");
|
||||
if (m_position == -1)
|
||||
{
|
||||
Log::error("ProgressBarAndroid", "Failed to get attrib location.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_progress = glGetUniformLocation(m_program, "progress");
|
||||
if (m_progress == -1)
|
||||
{
|
||||
Log::error("ProgressBarAndroid", "Failed to get uniform location.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProgressBarAndroid::deleteShaders()
|
||||
{
|
||||
glDeleteShader(m_vertex_shader);
|
||||
glDeleteShader(m_fragment_shader);
|
||||
glDeleteProgram(m_program);
|
||||
}
|
||||
|
||||
void ProgressBarAndroid::init()
|
||||
{
|
||||
SIrrlichtCreationParameters params;
|
||||
params.DriverType = video::EDT_OGLES2;
|
||||
params.Bits = 32;
|
||||
params.Fullscreen = UserConfigParams::m_fullscreen;
|
||||
params.WindowSize = core::dimension2du(640, 480);
|
||||
#if defined(ANDROID)
|
||||
params.PrivateData = (void*)global_android_app;
|
||||
#endif
|
||||
|
||||
m_device = createDeviceEx(params);
|
||||
|
||||
if (!m_device)
|
||||
return;
|
||||
|
||||
bool success = compileShaders();
|
||||
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
const GLfloat vertices[] =
|
||||
{
|
||||
-1, 1, 1, -1, -1, -1,
|
||||
1, -1, -1, 1, 1, 1
|
||||
};
|
||||
|
||||
glGenBuffers(1, &m_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glUseProgram(m_program);
|
||||
glEnableVertexAttribArray(m_position);
|
||||
glVertexAttribPointer(m_position, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void ProgressBarAndroid::close()
|
||||
{
|
||||
glDisableVertexAttribArray(m_position);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
deleteShaders();
|
||||
|
||||
if (m_device != NULL)
|
||||
{
|
||||
m_device->closeDevice();
|
||||
m_device->clearSystemMessages();
|
||||
m_device->run();
|
||||
m_device->drop();
|
||||
m_device = NULL;
|
||||
}
|
||||
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
void ProgressBarAndroid::draw(float value)
|
||||
{
|
||||
if (!m_initialized || m_close_event_received)
|
||||
return;
|
||||
|
||||
value = value > 1.0f ? 1.0f : value;
|
||||
|
||||
m_close_event_received = !m_device->run();
|
||||
|
||||
m_device->getVideoDriver()->beginScene(true, true);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glUniform1f(m_progress, value);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
m_device->getVideoDriver()->endScene();
|
||||
}
|
||||
|
||||
#endif
|
55
src/utils/progress_bar_android.hpp
Normal file
55
src/utils/progress_bar_android.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014-2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_PROGRESS_BAR_ANDROID_HPP
|
||||
#define HEADER_PROGRESS_BAR_ANDROID_HPP
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include "IrrlichtDevice.h"
|
||||
#include "graphics/gl_headers.hpp"
|
||||
|
||||
class ProgressBarAndroid
|
||||
{
|
||||
private:
|
||||
GLuint m_program;
|
||||
GLuint m_vertex_shader;
|
||||
GLuint m_fragment_shader;
|
||||
GLint m_position;
|
||||
GLint m_progress;
|
||||
GLuint m_vbo;
|
||||
|
||||
irr::IrrlichtDevice* m_device;
|
||||
bool m_initialized;
|
||||
bool m_close_event_received;
|
||||
|
||||
bool compileShaders();
|
||||
void deleteShaders();
|
||||
void init();
|
||||
void close();
|
||||
|
||||
public:
|
||||
ProgressBarAndroid();
|
||||
~ProgressBarAndroid();
|
||||
|
||||
void draw(float value);
|
||||
bool closeEventReceived() {return m_close_event_received;}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user