set(OPENMW_SOURCES
    engine.cpp
    options.cpp
)

# Start of tes3mp change
#
# The game is tes3mp.exe: its own icon and manifest
set(OPENMW_RESOURCES
    ${CMAKE_SOURCE_DIR}/files/tes3mp/tes3mp.rc
    ${CMAKE_SOURCE_DIR}/files/tes3mp/tes3mp.exe.manifest
)
#set(OPENMW_RESOURCES
#    ${CMAKE_SOURCE_DIR}/files/windows/openmw.rc
#    ${CMAKE_SOURCE_DIR}/files/windows/openmw.exe.manifest
#)
# End of tes3mp change

set(OPENMW_HEADERS
    doc.hpp
    engine.hpp
    options.hpp
    profile.hpp
)

source_group(apps/openmw FILES main.cpp androidmain.cpp ${OPENMW_SOURCES} ${OPENMW_HEADERS} ${OPENMW_RESOURCES})

add_openmw_dir (mwrender
    actors objects renderingmanager animation rotatecontroller sky skyutil npcanimation esm4npcanimation vismask
    creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager
    bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
    renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover
    postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass precipitationocclusion ripples
    actorutil distortion animationpriority bonegroup blendmask animblendcontroller
    # Start of tes3mp addition
    occlusionculling
    # End of tes3mp addition
    # Start of tes3mp addition
    actorshadows
    # End of tes3mp addition
    # Start of tes3mp addition
    # merge one of those (createChunk re-reads the cell's ESM ref stream, which has no record of a runtime placement).
    placedbatcher
    # PF1: the batcher's geometry half, split out so a test can build batches without a world.
    placedbatchbuild
    # End of tes3mp addition
    # Start of tes3mp addition
    # foot IK for players, NPCs and creatures with legs. Our own work.
    limbik limbiksolve footik
    # End of tes3mp addition
    # Start of tes3mp addition
    firstpersonarmsrule firstpersonarmsview
    # End of tes3mp addition
    # Start of tes3mp addition
    objectpreview
    # End of tes3mp addition
    )

add_openmw_dir (mwinput
    actions actionmanager bindingsmanager controllermanager controlswitch
    inputmanagerimp mousemanager keyboardmanager sensormanager gyromanager
    )

add_openmw_dir (mwgui
    layout textinput widgets race class birth review windowmanagerimp console dialogue
    windowbase statswindow messagebox journalwindow charactercreation
    mapwindow windowpinnablebase tooltips scrollwindow bookwindow resourceskin
    formatting inventorywindow container hud countdialog tradewindow settingswindow
    confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
    itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
    enchantingdialog trainingwindow travelwindow exposedwindow cursor spellicons
    merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
    itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
    tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
    recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
    draganddrop timeadvancer jailscreen itemchargeview keyboardnavigation textcolours statswatcher
    postprocessorhud settings worlditemmodel itemtransfer controllerbuttonsoverlay inventorytabsoverlay
    # Start of tes3mp addition
    theftprompt
    # End of tes3mp addition
    # Start of tes3mp addition
    mapwindowoverlays
    # End of tes3mp addition
    # Start of tes3mp addition
    luabookpage
    # End of tes3mp addition
    )

add_openmw_dir (mwdialogue
    dialoguemanagerimp journalimp journalentry quest topic filter selectwrapper keywordsearch scripttest
    )

add_openmw_dir (mwscript
    locals scriptmanagerimp compilercontext interpretercontext cellextensions miscextensions
    guiextensions soundextensions skyextensions statsextensions containerextensions
    aiextensions controlextensions extensions globalscripts ref dialogueextensions
    animationextensions transformationextensions consoleextensions userextensions
    )

add_openmw_dir (mwlua
    luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant loadscripts contentbindings
    context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings coremwscriptbindings
    mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings
    postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker landbindings magicbindings factionbindings
    classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings weatherbindings regionbindings
    types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc
    types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus
    types/potion types/ingredient types/misc types/repair types/armor types/light types/static
    types/clothing types/levelledlist types/terminal magictypebindings
    )

add_openmw_dir (mwsound
    soundmanagerimp openaloutput ffmpegdecoder sound soundbuffer sounddecoder soundoutput
    loudness movieaudiofactory alext efx efxpresets regionsoundselector watersoundupdater
    )

