Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker 2017-02-20 07:45:26 +11:00
commit 8e8de3c5e2
122 changed files with 3821 additions and 473 deletions

17
.gitignore vendored
View File

@ -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
View 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)

View 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>

126
android/README.ANDROID Normal file
View File

@ -0,0 +1,126 @@
================================================================================
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. 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
5. STK crashes on Qualcomm with Adreno 305 when trying to draw menu interface.
Backtrace shows glDrawElements function, and internally crashed in vbo
allocation.
6. 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.
7. Angelscript doesn't have full support for aarch64 builds, so that scripting
won't work on this platform.
8. Turning left/right using accelerometer is available, but at this stage the
default screen orientation is not automatically detected and user must
manually choose if he needs "phone" or "tablet" accelerometer.

6
android/build.xml Normal file
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SuperTuxKart</string>
</resources>

View 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} "")

View File

@ -119,6 +119,9 @@ Karts
Objects
- GeekPenguinBR, TuxKartDriver : Models from Las Dunas Stadium
Jymis
- Karts and icons
Minibjorn
- Powerups and baddies (models + icons)
- Explosion and smoke particles

View File

@ -10,8 +10,8 @@
<material file="explode.png" />
<!-- Amount of particles emitted per second -->
<rate min="500"
max="800" />
<rate min="400"
max="600" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="1000"

View File

@ -10,8 +10,8 @@
<material file="explode.png" />
<!-- Amount of particles emitted per second -->
<rate min="500"
max="800" />
<rate min="400"
max="600" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="1000"

View File

@ -10,8 +10,8 @@
<material file="explode.png" />
<!-- Amount of particles emitted per second -->
<rate min="500"
max="800" />
<rate min="400"
max="600" />
<!-- Minimal and maximal lifetime of a particle, in milliseconds. -->
<lifetime min="1000"

View File

@ -1,9 +1,16 @@
<?xml version="1.0"?>
<graphical-restrictions>
<card is="Intel(R) HD Graphics" os="windows" version="<9.0" disable="ForceLegacyDevice"/>
<card is="Intel(R) HD Graphics" os="windows" version="<9.0" disable="HighDefinitionTextures"/>
<card is="Intel(R) HD Graphics 2000" os="windows" disable="UniformBufferObject"/>
<card is="Intel(R) HD Graphics 2000" os="windows" disable="AdvancedPipeline"/>
<card is="Intel(R) HD Graphics 2000" os="windows" disable="FramebufferSRGBWorking"/>
<card is="Intel(R) HD Graphics 2000" os="windows" disable="HighDefinitionTextures"/>
<card is="Intel(R) HD Graphics 3000" os="windows" disable="UniformBufferObject"/>
<card is="Intel(R) HD Graphics 3000" os="windows" disable="AdvancedPipeline"/>
<card is="Intel(R) HD Graphics 3000" os="windows" disable="FramebufferSRGBWorking"/>
<card is="Intel(R) HD Graphics" os="windows" disable="ForceLegacyDevice"/>
<card is="Intel(R) HD Graphics 3000" os="windows" disable="HighDefinitionTextures"/>
<card is="Intel(R) HD Graphics 4600" os="windows" disable="ComputeShader"/>
<card contains="Intel" os="osx" disable="GI"/>
<card contains="Intel" os="linux" version="<11.2" disable="ComputeShader"/>
<card contains="Intel" os="linux" version="<11.2" disable="GeometryShader"/>
@ -11,7 +18,6 @@
<card contains="Intel" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
<card contains="Intel" os="windows" disable="TextureCompressionS3TC"/>
<card contains="Intel" os="osx" disable="TextureCompressionS3TC"/>
<card contains="Intel" os="windows" disable="HighDefinitionTextures"/>
<card contains="NVIDIA" os="windows" version="<344.65" disable="BufferStorage"/>
<card contains="NVIDIA" os="linux" version="<343.22" disable="BufferStorage"/>
<card contains="NVIDIA" disable="ShaderAtomicCounters"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
data/gui/android/drift.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -0,0 +1,12 @@
# Licensing work
Icons firstly made for SuperTuxKart UI on Android.
Files: blur_bg_button ; blur_bg_button_focus ; directionnal_wheel ; drift ; nitro ; nitro_empty ; pause ; thunderbird_reset ; wing_mirror
- CC BY-SA 4.0 / author: Néd J. Édoire
# License information:
- Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
Visit the following link for detailed informations:
https://creativecommons.org/licenses/by-sa/4.0/

BIN
data/gui/android/nitro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
data/gui/android/pause.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -3,12 +3,18 @@
<div x="2%" y="1%" width="96%" height="98%" layout="vertical-row" >
<header id="title" width="100%" height="fit" text_align="center" word_wrap="true" text="Touch Device Settings" />
<spacer height="30" width="10" />
<spacer height="35" width="10" />
<label width="100%" I18N="In the multitouch settings screen" text="General"/>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Device enabled"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="buttons_enabled"/>
</div>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Buttons scale"/>
<div proportion="1" height="fit" layout="horizontal-row" >
@ -16,13 +22,35 @@
<gauge id="scale" proportion="1" min_value="50" max_value="150"/>
</div>
</div>
<label width="100%" I18N="In the multitouch settings screen" text="Accelerometer"/>
<spacer height="45" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Disabled"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="accelerometer_disabled"/>
</div>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Phone"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="accelerometer_phone"/>
</div>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Tablet"/>
<div proportion="1" height="fit" layout="horizontal-row" >
<spacer width="40" height="100%" />
<checkbox id="accelerometer_tablet"/>
</div>
</div>
<label width="100%" I18N="In the multitouch settings screen" text="Advanced"/>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Deadzone center"/>
<div proportion="1" height="fit" layout="horizontal-row" >
@ -31,8 +59,6 @@
</div>
</div>
<spacer height="15" width="10"/>
<div width="75%" height="fit" layout="horizontal-row" >
<label proportion="1" height="100%" text_align="right" I18N="In the multitouch settings screen" text="Deadzone edge"/>
<div proportion="1" height="fit" layout="horizontal-row" >
@ -41,12 +67,13 @@
</div>
</div>
<spacer height="45" width="10"/>
<spacer height="35" width="10"/>
<button id="restore" text="Restore defaults" align="center"/>
<spacer height="15" width="10"/>
<button id="close" text="Apply" align="center"/>
<div width="fit" height="fit" layout="horizontal-row" align="center">
<button id="restore" text="Restore defaults"/>
<spacer width="40" height="100%" />
<button id="close" text="Apply"/>
</div>
</div>
</stkgui>

View File

@ -202,16 +202,21 @@
friction: The friction increase when a parachute is attached.
duration: The time an attached parachute is active
duration-other: The time a parachute attached from other kart works
duration-rank-mult: The multiplier applied to the duration of the
parachute on the 1st kart when affected by the item. Scale for
intermediary ranks to 1.0 for the last affected.
duration-speed-mult: Applied in all cases, multitplier to duration
of the parachute at max-speed. Scale to 1.0 at 0 speed.
lbound-fraction: The lower bound fraction of speed when lost will
detach parachute. E.g. at nearly 0 speed, only 5% of speed
detach parachute. E.g. at nearly 0 speed, only 20% of speed
need to be lost.
ubound-fraction: The upper bound fraction of speed when lost will
detach parachute. E.g. at max-speed 30% of speed must be lost.
detach parachute. E.g. at max-speed 50% of speed must be lost.
max-speed: A factor that decides the impact of rate of speed
(distance between bounds) -->
<parachute friction="2.0" duration="4.0" duration-other="8.0"
lbound-fraction="0.95" ubound-fraction="0.7" max-speed="23" />
<parachute friction="2.0" duration="2.0" duration-other="2.6"
duration-rank-mult="1.35" duration-speed-mult="2.0"
lbound-fraction="0.8" ubound-fraction="0.5" max-speed="23" />
<!-- Bubblegum
duration: How long the bubblegum lasts.
speed-fraction: To what fraction of top-speed the speed is reduced.

View File

@ -2,7 +2,7 @@ uniform mat4 ModelViewMatrix;
uniform vec3 Position;
uniform vec2 Size;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec2 Corner;
layout(location = 3) in vec2 Texcoord;
#else

View File

