310 changes: 310 additions & 0 deletions build/android/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions build/android/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -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 changes: 37 additions & 0 deletions build/android/libvorbis-libogg-fpu.patch
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions build/android/project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target=android-10
Binary file added build/android/res/drawable-hdpi/irr_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/android/res/drawable-ldpi/irr_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/android/res/drawable-mdpi/irr_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/android/res/drawable-xhdpi/irr_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions build/android/res/layout/assetcopy.xml
Original file line number Diff line number Diff line change
@@ -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 changes: 11 additions & 0 deletions build/android/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -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 changes: 288 additions & 0 deletions build/android/src/org/minetest/minetest/MinetestAssetCopy.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
91 changes: 91 additions & 0 deletions build/android/src/org/minetest/minetest/MinetestTextEntry.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
93 changes: 93 additions & 0 deletions build/android/src/org/minetest/minetest/MtNativeActivity.java
Original file line number Diff line number Diff line change
@@ -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;
}
10 changes: 5 additions & 5 deletions builtin/mainmenu/dlg_delete_world.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


local function create_world_formspec(dialogdata)
local function delete_world_formspec(dialogdata)

local retval =
"size[12,6,true]" ..
Expand All @@ -27,7 +27,7 @@ local function create_world_formspec(dialogdata)
return retval
end

local function create_world_buttonhandler(this, fields)
local function delete_world_buttonhandler(this, fields)
if fields["world_delete_confirm"] then

if this.data.delete_index > 0 and
Expand All @@ -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(index_to_del ~= nil and type(index_to_del) == "number")

local retval = dialog_create("sp_create_world",
create_world_formspec,
create_world_buttonhandler,
local retval = dialog_create("delete_world",
delete_world_formspec,
delete_world_buttonhandler,
nil)
retval.data.delete_name = name_to_del
retval.data.delete_index = index_to_del
Expand Down
102 changes: 102 additions & 0 deletions builtin/mainmenu/init_android.lua
Original file line number Diff line number Diff line change
@@ -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()

75 changes: 55 additions & 20 deletions builtin/mainmenu/tab_settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ end
local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)

if fields["dlg_reset_singleplayer_confirm"] ~= nil then

local worldlist = core.get_worlds()
local found_singleplayerworld = false

Expand Down Expand Up @@ -63,19 +62,43 @@ local function dlg_confirm_reset_btnhandler(this, fields, dialogdata)
this.parent:show()
this:hide()
this:delete()
return true
end

local function showconfirm_reset(tabview)
local new_dlg = dialog_create("reset_spworld",
dlg_confirm_reset_formspec,
dlg_confirm_reset_btnhandler,
nil,
tabview)
nil)
new_dlg:set_parent(tabview)
tabview:hide()
new_dlg:show()
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 tab_string =
Expand All @@ -93,8 +116,6 @@ local function formspec(tabview, name, tabdata)
.. dump(core.setting_getbool("preload_item_visuals")) .. "]"..
"checkbox[1,2.5;cb_particles;".. fgettext("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]" ..
"checkbox[4.5,0;cb_mipmapping;".. fgettext("Mip-Mapping") .. ";"
.. dump(core.setting_getbool("mip_map")) .. "]"..
Expand All @@ -106,16 +127,25 @@ local function formspec(tabview, name, tabdata)
.. dump(core.setting_getbool("trilinear_filter")) .. "]"..
"box[7.75,0;4,4;#999999]" ..
"checkbox[8,0;cb_shaders;".. fgettext("Shaders") .. ";"
.. dump(core.setting_getbool("enable_shaders")) .. "]"..
"button[1,4.5;2.25,0.5;btn_change_keys;".. fgettext("Change keys") .. "]"
.. dump(core.setting_getbool("enable_shaders")) .. "]"
if not ANDROID then
tab_string = tab_string ..
"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() .. "]"

local android = false
if android then
if ANDROID then
tab_string = tab_string ..
"box[4.25,2.75;3.25,2.5;#999999]" ..
"box[4.25,2.75;3.25,2.15;#999999]" ..
"checkbox[4.5,2.75;cb_touchscreen_target;".. fgettext("Touch free target") .. ";"
.. dump(core.setting_getbool("touchtarget")) .. "]" ..
"button[8,4.5;3.75,0.5;btn_reset_singleplayer;".. fgettext("Reset singleplayer world") .. "]"
.. dump(core.setting_getbool("touchtarget")) .. "]"
end

if core.setting_get("touchscreen_threshold") ~= nil then
Expand Down Expand Up @@ -202,10 +232,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
core.setting_set("enable_particles", fields["cb_particles"])
return true
end
if fields["cb_finite_liquid"] then
core.setting_set("liquid_finite", fields["cb_finite_liquid"])
return true
end
if fields["cb_bumpmapping"] then
core.setting_set("enable_bumpmapping", fields["cb_bumpmapping"])
end
Expand Down Expand Up @@ -235,14 +261,23 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
core.setting_set("touchtarget", fields["cb_touchscreen_target"])
return true
end
if fields["dd_touchthreshold"] then
core.setting_set("touchscreen_threshold",fields["dd_touchthreshold"])
return true
end
if fields["btn_reset_singleplayer"] then
print("sp reset")
showconfirm_reset(this)
return true
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

