diff --git a/.gitignore b/.gitignore index f9e4e7c93..b4d39213a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,9 @@ internal/ #os .DS_Store + + +CMakeCache.txt +cmake_install.cmake +CMakeFiles/ +Makefile diff --git a/AndroidManifest.xml.in b/AndroidManifest.xml.in new file mode 100644 index 000000000..76495b541 --- /dev/null +++ b/AndroidManifest.xml.in @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 552a4d9e4..232f95b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) @@ -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) @@ -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() @@ -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() diff --git a/cmake/android/GenerateAndroidBuild.cmake b/cmake/android/GenerateAndroidBuild.cmake new file mode 100644 index 000000000..ff93fee23 --- /dev/null +++ b/cmake/android/GenerateAndroidBuild.cmake @@ -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() diff --git a/cmake/android/app.build.gradle.in b/cmake/android/app.build.gradle.in new file mode 100644 index 000000000..fcc6bca7a --- /dev/null +++ b/cmake/android/app.build.gradle.in @@ -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' +} diff --git a/game/commandline.cpp b/game/commandline.cpp index eda2039ba..6b4639535 100644 --- a/game/commandline.cpp +++ b/game/commandline.cpp @@ -225,13 +225,23 @@ std::u16string CommandLine::nestedPath(const std::initializer_list main; - + /// Reverse direction (e.g. S or Down arrow) std::array reverse; @@ -108,7 +109,7 @@ class PlayerControl final { } return false; } - + /// Is any key pressed that activates the reverse direction /// (e.g. S or Down arrow in Forward-Backward axis) auto anyReverse() const -> bool { @@ -120,7 +121,7 @@ class PlayerControl final { }; struct MovementStatus { - AxisStatus forwardBackward; + AxisStatus forwardBackward; AxisStatus strafeRightLeft; AxisStatus turnRightLeft; @@ -131,7 +132,7 @@ class PlayerControl final { this->turnRightLeft.reset(); } } movement; - + bool ctrl[Action::Last]={}; bool wctrl[WeaponAction::Last]={}; bool actrl[7]={}; @@ -142,6 +143,8 @@ class PlayerControl final { Focus currentFocus; float rotMouse=0; float rotMouseY=0; + float gamepadLX=0; + float gamepadLY=0; bool casting = false; size_t pickLockProgress = 0; @@ -180,17 +183,17 @@ class PlayerControl final { ////////////////////////////////// auto wantsToMoveForward() const -> bool { - return movement.forwardBackward.value() > 0.f; + return movement.forwardBackward.value() > 0.f || gamepadLY < -0.2f; } auto wantsToMoveBackward() const -> bool { - return movement.forwardBackward.value() < 0.f; + return movement.forwardBackward.value() < 0.f || gamepadLY > 0.2f; } auto wantsToStrafeRight() const -> bool { - return movement.strafeRightLeft.value() > 0.f; + return movement.strafeRightLeft.value() > 0.f || gamepadLX > 0.2f; } auto wantsToStrafeLeft() const -> bool { - return movement.strafeRightLeft.value() < 0.f; + return movement.strafeRightLeft.value() < 0.f || gamepadLX < -0.2f; } auto wantsToTurnRight() const -> bool { diff --git a/game/main.cpp b/game/main.cpp index de00118e9..42603bc74 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -14,7 +14,7 @@ #include #endif -#if defined(__IOS__) +#if defined(__IOS__) || defined(__ANDROID__) #include "utils/installdetect.h" #endif @@ -53,7 +53,7 @@ std::unique_ptr mkApi(const CommandLine& g) { break; #endif case CommandLine::Vulkan: -#if !defined(__APPLE__) +#if !defined(__APPLE__) || defined(__ANDROID__) return std::make_unique(flg); #else break; @@ -73,6 +73,13 @@ int main(int argc,const char** argv) { auto appdir = InstallDetect::applicationSupportDirectory(); std::filesystem::current_path(appdir); } +#elif defined(__ANDROID__) + { + auto appdir = InstallDetect::applicationSupportDirectory(); + if(!appdir.empty()) { + std::filesystem::current_path(appdir); + } + } #endif try { diff --git a/game/mainwindow.cpp b/game/mainwindow.cpp index 34985d74e..e59422113 100644 --- a/game/mainwindow.cpp +++ b/game/mainwindow.cpp @@ -26,6 +26,8 @@ #include "commandline.h" #include "gothic.h" +#include + using namespace Tempest; MainWindow::MainWindow(Device& device) @@ -281,8 +283,17 @@ void MainWindow::paintEvent(PaintEvent& event) { void MainWindow::resizeEvent(SizeEvent&) { for(auto& i:fence) i.wait(); + + auto rectBefore = SystemApi::windowClientRect(hwnd()); + Tempest::Log::i("MainWindow::resizeEvent: Starting resize - window: ", rectBefore.w, "x", rectBefore.h); + swapchain.reset(); renderer.resetSwapchain(); + + auto rectAfter = SystemApi::windowClientRect(hwnd()); + Tempest::Log::i("MainWindow::resizeEvent: After swapchain reset - window: ", rectAfter.w, "x", rectAfter.h); + Tempest::Log::i("MainWindow::resizeEvent: Swapchain size: ", swapchain.w(), "x", swapchain.h()); + if(auto camera = Gothic::inst().camera()) camera->setViewport(swapchain.w(),swapchain.h()); @@ -291,6 +302,8 @@ void MainWindow::resizeEvent(SizeEvent&) { setCursorPosition(rect.w/2,rect.h/2); setCursorShape(fs ? CursorShape::Hidden : CursorShape::Arrow); dMouse = Point(); + + Tempest::Log::i("MainWindow::resizeEvent: Resize completed"); } void MainWindow::mouseDownEvent(MouseEvent &event) { @@ -369,6 +382,42 @@ void MainWindow::tickMouse(uint64_t dt) { dMouse = Point(); } +void MainWindow::tickGamepad() { + auto gp = SystemApi::gamepadState(); + if(!gp.connected) + return; + + auto camera = Gothic::inst().camera(); + if(dialogs.hasContent() || Gothic::inst().isPause() || camera==nullptr || camera->isCutscene()) + return; + + const float deadzone = 0.15f; + const float sensitivity = 15.0f; + + float rx = gp.rightStickX; + float ry = gp.rightStickY; + + if(std::abs(rx) < deadzone) rx = 0.0f; + if(std::abs(ry) < deadzone) ry = 0.0f; + + if(rx != 0.0f || ry != 0.0f) { + PointF dp(ry * sensitivity, -rx * sensitivity); + camera->onRotateMouse(dp); + + if(!inventory.isActive()) { + player.onRotateMouse(-dp.y, dp.x); + } + } + + float lx = gp.leftStickX; + float ly = gp.leftStickY; + + if(std::abs(lx) < deadzone) lx = 0.0f; + if(std::abs(ly) < deadzone) ly = 0.0f; + + player.setGamepadAxis(lx, ly); + } + void MainWindow::onSettings() { auto zMaxFps = Gothic::options().fpsLimit; if(zMaxFps<=0) @@ -529,6 +578,7 @@ void MainWindow::keyUpEvent(KeyEvent &event) { if(auto pl = Gothic::inst().player()) rootMenu.setPlayer(*pl); clearInput(); + //event.accept(); } else if(act==KeyCodec::Inventory && !dialogs.isActive()) { if(inventory.isActive()) { @@ -892,6 +942,7 @@ uint64_t MainWindow::tick() { else if(runtimeMode==R_Suspended) { auto camera = Gothic::inst().camera(); if(camera!=nullptr && camera->isFree()) { + tickGamepad(); tickMouse(dt); } update(); @@ -907,7 +958,8 @@ uint64_t MainWindow::tick() { ;//clearInput(); if(document.isActive()) clearInput(); - tickMouse(dt); + tickMouse(); + tickGamepad(); player.tickMove(dt); update(); return dt; diff --git a/game/mainwindow.h b/game/mainwindow.h index 833e58894..a5ff720de 100644 --- a/game/mainwindow.h +++ b/game/mainwindow.h @@ -89,7 +89,8 @@ class MainWindow : public Tempest::Window { void setFullscreen(bool fs); void processMouse(Tempest::MouseEvent& event, bool enable); - void tickMouse(uint64_t dt); + void tickMouse(uint64_t dt = 0); + void tickGamepad(); void onSettings(); void setupUi(); diff --git a/game/utils/crashlog.cpp b/game/utils/crashlog.cpp index 4373f8ce0..f667931d6 100644 --- a/game/utils/crashlog.cpp +++ b/game/utils/crashlog.cpp @@ -14,7 +14,7 @@ #include #endif -#if defined(__LINUX__) || defined(__APPLE__) +#if (defined(__LINUX__) || defined(__APPLE__)) && !defined(__ANDROID__) #include // backtrace #include // dladdr #include // __cxa_demangle @@ -167,7 +167,7 @@ void CrashLog::tracebackStd(std::ostream &out) { } void CrashLog::tracebackLinux(std::ostream &out) { -#if defined(__LINUX__) || defined(__APPLE__) +#if (defined(__LINUX__) || defined(__APPLE__)) && !defined(__ANDROID__) // inspired by https://gist.github.com/fmela/591333/36faca4c2f68f7483cd0d3a357e8a8dd5f807edf (BSD) void *callstack[64] = {}; char **symbols = nullptr; diff --git a/game/utils/installdetect.cpp b/game/utils/installdetect.cpp index 9c7f3de39..b15be3b0d 100644 --- a/game/utils/installdetect.cpp +++ b/game/utils/installdetect.cpp @@ -1,6 +1,7 @@ #include "installdetect.h" #include +#include #ifdef __WINDOWS__ #include "windows.h" @@ -8,7 +9,11 @@ #include "shlwapi.h" #endif -#include +#ifdef __ANDROID__ +#include +extern "C" struct android_app* tempest_android_get_app(); +#endif + #include "utils/fileutil.h" InstallDetect::InstallDetect() { @@ -16,7 +21,7 @@ InstallDetect::InstallDetect() { pfiles = programFiles(false); pfilesX86 = programFiles(true); #endif -#if defined(__OSX__) || defined(__IOS__) +#if defined(__OSX__) || defined(__IOS__) || defined(__ANDROID__) appDir = applicationSupportDirectory(); #endif } @@ -27,6 +32,14 @@ std::u16string InstallDetect::detectG2() { if(ret.empty()) ret = detectG2(pfilesX86); return ret; +#elif defined(__ANDROID__) + // Check external storage + if(FileUtil::exists(u"/storage/emulated/0/Gothic2/")) + return u"/storage/emulated/0/Gothic2/"; + // First check app's private data directory + if(FileUtil::exists(appDir)) + return appDir; + return u""; #elif defined(__OSX__) || defined(__IOS__) if(FileUtil::exists(appDir)) return appDir; @@ -62,3 +75,20 @@ std::u16string InstallDetect::programFiles(bool x86) { return ret; } #endif + +#ifdef __ANDROID__ +std::u16string InstallDetect::applicationSupportDirectory() { + struct android_app* app = tempest_android_get_app(); + if(app == nullptr || app->activity == nullptr) + return u""; + + // Prefer external data path (accessible without root) + const char* path = app->activity->externalDataPath; + if(path == nullptr) + path = app->activity->internalDataPath; + if(path == nullptr) + return u""; + + return Tempest::TextCodec::toUtf16(path); + } +#endif diff --git a/game/utils/installdetect.h b/game/utils/installdetect.h index 140855660..fdf3709ce 100644 --- a/game/utils/installdetect.h +++ b/game/utils/installdetect.h @@ -8,7 +8,7 @@ class InstallDetect final { InstallDetect(); std::u16string detectG2(); -#if defined(__OSX__) || defined(__IOS__) +#if defined(__OSX__) || defined(__IOS__) || defined(__ANDROID__) static std::u16string applicationSupportDirectory(); #endif @@ -20,7 +20,7 @@ class InstallDetect final { std::u16string pfiles, pfilesX86; #endif -#if defined(__OSX__) || defined(__IOS__) +#if defined(__OSX__) || defined(__IOS__) || defined(__ANDROID__) std::u16string appDir; #endif }; diff --git a/lib/Tempest b/lib/Tempest index 4487b10b5..480afd888 160000 --- a/lib/Tempest +++ b/lib/Tempest @@ -1 +1 @@ -Subproject commit 4487b10b5991f7e3cc48978a9b5cf376e2546dae +Subproject commit 480afd888eb4415b2c70e27f1697626feadfddca diff --git a/shader/CMakeLists.txt b/shader/CMakeLists.txt index 4eda6621a..461a2d5eb 100644 --- a/shader/CMakeLists.txt +++ b/shader/CMakeLists.txt @@ -6,18 +6,18 @@ set(HEADER "${PROJECT_BINARY_DIR}/sprv/shader.h") set(CPP "${PROJECT_BINARY_DIR}/sprv/shader.cpp") file(GLOB_RECURSE SOURCES - "${CMAKE_SOURCE_DIR}/shader/*.vert" - "${CMAKE_SOURCE_DIR}/shader/*.tesc" - "${CMAKE_SOURCE_DIR}/shader/*.tese" - "${CMAKE_SOURCE_DIR}/shader/*.geom" - "${CMAKE_SOURCE_DIR}/shader/*.frag" - "${CMAKE_SOURCE_DIR}/shader/*.glsl" - "${CMAKE_SOURCE_DIR}/shader/*.task" - "${CMAKE_SOURCE_DIR}/shader/*.mesh" - "${CMAKE_SOURCE_DIR}/shader/*.comp") + "${CMAKE_CURRENT_LIST_DIR}/*.vert" + "${CMAKE_CURRENT_LIST_DIR}/*.tesc" + "${CMAKE_CURRENT_LIST_DIR}/*.tese" + "${CMAKE_CURRENT_LIST_DIR}/*.geom" + "${CMAKE_CURRENT_LIST_DIR}/*.frag" + "${CMAKE_CURRENT_LIST_DIR}/*.glsl" + "${CMAKE_CURRENT_LIST_DIR}/*.task" + "${CMAKE_CURRENT_LIST_DIR}/*.mesh" + "${CMAKE_CURRENT_LIST_DIR}/*.comp") file(GLOB_RECURSE GLSL_SOURCES - "${CMAKE_SOURCE_DIR}/shader/*.glsl") + "${CMAKE_CURRENT_LIST_DIR}/*.glsl") # GLSL to SPIRV compiler find_program(GLSLANGVALIDATOR glslangValidator "/opt/homebrew/bin") @@ -27,7 +27,7 @@ endif() function(add_shader OUTPUT SOURCE) set(OUTPUT_FILE "${PROJECT_BINARY_DIR}/sprv/${OUTPUT}.sprv") - set(SOURCE_FILE "${CMAKE_SOURCE_DIR}/shader/${SOURCE}") + set(SOURCE_FILE "${CMAKE_CURRENT_LIST_DIR}/${SOURCE}") set(OPENGOTHIC_SHADERS ${OPENGOTHIC_SHADERS} ${SOURCE_FILE} PARENT_SCOPE) set(OPENGOTHIC_SHADERS_SPRV ${OPENGOTHIC_SHADERS_SPRV} ${OUTPUT_FILE} PARENT_SCOPE) @@ -67,7 +67,7 @@ function(add_shader OUTPUT SOURCE) OUTPUT ${OUTPUT_FILE} DEPENDS ${SOURCE_FILE} ${GLSL_SOURCES} COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/sprv/" - COMMAND ${GLSLANGVALIDATOR} -V ${VARS} -I"${CMAKE_SOURCE_DIR}/shader" "${SOURCE_FILE}" -o ${OUTPUT_FILE} + COMMAND ${GLSLANGVALIDATOR} -V ${VARS} -I"${CMAKE_CURRENT_LIST_DIR}" "${SOURCE_FILE}" -o ${OUTPUT_FILE} ) endfunction(add_shader) @@ -373,13 +373,13 @@ add_custom_command( OUTPUT ${HEADER} ${CPP} DEPENDS ${OPENGOTHIC_SHADERS_SPRV} COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/sprv/" - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_SOURCE_DIR}/shader/link_shaders.cmake" + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/link_shaders.cmake" WORKING_DIRECTORY "${PROJECT_BINARY_DIR}" ) add_custom_target(shader DEPENDS ${HEADER} ${CPP} - SOURCES ${SOURCES} "${CMAKE_SOURCE_DIR}/shader/link_shaders.cmake") + SOURCES ${SOURCES} "${CMAKE_CURRENT_LIST_DIR}/link_shaders.cmake") add_library(${PROJECT_NAME} STATIC ${HEADER} ${CPP}) add_dependencies(${PROJECT_NAME} shader)