@ -1,7 +1,7 @@
uniform vec2 center;
uniform vec2 size;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec2 Position;
#else
in vec2 Position;
@ -11,4 +11,4 @@ in vec2 Position;
void main()
{
gl_Position = vec4(Position * size + center, 0., 1.);
}
}

View File

@ -3,7 +3,7 @@ uniform vec2 size;
uniform vec2 texcenter;
uniform vec2 texsize;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location=0) in vec2 Position;
layout(location=3) in vec2 Texcoord;
layout(location=2) in uvec4 Color;

View File

@ -23,7 +23,6 @@ void main(void)
#endif
#endif
vec4 detail = texture(Detail, uv_bis);
detail.xyz = pow(detail.xyz, vec3(2.2));
detail.rgb = detail.a * detail.rgb;
color.rgb = detail.rgb + color.rgb * (1. - detail.a);
float specmap = texture(SpecMap, uv).g;

View File

@ -1,6 +1,6 @@
uniform mat4 ModelMatrix;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 3) in vec2 Texcoord;
layout(location = 4) in vec2 SecondTexcoord;

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location=0) in vec3 Position;
layout(location = 1) in float lifetime;
layout(location = 2) in float size;

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 7) in vec3 Origin;
layout(location = 8) in vec3 Orientation;

View File

@ -2,7 +2,7 @@ uniform vec3 windDir;
uniform mat4 ModelMatrix;
uniform mat4 InverseModelMatrix;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -29,7 +29,6 @@ void main(void)
vec4 detail = texture(Detail, uv_bis);
float specmap = texture(SpecMap, uv).g;
#endif
detail.xyz = pow(detail.xyz, vec3(2.2));
detail.rgb = detail.a * detail.rgb;
color.rgb = detail.rgb + color.rgb * (1. - detail.a);
FragColor = vec4(getLightFactor(color.xyz, vec3(1.), specmap, 0.), 1.);

View File

@ -1,6 +1,6 @@
uniform vec3 windDir;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -1,7 +1,7 @@
uniform int layer;
uniform vec3 windDir;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 2) in vec4 Color;
layout(location = 3) in vec2 Texcoord;

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -1,6 +1,6 @@
uniform int layer;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 3) in vec2 Texcoord;

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -1,6 +1,6 @@
uniform int layer;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 3) in vec4 Data1;
layout(location = 5) in ivec4 Joint;

View File

@ -17,7 +17,7 @@ uniform mat4 InverseModelMatrix =
uniform vec2 texture_trans = vec2(0., 0.);
#endif
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -40,7 +40,11 @@ void main(void)
col = vec4(new_color.r, new_color.g, new_color.b, col.a);
}
#ifdef GL_ES
col.xyz *= color.xyz;
#else
col.xyz *= pow(color.xyz, vec3(2.2));
#endif
float specmap = texture(SpecMap, uv).g;
float emitmap = texture(SpecMap, uv).b;
FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap, emitmap), 1.);

View File

@ -1,7 +1,7 @@
uniform vec3 color_from;
uniform vec3 color_to;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location=0) in vec3 Position;
layout(location = 1) in float lifetime;
layout(location = 2) in float size;

View File

@ -9,7 +9,7 @@ uniform float track_x_len;
uniform float track_z_len;
uniform samplerBuffer heightmap;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout (location = 4) in vec3 particle_position_initial;
layout (location = 5) in float lifetime_initial;
layout (location = 6) in vec3 particle_velocity_initial;

View File

@ -4,7 +4,7 @@ uniform mat4 sourcematrix;
uniform int level;
uniform float size_increase_factor;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout (location = 4) in vec3 particle_position_initial;
layout (location = 5) in float lifetime_initial;
layout (location = 6) in vec3 particle_velocity_initial;
@ -40,14 +40,14 @@ void main(void)
{
float dt_from_last_frame = fract(updated_lifetime) * lifetime_initial;
float coeff = dt_from_last_frame / float(dt);
vec4 previous_frame_position = previous_frame_sourcematrix * vec4(particle_position_initial, 1.0);
vec4 current_frame_position = sourcematrix * vec4(particle_position_initial, 1.0);
vec4 updated_initialposition = mix(current_frame_position,
previous_frame_position,
coeff);
vec4 updated_initial_velocity = mix(sourcematrix * vec4(particle_velocity_initial, 0.0),
previous_frame_sourcematrix * vec4(particle_velocity_initial, 0.0),
coeff);
@ -56,12 +56,12 @@ void main(void)
//But the simple formula ( (current_frame_position - previous_frame_position) / dt ) with a constant speed
//between 2 frames creates visual artifacts when the framerate is low, and a more accurate formula would need
//more complex computations.
new_particle_position = updated_initialposition.xyz + dt_from_last_frame * updated_initial_velocity.xyz;
new_particle_velocity = updated_initial_velocity.xyz;
new_lifetime = fract(updated_lifetime);
new_size = mix(size_initial, size_initial * size_increase_factor, fract(updated_lifetime));
new_size = mix(size_initial, size_initial * size_increase_factor, fract(updated_lifetime));
}
else
{

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -2,7 +2,7 @@ uniform mat4 ModelMatrix;
uniform mat4 RSMMatrix;
uniform vec2 texture_trans = vec2(0., 0.);
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec2 Position;
layout(location = 3) in vec2 Texcoord;
#else

View File

@ -1,7 +1,7 @@
uniform int layer;
uniform mat4 ModelMatrix;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 3) in vec2 Texcoord;
#else

View File

@ -2,7 +2,7 @@ uniform int layer;
uniform mat4 ModelMatrix;
uniform vec3 windDir;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 2) in vec4 Color;
layout(location = 3) in vec2 Texcoord;

View File

@ -18,7 +18,7 @@ uniform vec2 texture_trans = vec2(0., 0.);
#endif
uniform int skinning_offset;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;

View File

@ -2,7 +2,7 @@ uniform mat4 ModelMatrix;
uniform int skinning_offset;
uniform int layer;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
layout(location = 3) in vec4 Data1;
layout(location = 5) in ivec4 Joint;

View File

@ -1,4 +1,4 @@
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location = 0) in vec3 Position;
#else
in vec3 Position;

View File

@ -35,7 +35,11 @@ float getShadowFactor(vec3 pos, int index)
for (float i = -1.; i <= 1.; i += 1.)
{
for (float j = -1.; j <= 1.; j += 1.)
result += texture(shadowtex, vec4(shadowtexcoord + vec2(i,j) / shadow_res, float(index), d));
{
// result += texture(shadowtex, vec4(shadowtexcoord + vec2(i,j) / shadow_res, float(index), d));
// Added a hack with j+1. to avoid ugly lines
result += texture(shadowtex, vec4(shadowtexcoord + vec2(i,j+1.) / shadow_res, float(index), d));
}
}
return result / 9.;

View File

@ -3,7 +3,7 @@ uniform vec2 size;
uniform vec2 texcenter;
uniform vec2 texsize;
#if __VERSION__ >= 330
#ifdef Explicit_Attrib_Location_Usable
layout(location=0) in vec2 Position;
layout(location=3) in vec2 Texcoord;
#else
@ -17,4 +17,4 @@ void main()
{
uv = Texcoord * texsize + texcenter;
gl_Position = vec4(Position * size + center, 0., 1.);
}
}

View File

@ -14,6 +14,10 @@ vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapVa
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
#ifdef GL_ES
DiffuseComponent = pow(DiffuseComponent, vec3(1. / 2.2));
SpecularComponent = pow(SpecularComponent, vec3(1. / 2.2));
#endif
vec3 tmp = diffuseMatColor * DiffuseComponent * (1. - specMapValue) + specularMatColor * SpecularComponent * specMapValue;
vec3 emitCol = diffuseMatColor.xyz * diffuseMatColor.xyz * diffuseMatColor.xyz * 15.;
return tmp * ao + (emitMapValue * emitCol);

View File

