cmake_minimum_required(VERSION 3.26)

project(SimVulcan
    VERSION 0.1.0
    DESCRIPTION "Vulkan 3D editor: orbit camera, reference grid, OBJ model viewer"
    LANGUAGES CXX C
)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

include(CompilerWarnings)
include(Sanitizers)
include(VulkanSetup)
include(ShaderCompile)
include(FetchContent)

# ----------------------------------------------------------------------------
#  External dependencies (FetchContent — pinned commits)
# ----------------------------------------------------------------------------
set(FETCHCONTENT_QUIET OFF)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)

# GLFW
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS    OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_DOCS     OFF CACHE BOOL "" FORCE)
FetchContent_Declare(glfw
    GIT_REPOSITORY https://github.com/glfw/glfw.git
    GIT_TAG        3.4
)

# GLM
FetchContent_Declare(glm
    GIT_REPOSITORY https://github.com/g-truc/glm.git
    GIT_TAG        1.0.1
)

# volk (lazy Vulkan loader)
FetchContent_Declare(volk
    GIT_REPOSITORY https://github.com/zeux/volk.git
    GIT_TAG        1.3.295
)

# vk-bootstrap
FetchContent_Declare(vk-bootstrap
    GIT_REPOSITORY https://github.com/charles-lunarg/vk-bootstrap.git
    GIT_TAG        v1.3.295
)

# Vulkan Memory Allocator
FetchContent_Declare(VulkanMemoryAllocator
    GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
    GIT_TAG        v3.1.0
)

# Dear ImGui (we wrap it in a small CMake target ourselves below).
FetchContent_Declare(imgui
    GIT_REPOSITORY https://github.com/ocornut/imgui.git
    GIT_TAG        v1.91.5-docking
)

# spdlog
set(SPDLOG_BUILD_SHARED OFF CACHE BOOL "" FORCE)
set(SPDLOG_FMT_EXTERNAL OFF CACHE BOOL "" FORCE)
FetchContent_Declare(spdlog
    GIT_REPOSITORY https://github.com/gabime/spdlog.git
    GIT_TAG        v1.14.1
)

# tinyobjloader (header-only)
FetchContent_Declare(tinyobjloader
    GIT_REPOSITORY https://github.com/tinyobjloader/tinyobjloader.git
    GIT_TAG        v2.0.0rc13
)

# Catch2
FetchContent_Declare(Catch2
    GIT_REPOSITORY https://github.com/catchorg/Catch2.git
    GIT_TAG        v3.7.1
)

FetchContent_MakeAvailable(
    glfw glm volk vk-bootstrap VulkanMemoryAllocator
    imgui spdlog tinyobjloader Catch2
)

# ----------------------------------------------------------------------------
#  ImGui static library (needs explicit target — official repo has none)
# ----------------------------------------------------------------------------
add_library(imgui STATIC
    ${imgui_SOURCE_DIR}/imgui.cpp
    ${imgui_SOURCE_DIR}/imgui_demo.cpp
    ${imgui_SOURCE_DIR}/imgui_draw.cpp
    ${imgui_SOURCE_DIR}/imgui_tables.cpp
    ${imgui_SOURCE_DIR}/imgui_widgets.cpp
    ${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
    ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp
)
target_include_directories(imgui PUBLIC
    ${imgui_SOURCE_DIR}
    ${imgui_SOURCE_DIR}/backends
)
target_link_libraries(imgui PUBLIC glfw Vulkan::Headers volk)
# Have ImGui's Vulkan backend pick up function pointers from volk directly,
# instead of asking us to load them via ImGui_ImplVulkan_LoadFunctions.
target_compile_definitions(imgui PUBLIC
    IMGUI_IMPL_VULKAN_NO_PROTOTYPES
    IMGUI_IMPL_VULKAN_USE_VOLK
    VK_NO_PROTOTYPES
)

# Catch2 helpers (catch_discover_tests).
include(CTest)
include(${Catch2_SOURCE_DIR}/extras/Catch.cmake)

# ----------------------------------------------------------------------------
#  Project targets
# ----------------------------------------------------------------------------
add_subdirectory(shaders)        # produces simv_shaders custom target
add_subdirectory(src/core)
add_subdirectory(src/vk)
add_subdirectory(src/mesh)
add_subdirectory(src/editor)
add_subdirectory(src/app)
enable_testing()
add_subdirectory(tests)

message(STATUS "")
message(STATUS "SimVulcan ${PROJECT_VERSION} configured.")
message(STATUS "  Build type:  ${CMAKE_BUILD_TYPE}")
message(STATUS "  C++ std:     ${CMAKE_CXX_STANDARD}")
message(STATUS "  Vulkan:      ${Vulkan_VERSION}")
message(STATUS "  Generator:   ${CMAKE_GENERATOR}")
message(STATUS "")