tab_settings = {
Expand Down
34 changes: 25 additions & 9 deletions builtin/mainmenu/tab_simple_main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ local function get_formspec(tabview, name, tabdata)
local render_details = dump(core.setting_getbool("public_serverlist"))

retval = retval ..
"label[0,3.0;".. fgettext("Address/Port") .. "]"..
"label[8,0.5;".. fgettext("Name/Password") .. "]" ..
"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") .."]" ..
Expand Down Expand Up @@ -66,27 +65,30 @@ local function get_formspec(tabview, name, tabdata)
dump(core.setting_getbool("free_move")) .. "]"
-- buttons
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
end

--------------------------------------------------------------------------------

local function main_button_handler(tabview, fields, name, tabdata)

if fields["btn_start_singleplayer"] then
gamedata.selected_world = gamedata.worldindex
gamedata.singleplayer = true
core.start()
return true
end

if fields["favourites"] ~= nil then
local event = core.explode_textlist_event(fields["favourites"])

if event.type == "CHG" then
if event.index <= #maintab_favorites then
local address = maintab_favorites[event.index].address
local port = maintab_favorites[event.index].port
if event.index <= #menudata.favorites then
local address = menudata.favorites[event.index].address
local port = menudata.favorites[event.index].port

if address ~= nil and
port ~= nil then
Expand All @@ -97,7 +99,7 @@ local function main_button_handler(tabview, fields, name, tabdata)
tabdata.fav_selected = event.index
end
end
return
return true
end

if fields["cb_public_serverlist"] ~= nil then
Expand All @@ -106,21 +108,24 @@ local function main_button_handler(tabview, fields, name, tabdata)
if core.setting_getbool("public_serverlist") then
asyncOnlineFavourites()
else
maintab_favorites = core.get_favorites("local")
menudata.favorites = core.get_favorites("local")
end
return
return true
end

if fields["cb_creative"] then
core.setting_set("creative_mode", fields["cb_creative"])
return true
end

if fields["cb_damage"] then
core.setting_set("enable_damage", fields["cb_damage"])
return true
end

if fields["cb_fly_mode"] then
core.setting_set("free_move", fields["cb_fly_mode"])
return true
end

if fields["btn_mp_connect"] ~= nil or
Expand Down Expand Up @@ -150,7 +155,18 @@ local function main_button_handler(tabview, fields, name, tabdata)
core.setting_set("remote_port",fields["te_port"])

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

Expand Down
130 changes: 130 additions & 0 deletions doc/README.android
Original file line number Diff line number Diff line change
@@ -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
1 change: 0 additions & 1 deletion src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h"
#include "util/serialize.h"
#include "config.h"
#include "cmake_config_githash.h"
#include "util/directiontables.h"
#include "util/pointedthing.h"
#include "version.h"
Expand Down
14 changes: 12 additions & 2 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

#define PROJECT_NAME "Minetest"
#define RUN_IN_PLACE 0
#define STATIC_SHAREDIR ""

#define USE_GETTEXT 0

#ifndef USE_SOUND
#define USE_SOUND 0
#endif
Expand All @@ -17,8 +20,9 @@
#define USE_CURL 0
#endif

#define USE_FREETYPE 0
#define STATIC_SHAREDIR ""
#ifndef USE_FREETYPE
#define USE_FREETYPE 0
#endif

#ifndef USE_LEVELDB
#define USE_LEVELDB 0
Expand Down Expand Up @@ -70,5 +74,11 @@
#define VERSION_EXTRA_STRING CMAKE_VERSION_EXTRA_STRING
#endif

#ifdef __ANDROID__
#include "android_version.h"
#else
#include "cmake_config_githash.h"
#endif

#endif

6 changes: 5 additions & 1 deletion src/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/


#include "porting.h"
#include "debug.h"
#include "exceptions.h"
#include "threads.h"
Expand All @@ -27,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <map>
#include "jthread/jmutex.h"
#include "jthread/jmutexautolock.h"