add_openmw_dir (mwworld
    refdata worldimp scene globals class action nullaction actionteleport
    containerstore actiontalk actiontake manualref player cellvisitors failedaction
    worldmodel localscripts customdata inventorystore ptr actionopen actionread actionharvest
    actionequip timestamp actionalchemy cellstore actionapply actioneat
    store esmstore fallback actionrepair actionsoulgem livecellref actiondoor
    contentloader esmloader actiontrap cellreflist cellref weather projectilemanager
    cellpreloader datetimemanager groundcoverstore magiceffects cell ptrregistry
    # Start of tes3mp addition
    # so SiltStriderFollowerSpotTest builds it standalone. Our own work.
    followerspot
    # End of tes3mp addition
    positioncellgrid
    )

add_openmw_dir (mwphysics
    physicssystem trace collisiontype actor convert object heightfield closestnotmerayresultcallback
    contacttestresultcallback stepper movementsolver projectile
    actorconvexcallback raycasting mtphysics contacttestwrapper projectileconvexcallback
    # Start of tes3mp addition
    ghostspace
    # End of tes3mp addition
    )

add_openmw_dir (mwclass
    classes activator creature npc weapon armor potion apparatus book clothing container door
    ingredient creaturelevlist itemlevlist light lockpick misc probe repair static actor bodypart
    esm4base esm4npc light4
    )

add_openmw_dir (mwmechanics
    mechanicsmanagerimp stat creaturestats magiceffects movement actorutil spelllist
    drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
    aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance
    disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction summoning
    character actors objects aistate weaponpriority spellpriority weapontype spellutil
    spelleffects
    activeblock
    # Start of tes3mp addition
    # that SiltStriderNavHolesTest can compile it alone.
    navholes
    # End of tes3mp addition
    )

add_openmw_dir (mwstate
    statemanagerimp charactermanager character quicksavemanager
    )

add_openmw_dir (mwbase
    environment world scriptmanager dialoguemanager journal soundmanager mechanicsmanager
    inputmanager windowmanager statemanager luamanager
    )

# Start of tes3mp addition
#
# The multiplayer layer. The processors are header only. The content updater and the crash
# reporter's files (mwmp/content, CrashSession, CrashReport, CrashUpload, CrashWindow,
# CrashFlow, ClientPlatform) are not listed here: they build as the tes3mp-content library in
# mwmp/content, in their own directory scope, because they are plain Win32 and 0.51's root
# CMakeLists defines NOGDI, NOMB and UNICODE for every Windows target.
add_openmw_dir (mwmp
    PlacementMode Main Networking LocalSystem LocalPlayer DedicatedPlayer PlayerList LocalActor DedicatedActor ActorList
    OverheadText HeadAnchor NameOverrides RoadOverlay NodeOverlay HeadLookDebug
    ObjectList Worldstate Cell CellController GUIController MechanicsHelper RecordHelper ScriptController
    DispositionNotify DispositionPending MerchantPrices MerchantStock
    Vessel VesselCart VesselList RideExit GhostNavigator
    RefNumIdentities WireConvert
    Frontier
    LiveAssets LiveAssetsBundle
    ViewStrip # AV1: the AIRIS 360 degree view
    SpawnPreloader
    )

add_openmw_dir (mwmp/GUI GUIChat GUILogin PlayerMarkerCollection GUIDialogList GUIGridBox GUIPreviewBox
    GUIAlertBox PreviewDump PreviewSpec TextInputDialog
    # the bug report window (its OS half, BugReportPlatform, builds in mwmp/content because it is
    # plain Win32)
    GUIBugReport
    # CR1: the upload both report windows share, and the crash report window
    BugReportUpload GUICrashReport
    )

add_openmw_dir (mwmp/processors BaseClientPacketProcessor SystemProcessor PlayerProcessor ObjectProcessor ActorProcessor
    WorldstateProcessor ProcessorInitializer
    )

add_openmw_dir (mwmp/processors/system ProcessorSystemHandshake
    )

add_openmw_dir (mwmp/processors/actor ProcessorActorOverhead ProcessorActorFacePlayer ProcessorActorAI ProcessorActorAIState ProcessorActorAnimFlags ProcessorActorAnimPlay ProcessorActorAttack
    ProcessorActorAuthority ProcessorActorCast ProcessorActorCellChange ProcessorActorDeath ProcessorActorEquipment
    ProcessorActorList ProcessorActorPosition ProcessorActorSpeech ProcessorActorSpellsActive ProcessorActorStatsDynamic
    ProcessorActorTest
    )