@ -16,12 +16,51 @@
<!-- Scores are the number of points given when the race ends. -->
<grand-prix>
<!-- Karts on position 1 and 2 will have 3 more points than the next kart;
a kart on position 3 and 4 will have two more points than the next;
and all remaining karts will have one more point than the next. -->
<points from="1" to="2" points="3"/>
<points from="3" to="4" points="2"/>
<points from="5" points="1"/>
<!-- Establish the distribution of points in GP.
For a race of N karts ; the N-first point values are taken.
Then, they are sorted. E.g. ; 0 1 2 1 3 2 becomes 0 1 1 2 2 3.
Then these numbers are used to establish the DIFFERENCE of points
between consecutive karts.
The smaller of the numbers is used to establish the score for the
last kart and not the difference between 2 karts.
In the above example, the last kart will have 0 point, the one before
before 1 (0+1) ; the one before 2 (0+1+1), the one before 4 (0+1+1+2),
etc. until the 1st which have 9 (0+1+1+2+2+3)
There shall be at least as much points nodes as max-numbers kart -->
<points points="0" /> <!-- added with 1 kart, score for the last kart -->
<points points="1" /> <!-- added with 2 karts -->
<points points="1" /> <!-- added with 3 karts -->
<points points="2" /> <!-- added with 4 karts -->
<points points="2" /> <!-- added with 5 karts -->
<points points="1" /> <!-- added with 6 karts -->
<points points="3" /> <!-- added with 7 karts -->
<points points="2" /> <!-- added with 8 karts -->
<points points="3" /> <!-- added with 9 karts -->
<points points="1" /> <!-- added with 10 karts -->
<points points="4" /> <!-- added with 11 karts -->
<points points="2" /> <!-- added with 12 karts -->
<points points="1" /> <!-- added with 13 karts -->
<points points="3" /> <!-- added with 14 karts -->
<points points="2" /> <!-- added with 15 karts -->
<points points="1" /> <!-- added with 16 karts -->
<points points="4" /> <!-- added with 17 karts -->
<points points="2" /> <!-- added with 18 karts -->
<points points="3" /> <!-- added with 19 karts -->
<points points="1" /> <!-- added with 20 karts -->
<points points="5" /> <!-- added with 21 karts -->
<points points="2" /> <!-- added with 22 karts -->
<points points="1" /> <!-- added with 23 karts -->
<points points="3" /> <!-- added with 24 karts -->
<points points="4" /> <!-- added with 25 karts -->
<points points="1" /> <!-- added with 26 karts -->
<points points="2" /> <!-- added with 27 karts -->
<points points="1" /> <!-- added with 28 karts -->
<points points="3" /> <!-- added with 29 karts -->
<points points="5" /> <!-- added with 30 karts -->
</grand-prix>
<!-- Time in follow-the-leader after which karts are removed.
@ -353,7 +392,7 @@
outside of the chassis and results in more stable physical
behaviour of the karts. -->
<collision impulse-type="normal"
impulse="3000" impulse-time="0.1" terrain-impulse="1600"
impulse="3000" impulse-time="0.1" terrain-impulse="160"
restitution="1.0" bevel-factor="0.5 0.0 0.7"
physical-wheel-position="-1" />

View File

@ -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

View 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

View 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__

View File

@ -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

View File

@ -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")

View File

@ -103,7 +103,7 @@ void STKConfig::load(const std::string &filename)
strA,filename.c_str()); \
}
if(m_score_increase.size()==0 || (int)m_score_increase.size()!=m_max_karts)
if(m_score_increase.size()==0)
{
Log::fatal("StkConfig", "Not or not enough scores defined in stk_config");
}
@ -214,22 +214,20 @@ void STKConfig::getAllData(const XMLNode * root)
for(unsigned int i=0; i<gp_node->getNumNodes(); i++)
{
const XMLNode *pn=gp_node->getNode(i);
int from=-1;
pn->get("from", &from);
int to=-1;
pn->get("to", &to);
if(to<0) to=m_max_karts;
int points=-1;
pn->get("points", &points);
if(points<0 || from<0 || from>to||
(int)m_score_increase.size()!=from-1)
if(points<0)
{
Log::error("StkConfig", "Incorrect GP point specification:");
Log::fatal("StkConfig", "from: %d to: %d points: %d",
from, to, points);
Log::fatal("StkConfig", "points: %d",
points);
}
for(int j=from; j<=to; j++)
m_score_increase.push_back(points);
m_score_increase.push_back(points);
}
if (m_max_karts > int(gp_node->getNumNodes()))
{
Log::error("StkConfig", "Not enough grand-prix ranking nodes:");
m_score_increase.resize(m_max_karts, 0);
}
}
@ -391,15 +389,27 @@ void STKConfig::getAllData(const XMLNode * root)
*/
void STKConfig::getAllScores(std::vector<int> *all_scores, int num_karts)
{
std::vector<int> sorted_score_increase;
if (num_karts == 0) return;
assert(num_karts <= m_max_karts);
all_scores->resize(num_karts);
(*all_scores)[num_karts-1] = 1; // last position gets one point
sorted_score_increase.resize(num_karts+1); //sorting function is [begin, end[
//get increase data into sorted_score_increase
for(int i=0; i<num_karts; i++)
{
sorted_score_increase[i] = m_score_increase[i];
}
std::sort (sorted_score_increase.begin(), sorted_score_increase.end());
(*all_scores)[num_karts-1] = sorted_score_increase[0]; // last position score
// Must be signed, in case that num_karts==1
for(int i=num_karts-2; i>=0; i--)
{
(*all_scores)[i] = (*all_scores)[i+1] + m_score_increase[i];
(*all_scores)[i] = (*all_scores)[i+1] + sorted_score_increase[num_karts-i];
}
} // getAllScores

View File

