Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ internal/

#os
.DS_Store


CMakeCache.txt
cmake_install.cmake
CMakeFiles/
Makefile
42 changes: 42 additions & 0 deletions AndroidManifest.xml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />

<uses-feature android:glEsVersion="0x00030001" android:required="true" />
<uses-feature android:name="android.hardware.vulkan.level" android:required="false" />
<uses-feature android:name="android.hardware.vulkan.version" android:required="true" android:version="0x00401000" />

<application
android:allowBackup="false"
android:label="@ANDROID_PROJECT_NAME@"
android:hasFragileUserData="true"
android:requestLegacyExternalStorage="true"
tools:targetApi="31">

<activity
android:name="android.app.NativeActivity"
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:screenOrientation="sensorLandscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">

<meta-data
android:name="android.app.lib_name"
android:value="@ANDROID_LIB_NAME@" />

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
29 changes: 28 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
cmake_minimum_required(VERSION 3.16)

project(Gothic2Notr LANGUAGES C CXX)

# Option to generate Android build directory (run with: cmake -DGENERATE_ANDROID_BUILD=ON -P CMakeLists.txt)
option(GENERATE_ANDROID_BUILD "Generate Android/Gradle build directory from templates" OFF)
if(GENERATE_ANDROID_BUILD)
include(${CMAKE_SOURCE_DIR}/cmake/android/GenerateAndroidBuild.cmake)
generate_android_build(
SOURCE_DIR "${CMAKE_SOURCE_DIR}"
OUTPUT_DIR "${CMAKE_SOURCE_DIR}/build/android-build"
)
return()
endif()
set(CMAKE_CXX_STANDARD 20)
set(BUILD_SHARED_LIBS OFF)

Expand All @@ -11,7 +22,11 @@ set(CMAKE_RELWITHDEBINFO_POSTFIX "")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_SKIP_RPATH ON)

add_executable(${PROJECT_NAME})
if(ANDROID)
add_library(${PROJECT_NAME} SHARED)
else()
add_executable(${PROJECT_NAME})
endif()

if(MSVC)
add_definitions(-D_USE_MATH_DEFINES)
Expand Down Expand Up @@ -59,6 +74,12 @@ elseif(IOS)
MACOSX_BUNDLE_BUNDLE_VERSION 1
MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer")
elseif(ANDROID)
# Android build configuration
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
# Build as shared library for Android
set_target_properties(${PROJECT_NAME} PROPERTIES
LIBRARY_OUTPUT_NAME "opengothic")
elseif(APPLE)
enable_language(OBJCXX)
endif()
Expand Down Expand Up @@ -96,6 +117,12 @@ endif()

if(WIN32)
target_link_libraries(${PROJECT_NAME} shlwapi DbgHelp)
elseif(ANDROID)
# Add android_native_app_glue
set(ANDROID_NATIVE_APP_GLUE_DIR "${ANDROID_NDK}/sources/android/native_app_glue")
target_sources(${PROJECT_NAME} PRIVATE "${ANDROID_NATIVE_APP_GLUE_DIR}/android_native_app_glue.c")
target_include_directories(${PROJECT_NAME} PRIVATE "${ANDROID_NATIVE_APP_GLUE_DIR}")
target_link_libraries(${PROJECT_NAME} android log)
elseif(UNIX)
target_link_libraries(${PROJECT_NAME} -lpthread -ldl)
endif()
Expand Down
114 changes: 114 additions & 0 deletions cmake/android/GenerateAndroidBuild.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# GenerateAndroidBuild.cmake
# Generates a complete Android/Gradle build directory from templates
#
# Usage from CMakeLists.txt:
# cmake -DGENERATE_ANDROID_BUILD=ON .

# Default configuration values
set(ANDROID_PROJECT_NAME "OpenGothic" CACHE STRING "Android project name")
set(ANDROID_NAMESPACE "com.example.opengothic" CACHE STRING "Android namespace")
set(ANDROID_APPLICATION_ID "com.example.opengothic" CACHE STRING "Android application ID")
set(ANDROID_LIB_NAME "opengothic" CACHE STRING "Native library name")
set(ANDROID_COMPILE_SDK "35" CACHE STRING "Android compile SDK version")
set(ANDROID_MIN_SDK "24" CACHE STRING "Android minimum SDK version")
set(ANDROID_TARGET_SDK "35" CACHE STRING "Android target SDK version")
set(ANDROID_VERSION_CODE "1" CACHE STRING "Android version code")
set(ANDROID_VERSION_NAME "1.0" CACHE STRING "Android version name")
set(ANDROID_GRADLE_PLUGIN_VERSION "8.7.3" CACHE STRING "Android Gradle Plugin version")
set(ANDROID_CMAKE_VERSION "3.22.1" CACHE STRING "CMake version for Android build")
set(ANDROID_ABI_LIST "\"arm64-v8a\", \"x86_64\"" CACHE STRING "Android ABI list")

function(generate_android_build)
cmake_parse_arguments(ARG "" "OUTPUT_DIR;SOURCE_DIR" "" ${ARGN})

if(NOT ARG_SOURCE_DIR)
set(ARG_SOURCE_DIR "${CMAKE_SOURCE_DIR}")
endif()
if(NOT ARG_OUTPUT_DIR)
set(ARG_OUTPUT_DIR "${CMAKE_BINARY_DIR}/android-build")
endif()

set(OPENGOTHIC_SOURCE_DIR "${ARG_SOURCE_DIR}")
set(ANDROID_BUILD_DIR "${ARG_OUTPUT_DIR}")

message(STATUS "Generating Android build directory: ${ANDROID_BUILD_DIR}")