add_openmw_dir (mwmp/processors/player ProcessorPlayerOverhead ProcessorPlayerNameOverride ProcessorPlayerJournalCustom ProcessorPlayerTerritory ProcessorPlayerOpenService ProcessorPlayerDispositionState ProcessorPlayerMerchant ProcessorPlayerNavMesh ProcessorPlayerNodeOverlay ProcessorPlayerHeadGear ProcessorChatMessage ProcessorGUIMessageBox ProcessorUserDisconnected
    ProcessorUserMyID ProcessorGameSettings ProcessorPlayerAlly ProcessorPlayerAnimFlags ProcessorPlayerAnimPlay
    ProcessorPlayerAttack ProcessorPlayerAttribute ProcessorPlayerBaseInfo ProcessorPlayerBehavior ProcessorPlayerBook
    ProcessorPlayerBounty ProcessorPlayerCast ProcessorPlayerCellChange ProcessorPlayerCellState ProcessorPlayerCharClass
    ProcessorPlayerCharGen ProcessorPlayerCooldowns ProcessorPlayerDeath ProcessorPlayerDisposition ProcessorPlayerEquipment
    ProcessorPlayerFaction ProcessorPlayerInput ProcessorPlayerInventory ProcessorPlayerItemUse ProcessorPlayerJail
    ProcessorPlayerJournal ProcessorPlayerLevel ProcessorPlayerMiscellaneous ProcessorPlayerMomentum ProcessorPlayerPosition
    ProcessorPlayerQuickKeys ProcessorPlayerReputation ProcessorPlayerResurrect ProcessorPlayerShapeshift
    ProcessorPlayerSkill ProcessorPlayerSpeech ProcessorPlayerSpellbook ProcessorPlayerSpellsActive
    ProcessorPlayerStatsDynamic ProcessorPlayerTopic
    )

add_openmw_dir (mwmp/processors/object BaseObjectProcessor

    ProcessorConsoleCommand ProcessorConsoleRequest ProcessorContainer ProcessorDoorDestination ProcessorDoorState ProcessorMusicPlay
    ProcessorVideoPlay

    ProcessorObjectActivate ProcessorObjectAnimPlay ProcessorObjectAttach ProcessorObjectDelete
    ProcessorObjectDialogueChoice ProcessorObjectHit ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace
    ProcessorObjectRestock ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSound ProcessorObjectSpawn
    ProcessorObjectState ProcessorObjectTrap ProcessorClientScriptLocal ProcessorScriptMemberShort
    ProcessorObjectMiscellaneous
    )

add_openmw_dir (mwmp/processors/worldstate ProcessorCellReset ProcessorClientScriptGlobal ProcessorClientScriptSettings
    ProcessorRecordDynamic ProcessorWorldCollisionOverride ProcessorWorldDestinationOverride ProcessorWorldKillCount
    ProcessorWorldMap ProcessorWorldRegionAuthority ProcessorWorldTime ProcessorWorldWeather ProcessorWorldVessel ProcessorWorldRefNumIdentity
    ProcessorWorldFrontier
    )