#include "config.h"
/*
Debug output
*/
Expand Down Expand Up @@ -95,6 +96,9 @@ class Debugbuf : public std::streambuf
}
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++)
{
if(g_debugstreams[i] == stderr && m_disable_stderr)
Expand Down
36 changes: 35 additions & 1 deletion src/defaultsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("doubletap_jump", "false");
settings->setDefault("always_fly_fast", "true");
settings->setDefault("directional_colored_fog", "true");
settings->setDefault("tooltip_show_delay", "400");
settings->setDefault("tooltip_show_delay", "400");

// Some (temporary) keys for debugging
settings->setDefault("keymap_print_debug_stacks", "KEY_KEY_P");
Expand Down Expand Up @@ -154,6 +154,7 @@ void set_default_settings(Settings *settings)
settings->setDefault("curl_timeout", "5000");
settings->setDefault("curl_parallel_limit", "8");
settings->setDefault("curl_file_download_timeout", "300000");
settings->setDefault("curl_verify_cert", "true");

settings->setDefault("enable_remote_media_server", "true");

Expand Down Expand Up @@ -278,6 +279,39 @@ void set_default_settings(Settings *settings)
settings->setDefault("high_precision_fpu", "true");

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)
Expand Down
7 changes: 7 additions & 0 deletions src/drawscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,13 @@ void draw_scene(video::IVideoDriver* driver, scene::ISceneManager* smgr,
bool draw_crosshair = ((player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
(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");

smgr->drawAll();
Expand Down
21 changes: 13 additions & 8 deletions src/filesys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <errno.h>
#include <fstream>
#include "log.h"
#include "config.h"

namespace fs
{
Expand All @@ -34,8 +35,8 @@ namespace fs
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <malloc.h>
#include <tchar.h>
#include <wchar.h>
#include <tchar.h>
#include <wchar.h>

#define BUFSIZE MAX_PATH

Expand Down Expand Up @@ -73,12 +74,12 @@ std::vector<DirListNode> GetDirListing(std::string pathstring)
// Find the first file in the directory.
hFind = FindFirstFile(DirSpec, &FindFileData);

if (hFind == INVALID_HANDLE_VALUE)
if (hFind == INVALID_HANDLE_VALUE)
{
retval = (-1);
goto Cleanup;
}
else
}
else
{
// NOTE:
// Be very sure to not include '..' in the results, it will
Expand All @@ -91,7 +92,7 @@ std::vector<DirListNode> GetDirListing(std::string pathstring)
listing.push_back(node);

// List all the other files in the directory.
while (FindNextFile(hFind, &FindFileData) != 0)
while (FindNextFile(hFind, &FindFileData) != 0)
{
DirListNode node;
node.name = FindFileData.cFileName;
Expand All @@ -102,7 +103,7 @@ std::vector<DirListNode> GetDirListing(std::string pathstring)

dwError = GetLastError();
FindClose(hFind);
if (dwError != ERROR_NO_MORE_FILES)
if (dwError != ERROR_NO_MORE_FILES)
{
errorstream<<"GetDirListing: FindNextFile error. Error is "
<<dwError<<std::endl;
Expand Down Expand Up @@ -401,7 +402,11 @@ std::string TempPath()
compatible with lua's os.tmpname which under the default
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
Expand Down
120 changes: 91 additions & 29 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "drawscene.h"
#include "content_cao.h"

#ifdef HAVE_TOUCHSCREENGUI
#include "touchscreengui.h"
#endif

/*
Text input system
*/
Expand Down Expand Up @@ -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,
InventoryManager *invmgr, IGameDef *gamedef,
IWritableTextureSource* tsrc, IrrlichtDevice * device,
Client* client, std::string text)
{
std::string formspec =
FORMSPEC_VERSION_STRING
"size[11,5.5,true]"
FORMSPEC_VERSION_STRING
SIZE_TAG
"field[3,2.35;6,0.5;f_text;;" + text + "]"
"button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]"
;
Expand All @@ -969,7 +979,7 @@ static void show_deathscreen(GUIFormSpecMenu** cur_formspec,
{
std::string formspec =
std::string(FORMSPEC_VERSION_STRING) +
"size[11,5.5,true]"
SIZE_TAG
"bgcolor[#320000b4;true]"
"label[4.85,1.35;You died.]"
"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
Expand All @@ -990,6 +1000,21 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
IWritableTextureSource* tsrc, IrrlichtDevice * device,
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"
"- WASD: move\n"
"- Space: jump/climb\n"
Expand All @@ -1002,11 +1027,11 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
"- Mouse wheel: select item\n"
"- T: chat\n"
));

#endif
float ypos = singleplayermode ? 1.0 : 0.5;
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;"
<< wide_to_narrow(wstrgettext("Continue")) << "]";

Expand All @@ -1021,7 +1046,7 @@ static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
<< wide_to_narrow(wstrgettext("Exit to Menu")) << "]";
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_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"
<< minetest_build_info << "\n"
<< "path_user = " << wrap_rows(porting::path_user, 20)
Expand Down Expand Up @@ -1253,18 +1278,18 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
server->step(dtime);

// End condition
if(client.getState() == LC_Init){
if(client.getState() == LC_Init) {
could_connect = true;
break;
}
// Break conditions
if(client.accessDenied()){
if(client.accessDenied()) {
error_message = L"Access denied. Reason: "
+client.accessDeniedReason();
errorstream<<wide_to_narrow(error_message)<<std::endl;
break;
}
if(input->wasKeyDown(EscapeKey)){
if(input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
connect_aborted = true;
infostream<<"Connect aborted [Escape]"<<std::endl;
break;
Expand Down Expand Up @@ -1310,8 +1335,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
/*
Handle failure to connect
*/
if(!could_connect){
if(error_message == L"" && !connect_aborted){
if(!could_connect) {
if(error_message == L"" && !connect_aborted) {
error_message = L"Connection failed";
errorstream<<wide_to_narrow(error_message)<<std::endl;
}
Expand All @@ -1330,8 +1355,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
float fps_max = g_settings->getFloat("fps_max");
bool cloud_menu_background = g_settings->getBool("menu_clouds");
u32 lasttime = device->getTimer()->getTime();
while(device->run())
{
while (device->run()) {
f32 dtime = 0.033; // in seconds
if (cloud_menu_background) {
u32 time = device->getTimer()->getTime();
Expand All @@ -1343,29 +1367,29 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
}
// Update client and server
client.step(dtime);
if(server != NULL)
if (server != NULL)
server->step(dtime);

// End condition
if(client.mediaReceived() &&
if (client.mediaReceived() &&
client.itemdefReceived() &&
client.nodedefReceived()){
client.nodedefReceived()) {
got_content = true;
break;
}
// Break conditions
if(client.accessDenied()){
if (client.accessDenied()) {
error_message = L"Access denied. Reason: "
+client.accessDeniedReason();
errorstream<<wide_to_narrow(error_message)<<std::endl;
break;
}
if(client.getState() < LC_Init){
if (client.getState() < LC_Init) {
error_message = L"Client disconnected";
errorstream<<wide_to_narrow(error_message)<<std::endl;
break;
}
if(input->wasKeyDown(EscapeKey)){
if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
content_aborted = true;
infostream<<"Connect aborted [Escape]"<<std::endl;
break;
Expand Down Expand Up @@ -1548,6 +1572,11 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
guitext_profiler->setVisible(false);
guitext_profiler->setWordWrap(true);

#ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui)
g_touchscreengui->init(tsrc,porting::getDisplayDensity());
#endif

/*
Some statistics are collected in these
*/
Expand Down Expand Up @@ -1641,7 +1670,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,

for(;;)
{
if(device->run() == false || kill == true)
if(device->run() == false || kill == true ||
g_gamecallback->shutdown_requested)
break;

v2u32 screensize = driver->getScreenSize();
Expand Down Expand Up @@ -1858,6 +1888,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input,

// Input handler step() (used by the random input generator)
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"
if(g_settings->getBool("doubletap_jump") && jump_timer <= 0.2)
Expand Down Expand Up @@ -1890,7 +1929,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
inventoryloc.setCurrentPlayer();
current_formspec->setFormSpec(fs_src->getForm(), inventoryloc);
}
else if(input->wasKeyDown(EscapeKey))
else if(input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey))
{
show_pause_menu(&current_formspec, &client, gamedef, tsrc, device,
simple_singleplayer_mode);
Expand Down Expand Up @@ -2214,21 +2253,29 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
float turn_amount = 0;
if((device->isWindowActive() && noMenuActive()) || random_input)
{
#ifndef __ANDROID__
if(!random_input)
{
// Mac OSX gets upset if this is set every frame
if(device->getCursorControl()->isVisible())
device->getCursorControl()->setVisible(false);
}
#endif

if(first_loop_after_window_activation){
//infostream<<"window active, first loop"<<std::endl;
first_loop_after_window_activation = false;
}
else{
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) {
} else {
#ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui) {
camera_yaw = g_touchscreengui->getYaw();
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;
}
//infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
Expand All @@ -2247,18 +2294,23 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
d = rangelim(d, 0.01, 100.0);
camera_yaw -= dx*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;

turn_amount = v2f(dx, dy).getLength() * d;
}
input->setMousePos((driver->getScreenSize().Width/2),
(driver->getScreenSize().Height/2));
}
else{
#ifndef ANDROID
// Mac OSX gets upset if this is set every frame
if(device->getCursorControl()->isVisible() == false)
device->getCursorControl()->setVisible(true);
#endif

//infostream<<"window inactive"<<std::endl;
first_loop_after_window_activation = true;
Expand Down Expand Up @@ -2668,10 +2720,19 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
core::line3d<f32> shootline(camera_position,
camera_position + camera_direction * BS * (d+1));


// prevent player pointing anything in front-view
if (camera.getCameraMode() == CAMERA_MODE_THIRD_FRONT)
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;

PointedThing pointed = getPointedThing(
Expand Down Expand Up @@ -3156,8 +3217,9 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
}
else if(show_hud || show_chat)
{
u16 fps = (1.0/dtime_avg1);
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->setVisible(true);
}
Expand Down
18 changes: 18 additions & 0 deletions src/guiEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "clouds.h"
#include "httpfetch.h"
#include "util/numeric.h"
#ifdef __ANDROID__
#include "tile.h"
#include <GLES/gl.h>
#endif

#include <IGUIStaticText.h>
#include <ICameraSceneNode.h>
Expand Down Expand Up @@ -83,6 +87,16 @@ video::ITexture* MenuTextureSource::getTexture(const std::string &name, u32 *id)
if(name.empty())
return NULL;
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());
}

Expand Down Expand Up @@ -266,6 +280,10 @@ void GUIEngine::run()
sleep_ms(25);

m_script->step();

#ifdef __ANDROID__
m_menu->getAndroidUIInput();
#endif
}
}

Expand Down
248 changes: 241 additions & 7 deletions src/guiFormSpecMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
m_ext_ptr(ext_ptr),
m_font(dev->getGUIEnvironment()->getSkin()->getFont()),
m_formspec_version(0)
#ifdef __ANDROID__
,m_JavaDialogFieldName(L"")
#endif
{
current_keys_pending.key_down = false;
current_keys_pending.key_up = false;
Expand Down Expand Up @@ -1878,6 +1881,52 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
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
{
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
Expand All @@ -1886,8 +1935,7 @@ GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
{
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 x = (i%s.geom.X) * spacing.X;
s32 y = (i/s.geom.X) * spacing.Y;
Expand Down Expand Up @@ -2051,8 +2099,6 @@ void GUIFormSpecMenu::drawMenu()
}
}

m_pointer = m_device->getCursorControl()->getPosition();

updateSelectedItem();

gui::IGUISkin* skin = Environment->getSkin();
Expand Down Expand Up @@ -2195,6 +2241,11 @@ void GUIFormSpecMenu::drawMenu()
*/
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
*/
Expand Down Expand Up @@ -2491,7 +2542,8 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
// Fix Esc/Return key being eaten by checkboxen and tables
if(event.EventType==EET_KEY_INPUT_EVENT) {
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) {
gui::IGUIElement *focused = Environment->getFocus();
if (focused && isMyChild(focused) &&
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -2584,8 +2786,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT) {
KeyPress kp(event.KeyInput);
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
kp == getKeySetting("keymap_inventory"))) {
if (event.KeyInput.PressedDown && ( (kp == EscapeKey) ||
(kp == getKeySetting("keymap_inventory")) || (kp == CancelKey))) {
if (m_allowclose) {
doPause = false;
acceptInput(quit_mode_cancel);
Expand Down Expand Up @@ -3015,6 +3217,38 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
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 quiet)
{
Expand Down
14 changes: 13 additions & 1 deletion src/guiFormSpecMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class GUIFormSpecMenu : public GUIModalMenu
{
}
FieldSpec(const std::wstring &name, const std::wstring &label,
const std::wstring &fdeflt, int id) :
const std::wstring &fdeflt, int id) :
fname(name),
flabel(label),
fdefault(fdeflt),
Expand Down Expand Up @@ -274,6 +274,10 @@ class GUIFormSpecMenu : public GUIModalMenu
static bool parseColor(const std::string &value,
video::SColor &color, bool quiet);

#ifdef __ANDROID__
bool getAndroidUIInput();
#endif

protected:
v2s32 getBasePos() const
{
Expand Down Expand Up @@ -409,6 +413,14 @@ class GUIFormSpecMenu : public GUIModalMenu
clickpos m_doubleclickdetect[2];

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
Expand Down
8 changes: 6 additions & 2 deletions src/httpfetch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ HTTPFetchRequest::HTTPFetchRequest()
request_id = 0;
timeout = g_settings->getS32("curl_timeout");
connect_timeout = timeout;

useragent = std::string("Minetest/") + minetest_version_hash + " (" + porting::get_sysinfo() + ")";
}

Expand Down Expand Up @@ -259,6 +259,10 @@ struct HTTPFetchOngoing
request.extra_headers[i].c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, httpheader);

if (!g_settings->getBool("curl_verify_cert")) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
}
}
}

Expand Down Expand Up @@ -302,7 +306,7 @@ struct HTTPFetchOngoing
}

if (res != CURLE_OK) {
infostream<<request.url<<" not found ("
errorstream<<request.url<<" not found ("
<<curl_easy_strerror(res)<<")"
<<" (response code "<<result.response_code<<")"
<<std::endl;
Expand Down
13 changes: 13 additions & 0 deletions src/hud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h"
#include <IGUIStaticText.h>

#ifdef HAVE_TOUCHSCREENGUI
#include "touchscreengui.h"
#endif

Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
gui::IGUIEnvironment* guienv, gui::IGUIFont *font,
Expand Down Expand Up @@ -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,
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 width = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);

Expand Down Expand Up @@ -222,6 +230,11 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
}

drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i +1) == selectitem );

#ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui)
g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
#endif
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/itemdef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <map>
#include <set>

#ifdef __ANDROID__
#include <GLES/gl.h>
#endif

/*
ItemDefinition
*/
Expand Down Expand Up @@ -433,6 +437,11 @@ class CItemDefManager: public IWritableItemDefManager
params.light_color.set(1.0, 0.5, 0.5, 0.5);
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 =
tsrc->generateTextureFromMesh(params);

Expand Down
8 changes: 8 additions & 0 deletions src/jthread/pthread/jsemaphore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ JSemaphore::JSemaphore() {

JSemaphore::~JSemaphore() {
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);
#endif
UNUSED(sem_destroy_retval);
}

Expand Down
4 changes: 4 additions & 0 deletions src/jthread/pthread/jthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ int JThread::Kill()
}
return ERR_JTHREAD_NOTRUNNING;
}
#ifdef __ANDROID__
pthread_kill(threadid, SIGKILL);
#else
pthread_cancel(threadid);
#endif
if (started) {
int pthread_join_retval = pthread_join(threadid,&status);
assert(pthread_join_retval == 0);
Expand Down
1 change: 1 addition & 0 deletions src/keycode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ const char *KeyPress::name() const
}

const KeyPress EscapeKey("KEY_ESCAPE");
const KeyPress CancelKey("KEY_CANCEL");
const KeyPress NumberKey[] = {
KeyPress("KEY_KEY_0"), KeyPress("KEY_KEY_1"), KeyPress("KEY_KEY_2"),
KeyPress("KEY_KEY_3"), KeyPress("KEY_KEY_4"), KeyPress("KEY_KEY_5"),
Expand Down
4 changes: 4 additions & 0 deletions src/keycode.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define KEYCODE_HEADER

#include "irrlichttypes.h"
#include "Keycodes.h"
#include <IEventReceiver.h>
#include <string>

Expand Down Expand Up @@ -57,6 +58,7 @@ class KeyPress
};

extern const KeyPress EscapeKey;
extern const KeyPress CancelKey;
extern const KeyPress NumberKey[10];

// Key configuration getter
Expand All @@ -65,5 +67,7 @@ KeyPress getKeySetting(const char *settingname);
// Clear fast lookup cache
void clearKeyCache();

irr::EKEY_CODE keyname_to_keycode(const char *name);

#endif

5 changes: 5 additions & 0 deletions src/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "threads.h"
#include "debug.h"
#include "gettime.h"
#include "porting.h"
#include "config.h"

std::list<ILogOutput*> log_outputs[LMT_NUM_VALUES];
std::map<threadid_t, std::string> log_threadnames;
Expand Down Expand Up @@ -139,6 +141,9 @@ class Logbuf : public std::streambuf
void printbuf()
{
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)
Expand Down
6 changes: 6 additions & 0 deletions src/lua/src/llex.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,15 @@ static void buffreplace (LexState *ls, char from, char to) {

static void trydecpoint (LexState *ls, SemInfo *seminfo) {
/* format error: try to update decimal point separator */
#ifndef __ANDROID__
struct lconv *cv = localeconv();
#endif
char old = ls->decpoint;
#ifndef __ANDROID__
ls->decpoint = (cv ? cv->decimal_point[0] : '.');
#else
ls->decpoint = '.';
#endif
buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
/* format error with correct decimal point: no more options */
Expand Down
107 changes: 86 additions & 21 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifdef USE_LEVELDB
#include "database-leveldb.h"
#endif

#if USE_REDIS
#include "database-redis.h"
#endif

#ifdef HAVE_TOUCHSCREENGUI
#include "touchscreengui.h"
#endif
/*
Settings.
These are loaded from the config file.
Expand Down Expand Up @@ -253,6 +257,11 @@ class MyEventReceiver : public IEventReceiver
React to nothing here if a menu is active
*/
if (noMenuActive() == false) {
#ifdef HAVE_TOUCHSCREENGUI
if (m_touchscreengui != 0) {
m_touchscreengui->Toggle(false);
}
#endif
return g_menumgr.preprocessEvent(event);
}

Expand All @@ -266,7 +275,16 @@ class MyEventReceiver : public IEventReceiver
}
}

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) {
left_active = false;
middle_active = false;
Expand All @@ -293,8 +311,8 @@ class MyEventReceiver : public IEventReceiver
}
}
}
if (event.EventType == irr::EET_LOG_TEXT_EVENT) {
dstream << "Irrlicht log: " << event.LogEvent.Text << std::endl;
if(event.EventType == irr::EET_LOG_TEXT_EVENT) {
dstream<< std::string("Irrlicht log: ") + std::string(event.LogEvent.Text)<<std::endl;
return true;
}
/* always return false in order to continue processing events */
Expand Down Expand Up @@ -342,6 +360,9 @@ class MyEventReceiver : public IEventReceiver
MyEventReceiver()
{
clearInput();
#ifdef HAVE_TOUCHSCREENGUI
m_touchscreengui = NULL;
#endif
}

bool leftclicked;
Expand All @@ -355,7 +376,12 @@ class MyEventReceiver : public IEventReceiver

s32 mouse_wheel;

#ifdef HAVE_TOUCHSCREENGUI
TouchScreenGUI* m_touchscreengui;
#endif

private:
IrrlichtDevice *m_device;

// The current state of keys
KeyList keyIsDown;
Expand All @@ -372,7 +398,8 @@ class RealInputHandler : public InputHandler
public:
RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver):
m_device(device),
m_receiver(receiver)
m_receiver(receiver),
m_mousepos(0,0)
{
}
virtual bool isKeyDown(const KeyPress &keyCode)
Expand All @@ -385,11 +412,21 @@ class RealInputHandler : public InputHandler
}
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)
{
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()
Expand Down Expand Up @@ -445,8 +482,9 @@ class RealInputHandler : public InputHandler
m_receiver->clearInput();
}
private:
IrrlichtDevice *m_device;
IrrlichtDevice *m_device;
MyEventReceiver *m_receiver;
v2s32 m_mousepos;
};

class RandomInputHandler : public InputHandler
Expand Down Expand Up @@ -855,8 +893,18 @@ int main(int argc, char *argv[])

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
fs::CreateDir(porting::path_user);
#endif

infostream << "path_share = " << porting::path_share << std::endl;
infostream << "path_user = " << porting::path_user << std::endl;
Expand Down Expand Up @@ -975,14 +1023,15 @@ int main(int argc, char *argv[])
// Initialize HTTP fetcher
httpfetch_init(g_settings->getS32("curl_parallel_limit"));

#ifndef __ANDROID__
/*
Run unit tests
*/

if ((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false)
|| cmd_args.getFlag("enable-unittests") == true) {
run_tests();
}
#endif
#ifdef _MSC_VER
init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),
g_settings->get("language"), argc, argv);
Expand Down Expand Up @@ -1348,7 +1397,7 @@ int main(int argc, char *argv[])
List video modes if requested
*/

MyEventReceiver receiver;
MyEventReceiver* receiver = new MyEventReceiver();

if (cmd_args.getFlag("videomodes")) {
IrrlichtDevice *nulldevice;
Expand All @@ -1361,7 +1410,7 @@ int main(int argc, char *argv[])
params.Fullscreen = false;
params.Stencilbuffer = false;
params.Vsync = vsync;
params.EventReceiver = &receiver;
params.EventReceiver = receiver;
params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu");

nulldevice = createDeviceEx(params);
Expand Down Expand Up @@ -1397,15 +1446,13 @@ int main(int argc, char *argv[])

nulldevice->drop();

delete receiver;
return 0;
}

/*
Create device and exit if creation failed
*/

IrrlichtDevice *device;

SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
params.DriverType = driverType;
params.WindowSize = core::dimension2d<u32>(screenW, screenH);
Expand All @@ -1414,12 +1461,18 @@ int main(int argc, char *argv[])
params.Fullscreen = fullscreen;
params.Stencilbuffer = false;
params.Vsync = vsync;
params.EventReceiver = &receiver;
params.EventReceiver = receiver;
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) {
delete receiver;
return 1; // could not create selected driver.
}