# Create directory structure
file(MAKE_DIRECTORY "${ANDROID_BUILD_DIR}/app/src/main")
file(MAKE_DIRECTORY "${ANDROID_BUILD_DIR}/gradle/wrapper")

# settings.gradle
file(WRITE "${ANDROID_BUILD_DIR}/settings.gradle"
"pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = \"${ANDROID_PROJECT_NAME}\"
include ':app'
")

# build.gradle (root)
file(WRITE "${ANDROID_BUILD_DIR}/build.gradle"
"plugins {
id 'com.android.application' version '${ANDROID_GRADLE_PLUGIN_VERSION}' apply false
}
")

# gradle.properties
file(WRITE "${ANDROID_BUILD_DIR}/gradle.properties"
"org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
android.nonTransitiveRClass=true
")

# gradle-wrapper.properties
file(WRITE "${ANDROID_BUILD_DIR}/gradle/wrapper/gradle-wrapper.properties"
"distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
")

# app/build.gradle (from template - more complex)
configure_file(
"${OPENGOTHIC_SOURCE_DIR}/cmake/android/app.build.gradle.in"
"${ANDROID_BUILD_DIR}/app/build.gradle"
@ONLY
)

# AndroidManifest.xml (from template)
configure_file(
"${OPENGOTHIC_SOURCE_DIR}/AndroidManifest.xml.in"
"${ANDROID_BUILD_DIR}/app/src/main/AndroidManifest.xml"
@ONLY
)

# local.properties (SDK path)
if(DEFINED ENV{ANDROID_HOME})
set(SDK_DIR "$ENV{ANDROID_HOME}")
elseif(DEFINED ENV{ANDROID_SDK_ROOT})
set(SDK_DIR "$ENV{ANDROID_SDK_ROOT}")
else()
set(SDK_DIR "")
endif()

if(SDK_DIR)
string(REPLACE "\\" "/" SDK_DIR "${SDK_DIR}")
file(WRITE "${ANDROID_BUILD_DIR}/local.properties" "sdk.dir=${SDK_DIR}\n")
else()
file(WRITE "${ANDROID_BUILD_DIR}/local.properties" "# sdk.dir=/path/to/Android/Sdk\n")
endif()

message(STATUS "Done. Build: cd ${ANDROID_BUILD_DIR} && ./gradlew assembleRelease")
endfunction()
66 changes: 66 additions & 0 deletions cmake/android/app.build.gradle.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// App build file - generated by CMake
plugins {
id 'com.android.application'
}

android {
namespace '@ANDROID_NAMESPACE@'
compileSdk @ANDROID_COMPILE_SDK@

defaultConfig {
applicationId "@ANDROID_APPLICATION_ID@"
minSdk @ANDROID_MIN_SDK@
targetSdk @ANDROID_TARGET_SDK@
versionCode @ANDROID_VERSION_CODE@
versionName "@ANDROID_VERSION_NAME@"

ndk {
abiFilters 'arm64-v8a', 'x86_64'
}

externalNativeBuild {
cmake {
cppFlags '-std=c++20 -fvisibility=hidden -ffunction-sections -fdata-sections'
arguments '-DANDROID_STL=c++_static',
'-DBUILD_SHARED_LIBS=ON',
'-DCMAKE_BUILD_TYPE=Release',
'-DCMAKE_SHARED_LINKER_FLAGS=-Wl,-z,max-page-size=16384'
}
}
}

buildTypes {
release {
minifyEnabled false
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

externalNativeBuild {
cmake {
// Point directly to the project root CMakeLists.txt
path file('@OPENGOTHIC_SOURCE_DIR@/CMakeLists.txt')
version '@ANDROID_CMAKE_VERSION@'
}
}

buildFeatures {
prefab true
}

sourceSets {
main {
manifest.srcFile '@ANDROID_BUILD_DIR@/app/src/main/AndroidManifest.xml'
}
}
}

dependencies {
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.games:games-activity:3.0.5'
}
18 changes: 14 additions & 4 deletions game/commandline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,23 @@ std::u16string CommandLine::nestedPath(const std::initializer_list<const char16_
}

bool CommandLine::validateGothicPath() const {
if(gpath.empty())
if(gpath.empty()) {
Log::e("Gothic path is empty");
return false;
if(!FileUtil::exists(gscript))
}
if(!FileUtil::exists(gscript)) {
Log::e("Missing scripts directory: \"",TextCodec::toUtf8(gscript),"\"");
return false;
if(!FileUtil::exists(nestedPath({u"Data"},Dir::FT_Dir)))
}
auto dataPath = nestedPath({u"Data"},Dir::FT_Dir);
if(!FileUtil::exists(dataPath)) {
Log::e("Missing Data directory: \"",TextCodec::toUtf8(dataPath),"\"");
return false;
if(!FileUtil::exists(nestedPath({u"_work",u"Data"},Dir::FT_Dir)))
}
auto workDataPath = nestedPath({u"_work",u"Data"},Dir::FT_Dir);
if(!FileUtil::exists(workDataPath)) {
Log::e("Missing _work/Data directory: \"",TextCodec::toUtf8(workDataPath),"\"");
return false;
}
return true;
}
5 changes: 5 additions & 0 deletions game/game/playercontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ void PlayerControl::onRotateMouse(float dAngleX, float dAngleY) {
rotMouseY += dAngleY;
}

void PlayerControl::setGamepadAxis(float lx, float ly) {
gamepadLX = lx;
gamepadLY = ly;
}

void PlayerControl::tickFocus() {
currentFocus = findFocus(&currentFocus);
setTarget(currentFocus.npc);
Expand Down
Loading