# SiltVersions.hpp (the engine and launcher revision stamps) is generated into the build root on
# every build by the silt-version target. apps/siltstrider/CMakeLists.txt has the same guarded
# block; whichever directory is configured first defines it, never both.
if (NOT TARGET silt-version)
    if (GIT_CHECKOUT)
        add_custom_target(silt-version
            COMMAND ${CMAKE_COMMAND}
                -DGIT_EXECUTABLE=${GIT_EXECUTABLE}
                -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
                -DVERSION_HPP_DIR=${OpenMW_BINARY_DIR}
                -P ${CMAKE_SOURCE_DIR}/cmake/SiltVersion.cmake
            VERBATIM)
    else ()
        file(WRITE "${OpenMW_BINARY_DIR}/SiltVersions.hpp"
            "#ifndef OPENMW_SILTVERSIONS_HPP
#define OPENMW_SILTVERSIONS_HPP
#define SILTSTRIDER_ENGINE_REV \"unknown\"
#define SILTSTRIDER_LAUNCHER_REV \"unknown\"
#endif
")
    endif ()
endif ()

add_subdirectory(mwmp/content)
# End of tes3mp addition

# Main executable

add_library(openmw-lib STATIC
    ${OPENMW_FILES}
    ${OPENMW_SOURCES}
)

if (MSVC)
    # these TUs take a lot of memory for codegen
    # in CI, they often go over the 8GB memory limit if another cl.exe is running at the same time
    # this option (make sure you're not looking at the docs for the identically-named linker option) stops four codegen threads being spun off
    # it hurts build time ~33% to enable this unnecessarily, though, so target it to the hungriest boys
    set_source_files_properties(
        mwlua/dialoguebindings.cpp
        mwlua/magicbindings.cpp
        mwlua/objectbindings
        mwlua/stats.cpp
        mwworld/esmstore.cpp
        PROPERTIES
        COMPILE_OPTIONS /cgthreads1
    )
endif()

if(BUILD_OPENMW)
    if (ANDROID)
        add_library(openmw SHARED
            main.cpp
            androidmain.cpp
        )
    else()
        openmw_add_executable(openmw
            ${APPLE_BUNDLE_RESOURCES}
            ${OPENMW_RESOURCES}
            main.cpp
        )
    endif()

    target_link_libraries(openmw openmw-lib)

    # Start of tes3mp addition
    #
    # The game executable is tes3mp. The target stays openmw so that every upstream reference
    # to it keeps working and merges cleanly; tes3mp is a custom target that builds it, and
    # the file it writes is tes3mp.exe.
    set_target_properties(openmw PROPERTIES OUTPUT_NAME tes3mp)
    add_custom_target(tes3mp DEPENDS openmw)
    # End of tes3mp addition

    # Workaround necessary to ensure osgAnimation::MatrixLinearSampler dynamic casts work under Clang
    # NOTE: it's unclear whether the broken behavior is spec-compliant
    if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
        set_target_properties(openmw PROPERTIES ENABLE_EXPORTS ON)
    endif()
endif()

# Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING
# when we change the backend.
include_directories(
    ${FFmpeg_INCLUDE_DIRS}
)

target_link_libraries(openmw-lib
    # CMake's built-in OSG finder does not use pkgconfig, so we have to
    # manually ensure the order is correct for inter-library dependencies.
    # This only makes a difference with `-DOPENMW_USE_SYSTEM_OSG=ON -DOSG_STATIC=ON`.
    # https://gitlab.kitware.com/cmake/cmake/-/issues/21701
    ${OSGPARTICLE_LIBRARIES}
    ${OSGVIEWER_LIBRARIES}
    ${OSGGA_LIBRARIES}
    ${OSGSHADOW_LIBRARIES}
    ${OSGDB_LIBRARIES}
    ${OSGUTIL_LIBRARIES}
    ${OSG_LIBRARIES}
    Boost::program_options
    ${OPENAL_LIBRARY}
    ${FFmpeg_LIBRARIES}
    ${MyGUI_LIBRARIES}
    SDL2::SDL2
    ${RecastNavigation_LIBRARIES}
    osg-ffmpeg-videoplayer
    oics
    components
    # Start of tes3mp addition
    # after components: GNU ld resolves static archives left to right.
    maskedoc
    # End of tes3mp addition
    # Start of tes3mp addition
    tes3mp-wire
    tes3mp-content
    # End of tes3mp addition
)

# Start of tes3mp addition
#
# silt-version writes SiltVersions.hpp, which the content updater and the crash reporter include
if (TARGET silt-version)
    add_dependencies(openmw-lib silt-version)
endif ()
# End of tes3mp addition

if (MSVC AND PRECOMPILE_HEADERS_WITH_MSVC)
    target_precompile_headers(openmw-lib PRIVATE
        <boost/program_options/options_description.hpp>

        <sol/sol.hpp>

        <osg/StateSet>
        <osg/Node>
        <osg/Drawable>
        <osg/Camera>

        <osgViewer/Viewer>

        <MyGUI_Widget.h>

        <algorithm>
        <filesystem>
        <fstream>
        <functional>
        <memory>
        <string>
        <string_view>
        <vector>
    )
endif()

if (ANDROID)
    target_link_libraries(openmw-lib EGL android log z)
endif (ANDROID)

if (USE_SYSTEM_TINYXML)
    target_link_libraries(openmw-lib ${TinyXML_LIBRARIES})
endif()

if (NOT UNIX)
    target_link_libraries(openmw-lib ${SDL2MAIN_LIBRARY})
endif()

# Fix for not visible pthreads functions for linker with glibc 2.15
if (UNIX AND NOT APPLE)
    target_link_libraries(openmw-lib ${CMAKE_THREAD_LIBS_INIT})
endif()

# Start of tes3mp addition
# Static libstdc++/libgcc on the Linux game client, matching SiltStriderLauncher. The tarball must NOT bundle
# libstdc++.so.6: LD_LIBRARY_PATH points at our lib directory, so a bundled copy wins for the system Mesa too, and a
# Mesa built against a newer libstdc++ then cannot resolve its own symbols (GL dies with "Couldn't find matching GLX
# visual" after sign-in). Linking it in depends on neither the bundle nor the host copy. The target is openmw
# (OUTPUT_NAME tes3mp).
if (UNIX AND NOT APPLE AND BUILD_OPENMW)
    target_link_options(openmw PRIVATE -static-libstdc++ -static-libgcc)
endif()
# End of tes3mp addition

if(APPLE AND BUILD_OPENMW)
    set(BUNDLE_RESOURCES_DIR "${APP_BUNDLE_DIR}/Contents/Resources")

    set(OPENMW_RESOURCES_ROOT ${BUNDLE_RESOURCES_DIR})

    add_subdirectory(../../files/ ${CMAKE_CURRENT_BINARY_DIR}/files)

    configure_file("${OpenMW_BINARY_DIR}/defaults.bin" ${BUNDLE_RESOURCES_DIR} COPYONLY)
    configure_file("${OpenMW_BINARY_DIR}/openmw.cfg" ${BUNDLE_RESOURCES_DIR} COPYONLY)
    configure_file("${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" ${BUNDLE_RESOURCES_DIR} COPYONLY)

    add_custom_command(TARGET openmw
        POST_BUILD
        COMMAND cp "${OpenMW_BINARY_DIR}/resources/version" "${BUNDLE_RESOURCES_DIR}/resources")

    find_library(COCOA_FRAMEWORK Cocoa)
    find_library(IOKIT_FRAMEWORK IOKit)
    target_link_libraries(openmw ${COCOA_FRAMEWORK} ${IOKIT_FRAMEWORK})

    if (FFmpeg_FOUND)
        target_link_options(openmw PRIVATE "LINKER:SHELL:-framework CoreVideo"
                                           "LINKER:SHELL:-framework CoreMedia"
                                           "LINKER:SHELL:-framework VideoToolbox"
                                           "LINKER:SHELL:-framework AudioToolbox"
                                           "LINKER:SHELL:-framework VideoDecodeAcceleration")
    endif()
endif()

# Start of tes3mp addition
# server repo's tools/tests run them (limb-ik.lua, crash-report.lua).
#
# checks that the limb IK's knee never bends backwards (mwrender/limbiksolve.cpp, the hinged
# two-bone solve), on downhill and angled slopes, out of reach and across sweeps. OSG maths only;
# /MD.
add_executable(SiltStriderLimbIkTest
    mwrender/LimbIkTest.cpp
    mwrender/limbiksolve.cpp
)
target_include_directories(SiltStriderLimbIkTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwrender)
target_link_libraries(SiltStriderLimbIkTest ${OSG_LIBRARIES} ${OPENTHREADS_LIBRARIES})

# STRIDER-LIFT: checks the silt strider's lift rules (mwmp/StriderLift.hpp: the clamped drop and its
# rate, the jump key's tap/hold split, the leg's tightest fold) and the leg IK's solve on the
# strider's real skeleton from the top to the floor. OSG maths only; /MD, like
# SiltStriderLimbIkTest.
add_executable(SiltStriderStriderLiftTest
    mwmp/StriderLiftTest.cpp
    mwrender/limbiksolve.cpp
)
target_include_directories(SiltStriderStriderLiftTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwrender
    ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
target_link_libraries(SiltStriderStriderLiftTest ${OSG_LIBRARIES} ${OPENTHREADS_LIBRARIES})

# (siltstrider 8e381cf968): checks for the queries that cross between the world and the ghost decks
# (mwphysics/ghostspace.cpp), on a bare Bullet collision world laid out as the game lays one out.
# The module takes no engine types; it needs Bullet (double precision and thread-safe, as the
# components library declares for the whole tree) and OSG's maths. The server repo's
# tools/tests/ghost-space.lua runs it.
add_executable(SiltStriderGhostSpaceTest
    mwphysics/GhostSpaceTest.cpp
    mwphysics/ghostspace.cpp
)
target_include_directories(SiltStriderGhostSpaceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwphysics)
target_compile_definitions(SiltStriderGhostSpaceTest PRIVATE BT_USE_DOUBLE_PRECISION BT_THREADSAFE=1)
target_link_libraries(SiltStriderGhostSpaceTest ${BULLET_LIBRARIES} ${OSG_LIBRARIES} ${OPENTHREADS_LIBRARIES})

# Start of tes3mp addition
# toward the hull in either order Bullet names the pair (mwphysics/overlapaway.hpp). Bare Bullet world.
add_executable(SiltStriderOverlapAwayTest mwphysics/OverlapAwayTest.cpp)
target_include_directories(SiltStriderOverlapAwayTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwphysics)
target_compile_definitions(SiltStriderOverlapAwayTest PRIVATE BT_USE_DOUBLE_PRECISION BT_THREADSAFE=1)
target_link_libraries(SiltStriderOverlapAwayTest ${BULLET_LIBRARIES})
# End of tes3mp addition

# FP1, FP2, FP3, checks the first-person arms' rules (mwrender/firstpersonarmsrule.cpp): which arms
# group a body group plays, which body parts and effect bones are kept from the eye, when the arms
# are up, a robe's sleeve triangles, and where the arms are drawn (firstpersonarmsview.cpp).
# Standard library, the ESM part enum and OSG; /MD like the test above.
add_executable(SiltStriderFirstPersonArmsTest
    mwrender/FirstPersonArmsTest.cpp
    mwrender/firstpersonarmsrule.cpp
    mwrender/firstpersonarmsview.cpp
)
target_include_directories(SiltStriderFirstPersonArmsTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwrender)
target_link_libraries(SiltStriderFirstPersonArmsTest ${OSG_LIBRARIES} ${OSGUTIL_LIBRARIES} ${OPENTHREADS_LIBRARIES})

# NV1, nav holes: checks on the REAL navigator (components/detournavigator's NavigatorImpl, Recast
# and Detour) with a floor, two walls and a door - a locked door's connection shuts, unlocking or
# opening it reopens the way, furniture placed, moved and removed cuts and restores the mesh - plus
# the per-actor rule (mwmechanics/navholesrule.hpp) and the time a tile rebuild takes. Links
# components, so /MD like the tests above.
add_executable(SiltStriderNavHolesTest
    mwmechanics/NavHolesTest.cpp
)
target_include_directories(SiltStriderNavHolesTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmechanics)
target_link_libraries(SiltStriderNavHolesTest components)

# checks the search for a follower's spot beside a door's arrival point (mwworld/followerspot.cpp) -
# behind first, never through a wall or a door, never onto a table or off a ledge, apart from the
# player and from each other - on a world of boxes and a floor with a hole. OSG maths only; /MD like
# the tests above.
add_executable(SiltStriderFollowerSpotTest
    mwworld/FollowerSpotTest.cpp
    mwworld/followerspot.cpp
)
target_include_directories(SiltStriderFollowerSpotTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwworld)
target_link_libraries(SiltStriderFollowerSpotTest ${OSG_LIBRARIES} ${OPENTHREADS_LIBRARIES})

# Start of tes3mp addition
# objects over frames (mwmp/CellStagger.hpp): class order, per-frame budget, the half-second drain, flush and cancel of a
# named ref, drop on leaving the cell. Standard library only.
add_executable(SiltStriderCellStaggerTest
    mwmp/CellStaggerTest.cpp
)
target_include_directories(SiltStriderCellStaggerTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
# End of tes3mp addition

# Start of tes3mp addition
# (mwmp/DeferredInsert.hpp). Standard library only.
add_executable(SiltStriderDeferredInsertTest
    mwmp/DeferredInsertTest.cpp
)
target_include_directories(SiltStriderDeferredInsertTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
# End of tes3mp addition

# Start of tes3mp addition
# (mwmp/GoldPileRules.hpp). Standard library only.
add_executable(SiltStriderGoldPileRulesTest
    mwmp/GoldPileRulesTest.cpp
)
target_include_directories(SiltStriderGoldPileRulesTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
# End of tes3mp addition

# Start of tes3mp addition
# (mwmp/ContainerRowEquip.hpp). Standard library only.
add_executable(SiltStriderContainerRowEquipTest
    mwmp/ContainerRowEquipTest.cpp
)
target_include_directories(SiltStriderContainerRowEquipTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
# End of tes3mp addition

# checks that autoEquip's trial cuts of a stack are put back together unless the settled outfit
# wears one of them (mwworld/trialsplits.hpp), and that a take from a companion's pack is never more
# than the stack holds now (mwgui/companiontransfer.hpp). Both header only, standard library only.
add_executable(SiltStriderTrialSplitTest
    mwworld/TrialSplitsTest.cpp
)
target_include_directories(SiltStriderTrialSplitTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwworld)

# Start of tes3mp addition
# The infinite fall failsafe (mwworld/voidfall.hpp, upstream OpenMW b43c7238e9 + e1cfd46f87) - its rules, and source
# checks on mwworld/scene.cpp and on mwmp/LocalPlayer.cpp (a server-set position lands the player). Header only,
# standard library. The server repo's tools/tests/void-fall.lua runs it.
add_executable(SiltStriderVoidFallTest
    mwworld/VoidFallTest.cpp
)
# End of tes3mp addition

# Start of tes3mp addition
# The async physics workers' hand-shake with the main thread (mwphysics/workerssync.hpp, upstream OpenMW 0040da3497) -
# WorkersSync itself, a model of the scheduler's locks and barriers run for many frames under a stall watchdog, and source
# checks on mtphysics.cpp. Header only, standard library and Misc::Barrier. The server repo's
# tools/tests/physics-workers-sync.lua runs it.
add_executable(SiltStriderPhysicsSyncTest
    mwphysics/PhysicsSyncTest.cpp
)
target_include_directories(SiltStriderPhysicsSyncTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwphysics ${CMAKE_SOURCE_DIR})
target_link_libraries(SiltStriderPhysicsSyncTest ${CMAKE_THREAD_LIBS_INIT})
# End of tes3mp addition

# CollisionProof (the old server's TES3MP_COLLISION_SELFTEST): a Bullet collision world with a
# LAND-style double-precision heightfield and a box answers the ground-snap and line-of-sight
# raycasts. Links components for Bullet and its BT_USE_DOUBLE_PRECISION definition, so /MD like the
# tests above.
add_executable(SiltStriderCollisionProofTest
    mwphysics/CollisionProofTest.cpp
)
target_link_libraries(SiltStriderCollisionProofTest components)

# Start of tes3mp addition
# What drawing a furnished house costs, measured on the real meshes offline; builds the batches without a world.
add_executable(SiltStriderPlacedInstancingTest
    mwrender/PlacedInstancingTest.cpp
    mwrender/placedbatchbuild.cpp
)
target_include_directories(SiltStriderPlacedInstancingTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwrender)
target_link_libraries(SiltStriderPlacedInstancingTest components)
# End of tes3mp addition

# Start of tes3mp addition
# tools/tests/custom-heads.lua runs it.
add_executable(SiltStriderLiveAssetsTest
    mwmp/LiveAssetsTest.cpp
    mwmp/LiveAssetsBundle.cpp
)
target_include_directories(SiltStriderLiveAssetsTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
# End of tes3mp addition

# Links components for the gzip and the content updater's HTTP client, so /MD like the test above.
# (The reporter's own files build in the tes3mp-content library, in mwmp/content, because they are
# plain Win32.)
add_executable(SiltStriderCrashReportTest
    mwmp/CrashReportTest.cpp
    mwmp/GUI/BugReportUpload.cpp
)
target_include_directories(SiltStriderCrashReportTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/mwmp)
target_link_libraries(SiltStriderCrashReportTest tes3mp-content components)
if (UNIX)
    target_link_libraries(SiltStriderCrashReportTest pthread)
endif()
# End of tes3mp addition

if (BUILD_WITH_CODE_COVERAGE)
    target_compile_options(openmw-lib PRIVATE --coverage)
    target_link_libraries(openmw-lib gcov)
    if (NOT ANDROID AND BUILD_OPENMW)
        target_compile_options(openmw PRIVATE --coverage)
        target_link_libraries(openmw gcov)
    endif()
endif()

if (WIN32 AND BUILD_OPENMW)
    INSTALL(TARGETS openmw RUNTIME DESTINATION ".")
endif()