Expand Down Expand Up @@ -1476,10 +1529,11 @@ int main(int argc, char *argv[])
bool random_input = g_settings->getBool("random_input")
|| cmd_args.getFlag("random-input");
InputHandler *input = NULL;

if (random_input) {
input = new RandomInputHandler();
} else {
input = new RealInputHandler(device, &receiver);
input = new RealInputHandler(device,receiver);
}

scene::ISceneManager* smgr = device->getSceneManager();
Expand Down Expand Up @@ -1564,7 +1618,8 @@ int main(int argc, char *argv[])
/*
Menu-game loop
*/
while (device->run() && kill == false)
while (device->run() && (kill == false) &&
(g_gamecallback->shutdown_requested == false))
{
// Set the window caption
wchar_t* text = wgettext("Main Menu");
Expand Down Expand Up @@ -1612,7 +1667,9 @@ int main(int argc, char *argv[])
first_loop = false;

// Cursor can be non-visible when coming from the game
#ifndef ANDROID
device->getCursorControl()->setVisible(true);
#endif
// Some stuff are left to scene manager when coming from the game
// (map at least?)
smgr->clear();
Expand Down Expand Up @@ -1661,10 +1718,9 @@ int main(int argc, char *argv[])
}
infostream << "Waited for other menus" << std::endl;