@ -408,6 +408,16 @@ namespace UserConfigParams
PARAM_DEFAULT( BoolUserConfigParam(false, "multitouch_enabled",
&m_multitouch_group,
"Enable multitouch support.") );
PARAM_PREFIX IntUserConfigParam m_multitouch_mode
PARAM_DEFAULT( IntUserConfigParam(1, "multitouch_mode",
&m_multitouch_group,
"Steering mode: 0 = off, 1 = buttons"));
PARAM_PREFIX IntUserConfigParam m_multitouch_accelerometer
PARAM_DEFAULT( IntUserConfigParam(0, "multitouch_accelerometer",
&m_multitouch_group,
"Accelerometer mode: 0 = off, 1 = tablet, 2 = phone"));
PARAM_PREFIX FloatUserConfigParam m_multitouch_deadzone_center
PARAM_DEFAULT( FloatUserConfigParam(0.1f, "multitouch_deadzone_center",

View File

@ -206,28 +206,33 @@ void FontWithFace::insertGlyph(wchar_t c, const GlyphInfo& gi)
const unsigned int cur_tex = m_spritebank->getTextureCount() -1;
#ifndef SERVER_ONLY
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
assert(bits->pixel_mode == FT_PIXEL_MODE_GRAY);
if (CVS->isARBTextureSwizzleUsable())
if (bits->buffer != NULL)
{
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE, bits->buffer);
video::ITexture* tex = m_spritebank->getTexture(cur_tex);
glBindTexture(GL_TEXTURE_2D, tex->getOpenGLTextureName());
assert(bits->pixel_mode == FT_PIXEL_MODE_GRAY);
if (CVS->isARBTextureSwizzleUsable())
{
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
bits->width, bits->rows, GL_RED, GL_UNSIGNED_BYTE,
bits->buffer);
}
else
{
const unsigned int size = bits->width * bits->rows;
uint8_t* image_data = new uint8_t[size * 4];
memset(image_data, 255, size * 4);
for (unsigned int i = 0; i < size; i++)
image_data[4 * i + 3] = bits->buffer[i];
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
bits->width, bits->rows, GL_BGRA, GL_UNSIGNED_BYTE,
image_data);
delete[] image_data;
}
if (tex->hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
else
{
const unsigned int size = bits->width * bits->rows;
uint8_t* image_data = new uint8_t[size * 4];
memset(image_data, 255, size * 4);
for (unsigned int i = 0; i < size; i++)
image_data[4 * i + 3] = bits->buffer[i];
glTexSubImage2D(GL_TEXTURE_2D, 0, m_used_width, m_used_height,
bits->width, bits->rows, GL_BGRA, GL_UNSIGNED_BYTE, image_data);
delete[] image_data;
}
if (tex->hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
#endif
// Store the rectangle of current glyph

View File

@ -38,11 +38,10 @@
*/
CameraNormal::CameraNormal(Camera::CameraType type, int camera_index,
AbstractKart* kart)
: Camera(type, camera_index, kart)
: Camera(type, camera_index, kart), m_camera_offset(0, 0, -15.0f)
{
m_distance = kart ? kart->getKartProperties()->getCameraDistance() : 1000.0f;
m_ambient_light = Track::getCurrentTrack()->getDefaultAmbientColor();
m_smooth_dt = 0.0f;
// TODO: Put these values into a config file
// Global or per split screen zone?
@ -53,8 +52,17 @@ CameraNormal::CameraNormal(Camera::CameraType type, int camera_index,
m_target_speed = 10.0f;
m_rotation_range = 0.4f;
m_rotation_range = 0.0f;
m_kart_position = btVector3(0, 0, 0);
m_kart_rotation = btQuaternion(0, 0, 0, 0);
reset();
m_camera->setNearValue(1.0f);
if (kart)
{
btTransform btt = kart->getTrans();
m_kart_position = btt.getOrigin();
m_kart_rotation = btt.getRotation();
}
} // Camera
//-----------------------------------------------------------------------------
@ -65,22 +73,23 @@ CameraNormal::CameraNormal(Camera::CameraType type, int camera_index,
*/
void CameraNormal::smoothMoveCamera(float dt)
{
if(!m_kart) return;
Kart *kart = dynamic_cast<Kart*>(m_kart);
if (kart->isFlying())
{
Vec3 vec3 = m_kart->getXYZ() + Vec3(sin(m_kart->getHeading()) * -4.0f,
0.5f,
cos(m_kart->getHeading()) * -4.0f);
0.5f,
cos(m_kart->getHeading()) * -4.0f);
m_camera->setTarget(m_kart->getXYZ().toIrrVector());
m_camera->setPosition(vec3.toIrrVector());
return;
} // kart is flying
core::vector3df current_position = m_camera->getPosition();
core::vector3df current_position = m_camera->getPosition();
// Smoothly interpolate towards the position and target
const KartProperties *kp = m_kart->getKartProperties();
float max_increase_with_zipper = kp->getZipperMaxSpeedIncrease();
float max_speed_without_zipper = kp->getEngineMaxSpeed();
float current_speed = m_kart->getSmoothedSpeed();
@ -88,44 +97,54 @@ void CameraNormal::smoothMoveCamera(float dt)
float skid_factor = ks->getVisualSkidRotation();
float skid_angle = asin(skid_factor);
float ratio = (current_speed - max_speed_without_zipper) / max_increase_with_zipper;
float ratio = current_speed / max_speed_without_zipper;
ratio = ratio > -0.12f ? ratio : -0.12f;
// distance of camera from kart in x and z plane
float camera_distance = -3 * (0.5f + ratio);
if (camera_distance > -2.0f) camera_distance = -2.0f;
float camera_distance = -1.25f - 2.5f * ratio;
if (camera_distance > -2.0f) camera_distance = -2.0f; // don't get too close to the kart
// Defines how far camera should be from player kart.
Vec3 camera_offset(camera_distance * sin(skid_angle / 2),
1.1f * (1 + ratio / 2),
camera_distance * cos(skid_angle / 2));
Vec3 m_kart_camera_position_with_offset = m_kart->getTrans()(camera_offset);
Vec3 wanted_camera_offset(camera_distance * sin(skid_angle / 2),
(0.85f + ratio / 2.5f),
camera_distance * cos(skid_angle / 2));
//m_smooth_dt = 0.3f * dt + 0.7f * m_smooth_dt;
float delta = (dt*5.0f);
if (delta < 0.0f)
delta = 0.0f;
else if (delta > 1.0f)
delta = 1.0f;
m_camera_offset += (wanted_camera_offset - m_camera_offset) * delta;
float delta2 = dt * 8.0f;
if (delta2 < 0)
delta2 = 0;
else if (delta2 > 1)
delta2 = 1;
btTransform btt = m_kart->getTrans();
m_kart_position = btt.getOrigin();// m_kart_position + (btt.getOrigin() - m_kart_position) * delta2;
m_kart_rotation = m_kart_rotation.normalized().slerp(btt.getRotation().normalized(), delta2);
btt.setOrigin(m_kart_position);
btt.setRotation(m_kart_rotation);
Vec3 m_kart_camera_position_with_offset = btt(m_camera_offset);
// next target
Vec3 current_target = m_kart->getTrans()(Vec3(0, 0.5f, 0));
Vec3 current_target = btt(Vec3(0, 0.5f, 0));
// new required position of camera
core::vector3df wanted_position = m_kart_camera_position_with_offset.toIrrVector();
current_position = m_kart_camera_position_with_offset.toIrrVector();
float f = 5.0f;
if ((current_speed > 5 ) || (current_speed < 0 ))
{
f = current_speed >0 ? current_speed/3 + 1.0f
: -1.5f * current_speed + 2.0f;
}
m_smooth_dt = 0.3f * dt + 0.7f * m_smooth_dt;
current_position += (wanted_position - current_position) * (m_smooth_dt*f);
// Avoid camera crash: if the speed is negative, the current_position
// can oscillate between plus and minus, getting bigger and bigger. If
// this happens often enough, floating point overflow happens (large
// negative speeds can happen when the kart is tumbling/falling)
// To avoid this, we just move the camera to the wanted position if
// the distance becomes too large (see #1356).
if( (current_position - wanted_position).getLengthSQ() > 100)
{
Log::debug("camera", "Resetting camera position to avoid crash");
current_position = wanted_position;
}
//Log::info("CAM_DEBUG", "OFFSET: %f %f %f TRANSFORMED %f %f %f TARGET %f %f %f",
// wanted_camera_offset.x(), wanted_camera_offset.y(), wanted_camera_offset.z(),
// m_kart_camera_position_with_offset.x(), m_kart_camera_position_with_offset.y(),
// m_kart_camera_position_with_offset.z(), current_target.x(), current_target.y(),
// current_target.z());
if(getMode()!=CM_FALLING)
m_camera->setPosition(current_position);

View File

@ -49,8 +49,8 @@ private:
/** Factor of the effects of steering in camera aim. */
float m_rotation_range;
/** Used to smoothly move the camera. */
float m_smooth_dt;
Vec3 m_camera_offset;
void smoothMoveCamera(float dt);
void handleEndCamera(float dt);
void getCameraSettings(float *above_kart, float *cam_angle,
@ -59,6 +59,9 @@ private:
void positionCamera(float dt, float above_kart, float cam_angle,
float side_way, float distance, float smoothing);
btVector3 m_kart_position;
btQuaternion m_kart_rotation;
// Give a few classes access to the constructor (mostly for inheritance)
friend class Camera;
friend class CameraDebug;

View File

@ -91,7 +91,7 @@ void CentralVideoSettings::init()
std::string driver((char*)(glGetString(GL_VERSION)));
std::string card((char*)(glGetString(GL_RENDERER)));
GraphicsRestrictions::init(driver, card);
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FORCE_LEGACY_DEVICE))
{
m_glsl = false;
@ -238,6 +238,13 @@ void CentralVideoSettings::init()
hasTextureStorage = true;
hasTextureSwizzle = true;
}
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXPLICIT_ATTRIB_LOCATION) &&
m_glsl == true)
{
Log::info("GLDriver", "Explicit Attrib Location Present");
hasExplicitAttribLocation = true;
}
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_TEXTURE_FORMAT_BGRA8888) &&
(hasGLExtension("GL_IMG_texture_format_BGRA8888") ||
@ -259,12 +266,19 @@ void CentralVideoSettings::init()
unsigned CentralVideoSettings::getGLSLVersion() const
{
#if defined(USE_GLES2)
if (m_gl_major_version >= 3)
return 300;
else
return 100;
#else
if (m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version == 3))
return m_gl_major_version * 100 + m_gl_minor_version * 10;
else if (m_gl_major_version == 3)
return 100 + (m_gl_minor_version + 3) * 10;
else
return 120;
#endif
}
bool CentralVideoSettings::isGLSL() const

View File

