Add support for Android 2.3+
There have been plenty of ppl involved in creating this version. I don't wanna mention names as I'm sure I'd forget someone so I just tell where help has been done: - The partial android versions done by various ppl - Testing on different android devices - reviewing code (especially the in core changes) - testing controls - reviewing texts A big thank you to everyone helping this to be completed!
13
.gitignore
vendored
@ -64,3 +64,16 @@ locale/
|
|||||||
*.layout
|
*.layout
|
||||||
*.o
|
*.o
|
||||||
|
|
||||||
|
#build variants
|
||||||
|
build/android/assets
|
||||||
|
build/android/bin
|
||||||
|
build/android/Debug
|
||||||
|
build/android/deps
|
||||||
|
build/android/gen
|
||||||
|
build/android/jni/src/*
|
||||||
|
build/android/libs
|
||||||
|
build/android/obj
|
||||||
|
timestamp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
35
build/android/AndroidManifest.xml.template
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.minetest.minetest"
|
||||||
|
android:versionCode="###ANDROID_VERSION###"
|
||||||
|
android:versionName="###BASE_VERSION###.###ANDROID_VERSION###"
|
||||||
|
android:installLocation="auto">
|
||||||
|
<uses-sdk android:minSdkVersion="9"/>
|
||||||
|
<uses-feature android:glEsVersion="0x00010000" android:required="true"/>
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
###DEBUG_BUILD###
|
||||||
|
<application android:icon="@drawable/irr_icon" android:label="Minetest" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ###DEBUG_FLAG###>
|
||||||
|
<activity android:name=".MtNativeActivity"
|
||||||
|
android:label="Minetest"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:configChanges="orientation|keyboardHidden"
|
||||||
|
android:screenOrientation="landscape"
|
||||||
|
android:clearTaskOnLaunch="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.app.lib_name" android:value="minetest" />
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".MinetestTextEntry"
|
||||||
|
android:theme="@style/Theme.Transparent"
|
||||||
|
android:excludeFromRecents="true">
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".MinetestAssetCopy"
|
||||||
|
android:theme="@style/Theme.Transparent"
|
||||||
|
android:excludeFromRecents="true">
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
724
build/android/Makefile
Normal file
@ -0,0 +1,724 @@
|
|||||||
|
# build options
|
||||||
|
|
||||||
|
OS := $(shell uname)
|
||||||
|
|
||||||
|
#automaticaly set number of jobs
|
||||||
|
ifeq ($(OS),Linux)
|
||||||
|
PARALLEL := $(shell grep -c ^processor /proc/cpuinfo)
|
||||||
|
else
|
||||||
|
PARALLEL := 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
# compile with GPROF
|
||||||
|
# GPROF = 1
|
||||||
|
|
||||||
|
# build for build platform
|
||||||
|
APP_PLATFORM = android-9
|
||||||
|
|
||||||
|
# paths used for timestaps, dependencys, tree config and libs
|
||||||
|
PATHCFGFILE = path.cfg
|
||||||
|
|
||||||
|
ROOT = $(shell pwd)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Android Version code
|
||||||
|
# Increase for each build!
|
||||||
|
################################################################################
|
||||||
|
ANDROID_VERSION_CODE = 3
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# toolchain config for arm old processors
|
||||||
|
################################################################################
|
||||||
|
TARGET_HOST = arm-linux
|
||||||
|
TARGET_ABI = armeabi
|
||||||
|
TARGET_LIBDIR = armeabi
|
||||||
|
TARGET_TOOLCHAIN = arm-linux-androideabi-
|
||||||
|
TARGET_CFLAGS_ADDON = -mfloat-abi=softfp -mfpu=vfp
|
||||||
|
CROSS_PREFIX = arm-linux-androideabi-
|
||||||
|
COMPILER_VERSION = 4.8
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# toolchain config for arm new processors
|
||||||
|
################################################################################
|
||||||
|
#TARGET_HOST = arm-linux
|
||||||
|
#TARGET_ABI = armeabi-v7a-hard
|
||||||
|
#TARGET_LIBDIR = armeabi-v7a
|
||||||
|
#TARGET_TOOLCHAIN = arm-linux-androideabi-
|
||||||
|
#TARGET_CFLAGS_ADDON = -mfpu=vfpv3-d16 -D_NDK_MATH_NO_SOFTFP=1 \
|
||||||
|
# -mfloat-abi=hard -march=armv7-a
|
||||||
|
#TARGET_CXXFLAGS_ADDON = $(TARGET_CFLAGS_ADDON)
|
||||||
|
#TARGET_LDFLAGS_ADDON = -Wl,--no-warn-mismatch -lm_hard
|
||||||
|
#CROSS_PREFIX = arm-linux-androideabi-
|
||||||
|
#COMPILER_VERSION = 4.8
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# toolchain config for little endian mips
|
||||||
|
################################################################################
|
||||||
|
#TARGET_HOST = mipsel-linux
|
||||||
|
#TARGET_ABI = mips
|
||||||
|
#TARGET_LIBDIR = mips
|
||||||
|
#TARGET_TOOLCHAIN = mipsel-linux-android-
|
||||||
|
#CROSS_PREFIX = mipsel-linux-android-
|
||||||
|
#COMPILER_VERSION = 4.8
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# toolchain config for x86
|
||||||
|
################################################################################
|
||||||
|
#TARGET_HOST = x86-linux
|
||||||
|
#TARGET_ABI = x86
|
||||||
|
#TARGET_LIBDIR = x86
|
||||||
|
#TARGET_TOOLCHAIN = x86-
|
||||||
|
#CROSS_PREFIX = i686-linux-android-
|
||||||
|
#COMPILER_VERSION = 4.8
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
ASSETS_TIMESTAMP = deps/assets_timestamp
|
||||||
|
|
||||||
|
LEVELDB_DIR = $(ROOT)/deps/leveldb/
|
||||||
|
LEVELDB_LIB = $(LEVELDB_DIR)libleveldb.a
|
||||||
|
LEVELDB_TIMESTAMP = $(LEVELDB_DIR)/timestamp
|
||||||
|
LEVELDB_TIMESTAMP_INT = $(ROOT)/deps/leveldb_timestamp
|
||||||
|
LEVELDB_URL_GIT = https://code.google.com/p/leveldb/
|
||||||
|
|
||||||
|
OPENAL_DIR = $(ROOT)/deps/openal-soft/
|
||||||
|
OPENAL_LIB = $(OPENAL_DIR)libs/$(TARGET_ABI)/libopenal.so
|
||||||
|
OPENAL_TIMESTAMP = $(OPENAL_DIR)/timestamp
|
||||||
|
OPENAL_TIMESTAMP_INT = $(ROOT)/deps/openal_timestamp
|
||||||
|
OPENAL_URL_GIT = https://github.com/apportable/openal-soft
|
||||||
|
|
||||||
|
OGG_DIR = $(ROOT)/deps/libvorbis-libogg-android/
|
||||||
|
OGG_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
|
||||||
|
VORBIS_LIB = $(OGG_DIR)libs/$(TARGET_ABI)/libogg.so
|
||||||
|
OGG_TIMESTAMP = $(OGG_DIR)timestamp
|
||||||
|
OGG_TIMESTAMP_INT = $(ROOT)/deps/ogg_timestamp
|
||||||
|
OGG_URL_GIT = https://github.com/vincentjames501/libvorbis-libogg-android
|
||||||
|
|
||||||
|
IRRLICHT_DIR = $(ROOT)/deps/irrlicht/
|
||||||
|
IRRLICHT_LIB = $(IRRLICHT_DIR)lib/Android/libIrrlicht.a
|
||||||
|
IRRLICHT_TIMESTAMP = $(IRRLICHT_DIR)timestamp
|
||||||
|
IRRLICHT_TIMESTAMP_INT = $(ROOT)/deps/irrlicht_timestamp
|
||||||
|
IRRLICHT_URL_SVN = http://svn.code.sf.net/p/irrlicht/code/branches/ogl-es/
|
||||||
|
|
||||||
|
OPENSSL_BASEDIR = openssl-android
|
||||||
|
OPENSSL_DIR = $(ROOT)/deps/$(OPENSSL_BASEDIR)/
|
||||||
|
OPENSSL_LIB = $(OPENSSL_DIR)libs/$(TARGET_ABI)/libopenssl.so
|
||||||
|
OPENSSL_TIMESTAMP = $(OPENSSL_DIR)timestamp
|
||||||
|
OPENSSL_TIMESTAMP_INT = $(ROOT)/deps/openssl_timestamp
|
||||||
|
OPENSSL_URL_GIT = https://github.com/wobbals/openssl-android
|
||||||
|
|
||||||
|
CURL_VERSION = 7.35.0
|
||||||
|
CURL_DIR = $(ROOT)/deps/curl-$(CURL_VERSION)
|
||||||
|
CURL_LIB = $(CURL_DIR)/lib/.libs/libcurl.a
|
||||||
|
CURL_TIMESTAMP = $(CURL_DIR)/timestamp
|
||||||
|
CURL_TIMESTAMP_INT = $(ROOT)/deps/curl_timestamp
|
||||||
|
CURL_URL_HTTP = http://curl.haxx.se/download/curl-${CURL_VERSION}.tar.bz2
|
||||||
|
|
||||||
|
FREETYPE_DIR = $(ROOT)/deps/freetype2-android/
|
||||||
|
FREETYPE_LIB = $(FREETYPE_DIR)/Android/obj/local/$(TARGER_ABI)/libfreetype2-static.a
|
||||||
|
FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
|
||||||
|
FREETYPE_TIMESTAMP_INT = $(ROOT)/deps/freetype_timestamp
|
||||||
|
FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android
|
||||||
|
|
||||||
|
-include $(PATHCFGFILE)
|
||||||
|
|
||||||
|
.PHONY : debug release reconfig delconfig \
|
||||||
|
leveldb_download clean_leveldb leveldb\
|
||||||
|
irrlicht_download clean_irrlicht irrlicht \
|
||||||
|
clean_assets assets \
|
||||||
|
freetype_download clean_freetype freetype \
|
||||||
|
apk clean_apk \
|
||||||
|
clean_all clean prep_srcdir \
|
||||||
|
install_debug install envpaths all \
|
||||||
|
manifest clean_manifest\
|
||||||
|
$(ASSETS_TIMESTAMP) $(LEVELDB_TIMESTAMP) \
|
||||||
|
$(OPENAL_TIMESTAMP) $(OGG_TIMESTAMP) \
|
||||||
|
$(IRRLICHT_TIMESTAMP) $(CURL_TIMESTAMP) \
|
||||||
|
$(OPENSSL_TIMESTAMP) curl_binary \
|
||||||
|
$(ROOT)/jni/src/android_version.h
|
||||||
|
|
||||||
|
debug : $(PATHCFGFILE)
|
||||||
|
export NDEBUG=; \
|
||||||
|
export BUILD_TYPE=debug; \
|
||||||
|
$(MAKE) -j${PARALLEL} apk
|
||||||
|
|
||||||
|
all : debug release
|
||||||
|
|
||||||
|
release : $(PATHCFGFILE)
|
||||||
|
@export NDEBUG=1; \
|
||||||
|
export BUILD_TYPE=release; \
|
||||||
|
$(MAKE) -j${PARALLEL} apk
|
||||||
|
|
||||||
|
reconfig: delconfig
|
||||||
|
@$(MAKE) -j${PARALLEL} $(PATHCFGFILE)
|
||||||
|
|
||||||
|
delconfig :
|
||||||
|
$(RM) ${PATHCFGFILE}
|
||||||
|
|
||||||
|
$(PATHCFGFILE) :
|
||||||
|
@echo "Please specify path of ANDROID NDK"; \
|
||||||
|
echo "e.g. /home/user/android-ndk-r9c/"; \
|
||||||
|
read ANDROID_NDK ; \
|
||||||
|
if [ ! -d $$ANDROID_NDK ] ; then \
|
||||||
|
echo "$$ANDROID_NDK is not a valid folder"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
echo "ANDROID_NDK = $$ANDROID_NDK" > ${PATHCFGFILE}; \
|
||||||
|
echo "NDK_MODULE_PATH = $$ANDROID_NDK/tools" >> ${PATHCFGFILE}; \
|
||||||
|
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\
|
||||||
|
echo "+ Note: NDK_MODULE_PATH is set to $$ANDROID_NDK/tools"; \
|
||||||
|
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";\
|
||||||
|
echo "Please specify path of ANDROID SDK"; \
|
||||||
|
echo "e.g. /home/user/adt-bundle-linux-x86_64-20131030/sdk/"; \
|
||||||
|
read SDKFLDR ; \
|
||||||
|
if [ ! -d $$SDKFLDR ] ; then \
|
||||||
|
echo "$$SDKFLDR is not a valid folder"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
echo "SDKFOLDER = $$SDKFLDR" >> ${PATHCFGFILE};
|
||||||
|
|
||||||
|
$(OPENAL_TIMESTAMP) : openal_download
|
||||||
|
@LAST_MODIF=$$(find ${OPENAL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${OPENAL_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
openal_download :
|
||||||
|
@if [ ! -d ${OPENAL_DIR} ] ; then \
|
||||||
|
echo "openal sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd ${ROOT}/deps ; \
|
||||||
|
git clone ${OPENAL_URL_GIT} || exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
openal : $(OPENAL_LIB)
|
||||||
|
|
||||||
|
$(OPENAL_LIB): $(OPENAL_TIMESTAMP)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${OPENAL_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${OPENAL_TIMESTAMP} -nt ${OPENAL_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
echo "changed timestamp for openal detected building..."; \
|
||||||
|
cd ${OPENAL_DIR}; \
|
||||||
|
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
||||||
|
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \
|
||||||
|
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
||||||
|
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
||||||
|
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
||||||
|
touch ${OPENAL_TIMESTAMP}; \
|
||||||
|
touch ${OPENAL_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for openal"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_openal :
|
||||||
|
$(RM) -rf ${OPENAL_DIR}
|
||||||
|
|
||||||
|
$(OGG_TIMESTAMP) : ogg_download
|
||||||
|
@LAST_MODIF=$$(find ${OGG_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${OGG_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
ogg_download :
|
||||||
|
@if [ ! -d ${OGG_DIR} ] ; then \
|
||||||
|
echo "ogg sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd ${ROOT}/deps ; \
|
||||||
|
git clone ${OGG_URL_GIT}|| exit 1; \
|
||||||
|
cd libvorbis-libogg-android ; \
|
||||||
|
patch -p1 < ../../libvorbis-libogg-fpu.patch || exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
ogg : $(OGG_LIB)
|
||||||
|
|
||||||
|
$(OGG_LIB): $(OGG_TIMESTAMP)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${OGG_TIMESTAMP_INT} ] ; then \
|
||||||
|
echo "${OGG_TIMESTAMP_INT} doesn't exist"; \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${OGG_TIMESTAMP} -nt ${OGG_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
echo "changed timestamp for ogg detected building..."; \
|
||||||
|
cd ${OGG_DIR}; \
|
||||||
|
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
||||||
|
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \
|
||||||
|
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
||||||
|
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
||||||
|
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
||||||
|
touch ${OGG_TIMESTAMP}; \
|
||||||
|
touch ${OGG_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for libogg/libvorbis"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_ogg :
|
||||||
|
$(RM) -rf ${OGG_DIR}
|
||||||
|
|
||||||
|
$(OPENSSL_TIMESTAMP) : openssl_download
|
||||||
|
@LAST_MODIF=$$(find ${OPENSSL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${OPENSSL_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
openssl_download :
|
||||||
|
@if [ ! -d ${OPENSSL_DIR} ] ; then \
|
||||||
|
echo "openssl sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd ${ROOT}/deps ; \
|
||||||
|
git clone ${OPENSSL_URL_GIT} || exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
openssl : $(OPENSSL_LIB)
|
||||||
|
|
||||||
|
$(OPENSSL_LIB): $(OPENSSL_TIMESTAMP)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${OPENSSL_TIMESTAMP_INT} ] ; then \
|
||||||
|
echo "${OPENSSL_TIMESTAMP_INT} doesn't exist"; \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${OPENSSL_TIMESTAMP} -nt ${OPENSSL_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
echo "changed timestamp for openssl detected building..."; \
|
||||||
|
cd ${OPENSSL_DIR}; \
|
||||||
|
cat jni/Application.mk | grep -v NDK_TOOLCHAIN_VERSION >jni/Application.mk.new;\
|
||||||
|
mv jni/Application.mk.new jni/Application.mk; \
|
||||||
|
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
||||||
|
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \
|
||||||
|
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
||||||
|
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
||||||
|
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
||||||
|
touch ${OPENSSL_TIMESTAMP}; \
|
||||||
|
touch ${OPENSSL_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for openssl"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_openssl :
|
||||||
|
$(RM) -rf ${OPENSSL_DIR}
|
||||||
|
|
||||||
|
$(LEVELDB_TIMESTAMP) : leveldb_download
|
||||||
|
@LAST_MODIF=$$(find ${LEVELDB_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${LEVELDB_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
leveldb_download :
|
||||||
|
@if [ ! -d ${LEVELDB_DIR} ] ; then \
|
||||||
|
echo "leveldb sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd ${ROOT}/deps ; \
|
||||||
|
git clone ${LEVELDB_URL_GIT} || exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
leveldb : $(LEVELDB_LIB)
|
||||||
|
|
||||||
|
$(LEVELDB_LIB): $(LEVELDB_TIMESTAMP)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${LEVELDB_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${LEVELDB_TIMESTAMP} -nt ${LEVELDB_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
export PATH=$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
echo "changed timestamp for leveldb detected building..."; \
|
||||||
|
cd deps/leveldb; \
|
||||||
|
export CROSS_PREFIX=${CROSS_PREFIX}; \
|
||||||
|
export TOOLCHAIN=/tmp/ndk-arm; \
|
||||||
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
|
--install-dir=$${TOOLCHAIN} --system=linux-x86_64; \
|
||||||
|
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
||||||
|
export CC=${CROSS_PREFIX}gcc; \
|
||||||
|
export CXX=${CROSS_PREFIX}g++; \
|
||||||
|
export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \
|
||||||
|
export CPPFLAGS="$${CPPFLAGS} ${TARGET_CFLAGS_ADDON}"; \
|
||||||
|
export LDFLAGS="$${LDFLAGS} ${TARGET_LDFLAGS_ADDON}"; \
|
||||||
|
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
|
||||||
|
$(MAKE) -j${PARALLEL} -s || exit 1; \
|
||||||
|
touch ${LEVELDB_TIMESTAMP}; \
|
||||||
|
touch ${LEVELDB_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for leveldb"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_leveldb :
|
||||||
|
$(RM) -rf deps/leveldb
|
||||||
|
|
||||||
|
$(FREETYPE_TIMESTAMP) : freetype_download
|
||||||
|
@LAST_MODIF=$$(find ${FREETYPE_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${FREETYPE_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
freetype_download :
|
||||||
|
@if [ ! -d ${FREETYPE_DIR} ] ; then \
|
||||||
|
echo "freetype sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd deps; \
|
||||||
|
git clone ${FREETYPE_URL_GIT} || exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
$(IRRLICHT_TIMESTAMP) : irrlicht_download
|
||||||
|
@LAST_MODIF=$$(find ${IRRLICHT_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${IRRLICHT_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
freetype : $(FREETYPE_LIB)
|
||||||
|
|
||||||
|
$(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${FREETYPE_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ! -e ${FREETYPE_LIB} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${FREETYPE_TIMESTAMP} -nt ${FREETYPE_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
mkdir -p ${FREETYPE_DIR}; \
|
||||||
|
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
echo "changed timestamp for freetype detected building..."; \
|
||||||
|
cd ${FREETYPE_DIR}/Android/jni; \
|
||||||
|
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
||||||
|
APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} -j${PARALLEL} \
|
||||||
|
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
||||||
|
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
||||||
|
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
||||||
|
touch ${FREETYPE_TIMESTAMP}; \
|
||||||
|
touch ${FREETYPE_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for freetype"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_freetype :
|
||||||
|
$(RM) -rf ${FREETYPE_DIR}
|
||||||
|
|
||||||
|
#Note: Texturehack patch is required for gpu's not supporting color format
|
||||||
|
# correctly. Known bad GPU:
|
||||||
|
# -geforce on emulator
|
||||||
|
# -Vivante Corporation GC1000 core (e.g. Galaxy Tab 3)
|
||||||
|
|
||||||
|
irrlicht_download :
|
||||||
|
@if [ ! -d "deps/irrlicht" ] ; then \
|
||||||
|
echo "irrlicht sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd deps; \
|
||||||
|
svn co ${IRRLICHT_URL_SVN} irrlicht || exit 1; \
|
||||||
|
cd irrlicht; \
|
||||||
|
patch -p1 < ../../irrlicht-touchcount.patch || exit 1; \
|
||||||
|
patch -p1 < ../../irrlicht-back_button.patch || exit 1; \
|
||||||
|
patch -p1 < ../../irrlicht-texturehack.patch || exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
irrlicht : $(IRRLICHT_LIB)
|
||||||
|
|
||||||
|
$(IRRLICHT_LIB): $(IRRLICHT_TIMESTAMP) $(FREETYPE_LIB)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${IRRLICHT_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ! -e ${IRRLICHT_LIB} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${IRRLICHT_TIMESTAMP} -nt ${IRRLICHT_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
mkdir -p ${IRRLICHT_DIR}; \
|
||||||
|
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
echo "changed timestamp for irrlicht detected building..."; \
|
||||||
|
cd deps/irrlicht/source/Irrlicht/Android; \
|
||||||
|
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
|
||||||
|
APP_ABI=${TARGET_ABI} APP_PLATFORM=${APP_PLATFORM} -j${PARALLEL} \
|
||||||
|
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
||||||
|
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
||||||
|
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
|
||||||
|
touch ${IRRLICHT_TIMESTAMP}; \
|
||||||
|
touch ${IRRLICHT_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for irrlicht"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_irrlicht :
|
||||||
|
$(RM) -rf deps/irrlicht
|
||||||
|
|
||||||
|
$(CURL_TIMESTAMP) : curl_download
|
||||||
|
@LAST_MODIF=$$(find ${CURL_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${CURL_TIMESTAMP}; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl_download :
|
||||||
|
@if [ ! -d "deps/curl-${CURL_VERSION}" ] ; then \
|
||||||
|
echo "curl sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd deps; \
|
||||||
|
wget ${CURL_URL_HTTP} || exit 1; \
|
||||||
|
tar -xjf curl-${CURL_VERSION}.tar.bz2 || exit 1; \
|
||||||
|
rm curl-${CURL_VERSION}.tar.bz2; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl : $(CURL_LIB)
|
||||||
|
|
||||||
|
$(CURL_LIB): $(CURL_TIMESTAMP) $(OPENSSL_LIB)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${CURL_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ! -e ${CURL_LIB} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${CURL_TIMESTAMP} -nt ${CURL_TIMESTAMP_INT} ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
mkdir -p ${CURL_DIR}; \
|
||||||
|
export PATH="$${PATH}:${SDKFOLDER}/platform-tools:${ANDROID_NDK}"; \
|
||||||
|
echo "changed timestamp for curl detected building..."; \
|
||||||
|
cd deps/curl-${CURL_VERSION}; \
|
||||||
|
export CROSS_PREFIX=${CROSS_PREFIX}; \
|
||||||
|
export TOOLCHAIN=/tmp/ndk-arm; \
|
||||||
|
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||||
|
--toolchain=${TARGET_TOOLCHAIN}${COMPILER_VERSION} \
|
||||||
|
--install-dir=$${TOOLCHAIN} --system=linux-x86_64; \
|
||||||
|
export PATH="$${TOOLCHAIN}/bin:$${PATH}"; \
|
||||||
|
export CC=${CROSS_PREFIX}gcc; \
|
||||||
|
export CXX=${CROSS_PREFIX}g++; \
|
||||||
|
export TARGET_OS=OS_ANDROID_CROSSCOMPILE; \
|
||||||
|
export CPPFLAGS="$${CPPFLAGS} -I${OPENSSL_DIR}/include \
|
||||||
|
-L${OPENSSL_DIR}/libs/${TARGET_ABI}/ ${TARGET_CFLAGS_ADDON}"; \
|
||||||
|
export CFLAGS="$${CFLAGS} ${TARGET_CFLAGS_ADDON}"; \
|
||||||
|
export LDFLAGS="$${LDFLAGS} -L${OPENSSL_DIR}/libs/${TARGET_ABI}/ \
|
||||||
|
${TARGET_LDFLAGS_ADDON}"; \
|
||||||
|
./configure --host=${TARGET_HOST} --disable-shared --enable-static --with-ssl; \
|
||||||
|
$(MAKE) -j${PARALLEL} -s || exit 1; \
|
||||||
|
touch ${CURL_TIMESTAMP}; \
|
||||||
|
touch ${CURL_TIMESTAMP_INT}; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for curl"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_curl :
|
||||||
|
$(RM) -rf deps/curl-${CURL_VERSION}
|
||||||
|
|
||||||
|
|
||||||
|
curl_binary:
|
||||||
|
@if [ ! -d "deps/curl-${CURL_VERSION_BINARY}" ] ; then \
|
||||||
|
echo "curl sources missing, downloading..."; \
|
||||||
|
mkdir -p ${ROOT}/deps; \
|
||||||
|
cd deps; \
|
||||||
|
wget http://curl.haxx.se/gknw.net/7.34.0/dist-android/curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\
|
||||||
|
tar -xzf curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz || exit 1;\
|
||||||
|
mv curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android curl-${CURL_VERSION_BINARY};\
|
||||||
|
rm curl-7.34.0-rtmp-ssh2-ssl-zlib-static-bin-android.tar.gz; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
$(ASSETS_TIMESTAMP) : $(IRRLICHT_LIB)
|
||||||
|
@mkdir -p ${ROOT}/deps; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../builtin -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../builtin/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
echo builtin changed $$LAST_MODIF; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../client -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../client/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../doc -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../doc/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../fonts -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../fonts/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../games -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../games/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../mods -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../mods/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../po -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../po/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${ROOT}/../../textures -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${ROOT}/../../textures/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
LAST_MODIF=$$(find ${IRRLICHT_DIR}/media -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
|
||||||
|
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
|
||||||
|
touch ${IRRLICHT_DIR}/media/timestamp; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
if [ ${ROOT}/../../minetest.conf.example -nt ${ASSETS_TIMESTAMP} ] ; then \
|
||||||
|
echo "conf changed"; \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
if [ ${ROOT}/../../README.txt -nt ${ASSETS_TIMESTAMP} ] ; then \
|
||||||
|
touch ${ASSETS_TIMESTAMP}; \
|
||||||
|
fi; \
|
||||||
|
if [ ! -e $(ASSETS_TIMESTAMP) ] ; then \
|
||||||
|
touch $(ASSETS_TIMESTAMP); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
assets : $(ASSETS_TIMESTAMP)
|
||||||
|
@REFRESH=0; \
|
||||||
|
if [ ! -e ${ASSETS_TIMESTAMP}.old ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ${ASSETS_TIMESTAMP} -nt ${ASSETS_TIMESTAMP}.old ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ ! -d ${ROOT}/assets ] ; then \
|
||||||
|
REFRESH=1; \
|
||||||
|
fi; \
|
||||||
|
if [ $$REFRESH -ne 0 ] ; then \
|
||||||
|
echo "assets changed, refreshing..."; \
|
||||||
|
$(MAKE) -j${PARALLEL} clean_assets; \
|
||||||
|
mkdir -p ${ROOT}/assets/Minetest; \
|
||||||
|
cp ${ROOT}/../../minetest.conf.example ${ROOT}/assets/Minetest; \
|
||||||
|
cp ${ROOT}/../../README.txt ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../builtin ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../client ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../doc ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../fonts ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../games ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../mods ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../po ${ROOT}/assets/Minetest; \
|
||||||
|
cp -r ${ROOT}/../../textures ${ROOT}/assets/Minetest; \
|
||||||
|
mkdir -p ${ROOT}/assets/Minetest/media; \
|
||||||
|
cp -r ${IRRLICHT_DIR}/media/Shaders ${ROOT}/assets/Minetest/media; \
|
||||||
|
cd ${ROOT}/assets; \
|
||||||
|
find . -name "timestamp" -exec rm {} \; ; \
|
||||||
|
find . -name "*.blend" -exec rm {} \; ; \
|
||||||
|
ls -R | grep ":$$" | sed -e 's/:$$//' -e 's/\.//' -e 's/^\///' > "index.txt"; \
|
||||||
|
cp ${ROOT}/${ASSETS_TIMESTAMP} ${ROOT}/${ASSETS_TIMESTAMP}.old; \
|
||||||
|
else \
|
||||||
|
echo "nothing to be done for assets"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean_assets :
|
||||||
|
@$(RM) -r assets
|
||||||
|
|
||||||
|
apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) \
|
||||||
|
$(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ROOT)/jni/src/android_version.h
|
||||||
|
@export NDEBUG=$$NDEBUG; $(MAKE) -j${PARALLEL} manifest; \
|
||||||
|
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
|
||||||
|
export ANDROID_HOME=${SDKFOLDER}; \
|
||||||
|
mkdir -p ${ROOT}/src; \
|
||||||
|
ndk-build NDK_MODULE_PATH=${NDK_MODULE_PATH} -j${PARALLEL} \
|
||||||
|
GPROF=${GPROF} APP_ABI=${TARGET_ABI} \
|
||||||
|
APP_PLATFORM=${APP_PLATFORM} \
|
||||||
|
TARGET_LIBDIR=${TARGET_LIBDIR} \
|
||||||
|
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
|
||||||
|
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
|
||||||
|
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" && \
|
||||||
|
ant $$BUILD_TYPE && \
|
||||||
|
echo "++ Success!" && \
|
||||||
|
echo "APK: bin/Minetest-$$BUILD_TYPE.apk" && \
|
||||||
|
echo "You can install it with \`adb install -r bin/Minetest-$$BUILD_TYPE.apk\`"
|
||||||
|
|
||||||
|
prep_srcdir :
|
||||||
|
@rm ${ROOT}/jni/src; \
|
||||||
|
ln -s ${ROOT}/../../src ${ROOT}/jni/src
|
||||||
|
|
||||||
|
clean_apk : manifest
|
||||||
|
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
|
||||||
|
export ANDROID_HOME=${SDKFOLDER}; \
|
||||||
|
ant clean
|
||||||
|
|
||||||
|
install_debug :
|
||||||
|
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
|
||||||
|
adb install -r ${ROOT}/bin/Minetest-debug.apk
|
||||||
|
|
||||||
|
install :
|
||||||
|
@export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}; \
|
||||||
|
adb install -r ${ROOT}/bin/Minetest-release.apk
|
||||||
|
|
||||||
|
envpaths :
|
||||||
|
@echo "export PATH=$$PATH:${SDKFOLDER}platform-tools:${ANDROID_NDK}" > and_env;\
|
||||||
|
echo "export ANDROID_HOME=${SDKFOLDER}" >> and_env;
|
||||||
|
|
||||||
|
clean_all :
|
||||||
|
@$(MAKE) -j${PARALLEL} clean_apk; \
|
||||||
|
$(MAKE) clean_assets clean_irrlicht clean_leveldb clean_curl clean_openssl \
|
||||||
|
clean_openal clean_ogg clean_manifest; \
|
||||||
|
sleep 1; \
|
||||||
|
$(RM) -r gen libs obj deps bin Debug and_env
|
||||||
|
|
||||||
|
$(ROOT)/jni/src/android_version.h :
|
||||||
|
@echo "#define STR_HELPER(x) #x" \
|
||||||
|
>${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define STR(x) STR_HELPER(x)" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define VERSION_MAJOR $$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}')" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define VERSION_MINOR $$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}')" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define VERSION_PATCH $$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define VERSION_PATCH_ORIG $$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}')" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define CMAKE_VERSION_GITHASH \"$$(git rev-parse --short=8 HEAD)\"" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h; \
|
||||||
|
echo "#define CMAKE_VERSION_STRING STR(VERSION_MAJOR)\".\"STR(VERSION_MINOR)\
|
||||||
|
\".\"STR(VERSION_PATCH)" \
|
||||||
|
>> ${ROOT}/jni/src/android_version.h;
|
||||||
|
|
||||||
|
manifest :
|
||||||
|
@VERS_MAJOR=$$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_MAJOR\ | sed 's/)/ /' | awk '{print $$2;}'); \
|
||||||
|
VERS_MINOR=$$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_MINOR\ | sed 's/)/ /' | awk '{print $$2;}'); \
|
||||||
|
VERS_PATCH=$$(cat ${ROOT}/../../CMakeLists.txt | \
|
||||||
|
grep ^set\(VERSION_PATCH\ | sed 's/)/ /' | awk '{print $$2;}'); \
|
||||||
|
BASE_VERSION="$$VERS_MAJOR.$$VERS_MINOR.$$VERS_PATCH"; \
|
||||||
|
if [ "${NDEBUG}x" != "x" ] ; then \
|
||||||
|
DBG=''; \
|
||||||
|
DBG_FLAG="android:debuggable=\"false\""; \
|
||||||
|
else \
|
||||||
|
DBG="<uses-permission android:name=\"android.permission.SET_DEBUG_APP\" />"; \
|
||||||
|
DBG_FLAG="android:debuggable=\"true\""; \
|
||||||
|
fi; \
|
||||||
|
cat ${ROOT}/AndroidManifest.xml.template | \
|
||||||
|
sed s/###ANDROID_VERSION###/${ANDROID_VERSION_CODE}/g | \
|
||||||
|
sed s/###BASE_VERSION###/$$BASE_VERSION/g | \
|
||||||
|
sed -e "s@###DEBUG_BUILD###@$$DBG@g" | \
|
||||||
|
sed -e "s@###DEBUG_FLAG###@$$DBG_FLAG@g" >${ROOT}/AndroidManifest.xml
|
||||||
|
|
||||||
|
clean_manifest :
|
||||||
|
rm -rf ${ROOT}/AndroidManifest.xml
|
||||||
|
|
||||||
|
clean : clean_apk clean_assets
|
16
build/android/build.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="Minetest" default="help">
|
||||||
|
<property file="local.properties" />
|
||||||
|
<property file="ant.properties" />
|
||||||
|
<property environment="env" />
|
||||||
|
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||||
|
<isset property="env.ANDROID_HOME" />
|
||||||
|
</condition>
|
||||||
|
<loadproperties srcFile="project.properties" />
|
||||||
|
<fail
|
||||||
|
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||||
|
unless="sdk.dir"
|
||||||
|
/>
|
||||||
|
<import file="custom_rules.xml" optional="true" />
|
||||||
|
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||||
|
</project>
|
19
build/android/irrlicht-back_button.patch
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
--- irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 20:56:21.289559503 +0200
|
||||||
|
+++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp.orig 2014-06-03 20:57:39.281556749 +0200
|
||||||
|
@@ -423,6 +423,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
device->postEventFromUser(event);
|
||||||
|
+ status = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
@@ -479,7 +480,7 @@
|
||||||
|
KeyMap[1] = KEY_LBUTTON; // AKEYCODE_SOFT_LEFT
|
||||||
|
KeyMap[2] = KEY_RBUTTON; // AKEYCODE_SOFT_RIGHT
|
||||||
|
KeyMap[3] = KEY_HOME; // AKEYCODE_HOME
|
||||||
|
- KeyMap[4] = KEY_BACK; // AKEYCODE_BACK
|
||||||
|
+ KeyMap[4] = KEY_CANCEL; // AKEYCODE_BACK
|
||||||
|
KeyMap[5] = KEY_UNKNOWN; // AKEYCODE_CALL
|
||||||
|
KeyMap[6] = KEY_UNKNOWN; // AKEYCODE_ENDCALL
|
||||||
|
KeyMap[7] = KEY_KEY_0; // AKEYCODE_0
|
240
build/android/irrlicht-texturehack.patch
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
--- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-22 17:01:13.266568869 +0200
|
||||||
|
+++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-22 17:03:59.298572810 +0200
|
||||||
|
@@ -366,112 +366,140 @@
|
||||||
|
void(*convert)(const void*, s32, void*) = 0;
|
||||||
|
getFormatParameters(ColorFormat, InternalFormat, filtering, PixelFormat, PixelType, convert);
|
||||||
|
|
||||||
|
- // make sure we don't change the internal format of existing images
|
||||||
|
- if (!newTexture)
|
||||||
|
- InternalFormat = oldInternalFormat;
|
||||||
|
-
|
||||||
|
- Driver->setActiveTexture(0, this);
|
||||||
|
-
|
||||||
|
- if (Driver->testGLError())
|
||||||
|
- os::Printer::log("Could not bind Texture", ELL_ERROR);
|
||||||
|
-
|
||||||
|
- // mipmap handling for main texture
|
||||||
|
- if (!level && newTexture)
|
||||||
|
- {
|
||||||
|
- // auto generate if possible and no mipmap data is given
|
||||||
|
- if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||||
|
- {
|
||||||
|
- if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||||
|
- glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
|
||||||
|
- else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
|
||||||
|
- glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||||
|
- else
|
||||||
|
- glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
|
||||||
|
+ bool retry = false;
|
||||||
|
+
|
||||||
|
+ do {
|
||||||
|
+ if (retry) {
|
||||||
|
+ InternalFormat = GL_RGBA;
|
||||||
|
+ PixelFormat = GL_RGBA;
|
||||||
|
+ convert = CColorConverter::convert_A8R8G8B8toA8B8G8R8;
|
||||||
|
+ }
|
||||||
|
+ // make sure we don't change the internal format of existing images
|
||||||
|
+ if (!newTexture)
|
||||||
|
+ InternalFormat = oldInternalFormat;
|
||||||
|
|
||||||
|
- glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||||
|
- AutomaticMipmapUpdate=true;
|
||||||
|
- }
|
||||||
|
+ Driver->setActiveTexture(0, this);
|
||||||
|
|
||||||
|
- // enable bilinear filter without mipmaps
|
||||||
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||||
|
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||||
|
- }
|
||||||
|
+ if (Driver->testGLError())
|
||||||
|
+ os::Printer::log("Could not bind Texture", ELL_ERROR);
|
||||||
|
|
||||||
|
- // now get image data and upload to GPU
|
||||||
|
+ // mipmap handling for main texture
|
||||||
|
+ if (!level && newTexture)
|
||||||
|
+ {
|
||||||
|
+ // auto generate if possible and no mipmap data is given
|
||||||
|
+ if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||||
|
+ {
|
||||||
|
+ if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
|
||||||
|
+ glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
|
||||||
|
+ else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
|
||||||
|
+ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||||
|
+ else
|
||||||
|
+ glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
|
||||||
|
+
|
||||||
|
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||||
|
+ AutomaticMipmapUpdate=true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // enable bilinear filter without mipmaps
|
||||||
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||||
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height);
|
||||||
|
+ // now get image data and upload to GPU
|
||||||
|
|
||||||
|
- void* source = image->lock();
|
||||||
|
+ u32 compressedImageSize = IImage::getCompressedImageSize(ColorFormat, image->getDimension().Width, image->getDimension().Height);
|
||||||
|
|
||||||
|
- IImage* tmpImage = 0;
|
||||||
|
+ void* source = image->lock();
|
||||||
|
|
||||||
|
- if (convert)
|
||||||
|
- {
|
||||||
|
- tmpImage = new CImage(image->getColorFormat(), image->getDimension());
|
||||||
|
- void* dest = tmpImage->lock();
|
||||||
|
- convert(source, image->getDimension().getArea(), dest);
|
||||||
|
- image->unlock();
|
||||||
|
- source = dest;
|
||||||
|
- }
|
||||||
|
+ IImage* tmpImage = 0;
|
||||||
|
|
||||||
|
- if (newTexture)
|
||||||
|
- {
|
||||||
|
- if (IsCompressed)
|
||||||
|
+ if (convert)
|
||||||
|
{
|
||||||
|
- glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width,
|
||||||
|
- image->getDimension().Height, 0, compressedImageSize, source);
|
||||||
|
+ tmpImage = new CImage(image->getColorFormat(), image->getDimension());
|
||||||
|
+ void* dest = tmpImage->lock();
|
||||||
|
+ convert(source, image->getDimension().getArea(), dest);
|
||||||
|
+ image->unlock();
|
||||||
|
+ source = dest;
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
|
||||||
|
- image->getDimension().Height, 0, PixelFormat, PixelType, source);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- if (IsCompressed)
|
||||||
|
+
|
||||||
|
+ if (newTexture)
|
||||||
|
{
|
||||||
|
- glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
|
||||||
|
- image->getDimension().Height, PixelFormat, compressedImageSize, source);
|
||||||
|
+ if (IsCompressed)
|
||||||
|
+ {
|
||||||
|
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, image->getDimension().Width,
|
||||||
|
+ image->getDimension().Height, 0, compressedImageSize, source);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
|
||||||
|
+ image->getDimension().Height, 0, PixelFormat, PixelType, source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
- glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
|
||||||
|
- image->getDimension().Height, PixelFormat, PixelType, source);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (convert)
|
||||||
|
- {
|
||||||
|
- tmpImage->unlock();
|
||||||
|
- tmpImage->drop();
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- image->unlock();
|
||||||
|
-
|
||||||
|
- if (!level && newTexture)
|
||||||
|
- {
|
||||||
|
- if (IsCompressed && !mipmapData)
|
||||||
|
{
|
||||||
|
- if (image->hasMipMaps())
|
||||||
|
- mipmapData = static_cast<u8*>(image->lock())+compressedImageSize;
|
||||||
|
+ if (IsCompressed)
|
||||||
|
+ {
|
||||||
|
+ glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
|
||||||
|
+ image->getDimension().Height, PixelFormat, compressedImageSize, source);
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
- HasMipMaps = false;
|
||||||
|
+ glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
|
||||||
|
+ image->getDimension().Height, PixelFormat, PixelType, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
- regenerateMipMapLevels(mipmapData);
|
||||||
|
-
|
||||||
|
- if (HasMipMaps) // might have changed in regenerateMipMapLevels
|
||||||
|
+ if (convert)
|
||||||
|
{
|
||||||
|
- // enable bilinear mipmap filter
|
||||||
|
- GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST;
|
||||||
|
-
|
||||||
|
- if (filtering != GL_LINEAR)
|
||||||
|
- filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST;
|
||||||
|
+ tmpImage->unlock();
|
||||||
|
+ tmpImage->drop();
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ image->unlock();
|
||||||
|
+
|
||||||
|
+ if (glGetError() != GL_NO_ERROR) {
|
||||||
|
+ static bool warned = false;
|
||||||
|
+ if ((!retry) && (ColorFormat == ECF_A8R8G8B8)) {
|
||||||
|
+
|
||||||
|
+ if (!warned) {
|
||||||
|
+ os::Printer::log("Your driver claims to support GL_BGRA but fails on trying to upload a texture, converting to GL_RGBA and trying again", ELL_ERROR);
|
||||||
|
+ warned = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (retry) {
|
||||||
|
+ os::Printer::log("Neither uploading texture as GL_BGRA nor, converted one using GL_RGBA succeeded", ELL_ERROR);
|
||||||
|
+ }
|
||||||
|
+ retry = !retry;
|
||||||
|
+ continue;
|
||||||
|
+ } else {
|
||||||
|
+ retry = false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps);
|
||||||
|
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||||
|
+ if (!level && newTexture)
|
||||||
|
+ {
|
||||||
|
+ if (IsCompressed && !mipmapData)
|
||||||
|
+ {
|
||||||
|
+ if (image->hasMipMaps())
|
||||||
|
+ mipmapData = static_cast<u8*>(image->lock())+compressedImageSize;
|
||||||
|
+ else
|
||||||
|
+ HasMipMaps = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ regenerateMipMapLevels(mipmapData);
|
||||||
|
+
|
||||||
|
+ if (HasMipMaps) // might have changed in regenerateMipMapLevels
|
||||||
|
+ {
|
||||||
|
+ // enable bilinear mipmap filter
|
||||||
|
+ GLint filteringMipMaps = GL_LINEAR_MIPMAP_NEAREST;
|
||||||
|
+
|
||||||
|
+ if (filtering != GL_LINEAR)
|
||||||
|
+ filteringMipMaps = GL_NEAREST_MIPMAP_NEAREST;
|
||||||
|
+
|
||||||
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filteringMipMaps);
|
||||||
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
|
||||||
|
- if (Driver->testGLError())
|
||||||
|
- os::Printer::log("Could not glTexImage2D", ELL_ERROR);
|
||||||
|
+ if (Driver->testGLError())
|
||||||
|
+ os::Printer::log("Could not glTexImage2D", ELL_ERROR);
|
||||||
|
+ }
|
||||||
|
+ while(retry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- irrlicht/source/Irrlicht/COGLESTexture.cpp.orig 2014-06-25 00:28:50.820501856 +0200
|
||||||
|
+++ irrlicht/source/Irrlicht/COGLESTexture.cpp 2014-06-25 00:08:37.712544692 +0200
|
||||||
|
@@ -422,6 +422,9 @@
|
||||||
|
source = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ //clear old error
|
||||||
|
+ glGetError();
|
||||||
|
+
|
||||||
|
if (newTexture)
|
||||||
|
{
|
||||||
|
if (IsCompressed)
|
30
build/android/irrlicht-touchcount.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
--- irrlicht.orig/include/IEventReceiver.h 2014-06-03 19:43:50.433713133 +0200
|
||||||
|
+++ irrlicht/include/IEventReceiver.h 2014-06-03 19:44:36.993711489 +0200
|
||||||
|
@@ -375,6 +375,9 @@
|
||||||
|
// Y position of simple touch.
|
||||||
|
s32 Y;
|
||||||
|
|
||||||
|
+ // number of current touches
|
||||||
|
+ s32 touchedCount;
|
||||||
|
+
|
||||||
|
//! Type of touch event.
|
||||||
|
ETOUCH_INPUT_EVENT Event;
|
||||||
|
};
|
||||||
|
--- irrlicht.orig/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:43:50.505713130 +0200
|
||||||
|
+++ irrlicht/source/Irrlicht/Android/CIrrDeviceAndroid.cpp 2014-06-03 19:45:37.265709359 +0200
|
||||||
|
@@ -315,6 +315,7 @@
|
||||||
|
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, i);
|
||||||
|
event.TouchInput.X = AMotionEvent_getX(androidEvent, i);
|
||||||
|
event.TouchInput.Y = AMotionEvent_getY(androidEvent, i);
|
||||||
|
+ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent);
|
||||||
|
|
||||||
|
device->postEventFromUser(event);
|
||||||
|
}
|
||||||
|
@@ -326,6 +327,7 @@
|
||||||
|
event.TouchInput.ID = AMotionEvent_getPointerId(androidEvent, pointerIndex);
|
||||||
|
event.TouchInput.X = AMotionEvent_getX(androidEvent, pointerIndex);
|
||||||
|
event.TouchInput.Y = AMotionEvent_getY(androidEvent, pointerIndex);
|
||||||
|
+ event.TouchInput.touchedCount = AMotionEvent_getPointerCount(androidEvent);
|
||||||
|
|
||||||
|
device->postEventFromUser(event);
|
||||||
|
}
|
310
build/android/jni/Android.mk
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)/..
|
||||||
|
|
||||||
|
#LOCAL_ADDRESS_SANITIZER:=true
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := Irrlicht
|
||||||
|
LOCAL_SRC_FILES := deps/irrlicht/lib/Android/libIrrlicht.a
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
#include $(CLEAR_VARS)
|
||||||
|
#LOCAL_MODULE := LevelDB
|
||||||
|
#LOCAL_SRC_FILES := deps/leveldb/libleveldb.a
|
||||||
|
#include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := curl
|
||||||
|
LOCAL_SRC_FILES := deps/curl-7.35.0/lib/.libs/libcurl.a
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := freetype
|
||||||
|
LOCAL_SRC_FILES := deps/freetype2-android/Android/obj/local/$(TARGET_ARCH_ABI)/libfreetype2-static.a
|
||||||
|
include $(PREBUILT_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := openal
|
||||||
|
LOCAL_SRC_FILES := deps/openal-soft/libs/$(TARGET_LIBDIR)/libopenal.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := ogg
|
||||||
|
LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libogg.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := vorbis
|
||||||
|
LOCAL_SRC_FILES := deps/libvorbis-libogg-android/libs/$(TARGET_LIBDIR)/libvorbis.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := ssl
|
||||||
|
LOCAL_SRC_FILES := deps/openssl-android/libs/$(TARGET_LIBDIR)/libssl.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := crypto
|
||||||
|
LOCAL_SRC_FILES := deps/openssl-android/libs/$(TARGET_LIBDIR)/libcrypto.so
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := minetest
|
||||||
|
|
||||||
|
LOCAL_CPP_FEATURES += exceptions
|
||||||
|
|
||||||
|
ifdef GPROF
|
||||||
|
GPROF_DEF=-DGPROF
|
||||||
|
endif
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ \
|
||||||
|
-DHAVE_TOUCHSCREENGUI \
|
||||||
|
-DUSE_CURL=1 \
|
||||||
|
-DUSE_SOUND=1 \
|
||||||
|
-DUSE_FREETYPE=1 \
|
||||||
|
$(GPROF_DEF) \
|
||||||
|
-pipe -fstrict-aliasing
|
||||||
|
|
||||||
|
ifndef NDEBUG
|
||||||
|
LOCAL_CFLAGS += -g -D_DEBUG -O0 -fno-omit-frame-pointer
|
||||||
|
else
|
||||||
|
LOCAL_CFLAGS += -fexpensive-optimizations -O3
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef GPROF
|
||||||
|
PROFILER_LIBS := android-ndk-profiler
|
||||||
|
LOCAL_CFLAGS += -pg
|
||||||
|
endif
|
||||||
|
|
||||||
|
# LOCAL_CFLAGS += -fsanitize=address
|
||||||
|
# LOCAL_LDFLAGS += -fsanitize=address
|
||||||
|
|
||||||
|
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||||
|
LOCAL_CFLAGS += -fno-stack-protector
|
||||||
|
endif
|
||||||
|
|
||||||
|
LOCAL_C_INCLUDES := \
|
||||||
|
jni/src jni/src/sqlite \
|
||||||
|
jni/src/script \
|
||||||
|
jni/src/lua/src \
|
||||||
|
jni/src/json \
|
||||||
|
jni/src/cguittfont \
|
||||||
|
deps/irrlicht/include \
|
||||||
|
deps/freetype2-android/include \
|
||||||
|
deps/curl-7.35.0/include \
|
||||||
|
deps/openal-soft/jni/OpenAL/include \
|
||||||
|
deps/libvorbis-libogg-android/jni/include
|
||||||
|
|
||||||
|
# deps/leveldb/include \
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
jni/src/ban.cpp \
|
||||||
|
jni/src/base64.cpp \
|
||||||
|
jni/src/biome.cpp \
|
||||||
|
jni/src/camera.cpp \
|
||||||
|
jni/src/cavegen.cpp \
|
||||||
|
jni/src/chat.cpp \
|
||||||
|
jni/src/client.cpp \
|
||||||
|
jni/src/clientiface.cpp \
|
||||||
|
jni/src/clientmap.cpp \
|
||||||
|
jni/src/clientmedia.cpp \
|
||||||
|
jni/src/clientobject.cpp \
|
||||||
|
jni/src/clouds.cpp \
|
||||||
|
jni/src/collision.cpp \
|
||||||
|
jni/src/connection.cpp \
|
||||||
|
jni/src/content_abm.cpp \
|
||||||
|
jni/src/content_cao.cpp \
|
||||||
|
jni/src/content_cso.cpp \
|
||||||
|
jni/src/content_mapblock.cpp \
|
||||||
|
jni/src/content_mapnode.cpp \
|
||||||
|
jni/src/content_nodemeta.cpp \
|
||||||
|
jni/src/content_sao.cpp \
|
||||||
|
jni/src/convert_json.cpp \
|
||||||
|
jni/src/craftdef.cpp \
|
||||||
|
jni/src/database-dummy.cpp \
|
||||||
|
jni/src/database-sqlite3.cpp \
|
||||||
|
jni/src/database.cpp \
|
||||||
|
jni/src/debug.cpp \
|
||||||
|
jni/src/defaultsettings.cpp \
|
||||||
|
jni/src/drawscene.cpp \
|
||||||
|
jni/src/dungeongen.cpp \
|
||||||
|
jni/src/emerge.cpp \
|
||||||
|
jni/src/environment.cpp \
|
||||||
|
jni/src/filecache.cpp \
|
||||||
|
jni/src/filesys.cpp \
|
||||||
|
jni/src/game.cpp \
|
||||||
|
jni/src/genericobject.cpp \
|
||||||
|
jni/src/gettext.cpp \
|
||||||
|
jni/src/guiChatConsole.cpp \
|
||||||
|
jni/src/guiEngine.cpp \
|
||||||
|
jni/src/guiFileSelectMenu.cpp \
|
||||||
|
jni/src/guiFormSpecMenu.cpp \
|
||||||
|
jni/src/guiKeyChangeMenu.cpp \
|
||||||
|
jni/src/guiPasswordChange.cpp \
|
||||||
|
jni/src/guiTable.cpp \
|
||||||
|
jni/src/guiVolumeChange.cpp \
|
||||||
|
jni/src/httpfetch.cpp \
|
||||||
|
jni/src/hud.cpp \
|
||||||
|
jni/src/inventory.cpp \
|
||||||
|
jni/src/inventorymanager.cpp \
|
||||||
|
jni/src/itemdef.cpp \
|
||||||
|
jni/src/keycode.cpp \
|
||||||
|
jni/src/light.cpp \
|
||||||
|
jni/src/localplayer.cpp \
|
||||||
|
jni/src/log.cpp \
|
||||||
|
jni/src/main.cpp \
|
||||||
|
jni/src/map.cpp \
|
||||||
|
jni/src/mapblock.cpp \
|
||||||
|
jni/src/mapblock_mesh.cpp \
|
||||||
|
jni/src/mapgen.cpp \
|
||||||
|
jni/src/mapgen_indev.cpp \
|
||||||
|
jni/src/mapgen_math.cpp \
|
||||||
|
jni/src/mapgen_singlenode.cpp \
|
||||||
|
jni/src/mapgen_v6.cpp \
|
||||||
|
jni/src/mapgen_v7.cpp \
|
||||||
|
jni/src/mapnode.cpp \
|
||||||
|
jni/src/mapsector.cpp \
|
||||||
|
jni/src/mesh.cpp \
|
||||||
|
jni/src/mods.cpp \
|
||||||
|
jni/src/nameidmapping.cpp \
|
||||||
|
jni/src/nodedef.cpp \
|
||||||
|
jni/src/nodemetadata.cpp \
|
||||||
|
jni/src/nodetimer.cpp \
|
||||||
|
jni/src/noise.cpp \
|
||||||
|
jni/src/object_properties.cpp \
|
||||||
|
jni/src/particles.cpp \
|
||||||
|
jni/src/pathfinder.cpp \
|
||||||
|
jni/src/player.cpp \
|
||||||
|
jni/src/porting_android.cpp \
|
||||||
|
jni/src/porting.cpp \
|
||||||
|
jni/src/quicktune.cpp \
|
||||||
|
jni/src/rollback.cpp \
|
||||||
|
jni/src/rollback_interface.cpp \
|
||||||
|
jni/src/serialization.cpp \
|
||||||
|
jni/src/server.cpp \
|
||||||
|
jni/src/serverlist.cpp \
|
||||||
|
jni/src/serverobject.cpp \
|
||||||
|
jni/src/sha1.cpp \
|
||||||
|
jni/src/shader.cpp \
|
||||||
|
jni/src/sky.cpp \
|
||||||
|
jni/src/socket.cpp \
|
||||||
|
jni/src/sound.cpp \
|
||||||
|
jni/src/sound_openal.cpp \
|
||||||
|
jni/src/staticobject.cpp \
|
||||||
|
jni/src/subgame.cpp \
|
||||||
|
jni/src/test.cpp \
|
||||||
|
jni/src/tile.cpp \
|
||||||
|
jni/src/tool.cpp \
|
||||||
|
jni/src/treegen.cpp \
|
||||||
|
jni/src/version.cpp \
|
||||||
|
jni/src/voxel.cpp \
|
||||||
|
jni/src/voxelalgorithms.cpp \
|
||||||
|
jni/src/util/directiontables.cpp \
|
||||||
|
jni/src/util/numeric.cpp \
|
||||||
|
jni/src/util/pointedthing.cpp \
|
||||||
|
jni/src/util/serialize.cpp \
|
||||||
|
jni/src/util/string.cpp \
|
||||||
|
jni/src/util/timetaker.cpp \
|
||||||
|
jni/src/touchscreengui.cpp
|
||||||
|
|
||||||
|
# jni/src/database-leveldb.cpp \
|
||||||
|
|
||||||
|
# lua api
|
||||||
|
LOCAL_SRC_FILES += \
|
||||||
|
jni/src/script/common/c_content.cpp \
|
||||||
|
jni/src/script/common/c_converter.cpp \
|
||||||
|
jni/src/script/common/c_internal.cpp \
|
||||||
|
jni/src/script/common/c_types.cpp \
|
||||||
|
jni/src/script/cpp_api/s_base.cpp \
|
||||||
|
jni/src/script/cpp_api/s_entity.cpp \
|
||||||
|
jni/src/script/cpp_api/s_env.cpp \
|
||||||
|
jni/src/script/cpp_api/s_inventory.cpp \
|
||||||
|
jni/src/script/cpp_api/s_item.cpp \
|
||||||
|
jni/src/script/cpp_api/s_mainmenu.cpp \
|
||||||
|
jni/src/script/cpp_api/s_node.cpp \
|
||||||
|
jni/src/script/cpp_api/s_nodemeta.cpp \
|
||||||
|
jni/src/script/cpp_api/s_player.cpp \
|
||||||
|
jni/src/script/cpp_api/s_server.cpp \
|
||||||
|
jni/src/script/cpp_api/s_async.cpp \
|
||||||
|
jni/src/script/lua_api/l_base.cpp \
|
||||||
|
jni/src/script/lua_api/l_craft.cpp \
|
||||||
|
jni/src/script/lua_api/l_env.cpp \
|
||||||
|
jni/src/script/lua_api/l_inventory.cpp \
|
||||||
|
jni/src/script/lua_api/l_item.cpp \
|
||||||
|
jni/src/script/lua_api/l_mainmenu.cpp \
|
||||||
|
jni/src/script/lua_api/l_mapgen.cpp \
|
||||||
|
jni/src/script/lua_api/l_nodemeta.cpp \
|
||||||
|
jni/src/script/lua_api/l_nodetimer.cpp \
|
||||||
|
jni/src/script/lua_api/l_noise.cpp \
|
||||||
|
jni/src/script/lua_api/l_object.cpp \
|
||||||
|
jni/src/script/lua_api/l_particles.cpp \
|
||||||
|
jni/src/script/lua_api/l_rollback.cpp \
|
||||||
|
jni/src/script/lua_api/l_server.cpp \
|
||||||
|
jni/src/script/lua_api/l_settings.cpp \
|
||||||
|
jni/src/script/lua_api/l_util.cpp \
|
||||||
|
jni/src/script/lua_api/l_vmanip.cpp \
|
||||||
|
jni/src/script/scripting_game.cpp \
|
||||||
|
jni/src/script/scripting_mainmenu.cpp
|
||||||
|
|
||||||
|
#freetype2 support
|
||||||
|
LOCAL_SRC_FILES += \
|
||||||
|
jni/src/cguittfont/xCGUITTFont.cpp
|
||||||
|
|
||||||
|
# lua
|
||||||
|
LOCAL_SRC_FILES += \
|
||||||
|
jni/src/lua/src/lapi.c \
|
||||||
|
jni/src/lua/src/lauxlib.c \
|
||||||
|
jni/src/lua/src/lbaselib.c \
|
||||||
|
jni/src/lua/src/lcode.c \
|
||||||
|
jni/src/lua/src/ldblib.c \
|
||||||
|
jni/src/lua/src/ldebug.c \
|
||||||
|
jni/src/lua/src/ldo.c \
|
||||||
|
jni/src/lua/src/ldump.c \
|
||||||
|
jni/src/lua/src/lfunc.c \
|
||||||
|
jni/src/lua/src/lgc.c \
|
||||||
|
jni/src/lua/src/linit.c \
|
||||||
|
jni/src/lua/src/liolib.c \
|
||||||
|
jni/src/lua/src/llex.c \
|
||||||
|
jni/src/lua/src/lmathlib.c \
|
||||||
|
jni/src/lua/src/lmem.c \
|
||||||
|
jni/src/lua/src/loadlib.c \
|
||||||
|
jni/src/lua/src/lobject.c \
|
||||||
|
jni/src/lua/src/lopcodes.c \
|
||||||
|
jni/src/lua/src/loslib.c \
|
||||||
|
jni/src/lua/src/lparser.c \
|
||||||
|
jni/src/lua/src/lstate.c \
|
||||||
|
jni/src/lua/src/lstring.c \
|
||||||
|
jni/src/lua/src/lstrlib.c \
|
||||||
|
jni/src/lua/src/ltable.c \
|
||||||
|
jni/src/lua/src/ltablib.c \
|
||||||
|
jni/src/lua/src/ltm.c \
|
||||||
|
jni/src/lua/src/lundump.c \
|
||||||
|
jni/src/lua/src/lvm.c \
|
||||||
|
jni/src/lua/src/lzio.c \
|
||||||
|
jni/src/lua/src/print.c
|
||||||
|
|
||||||
|
# sqlite
|
||||||
|
LOCAL_SRC_FILES += jni/src/sqlite/sqlite3.c
|
||||||
|
|
||||||
|
# jthread
|
||||||
|
LOCAL_SRC_FILES += \
|
||||||
|
jni/src/jthread/pthread/jevent.cpp \
|
||||||
|
jni/src/jthread/pthread/jmutex.cpp \
|
||||||
|
jni/src/jthread/pthread/jsemaphore.cpp \
|
||||||
|
jni/src/jthread/pthread/jthread.cpp
|
||||||
|
|
||||||
|
# json
|
||||||
|
LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp
|
||||||
|
|
||||||
|
LOCAL_SHARED_LIBRARIES := openal ogg vorbis ssl crypto
|
||||||
|
LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl android_native_app_glue $(PROFILER_LIBS)
|
||||||
|
# LevelDB
|
||||||
|
LOCAL_LDLIBS := -lEGL -llog -lGLESv1_CM -lGLESv2 -lz -landroid
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
# at the end of Android.mk
|
||||||
|
ifdef GPROF
|
||||||
|
$(call import-module,android-ndk-profiler)
|
||||||
|
endif
|
||||||
|
$(call import-module,android/native_app_glue)
|
8
build/android/jni/Application.mk
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# NDK_TOOLCHAIN_VERSION := clang3.3
|
||||||
|
|
||||||
|
APP_PLATFORM := android-9
|
||||||
|
APP_MODULES := minetest
|
||||||
|
APP_STL := gnustl_static
|
||||||
|
|
||||||
|
APP_CPPFLAGS += -fexceptions
|
||||||
|
APP_GNUSTL_FORCE_CPP_FEATURES := rtti
|
37
build/android/libvorbis-libogg-fpu.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
--- libvorbis-libogg-android/jni/libvorbis-jni/Android.mk.orig 2014-06-17 19:22:50.621559073 +0200
|
||||||
|
+++ libvorbis-libogg-android/jni/libvorbis-jni/Android.mk 2014-06-17 19:38:20.641581140 +0200
|
||||||
|
@@ -4,9 +4,6 @@
|
||||||
|
|
||||||
|
LOCAL_MODULE := vorbis-jni
|
||||||
|
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -fsigned-char
|
||||||
|
-ifeq ($(TARGET_ARCH),arm)
|
||||||
|
- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp
|
||||||
|
-endif
|
||||||
|
|
||||||
|
LOCAL_SHARED_LIBRARIES := libogg libvorbis
|
||||||
|
|
||||||
|
--- libvorbis-libogg-android/jni/libvorbis/Android.mk.orig 2014-06-17 19:22:39.077558797 +0200
|
||||||
|
+++ libvorbis-libogg-android/jni/libvorbis/Android.mk 2014-06-17 19:38:52.121581887 +0200
|
||||||
|
@@ -4,9 +4,6 @@
|
||||||
|
|
||||||
|
LOCAL_MODULE := libvorbis
|
||||||
|
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char
|
||||||
|
-ifeq ($(TARGET_ARCH),arm)
|
||||||
|
- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp
|
||||||
|
-endif
|
||||||
|
LOCAL_SHARED_LIBRARIES := libogg
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
--- libvorbis-libogg-android/jni/libogg/Android.mk.orig 2014-06-17 19:22:33.965558675 +0200
|
||||||
|
+++ libvorbis-libogg-android/jni/libogg/Android.mk 2014-06-17 19:38:25.337581252 +0200
|
||||||
|
@@ -4,10 +4,6 @@
|
||||||
|
|
||||||
|
LOCAL_MODULE := libogg
|
||||||
|
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../include -ffast-math -fsigned-char
|
||||||
|
-ifeq ($(TARGET_ARCH),arm)
|
||||||
|
- LOCAL_CFLAGS += -march=armv6 -marm -mfloat-abi=softfp -mfpu=vfp
|
||||||
|
-endif
|
||||||
|
-
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
bitwise.c \
|
1
build/android/project.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
target=android-10
|
BIN
build/android/res/drawable-hdpi/irr_icon.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
build/android/res/drawable-ldpi/irr_icon.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
build/android/res/drawable-mdpi/irr_icon.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
build/android/res/drawable-xhdpi/irr_icon.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
22
build/android/res/layout/assetcopy.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar1"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="preparing media ..."
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
11
build/android/res/values/styles.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="Theme.Transparent" parent="android:Theme">
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
|
<item name="android:windowContentOverlay">@null</item>
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:windowIsFloating">true</item>
|
||||||
|
<item name="android:backgroundDimEnabled">false</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
288
build/android/src/org/minetest/minetest/MinetestAssetCopy.java
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
package org.minetest.minetest;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class MinetestAssetCopy extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.assetcopy);
|
||||||
|
|
||||||
|
m_ProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
|
||||||
|
m_Filename = (TextView) findViewById(R.id.textView1);
|
||||||
|
|
||||||
|
Display display = getWindowManager().getDefaultDisplay();
|
||||||
|
m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8);
|
||||||
|
m_ProgressBar.invalidate();
|
||||||
|
|
||||||
|
m_AssetCopy = new copyAssetTask();
|
||||||
|
m_AssetCopy.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar m_ProgressBar;
|
||||||
|
TextView m_Filename;
|
||||||
|
|
||||||
|
copyAssetTask m_AssetCopy;
|
||||||
|
|
||||||
|
private class copyAssetTask extends AsyncTask<String, Integer, String>{
|
||||||
|
|
||||||
|
private void copyElement(String name, String path) {
|
||||||
|
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||||
|
String full_path;
|
||||||
|
if (path != "") {
|
||||||
|
full_path = path + "/" + name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
full_path = name;
|
||||||
|
}
|
||||||
|
//is a folder read asset list
|
||||||
|
if (m_foldernames.contains(full_path)) {
|
||||||
|
m_Foldername = full_path;
|
||||||
|
publishProgress(0);
|
||||||
|
File current_folder = new File(baseDir + "/" + full_path);
|
||||||
|
if (!current_folder.exists()) {
|
||||||
|
if (!current_folder.mkdirs()) {
|
||||||
|
Log.w("MinetestAssetCopy","\t failed create folder: " + baseDir + "/" + full_path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.w("MinetestAssetCopy","\t created folder: " + baseDir + "/" + full_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String[] current_assets = getAssets().list(full_path);
|
||||||
|
for(int i=0; i < current_assets.length; i++) {
|
||||||
|
copyElement(current_assets[i],full_path);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w("MinetestAssetCopy","\t failed to read contents of folder");
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//is a file just copy
|
||||||
|
else {
|
||||||
|
boolean refresh = true;
|
||||||
|
|
||||||
|
File testme = new File(baseDir + "/" + full_path);
|
||||||
|
|
||||||
|
long asset_filesize = -1;
|
||||||
|
long stored_filesize = -1;
|
||||||
|
|
||||||
|
if (testme.exists()) {
|
||||||
|
try {
|
||||||
|
AssetFileDescriptor fd = getAssets().openFd(full_path);
|
||||||
|
asset_filesize = fd.getLength();
|
||||||
|
fd.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
refresh = true;
|
||||||
|
m_asset_size_unknown.add(full_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
stored_filesize = testme.length();
|
||||||
|
|
||||||
|
if (asset_filesize == stored_filesize) {
|
||||||
|
refresh = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refresh) {
|
||||||
|
m_tocopy.add(full_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getFullSize(String filename) {
|
||||||
|
long size = 0;
|
||||||
|
try {
|
||||||
|
InputStream src = getAssets().open(filename);
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
while ((len = src.read(buf)) > 0) {
|
||||||
|
size += len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String doInBackground(String... files) {
|
||||||
|
|
||||||
|
m_foldernames = new Vector<String>();
|
||||||
|
m_tocopy = new Vector<String>();
|
||||||
|
m_asset_size_unknown = new Vector<String>();
|
||||||
|
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
|
||||||
|
|
||||||
|
File TempFolder = new File(baseDir + "Minetest/tmp/");
|
||||||
|
|
||||||
|
if (!TempFolder.exists()) {
|
||||||
|
TempFolder.mkdir();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
File[] todel = TempFolder.listFiles();
|
||||||
|
|
||||||
|
for(int i=0; i < todel.length; i++) {
|
||||||
|
Log.w("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath());
|
||||||
|
todel[i].delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a .nomedia file
|
||||||
|
try {
|
||||||
|
OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia");
|
||||||
|
dst.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w("MinetestAssetCopy","Failed to create .nomedia file");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream is = getAssets().open("index.txt");
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||||
|
|
||||||
|
String line = reader.readLine();
|
||||||
|
while(line != null){
|
||||||
|
m_foldernames.add(line);
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
} catch (IOException e1) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
copyElement("Minetest","");
|
||||||
|
|
||||||
|
m_copy_started = true;
|
||||||
|
m_ProgressBar.setMax(m_tocopy.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < m_tocopy.size(); i++) {
|
||||||
|
try {
|
||||||
|
String filename = m_tocopy.get(i);
|
||||||
|
publishProgress(i);
|
||||||
|
|
||||||
|
boolean asset_size_unknown = false;
|
||||||
|
long filesize = -1;
|
||||||
|
|
||||||
|
if (m_asset_size_unknown.contains(filename)) {
|
||||||
|
File testme = new File(baseDir + "/" + filename);
|
||||||
|
|
||||||
|
if(testme.exists()) {
|
||||||
|
filesize = testme.length();
|
||||||
|
}
|
||||||
|
asset_size_unknown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream src;
|
||||||
|
try {
|
||||||
|
src = getAssets().open(filename);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)");
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer bytes from in to out
|
||||||
|
byte[] buf = new byte[1*1024];
|
||||||
|
int len = src.read(buf, 0, 1024);
|
||||||
|
|
||||||
|
/* following handling is crazy but we need to deal with */
|
||||||
|
/* compressed assets.Flash chips limited livetime sue to */
|
||||||
|
/* write operations, we can't allow large files to destroy */
|
||||||
|
/* users flash. */
|
||||||
|
if (asset_size_unknown) {
|
||||||
|
if ( (len > 0) && (len < buf.length) && (len == filesize)) {
|
||||||
|
src.close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == buf.length) {
|
||||||
|
src.close();
|
||||||
|
long size = getFullSize(filename);
|
||||||
|
if ( size == filesize) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
src = getAssets().open(filename);
|
||||||
|
len = src.read(buf, 0, 1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
int total_filesize = 0;
|
||||||
|
OutputStream dst;
|
||||||
|
try {
|
||||||
|
dst = new FileOutputStream(baseDir + "/" + filename);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w("MinetestAssetCopy","Copying file: " + baseDir +
|
||||||
|
"/" + filename + " FAILED (couldn't open output file)");
|
||||||
|
e.printStackTrace();
|
||||||
|
src.close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dst.write(buf, 0, len);
|
||||||
|
total_filesize += len;
|
||||||
|
|
||||||
|
while ((len = src.read(buf)) > 0) {
|
||||||
|
dst.write(buf, 0, len);
|
||||||
|
total_filesize += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.close();
|
||||||
|
Log.w("MinetestAssetCopy","Copied file: " + m_tocopy.get(i) + " (" + total_filesize + " bytes)");
|
||||||
|
}
|
||||||
|
else if (len < 0) {
|
||||||
|
Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed, size < 0");
|
||||||
|
}
|
||||||
|
src.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w("MinetestAssetCopy","Copying file: " + m_tocopy.get(i) + " failed");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
|
if (m_copy_started) {
|
||||||
|
m_ProgressBar.setProgress(progress[0]);
|
||||||
|
m_Filename.setText(m_tocopy.get(progress[0]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_Filename.setText("scanning " + m_Foldername + " ...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute (String result) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
boolean m_copy_started = false;
|
||||||
|
String m_Foldername = "media";
|
||||||
|
Vector<String> m_foldernames;
|
||||||
|
Vector<String> m_tocopy;
|
||||||
|
Vector<String> m_asset_size_unknown;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package org.minetest.minetest;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnKeyListener;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
public class MinetestTextEntry extends Activity {
|
||||||
|
public AlertDialog mTextInputDialog;
|
||||||
|
public EditText mTextInputWidget;
|
||||||
|
|
||||||
|
private final int MultiLineTextInput = 1;
|
||||||
|
private final int SingleLineTextInput = 2;
|
||||||
|
private final int SingleLinePasswordInput = 3;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
Bundle b = getIntent().getExtras();
|
||||||
|
String acceptButton = b.getString("EnterButton");
|
||||||
|
String hint = b.getString("hint");
|
||||||
|
String current = b.getString("current");
|
||||||
|
int editType = b.getInt("editType");
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
mTextInputWidget = new EditText(this);
|
||||||
|
mTextInputWidget.setHint(hint);
|
||||||
|
mTextInputWidget.setText(current);
|
||||||
|
mTextInputWidget.setMinWidth(300);
|
||||||
|
if (editType == SingleLinePasswordInput) {
|
||||||
|
mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT |
|
||||||
|
InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mTextInputWidget.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
builder.setView(mTextInputWidget);
|
||||||
|
|
||||||
|
if (editType == MultiLineTextInput) {
|
||||||
|
builder.setPositiveButton(acceptButton, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int whichButton)
|
||||||
|
{ pushResult(mTextInputWidget.getText().toString()); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||||
|
public void onCancel(DialogInterface dialog) {
|
||||||
|
cancelDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mTextInputWidget.setOnKeyListener(new OnKeyListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onKey(View view, int KeyCode, KeyEvent event) {
|
||||||
|
if ( KeyCode == KeyEvent.KEYCODE_ENTER){
|
||||||
|
|
||||||
|
pushResult(mTextInputWidget.getText().toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mTextInputDialog = builder.create();
|
||||||
|
mTextInputDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushResult(String text) {
|
||||||
|
Intent resultData = new Intent();
|
||||||
|
resultData.putExtra("text", text);
|
||||||
|
setResult(Activity.RESULT_OK,resultData);
|
||||||
|
mTextInputDialog.dismiss();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelDialog() {
|
||||||
|
setResult(Activity.RESULT_CANCELED);
|
||||||
|
mTextInputDialog.dismiss();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package org.minetest.minetest;
|
||||||
|
|
||||||
|
import android.app.NativeActivity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
public class MtNativeActivity extends NativeActivity {
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
m_MessagReturnCode = -1;
|
||||||
|
m_MessageReturnValue = "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void copyAssets() {
|
||||||
|
Intent intent = new Intent(this, MinetestAssetCopy.class);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showDialog(String acceptButton, String hint, String current,
|
||||||
|
int editType) {
|
||||||
|
|
||||||
|
Intent intent = new Intent(this, MinetestTextEntry.class);
|
||||||
|
Bundle params = new Bundle();
|
||||||
|
params.putString("acceptButton", acceptButton);
|
||||||
|
params.putString("hint", hint);
|
||||||
|
params.putString("current", current);
|
||||||
|
params.putInt("editType", editType);
|
||||||
|
intent.putExtras(params);
|
||||||
|
startActivityForResult(intent, 101);
|
||||||
|
m_MessageReturnValue = "";
|
||||||
|
m_MessagReturnCode = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native void putMessageBoxResult(String text);
|
||||||
|
|
||||||
|
/* ugly code to workaround putMessageBoxResult not beeing found */
|
||||||
|
public int getDialogState() {
|
||||||
|
return m_MessagReturnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDialogValue() {
|
||||||
|
m_MessagReturnCode = -1;
|
||||||
|
return m_MessageReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getDensity() {
|
||||||
|
return getResources().getDisplayMetrics().density;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayWidth() {
|
||||||
|
return getResources().getDisplayMetrics().widthPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayHeight() {
|
||||||
|
return getResources().getDisplayMetrics().heightPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode,
|
||||||
|
Intent data) {
|
||||||
|
if (requestCode == 101) {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
String text = data.getStringExtra("text");
|
||||||
|
m_MessagReturnCode = 0;
|
||||||
|
m_MessageReturnValue = text;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_MessagReturnCode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
System.loadLibrary("openal");
|
||||||
|
System.loadLibrary("ogg");
|
||||||
|
System.loadLibrary("vorbis");
|
||||||
|
System.loadLibrary("ssl");
|
||||||
|
System.loadLibrary("crypto");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int m_MessagReturnCode;
|
||||||
|
private String m_MessageReturnValue;
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
|
||||||
local function create_world_formspec(dialogdata)
|
local function delete_world_formspec(dialogdata)
|
||||||
|
|
||||||
local retval =
|
local retval =
|
||||||
"size[12,6,true]" ..
|
"size[12,6,true]" ..
|
||||||
@ -27,7 +27,7 @@ local function create_world_formspec(dialogdata)
|
|||||||
return retval
|
return retval
|
||||||
end
|
end
|
||||||
|
|
||||||
local function create_world_buttonhandler(this, fields)
|
local function delete_world_buttonhandler(this, fields)
|
||||||
if fields["world_delete_confirm"] then
|
if fields["world_delete_confirm"] then
|
||||||
|
|
||||||
if this.data.delete_index > 0 and
|
if this.data.delete_index > 0 and
|
||||||
@ -53,9 +53,9 @@ function create_delete_world_dlg(name_to_del,index_to_del)
|
|||||||
assert(name_to_del ~= nil and type(name_to_del) == "string" and name_to_del ~= "")
|
assert(name_to_del ~= nil and type(name_to_del) == "string" and name_to_del ~= "")
|
||||||
assert(index_to_del ~= nil and type(index_to_del) == "number")
|
assert(index_to_del ~= nil and type(index_to_del) == "number")
|
||||||
|
|
||||||
local retval = dialog_create("sp_create_world",
|
local retval = dialog_create("delete_world",
|
||||||
create_world_formspec,
|
delete_world_formspec,
|
||||||
create_world_buttonhandler,
|
delete_world_buttonhandler,
|
||||||
nil)
|
nil)
|
||||||
retval.data.delete_name = name_to_del
|
retval.data.delete_name = name_to_del
|
||||||
retval.data.delete_index = index_to_del
|
retval.data.delete_index = index_to_del
|
||||||
|
102
builtin/mainmenu/init_android.lua
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2014 sapier
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
mt_color_grey = "#AAAAAA"
|
||||||
|
mt_color_blue = "#0000DD"
|
||||||
|
mt_color_green = "#00DD00"
|
||||||
|
mt_color_dark_green = "#003300"
|
||||||
|
|
||||||
|
--marker for android specific code
|
||||||
|
ANDROID = true
|
||||||
|
|
||||||
|
local menupath = core.get_mainmenu_path()
|
||||||
|
local basepath = core.get_builtin_path()
|
||||||
|
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
|
||||||
|
DIR_DELIM .. "pack" .. DIR_DELIM
|
||||||
|
|
||||||
|
dofile(basepath .. DIR_DELIM .. "common" .. DIR_DELIM .. "async_event.lua")
|
||||||
|
dofile(basepath .. DIR_DELIM .. "common" .. DIR_DELIM .. "filterlist.lua")
|
||||||
|
dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "buttonbar.lua")
|
||||||
|
dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "dialog.lua")
|
||||||
|
dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "tabview.lua")
|
||||||
|
dofile(basepath .. DIR_DELIM .. "fstk" .. DIR_DELIM .. "ui.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "common.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "gamemgr.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "modmgr.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "store.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "tab_simple_main.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "tab_credits.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "tab_mods.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "tab_settings.lua")
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local function main_event_handler(tabview,event)
|
||||||
|
if event == "MenuQuit" then
|
||||||
|
core.close()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function init_globals()
|
||||||
|
--init gamedata
|
||||||
|
gamedata.worldindex = 0
|
||||||
|
|
||||||
|
local worldlist = core.get_worlds()
|
||||||
|
|
||||||
|
local found_singleplayerworld = false
|
||||||
|
|
||||||
|
for i=1,#worldlist,1 do
|
||||||
|
if worldlist[i].name == "singleplayerworld" then
|
||||||
|
found_singleplayerworld = true
|
||||||
|
gamedata.worldindex = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not found_singleplayerworld then
|
||||||
|
core.create_world("singleplayerworld", 1)
|
||||||
|
|
||||||
|
local worldlist = core.get_worlds()
|
||||||
|
|
||||||
|
for i=1,#worldlist,1 do
|
||||||
|
if worldlist[i].name == "singleplayerworld" then
|
||||||
|
gamedata.worldindex = i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--create main tabview
|
||||||
|
local tv_main = tabview_create("maintab",{x=12,y=5.2},{x=-0,y=-0})
|
||||||
|
tv_main:add(tab_simple_main)
|
||||||
|
tv_main:add(tab_mods)
|
||||||
|
tv_main:add(tab_settings)
|
||||||
|
tv_main:add(tab_credits)
|
||||||
|
tv_main:set_global_event_handler(main_event_handler)
|
||||||
|
tv_main:set_fixed_size(false)
|
||||||
|
ui.set_default("maintab")
|
||||||
|
tv_main:show()
|
||||||
|
|
||||||
|
--create modstore ui
|
||||||
|
modstore.init({x=12,y=6},3,2)
|
||||||
|
|
||||||
|
ui.update()
|
||||||
|
|
||||||
|
core.sound_play("main_menu", true)
|
||||||
|
end
|
||||||
|
|
||||||
|
init_globals()
|
||||||
|
|
@ -31,7 +31,6 @@ end
|
|||||||
local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
|
local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
|
||||||
|
|
||||||
if fields["dlg_reset_singleplayer_confirm"] ~= nil then
|
if fields["dlg_reset_singleplayer_confirm"] ~= nil then
|
||||||
|
|
||||||
local worldlist = core.get_worlds()
|
local worldlist = core.get_worlds()
|
||||||
local found_singleplayerworld = false
|
local found_singleplayerworld = false
|
||||||
|
|
||||||
@ -63,19 +62,43 @@ local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
|
|||||||
this.parent:show()
|
this.parent:show()
|
||||||
this:hide()
|
this:hide()
|
||||||
this:delete()
|
this:delete()
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function showconfirm_reset(tabview)
|
local function showconfirm_reset(tabview)
|
||||||
local new_dlg = dialog_create("reset_spworld",
|
local new_dlg = dialog_create("reset_spworld",
|
||||||
dlg_confirm_reset_formspec,
|
dlg_confirm_reset_formspec,
|
||||||
dlg_confirm_reset_btnhandler,
|
dlg_confirm_reset_btnhandler,
|
||||||
nil,
|
nil)
|
||||||
tabview)
|
new_dlg:set_parent(tabview)
|
||||||
tabview:hide()
|
tabview:hide()
|
||||||
new_dlg:show()
|
new_dlg:show()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function gui_scale_index()
|
||||||
|
|
||||||
|
local current_value = tonumber(core.setting_get("gui_scaling"))
|
||||||
|
|
||||||
|
if (current_value == nil) then
|
||||||
|
return 0
|
||||||
|
elseif current_value <= 0.5 then
|
||||||
|
return 1
|
||||||
|
elseif current_value <= 0.625 then
|
||||||
|
return 2
|
||||||
|
elseif current_value <= 0.75 then
|
||||||
|
return 3
|
||||||
|
elseif current_value <= 0.875 then
|
||||||
|
return 4
|
||||||
|
elseif current_value <= 1.0 then
|
||||||
|
return 5
|
||||||
|
elseif current_value <= 1.25 then
|
||||||
|
return 6
|
||||||
|
elseif current_value <= 1.5 then
|
||||||
|
return 7
|
||||||
|
else
|
||||||
|
return 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function formspec(tabview, name, tabdata)
|
local function formspec(tabview, name, tabdata)
|
||||||
local tab_string =
|
local tab_string =
|
||||||
@ -93,8 +116,6 @@ local function formspec(tabview, name, tabdata)
|
|||||||
.. dump(core.setting_getbool("preload_item_visuals")) .. "]"..
|
.. dump(core.setting_getbool("preload_item_visuals")) .. "]"..
|
||||||
"checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";"
|
"checkbox[1,2.5;cb_particles;".. fgettext("Enable Particles") .. ";"
|
||||||
.. dump(core.setting_getbool("enable_particles")) .. "]"..
|
.. dump(core.setting_getbool("enable_particles")) .. "]"..
|
||||||
"checkbox[1,3.0;cb_finite_liquid;".. fgettext("Finite Liquid") .. ";"
|
|
||||||
.. dump(core.setting_getbool("liquid_finite")) .. "]"..
|
|
||||||
"box[4.25,0;3.25,2.5;#999999]" ..
|
"box[4.25,0;3.25,2.5;#999999]" ..
|
||||||
"checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";"
|
"checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";"
|
||||||
.. dump(core.setting_getbool("mip_map")) .. "]"..
|
.. dump(core.setting_getbool("mip_map")) .. "]"..
|
||||||
@ -106,16 +127,25 @@ local function formspec(tabview, name, tabdata)
|
|||||||
.. dump(core.setting_getbool("trilinear_filter")) .. "]"..
|
.. dump(core.setting_getbool("trilinear_filter")) .. "]"..
|
||||||
"box[7.75,0;4,4;#999999]" ..
|
"box[7.75,0;4,4;#999999]" ..
|
||||||
"checkbox[8,0;cb_shaders;".. fgettext("Shaders") .. ";"
|
"checkbox[8,0;cb_shaders;".. fgettext("Shaders") .. ";"
|
||||||
.. dump(core.setting_getbool("enable_shaders")) .. "]"..
|
.. dump(core.setting_getbool("enable_shaders")) .. "]"
|
||||||
"button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
|
if not ANDROID then
|
||||||
|
|
||||||
local android = false
|
|
||||||
if android then
|
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"box[4.25,2.75;3.25,2.5;#999999]" ..
|
"button[8,4.75;3.75,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
|
||||||
|
else
|
||||||
|
tab_string = tab_string ..
|
||||||
|
"button[8,4.75;3.75,0.5;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. "]"
|
||||||
|
end
|
||||||
|
tab_string = tab_string ..
|
||||||
|
"box[0.75,4.25;3.25,1.25;#999999]" ..
|
||||||
|
"label[1,4.25;" .. fgettext("GUI scale factor") .. "]" ..
|
||||||
|
"dropdown[1,4.75;3.0;dd_gui_scaling;0.5,0.625,0.75,0.875,1.0,1.25,1.5,2.0;"
|
||||||
|
.. gui_scale_index() .. "]"
|
||||||
|
|
||||||
|
if ANDROID then
|
||||||
|
tab_string = tab_string ..
|
||||||
|
"box[4.25,2.75;3.25,2.15;#999999]" ..
|
||||||
"checkbox[4.5,2.75;cb_touchscreen_target;".. fgettext("Touch free target") .. ";"
|
"checkbox[4.5,2.75;cb_touchscreen_target;".. fgettext("Touch free target") .. ";"
|
||||||
.. dump(core.setting_getbool("touchtarget")) .. "]" ..
|
.. dump(core.setting_getbool("touchtarget")) .. "]"
|
||||||
"button[8,4.5;3.75,0.5;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. "]"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if core.setting_get("touchscreen_threshold") ~= nil then
|
if core.setting_get("touchscreen_threshold") ~= nil then
|
||||||
@ -202,10 +232,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
|
|||||||
core.setting_set("enable_particles", fields["cb_particles"])
|
core.setting_set("enable_particles", fields["cb_particles"])
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
if fields["cb_finite_liquid"] then
|
|
||||||
core.setting_set("liquid_finite", fields["cb_finite_liquid"])
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if fields["cb_bumpmapping"] then
|
if fields["cb_bumpmapping"] then
|
||||||
core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
|
core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
|
||||||
end
|
end
|
||||||
@ -235,14 +261,23 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
|
|||||||
core.setting_set("touchtarget", fields["cb_touchscreen_target"])
|
core.setting_set("touchtarget", fields["cb_touchscreen_target"])
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
if fields["dd_touchthreshold"] then
|
|
||||||
core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"])
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if fields["btn_reset_singleplayer"] then
|
if fields["btn_reset_singleplayer"] then
|
||||||
|
print("sp reset")
|
||||||
showconfirm_reset(this)
|
showconfirm_reset(this)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
--Note dropdowns have to be handled LAST!
|
||||||
|
local ddhandled = false
|
||||||
|
if fields["dd_touchthreshold"] then
|
||||||
|
core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"])
|
||||||
|
ddhandled = true
|
||||||
|
end
|
||||||
|
if fields["dd_gui_scaling"] then
|
||||||
|
core.setting_set("gui_scaling",fields["dd_gui_scaling"])
|
||||||
|
ddhandled = true
|
||||||
|
end
|
||||||
|
|
||||||
|
return ddhandled
|
||||||
end
|
end
|
||||||
|
|
||||||
tab_settings = {
|
tab_settings = {
|
||||||
|
@ -22,7 +22,6 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
local render_details = dump(core.setting_getbool("public_serverlist"))
|
local render_details = dump(core.setting_getbool("public_serverlist"))
|
||||||
|
|
||||||
retval = retval ..
|
retval = retval ..
|
||||||
"label[0,3.0;".. fgettext("Address/Port") .. "]"..
|
|
||||||
"label[8,0.5;".. fgettext("Name/Password") .. "]" ..
|
"label[8,0.5;".. fgettext("Name/Password") .. "]" ..
|
||||||
"field[0.25,3.25;5.5,0.5;te_address;;" ..core.setting_get("address") .."]" ..
|
"field[0.25,3.25;5.5,0.5;te_address;;" ..core.setting_get("address") .."]" ..
|
||||||
"field[5.75,3.25;2.25,0.5;te_port;;" ..core.setting_get("remote_port") .."]" ..
|
"field[5.75,3.25;2.25,0.5;te_port;;" ..core.setting_get("remote_port") .."]" ..
|
||||||
@ -66,7 +65,8 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
dump(core.setting_getbool("free_move")) .. "]"
|
dump(core.setting_getbool("free_move")) .. "]"
|
||||||
-- buttons
|
-- buttons
|
||||||
retval = retval ..
|
retval = retval ..
|
||||||
"button[3.0,4.5;6,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]"
|
"button[2.0,4.5;6,1.5;btn_start_singleplayer;" .. fgettext("Start Singleplayer") .. "]" ..
|
||||||
|
"button[8.25,4.5;2.5,1.5;btn_config_sp_world;" .. fgettext("Config MODs") .. "]"
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
end
|
end
|
||||||
@ -74,19 +74,21 @@ end
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function main_button_handler(tabview, fields, name, tabdata)
|
local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
|
|
||||||
if fields["btn_start_singleplayer"] then
|
if fields["btn_start_singleplayer"] then
|
||||||
gamedata.selected_world = gamedata.worldindex
|
gamedata.selected_world = gamedata.worldindex
|
||||||
gamedata.singleplayer = true
|
gamedata.singleplayer = true
|
||||||
core.start()
|
core.start()
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["favourites"] ~= nil then
|
if fields["favourites"] ~= nil then
|
||||||
local event = core.explode_textlist_event(fields["favourites"])
|
local event = core.explode_textlist_event(fields["favourites"])
|
||||||
|
|
||||||
if event.type == "CHG" then
|
if event.type == "CHG" then
|
||||||
if event.index <= #maintab_favorites then
|
if event.index <= #menudata.favorites then
|
||||||
local address = maintab_favorites[event.index].address
|
local address = menudata.favorites[event.index].address
|
||||||
local port = maintab_favorites[event.index].port
|
local port = menudata.favorites[event.index].port
|
||||||
|
|
||||||
if address ~= nil and
|
if address ~= nil and
|
||||||
port ~= nil then
|
port ~= nil then
|
||||||
@ -97,7 +99,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
tabdata.fav_selected = event.index
|
tabdata.fav_selected = event.index
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["cb_public_serverlist"] ~= nil then
|
if fields["cb_public_serverlist"] ~= nil then
|
||||||
@ -106,21 +108,24 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
if core.setting_getbool("public_serverlist") then
|
if core.setting_getbool("public_serverlist") then
|
||||||
asyncOnlineFavourites()
|
asyncOnlineFavourites()
|
||||||
else
|
else
|
||||||
maintab_favorites = core.get_favorites("local")
|
menudata.favorites = core.get_favorites("local")
|
||||||
end
|
end
|
||||||
return
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["cb_creative"] then
|
if fields["cb_creative"] then
|
||||||
core.setting_set("creative_mode", fields["cb_creative"])
|
core.setting_set("creative_mode", fields["cb_creative"])
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["cb_damage"] then
|
if fields["cb_damage"] then
|
||||||
core.setting_set("enable_damage", fields["cb_damage"])
|
core.setting_set("enable_damage", fields["cb_damage"])
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["cb_fly_mode"] then
|
if fields["cb_fly_mode"] then
|
||||||
core.setting_set("free_move", fields["cb_fly_mode"])
|
core.setting_set("free_move", fields["cb_fly_mode"])
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fields["btn_mp_connect"] ~= nil or
|
if fields["btn_mp_connect"] ~= nil or
|
||||||
@ -150,7 +155,18 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
|||||||
core.setting_set("remote_port",fields["te_port"])
|
core.setting_set("remote_port",fields["te_port"])
|
||||||
|
|
||||||
core.start()
|
core.start()
|
||||||
return
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["btn_config_sp_world"] ~= nil then
|
||||||
|
local configdialog = create_configure_world_dlg(1)
|
||||||
|
|
||||||
|
if (configdialog ~= nil) then
|
||||||
|
configdialog:set_parent(tabview)
|
||||||
|
tabview:hide()
|
||||||
|
configdialog:show()
|
||||||
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
130
doc/README.android
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
Minetest Android port
|
||||||
|
=====================
|
||||||
|
Date: 2014 06 28
|
||||||
|
|
||||||
|
Controls
|
||||||
|
--------
|
||||||
|
The Android port doesn't support everything you can do on PC due to the
|
||||||
|
limited capabilities of common devices. What can be done is described
|
||||||
|
below:
|
||||||
|
|
||||||
|
While you're playing the game normally (that is, no menu or inventory is
|
||||||
|
shown), the following controls are available:
|
||||||
|
* Look around: touch screen and slide finger
|
||||||
|
* double tap: place a node or use selected item
|
||||||
|
* long tap: dig node
|
||||||
|
* touch shown buttons: press button
|
||||||
|
* Buttons:
|
||||||
|
** left upper corner: chat
|
||||||
|
** right lower corner: jump
|
||||||
|
** right lower corner: crouch
|
||||||
|
** left lower corner: walk/step...
|
||||||
|
left up right
|
||||||
|
down
|
||||||
|
** left lower corner: display inventory
|
||||||
|
|
||||||
|
When a menu or inventory is displayed:
|
||||||
|
* double tap outside menu area: close menu
|
||||||
|
* tap on an item stack: select that stack
|
||||||
|
* tap on an empty slot: if you selected a stack already, that stack is placed here
|
||||||
|
* drag and drop: touch stack and hold finger down, move the stack to another
|
||||||
|
slot, tap another finger while keeping first finger on screen
|
||||||
|
--> places a single item from dragged stack into current (first touched) slot
|
||||||
|
|
||||||
|
Special settings
|
||||||
|
----------------
|
||||||
|
There are some settings esspecially usefull for Android users. Minetest's config
|
||||||
|
file can usually be found at /mnt/sdcard/Minetest.
|
||||||
|
|
||||||
|
* gui_scaling: this is a user-specified scaling factor for the GUI- In case
|
||||||
|
main menu is to big or small on your device, try changing this
|
||||||
|
value.
|
||||||
|
* inventory_image_hack: if your inventory items are messed up, try setting
|
||||||
|
this to true
|
||||||
|
|
||||||
|
Known issues
|
||||||
|
------------
|
||||||
|
Not all issues are fixed by now:
|
||||||
|
|
||||||
|
* Unable to exit from volume menu -- don't use the volume menu, use Android's
|
||||||
|
volume controls instead.
|
||||||
|
* 512 MB RAM seems to be inadequate -- this depends on the server you join.
|
||||||
|
Try to play on more lightweight servers.
|
||||||
|
|
||||||
|
Versioning
|
||||||
|
----------
|
||||||
|
Android version numbers are 4 digits instead of Minetest's 3 digits. The last
|
||||||
|
number of Android's version represents the Android internal version code. This
|
||||||
|
version code is strictly incremental. It's incremented for each official
|
||||||
|
Minetest Android build.
|
||||||
|
|
||||||
|
E.g. pre-release Minetest Android builds have been 0.4.9.3, while the first
|
||||||
|
official version most likely will be 0.4.10.4
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
In order to build, your PC has to be set up to build Minetest in the usual
|
||||||
|
manner (see the regular Minetest documentation for how to get this done).
|
||||||
|
In addition to what is required for Minetest in general, you will need the
|
||||||
|
following software packages. The version number in parenthesis denotes the
|
||||||
|
version that was tested at the time this README was drafted; newer/older
|
||||||
|
versions may or may not work.
|
||||||
|
|
||||||
|
* android SDK (x86_64 20131030)
|
||||||
|
* android NDK (r9d)
|
||||||
|
* wget (1.13.4)
|
||||||
|
|
||||||
|
Additionally, you'll need to have an Internet connection available on the
|
||||||
|
build system, as the Android build will download some source packages.
|
||||||
|
|
||||||
|
Build
|
||||||
|
-----
|
||||||
|
|
||||||
|
Debug build:
|
||||||
|
* Enter "build/android" subdirectory
|
||||||
|
* Execute "make"
|
||||||
|
* Answer the questions about where SDK and NDK are located on your filesystem
|
||||||
|
* Wait for build to finish
|
||||||
|
|
||||||
|
After the build is finished, the resulting apk can be fond in
|
||||||
|
build/android/bin/. It will be called Minetest-debug.apk
|
||||||
|
|
||||||
|
Release build:
|
||||||
|
|
||||||
|
* In order to make a release build you'll have to have a keystore setup to sign
|
||||||
|
the resulting apk package. How this is done is not part of this README. There
|
||||||
|
are different tutorials on the web explaining how to do it
|
||||||
|
- choose one yourself.
|
||||||
|
|
||||||
|
* Once your keystore is setup, enter build/android subdirectory and create a new
|
||||||
|
file "ant.properties" there. Add following lines to that file:
|
||||||
|
|
||||||
|
> key.store=<path to your keystore>
|
||||||
|
> key.alias=Minetest
|
||||||
|
|
||||||
|
* Execute "make release"
|
||||||
|
* Enter your keystore as well as your Mintest key password once asked. Be
|
||||||
|
carefull it's shown on console in clear text!
|
||||||
|
* The result can be found at "bin/Minetest-release.apk"
|
||||||
|
|
||||||
|
Other things that may be nice to know
|
||||||
|
------------
|
||||||
|
* The environment for Android development tools is saved within Android build
|
||||||
|
build folder. If you want direct access to it do:
|
||||||
|
|
||||||
|
> make envpaths
|
||||||
|
> . and_env
|
||||||
|
|
||||||
|
After you've done this you'll have your path and path variables set correct
|
||||||
|
to use adb and all other Android development tools
|
||||||
|
|
||||||
|
* You can build a single dependency by calling make and the dependency's name,
|
||||||
|
e.g.:
|
||||||
|
|
||||||
|
> make irrlicht
|
||||||
|
|
||||||
|
* You can completely cleanup a dependency by calling make and the "clean" target,
|
||||||
|
e.g.:
|
||||||
|
|
||||||
|
> make clean_irrlicht
|
@ -47,7 +47,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "cmake_config_githash.h"
|
|
||||||
#include "util/directiontables.h"
|
#include "util/directiontables.h"
|
||||||
#include "util/pointedthing.h"
|
#include "util/pointedthing.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
14
src/config.h
@ -8,7 +8,10 @@
|
|||||||
|
|
||||||
#define PROJECT_NAME "Minetest"
|
#define PROJECT_NAME "Minetest"
|
||||||
#define RUN_IN_PLACE 0
|
#define RUN_IN_PLACE 0
|
||||||
|
#define STATIC_SHAREDIR ""
|
||||||
|
|
||||||
#define USE_GETTEXT 0
|
#define USE_GETTEXT 0
|
||||||
|
|
||||||
#ifndef USE_SOUND
|
#ifndef USE_SOUND
|
||||||
#define USE_SOUND 0
|
#define USE_SOUND 0
|
||||||
#endif
|
#endif
|
||||||
@ -17,8 +20,9 @@
|
|||||||
#define USE_CURL 0
|
#define USE_CURL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define USE_FREETYPE 0
|
#ifndef USE_FREETYPE
|
||||||
#define STATIC_SHAREDIR ""
|
#define USE_FREETYPE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USE_LEVELDB
|
#ifndef USE_LEVELDB
|
||||||
#define USE_LEVELDB 0
|
#define USE_LEVELDB 0
|
||||||
@ -70,5 +74,11 @@
|
|||||||
#define VERSION_EXTRA_STRING CMAKE_VERSION_EXTRA_STRING
|
#define VERSION_EXTRA_STRING CMAKE_VERSION_EXTRA_STRING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include "android_version.h"
|
||||||
|
#else
|
||||||
|
#include "cmake_config_githash.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "porting.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "threads.h"
|
#include "threads.h"
|
||||||
@ -27,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include "jthread/jmutex.h"
|
#include "jthread/jmutex.h"
|
||||||
#include "jthread/jmutexautolock.h"
|
#include "jthread/jmutexautolock.h"
|
||||||
|
#include "config.h"
|
||||||
/*
|
/*
|
||||||
Debug output
|
Debug output
|
||||||
*/
|
*/
|
||||||
@ -95,6 +96,9 @@ public:
|
|||||||
}
|
}
|
||||||
std::streamsize xsputn(const char *s, std::streamsize n)
|
std::streamsize xsputn(const char *s, std::streamsize n)
|
||||||
{
|
{
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, PROJECT_NAME, "%s", s);
|
||||||
|
#endif
|
||||||
for(int i=0; i<DEBUGSTREAM_COUNT; i++)
|
for(int i=0; i<DEBUGSTREAM_COUNT; i++)
|
||||||
{
|
{
|
||||||
if(g_debugstreams[i] == stderr && m_disable_stderr)
|
if(g_debugstreams[i] == stderr && m_disable_stderr)
|
||||||
|
@ -154,6 +154,7 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("curl_timeout", "5000");
|
settings->setDefault("curl_timeout", "5000");
|
||||||
settings->setDefault("curl_parallel_limit", "8");
|
settings->setDefault("curl_parallel_limit", "8");
|
||||||
settings->setDefault("curl_file_download_timeout", "300000");
|
settings->setDefault("curl_file_download_timeout", "300000");
|
||||||
|
settings->setDefault("curl_verify_cert", "true");
|
||||||
|
|
||||||
settings->setDefault("enable_remote_media_server", "true");
|
settings->setDefault("enable_remote_media_server", "true");
|
||||||
|
|
||||||
@ -278,6 +279,39 @@ void set_default_settings(Settings *settings)
|
|||||||
settings->setDefault("high_precision_fpu", "true");
|
settings->setDefault("high_precision_fpu", "true");
|
||||||
|
|
||||||
settings->setDefault("language", "");
|
settings->setDefault("language", "");
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
settings->setDefault("screenW", "0");
|
||||||
|
settings->setDefault("screenH", "0");
|
||||||
|
settings->setDefault("enable_shaders", "false");
|
||||||
|
settings->setDefault("fullscreen", "true");
|
||||||
|
settings->setDefault("enable_particles", "false");
|
||||||
|
settings->setDefault("video_driver", "ogles1");
|
||||||
|
settings->setDefault("touchtarget", "true");
|
||||||
|
settings->setDefault("main_menu_script","/sdcard/Minetest/builtin/mainmenu/init_android.lua");
|
||||||
|
settings->setDefault("TMPFolder","/sdcard/Minetest/tmp/");
|
||||||
|
settings->setDefault("touchscreen_threshold","20");
|
||||||
|
settings->setDefault("smooth_lighting", "false");
|
||||||
|
settings->setDefault("max_simultaneous_block_sends_per_client", "3");
|
||||||
|
settings->setDefault("emergequeue_limit_diskonly", "8");
|
||||||
|
settings->setDefault("emergequeue_limit_generate", "8");
|
||||||
|
settings->setDefault("preload_item_visuals", "false");
|
||||||
|
|
||||||
|
settings->setDefault("viewing_range_nodes_max", "50");
|
||||||
|
settings->setDefault("viewing_range_nodes_min", "20");
|
||||||
|
settings->setDefault("inventory_image_hack", "false");
|
||||||
|
|
||||||
|
//check for device with small screen
|
||||||
|
float x_inches = ((double) porting::getDisplaySize().X /
|
||||||
|
(160 * porting::getDisplayDensity()));
|
||||||
|
if (x_inches < 3.5) {
|
||||||
|
settings->setDefault("gui_scaling", "0.6");
|
||||||
|
}
|
||||||
|
else if (x_inches < 4.5) {
|
||||||
|
settings->setDefault("gui_scaling", "0.7");
|
||||||
|
}
|
||||||
|
settings->setDefault("curl_verify_cert","false");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void late_init_default_settings(Settings* settings)
|
void late_init_default_settings(Settings* settings)
|
||||||
|
@ -427,6 +427,13 @@ void draw_scene(video::IVideoDriver* driver, scene::ISceneManager* smgr,
|
|||||||
bool draw_crosshair = ((player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
|
bool draw_crosshair = ((player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
|
||||||
(camera.getCameraMode() != CAMERA_MODE_THIRD_FRONT));
|
(camera.getCameraMode() != CAMERA_MODE_THIRD_FRONT));
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
try {
|
||||||
|
draw_crosshair = !g_settings->getBool("touchtarget");
|
||||||
|
}
|
||||||
|
catch(SettingNotFoundException) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string draw_mode = g_settings->get("3d_mode");
|
std::string draw_mode = g_settings->get("3d_mode");
|
||||||
|
|
||||||
smgr->drawAll();
|
smgr->drawAll();
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
namespace fs
|
namespace fs
|
||||||
{
|
{
|
||||||
@ -401,7 +402,11 @@ std::string TempPath()
|
|||||||
compatible with lua's os.tmpname which under the default
|
compatible with lua's os.tmpname which under the default
|
||||||
configuration hardcodes mkstemp("/tmp/lua_XXXXXX").
|
configuration hardcodes mkstemp("/tmp/lua_XXXXXX").
|
||||||
*/
|
*/
|
||||||
return std::string(DIR_DELIM) + "tmp";
|
#ifdef __ANDROID__
|
||||||
|
return DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME DIR_DELIM "tmp";
|
||||||
|
#else
|
||||||
|
return DIR_DELIM "tmp";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
120
src/game.cpp
@ -70,6 +70,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "drawscene.h"
|
#include "drawscene.h"
|
||||||
#include "content_cao.h"
|
#include "content_cao.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
#include "touchscreengui.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Text input system
|
Text input system
|
||||||
*/
|
*/
|
||||||
@ -942,14 +946,20 @@ static inline void create_formspec_menu(GUIFormSpecMenu** cur_formspec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#define SIZE_TAG "size[11,5.5]"
|
||||||
|
#else
|
||||||
|
#define SIZE_TAG "size[11,5.5,true]"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void show_chat_menu(GUIFormSpecMenu** cur_formspec,
|
static void show_chat_menu(GUIFormSpecMenu** cur_formspec,
|
||||||
InventoryManager *invmgr, IGameDef *gamedef,
|
InventoryManager *invmgr, IGameDef *gamedef,
|
||||||
IWritableTextureSource* tsrc, IrrlichtDevice * device,
|
IWritableTextureSource* tsrc, IrrlichtDevice * device,
|
||||||
Client* client, std::string text)
|
Client* client, std::string text)
|
||||||
{
|
{
|
||||||
std::string formspec =
|
std::string formspec =
|
||||||
FORMSPEC_VERSION_STRING
|
FORMSPEC_VERSION_STRING
|
||||||
"size[11,5.5,true]"
|
SIZE_TAG
|
||||||
"field[3,2.35;6,0.5;f_text;;" + text + "]"
|
"field[3,2.35;6,0.5;f_text;;" + text + "]"
|
||||||
"button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]"
|
"button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]"
|
||||||
;
|
;
|
||||||
@ -969,7 +979,7 @@ static void show_deathscreen(GUIFormSpecMenu** cur_formspec,
|
|||||||
{
|
{
|
||||||
std::string formspec =
|
std::string formspec =
|
||||||
std::string(FORMSPEC_VERSION_STRING) +
|
std::string(FORMSPEC_VERSION_STRING) +
|
||||||
"size[11,5.5,true]"
|
SIZE_TAG
|
||||||
"bgcolor[#320000b4;true]"
|
"bgcolor[#320000b4;true]"
|
||||||
"label[4.85,1.35;You died.]"
|
"label[4.85,1.35;You died.]"
|
||||||
"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
|
"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
|
||||||
@ -990,6 +1000,21 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
|
|||||||
IWritableTextureSource* tsrc, IrrlichtDevice * device,
|
IWritableTextureSource* tsrc, IrrlichtDevice * device,
|
||||||
bool singleplayermode)
|
bool singleplayermode)
|
||||||
{
|
{
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n"
|
||||||
|
"No menu visible:\n"
|
||||||
|
"- single tap: button activate\n"
|
||||||
|
"- double tap: place/use\n"
|
||||||
|
"- slide finger: look around\n"
|
||||||
|
"Menu/Inventory visible:\n"
|
||||||
|
"- double tap (outside):\n"
|
||||||
|
" -->close\n"
|
||||||
|
"- touch stack, touch slot:\n"
|
||||||
|
" --> move stack\n"
|
||||||
|
"- touch&drag, tap 2nd finger\n"
|
||||||
|
" --> place single item to slot\n"
|
||||||
|
));
|
||||||
|
#else
|
||||||
std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n"
|
std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n"
|
||||||
"- WASD: move\n"
|
"- WASD: move\n"
|
||||||
"- Space: jump/climb\n"
|
"- Space: jump/climb\n"
|
||||||
@ -1002,11 +1027,11 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
|
|||||||
"- Mouse wheel: select item\n"
|
"- Mouse wheel: select item\n"
|
||||||
"- T: chat\n"
|
"- T: chat\n"
|
||||||
));
|
));
|
||||||
|
#endif
|
||||||
float ypos = singleplayermode ? 1.0 : 0.5;
|
float ypos = singleplayermode ? 1.0 : 0.5;
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
|
||||||
os << FORMSPEC_VERSION_STRING << "size[11,5.5,true]"
|
os << FORMSPEC_VERSION_STRING << SIZE_TAG
|
||||||
<< "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;"
|
<< "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;"
|
||||||
<< wide_to_narrow(wstrgettext("Continue")) << "]";
|
<< wide_to_narrow(wstrgettext("Continue")) << "]";
|
||||||
|
|
||||||
@ -1021,7 +1046,7 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
|
|||||||
<< wide_to_narrow(wstrgettext("Exit to Menu")) << "]";
|
<< wide_to_narrow(wstrgettext("Exit to Menu")) << "]";
|
||||||
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;"
|
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;"
|
||||||
<< wide_to_narrow(wstrgettext("Exit to OS")) << "]"
|
<< wide_to_narrow(wstrgettext("Exit to OS")) << "]"
|
||||||
<< "textarea[7.5,0.25;3.75,6;;" << control_text << ";]"
|
<< "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]"
|
||||||
<< "textarea[0.4,0.25;3.5,6;;" << "Minetest\n"
|
<< "textarea[0.4,0.25;3.5,6;;" << "Minetest\n"
|
||||||
<< minetest_build_info << "\n"
|
<< minetest_build_info << "\n"
|
||||||
<< "path_user = " << wrap_rows(porting::path_user, 20)
|
<< "path_user = " << wrap_rows(porting::path_user, 20)
|
||||||
@ -1253,18 +1278,18 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
server->step(dtime);
|
server->step(dtime);
|
||||||
|
|
||||||
// End condition
|
// End condition
|
||||||
if(client.getState() == LC_Init){
|
if(client.getState() == LC_Init) {
|
||||||
could_connect = true;
|
could_connect = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Break conditions
|
// Break conditions
|
||||||
if(client.accessDenied()){
|
if(client.accessDenied()) {
|
||||||
error_message = L"Access denied. Reason: "
|
error_message = L"Access denied. Reason: "
|
||||||
+client.accessDeniedReason();
|
+client.accessDeniedReason();
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(input->wasKeyDown(EscapeKey)){
|
if(input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
|
||||||
connect_aborted = true;
|
connect_aborted = true;
|
||||||
infostream<<"Connect aborted [Escape]"<<std::endl;
|
infostream<<"Connect aborted [Escape]"<<std::endl;
|
||||||
break;
|
break;
|
||||||
@ -1310,8 +1335,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
/*
|
/*
|
||||||
Handle failure to connect
|
Handle failure to connect
|
||||||
*/
|
*/
|
||||||
if(!could_connect){
|
if(!could_connect) {
|
||||||
if(error_message == L"" && !connect_aborted){
|
if(error_message == L"" && !connect_aborted) {
|
||||||
error_message = L"Connection failed";
|
error_message = L"Connection failed";
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
}
|
}
|
||||||
@ -1330,8 +1355,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
float fps_max = g_settings->getFloat("fps_max");
|
float fps_max = g_settings->getFloat("fps_max");
|
||||||
bool cloud_menu_background = g_settings->getBool("menu_clouds");
|
bool cloud_menu_background = g_settings->getBool("menu_clouds");
|
||||||
u32 lasttime = device->getTimer()->getTime();
|
u32 lasttime = device->getTimer()->getTime();
|
||||||
while(device->run())
|
while (device->run()) {
|
||||||
{
|
|
||||||
f32 dtime = 0.033; // in seconds
|
f32 dtime = 0.033; // in seconds
|
||||||
if (cloud_menu_background) {
|
if (cloud_menu_background) {
|
||||||
u32 time = device->getTimer()->getTime();
|
u32 time = device->getTimer()->getTime();
|
||||||
@ -1343,29 +1367,29 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
}
|
}
|
||||||
// Update client and server
|
// Update client and server
|
||||||
client.step(dtime);
|
client.step(dtime);
|
||||||
if(server != NULL)
|
if (server != NULL)
|
||||||
server->step(dtime);
|
server->step(dtime);
|
||||||
|
|
||||||
// End condition
|
// End condition
|
||||||
if(client.mediaReceived() &&
|
if (client.mediaReceived() &&
|
||||||
client.itemdefReceived() &&
|
client.itemdefReceived() &&
|
||||||
client.nodedefReceived()){
|
client.nodedefReceived()) {
|
||||||
got_content = true;
|
got_content = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Break conditions
|
// Break conditions
|
||||||
if(client.accessDenied()){
|
if (client.accessDenied()) {
|
||||||
error_message = L"Access denied. Reason: "
|
error_message = L"Access denied. Reason: "
|
||||||
+client.accessDeniedReason();
|
+client.accessDeniedReason();
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(client.getState() < LC_Init){
|
if (client.getState() < LC_Init) {
|
||||||
error_message = L"Client disconnected";
|
error_message = L"Client disconnected";
|
||||||
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
errorstream<<wide_to_narrow(error_message)<<std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(input->wasKeyDown(EscapeKey)){
|
if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
|
||||||
content_aborted = true;
|
content_aborted = true;
|
||||||
infostream<<"Connect aborted [Escape]"<<std::endl;
|
infostream<<"Connect aborted [Escape]"<<std::endl;
|
||||||
break;
|
break;
|
||||||
@ -1548,6 +1572,11 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
guitext_profiler->setVisible(false);
|
guitext_profiler->setVisible(false);
|
||||||
guitext_profiler->setWordWrap(true);
|
guitext_profiler->setWordWrap(true);
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if (g_touchscreengui)
|
||||||
|
g_touchscreengui->init(tsrc,porting::getDisplayDensity());
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some statistics are collected in these
|
Some statistics are collected in these
|
||||||
*/
|
*/
|
||||||
@ -1641,7 +1670,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if(device->run() == false || kill == true)
|
if(device->run() == false || kill == true ||
|
||||||
|
g_gamecallback->shutdown_requested)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
v2u32 screensize = driver->getScreenSize();
|
v2u32 screensize = driver->getScreenSize();
|
||||||
@ -1858,6 +1888,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
|
|
||||||
// Input handler step() (used by the random input generator)
|
// Input handler step() (used by the random input generator)
|
||||||
input->step(dtime);
|
input->step(dtime);
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if (g_touchscreengui) {
|
||||||
|
g_touchscreengui->step(dtime);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
if (current_formspec != 0)
|
||||||
|
current_formspec->getAndroidUIInput();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Increase timer for doubleclick of "jump"
|
// Increase timer for doubleclick of "jump"
|
||||||
if(g_settings->getBool("doubletap_jump") && jump_timer <= 0.2)
|
if(g_settings->getBool("doubletap_jump") && jump_timer <= 0.2)
|
||||||
@ -1890,7 +1929,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
inventoryloc.setCurrentPlayer();
|
inventoryloc.setCurrentPlayer();
|
||||||
current_formspec->setFormSpec(fs_src->getForm(), inventoryloc);
|
current_formspec->setFormSpec(fs_src->getForm(), inventoryloc);
|
||||||
}
|
}
|
||||||
else if(input->wasKeyDown(EscapeKey))
|
else if(input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey))
|
||||||
{
|
{
|
||||||
show_pause_menu(¤t_formspec, &client, gamedef, tsrc, device,
|
show_pause_menu(¤t_formspec, &client, gamedef, tsrc, device,
|
||||||
simple_singleplayer_mode);
|
simple_singleplayer_mode);
|
||||||
@ -2214,21 +2253,29 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
float turn_amount = 0;
|
float turn_amount = 0;
|
||||||
if((device->isWindowActive() && noMenuActive()) || random_input)
|
if((device->isWindowActive() && noMenuActive()) || random_input)
|
||||||
{
|
{
|
||||||
|
#ifndef __ANDROID__
|
||||||
if(!random_input)
|
if(!random_input)
|
||||||
{
|
{
|
||||||
// Mac OSX gets upset if this is set every frame
|
// Mac OSX gets upset if this is set every frame
|
||||||
if(device->getCursorControl()->isVisible())
|
if(device->getCursorControl()->isVisible())
|
||||||
device->getCursorControl()->setVisible(false);
|
device->getCursorControl()->setVisible(false);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(first_loop_after_window_activation){
|
if(first_loop_after_window_activation){
|
||||||
//infostream<<"window active, first loop"<<std::endl;
|
//infostream<<"window active, first loop"<<std::endl;
|
||||||
first_loop_after_window_activation = false;
|
first_loop_after_window_activation = false;
|
||||||
}
|
} else {
|
||||||
else{
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
s32 dx = input->getMousePos().X - (driver->getScreenSize().Width/2);
|
if (g_touchscreengui) {
|
||||||
s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height/2);
|
camera_yaw = g_touchscreengui->getYaw();
|
||||||
if(invert_mouse || camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT) {
|
camera_pitch = g_touchscreengui->getPitch();
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
s32 dx = input->getMousePos().X - (driver->getScreenSize().Width/2);
|
||||||
|
s32 dy = input->getMousePos().Y - (driver->getScreenSize().Height/2);
|
||||||
|
if ((invert_mouse)
|
||||||
|
|| (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT)) {
|
||||||
dy = -dy;
|
dy = -dy;
|
||||||
}
|
}
|
||||||
//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
|
||||||
@ -2247,18 +2294,23 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
d = rangelim(d, 0.01, 100.0);
|
d = rangelim(d, 0.01, 100.0);
|
||||||
camera_yaw -= dx*d;
|
camera_yaw -= dx*d;
|
||||||
camera_pitch += dy*d;
|
camera_pitch += dy*d;
|
||||||
|
turn_amount = v2f(dx, dy).getLength() * d;
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(camera_pitch < -89.5) camera_pitch = -89.5;
|
if(camera_pitch < -89.5) camera_pitch = -89.5;
|
||||||
if(camera_pitch > 89.5) camera_pitch = 89.5;
|
if(camera_pitch > 89.5) camera_pitch = 89.5;
|
||||||
|
|
||||||
turn_amount = v2f(dx, dy).getLength() * d;
|
|
||||||
}
|
}
|
||||||
input->setMousePos((driver->getScreenSize().Width/2),
|
input->setMousePos((driver->getScreenSize().Width/2),
|
||||||
(driver->getScreenSize().Height/2));
|
(driver->getScreenSize().Height/2));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
#ifndef ANDROID
|
||||||
// Mac OSX gets upset if this is set every frame
|
// Mac OSX gets upset if this is set every frame
|
||||||
if(device->getCursorControl()->isVisible() == false)
|
if(device->getCursorControl()->isVisible() == false)
|
||||||
device->getCursorControl()->setVisible(true);
|
device->getCursorControl()->setVisible(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
//infostream<<"window inactive"<<std::endl;
|
//infostream<<"window inactive"<<std::endl;
|
||||||
first_loop_after_window_activation = true;
|
first_loop_after_window_activation = true;
|
||||||
@ -2668,10 +2720,19 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
core::line3d<f32> shootline(camera_position,
|
core::line3d<f32> shootline(camera_position,
|
||||||
camera_position + camera_direction * BS * (d+1));
|
camera_position + camera_direction * BS * (d+1));
|
||||||
|
|
||||||
|
|
||||||
// prevent player pointing anything in front-view
|
// prevent player pointing anything in front-view
|
||||||
if (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT)
|
if (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT)
|
||||||
shootline = core::line3d<f32>(0,0,0,0,0,0);
|
shootline = core::line3d<f32>(0,0,0,0,0,0);
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if ((g_settings->getBool("touchtarget")) && (g_touchscreengui)) {
|
||||||
|
shootline = g_touchscreengui->getShootline();
|
||||||
|
shootline.start += intToFloat(camera_offset,BS);
|
||||||
|
shootline.end += intToFloat(camera_offset,BS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ClientActiveObject *selected_object = NULL;
|
ClientActiveObject *selected_object = NULL;
|
||||||
|
|
||||||
PointedThing pointed = getPointedThing(
|
PointedThing pointed = getPointedThing(
|
||||||
@ -3156,8 +3217,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
|
|||||||
}
|
}
|
||||||
else if(show_hud || show_chat)
|
else if(show_hud || show_chat)
|
||||||
{
|
{
|
||||||
|
u16 fps = (1.0/dtime_avg1);
|
||||||
std::ostringstream os(std::ios_base::binary);
|
std::ostringstream os(std::ios_base::binary);
|
||||||
os<<"Minetest "<<minetest_version_hash;
|
os<<"Minetest "<<minetest_version_hash <<" FPS = "<<fps;
|
||||||
guitext->setText(narrow_to_wide(os.str()).c_str());
|
guitext->setText(narrow_to_wide(os.str()).c_str());
|
||||||
guitext->setVisible(true);
|
guitext->setVisible(true);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
#include "httpfetch.h"
|
#include "httpfetch.h"
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include "tile.h"
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
#include <ICameraSceneNode.h>
|
#include <ICameraSceneNode.h>
|
||||||
@ -83,6 +87,16 @@ video::ITexture* MenuTextureSource::getTexture(const std::string &name, u32 *id)
|
|||||||
if(name.empty())
|
if(name.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
m_to_delete.insert(name);
|
m_to_delete.insert(name);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
video::IImage *image = m_driver->createImageFromFile(name.c_str());
|
||||||
|
if (image) {
|
||||||
|
image = Align2Npot2(image, m_driver);
|
||||||
|
video::ITexture* retval = m_driver->addTexture(name.c_str(), image);
|
||||||
|
image->drop();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return m_driver->getTexture(name.c_str());
|
return m_driver->getTexture(name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,6 +280,10 @@ void GUIEngine::run()
|
|||||||
sleep_ms(25);
|
sleep_ms(25);
|
||||||
|
|
||||||
m_script->step();
|
m_script->step();
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
m_menu->getAndroidUIInput();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,9 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
|||||||
m_ext_ptr(ext_ptr),
|
m_ext_ptr(ext_ptr),
|
||||||
m_font(dev->getGUIEnvironment()->getSkin()->getFont()),
|
m_font(dev->getGUIEnvironment()->getSkin()->getFont()),
|
||||||
m_formspec_version(0)
|
m_formspec_version(0)
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
,m_JavaDialogFieldName(L"")
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
current_keys_pending.key_down = false;
|
current_keys_pending.key_down = false;
|
||||||
current_keys_pending.key_up = false;
|
current_keys_pending.key_up = false;
|
||||||
@ -1878,6 +1881,52 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
setInitialFocus();
|
setInitialFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
bool GUIFormSpecMenu::getAndroidUIInput()
|
||||||
|
{
|
||||||
|
/* no dialog shown */
|
||||||
|
if (m_JavaDialogFieldName == L"") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* still waiting */
|
||||||
|
if (porting::getInputDialogState() == -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring fieldname = m_JavaDialogFieldName;
|
||||||
|
m_JavaDialogFieldName = L"";
|
||||||
|
|
||||||
|
/* no value abort dialog processing */
|
||||||
|
if (porting::getInputDialogState() != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::vector<FieldSpec>::iterator iter = m_fields.begin();
|
||||||
|
iter != m_fields.end(); iter++) {
|
||||||
|
|
||||||
|
if (iter->fname != fieldname) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IGUIElement* tochange = getElementFromId(iter->fid);
|
||||||
|
|
||||||
|
if (tochange == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tochange->getType() != irr::gui::EGUIET_EDIT_BOX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string text = porting::getInputDialogValue();
|
||||||
|
|
||||||
|
((gui::IGUIEditBox*) tochange)->
|
||||||
|
setText(narrow_to_wide(text).c_str());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
|
GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
|
||||||
{
|
{
|
||||||
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
|
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
|
||||||
@ -1886,8 +1935,7 @@ GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
|
|||||||
{
|
{
|
||||||
const ListDrawSpec &s = m_inventorylists[i];
|
const ListDrawSpec &s = m_inventorylists[i];
|
||||||
|
|
||||||
for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
|
for(s32 i=0; i<s.geom.X*s.geom.Y; i++) {
|
||||||
{
|
|
||||||
s32 item_i = i + s.start_item_i;
|
s32 item_i = i + s.start_item_i;
|
||||||
s32 x = (i%s.geom.X) * spacing.X;
|
s32 x = (i%s.geom.X) * spacing.X;
|
||||||
s32 y = (i/s.geom.X) * spacing.Y;
|
s32 y = (i/s.geom.X) * spacing.Y;
|
||||||
@ -2051,8 +2099,6 @@ void GUIFormSpecMenu::drawMenu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pointer = m_device->getCursorControl()->getPosition();
|
|
||||||
|
|
||||||
updateSelectedItem();
|
updateSelectedItem();
|
||||||
|
|
||||||
gui::IGUISkin* skin = Environment->getSkin();
|
gui::IGUISkin* skin = Environment->getSkin();
|
||||||
@ -2195,6 +2241,11 @@ void GUIFormSpecMenu::drawMenu()
|
|||||||
*/
|
*/
|
||||||
gui::IGUIElement::draw();
|
gui::IGUIElement::draw();
|
||||||
|
|
||||||
|
/* TODO find way to show tooltips on touchscreen */
|
||||||
|
#ifndef HAVE_TOUCHSCREENGUI
|
||||||
|
m_pointer = m_device->getCursorControl()->getPosition();
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Draw fields/buttons tooltips
|
Draw fields/buttons tooltips
|
||||||
*/
|
*/
|
||||||
@ -2491,7 +2542,8 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
|
|||||||
// Fix Esc/Return key being eaten by checkboxen and tables
|
// Fix Esc/Return key being eaten by checkboxen and tables
|
||||||
if(event.EventType==EET_KEY_INPUT_EVENT) {
|
if(event.EventType==EET_KEY_INPUT_EVENT) {
|
||||||
KeyPress kp(event.KeyInput);
|
KeyPress kp(event.KeyInput);
|
||||||
if (kp == EscapeKey || kp == getKeySetting("keymap_inventory")
|
if (kp == EscapeKey || kp == CancelKey
|
||||||
|
|| kp == getKeySetting("keymap_inventory")
|
||||||
|| event.KeyInput.Key==KEY_RETURN) {
|
|| event.KeyInput.Key==KEY_RETURN) {
|
||||||
gui::IGUIElement *focused = Environment->getFocus();
|
gui::IGUIElement *focused = Environment->getFocus();
|
||||||
if (focused && isMyChild(focused) &&
|
if (focused && isMyChild(focused) &&
|
||||||
@ -2533,6 +2585,156 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
// display software keyboard when clicking edit boxes
|
||||||
|
if (event.EventType == EET_MOUSE_INPUT_EVENT
|
||||||
|
&& event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
|
||||||
|
gui::IGUIElement *hovered =
|
||||||
|
Environment->getRootGUIElement()->getElementFromPoint(
|
||||||
|
core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
|
||||||
|
if ((hovered) && (hovered->getType() == irr::gui::EGUIET_EDIT_BOX)) {
|
||||||
|
bool retval = hovered->OnEvent(event);
|
||||||
|
if (retval) {
|
||||||
|
Environment->setFocus(hovered);
|
||||||
|
}
|
||||||
|
m_JavaDialogFieldName = getNameByID(hovered->getID());
|
||||||
|
std::string message = gettext("Enter ");
|
||||||
|
std::string label = wide_to_narrow(getLabelByID(hovered->getID()));
|
||||||
|
if (label == "") {
|
||||||
|
label = "text";
|
||||||
|
}
|
||||||
|
message += gettext(label) + ":";
|
||||||
|
|
||||||
|
/* single line text input */
|
||||||
|
int type = 2;
|
||||||
|
|
||||||
|
/* multi line text input */
|
||||||
|
if (((gui::IGUIEditBox*) hovered)->isMultiLineEnabled()) {
|
||||||
|
type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* passwords are always single line */
|
||||||
|
if (((gui::IGUIEditBox*) hovered)->isPasswordBox()) {
|
||||||
|
type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
porting::showInputDialog(gettext("ok"), "",
|
||||||
|
wide_to_narrow(((gui::IGUIEditBox*) hovered)->getText()),
|
||||||
|
type);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.EventType == EET_TOUCH_INPUT_EVENT)
|
||||||
|
{
|
||||||
|
SEvent translated;
|
||||||
|
memset(&translated, 0, sizeof(SEvent));
|
||||||
|
translated.EventType = EET_MOUSE_INPUT_EVENT;
|
||||||
|
gui::IGUIElement* root = Environment->getRootGUIElement();
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
errorstream
|
||||||
|
<< "GUIFormSpecMenu::preprocessEvent unable to get root element"
|
||||||
|
<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gui::IGUIElement* hovered = root->getElementFromPoint(
|
||||||
|
core::position2d<s32>(
|
||||||
|
event.TouchInput.X,
|
||||||
|
event.TouchInput.Y));
|
||||||
|
|
||||||
|
translated.MouseInput.X = event.TouchInput.X;
|
||||||
|
translated.MouseInput.Y = event.TouchInput.Y;
|
||||||
|
translated.MouseInput.Control = false;
|
||||||
|
|
||||||
|
bool dont_send_event = false;
|
||||||
|
|
||||||
|
if (event.TouchInput.touchedCount == 1) {
|
||||||
|
switch (event.TouchInput.Event) {
|
||||||
|
case ETIE_PRESSED_DOWN:
|
||||||
|
m_pointer = v2s32(event.TouchInput.X,event.TouchInput.Y);
|
||||||
|
translated.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
|
||||||
|
translated.MouseInput.ButtonStates = EMBSM_LEFT;
|
||||||
|
m_down_pos = m_pointer;
|
||||||
|
break;
|
||||||
|
case ETIE_MOVED:
|
||||||
|
m_pointer = v2s32(event.TouchInput.X,event.TouchInput.Y);
|
||||||
|
translated.MouseInput.Event = EMIE_MOUSE_MOVED;
|
||||||
|
translated.MouseInput.ButtonStates = EMBSM_LEFT;
|
||||||
|
break;
|
||||||
|
case ETIE_LEFT_UP:
|
||||||
|
translated.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
|
||||||
|
translated.MouseInput.ButtonStates = 0;
|
||||||
|
hovered = root->getElementFromPoint(m_down_pos);
|
||||||
|
/* we don't have a valid pointer element use last
|
||||||
|
* known pointer pos */
|
||||||
|
translated.MouseInput.X = m_pointer.X;
|
||||||
|
translated.MouseInput.Y = m_pointer.Y;
|
||||||
|
|
||||||
|
/* reset down pos */
|
||||||
|
m_down_pos = v2s32(0,0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dont_send_event = true;
|
||||||
|
//this is not supposed to happen
|
||||||
|
errorstream
|
||||||
|
<< "GUIFormSpecMenu::preprocessEvent unexpected usecase Event="
|
||||||
|
<< event.TouchInput.Event << std::endl;
|
||||||
|
}
|
||||||
|
} else if ( (event.TouchInput.touchedCount == 2) &&
|
||||||
|
(event.TouchInput.Event == ETIE_PRESSED_DOWN) ) {
|
||||||
|
hovered = root->getElementFromPoint(m_down_pos);
|
||||||
|
|
||||||
|
translated.MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN;
|
||||||
|
translated.MouseInput.ButtonStates = EMBSM_LEFT | EMBSM_RIGHT;
|
||||||
|
translated.MouseInput.X = m_pointer.X;
|
||||||
|
translated.MouseInput.Y = m_pointer.Y;
|
||||||
|
|
||||||
|
if (hovered) {
|
||||||
|
hovered->OnEvent(translated);
|
||||||
|
}
|
||||||
|
|
||||||
|
translated.MouseInput.Event = EMIE_RMOUSE_LEFT_UP;
|
||||||
|
translated.MouseInput.ButtonStates = EMBSM_LEFT;
|
||||||
|
|
||||||
|
|
||||||
|
if (hovered) {
|
||||||
|
hovered->OnEvent(translated);
|
||||||
|
}
|
||||||
|
dont_send_event = true;
|
||||||
|
}
|
||||||
|
/* ignore unhandled 2 touch events ... accidental moving for example */
|
||||||
|
else if (event.TouchInput.touchedCount == 2) {
|
||||||
|
dont_send_event = true;
|
||||||
|
}
|
||||||
|
else if (event.TouchInput.touchedCount > 2) {
|
||||||
|
errorstream
|
||||||
|
<< "GUIFormSpecMenu::preprocessEvent to many multitouch events "
|
||||||
|
<< event.TouchInput.touchedCount << " ignoring them" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dont_send_event) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if translated event needs to be preprocessed again */
|
||||||
|
if (preprocessEvent(translated)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (hovered) {
|
||||||
|
grab();
|
||||||
|
bool retval = hovered->OnEvent(translated);
|
||||||
|
|
||||||
|
if (event.TouchInput.Event == ETIE_LEFT_UP) {
|
||||||
|
/* reset pointer */
|
||||||
|
m_pointer = v2s32(0,0);
|
||||||
|
}
|
||||||
|
drop();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2584,8 +2786,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
|||||||
{
|
{
|
||||||
if(event.EventType==EET_KEY_INPUT_EVENT) {
|
if(event.EventType==EET_KEY_INPUT_EVENT) {
|
||||||
KeyPress kp(event.KeyInput);
|
KeyPress kp(event.KeyInput);
|
||||||
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
|
if (event.KeyInput.PressedDown && ( (kp == EscapeKey) ||
|
||||||
kp == getKeySetting("keymap_inventory"))) {
|
(kp == getKeySetting("keymap_inventory")) || (kp == CancelKey))) {
|
||||||
if (m_allowclose) {
|
if (m_allowclose) {
|
||||||
doPause = false;
|
doPause = false;
|
||||||
acceptInput(quit_mode_cancel);
|
acceptInput(quit_mode_cancel);
|
||||||
@ -3015,6 +3217,38 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
|||||||
return Parent ? Parent->OnEvent(event) : false;
|
return Parent ? Parent->OnEvent(event) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get name of element by element id
|
||||||
|
* @param id of element
|
||||||
|
* @return name string or empty string
|
||||||
|
*/
|
||||||
|
std::wstring GUIFormSpecMenu::getNameByID(s32 id)
|
||||||
|
{
|
||||||
|
for(std::vector<FieldSpec>::iterator iter = m_fields.begin();
|
||||||
|
iter != m_fields.end(); iter++) {
|
||||||
|
if (iter->fid == id) {
|
||||||
|
return iter->fname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get label of element by id
|
||||||
|
* @param id of element
|
||||||
|
* @return label string or empty string
|
||||||
|
*/
|
||||||
|
std::wstring GUIFormSpecMenu::getLabelByID(s32 id)
|
||||||
|
{
|
||||||
|
for(std::vector<FieldSpec>::iterator iter = m_fields.begin();
|
||||||
|
iter != m_fields.end(); iter++) {
|
||||||
|
if (iter->fid == id) {
|
||||||
|
return iter->flabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color,
|
bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color,
|
||||||
bool quiet)
|
bool quiet)
|
||||||
{
|
{
|
||||||
|
@ -151,7 +151,7 @@ class GUIFormSpecMenu : public GUIModalMenu
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
FieldSpec(const std::wstring &name, const std::wstring &label,
|
FieldSpec(const std::wstring &name, const std::wstring &label,
|
||||||
const std::wstring &fdeflt, int id) :
|
const std::wstring &fdeflt, int id) :
|
||||||
fname(name),
|
fname(name),
|
||||||
flabel(label),
|
flabel(label),
|
||||||
fdefault(fdeflt),
|
fdefault(fdeflt),
|
||||||
@ -274,6 +274,10 @@ public:
|
|||||||
static bool parseColor(const std::string &value,
|
static bool parseColor(const std::string &value,
|
||||||
video::SColor &color, bool quiet);
|
video::SColor &color, bool quiet);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
bool getAndroidUIInput();
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
v2s32 getBasePos() const
|
v2s32 getBasePos() const
|
||||||
{
|
{
|
||||||
@ -409,6 +413,14 @@ private:
|
|||||||
clickpos m_doubleclickdetect[2];
|
clickpos m_doubleclickdetect[2];
|
||||||
|
|
||||||
int m_btn_height;
|
int m_btn_height;
|
||||||
|
|
||||||
|
std::wstring getLabelByID(s32 id);
|
||||||
|
std::wstring getNameByID(s32 id);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
v2s32 m_down_pos;
|
||||||
|
std::wstring m_JavaDialogFieldName;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FormspecFormSource: public IFormSource
|
class FormspecFormSource: public IFormSource
|
||||||
|
@ -259,6 +259,10 @@ struct HTTPFetchOngoing
|
|||||||
request.extra_headers[i].c_str());
|
request.extra_headers[i].c_str());
|
||||||
}
|
}
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, httpheader);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, httpheader);
|
||||||
|
|
||||||
|
if (!g_settings->getBool("curl_verify_cert")) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +306,7 @@ struct HTTPFetchOngoing
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
infostream<<request.url<<" not found ("
|
errorstream<<request.url<<" not found ("
|
||||||
<<curl_easy_strerror(res)<<")"
|
<<curl_easy_strerror(res)<<")"
|
||||||
<<" (response code "<<result.response_code<<")"
|
<<" (response code "<<result.response_code<<")"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
13
src/hud.cpp
@ -33,6 +33,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
#include "touchscreengui.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
|
Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
|
||||||
gui::IGUIEnvironment* guienv, gui::IGUIFont *font,
|
gui::IGUIEnvironment* guienv, gui::IGUIFont *font,
|
||||||
@ -160,6 +163,11 @@ void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect, bool sele
|
|||||||
void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
|
void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
|
||||||
InventoryList *mainlist, u16 selectitem, u16 direction)
|
InventoryList *mainlist, u16 selectitem, u16 direction)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if ( (g_touchscreengui) && (offset == 0))
|
||||||
|
g_touchscreengui->resetHud();
|
||||||
|
#endif
|
||||||
|
|
||||||
s32 height = m_hotbar_imagesize + m_padding * 2;
|
s32 height = m_hotbar_imagesize + m_padding * 2;
|
||||||
s32 width = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);
|
s32 width = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);
|
||||||
|
|
||||||
@ -222,6 +230,11 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i +1) == selectitem );
|
drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i +1) == selectitem );
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if (g_touchscreengui)
|
||||||
|
g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ItemDefinition
|
ItemDefinition
|
||||||
*/
|
*/
|
||||||
@ -433,6 +437,11 @@ public:
|
|||||||
params.light_color.set(1.0, 0.5, 0.5, 0.5);
|
params.light_color.set(1.0, 0.5, 0.5, 0.5);
|
||||||
params.light_radius = 1000;
|
params.light_radius = 1000;
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
params.camera_position.set(0, -1.0, -1.5);
|
||||||
|
params.camera_position.rotateXZBy(45);
|
||||||
|
params.light_position.set(10, -100, -50);
|
||||||
|
#endif
|
||||||
cc->inventory_texture =
|
cc->inventory_texture =
|
||||||
tsrc->generateTextureFromMesh(params);
|
tsrc->generateTextureFromMesh(params);
|
||||||
|
|
||||||
|
@ -51,7 +51,15 @@ JSemaphore::JSemaphore() {
|
|||||||
|
|
||||||
JSemaphore::~JSemaphore() {
|
JSemaphore::~JSemaphore() {
|
||||||
int sem_destroy_retval = sem_destroy(&m_semaphore);
|
int sem_destroy_retval = sem_destroy(&m_semaphore);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
// WORKAROUND for broken bionic semaphore implementation!
|
||||||
|
assert(
|
||||||
|
(sem_destroy_retval == 0) ||
|
||||||
|
(errno == EBUSY)
|
||||||
|
);
|
||||||
|
#else
|
||||||
assert(sem_destroy_retval == 0);
|
assert(sem_destroy_retval == 0);
|
||||||
|
#endif
|
||||||
UNUSED(sem_destroy_retval);
|
UNUSED(sem_destroy_retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,11 @@ int JThread::Kill()
|
|||||||
}
|
}
|
||||||
return ERR_JTHREAD_NOTRUNNING;
|
return ERR_JTHREAD_NOTRUNNING;
|
||||||
}
|
}
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
pthread_kill(threadid, SIGKILL);
|
||||||
|
#else
|
||||||
pthread_cancel(threadid);
|
pthread_cancel(threadid);
|
||||||
|
#endif
|
||||||
if (started) {
|
if (started) {
|
||||||
int pthread_join_retval = pthread_join(threadid,&status);
|
int pthread_join_retval = pthread_join(threadid,&status);
|
||||||
assert(pthread_join_retval == 0);
|
assert(pthread_join_retval == 0);
|
||||||
|
@ -334,6 +334,7 @@ const char *KeyPress::name() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const KeyPress EscapeKey("KEY_ESCAPE");
|
const KeyPress EscapeKey("KEY_ESCAPE");
|
||||||
|
const KeyPress CancelKey("KEY_CANCEL");
|
||||||
const KeyPress NumberKey[] = {
|
const KeyPress NumberKey[] = {
|
||||||
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"),
|
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"),
|
||||||
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"),
|
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"),
|
||||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define KEYCODE_HEADER
|
#define KEYCODE_HEADER
|
||||||
|
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
#include "Keycodes.h"
|
||||||
#include <IEventReceiver.h>
|
#include <IEventReceiver.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const KeyPress EscapeKey;
|
extern const KeyPress EscapeKey;
|
||||||
|
extern const KeyPress CancelKey;
|
||||||
extern const KeyPress NumberKey[10];
|
extern const KeyPress NumberKey[10];
|
||||||
|
|
||||||
// Key configuration getter
|
// Key configuration getter
|
||||||
@ -65,5 +67,7 @@ KeyPress getKeySetting(const char *settingname);
|
|||||||
// Clear fast lookup cache
|
// Clear fast lookup cache
|
||||||
void clearKeyCache();
|
void clearKeyCache();
|
||||||
|
|
||||||
|
irr::EKEY_CODE keyname_to_keycode(const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "threads.h"
|
#include "threads.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "gettime.h"
|
#include "gettime.h"
|
||||||
|
#include "porting.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
|
std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
|
||||||
std::map<threadid_t, std::string> log_threadnames;
|
std::map<threadid_t, std::string> log_threadnames;
|
||||||
@ -139,6 +141,9 @@ public:
|
|||||||
void printbuf()
|
void printbuf()
|
||||||
{
|
{
|
||||||
log_printline(m_lev, m_buf);
|
log_printline(m_lev, m_buf);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME, "%s", m_buf.c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void bufchar(char c)
|
void bufchar(char c)
|
||||||
|
@ -176,9 +176,15 @@ static void buffreplace (LexState *ls, char from, char to) {
|
|||||||
|
|
||||||
static void trydecpoint (LexState *ls, SemInfo *seminfo) {
|
static void trydecpoint (LexState *ls, SemInfo *seminfo) {
|
||||||
/* format error: try to update decimal point separator */
|
/* format error: try to update decimal point separator */
|
||||||
|
#ifndef __ANDROID__
|
||||||
struct lconv *cv = localeconv();
|
struct lconv *cv = localeconv();
|
||||||
|
#endif
|
||||||
char old = ls->decpoint;
|
char old = ls->decpoint;
|
||||||
|
#ifndef __ANDROID__
|
||||||
ls->decpoint = (cv ? cv->decimal_point[0] : '.');
|
ls->decpoint = (cv ? cv->decimal_point[0] : '.');
|
||||||
|
#else
|
||||||
|
ls->decpoint = '.';
|
||||||
|
#endif
|
||||||
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
|
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
|
||||||
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
|
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
|
||||||
/* format error with correct decimal point: no more options */
|
/* format error with correct decimal point: no more options */
|
||||||
|
107
src/main.cpp
@ -84,10 +84,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#ifdef USE_LEVELDB
|
#ifdef USE_LEVELDB
|
||||||
#include "database-leveldb.h"
|
#include "database-leveldb.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_REDIS
|
#if USE_REDIS
|
||||||
#include "database-redis.h"
|
#include "database-redis.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
#include "touchscreengui.h"
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
Settings.
|
Settings.
|
||||||
These are loaded from the config file.
|
These are loaded from the config file.
|
||||||
@ -253,6 +257,11 @@ public:
|
|||||||
React to nothing here if a menu is active
|
React to nothing here if a menu is active
|
||||||
*/
|
*/
|
||||||
if (noMenuActive() == false) {
|
if (noMenuActive() == false) {
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if (m_touchscreengui != 0) {
|
||||||
|
m_touchscreengui->Toggle(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return g_menumgr.preprocessEvent(event);
|
return g_menumgr.preprocessEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +275,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
// case of touchscreengui we have to handle different events
|
||||||
|
if ((m_touchscreengui != 0) &&
|
||||||
|
(event.EventType == irr::EET_TOUCH_INPUT_EVENT)) {
|
||||||
|
m_touchscreengui->translateEvent(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// handle mouse events
|
||||||
|
if(event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
|
||||||
if (noMenuActive() == false) {
|
if (noMenuActive() == false) {
|
||||||
left_active = false;
|
left_active = false;
|
||||||
middle_active = false;
|
middle_active = false;
|
||||||
@ -293,8 +311,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.EventType == irr::EET_LOG_TEXT_EVENT) {
|
if(event.EventType == irr::EET_LOG_TEXT_EVENT) {
|
||||||
dstream << "Irrlicht log: " << event.LogEvent.Text << std::endl;
|
dstream<< std::string("Irrlicht log: ") + std::string(event.LogEvent.Text)<<std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* always return false in order to continue processing events */
|
/* always return false in order to continue processing events */
|
||||||
@ -342,6 +360,9 @@ public:
|
|||||||
MyEventReceiver()
|
MyEventReceiver()
|
||||||
{
|
{
|
||||||
clearInput();
|
clearInput();
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
m_touchscreengui = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool leftclicked;
|
bool leftclicked;
|
||||||
@ -355,7 +376,12 @@ public:
|
|||||||
|
|
||||||
s32 mouse_wheel;
|
s32 mouse_wheel;
|
||||||
|
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
TouchScreenGUI* m_touchscreengui;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
IrrlichtDevice *m_device;
|
||||||
|
|
||||||
// The current state of keys
|
// The current state of keys
|
||||||
KeyList keyIsDown;
|
KeyList keyIsDown;
|
||||||
@ -372,7 +398,8 @@ class RealInputHandler : public InputHandler
|
|||||||
public:
|
public:
|
||||||
RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver):
|
RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver):
|
||||||
m_device(device),
|
m_device(device),
|
||||||
m_receiver(receiver)
|
m_receiver(receiver),
|
||||||
|
m_mousepos(0,0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual bool isKeyDown(const KeyPress &keyCode)
|
virtual bool isKeyDown(const KeyPress &keyCode)
|
||||||
@ -385,11 +412,21 @@ public:
|
|||||||
}
|
}
|
||||||
virtual v2s32 getMousePos()
|
virtual v2s32 getMousePos()
|
||||||
{
|
{
|
||||||
return m_device->getCursorControl()->getPosition();
|
if (m_device->getCursorControl()) {
|
||||||
|
return m_device->getCursorControl()->getPosition();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return m_mousepos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
virtual void setMousePos(s32 x, s32 y)
|
virtual void setMousePos(s32 x, s32 y)
|
||||||
{
|
{
|
||||||
m_device->getCursorControl()->setPosition(x, y);
|
if (m_device->getCursorControl()) {
|
||||||
|
m_device->getCursorControl()->setPosition(x, y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_mousepos = v2s32(x,y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool getLeftState()
|
virtual bool getLeftState()
|
||||||
@ -445,8 +482,9 @@ public:
|
|||||||
m_receiver->clearInput();
|
m_receiver->clearInput();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
IrrlichtDevice *m_device;
|
IrrlichtDevice *m_device;
|
||||||
MyEventReceiver *m_receiver;
|
MyEventReceiver *m_receiver;
|
||||||
|
v2s32 m_mousepos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RandomInputHandler : public InputHandler
|
class RandomInputHandler : public InputHandler
|
||||||
@ -855,8 +893,18 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
porting::initializePaths();
|
porting::initializePaths();
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
porting::initAndroid();
|
||||||
|
|
||||||
|
porting::setExternalStorageDir(porting::jnienv);
|
||||||
|
if (!fs::PathExists(porting::path_user)) {
|
||||||
|
fs::CreateDir(porting::path_user);
|
||||||
|
}
|
||||||
|
porting::copyAssets();
|
||||||
|
#else
|
||||||
// Create user data directory
|
// Create user data directory
|
||||||
fs::CreateDir(porting::path_user);
|
fs::CreateDir(porting::path_user);
|
||||||
|
#endif
|
||||||
|
|
||||||
infostream << "path_share = " << porting::path_share << std::endl;
|
infostream << "path_share = " << porting::path_share << std::endl;
|
||||||
infostream << "path_user = " << porting::path_user << std::endl;
|
infostream << "path_user = " << porting::path_user << std::endl;
|
||||||
@ -975,14 +1023,15 @@ int main(int argc, char *argv[])
|
|||||||
// Initialize HTTP fetcher
|
// Initialize HTTP fetcher
|
||||||
httpfetch_init(g_settings->getS32("curl_parallel_limit"));
|
httpfetch_init(g_settings->getS32("curl_parallel_limit"));
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
/*
|
/*
|
||||||
Run unit tests
|
Run unit tests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
|
if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
|
||||||
|| cmd_args.getFlag("enable-unittests") == true) {
|
|| cmd_args.getFlag("enable-unittests") == true) {
|
||||||
run_tests();
|
run_tests();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),
|
init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),
|
||||||
g_settings->get("language"), argc, argv);
|
g_settings->get("language"), argc, argv);
|
||||||
@ -1348,7 +1397,7 @@ int main(int argc, char *argv[])
|
|||||||
List video modes if requested
|
List video modes if requested
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MyEventReceiver receiver;
|
MyEventReceiver* receiver = new MyEventReceiver();
|
||||||
|
|
||||||
if (cmd_args.getFlag("videomodes")) {
|
if (cmd_args.getFlag("videomodes")) {
|
||||||
IrrlichtDevice *nulldevice;
|
IrrlichtDevice *nulldevice;
|
||||||
@ -1361,7 +1410,7 @@ int main(int argc, char *argv[])
|
|||||||
params.Fullscreen = false;
|
params.Fullscreen = false;
|
||||||
params.Stencilbuffer = false;
|
params.Stencilbuffer = false;
|
||||||
params.Vsync = vsync;
|
params.Vsync = vsync;
|
||||||
params.EventReceiver = &receiver;
|
params.EventReceiver = receiver;
|
||||||
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");
|
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");
|
||||||
|
|
||||||
nulldevice = createDeviceEx(params);
|
nulldevice = createDeviceEx(params);
|
||||||
@ -1397,15 +1446,13 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
nulldevice->drop();
|
nulldevice->drop();
|
||||||
|
|
||||||
|
delete receiver;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create device and exit if creation failed
|
Create device and exit if creation failed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
IrrlichtDevice *device;
|
|
||||||
|
|
||||||
SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
|
SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
|
||||||
params.DriverType = driverType;
|
params.DriverType = driverType;
|
||||||
params.WindowSize = core::dimension2d<u32>(screenW, screenH);
|
params.WindowSize = core::dimension2d<u32>(screenW, screenH);
|
||||||
@ -1414,12 +1461,18 @@ int main(int argc, char *argv[])
|
|||||||
params.Fullscreen = fullscreen;
|
params.Fullscreen = fullscreen;
|
||||||
params.Stencilbuffer = false;
|
params.Stencilbuffer = false;
|
||||||
params.Vsync = vsync;
|
params.Vsync = vsync;
|
||||||
params.EventReceiver = &receiver;
|
params.EventReceiver = receiver;
|
||||||
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");
|
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
params.PrivateData = porting::app_global;
|
||||||
|
params.OGLES2ShaderPath = std::string(porting::path_user + DIR_DELIM +
|
||||||
|
"media" + DIR_DELIM + "Shaders" + DIR_DELIM).c_str();
|
||||||
|
#endif
|
||||||
|
|
||||||
device = createDeviceEx(params);
|
IrrlichtDevice * device = createDeviceEx(params);
|
||||||
|
|
||||||
if (device == 0) {
|
if (device == 0) {
|
||||||
|
delete receiver;
|
||||||
return 1; // could not create selected driver.
|
return 1; // could not create selected driver.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1476,10 +1529,11 @@ int main(int argc, char *argv[])
|
|||||||
bool random_input = g_settings->getBool("random_input")
|
bool random_input = g_settings->getBool("random_input")
|
||||||
|| cmd_args.getFlag("random-input");
|
|| cmd_args.getFlag("random-input");
|
||||||
InputHandler *input = NULL;
|
InputHandler *input = NULL;
|
||||||
|
|
||||||
if (random_input) {
|
if (random_input) {
|
||||||
input = new RandomInputHandler();
|
input = new RandomInputHandler();
|
||||||
} else {
|
} else {
|
||||||
input = new RealInputHandler(device, &receiver);
|
input = new RealInputHandler(device,receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
scene::ISceneManager* smgr = device->getSceneManager();
|
scene::ISceneManager* smgr = device->getSceneManager();
|
||||||
@ -1564,7 +1618,8 @@ int main(int argc, char *argv[])
|
|||||||
/*
|
/*
|
||||||
Menu-game loop
|
Menu-game loop
|
||||||
*/
|
*/
|
||||||
while (device->run() && kill == false)
|
while (device->run() && (kill == false) &&
|
||||||
|
(g_gamecallback->shutdown_requested == false))
|
||||||
{
|
{
|
||||||
// Set the window caption
|
// Set the window caption
|
||||||
wchar_t* text = wgettext("Main Menu");
|
wchar_t* text = wgettext("Main Menu");
|
||||||
@ -1612,7 +1667,9 @@ int main(int argc, char *argv[])
|
|||||||
first_loop = false;
|
first_loop = false;
|
||||||
|
|
||||||
// Cursor can be non-visible when coming from the game
|
// Cursor can be non-visible when coming from the game
|
||||||
|
#ifndef ANDROID
|
||||||
device->getCursorControl()->setVisible(true);
|
device->getCursorControl()->setVisible(true);
|
||||||
|
#endif
|
||||||
// Some stuff are left to scene manager when coming from the game
|
// Some stuff are left to scene manager when coming from the game
|
||||||
// (map at least?)
|
// (map at least?)
|
||||||
smgr->clear();
|
smgr->clear();
|
||||||
@ -1661,10 +1718,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
infostream << "Waited for other menus" << std::endl;
|
infostream << "Waited for other menus" << std::endl;
|
||||||
|
|
||||||
GUIEngine* temp = new GUIEngine(device, guiroot,
|
/* show main menu */
|
||||||
&g_menumgr, smgr, &menudata, kill);
|
GUIEngine mymenu(device, guiroot, &g_menumgr,smgr,&menudata,kill);
|
||||||
|
|
||||||
delete temp;
|
|
||||||
//once finished you'll never end up here
|
//once finished you'll never end up here
|
||||||
smgr->clear();
|
smgr->clear();
|
||||||
}
|
}
|
||||||
@ -1788,6 +1844,10 @@ int main(int argc, char *argv[])
|
|||||||
/*
|
/*
|
||||||
Run game
|
Run game
|
||||||
*/
|
*/
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
receiver->m_touchscreengui = new TouchScreenGUI(device, receiver);
|
||||||
|
g_touchscreengui = receiver->m_touchscreengui;
|
||||||
|
#endif
|
||||||
the_game(
|
the_game(
|
||||||
kill,
|
kill,
|
||||||
random_input,
|
random_input,
|
||||||
@ -1805,6 +1865,11 @@ int main(int argc, char *argv[])
|
|||||||
simple_singleplayer_mode
|
simple_singleplayer_mode
|
||||||
);
|
);
|
||||||
smgr->clear();
|
smgr->clear();
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
delete g_touchscreengui;
|
||||||
|
g_touchscreengui = NULL;
|
||||||
|
receiver->m_touchscreengui = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
} //try
|
} //try
|
||||||
catch(con::PeerNotFoundException &e)
|
catch(con::PeerNotFoundException &e)
|
||||||
@ -1849,7 +1914,7 @@ int main(int argc, char *argv[])
|
|||||||
if (use_freetype)
|
if (use_freetype)
|
||||||
font->drop();
|
font->drop();
|
||||||
#endif
|
#endif
|
||||||
|
delete receiver;
|
||||||
#endif // !SERVER
|
#endif // !SERVER
|
||||||
|
|
||||||
// Update configuration file
|
// Update configuration file
|
||||||
|
@ -124,13 +124,17 @@ public:
|
|||||||
disconnect_requested(false),
|
disconnect_requested(false),
|
||||||
changepassword_requested(false),
|
changepassword_requested(false),
|
||||||
changevolume_requested(false),
|
changevolume_requested(false),
|
||||||
|
shutdown_requested(false),
|
||||||
device(a_device)
|
device(a_device)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void exitToOS()
|
virtual void exitToOS()
|
||||||
{
|
{
|
||||||
|
shutdown_requested = true;
|
||||||
|
#ifndef __ANDROID__
|
||||||
device->closeDevice();
|
device->closeDevice();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void disconnect()
|
virtual void disconnect()
|
||||||
@ -151,6 +155,7 @@ public:
|
|||||||
bool disconnect_requested;
|
bool disconnect_requested;
|
||||||
bool changepassword_requested;
|
bool changepassword_requested;
|
||||||
bool changevolume_requested;
|
bool changevolume_requested;
|
||||||
|
bool shutdown_requested;
|
||||||
IrrlichtDevice *device;
|
IrrlichtDevice *device;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,6 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MODALMENU_HEADER
|
#define MODALMENU_HEADER
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
#include "touchscreengui.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class GUIModalMenu;
|
class GUIModalMenu;
|
||||||
|
|
||||||
@ -101,6 +104,10 @@ public:
|
|||||||
Environment->removeFocus(this);
|
Environment->removeFocus(this);
|
||||||
m_menumgr->deletingMenu(this);
|
m_menumgr->deletingMenu(this);
|
||||||
this->remove();
|
this->remove();
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if (g_touchscreengui)
|
||||||
|
g_touchscreengui->Show();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeChildren()
|
void removeChildren()
|
||||||
|
@ -167,6 +167,7 @@ int getNumberOfProcessors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
bool threadBindToProcessor(threadid_t tid, int pnumber) {
|
bool threadBindToProcessor(threadid_t tid, int pnumber) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
@ -219,7 +220,7 @@ bool threadBindToProcessor(threadid_t tid, int pnumber) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool threadSetPriority(threadid_t tid, int prio) {
|
bool threadSetPriority(threadid_t tid, int prio) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@ -458,9 +459,15 @@ void initializePaths()
|
|||||||
{
|
{
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
memset(buf, 0, BUFSIZ);
|
memset(buf, 0, BUFSIZ);
|
||||||
assert(readlink("/proc/self/exe", buf, BUFSIZ-1) != -1);
|
if (readlink("/proc/self/exe", buf, BUFSIZ-1) == -1) {
|
||||||
pathRemoveFile(buf, '/');
|
errorstream << "Unable to read bindir "<< std::endl;
|
||||||
bindir = buf;
|
#ifndef __ANDROID__
|
||||||
|
assert("Unable to read bindir" == 0);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
pathRemoveFile(buf, '/');
|
||||||
|
bindir = buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find share directory from these.
|
// Find share directory from these.
|
||||||
@ -472,6 +479,9 @@ void initializePaths()
|
|||||||
trylist.push_back(
|
trylist.push_back(
|
||||||
bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME);
|
bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME);
|
||||||
trylist.push_back(bindir + DIR_DELIM + "..");
|
trylist.push_back(bindir + DIR_DELIM + "..");
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
trylist.push_back(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME);
|
||||||
|
#endif
|
||||||
|
|
||||||
for(std::list<std::string>::const_iterator i = trylist.begin();
|
for(std::list<std::string>::const_iterator i = trylist.begin();
|
||||||
i != trylist.end(); i++)
|
i != trylist.end(); i++)
|
||||||
@ -490,8 +500,11 @@ void initializePaths()
|
|||||||
path_share = trypath;
|
path_share = trypath;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifndef __ANDROID__
|
||||||
path_user = std::string(getenv("HOME")) + DIR_DELIM + "." + PROJECT_NAME;
|
path_user = std::string(getenv("HOME")) + DIR_DELIM + "." + PROJECT_NAME;
|
||||||
|
#else
|
||||||
|
path_user = std::string(DIR_DELIM "sdcard" DIR_DELIM PROJECT_NAME DIR_DELIM);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
OS X
|
OS X
|
||||||
@ -539,6 +552,7 @@ v2u32 getWindowSize() {
|
|||||||
return device->getVideoDriver()->getScreenSize();
|
return device->getVideoDriver()->getScreenSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
|
|
||||||
float getDisplayDensity() {
|
float getDisplayDensity() {
|
||||||
float gui_scaling = g_settings->getFloat("gui_scaling");
|
float gui_scaling = g_settings->getFloat("gui_scaling");
|
||||||
@ -562,6 +576,7 @@ v2u32 getDisplaySize() {
|
|||||||
return deskres;
|
return deskres;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
} //namespace porting
|
} //namespace porting
|
||||||
|
|
||||||
|
@ -373,5 +373,9 @@ v2u32 getWindowSize();
|
|||||||
|
|
||||||
} // namespace porting
|
} // namespace porting
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include "porting_android.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // PORTING_HEADER
|
#endif // PORTING_HEADER
|
||||||
|
|
||||||
|
295
src/porting_android.cpp
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2014 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
|
#error This file may only be compiled for android!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "porting.h"
|
||||||
|
#include "porting_android.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "filesys.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#ifdef GPROF
|
||||||
|
#include "prof.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
void android_main(android_app *app)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
porting::app_global = app;
|
||||||
|
|
||||||
|
porting::setThreadName("MainThread");
|
||||||
|
|
||||||
|
try {
|
||||||
|
app_dummy();
|
||||||
|
char *argv[] = { (char*) "minetest" };
|
||||||
|
main(sizeof(argv) / sizeof(argv[0]), argv);
|
||||||
|
}
|
||||||
|
catch(BaseException e) {
|
||||||
|
std::stringstream msg;
|
||||||
|
msg << "Exception handled by main: " << e.what();
|
||||||
|
const char* message = msg.str().c_str();
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME, "%s", message);
|
||||||
|
errorstream << msg << std::endl;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
catch(...) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME,
|
||||||
|
"Some exception occured");
|
||||||
|
errorstream << "Uncaught exception in main thread!" << std::endl;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
porting::cleanupAndroid();
|
||||||
|
errorstream << "Shutting down minetest." << std::endl;
|
||||||
|
exit(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handler for finished message box input */
|
||||||
|
/* Intentionally NOT in namespace porting */
|
||||||
|
/* TODO this doesn't work as expected, no idea why but there's a workaround */
|
||||||
|
/* for it right now */
|
||||||
|
extern "C" {
|
||||||
|
JNIEXPORT void JNICALL Java_org_minetest_MtNativeActivity_putMessageBoxResult(
|
||||||
|
JNIEnv * env, jclass thiz, jstring text)
|
||||||
|
{
|
||||||
|
errorstream << "Java_org_minetest_MtNativeActivity_putMessageBoxResult got: "
|
||||||
|
<< std::string((const char*)env->GetStringChars(text,0))
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace porting {
|
||||||
|
|
||||||
|
std::string path_storage = DIR_DELIM "sdcard" DIR_DELIM;
|
||||||
|
|
||||||
|
android_app* app_global;
|
||||||
|
JNIEnv* jnienv;
|
||||||
|
jclass nativeActivity;
|
||||||
|
|
||||||
|
jclass findClass(std::string classname)
|
||||||
|
{
|
||||||
|
if (jnienv == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass nativeactivity = jnienv->FindClass("android/app/NativeActivity");
|
||||||
|
jmethodID getClassLoader =
|
||||||
|
jnienv->GetMethodID(nativeactivity,"getClassLoader",
|
||||||
|
"()Ljava/lang/ClassLoader;");
|
||||||
|
jobject cls =
|
||||||
|
jnienv->CallObjectMethod(app_global->activity->clazz, getClassLoader);
|
||||||
|
jclass classLoader = jnienv->FindClass("java/lang/ClassLoader");
|
||||||
|
jmethodID findClass =
|
||||||
|
jnienv->GetMethodID(classLoader, "loadClass",
|
||||||
|
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||||
|
jstring strClassName =
|
||||||
|
jnienv->NewStringUTF(classname.c_str());
|
||||||
|
return (jclass) jnienv->CallObjectMethod(cls, findClass, strClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyAssets()
|
||||||
|
{
|
||||||
|
jmethodID assetcopy = jnienv->GetMethodID(nativeActivity,"copyAssets","()V");
|
||||||
|
|
||||||
|
if (assetcopy == 0) {
|
||||||
|
assert("porting::copyAssets unable to find copy assets method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
jnienv->CallVoidMethod(app_global->activity->clazz, assetcopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initAndroid()
|
||||||
|
{
|
||||||
|
porting::jnienv = NULL;
|
||||||
|
JavaVM *jvm = app_global->activity->vm;
|
||||||
|
JavaVMAttachArgs lJavaVMAttachArgs;
|
||||||
|
lJavaVMAttachArgs.version = JNI_VERSION_1_6;
|
||||||
|
lJavaVMAttachArgs.name = "MinetestNativeThread";
|
||||||
|
lJavaVMAttachArgs.group = NULL;
|
||||||
|
#ifdef NDEBUG
|
||||||
|
// This is a ugly hack as arm v7a non debuggable builds crash without this
|
||||||
|
// printf ... if someone finds out why please fix it!
|
||||||
|
infostream << "Attaching native thread. " << std::endl;
|
||||||
|
#endif
|
||||||
|
if ( jvm->AttachCurrentThread(&porting::jnienv, &lJavaVMAttachArgs) == JNI_ERR) {
|
||||||
|
errorstream << "Failed to attach native thread to jvm" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeActivity = findClass("org/minetest/minetest/MtNativeActivity");
|
||||||
|
if (nativeActivity == 0) {
|
||||||
|
errorstream <<
|
||||||
|
"porting::initAndroid unable to find java native activity class" <<
|
||||||
|
std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GPROF
|
||||||
|
/* in the start-up code */
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME,
|
||||||
|
"Initializing GPROF profiler");
|
||||||
|
monstartup("libminetest.so");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupAndroid()
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef GPROF
|
||||||
|
errorstream << "Shutting down GPROF profiler" << std::endl;
|
||||||
|
setenv("CPUPROFILE", (path_user + DIR_DELIM + "gmon.out").c_str(), 1);
|
||||||
|
moncleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JavaVM *jvm = app_global->activity->vm;
|
||||||
|
jvm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExternalStorageDir(JNIEnv* lJNIEnv)
|
||||||
|
{
|
||||||
|
// Android: Retrieve ablsolute path to external storage device (sdcard)
|
||||||
|
jclass ClassEnv = lJNIEnv->FindClass("android/os/Environment");
|
||||||
|
jmethodID MethodDir =
|
||||||
|
lJNIEnv->GetStaticMethodID(ClassEnv,
|
||||||
|
"getExternalStorageDirectory","()Ljava/io/File;");
|
||||||
|
jobject ObjectFile = lJNIEnv->CallStaticObjectMethod(ClassEnv, MethodDir);
|
||||||
|
jclass ClassFile = lJNIEnv->FindClass("java/io/File");
|
||||||
|
|
||||||
|
jmethodID MethodPath =
|
||||||
|
lJNIEnv->GetMethodID(ClassFile, "getAbsolutePath",
|
||||||
|
"()Ljava/lang/String;");
|
||||||
|
jstring StringPath =
|
||||||
|
(jstring) lJNIEnv->CallObjectMethod(ObjectFile, MethodPath);
|
||||||
|
|
||||||
|
const char *externalPath = lJNIEnv->GetStringUTFChars(StringPath, NULL);
|
||||||
|
std::string userPath(externalPath);
|
||||||
|
lJNIEnv->ReleaseStringUTFChars(StringPath, externalPath);
|
||||||
|
|
||||||
|
path_storage = userPath;
|
||||||
|
path_user = userPath + DIR_DELIM + PROJECT_NAME;
|
||||||
|
path_share = userPath + DIR_DELIM + PROJECT_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
void showInputDialog(const std::string& acceptButton, const std::string& hint,
|
||||||
|
const std::string& current, int editType)
|
||||||
|
{
|
||||||
|
jmethodID showdialog = jnienv->GetMethodID(nativeActivity,"showDialog",
|
||||||
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
|
||||||
|
|
||||||
|
if (showdialog == 0) {
|
||||||
|
assert("porting::showInputDialog unable to find java show dialog method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring jacceptButton = jnienv->NewStringUTF(acceptButton.c_str());
|
||||||
|
jstring jhint = jnienv->NewStringUTF(hint.c_str());
|
||||||
|
jstring jcurrent = jnienv->NewStringUTF(current.c_str());
|
||||||
|
jint jeditType = editType;
|
||||||
|
|
||||||
|
jnienv->CallVoidMethod(app_global->activity->clazz, showdialog,
|
||||||
|
jacceptButton, jhint, jcurrent, jeditType);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getInputDialogState()
|
||||||
|
{
|
||||||
|
jmethodID dialogstate = jnienv->GetMethodID(nativeActivity,
|
||||||
|
"getDialogState", "()I");
|
||||||
|
|
||||||
|
if (dialogstate == 0) {
|
||||||
|
assert("porting::getInputDialogState unable to find java dialog state method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jnienv->CallIntMethod(app_global->activity->clazz, dialogstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getInputDialogValue()
|
||||||
|
{
|
||||||
|
jmethodID dialogvalue = jnienv->GetMethodID(nativeActivity,
|
||||||
|
"getDialogValue", "()Ljava/lang/String;");
|
||||||
|
|
||||||
|
if (dialogvalue == 0) {
|
||||||
|
assert("porting::getInputDialogValue unable to find java dialog value method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject result = jnienv->CallObjectMethod(app_global->activity->clazz,
|
||||||
|
dialogvalue);
|
||||||
|
|
||||||
|
const char* javachars = jnienv->GetStringUTFChars((jstring) result,0);
|
||||||
|
std::string text(javachars);
|
||||||
|
jnienv->ReleaseStringUTFChars((jstring) result, javachars);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if not defined(SERVER)
|
||||||
|
float getDisplayDensity()
|
||||||
|
{
|
||||||
|
static bool firstrun = true;
|
||||||
|
static float value = 0;
|
||||||
|
|
||||||
|
if (firstrun) {
|
||||||
|
jmethodID getDensity = jnienv->GetMethodID(nativeActivity, "getDensity",
|
||||||
|
"()F");
|
||||||
|
|
||||||
|
if (getDensity == 0) {
|
||||||
|
assert("porting::getDisplayDensity unable to find java getDensity method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = jnienv->CallFloatMethod(app_global->activity->clazz, getDensity);
|
||||||
|
firstrun = false;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2u32 getDisplaySize()
|
||||||
|
{
|
||||||
|
static bool firstrun = true;
|
||||||
|
static v2u32 retval;
|
||||||
|
|
||||||
|
if (firstrun) {
|
||||||
|
jmethodID getDisplayWidth = jnienv->GetMethodID(nativeActivity,
|
||||||
|
"getDisplayWidth", "()I");
|
||||||
|
|
||||||
|
if (getDisplayWidth == 0) {
|
||||||
|
assert("porting::getDisplayWidth unable to find java getDisplayWidth method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
retval.X = jnienv->CallIntMethod(app_global->activity->clazz,
|
||||||
|
getDisplayWidth);
|
||||||
|
|
||||||
|
jmethodID getDisplayHeight = jnienv->GetMethodID(nativeActivity,
|
||||||
|
"getDisplayHeight", "()I");
|
||||||
|
|
||||||
|
if (getDisplayHeight == 0) {
|
||||||
|
assert("porting::getDisplayHeight unable to find java getDisplayHeight method" == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
retval.Y = jnienv->CallIntMethod(app_global->activity->clazz,
|
||||||
|
getDisplayHeight);
|
||||||
|
|
||||||
|
firstrun = false;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif //SERVER
|
||||||
|
}
|
81
src/porting_android.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2014 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
#ifndef __PORTING_ANDROID_H__
|
||||||
|
#define __PORTING_ANDROID_H__
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
|
#error this include has to be included on android port only!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include <android_native_app_glue.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace porting {
|
||||||
|
/** java app **/
|
||||||
|
extern android_app *app_global;
|
||||||
|
|
||||||
|
/** java <-> c++ interaction interface **/
|
||||||
|
extern JNIEnv *jnienv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do initialization required on android only
|
||||||
|
*/
|
||||||
|
void initAndroid();
|
||||||
|
void cleanupAndroid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set storage dir on external sdcard#
|
||||||
|
* @param lJNIEnv environment from android
|
||||||
|
*/
|
||||||
|
void setExternalStorageDir(JNIEnv* lJNIEnv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use java function to copy media from assets to external storage
|
||||||
|
*/
|
||||||
|
void copyAssets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show text input dialog in java
|
||||||
|
* @param acceptButton text to display on accept button
|
||||||
|
* @param hint hint to show
|
||||||
|
* @param current initial value to display
|
||||||
|
* @param editType type of texfield
|
||||||
|
* (1==multiline text input; 2==single line text input; 3=password field)
|
||||||
|
*/
|
||||||
|
void showInputDialog(const std::string& acceptButton,
|
||||||
|
const std::string& hint, const std::string& current, int editType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WORKAROUND for not working callbacks from java -> c++
|
||||||
|
* get current state of input dialog
|
||||||
|
*/
|
||||||
|
int getInputDialogState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WORKAROUND for not working callbacks from java -> c++
|
||||||
|
* get text in current input dialog
|
||||||
|
*/
|
||||||
|
std::string getInputDialogValue();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
227
src/tile.cpp
@ -32,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
#include "util/numeric.h"
|
#include "util/numeric.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A cache from texture name to texture path
|
A cache from texture name to texture path
|
||||||
*/
|
*/
|
||||||
@ -702,6 +706,9 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
|
|||||||
|
|
||||||
if(baseimg != NULL)
|
if(baseimg != NULL)
|
||||||
{
|
{
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
baseimg = Align2Npot2(baseimg, driver);
|
||||||
|
#endif
|
||||||
// Create texture from resulting image
|
// Create texture from resulting image
|
||||||
t = driver->addTexture(name.c_str(), baseimg);
|
t = driver->addTexture(name.c_str(), baseimg);
|
||||||
baseimg->drop();
|
baseimg->drop();
|
||||||
@ -790,11 +797,17 @@ void TextureSource::rebuildImagesAndTextures()
|
|||||||
JMutexAutoLock lock(m_textureinfo_cache_mutex);
|
JMutexAutoLock lock(m_textureinfo_cache_mutex);
|
||||||
|
|
||||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||||
|
assert(driver != 0);
|
||||||
|
|
||||||
// Recreate textures
|
// Recreate textures
|
||||||
for(u32 i=0; i<m_textureinfo_cache.size(); i++){
|
for(u32 i=0; i<m_textureinfo_cache.size(); i++){
|
||||||
TextureInfo *ti = &m_textureinfo_cache[i];
|
TextureInfo *ti = &m_textureinfo_cache[i];
|
||||||
video::IImage *img = generateImageFromScratch(ti->name);
|
video::IImage *img = generateImageFromScratch(ti->name);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
img = Align2Npot2(img,driver);
|
||||||
|
assert(img->getDimension().Height == npot2(img->getDimension().Height));
|
||||||
|
assert(img->getDimension().Width == npot2(img->getDimension().Width));
|
||||||
|
#endif
|
||||||
// Create texture from resulting image
|
// Create texture from resulting image
|
||||||
video::ITexture *t = NULL;
|
video::ITexture *t = NULL;
|
||||||
if(img) {
|
if(img) {
|
||||||
@ -816,6 +829,126 @@ video::ITexture* TextureSource::generateTextureFromMesh(
|
|||||||
video::IVideoDriver *driver = m_device->getVideoDriver();
|
video::IVideoDriver *driver = m_device->getVideoDriver();
|
||||||
assert(driver);
|
assert(driver);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
const GLubyte* renderstr = glGetString(GL_RENDERER);
|
||||||
|
std::string renderer((char*) renderstr);
|
||||||
|
|
||||||
|
// use no render to texture hack
|
||||||
|
if (
|
||||||
|
(renderer.find("Adreno") != std::string::npos) ||
|
||||||
|
(renderer.find("Mali") != std::string::npos) ||
|
||||||
|
(renderer.find("Immersion") != std::string::npos) ||
|
||||||
|
(renderer.find("Tegra") != std::string::npos) ||
|
||||||
|
g_settings->getBool("inventory_image_hack")
|
||||||
|
) {
|
||||||
|
// Get a scene manager
|
||||||
|
scene::ISceneManager *smgr_main = m_device->getSceneManager();
|
||||||
|
assert(smgr_main);
|
||||||
|
scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
|
||||||
|
assert(smgr);
|
||||||
|
|
||||||
|
const float scaling = 0.2;
|
||||||
|
|
||||||
|
scene::IMeshSceneNode* meshnode =
|
||||||
|
smgr->addMeshSceneNode(params.mesh, NULL,
|
||||||
|
-1, v3f(0,0,0), v3f(0,0,0),
|
||||||
|
v3f(1.0 * scaling,1.0 * scaling,1.0 * scaling), true);
|
||||||
|
meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||||
|
meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
|
||||||
|
meshnode->setMaterialFlag(video::EMF_TRILINEAR_FILTER, m_setting_trilinear_filter);
|
||||||
|
meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, m_setting_bilinear_filter);
|
||||||
|
meshnode->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, m_setting_anisotropic_filter);
|
||||||
|
|
||||||
|
scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(0,
|
||||||
|
params.camera_position, params.camera_lookat);
|
||||||
|
// second parameter of setProjectionMatrix (isOrthogonal) is ignored
|
||||||
|
camera->setProjectionMatrix(params.camera_projection_matrix, false);
|
||||||
|
|
||||||
|
smgr->setAmbientLight(params.ambient_light);
|
||||||
|
smgr->addLightSceneNode(0,
|
||||||
|
params.light_position,
|
||||||
|
params.light_color,
|
||||||
|
params.light_radius*scaling);
|
||||||
|
|
||||||
|
core::dimension2d<u32> screen = driver->getScreenSize();
|
||||||
|
|
||||||
|
// Render scene
|
||||||
|
driver->beginScene(true, true, video::SColor(0,0,0,0));
|
||||||
|
driver->clearZBuffer();
|
||||||
|
smgr->drawAll();
|
||||||
|
|
||||||
|
core::dimension2d<u32> partsize(screen.Width * scaling,screen.Height * scaling);
|
||||||
|
|
||||||
|
irr::video::IImage* rawImage =
|
||||||
|
driver->createImage(irr::video::ECF_A8R8G8B8, partsize);
|
||||||
|
|
||||||
|
u8* pixels = static_cast<u8*>(rawImage->lock());
|
||||||
|
if (!pixels)
|
||||||
|
{
|
||||||
|
rawImage->drop();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::rect<s32> source(
|
||||||
|
screen.Width /2 - (screen.Width * (scaling / 2)),
|
||||||
|
screen.Height/2 - (screen.Height * (scaling / 2)),
|
||||||
|
screen.Width /2 + (screen.Width * (scaling / 2)),
|
||||||
|
screen.Height/2 + (screen.Height * (scaling / 2))
|
||||||
|
);
|
||||||
|
|
||||||
|
glReadPixels(source.UpperLeftCorner.X, source.UpperLeftCorner.Y,
|
||||||
|
partsize.Width, partsize.Height, GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE, pixels);
|
||||||
|
|
||||||
|
driver->endScene();
|
||||||
|
|
||||||
|
// Drop scene manager
|
||||||
|
smgr->drop();
|
||||||
|
|
||||||
|
unsigned int pixelcount = partsize.Width*partsize.Height;
|
||||||
|
|
||||||
|
u8* runptr = pixels;
|
||||||
|
for (unsigned int i=0; i < pixelcount; i++) {
|
||||||
|
|
||||||
|
u8 B = *runptr;
|
||||||
|
u8 G = *(runptr+1);
|
||||||
|
u8 R = *(runptr+2);
|
||||||
|
u8 A = *(runptr+3);
|
||||||
|
|
||||||
|
//BGRA -> RGBA
|
||||||
|
*runptr = R;
|
||||||
|
runptr ++;
|
||||||
|
*runptr = G;
|
||||||
|
runptr ++;
|
||||||
|
*runptr = B;
|
||||||
|
runptr ++;
|
||||||
|
*runptr = A;
|
||||||
|
runptr ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::IImage* inventory_image =
|
||||||
|
driver->createImage(irr::video::ECF_A8R8G8B8, params.dim);
|
||||||
|
|
||||||
|
rawImage->copyToScaling(inventory_image);
|
||||||
|
rawImage->drop();
|
||||||
|
|
||||||
|
video::ITexture *rtt = driver->addTexture(params.rtt_texture_name.c_str(), inventory_image);
|
||||||
|
inventory_image->drop();
|
||||||
|
|
||||||
|
if (rtt == NULL) {
|
||||||
|
errorstream << "TextureSource::generateTextureFromMesh(): failed to recreate texture from image: " << params.rtt_texture_name << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver->makeColorKeyTexture(rtt, v2s32(0,0));
|
||||||
|
|
||||||
|
if(params.delete_texture_on_shutdown)
|
||||||
|
m_texture_trash.push_back(rtt);
|
||||||
|
|
||||||
|
return rtt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
|
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
|
||||||
{
|
{
|
||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
@ -840,7 +973,12 @@ video::ITexture* TextureSource::generateTextureFromMesh(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set render target
|
// Set render target
|
||||||
driver->setRenderTarget(rtt, false, true, video::SColor(0,0,0,0));
|
if (!driver->setRenderTarget(rtt, false, true, video::SColor(0,0,0,0))) {
|
||||||
|
driver->removeTexture(rtt);
|
||||||
|
errorstream<<"TextureSource::generateTextureFromMesh(): "
|
||||||
|
<<"failed to set render target"<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Get a scene manager
|
// Get a scene manager
|
||||||
scene::ISceneManager *smgr_main = m_device->getSceneManager();
|
scene::ISceneManager *smgr_main = m_device->getSceneManager();
|
||||||
@ -848,7 +986,9 @@ video::ITexture* TextureSource::generateTextureFromMesh(
|
|||||||
scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
|
scene::ISceneManager *smgr = smgr_main->createNewSceneManager();
|
||||||
assert(smgr);
|
assert(smgr);
|
||||||
|
|
||||||
scene::IMeshSceneNode* meshnode = smgr->addMeshSceneNode(params.mesh, NULL, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
|
scene::IMeshSceneNode* meshnode =
|
||||||
|
smgr->addMeshSceneNode(params.mesh, NULL,
|
||||||
|
-1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
|
||||||
meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
|
meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||||
meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
|
meshnode->setMaterialFlag(video::EMF_ANTI_ALIASING, true);
|
||||||
meshnode->setMaterialFlag(video::EMF_TRILINEAR_FILTER, m_setting_trilinear_filter);
|
meshnode->setMaterialFlag(video::EMF_TRILINEAR_FILTER, m_setting_trilinear_filter);
|
||||||
@ -871,11 +1011,6 @@ video::ITexture* TextureSource::generateTextureFromMesh(
|
|||||||
smgr->drawAll();
|
smgr->drawAll();
|
||||||
driver->endScene();
|
driver->endScene();
|
||||||
|
|
||||||
// NOTE: The scene nodes should not be dropped, otherwise
|
|
||||||
// smgr->drop() segfaults
|
|
||||||
/*cube->drop();
|
|
||||||
camera->drop();
|
|
||||||
light->drop();*/
|
|
||||||
// Drop scene manager
|
// Drop scene manager
|
||||||
smgr->drop();
|
smgr->drop();
|
||||||
|
|
||||||
@ -938,6 +1073,57 @@ video::IImage* TextureSource::generateImageFromScratch(std::string name)
|
|||||||
return baseimg;
|
return baseimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
/**
|
||||||
|
* Check and align image to npot2 if required by hardware
|
||||||
|
* @param image image to check for npot2 alignment
|
||||||
|
* @param driver driver to use for image operations
|
||||||
|
* @return image or copy of image aligned to npot2
|
||||||
|
*/
|
||||||
|
video::IImage * Align2Npot2(video::IImage * image,
|
||||||
|
video::IVideoDriver* driver)
|
||||||
|
{
|
||||||
|
if(image == NULL) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
|
||||||
|
std::string extensions = (char*) glGetString(GL_EXTENSIONS);
|
||||||
|
if (extensions.find("GL_OES_texture_npot") != std::string::npos) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int height = npot2(dim.Height);
|
||||||
|
unsigned int width = npot2(dim.Width);
|
||||||
|
|
||||||
|
if ((dim.Height == height) &&
|
||||||
|
(dim.Width == width)) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dim.Height > height) {
|
||||||
|
height *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dim.Width > width) {
|
||||||
|
width *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::IImage *targetimage =
|
||||||
|
driver->createImage(video::ECF_A8R8G8B8,
|
||||||
|
core::dimension2d<u32>(width, height));
|
||||||
|
|
||||||
|
if (targetimage != NULL) {
|
||||||
|
image->copyToScaling(targetimage);
|
||||||
|
}
|
||||||
|
image->drop();
|
||||||
|
return targetimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
bool TextureSource::generateImage(std::string part_of_name, video::IImage *& baseimg)
|
bool TextureSource::generateImage(std::string part_of_name, video::IImage *& baseimg)
|
||||||
{
|
{
|
||||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||||
@ -947,21 +1133,9 @@ bool TextureSource::generateImage(std::string part_of_name, video::IImage *& bas
|
|||||||
if(part_of_name.size() == 0 || part_of_name[0] != '[')
|
if(part_of_name.size() == 0 || part_of_name[0] != '[')
|
||||||
{
|
{
|
||||||
video::IImage *image = m_sourcecache.getOrLoad(part_of_name, m_device);
|
video::IImage *image = m_sourcecache.getOrLoad(part_of_name, m_device);
|
||||||
|
#ifdef __ANDROID__
|
||||||
if (image != NULL) {
|
image = Align2Npot2(image,driver);
|
||||||
if (!driver->queryFeature(irr::video::EVDF_TEXTURE_NPOT)) {
|
#endif
|
||||||
core::dimension2d<u32> dim = image->getDimension();
|
|
||||||
|
|
||||||
|
|
||||||
if ((dim.Height %2 != 0) ||
|
|
||||||
(dim.Width %2 != 0)) {
|
|
||||||
infostream << "TextureSource::generateImage "
|
|
||||||
<< part_of_name << " size npot2 x=" << dim.Width
|
|
||||||
<< " y=" << dim.Height << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image == NULL) {
|
if (image == NULL) {
|
||||||
if (part_of_name != "") {
|
if (part_of_name != "") {
|
||||||
if (part_of_name.find("_normal.png") == std::string::npos){
|
if (part_of_name.find("_normal.png") == std::string::npos){
|
||||||
@ -1284,7 +1458,16 @@ bool TextureSource::generateImage(std::string part_of_name, video::IImage *& bas
|
|||||||
video::IImage *img_right =
|
video::IImage *img_right =
|
||||||
generateImageFromScratch(imagename_right);
|
generateImageFromScratch(imagename_right);
|
||||||
assert(img_top && img_left && img_right);
|
assert(img_top && img_left && img_right);
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
assert(img_top->getDimension().Height == npot2(img_top->getDimension().Height));
|
||||||
|
assert(img_top->getDimension().Width == npot2(img_top->getDimension().Width));
|
||||||
|
|
||||||
|
assert(img_left->getDimension().Height == npot2(img_left->getDimension().Height));
|
||||||
|
assert(img_left->getDimension().Width == npot2(img_left->getDimension().Width));
|
||||||
|
|
||||||
|
assert(img_right->getDimension().Height == npot2(img_right->getDimension().Height));
|
||||||
|
assert(img_right->getDimension().Width == npot2(img_right->getDimension().Width));
|
||||||
|
#endif
|
||||||
// Create textures from images
|
// Create textures from images
|
||||||
video::ITexture *texture_top = driver->addTexture(
|
video::ITexture *texture_top = driver->addTexture(
|
||||||
(imagename_top + "__temp__").c_str(), img_top);
|
(imagename_top + "__temp__").c_str(), img_top);
|
||||||
|
19
src/tile.h
@ -131,6 +131,25 @@ public:
|
|||||||
|
|
||||||
IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
|
IWritableTextureSource* createTextureSource(IrrlichtDevice *device);
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
/**
|
||||||
|
* @param size get next npot2 value
|
||||||
|
* @return npot2 value
|
||||||
|
*/
|
||||||
|
inline unsigned int npot2(unsigned int size)
|
||||||
|
{
|
||||||
|
if (size == 0) return 0;
|
||||||
|
unsigned int npot = 1;
|
||||||
|
|
||||||
|
while ((size >>= 1) > 0) {
|
||||||
|
npot <<= 1;
|
||||||
|
}
|
||||||
|
return npot;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::IImage * Align2Npot2(video::IImage * image, video::IVideoDriver* driver);
|
||||||
|
#endif
|
||||||
|
|
||||||
enum MaterialType{
|
enum MaterialType{
|
||||||
TILE_MATERIAL_BASIC,
|
TILE_MATERIAL_BASIC,
|
||||||
TILE_MATERIAL_ALPHA,
|
TILE_MATERIAL_ALPHA,
|
||||||
|
690
src/touchscreengui.cpp
Normal file
@ -0,0 +1,690 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2014 sapier
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "touchscreengui.h"
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
#include "irr_v2d.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "keycode.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "gettime.h"
|
||||||
|
#include "util/numeric.h"
|
||||||
|
#include "porting.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <ISceneCollisionManager.h>
|
||||||
|
|
||||||
|
using namespace irr::core;
|
||||||
|
|
||||||
|
extern Settings *g_settings;
|
||||||
|
|
||||||
|
const char** touchgui_button_imagenames = (const char*[]) {
|
||||||
|
"up_arrow.png",
|
||||||
|
"down_arrow.png",
|
||||||
|
"left_arrow.png",
|
||||||
|
"right_arrow.png",
|
||||||
|
"jump_btn.png",
|
||||||
|
"down.png",
|
||||||
|
"inventory_btn.png",
|
||||||
|
"chat_btn.png"
|
||||||
|
};
|
||||||
|
|
||||||
|
static irr::EKEY_CODE id2keycode(touch_gui_button_id id)
|
||||||
|
{
|
||||||
|
std::string key = "";
|
||||||
|
switch (id) {
|
||||||
|
case forward_id:
|
||||||
|
key = "forward";
|
||||||
|
break;
|
||||||
|
case left_id:
|
||||||
|
key = "left";
|
||||||
|
break;
|
||||||
|
case right_id:
|
||||||
|
key = "right";
|
||||||
|
break;
|
||||||
|
case backward_id:
|
||||||
|
key = "backward";
|
||||||
|
break;
|
||||||
|
case jump_id:
|
||||||
|
key = "jump";
|
||||||
|
break;
|
||||||
|
case inventory_id:
|
||||||
|
key = "inventory";
|
||||||
|
break;
|
||||||
|
case chat_id:
|
||||||
|
key = "chat";
|
||||||
|
break;
|
||||||
|
case crunch_id:
|
||||||
|
key = "sneak";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(key != "");
|
||||||
|
return keyname_to_keycode(g_settings->get("keymap_" + key).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchScreenGUI *g_touchscreengui;
|
||||||
|
|
||||||
|
TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, IEventReceiver* receiver):
|
||||||
|
m_device(device),
|
||||||
|
m_guienv(device->getGUIEnvironment()),
|
||||||
|
m_camera_yaw(0.0),
|
||||||
|
m_camera_pitch(0.0),
|
||||||
|
m_visible(false),
|
||||||
|
m_move_id(-1),
|
||||||
|
m_receiver(receiver)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i < after_last_element_id; i++) {
|
||||||
|
m_buttons[i].guibutton = 0;
|
||||||
|
m_buttons[i].repeatcounter = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_screensize = m_device->getVideoDriver()->getScreenSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::loadButtonTexture(button_info* btn, const char* path)
|
||||||
|
{
|
||||||
|
unsigned int tid;
|
||||||
|
video::ITexture *texture = m_texturesource->getTexture(path,&tid);
|
||||||
|
if (texture) {
|
||||||
|
btn->guibutton->setUseAlphaChannel(true);
|
||||||
|
btn->guibutton->setImage(texture);
|
||||||
|
btn->guibutton->setPressedImage(texture);
|
||||||
|
btn->guibutton->setScaleImage(true);
|
||||||
|
btn->guibutton->setDrawBorder(false);
|
||||||
|
btn->guibutton->setText(L"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::initButton(touch_gui_button_id id, rect<s32> button_rect,
|
||||||
|
std::wstring caption, bool immediate_release )
|
||||||
|
{
|
||||||
|
|
||||||
|
button_info* btn = &m_buttons[id];
|
||||||
|
btn->guibutton = m_guienv->addButton(button_rect, 0, id, caption.c_str());
|
||||||
|
btn->guibutton->grab();
|
||||||
|
btn->repeatcounter = -1;
|
||||||
|
btn->keycode = id2keycode(id);
|
||||||
|
btn->immediate_release = immediate_release;
|
||||||
|
btn->ids.clear();
|
||||||
|
|
||||||
|
loadButtonTexture(btn,touchgui_button_imagenames[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getMaxControlPadSize(float density) {
|
||||||
|
return 200 * density * g_settings->getFloat("gui_scaling");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::init(ISimpleTextureSource* tsrc, float density)
|
||||||
|
{
|
||||||
|
assert(tsrc != 0);
|
||||||
|
|
||||||
|
u32 control_pad_size =
|
||||||
|
MYMIN((2 * m_screensize.Y) / 3,getMaxControlPadSize(density));
|
||||||
|
|
||||||
|
u32 button_size = control_pad_size / 3;
|
||||||
|
m_visible = true;
|
||||||
|
m_texturesource = tsrc;
|
||||||
|
m_control_pad_rect = rect<s32>(0, m_screensize.Y - 3 * button_size,
|
||||||
|
3 * button_size, m_screensize.Y);
|
||||||
|
/*
|
||||||
|
draw control pad
|
||||||
|
0 1 2
|
||||||
|
3 4 5
|
||||||
|
for now only 0, 1, 2, and 4 are used
|
||||||
|
*/
|
||||||
|
int number = 0;
|
||||||
|
for (int y = 0; y < 2; ++y)
|
||||||
|
for (int x = 0; x < 3; ++x, ++number) {
|
||||||
|
rect<s32> button_rect(
|
||||||
|
x * button_size, m_screensize.Y - button_size * (2 - y),
|
||||||
|
(x + 1) * button_size, m_screensize.Y - button_size * (1 - y)
|
||||||
|
);
|
||||||
|
touch_gui_button_id id = after_last_element_id;
|
||||||
|
std::wstring caption;
|
||||||
|
switch (number) {
|
||||||
|
case 0:
|
||||||
|
id = left_id;
|
||||||
|
caption = L"<";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
id = forward_id;
|
||||||
|
caption = L"^";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
id = right_id;
|
||||||
|
caption = L">";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
id = backward_id;
|
||||||
|
caption = L"v";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (id != after_last_element_id) {
|
||||||
|
initButton(id, button_rect, caption, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init inventory button */
|
||||||
|
initButton(inventory_id,
|
||||||
|
rect<s32>(0, m_screensize.Y - (button_size/2),
|
||||||
|
(button_size/2), m_screensize.Y), L"inv", true);
|
||||||
|
|
||||||
|
/* init jump button */
|
||||||
|
initButton(jump_id,
|
||||||
|
rect<s32>(m_screensize.X-(1.75*button_size),
|
||||||
|
m_screensize.Y - (0.5*button_size),
|
||||||
|
m_screensize.X-(0.25*button_size),
|
||||||
|
m_screensize.Y),
|
||||||
|
L"x",false);
|
||||||
|
|
||||||
|
/* init crunch button */
|
||||||
|
initButton(crunch_id,
|
||||||
|
rect<s32>(m_screensize.X-(3.25*button_size),
|
||||||
|
m_screensize.Y - (0.5*button_size),
|
||||||
|
m_screensize.X-(1.75*button_size),
|
||||||
|
m_screensize.Y),
|
||||||
|
L"H",false);
|
||||||
|
|
||||||
|
/* init chat button */
|
||||||
|
initButton(chat_id,
|
||||||
|
rect<s32>(m_screensize.X-(1.5*button_size), 0,
|
||||||
|
m_screensize.X, button_size),
|
||||||
|
L"Chat", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
touch_gui_button_id TouchScreenGUI::getButtonID(s32 x, s32 y)
|
||||||
|
{
|
||||||
|
IGUIElement* rootguielement = m_guienv->getRootGUIElement();
|
||||||
|
|
||||||
|
if (rootguielement != NULL) {
|
||||||
|
gui::IGUIElement *element =
|
||||||
|
rootguielement->getElementFromPoint(core::position2d<s32>(x,y));
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
for (unsigned int i=0; i < after_last_element_id; i++) {
|
||||||
|
if (element == m_buttons[i].guibutton) {
|
||||||
|
return (touch_gui_button_id) i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return after_last_element_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
touch_gui_button_id TouchScreenGUI::getButtonID(int eventID)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i < after_last_element_id; i++) {
|
||||||
|
button_info* btn = &m_buttons[i];
|
||||||
|
|
||||||
|
std::vector<int>::iterator id =
|
||||||
|
std::find(btn->ids.begin(),btn->ids.end(), eventID);
|
||||||
|
|
||||||
|
if (id != btn->ids.end())
|
||||||
|
return (touch_gui_button_id) i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return after_last_element_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TouchScreenGUI::isHUDButton(const SEvent &event)
|
||||||
|
{
|
||||||
|
// check if hud item is pressed
|
||||||
|
for (std::map<int,rect<s32> >::iterator iter = m_hud_rects.begin();
|
||||||
|
iter != m_hud_rects.end(); iter++) {
|
||||||
|
if (iter->second.isPointInside(
|
||||||
|
v2s32(event.TouchInput.X,
|
||||||
|
event.TouchInput.Y)
|
||||||
|
)) {
|
||||||
|
if ( iter->first < 8) {
|
||||||
|
SEvent* translated = new SEvent();
|
||||||
|
memset(translated,0,sizeof(SEvent));
|
||||||
|
translated->EventType = irr::EET_KEY_INPUT_EVENT;
|
||||||
|
translated->KeyInput.Key = (irr::EKEY_CODE) (KEY_KEY_1 + iter->first);
|
||||||
|
translated->KeyInput.Control = false;
|
||||||
|
translated->KeyInput.Shift = false;
|
||||||
|
translated->KeyInput.PressedDown = true;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
m_hud_ids[event.TouchInput.ID] = translated->KeyInput.Key;
|
||||||
|
delete translated;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TouchScreenGUI::isReleaseHUDButton(int eventID)
|
||||||
|
{
|
||||||
|
std::map<int,irr::EKEY_CODE>::iterator iter = m_hud_ids.find(eventID);
|
||||||
|
|
||||||
|
if (iter != m_hud_ids.end()) {
|
||||||
|
SEvent* translated = new SEvent();
|
||||||
|
memset(translated,0,sizeof(SEvent));
|
||||||
|
translated->EventType = irr::EET_KEY_INPUT_EVENT;
|
||||||
|
translated->KeyInput.Key = iter->second;
|
||||||
|
translated->KeyInput.PressedDown = false;
|
||||||
|
translated->KeyInput.Control = false;
|
||||||
|
translated->KeyInput.Shift = false;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
m_hud_ids.erase(iter);
|
||||||
|
delete translated;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::ButtonEvent(touch_gui_button_id button,
|
||||||
|
int eventID, bool action)
|
||||||
|
{
|
||||||
|
button_info* btn = &m_buttons[button];
|
||||||
|
SEvent* translated = new SEvent();
|
||||||
|
memset(translated,0,sizeof(SEvent));
|
||||||
|
translated->EventType = irr::EET_KEY_INPUT_EVENT;
|
||||||
|
translated->KeyInput.Key = btn->keycode;
|
||||||
|
translated->KeyInput.Control = false;
|
||||||
|
translated->KeyInput.Shift = false;
|
||||||
|
translated->KeyInput.Char = 0;
|
||||||
|
|
||||||
|
/* add this event */
|
||||||
|
if (action) {
|
||||||
|
assert(std::find(btn->ids.begin(),btn->ids.end(), eventID) == btn->ids.end());
|
||||||
|
|
||||||
|
btn->ids.push_back(eventID);
|
||||||
|
|
||||||
|
if (btn->ids.size() > 1) return;
|
||||||
|
|
||||||
|
btn->repeatcounter = 0;
|
||||||
|
translated->KeyInput.PressedDown = true;
|
||||||
|
translated->KeyInput.Key = btn->keycode;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
}
|
||||||
|
/* remove event */
|
||||||
|
if ((!action) || (btn->immediate_release)) {
|
||||||
|
|
||||||
|
std::vector<int>::iterator pos =
|
||||||
|
std::find(btn->ids.begin(),btn->ids.end(), eventID);
|
||||||
|
/* has to be in touch list */
|
||||||
|
assert(pos != btn->ids.end());
|
||||||
|
btn->ids.erase(pos);
|
||||||
|
|
||||||
|
if (btn->ids.size() > 0) { return; }
|
||||||
|
|
||||||
|
translated->KeyInput.PressedDown = false;
|
||||||
|
btn->repeatcounter = -1;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
}
|
||||||
|
delete translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||||
|
{
|
||||||
|
if (!m_visible) {
|
||||||
|
infostream << "TouchScreenGUI::translateEvent got event but not visible?!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.EventType != EET_TOUCH_INPUT_EVENT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.TouchInput.Event == ETIE_PRESSED_DOWN) {
|
||||||
|
|
||||||
|
/* add to own copy of eventlist ...
|
||||||
|
* android would provide this information but irrlicht guys don't
|
||||||
|
* wanna design a efficient interface
|
||||||
|
*/
|
||||||
|
id_status toadd;
|
||||||
|
toadd.id = event.TouchInput.ID;
|
||||||
|
toadd.X = event.TouchInput.X;
|
||||||
|
toadd.Y = event.TouchInput.Y;
|
||||||
|
m_known_ids.push_back(toadd);
|
||||||
|
|
||||||
|
int eventID = event.TouchInput.ID;
|
||||||
|
|
||||||
|
touch_gui_button_id button =
|
||||||
|
getButtonID(event.TouchInput.X, event.TouchInput.Y);
|
||||||
|
|
||||||
|
/* handle button events */
|
||||||
|
if (button != after_last_element_id) {
|
||||||
|
ButtonEvent(button,eventID,true);
|
||||||
|
}
|
||||||
|
else if (isHUDButton(event))
|
||||||
|
{
|
||||||
|
/* already handled in isHUDButton() */
|
||||||
|
}
|
||||||
|
/* handle non button events */
|
||||||
|
else {
|
||||||
|
/* if we don't already have a moving point make this the moving one */
|
||||||
|
if (m_move_id == -1) {
|
||||||
|
m_move_id = event.TouchInput.ID;
|
||||||
|
m_move_has_really_moved = false;
|
||||||
|
m_move_downtime = getTimeMs();
|
||||||
|
m_move_downlocation = v2s32(event.TouchInput.X, event.TouchInput.Y);
|
||||||
|
m_move_sent_as_mouse_event = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pointerpos[event.TouchInput.ID] = v2s32(event.TouchInput.X, event.TouchInput.Y);
|
||||||
|
}
|
||||||
|
else if (event.TouchInput.Event == ETIE_LEFT_UP) {
|
||||||
|
verbosestream << "Up event for pointerid: " << event.TouchInput.ID << std::endl;
|
||||||
|
|
||||||
|
touch_gui_button_id button = getButtonID(event.TouchInput.ID);
|
||||||
|
|
||||||
|
/* handle button events */
|
||||||
|
if (button != after_last_element_id) {
|
||||||
|
ButtonEvent(button,event.TouchInput.ID,false);
|
||||||
|
}
|
||||||
|
/* handle hud button events */
|
||||||
|
else if (isReleaseHUDButton(event.TouchInput.ID)) {
|
||||||
|
/* nothing to do here */
|
||||||
|
}
|
||||||
|
/* handle the point used for moving view */
|
||||||
|
else if (event.TouchInput.ID == m_move_id) {
|
||||||
|
m_move_id = -1;
|
||||||
|
|
||||||
|
/* if this pointer issued a mouse event issue symmetric release here */
|
||||||
|
if (m_move_sent_as_mouse_event) {
|
||||||
|
SEvent* translated = new SEvent;
|
||||||
|
memset(translated,0,sizeof(SEvent));
|
||||||
|
translated->EventType = EET_MOUSE_INPUT_EVENT;
|
||||||
|
translated->MouseInput.X = m_move_downlocation.X;
|
||||||
|
translated->MouseInput.Y = m_move_downlocation.Y;
|
||||||
|
translated->MouseInput.Shift = false;
|
||||||
|
translated->MouseInput.Control = false;
|
||||||
|
translated->MouseInput.ButtonStates = 0;
|
||||||
|
translated->MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
delete translated;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* do double tap detection */
|
||||||
|
doubleTapDetection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
infostream
|
||||||
|
<< "TouchScreenGUI::translateEvent released unknown button: "
|
||||||
|
<< event.TouchInput.ID << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<id_status>::iterator iter = m_known_ids.begin();
|
||||||
|
iter != m_known_ids.end(); iter++) {
|
||||||
|
if (iter->id == event.TouchInput.ID) {
|
||||||
|
m_known_ids.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(event.TouchInput.Event == ETIE_MOVED);
|
||||||
|
int move_idx = event.TouchInput.ID;
|
||||||
|
|
||||||
|
if (m_pointerpos[event.TouchInput.ID] ==
|
||||||
|
v2s32(event.TouchInput.X, event.TouchInput.Y)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_move_id != -1) {
|
||||||
|
if ((event.TouchInput.ID == m_move_id) &&
|
||||||
|
(!m_move_sent_as_mouse_event)) {
|
||||||
|
|
||||||
|
double distance = sqrt(
|
||||||
|
(m_pointerpos[event.TouchInput.ID].X - event.TouchInput.X) *
|
||||||
|
(m_pointerpos[event.TouchInput.ID].X - event.TouchInput.X) +
|
||||||
|
(m_pointerpos[event.TouchInput.ID].Y - event.TouchInput.Y) *
|
||||||
|
(m_pointerpos[event.TouchInput.ID].Y - event.TouchInput.Y));
|
||||||
|
|
||||||
|
if ((distance > g_settings->getU16("touchscreen_threshold")) ||
|
||||||
|
(m_move_has_really_moved)) {
|
||||||
|
m_move_has_really_moved = true;
|
||||||
|
s32 X = event.TouchInput.X;
|
||||||
|
s32 Y = event.TouchInput.Y;
|
||||||
|
|
||||||
|
// update camera_yaw and camera_pitch
|
||||||
|
s32 dx = X - m_pointerpos[event.TouchInput.ID].X;
|
||||||
|
s32 dy = Y - m_pointerpos[event.TouchInput.ID].Y;
|
||||||
|
|
||||||
|
/* adapt to similar behaviour as pc screen */
|
||||||
|
double d = g_settings->getFloat("mouse_sensitivity") *4;
|
||||||
|
double old_yaw = m_camera_yaw;
|
||||||
|
double old_pitch = m_camera_pitch;
|
||||||
|
|
||||||
|
m_camera_yaw -= dx * d;
|
||||||
|
m_camera_pitch = MYMIN(MYMAX( m_camera_pitch + (dy * d),-180),180);
|
||||||
|
|
||||||
|
while (m_camera_yaw < 0)
|
||||||
|
m_camera_yaw += 360;
|
||||||
|
|
||||||
|
while (m_camera_yaw > 360)
|
||||||
|
m_camera_yaw -= 360;
|
||||||
|
|
||||||
|
// update shootline
|
||||||
|
m_shootline = m_device
|
||||||
|
->getSceneManager()
|
||||||
|
->getSceneCollisionManager()
|
||||||
|
->getRayFromScreenCoordinates(v2s32(X, Y));
|
||||||
|
m_pointerpos[event.TouchInput.ID] = v2s32(X, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((event.TouchInput.ID == m_move_id) &&
|
||||||
|
(m_move_sent_as_mouse_event)) {
|
||||||
|
m_shootline = m_device
|
||||||
|
->getSceneManager()
|
||||||
|
->getSceneCollisionManager()
|
||||||
|
->getRayFromScreenCoordinates(
|
||||||
|
v2s32(event.TouchInput.X,event.TouchInput.Y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleChangedButton(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::handleChangedButton(const SEvent &event)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < after_last_element_id; i++) {
|
||||||
|
|
||||||
|
if (m_buttons[i].ids.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(std::vector<int>::iterator iter = m_buttons[i].ids.begin();
|
||||||
|
iter != m_buttons[i].ids.end(); iter++) {
|
||||||
|
|
||||||
|
if (event.TouchInput.ID == *iter) {
|
||||||
|
|
||||||
|
int current_button_id =
|
||||||
|
getButtonID(event.TouchInput.X, event.TouchInput.Y);
|
||||||
|
|
||||||
|
if (current_button_id == i) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove old button */
|
||||||
|
ButtonEvent((touch_gui_button_id) i,*iter,false);
|
||||||
|
|
||||||
|
if (current_button_id == after_last_element_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ButtonEvent((touch_gui_button_id) current_button_id,*iter,true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int current_button_id = getButtonID(event.TouchInput.X, event.TouchInput.Y);
|
||||||
|
|
||||||
|
if (current_button_id == after_last_element_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
button_info* btn = &m_buttons[current_button_id];
|
||||||
|
if (std::find(btn->ids.begin(),btn->ids.end(), event.TouchInput.ID) == btn->ids.end()) {
|
||||||
|
ButtonEvent((touch_gui_button_id) current_button_id,event.TouchInput.ID,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TouchScreenGUI::doubleTapDetection()
|
||||||
|
{
|
||||||
|
m_key_events[0].down_time = m_key_events[1].down_time;
|
||||||
|
m_key_events[0].x = m_key_events[1].x;
|
||||||
|
m_key_events[0].y = m_key_events[1].y;
|
||||||
|
m_key_events[1].down_time = m_move_downtime;
|
||||||
|
m_key_events[1].x = m_move_downlocation.X;
|
||||||
|
m_key_events[1].y = m_move_downlocation.Y;
|
||||||
|
|
||||||
|
u32 delta = porting::getDeltaMs(m_key_events[0].down_time,getTimeMs());
|
||||||
|
if (delta > 400)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
double distance = sqrt(
|
||||||
|
(m_key_events[0].x - m_key_events[1].x) * (m_key_events[0].x - m_key_events[1].x) +
|
||||||
|
(m_key_events[0].y - m_key_events[1].y) * (m_key_events[0].y - m_key_events[1].y));
|
||||||
|
|
||||||
|
|
||||||
|
if (distance >(20 + g_settings->getU16("touchscreen_threshold")))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SEvent* translated = new SEvent();
|
||||||
|
memset(translated,0,sizeof(SEvent));
|
||||||
|
translated->EventType = EET_MOUSE_INPUT_EVENT;
|
||||||
|
translated->MouseInput.X = m_key_events[0].x;
|
||||||
|
translated->MouseInput.Y = m_key_events[0].y;
|
||||||
|
translated->MouseInput.Shift = false;
|
||||||
|
translated->MouseInput.Control = false;
|
||||||
|
translated->MouseInput.ButtonStates = EMBSM_RIGHT;
|
||||||
|
|
||||||
|
// update shootline
|
||||||
|
m_shootline = m_device
|
||||||
|
->getSceneManager()
|
||||||
|
->getSceneCollisionManager()
|
||||||
|
->getRayFromScreenCoordinates(v2s32(m_key_events[0].x, m_key_events[0].y));
|
||||||
|
|
||||||
|
translated->MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN;
|
||||||
|
verbosestream << "TouchScreenGUI::translateEvent right click press" << std::endl;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
|
||||||
|
translated->MouseInput.ButtonStates = 0;
|
||||||
|
translated->MouseInput.Event = EMIE_RMOUSE_LEFT_UP;
|
||||||
|
verbosestream << "TouchScreenGUI::translateEvent right click release" << std::endl;
|
||||||
|
m_receiver->OnEvent(*translated);
|
||||||
|
delete translated;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchScreenGUI::~TouchScreenGUI()
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i < after_last_element_id; i++) {
|
||||||
|
button_info* btn = &m_buttons[i];
|
||||||
|
if (btn->guibutton != 0) {
|
||||||
|
btn->guibutton->drop();
|
||||||
|
btn->guibutton = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::step(float dtime)
|
||||||
|
{
|
||||||
|
/* simulate keyboard repeats */
|
||||||
|
for (unsigned int i=0; i < after_last_element_id; i++) {
|
||||||
|
button_info* btn = &m_buttons[i];
|
||||||
|
|
||||||
|
if (btn->ids.size() > 0) {
|
||||||
|
btn->repeatcounter += dtime;
|
||||||
|
|
||||||
|
if (btn->repeatcounter < 0.2) continue;
|
||||||
|
|
||||||
|
btn->repeatcounter = 0;
|
||||||
|
SEvent translated;
|
||||||
|
memset(&translated,0,sizeof(SEvent));
|
||||||
|
translated.EventType = irr::EET_KEY_INPUT_EVENT;
|
||||||
|
translated.KeyInput.Key = btn->keycode;
|
||||||
|
translated.KeyInput.PressedDown = false;
|
||||||
|
m_receiver->OnEvent(translated);
|
||||||
|
|
||||||
|
translated.KeyInput.PressedDown = true;
|
||||||
|
m_receiver->OnEvent(translated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if a new placed pointer isn't moved for some time start digging */
|
||||||
|
if ((m_move_id != -1) &&
|
||||||
|
(!m_move_has_really_moved) &&
|
||||||
|
(!m_move_sent_as_mouse_event)) {
|
||||||
|
|
||||||
|
u32 delta = porting::getDeltaMs(m_move_downtime,getTimeMs());
|
||||||
|
|
||||||
|
if (delta > MIN_DIG_TIME_MS) {
|
||||||
|
m_shootline = m_device
|
||||||
|
->getSceneManager()
|
||||||
|
->getSceneCollisionManager()
|
||||||
|
->getRayFromScreenCoordinates(
|
||||||
|
v2s32(m_move_downlocation.X,m_move_downlocation.Y));
|
||||||
|
|
||||||
|
SEvent translated;
|
||||||
|
memset(&translated,0,sizeof(SEvent));
|
||||||
|
translated.EventType = EET_MOUSE_INPUT_EVENT;
|
||||||
|
translated.MouseInput.X = m_move_downlocation.X;
|
||||||
|
translated.MouseInput.Y = m_move_downlocation.Y;
|
||||||
|
translated.MouseInput.Shift = false;
|
||||||
|
translated.MouseInput.Control = false;
|
||||||
|
translated.MouseInput.ButtonStates = EMBSM_LEFT;
|
||||||
|
translated.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
|
||||||
|
verbosestream << "TouchScreenGUI::step left click press" << std::endl;
|
||||||
|
m_receiver->OnEvent(translated);
|
||||||
|
m_move_sent_as_mouse_event = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::resetHud()
|
||||||
|
{
|
||||||
|
m_hud_rects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::registerHudItem(int index, const rect<s32> &rect)
|
||||||
|
{
|
||||||
|
m_hud_rects[index] = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::Toggle(bool visible)
|
||||||
|
{
|
||||||
|
m_visible = visible;
|
||||||
|
for (unsigned int i=0; i < after_last_element_id; i++) {
|
||||||
|
button_info* btn = &m_buttons[i];
|
||||||
|
if (btn->guibutton != 0) {
|
||||||
|
btn->guibutton->setVisible(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::Hide()
|
||||||
|
{
|
||||||
|
Toggle(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchScreenGUI::Show()
|
||||||
|
{
|
||||||
|
Toggle(true);
|
||||||
|
}
|
160
src/touchscreengui.h
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2014 sapier
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TOUCHSCREENGUI_HEADER
|
||||||
|
#define TOUCHSCREENGUI_HEADER
|
||||||
|
|
||||||
|
#include <IGUIEnvironment.h>
|
||||||
|
#include <IGUIButton.h>
|
||||||
|
#include <IEventReceiver.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "tile.h"
|
||||||
|
|
||||||
|
using namespace irr;
|
||||||
|
using namespace irr::core;
|
||||||
|
using namespace irr::gui;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
forward_id = 0,
|
||||||
|
backward_id,
|
||||||
|
left_id,
|
||||||
|
right_id,
|
||||||
|
jump_id,
|
||||||
|
crunch_id,
|
||||||
|
inventory_id,
|
||||||
|
chat_id,
|
||||||
|
after_last_element_id
|
||||||
|
} touch_gui_button_id;
|
||||||
|
|
||||||
|
#define MIN_DIG_TIME_MS 500
|
||||||
|
#define MAX_TOUCH_COUNT 64
|
||||||
|
|
||||||
|
extern const char** touchgui_button_imagenames;
|
||||||
|
|
||||||
|
class TouchScreenGUI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TouchScreenGUI(IrrlichtDevice *device, IEventReceiver* receiver);
|
||||||
|
~TouchScreenGUI();
|
||||||
|
|
||||||
|
void translateEvent(const SEvent &event);
|
||||||
|
|
||||||
|
void init(ISimpleTextureSource* tsrc,float density);
|
||||||
|
|
||||||
|
double getYaw() { return m_camera_yaw; }
|
||||||
|
double getPitch() { return m_camera_pitch; }
|
||||||
|
line3d<f32> getShootline() { return m_shootline; }
|
||||||
|
|
||||||
|
void step(float dtime);
|
||||||
|
void resetHud();
|
||||||
|
void registerHudItem(int index, const rect<s32> &rect);
|
||||||
|
void Toggle(bool visible);
|
||||||
|
|
||||||
|
void Hide();
|
||||||
|
void Show();
|
||||||
|
|
||||||
|
private:
|
||||||
|
IrrlichtDevice* m_device;
|
||||||
|
IGUIEnvironment* m_guienv;
|
||||||
|
IEventReceiver* m_receiver;
|
||||||
|
ISimpleTextureSource* m_texturesource;
|
||||||
|
v2u32 m_screensize;
|
||||||
|
std::map<int,rect<s32> > m_hud_rects;
|
||||||
|
std::map<int,irr::EKEY_CODE> m_hud_ids;
|
||||||
|
bool m_visible; // is the gui visible
|
||||||
|
|
||||||
|
/* value in degree */
|
||||||
|
double m_camera_yaw;
|
||||||
|
double m_camera_pitch;
|
||||||
|
|
||||||
|
line3d<f32> m_shootline;
|
||||||
|
|
||||||
|
rect<s32> m_control_pad_rect;
|
||||||
|
|
||||||
|
int m_move_id;
|
||||||
|
bool m_move_has_really_moved;
|
||||||
|
s32 m_move_downtime;
|
||||||
|
bool m_move_sent_as_mouse_event;
|
||||||
|
v2s32 m_move_downlocation;
|
||||||
|
|
||||||
|
struct button_info {
|
||||||
|
float repeatcounter;
|
||||||
|
irr::EKEY_CODE keycode;
|
||||||
|
std::vector<int> ids;
|
||||||
|
IGUIButton* guibutton;
|
||||||
|
bool immediate_release;
|
||||||
|
};
|
||||||
|
|
||||||
|
button_info m_buttons[after_last_element_id];
|
||||||
|
|
||||||
|
/* gui button detection */
|
||||||
|
touch_gui_button_id getButtonID(s32 x, s32 y);
|
||||||
|
|
||||||
|
/* gui button by eventID */
|
||||||
|
touch_gui_button_id getButtonID(int eventID);
|
||||||
|
|
||||||
|
/* check if a button has changed */
|
||||||
|
void handleChangedButton(const SEvent &event);
|
||||||
|
|
||||||
|
/* initialize a button */
|
||||||
|
void initButton(touch_gui_button_id id, rect<s32> button_rect,
|
||||||
|
std::wstring caption, bool immediate_release );
|
||||||
|
|
||||||
|
/* load texture */
|
||||||
|
void loadButtonTexture(button_info* btn, const char* path);
|
||||||
|
|
||||||
|
struct id_status{
|
||||||
|
int id;
|
||||||
|
int X;
|
||||||
|
int Y;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* vector to store known ids and their initial touch positions*/
|
||||||
|
std::vector<id_status> m_known_ids;
|
||||||
|
|
||||||
|
/* handle a button event */
|
||||||
|
void ButtonEvent(touch_gui_button_id bID, int eventID, bool action);
|
||||||
|
|
||||||
|
/* handle pressed hud buttons */
|
||||||
|
bool isHUDButton(const SEvent &event);
|
||||||
|
|
||||||
|
/* handle released hud buttons */
|
||||||
|
bool isReleaseHUDButton(int eventID);
|
||||||
|
|
||||||
|
/* handle double taps */
|
||||||
|
bool doubleTapDetection();
|
||||||
|
|
||||||
|
/* doubleclick detection variables */
|
||||||
|
struct key_event {
|
||||||
|
unsigned int down_time;
|
||||||
|
s32 x;
|
||||||
|
s32 y;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* array for saving last known position of a pointer */
|
||||||
|
v2s32 m_pointerpos[MAX_TOUCH_COUNT];
|
||||||
|
|
||||||
|
/* array for doubletap detection */
|
||||||
|
key_event m_key_events[2];
|
||||||
|
};
|
||||||
|
extern TouchScreenGUI *g_touchscreengui;
|
||||||
|
#endif
|
@ -29,6 +29,58 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "../hex.h"
|
#include "../hex.h"
|
||||||
#include "../porting.h"
|
#include "../porting.h"
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
const wchar_t* wide_chars = L" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||||
|
|
||||||
|
int wctomb(char *s, wchar_t wc)
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < (sizeof(wide_chars)/sizeof(wchar_t));j++) {
|
||||||
|
if (wc == wide_chars[j]) {
|
||||||
|
*s = (char) (j+32);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (wc == L'\n') {
|
||||||
|
*s = '\n';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mbtowc(wchar_t *pwc, const char *s, size_t n)
|
||||||
|
{
|
||||||
|
std::wstring intermediate = narrow_to_wide(s);
|
||||||
|
|
||||||
|
if (intermediate.length() > 0) {
|
||||||
|
*pwc = intermediate[0];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring narrow_to_wide(const std::string& mbs) {
|
||||||
|
size_t wcl = mbs.size();
|
||||||
|
|
||||||
|
std::wstring retval = L"";
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < wcl; i++) {
|
||||||
|
if (((unsigned char) mbs[i] >31) &&
|
||||||
|
((unsigned char) mbs[i] < 127)) {
|
||||||
|
|
||||||
|
retval += wide_chars[(unsigned char) mbs[i] -32];
|
||||||
|
}
|
||||||
|
//handle newline
|
||||||
|
else if (mbs[i] == '\n') {
|
||||||
|
retval += L'\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
std::wstring narrow_to_wide(const std::string& mbs)
|
std::wstring narrow_to_wide(const std::string& mbs)
|
||||||
{
|
{
|
||||||
size_t wcl = mbs.size();
|
size_t wcl = mbs.size();
|
||||||
@ -40,6 +92,35 @@ std::wstring narrow_to_wide(const std::string& mbs)
|
|||||||
return *wcs;
|
return *wcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
std::string wide_to_narrow(const std::wstring& wcs) {
|
||||||
|
size_t mbl = wcs.size()*4;
|
||||||
|
|
||||||
|
std::string retval = "";
|
||||||
|
for (unsigned int i = 0; i < wcs.size(); i++) {
|
||||||
|
wchar_t char1 = (wchar_t) wcs[i];
|
||||||
|
|
||||||
|
if (char1 == L'\n') {
|
||||||
|
retval += '\n';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < wcslen(wide_chars);j++) {
|
||||||
|
wchar_t char2 = (wchar_t) wide_chars[j];
|
||||||
|
|
||||||
|
if (char1 == char2) {
|
||||||
|
char toadd = (j+32);
|
||||||
|
retval += toadd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#else
|
||||||
std::string wide_to_narrow(const std::wstring& wcs)
|
std::string wide_to_narrow(const std::wstring& wcs)
|
||||||
{
|
{
|
||||||
size_t mbl = wcs.size()*4;
|
size_t mbl = wcs.size()*4;
|
||||||
@ -53,6 +134,8 @@ std::string wide_to_narrow(const std::wstring& wcs)
|
|||||||
return *mbs;
|
return *mbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get an sha-1 hash of the player's name combined with
|
// Get an sha-1 hash of the player's name combined with
|
||||||
// the password entered. That's what the server uses as
|
// the password entered. That's what the server uses as
|
||||||
// their password. (Exception : if the password field is
|
// their password. (Exception : if the password field is
|
||||||
|
@ -20,19 +20,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef USE_CMAKE_CONFIG_H
|
|
||||||
|
|
||||||
#include "cmake_config_githash.h"
|
|
||||||
|
|
||||||
const char *minetest_version_simple = CMAKE_VERSION_STRING;
|
const char *minetest_version_simple = CMAKE_VERSION_STRING;
|
||||||
const char *minetest_version_hash = CMAKE_VERSION_GITHASH;
|
const char *minetest_version_hash = CMAKE_VERSION_GITHASH;
|
||||||
|
|
||||||
|
#ifdef USE_CMAKE_CONFIG_H
|
||||||
const char *minetest_build_info =
|
const char *minetest_build_info =
|
||||||
"VER=" CMAKE_VERSION_GITHASH " " CMAKE_BUILD_INFO;
|
"VER=" CMAKE_VERSION_GITHASH " " CMAKE_BUILD_INFO;
|
||||||
|
#elif defined(ANDROID)
|
||||||
|
const char *minetest_build_info = "android jni";
|
||||||
#else
|
#else
|
||||||
|
|
||||||
const char *minetest_version_simple = "unknown";
|
|
||||||
const char *minetest_version_hash = "unknown";
|
|
||||||
const char *minetest_build_info = "non-cmake";
|
const char *minetest_build_info = "non-cmake";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
BIN
textures/base/pack/chat_btn.png
Normal file
After Width: | Height: | Size: 777 B |
BIN
textures/base/pack/down.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
textures/base/pack/down_arrow.png
Normal file
After Width: | Height: | Size: 843 B |
BIN
textures/base/pack/inventory_btn.png
Normal file
After Width: | Height: | Size: 733 B |
BIN
textures/base/pack/jump_btn.png
Normal file
After Width: | Height: | Size: 621 B |
BIN
textures/base/pack/ladder_down.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
textures/base/pack/left_arrow.png
Normal file
After Width: | Height: | Size: 742 B |
BIN
textures/base/pack/right_arrow.png
Normal file
After Width: | Height: | Size: 770 B |
BIN
textures/base/pack/up_arrow.png
Normal file
After Width: | Height: | Size: 704 B |