GUIEngine* temp = new GUIEngine(device, guiroot,
&g_menumgr, smgr, &menudata, kill);
/* show main menu */
GUIEngine mymenu(device, guiroot, &g_menumgr,smgr,&menudata,kill);

delete temp;
//once finished you'll never end up here
smgr->clear();
}
Expand Down Expand Up @@ -1788,6 +1844,10 @@ int main(int argc, char *argv[])
/*
Run game
*/
#ifdef HAVE_TOUCHSCREENGUI
receiver->m_touchscreengui = new TouchScreenGUI(device, receiver);
g_touchscreengui = receiver->m_touchscreengui;
#endif
the_game(
kill,
random_input,
Expand All @@ -1805,6 +1865,11 @@ int main(int argc, char *argv[])
simple_singleplayer_mode
);
smgr->clear();
#ifdef HAVE_TOUCHSCREENGUI
delete g_touchscreengui;
g_touchscreengui = NULL;
receiver->m_touchscreengui = NULL;
#endif

} //try
catch(con::PeerNotFoundException &e)
Expand Down Expand Up @@ -1849,7 +1914,7 @@ int main(int argc, char *argv[])
if (use_freetype)
font->drop();
#endif

delete receiver;
#endif // !SERVER

// Update configuration file
Expand Down
5 changes: 5 additions & 0 deletions src/mainmenumanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,17 @@ class MainGameCallback : public IGameCallback
disconnect_requested(false),
changepassword_requested(false),
changevolume_requested(false),
shutdown_requested(false),
device(a_device)
{
}