@ -91,13 +91,14 @@ public:
// ============================================================================
/** */
class HeightmapSimulationShader : public Shader <HeightmapSimulationShader,
core::matrix4, int, int,
float,float,float,float,float>
#if !defined(USE_GLES2)
class HeightmapSimulationShader :
public TextureShader<HeightmapSimulationShader, 1,
core::matrix4, int, int,
float, float, float, float,
float>
{
public:
GLuint m_TU_heightmap;
HeightmapSimulationShader()
{
const char *varyings[] = {"new_particle_position", "new_lifetime",
@ -105,12 +106,12 @@ public:
loadTFBProgram("particlesimheightmap.vert", varyings, 4);
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor",
"track_x", "track_x_len", "track_z", "track_z_len");
m_TU_heightmap = 2;
assignTextureUnit(m_TU_heightmap, "heightmap");
assignSamplerNames(0, "heightmap", ST_TEXTURE_BUFFER);
} // HeightmapSimulationShader
}; // class HeightmapSimulationShader
#endif
// ============================================================================
@ -203,6 +204,7 @@ void ParticleSystemProxy::setHeightmap(const std::vector<std::vector<float> > &h
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, heighmapbuffer);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
glBindTexture(GL_TEXTURE_BUFFER, 0);
delete[] hm_array;
#endif
@ -475,10 +477,9 @@ void ParticleSystemProxy::simulate()
{
#if !defined(USE_GLES2)
HeightmapSimulationShader::getInstance()->use();
glActiveTexture(GL_TEXTURE0 + HeightmapSimulationShader::getInstance()->m_TU_heightmap);
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
HeightmapSimulationShader::getInstance()->setTextureUnits(heightmaptexture);
HeightmapSimulationShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor, track_x, track_x_len, track_z, track_z_len);
#endif
#endif
}
else
{

View File

@ -76,7 +76,7 @@ Material::Material(const XMLNode *node, bool deprecated)
init();
bool b = false;
node->get("clampu", &b); if (b) m_clamp_tex |= UCLAMP; //blender 2.4 style
node->get("clampU", &b); if (b) m_clamp_tex |= UCLAMP; //blender 2.5 style
b = false;
@ -745,7 +745,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
ITexture *tex;
ITexture *glossytex;
STKTexManager* stm = STKTexManager::getInstance();
if (m_gloss_map.size() > 0 && UserConfigParams::m_dynamic_lights)
if (m_gloss_map.size() > 0 && CVS->isDefferedEnabled())
{
glossytex = stm->getTexture(m_gloss_map, false/*srgb*/,
false/*premul_alpha*/, false/*set_material*/,
@ -886,7 +886,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_normal_map_tex.size() > 0)
{
if (UserConfigParams::m_dynamic_lights)
if (CVS->isDefferedEnabled())
{
tex = stm->getTexture(m_normal_map_tex, false/*srgb*/,
false/*premul_alpha*/, false/*set_material*/,

View File

@ -709,7 +709,6 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
void ParticleEmitter::addHeightMapAffector(Track* t)
{
if (m_is_glsl)
{
const Vec3* aabb_min;

View File

@ -354,16 +354,16 @@ public:
} // render
}; // BloomShader
static video::ITexture *lensDustTex = 0;
// ============================================================================
class BloomBlendShader : public TextureShader<BloomBlendShader, 4>
{
private:
video::ITexture* m_lens_dust_tex;
public:
BloomBlendShader()
{
if (!lensDustTex)
lensDustTex = irr_driver->getTexture(FileManager::TEXTURE, "gfx_lensDust_a.png");
m_lens_dust_tex =
irr_driver->getTexture(FileManager::TEXTURE, "gfx_lensDust_a.png");
loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
GL_FRAGMENT_SHADER, "bloomblend.frag");
@ -381,7 +381,7 @@ public:
setTextureUnits(render_target_bloom_128,
render_target_bloom_256,
render_target_bloom_512,
lensDustTex->getOpenGLTextureName());
m_lens_dust_tex->getOpenGLTextureName());
drawFullScreenEffect();
} // render
}; // BloomBlendShader

View File

@ -237,7 +237,7 @@ void Referee::selectReadySetGo(int rsg)
return;
video::SMaterial &m = m_scene_node->getMaterial(m_st_traffic_buffer); // m_scene_node->getMesh()->getMeshBuffer(m_st_traffic_buffer)->getMaterial();
//if (irr_driver->isGLSL() && UserConfigParams::m_dynamic_lights)
//if (irr_driver->isGLSL() && CVS->isDefferedEnabled())
// m.MaterialType = irr_driver->getShader(ES_OBJECT_UNLIT);
core::matrix4* matrix = &m.getTextureMatrix(0);

View File

@ -42,7 +42,7 @@ int ShaderBase::loadTFBProgram(const std::string &shader_name,
#ifdef USE_GLES2
loadAndAttachShader(GL_FRAGMENT_SHADER, "tfb_dummy.frag");
#endif
if (CVS->getGLSLVersion() < 330)
if (!CVS->isARBExplicitAttribLocationUsable())
setAttribute(PARTICLES_SIM);
glTransformFeedbackVaryings(m_program, varying_count, varyings,
@ -74,7 +74,7 @@ void ShaderBase::bypassUBO() const
GLint PM = glGetUniformLocation(m_program, "ProjectionMatrix");
glUniformMatrix4fv(PM, 1, GL_FALSE, irr_driver->getProjMatrix().pointer());
GLint PVM = glGetUniformLocation(m_program, "ProjectionViewMatrix");
glUniformMatrix4fv(PVM, 1, GL_FALSE, irr_driver->getProjViewMatrix().pointer());

View File

@ -33,7 +33,7 @@
#include <string>
#include <vector>
/** A simple non-templated base class. It is used to store some enums used in
/** A simple non-templated base class. It is used to store some enums used in
* templates, the actual header for a shader, and a statis list of all kill
* functions (which delete all singletons, and therefore forces a reload of all
* shaders).
@ -301,7 +301,7 @@ public:
* \param index Index of the texture.
* \param uniform Uniform name.
*/
template<typename... T1>
template<typename... T1>
void assignTextureUnit(GLuint index, const char* uniform, T1... rest)
{
glUseProgram(m_program);
@ -349,7 +349,7 @@ public:
{
m_program = glCreateProgram();
loadAndAttachShader(args...);
if (CVS->getGLSLVersion() < 330)
if (!CVS->isARBExplicitAttribLocationUsable())
setAttribute(type);
glLinkProgram(m_program);

View File

@ -787,7 +787,9 @@ void ShaderBasedRenderer::render(float dt)
RaceGUIBase *rg = world->getRaceGUI();
if (rg) rg->update(dt);
if (!CVS->isDefferedEnabled())
bool force_rtt = UserConfigParams::m_scale_rtts_factor != 1.0f;
if (!CVS->isDefferedEnabled() && !force_rtt)
{
prepareForwardRenderer();
}
@ -801,7 +803,7 @@ void ShaderBasedRenderer::render(float dt)
oss << "drawAll() for kart " << cam;
PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (cam+1)*60,
0x00, 0x00);
camera->activate(!CVS->isDefferedEnabled());
camera->activate(!CVS->isDefferedEnabled() && !force_rtt);
rg->preRenderCallback(camera); // adjusts start referee
irr_driver->getSceneManager()->setActiveCamera(camnode);
@ -819,7 +821,7 @@ void ShaderBasedRenderer::render(float dt)
if(CVS->isARBUniformBufferObjectUsable())
uploadLightingData();
PROFILER_POP_CPU_MARKER();
renderScene(camnode, dt, track->hasShadows(), false);
renderScene(camnode, dt, track->hasShadows(), force_rtt);
if (irr_driver->getBoundingBoxesViz())
{
@ -828,7 +830,7 @@ void ShaderBasedRenderer::render(float dt)
debugPhysics();
if (CVS->isDefferedEnabled())
if (CVS->isDefferedEnabled() || force_rtt)
{
renderPostProcessing(camera);
}
@ -942,6 +944,7 @@ void ShaderBasedRenderer::renderToTexture(GL3RenderTarget *render_target,
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::preloadShaderFiles()
{
SharedGPUObjects::init();
ShaderFilesManager* sfm = ShaderFilesManager::getInstance();
sfm->addShaderFile("object_pass.vert", GL_VERTEX_SHADER);

View File

@ -89,7 +89,10 @@ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type)
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
if (CVS->isARBExplicitAttribLocationUsable())
{
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
code << "#define Explicit_Attrib_Location_Usable\n";
}
if (CVS->isAZDOEnabled())
{

View File

@ -259,7 +259,6 @@ void Shaders::loadShaders()
}
initGL();
SharedGPUObjects::init();
} // loadShaders
// ----------------------------------------------------------------------------

View File

@ -56,24 +56,21 @@ public:
} // bindVertexArray
}; // SkyboxShader
class SpecularIBLGenerator : public TextureShader<SpecularIBLGenerator, 1,
#if !defined(USE_GLES2)
class SpecularIBLGenerator : public TextureShader<SpecularIBLGenerator, 2,
core::matrix4, float >
{
public:
GLuint m_tu_samples;
SpecularIBLGenerator()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
GL_FRAGMENT_SHADER, "importance_sampling_specular.frag");
assignUniforms("PermutationMatrix", "ViewportSize");
m_tu_samples = 1;
assignSamplerNames(0, "tex", ST_TRILINEAR_CUBEMAP);
assignTextureUnit(m_tu_samples, "samples");
assignSamplerNames(0, "tex", ST_TRILINEAR_CUBEMAP,
1, "samples", ST_TEXTURE_BUFFER);
}
}; // SpecularIBLGenerator
#endif
namespace {
// ----------------------------------------------------------------------------
@ -277,16 +274,15 @@ void Skybox::generateSpecularCubemap()
}
glBindVertexArray(0);
glActiveTexture(GL_TEXTURE0 +
SpecularIBLGenerator::getInstance()->m_tu_samples);
GLuint sampleTex, sampleBuffer;
glGenBuffers(1, &sampleBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, sampleBuffer);
GLuint sample_texture, sample_buffer;
glGenBuffers(1, &sample_buffer);
glBindBuffer(GL_TEXTURE_BUFFER, sample_buffer);
glBufferData(GL_TEXTURE_BUFFER, 2048 * sizeof(float), tmp,
GL_STATIC_DRAW);
glGenTextures(1, &sampleTex);
glBindTexture(GL_TEXTURE_BUFFER, sampleTex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, sampleBuffer);
glGenTextures(1, &sample_texture);
glBindTexture(GL_TEXTURE_BUFFER, sample_texture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, sample_buffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
for (unsigned face = 0; face < 6; face++)
@ -298,20 +294,19 @@ void Skybox::generateSpecularCubemap()
GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(status == GL_FRAMEBUFFER_COMPLETE);
SpecularIBLGenerator::getInstance()->setTextureUnits(m_cube_map);
SpecularIBLGenerator::getInstance()
->setTextureUnits(m_cube_map, sample_texture);
SpecularIBLGenerator::getInstance()->setUniforms(M[face],
viewportSize);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
glActiveTexture( GL_TEXTURE0
+ SpecularIBLGenerator::getInstance()->m_tu_samples);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
glBindTexture(GL_TEXTURE_BUFFER, 0);
delete[] tmp;
glDeleteTextures(1, &sampleTex);
glDeleteBuffers(1, &sampleBuffer);
glDeleteTextures(1, &sample_texture);
glDeleteBuffers(1, &sample_buffer);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);

View File

@ -1,19 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 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.
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "graphics/stk_mesh_loader.hpp"
#include "graphics/stk_tex_manager.hpp"
@ -1059,7 +1046,7 @@ void STKMeshLoader::loadTextures(SB3dMaterial& material) const
video::ITexture* tex =
STKTexManager::getInstance()->getTexture(full_path.c_str(),
i == 0 ? true : false/*is_srgb*/, false/*premul_alpha*/,
i <= 1 ? true : false/*is_srgb*/, false/*premul_alpha*/,
true/*set_material*/);
material.Material.setTexture(i, tex);

View File

@ -1,19 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 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.
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef HEADER_STK_MESH_LOADER_HPP
#define HEADER_STK_MESH_LOADER_HPP

View File

@ -33,7 +33,8 @@ TextureShaderBase::BindFunction TextureShaderBase::m_all_bind_functions[] =
/* ST_VOLUME_LINEAR_FILTERED */ &TextureShaderBase::bindTextureVolume,
/* ST_NEARED_CLAMPED_FILTERED */ &TextureShaderBase::bindTextureNearestClamped,
/* ST_BILINEAR_CLAMPED_FILTERED */ &TextureShaderBase::bindTextureBilinearClamped,
/* ST_SEMI_TRILINEAR */ &TextureShaderBase::bindTextureSemiTrilinear
/* ST_SEMI_TRILINEAR */ &TextureShaderBase::bindTextureSemiTrilinear,
/* ST_TEXTURE_BUFFER */ &TextureShaderBase::bindTextureBuffer
};
GLuint TextureShaderBase::m_all_texture_types[] =
@ -47,6 +48,10 @@ GLuint TextureShaderBase::m_all_texture_types[] =
/* ST_NEARED_CLAMPED_FILTERED */ GL_TEXTURE_2D,
/* ST_BILINEAR_CLAMPED_FILTERED */ GL_TEXTURE_2D,
/* ST_SEMI_TRILINEAR */ GL_TEXTURE_2D
#ifndef USE_GLES2
/* ST_TEXTURE_BUFFER */, GL_TEXTURE_BUFFER
#endif
};
// ----------------------------------------------------------------------------
@ -116,6 +121,13 @@ void TextureShaderBase::bindTextureNearestClamped(GLuint texture_unit,
} // bindTextureNearestClamped
// ----------------------------------------------------------------------------
void TextureShaderBase::bindTextureBuffer(GLuint texture_unit, GLuint tex_id)
{
#ifndef USE_GLES2
glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_BUFFER, tex_id);
#endif
} // bindTextureBuffer
// ----------------------------------------------------------------------------
void TextureShaderBase::bindTextureBilinear(GLuint texture_unit, GLuint tex)
@ -239,6 +251,10 @@ GLuint TextureShaderBase::createSamplers(SamplerTypeNew sampler_type)
return createBilinearClampedSampler();
case ST_SEMI_TRILINEAR:
return createSemiTrilinearSampler();
#ifndef USE_GLES2
case ST_TEXTURE_BUFFER:
return 0;
#endif
default:
assert(false);
return 0;
@ -248,7 +264,6 @@ GLuint TextureShaderBase::createSamplers(SamplerTypeNew sampler_type)
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createNearestSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -258,13 +273,11 @@ GLuint TextureShaderBase::createNearestSampler()
if (CVS->isEXTTextureFilterAnisotropicUsable())
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
} // createNearestSampler
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createTrilinearSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -279,13 +292,11 @@ GLuint TextureShaderBase::createTrilinearSampler()
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
}
return id;
#endif
} // createTrilinearSampler
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createBilinearSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -295,12 +306,10 @@ GLuint TextureShaderBase::createBilinearSampler()
if (CVS->isEXTTextureFilterAnisotropicUsable())
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
} // createBilinearSampler
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createShadowSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -310,13 +319,11 @@ GLuint TextureShaderBase::createShadowSampler()
glSamplerParameterf(id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glSamplerParameterf(id, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
return id;
#endif
} // createShadowSampler
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createBilinearClampedSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -326,14 +333,12 @@ GLuint TextureShaderBase::createBilinearClampedSampler()
if (CVS->isEXTTextureFilterAnisotropicUsable())
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
} // createBilinearClampedSampler
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createTrilinearClampedArray()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -348,12 +353,10 @@ GLuint TextureShaderBase::createTrilinearClampedArray()
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
}
return id;
#endif
} // createTrilinearClampedArray
// ----------------------------------------------------------------------------
GLuint TextureShaderBase::createSemiTrilinearSampler()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -363,7 +366,6 @@ GLuint TextureShaderBase::createSemiTrilinearSampler()
if (CVS->isEXTTextureFilterAnisotropicUsable())
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
return id;
#endif
} // createSemiTrilinearSampler
// ----------------------------------------------------------------------------

