# Box2D samples app

# glad for OpenGL API
set(GLAD_DIR ${CMAKE_SOURCE_DIR}/extern/glad)

add_library(
    glad STATIC
    ${GLAD_DIR}/src/glad.c
    ${GLAD_DIR}/include/glad/glad.h
    ${GLAD_DIR}/include/KHR/khrplatform.h
)
target_include_directories(glad PUBLIC ${GLAD_DIR}/include)

# glfw for windowing and input
set(GLFW_BUILD_DOCS OFF CACHE BOOL "GLFW Docs")
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "GLFW Examples")
set(GLFW_BUILD_TESTS OFF CACHE BOOL "GLFW Tests")
set(GLFW_INSTALL OFF CACHE BOOL "GLFW Install")

FetchContent_Declare(
    glfw
    GIT_REPOSITORY https://github.com/glfw/glfw.git
    GIT_TAG 3.4
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(glfw)

# imgui and glfw backend for GUI
FetchContent_Declare(
    imgui
    GIT_REPOSITORY https://github.com/ocornut/imgui.git
    GIT_TAG v1.92.7
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(imgui)

add_library(imgui STATIC
    ${imgui_SOURCE_DIR}/imconfig.h
    ${imgui_SOURCE_DIR}/imgui.h
    ${imgui_SOURCE_DIR}/imgui.cpp
    ${imgui_SOURCE_DIR}/imgui_draw.cpp
    ${imgui_SOURCE_DIR}/imgui_demo.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_opengl3.cpp
)

target_link_libraries(imgui PUBLIC glfw glad)
target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR} ${imgui_SOURCE_DIR}/backends)
target_compile_definitions(imgui PUBLIC IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
target_compile_features(imgui PUBLIC cxx_std_20)
set_target_properties(imgui PROPERTIES CXX_EXTENSIONS NO)

# jsmn for json
set(JSMN_DIR ${CMAKE_SOURCE_DIR}/extern/jsmn)

add_library(jsmn INTERFACE ${JSMN_DIR}/jsmn.h)
target_include_directories(jsmn INTERFACE ${JSMN_DIR})

# implot for drawing real time plots
FetchContent_Declare(
    implot
    GIT_REPOSITORY https://github.com/epezent/implot.git
    GIT_TAG v0.17
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(implot)

add_library(implot STATIC
    ${implot_SOURCE_DIR}/implot.cpp
    ${implot_SOURCE_DIR}/implot_items.cpp
    ${implot_SOURCE_DIR}/implot_demo.cpp
    ${implot_SOURCE_DIR}/implot.h
    ${implot_SOURCE_DIR}/implot_internal.h
)
target_link_libraries(implot PUBLIC imgui)
target_include_directories(implot PUBLIC ${implot_SOURCE_DIR})

# nativefiledialog-extended for the Replay open dialog. Native OS file picker, target nfd.
set(NFD_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(NFD_INSTALL OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
    nfd
    GIT_REPOSITORY https://github.com/btzy/nativefiledialog-extended.git
    GIT_TAG v1.3.0
    GIT_SHALLOW TRUE
    GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(nfd)

# Embed shaders as null-terminated byte arrays into a generated header so the
# samples binary has no runtime dependency on samples/data/*.vs and *.fs.
set(SHADER_FILES
    data/background.vs data/background.fs
    data/circle.vs     data/circle.fs
    data/line.vs       data/line.fs
    data/point.vs      data/point.fs
    data/solid_capsule.vs data/solid_capsule.fs
    data/solid_circle.vs  data/solid_circle.fs
    data/solid_polygon.vs data/solid_polygon.fs
)

set(SHADER_HEADER "${CMAKE_CURRENT_BINARY_DIR}/shaders_embedded.h")
file(WRITE ${SHADER_HEADER}
    "// Generated by CMake from samples/data/*.vs and *.fs. Do not edit.\n"
    "#pragma once\n\n")
foreach(SHADER_FILE ${SHADER_FILES})
    set(SHADER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_FILE}")
    file(READ ${SHADER_PATH} SHADER_HEX HEX)
    string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," SHADER_BYTES "${SHADER_HEX}")
    get_filename_component(SHADER_NAME ${SHADER_FILE} NAME)
    string(REPLACE "." "_" SHADER_SYM ${SHADER_NAME})
    file(APPEND ${SHADER_HEADER}
        "static const char k_${SHADER_SYM}[] = { ${SHADER_BYTES} 0x00 };\n\n")
    set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${SHADER_PATH})
endforeach()

# The shared host plus the double precision aware samples. Compiled in every precision mode.
# The Replay Viewer is part of the host: it is the required way to view a double precision recording.
set(BOX2D_SAMPLE_FRAMEWORK_FILES
    container.c
    container.h
    draw.c
    draw.h
    draw_text.cpp
    main.cpp
    sample.cpp
    sample.h
    sample_replay.cpp
    shader.c
    shader.h
    stb_image_write.h
)

# Samples beyond the host. These compile in both precision modes: a world coordinate flowing
# through the b2World API keeps its natural type and is demoted only at the ad-hoc draw boundary.
set(BOX2D_SAMPLE_COMMON_FILES
    car.cpp
    car.h
    donut.cpp
    donut.h
    doohickey.cpp
    doohickey.h
    dynamic_mover.cpp
    dynamic_mover.h
    geometric_mover.cpp
    geometric_mover.h
    sample_benchmark.cpp
    sample_bodies.cpp
    sample_character.cpp
    sample_collision.cpp
    sample_continuous.cpp
    sample_determinism.cpp
    sample_events.cpp
    sample_geometry.cpp
    sample_issues.cpp
    sample_joints.cpp
    sample_restitution.cpp
    sample_robustness.cpp
    sample_shapes.cpp
    sample_stacking.cpp
    sample_world.cpp
)

set(BOX2D_SAMPLE_FILES ${BOX2D_SAMPLE_FRAMEWORK_FILES} ${BOX2D_SAMPLE_COMMON_FILES})

add_executable(samples ${BOX2D_SAMPLE_FILES})

set_target_properties(samples PROPERTIES
    CXX_STANDARD 20
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO
)

if(BOX2D_COMPILE_WARNING_AS_ERROR)
    set_target_properties(samples PROPERTIES COMPILE_WARNING_AS_ERROR ON)
endif()

target_include_directories(samples PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${JSMN_DIR})
target_link_libraries(samples PUBLIC box2d shared imgui implot glfw glad nfd)

# target_compile_definitions(samples PRIVATE "$<$<CONFIG:DEBUG>:SAMPLES_DEBUG>")
# message(STATUS "runtime = ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
# message(STATUS "binary = ${CMAKE_CURRENT_BINARY_DIR}")

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${BOX2D_SAMPLE_FILES})