virtual void exitToOS()
{
shutdown_requested = true;
#ifndef __ANDROID__
device->closeDevice();
#endif
}

virtual void disconnect()
Expand All @@ -151,6 +155,7 @@ class MainGameCallback : public IGameCallback
bool disconnect_requested;
bool changepassword_requested;
bool changevolume_requested;
bool shutdown_requested;
IrrlichtDevice *device;
};

Expand Down
7 changes: 7 additions & 0 deletions src/modalMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MODALMENU_HEADER

#include "irrlichttypes_extrabloated.h"
#ifdef HAVE_TOUCHSCREENGUI
#include "touchscreengui.h"
#endif

class GUIModalMenu;

Expand Down Expand Up @@ -101,6 +104,10 @@ class GUIModalMenu : public gui::IGUIElement
Environment->removeFocus(this);
m_menumgr->deletingMenu(this);
this->remove();
#ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui)
g_touchscreengui->Show();
#endif
}

void removeChildren()
Expand Down
39 changes: 27 additions & 12 deletions src/porting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ int getNumberOfProcessors() {
}


#ifndef __ANDROID__
bool threadBindToProcessor(threadid_t tid, int pnumber) {
#if defined(_WIN32)

Expand Down Expand Up @@ -194,7 +195,7 @@ bool threadBindToProcessor(threadid_t tid, int pnumber) {
pnumber, NULL) == 0;

#elif defined(_AIX)

return bindprocessor(BINDTHREAD, (tid_t)tid, pnumber) == 0;

#elif defined(__hpux) || defined(hpux)
Expand All @@ -203,11 +204,11 @@ bool threadBindToProcessor(threadid_t tid, int pnumber) {

return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP,
&answer, pnumber, tid) == 0;

#elif defined(__APPLE__)

struct thread_affinity_policy tapol;

thread_port_t threadport = pthread_mach_thread_np(tid);
tapol.affinity_tag = pnumber + 1;
return thread_policy_set(threadport, THREAD_AFFINITY_POLICY,
Expand All @@ -219,7 +220,7 @@ bool threadBindToProcessor(threadid_t tid, int pnumber) {

#endif
}

#endif

bool threadSetPriority(threadid_t tid, int prio) {
#if defined(_WIN32)
Expand All @@ -232,21 +233,21 @@ bool threadSetPriority(threadid_t tid, int prio) {

CloseHandle(hThread);
return success;

#else

struct sched_param sparam;
int policy;

if (pthread_getschedparam(tid, &policy, &sparam) != 0)
return false;

int min = sched_get_priority_min(policy);
int max = sched_get_priority_max(policy);

sparam.sched_priority = min + prio * (max - min) / THREAD_PRIORITY_HIGHEST;
return pthread_setschedparam(tid, policy, &sparam) == 0;

#endif
}

Expand Down Expand Up @@ -458,9 +459,15 @@ void initializePaths()
{
char buf[BUFSIZ];
memset(buf, 0, BUFSIZ);
assert(readlink("/proc/self/exe", buf, BUFSIZ-1) != -1);
pathRemoveFile(buf, '/');
bindir = buf;
if (readlink("/proc/self/exe", buf, BUFSIZ-1) == -1) {
errorstream << "Unable to read bindir "<< std::endl;
#ifndef __ANDROID__
assert("Unable to read bindir" == 0);
#endif
} else {
pathRemoveFile(buf, '/');
bindir = buf;
}
}

// Find share directory from these.
Expand All @@ -472,6 +479,9 @@ void initializePaths()
trylist.push_back(
bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME);
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();
i != trylist.end(); i++)
Expand All @@ -490,8 +500,11 @@ void initializePaths()
path_share = trypath;
break;
}

#ifndef __ANDROID__
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
Expand Down Expand Up @@ -539,6 +552,7 @@ v2u32 getWindowSize() {
return device->getVideoDriver()->getScreenSize();
}

#ifndef __ANDROID__

float getDisplayDensity() {
float gui_scaling = g_settings->getFloat("gui_scaling");
Expand All @@ -562,6 +576,7 @@ v2u32 getDisplaySize() {
return deskres;
}
#endif
#endif

} //namespace porting

Loading