View File

@ -43,13 +43,18 @@ enum SamplerTypeNew
ST_NEARED_CLAMPED_FILTERED,
ST_BILINEAR_CLAMPED_FILTERED,
ST_SEMI_TRILINEAR,
#ifdef USE_GLES2
ST_MAX = ST_SEMI_TRILINEAR
#else
ST_TEXTURE_BUFFER,
ST_MAX = ST_TEXTURE_BUFFER
#endif
}; // SamplerTypeNew
// ============================================================================
/** A simple non-templated base class for a shader that uses textures. A non
* templated base class is necessary to easily handle static objects (like
* list of all bind functions to call) - with templates each instance is a
* templated base class is necessary to easily handle static objects (like
* list of all bind functions to call) - with templates each instance is a
* different class (with different static values).
*/
class TextureShaderBase
@ -68,7 +73,8 @@ protected:
static void bindTextureShadow(GLuint tex_unit, GLuint tex_id);
static void bindTrilinearClampedArrayTexture(GLuint tex_unit, GLuint tex_id);
static void bindTextureVolume(GLuint tex_unit, GLuint tex_id);
static void bindTextureBuffer(GLuint tex_unit, GLuint tex_id);
GLuint createSamplers(SamplerTypeNew sampler_type);
private:
@ -88,7 +94,7 @@ protected:
// ========================================================================
/** Class C needs to be the newly declared shaders class (necessary for
* the instance template). NUM_TEXTURES is the number of texture units
* used in this shader. It is used to test at compile time that the
* used in this shader. It is used to test at compile time that the
* right number of arguments are supplied to the variadic functions.
*/
template<class C, int NUM_TEXTURES, typename...tp>
@ -171,13 +177,15 @@ public:
template<int N, typename... TexIds>
void setTextureUnitsImpl(GLuint tex_id, TexIds... args)
{
#if defined(USE_GLES2)
if (CVS->getGLSLVersion() >= 300)
#else
if (CVS->getGLSLVersion() >= 330)
#endif
{
#ifdef GL_VERSION_3_3
glActiveTexture(GL_TEXTURE0 + m_texture_units[N]);
glBindTexture(m_texture_type[N], tex_id);
glBindSampler(m_texture_units[N], m_sampler_ids[N]);
#endif
}
else
{

View File

@ -199,7 +199,8 @@ bool EventHandler::OnEvent (const SEvent &event)
else if (event.EventType == EET_MOUSE_INPUT_EVENT ||
event.EventType == EET_TOUCH_INPUT_EVENT ||
event.EventType == EET_KEY_INPUT_EVENT ||
event.EventType == EET_JOYSTICK_INPUT_EVENT)
event.EventType == EET_JOYSTICK_INPUT_EVENT ||
event.EventType == EET_ACCELEROMETER_EVENT)
{
// Remember the mouse position
if (event.EventType == EET_MOUSE_INPUT_EVENT &&

View File

@ -1129,30 +1129,26 @@ EventPropagation InputManager::input(const SEvent& event)
// Simulate touch event on non-android devices
#if !defined(ANDROID)
if (UserConfigParams::m_multitouch_enabled == true &&
(type == EMIE_LMOUSE_PRESSED_DOWN || type == EMIE_LMOUSE_LEFT_UP ||
type == EMIE_MOUSE_MOVED))
MultitouchDevice* device = m_device_manager->getMultitouchDevice();
if (device != NULL && (type == EMIE_LMOUSE_PRESSED_DOWN ||
type == EMIE_LMOUSE_LEFT_UP || type == EMIE_MOUSE_MOVED))
{
MultitouchDevice* device = m_device_manager->getMultitouchDevice();
device->m_events[0].id = 0;
device->m_events[0].x = event.MouseInput.X;
device->m_events[0].y = event.MouseInput.Y;
if (device != NULL)
if (type == EMIE_LMOUSE_PRESSED_DOWN)
{
device->m_events[0].id = 0;
device->m_events[0].x = event.MouseInput.X;
device->m_events[0].y = event.MouseInput.Y;
if (type == EMIE_LMOUSE_PRESSED_DOWN)
{
device->m_events[0].touched = true;
}
else if (type == EMIE_LMOUSE_LEFT_UP)
{
device->m_events[0].touched = false;
}
m_device_manager->updateMultitouchDevice();
device->updateDeviceState(0);
device->m_events[0].touched = true;
}
else if (type == EMIE_LMOUSE_LEFT_UP)
{
device->m_events[0].touched = false;
}
m_device_manager->updateMultitouchDevice();
device->updateDeviceState(0);
}
#endif
@ -1169,6 +1165,32 @@ EventPropagation InputManager::input(const SEvent& event)
how fast.
*/
}
else if (event.EventType == EET_ACCELEROMETER_EVENT)
{
MultitouchDevice* device = m_device_manager->getMultitouchDevice();
if (device)
{
for (unsigned int i = 0; i < device->getButtonsCount(); i++)
{
MultitouchButton* button = device->getButton(i);
if (button->type != BUTTON_STEERING)
continue;
if (UserConfigParams::m_multitouch_accelerometer == 1)
{
button->axis_x = -event.AccelerometerEvent.X / 5.0f;
device->handleControls(button);
}
else if (UserConfigParams::m_multitouch_accelerometer == 2)
{
button->axis_x = event.AccelerometerEvent.Y / 5.0f;
device->handleControls(button);
}
}
}
}
// block events in all modes but initial menus (except in text boxes to
// allow typing, and except in modal dialogs in-game)

View File

@ -36,6 +36,11 @@ MultitouchDevice::MultitouchDevice()
m_type = DT_MULTITOUCH;
m_name = "Multitouch";
m_player = NULL;
#ifdef ANDROID
m_android_device = dynamic_cast<CIrrDeviceAndroid*>(
irr_driver->getDevice());
assert(m_android_device != NULL);
#endif
for (MultitouchEvent& event : m_events)
{
@ -53,6 +58,13 @@ MultitouchDevice::MultitouchDevice()
*/
MultitouchDevice::~MultitouchDevice()
{
#ifdef ANDROID
if (m_android_device->isAccelerometerActive())
{
m_android_device->deactivateAccelerometer();
}
#endif
clearButtons();
}
@ -177,8 +189,7 @@ void MultitouchDevice::updateDeviceState(unsigned int event_id)
{
button->pressed = false;
button->event_id = 0;
button->axis_x = 0.0f;
button->axis_y = 0.0f;
updateButtonAxes(button, 0.0f, 0.0f);
}
}
else
@ -190,15 +201,13 @@ void MultitouchDevice::updateDeviceState(unsigned int event_id)
{
if (button->pressed == true)
{
button->axis_x = (float)(event.x - button->x) /
(button->width/2) - 1;
button->axis_y = (float)(event.y - button->y) /
(button->height/2) - 1;
updateButtonAxes(button,
(float)(event.x - button->x) / (button->width/2) - 1,
(float)(event.y - button->y) / (button->height/2) - 1);
}
else
{
button->axis_x = 0.0f;
button->axis_y = 0.0f;
updateButtonAxes(button, 0.0f, 0.0f);
}
if (prev_axis_x != button->axis_x ||
@ -232,6 +241,25 @@ void MultitouchDevice::updateConfigParams()
m_deadzone_edge = UserConfigParams::m_multitouch_deadzone_edge;
m_deadzone_edge = std::min(std::max(m_deadzone_edge, 0.0f), 0.5f);
#ifdef ANDROID
if (UserConfigParams::m_multitouch_accelerometer > 0 &&
!m_android_device->isAccelerometerActive())
{
m_android_device->activateAccelerometer(1.0f / 30);
// Disable accelerometer if it couldn't be activated
if (!m_android_device->isAccelerometerActive())
{
UserConfigParams::m_multitouch_accelerometer = 0;
}
}
else if (UserConfigParams::m_multitouch_accelerometer == 0 &&
m_android_device->isAccelerometerActive())
{
m_android_device->deactivateAccelerometer();
}
#endif
} // updateConfigParams
// ----------------------------------------------------------------------------
@ -249,6 +277,26 @@ float MultitouchDevice::getSteeringFactor(float value)
m_deadzone_center), 1.0f);
}
/** Updates the button axes. It leaves X axis untouched if the accelerometer is
* used for turning left/right
* \param button A button that should be updated
* \param x A value from 0 to 1
* \param y A value from 0 to 1
*/
void MultitouchDevice::updateButtonAxes(MultitouchButton* button, float x,
float y)
{
if (UserConfigParams::m_multitouch_accelerometer == 0)
{
button->axis_x = x;
}
button->axis_y = y;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/** Sends proper action for player controller depending on the button type
* and state.

View File

@ -25,6 +25,10 @@
#include "input/input_device.hpp"
#include "IEventReceiver.h"
#ifdef ANDROID
#include "../../../lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h"
#endif
#define NUMBER_OF_MULTI_TOUCHES 10
enum MultitouchButtonType
@ -77,8 +81,14 @@ private:
/** The parameter that is used for steering button and determines dead area
* at the edge of button */
float m_deadzone_edge;
#ifdef ANDROID
/** Pointer to the Android irrlicht device */
CIrrDeviceAndroid* m_android_device;
#endif
float getSteeringFactor(float value);
void updateButtonAxes(MultitouchButton* button, float x, float y);
public:
/** The array that contains data for all multitouch input events */

498
src/io/assets_android.cpp Normal file
View File

@ -0,0 +1,498 @@
// 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>
#include <sys/statfs.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)
{
std::string preferred_path = getPreferredPath(paths);
if (preferred_path.length() > 0)
{
if (m_file_manager->checkAndCreateDirectoryP(preferred_path +
"/stk/data"))
{
Log::info("AssetsAndroid", "Data directory created in: %s",
preferred_path.c_str());
m_stk_dir = preferred_path + "/stk";
needs_extract_data = true;
}
}
}
// If getPreferredPath failed for some reason, then try to use the first
// available path
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
}
//-----------------------------------------------------------------------------
/** Determines best path for extracting assets, depending on available disk
* space.
* \param paths A list of paths that should be checked
* \return Best path or empty string in case of error
*/
std::string AssetsAndroid::getPreferredPath(const std::vector<std::string>&
paths)
{
#ifdef ANDROID
std::string preferred_path;
int prev_available_space = 0;
for (std::string path : paths)
{
// Paths that start with /data should be used only as a fallback if
// everything other doesn't work, because typical user doesn't have
// access to these directories and i.e. can't manually delete the files
// to clean up device
if (path.find("/data") == 0)
continue;
struct statfs stat;
if (statfs(path.c_str(), &stat) != 0)
continue;
int available_space = (int)((stat.f_bavail * stat.f_bsize) / 1000000);
Log::info("AssetsAndroid", "Available space in '%s': %i MB",
path.c_str(), available_space);
if (available_space > prev_available_space)
{
preferred_path = path;
prev_available_space = available_space;
}
}
return preferred_path;
#endif
return "";
}
//-----------------------------------------------------------------------------

45
src/io/assets_android.hpp Normal file
View File

@ -0,0 +1,45 @@
// 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);
std::string getPreferredPath(const std::vector<std::string>& paths);
public:
AssetsAndroid(FileManager* file_manager);
~AssetsAndroid() {};
void init();
};
#endif

View File

@ -171,10 +171,25 @@ void Attachment::set(AttachmentType type, float time,
// by slowing down.
if(m_type==ATTACH_PARACHUTE)
{
const KartProperties *kp = m_kart->getKartProperties();
float speed_mult;
m_initial_speed = m_kart->getSpeed();
// if going very slowly or backwards, braking won't remove parachute
if(m_initial_speed <= 1.5) m_initial_speed = 1.5;
float f = m_initial_speed / kp->getParachuteMaxSpeed();
float temp_mult = kp->getParachuteDurationSpeedMult();
// duration can't be reduced by higher speed
if (temp_mult < 1.0f) temp_mult = 1.0f;
if (f > 1.0f) f = 1.0f; // cap fraction
speed_mult = 1.0f + (f * (temp_mult - 1.0f));
m_time_left = m_time_left * speed_mult;
if (UserConfigParams::m_graphical_effects)
{
// .blend was created @25 (<10 real, slow computer), make it faster

View File

@ -368,9 +368,9 @@ void Powerup::use()
case PowerupManager::POWERUP_PARACHUTE:
{
AbstractKart* player_kart = NULL;
//Attach a parachutte(that last twice as long as the
//one from the bananas) to all the karts that
//are in front of this one.
//Attach a parachute(that last 1,3 time as long as the
//one from the bananas and is affected by the rank multiplier)
//to all the karts that are in front of this one.
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
{
AbstractKart *kart=world->getKart(i);
@ -382,8 +382,24 @@ void Powerup::use()
}
if(m_kart->getPosition() > kart->getPosition())
{
float rank_mult, position_factor;
//0 if the one before the item user ; 1 if first ; scaled inbetween
if (kart->getPosition() == 1)
{
position_factor = 1.0f;
}
else //m_kart position is always >= 3
{
float rank_factor;
rank_factor = (float)(kart->getPosition() - 1) / (float)(m_kart->getPosition() - 2);
position_factor = 1.0f - rank_factor;
}
rank_mult = 1 + (position_factor * (kp->getParachuteDurationRankMult() - 1));
kart->getAttachment()->set(Attachment::ATTACH_PARACHUTE,
kp->getParachuteDurationOther());
(kp->getParachuteDurationOther() * rank_mult));
if(kart->getController()->isLocalPlayerController())
player_kart = kart;

View File

@ -126,6 +126,10 @@ AbstractCharacteristic::ValueType AbstractCharacteristic::getType(
return TYPE_FLOAT;
case PARACHUTE_DURATION_OTHER:
return TYPE_FLOAT;
case PARACHUTE_DURATION_RANK_MULT:
return TYPE_FLOAT;
case PARACHUTE_DURATION_SPEED_MULT:
return TYPE_FLOAT;
case PARACHUTE_LBOUND_FRACTION:
return TYPE_FLOAT;
case PARACHUTE_UBOUND_FRACTION:
@ -350,6 +354,10 @@ std::string AbstractCharacteristic::getName(CharacteristicType type)
return "PARACHUTE_DURATION";
case PARACHUTE_DURATION_OTHER:
return "PARACHUTE_DURATION_OTHER";
case PARACHUTE_DURATION_RANK_MULT:
return "PARACHUTE_DURATION_RANK_MULT";
case PARACHUTE_DURATION_SPEED_MULT:
return "PARACHUTE_DURATION_SPEED_MULT";
case PARACHUTE_LBOUND_FRACTION:
return "PARACHUTE_LBOUND_FRACTION";
case PARACHUTE_UBOUND_FRACTION:
@ -926,6 +934,30 @@ float AbstractCharacteristic::getParachuteDurationOther() const
return result;
} // getParachuteDurationOther
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteDurationRankMult() const
{
float result;
bool is_set = false;
process(PARACHUTE_DURATION_RANK_MULT, &result, &is_set);
if (!is_set)
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
getName(PARACHUTE_DURATION_RANK_MULT).c_str());
return result;
} // getParachuteDurationRankMult
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteDurationSpeedMult() const
{
float result;
bool is_set = false;
process(PARACHUTE_DURATION_SPEED_MULT, &result, &is_set);
if (!is_set)
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
getName(PARACHUTE_DURATION_SPEED_MULT).c_str());
return result;
} // getParachuteDurationSpeedMult
// ----------------------------------------------------------------------------
float AbstractCharacteristic::getParachuteLboundFraction() const
{

View File

@ -130,6 +130,8 @@ public:
PARACHUTE_FRICTION,
PARACHUTE_DURATION,
PARACHUTE_DURATION_OTHER,
PARACHUTE_DURATION_RANK_MULT,
PARACHUTE_DURATION_SPEED_MULT,
PARACHUTE_LBOUND_FRACTION,
PARACHUTE_UBOUND_FRACTION,
PARACHUTE_MAX_SPEED,
@ -300,6 +302,8 @@ public:
float getParachuteFriction() const;
float getParachuteDuration() const;
float getParachuteDurationOther() const;
float getParachuteDurationRankMult() const;
float getParachuteDurationSpeedMult() const;
float getParachuteLboundFraction() const;
float getParachuteUboundFraction() const;
float getParachuteMaxSpeed() const;

View File

@ -753,6 +753,18 @@ float KartProperties::getParachuteDurationOther() const
return m_cached_characteristic->getParachuteDurationOther();
} // getParachuteDurationOther
// ----------------------------------------------------------------------------
float KartProperties::getParachuteDurationRankMult() const
{
return m_cached_characteristic->getParachuteDurationRankMult();
} // getParachuteDurationRankMult
// ----------------------------------------------------------------------------
float KartProperties::getParachuteDurationSpeedMult() const
{
return m_cached_characteristic->getParachuteDurationSpeedMult();
} // getParachuteDurationSpeedMult
// ----------------------------------------------------------------------------
float KartProperties::getParachuteLboundFraction() const
{

Some files were not shown because too many files have changed in this diff Show More