2026-04-05 12:27:35 +03:00
|
|
|
# Unit test infrastructure using Catch2 v3 (amalgamated)
|
2026-04-03 09:41:34 +03:00
|
|
|
|
|
|
|
|
# Catch2 amalgamated as a library target
|
|
|
|
|
add_library(catch2_main STATIC
|
|
|
|
|
${CMAKE_SOURCE_DIR}/extern/catch2/catch_amalgamated.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(catch2_main PUBLIC
|
|
|
|
|
${CMAKE_SOURCE_DIR}/extern/catch2
|
|
|
|
|
)
|
|
|
|
|
# Catch2 v3 needs C++17 minimum
|
|
|
|
|
target_compile_features(catch2_main PUBLIC cxx_std_17)
|
|
|
|
|
|
|
|
|
|
# ── ASAN / UBSan propagation ────────────────────────────────
|
|
|
|
|
# Collect all test target names so we can apply sanitizer flags at the end.
|
|
|
|
|
set(ALL_TEST_TARGETS "")
|
|
|
|
|
|
|
|
|
|
# Helper: register a test target for ASAN/UBSan if enabled.
|
|
|
|
|
macro(register_test_target _target)
|
|
|
|
|
list(APPEND ALL_TEST_TARGETS ${_target})
|
|
|
|
|
endmacro()
|
|
|
|
|
|
|
|
|
|
# Shared source files used across multiple tests
|
|
|
|
|
set(TEST_COMMON_SOURCES
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/core/logger.cpp
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Include directories matching the main target
|
|
|
|
|
set(TEST_INCLUDE_DIRS
|
|
|
|
|
${CMAKE_SOURCE_DIR}/include
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src
|
|
|
|
|
)
|
|
|
|
|
set(TEST_SYSTEM_INCLUDE_DIRS
|
|
|
|
|
${CMAKE_SOURCE_DIR}/extern
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# ── test_packet ──────────────────────────────────────────────
|
|
|
|
|
add_executable(test_packet
|
|
|
|
|
test_packet.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/network/packet.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_packet PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_packet SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_packet PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME packet COMMAND test_packet)
|
|
|
|
|
register_test_target(test_packet)
|
|
|
|
|
|
|
|
|
|
# ── test_srp ─────────────────────────────────────────────────
|
|
|
|
|
add_executable(test_srp
|
|
|
|
|
test_srp.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/auth/srp.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/auth/big_num.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/auth/crypto.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_srp PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_srp SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_srp PRIVATE catch2_main OpenSSL::SSL OpenSSL::Crypto)
|
|
|
|
|
add_test(NAME srp COMMAND test_srp)
|
|
|
|
|
register_test_target(test_srp)
|
|
|
|
|
|
refactor: extract spline math, consolidate packet parsing, decompose TransportManager
Extract CatmullRomSpline (include/math/spline.hpp, src/math/spline.cpp) as a
standalone, immutable, thread-safe spline module with O(log n) binary segment
search and fused position+tangent evaluation — replacing the duplicated O(n)
evalTimedCatmullRom/orientationFromTangent pair in TransportManager.
Consolidate 7 copies of spline packet parsing into shared functions in
game/spline_packet.{hpp,cpp}: parseMonsterMoveSplineBody (WotLK/TBC),
parseMonsterMoveSplineBodyVanilla, parseClassicMoveUpdateSpline,
parseWotlkMoveUpdateSpline, and decodePackedDelta. Named SplineFlag constants
replace magic hex literals throughout.
Extract TransportPathRepository (game/transport_path_repository.{hpp,cpp}) from
TransportManager — owns path data, DBC loading, and path inference. Paths stored
as PathEntry wrapping CatmullRomSpline + metadata (zOnly, fromDBC, worldCoords).
TransportManager reduced from ~1200 to ~500 lines, focused on transport lifecycle
and server sync.
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-11 08:30:28 +03:00
|
|
|
# ── test_spline ──────────────────────────────────────────────
|
|
|
|
|
add_executable(test_spline
|
|
|
|
|
test_spline.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/math/spline.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_spline PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_spline SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_spline PRIVATE catch2_main)
|
2026-04-11 10:11:47 +03:00
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_spline PRIVATE glm::glm)
|
|
|
|
|
endif()
|
refactor: extract spline math, consolidate packet parsing, decompose TransportManager
Extract CatmullRomSpline (include/math/spline.hpp, src/math/spline.cpp) as a
standalone, immutable, thread-safe spline module with O(log n) binary segment
search and fused position+tangent evaluation — replacing the duplicated O(n)
evalTimedCatmullRom/orientationFromTangent pair in TransportManager.
Consolidate 7 copies of spline packet parsing into shared functions in
game/spline_packet.{hpp,cpp}: parseMonsterMoveSplineBody (WotLK/TBC),
parseMonsterMoveSplineBodyVanilla, parseClassicMoveUpdateSpline,
parseWotlkMoveUpdateSpline, and decodePackedDelta. Named SplineFlag constants
replace magic hex literals throughout.
Extract TransportPathRepository (game/transport_path_repository.{hpp,cpp}) from
TransportManager — owns path data, DBC loading, and path inference. Paths stored
as PathEntry wrapping CatmullRomSpline + metadata (zOnly, fromDBC, worldCoords).
TransportManager reduced from ~1200 to ~500 lines, focused on transport lifecycle
and server sync.
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-11 08:30:28 +03:00
|
|
|
add_test(NAME spline COMMAND test_spline)
|
|
|
|
|
register_test_target(test_spline)
|
|
|
|
|
|
|
|
|
|
# ── test_transport_path_repo ─────────────────────────────────
|
|
|
|
|
add_executable(test_transport_path_repo
|
|
|
|
|
test_transport_path_repo.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/game/transport_path_repository.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/math/spline.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/dbc_loader.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_transport_path_repo PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_transport_path_repo SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_transport_path_repo PRIVATE catch2_main)
|
2026-04-11 10:11:47 +03:00
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_transport_path_repo PRIVATE glm::glm)
|
|
|
|
|
endif()
|
refactor: extract spline math, consolidate packet parsing, decompose TransportManager
Extract CatmullRomSpline (include/math/spline.hpp, src/math/spline.cpp) as a
standalone, immutable, thread-safe spline module with O(log n) binary segment
search and fused position+tangent evaluation — replacing the duplicated O(n)
evalTimedCatmullRom/orientationFromTangent pair in TransportManager.
Consolidate 7 copies of spline packet parsing into shared functions in
game/spline_packet.{hpp,cpp}: parseMonsterMoveSplineBody (WotLK/TBC),
parseMonsterMoveSplineBodyVanilla, parseClassicMoveUpdateSpline,
parseWotlkMoveUpdateSpline, and decodePackedDelta. Named SplineFlag constants
replace magic hex literals throughout.
Extract TransportPathRepository (game/transport_path_repository.{hpp,cpp}) from
TransportManager — owns path data, DBC loading, and path inference. Paths stored
as PathEntry wrapping CatmullRomSpline + metadata (zOnly, fromDBC, worldCoords).
TransportManager reduced from ~1200 to ~500 lines, focused on transport lifecycle
and server sync.
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-11 08:30:28 +03:00
|
|
|
add_test(NAME transport_path_repo COMMAND test_transport_path_repo)
|
|
|
|
|
register_test_target(test_transport_path_repo)
|
|
|
|
|
|
2026-04-03 09:41:34 +03:00
|
|
|
# ── test_opcode_table ────────────────────────────────────────
|
|
|
|
|
add_executable(test_opcode_table
|
|
|
|
|
test_opcode_table.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/game/opcode_table.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_opcode_table PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_opcode_table SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_opcode_table PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME opcode_table COMMAND test_opcode_table)
|
|
|
|
|
register_test_target(test_opcode_table)
|
|
|
|
|
|
|
|
|
|
# ── test_entity ──────────────────────────────────────────────
|
|
|
|
|
add_executable(test_entity
|
|
|
|
|
test_entity.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/game/entity.cpp
|
2026-04-11 09:50:38 +03:00
|
|
|
${CMAKE_SOURCE_DIR}/src/math/spline.cpp
|
2026-04-03 09:41:34 +03:00
|
|
|
)
|
|
|
|
|
target_include_directories(test_entity PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_entity SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_entity PRIVATE catch2_main)
|
2026-04-11 10:11:47 +03:00
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_entity PRIVATE glm::glm)
|
|
|
|
|
endif()
|
2026-04-03 09:41:34 +03:00
|
|
|
add_test(NAME entity COMMAND test_entity)
|
|
|
|
|
register_test_target(test_entity)
|
|
|
|
|
|
|
|
|
|
# ── test_dbc_loader ──────────────────────────────────────────
|
|
|
|
|
add_executable(test_dbc_loader
|
|
|
|
|
test_dbc_loader.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/dbc_loader.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_dbc_loader PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_dbc_loader SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_dbc_loader PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME dbc_loader COMMAND test_dbc_loader)
|
|
|
|
|
register_test_target(test_dbc_loader)
|
|
|
|
|
|
|
|
|
|
# ── test_m2_structs ──────────────────────────────────────────
|
|
|
|
|
# Header-only struct layout tests — no source files needed
|
|
|
|
|
add_executable(test_m2_structs
|
|
|
|
|
test_m2_structs.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_m2_structs PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_m2_structs SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_m2_structs PRIVATE catch2_main)
|
2026-04-03 19:49:30 +03:00
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_m2_structs PRIVATE glm::glm)
|
|
|
|
|
endif()
|
2026-04-03 09:41:34 +03:00
|
|
|
add_test(NAME m2_structs COMMAND test_m2_structs)
|
|
|
|
|
register_test_target(test_m2_structs)
|
|
|
|
|
|
|
|
|
|
# ── test_blp_loader ──────────────────────────────────────────
|
|
|
|
|
add_executable(test_blp_loader
|
|
|
|
|
test_blp_loader.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/blp_loader.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_blp_loader PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_blp_loader SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_blp_loader PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME blp_loader COMMAND test_blp_loader)
|
|
|
|
|
register_test_target(test_blp_loader)
|
|
|
|
|
|
|
|
|
|
# ── test_frustum ─────────────────────────────────────────────
|
|
|
|
|
add_executable(test_frustum
|
|
|
|
|
test_frustum.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/frustum.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_frustum PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_frustum SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_frustum PRIVATE catch2_main)
|
2026-04-03 19:49:30 +03:00
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_frustum PRIVATE glm::glm)
|
|
|
|
|
endif()
|
2026-04-03 09:41:34 +03:00
|
|
|
add_test(NAME frustum COMMAND test_frustum)
|
|
|
|
|
register_test_target(test_frustum)
|
|
|
|
|
|
feat(animation): 452 named constants, 30-phase character animation state machine
Add animation_ids.hpp/cpp with all 452 WoW animation ID constants (anim::STAND,
anim::RUN, anim::FIRE_BOW, ... anim::FLY_BACKWARDS, etc.), nameFromId() O(1)
lookup, and flyVariant() compact 218-element ground→FLY_* resolver.
Expand AnimationController into a full state machine with 20+ named states:
spell cast (directed→omni→cast fallback chain, instant one-shot release),
hit reactions (WOUND/CRIT/DODGE/BLOCK/SHIELD_BLOCK), stun, wounded idle,
stealth animation substitution, loot, fishing channel, sit/sleep/kneel
down→loop→up transitions, sheathe/unsheathe combat enter/exit, ranged weapons
(BOW/GUN/CROSSBOW/THROWN with reload states), game object OPEN/CLOSE/DESTROY,
vehicle enter/exit, mount flight directionals (FLY_LEFT/RIGHT/UP/DOWN/BACKWARDS),
emote state variants, off-hand/pierce/dual-wield alternation, NPC
birth/spawn/drown/rise, sprint aura override, totem idle, NPC greeting/farewell.
Add spell_defines.hpp with SpellEffect (~45 constants) and SpellMissInfo
(12 constants) namespaces; replace all magic numbers in spell_handler.cpp.
Add GAMEOBJECT_BYTES_1 to update field table (all 4 expansion JSONs) and wire
GameObjectStateCallback. Add DBC cross-validation on world entry.
Expand tools/_ANIM_NAMES from ~35 to 452 entries in m2_viewer.py and
asset_pipeline_gui.py. Add tests/test_animation_ids.cpp.
Bug fixes included:
- Stand state 1 was animating READY_2H(27) — fixed to SITTING(97)
- Spell casts ended freeze-frame — add one-shot release animation
- NPC 2H swing probe chain missing ATTACK_2H_LOOSE (polearm/staff)
- Chair sits (states 2/4/5/6) incorrectly played floor-sit transition
- STOP(3) used for all spell casts — replaced with model-aware chain
2026-04-04 23:02:53 +03:00
|
|
|
# ── test_animation_ids ───────────────────────────────────────
|
|
|
|
|
add_executable(test_animation_ids
|
|
|
|
|
test_animation_ids.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
2026-04-05 12:27:35 +03:00
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/animation/animation_ids.cpp
|
feat(animation): 452 named constants, 30-phase character animation state machine
Add animation_ids.hpp/cpp with all 452 WoW animation ID constants (anim::STAND,
anim::RUN, anim::FIRE_BOW, ... anim::FLY_BACKWARDS, etc.), nameFromId() O(1)
lookup, and flyVariant() compact 218-element ground→FLY_* resolver.
Expand AnimationController into a full state machine with 20+ named states:
spell cast (directed→omni→cast fallback chain, instant one-shot release),
hit reactions (WOUND/CRIT/DODGE/BLOCK/SHIELD_BLOCK), stun, wounded idle,
stealth animation substitution, loot, fishing channel, sit/sleep/kneel
down→loop→up transitions, sheathe/unsheathe combat enter/exit, ranged weapons
(BOW/GUN/CROSSBOW/THROWN with reload states), game object OPEN/CLOSE/DESTROY,
vehicle enter/exit, mount flight directionals (FLY_LEFT/RIGHT/UP/DOWN/BACKWARDS),
emote state variants, off-hand/pierce/dual-wield alternation, NPC
birth/spawn/drown/rise, sprint aura override, totem idle, NPC greeting/farewell.
Add spell_defines.hpp with SpellEffect (~45 constants) and SpellMissInfo
(12 constants) namespaces; replace all magic numbers in spell_handler.cpp.
Add GAMEOBJECT_BYTES_1 to update field table (all 4 expansion JSONs) and wire
GameObjectStateCallback. Add DBC cross-validation on world entry.
Expand tools/_ANIM_NAMES from ~35 to 452 entries in m2_viewer.py and
asset_pipeline_gui.py. Add tests/test_animation_ids.cpp.
Bug fixes included:
- Stand state 1 was animating READY_2H(27) — fixed to SITTING(97)
- Spell casts ended freeze-frame — add one-shot release animation
- NPC 2H swing probe chain missing ATTACK_2H_LOOSE (polearm/staff)
- Chair sits (states 2/4/5/6) incorrectly played floor-sit transition
- STOP(3) used for all spell casts — replaced with model-aware chain
2026-04-04 23:02:53 +03:00
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/dbc_loader.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_animation_ids PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_animation_ids SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_animation_ids PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME animation_ids COMMAND test_animation_ids)
|
|
|
|
|
register_test_target(test_animation_ids)
|
|
|
|
|
|
2026-04-05 12:27:35 +03:00
|
|
|
# ── test_locomotion_fsm ──────────────────────────────────────
|
|
|
|
|
add_executable(test_locomotion_fsm
|
|
|
|
|
test_locomotion_fsm.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/animation/locomotion_fsm.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_locomotion_fsm PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_locomotion_fsm SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_locomotion_fsm PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME locomotion_fsm COMMAND test_locomotion_fsm)
|
|
|
|
|
register_test_target(test_locomotion_fsm)
|
|
|
|
|
|
|
|
|
|
# ── test_combat_fsm ──────────────────────────────────────────
|
|
|
|
|
add_executable(test_combat_fsm
|
|
|
|
|
test_combat_fsm.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/animation/combat_fsm.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_combat_fsm PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_combat_fsm SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_combat_fsm PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME combat_fsm COMMAND test_combat_fsm)
|
|
|
|
|
register_test_target(test_combat_fsm)
|
|
|
|
|
|
|
|
|
|
# ── test_activity_fsm ────────────────────────────────────────
|
|
|
|
|
add_executable(test_activity_fsm
|
|
|
|
|
test_activity_fsm.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/animation/activity_fsm.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_activity_fsm PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_activity_fsm SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_activity_fsm PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME activity_fsm COMMAND test_activity_fsm)
|
|
|
|
|
register_test_target(test_activity_fsm)
|
|
|
|
|
|
|
|
|
|
# NPC animator tests removed — NpcAnimator replaced by generic CharacterAnimator
|
|
|
|
|
|
|
|
|
|
# ── test_anim_capability ─────────────────────────────────────
|
|
|
|
|
# Header-only struct tests — no source files needed
|
|
|
|
|
add_executable(test_anim_capability
|
|
|
|
|
test_anim_capability.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_anim_capability PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_anim_capability SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_anim_capability PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME anim_capability COMMAND test_anim_capability)
|
|
|
|
|
register_test_target(test_anim_capability)
|
|
|
|
|
|
feat(rendering): add HiZ occlusion culling & fix WMO interior shadows
Implement GPU-driven Hierarchical-Z occlusion culling for M2 doodads
using a depth pyramid built from the previous frame's depth buffer.
The cull shader projects bounding spheres via prevViewProj (temporal
reprojection) and samples the HiZ pyramid to reject hidden objects
before the main render pass.
Key implementation details:
- Separate early compute submission (beginSingleTimeCommands + fence
wait) eliminates 2-frame visibility staleness
- Conservative safeguards prevent false culls: screen-edge guard,
full VP row-vector AABB projection (Cauchy-Schwarz), 50% sphere
inflation, depth bias, mip+1, min screen size threshold, camera
motion dampening (auto-disable on fast rotations), and per-instance
previouslyVisible flag tracking
- Graceful fallback to frustum-only culling if HiZ init fails
Fix dark WMO interiors by gating shadow map sampling on isInterior==0
in the WMO fragment shader. Interior groups (flag 0x2000) now rely
solely on pre-baked MOCV vertex-color lighting + MOHD ambient color.
Disable interiorDarken globally (was incorrectly darkening outdoor M2s
when camera was inside a WMO). Use isInsideInteriorWMO() instead of
isInsideWMO() for correct indoor detection.
New files:
- hiz_system.hpp/cpp: pyramid image management, compute pipeline,
descriptors, mip-chain build dispatch, resize handling
- hiz_build.comp.glsl: MAX-depth 2x2 reduction compute shader
- m2_cull_hiz.comp.glsl: frustum + HiZ occlusion cull compute shader
- test_indoor_shadows.cpp: 14 unit tests for shadow/interior contracts
Modified:
- CullUniformsGPU expanded 128->272 bytes (HiZ params, viewProj,
prevViewProj)
- Depth buffer images gain VK_IMAGE_USAGE_SAMPLED_BIT for HiZ reads
- wmo.frag.glsl: interior branch before unlit, shadow skip for 0x2000
- Render graph: hiz_build + compute_cull disabled (run in early compute)
- .gitignore: ignore compiled .spv binaries
- MEGA_BONE_MAX_INSTANCES: 2048 -> 4096
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-06 16:40:59 +03:00
|
|
|
# ── test_indoor_shadows ──────────────────────────────────────
|
|
|
|
|
add_executable(test_indoor_shadows
|
|
|
|
|
test_indoor_shadows.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_indoor_shadows PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_indoor_shadows SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_indoor_shadows PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_indoor_shadows PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME indoor_shadows COMMAND test_indoor_shadows)
|
|
|
|
|
register_test_target(test_indoor_shadows)
|
|
|
|
|
|
2026-04-11 09:50:38 +03:00
|
|
|
# ── test_transport_components ────────────────────────────────
|
|
|
|
|
add_executable(test_transport_components
|
|
|
|
|
test_transport_components.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/game/transport_clock_sync.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/game/transport_animator.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/math/spline.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_transport_components PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_transport_components SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_transport_components PRIVATE catch2_main)
|
2026-04-11 10:11:47 +03:00
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_transport_components PRIVATE glm::glm)
|
|
|
|
|
endif()
|
2026-04-11 09:50:38 +03:00
|
|
|
add_test(NAME transport_components COMMAND test_transport_components)
|
|
|
|
|
register_test_target(test_transport_components)
|
|
|
|
|
|
refactor: decompose world map into modular component architecture
Break the monolithic 1360-line world_map.cpp into 16 focused modules
under src/rendering/world_map/:
Architecture:
- world_map_facade: public API composing all components (PIMPL)
- world_map_types: Vulkan-free domain types (Zone, ViewLevel, etc.)
- data_repository: DBC zone loading, ZMP pixel map, POI/overlay storage
- coordinate_projection: UV projection, zone/continent lookups
- composite_renderer: Vulkan tile pipeline + off-screen compositing
- exploration_state: server mask + local exploration tracking
- view_state_machine: COSMIC→WORLD→CONTINENT→ZONE navigation
- input_handler: keyboard/mouse input → InputAction mapping
- overlay_renderer: layer-based ImGui overlay system (OCP)
- map_resolver: cross-map navigation (Outland, Northrend, etc.)
- zone_metadata: level ranges and faction data
Overlay layers (each an IOverlayLayer):
- player_marker, party_dot, taxi_node, poi_marker, quest_poi,
corpse_marker, zone_highlight, coordinate_display, subzone_tooltip
Fixes:
- Player marker no longer bleeds across continents (only shown when
player is in a zone belonging to the displayed continent)
- Zone hover uses DBC-projected AABB rectangles (restored from
original working behavior)
- Exploration overlay rendering for zone view subzones
Tests:
- 6 new test files covering coordinate projection, exploration state,
map resolver, view state machine, zone metadata, and integration
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 09:52:51 +03:00
|
|
|
# ── test_world_map ────────────────────────────────────────────
|
|
|
|
|
add_executable(test_world_map
|
|
|
|
|
test_world_map.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_world_map PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_world_map SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_world_map PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_world_map PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME world_map COMMAND test_world_map)
|
|
|
|
|
register_test_target(test_world_map)
|
|
|
|
|
|
|
|
|
|
# ── test_world_map_coordinate_projection ──────────────────────
|
|
|
|
|
add_executable(test_world_map_coordinate_projection
|
|
|
|
|
test_world_map_coordinate_projection.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/coordinate_projection.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_world_map_coordinate_projection PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_world_map_coordinate_projection SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_world_map_coordinate_projection PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_world_map_coordinate_projection PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME world_map_coordinate_projection COMMAND test_world_map_coordinate_projection)
|
|
|
|
|
register_test_target(test_world_map_coordinate_projection)
|
|
|
|
|
|
|
|
|
|
# ── test_world_map_map_resolver ───────────────────────────────
|
|
|
|
|
add_executable(test_world_map_map_resolver
|
|
|
|
|
test_world_map_map_resolver.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/map_resolver.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/coordinate_projection.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_world_map_map_resolver PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_world_map_map_resolver SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_world_map_map_resolver PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_world_map_map_resolver PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME world_map_map_resolver COMMAND test_world_map_map_resolver)
|
|
|
|
|
register_test_target(test_world_map_map_resolver)
|
|
|
|
|
|
|
|
|
|
# ── test_world_map_view_state_machine ─────────────────────────
|
|
|
|
|
add_executable(test_world_map_view_state_machine
|
|
|
|
|
test_world_map_view_state_machine.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/view_state_machine.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_world_map_view_state_machine PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_world_map_view_state_machine SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_world_map_view_state_machine PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_world_map_view_state_machine PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME world_map_view_state_machine COMMAND test_world_map_view_state_machine)
|
|
|
|
|
register_test_target(test_world_map_view_state_machine)
|
|
|
|
|
|
|
|
|
|
# ── test_world_map_exploration_state ──────────────────────────
|
|
|
|
|
add_executable(test_world_map_exploration_state
|
|
|
|
|
test_world_map_exploration_state.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/exploration_state.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/coordinate_projection.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_world_map_exploration_state PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_world_map_exploration_state SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_world_map_exploration_state PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_world_map_exploration_state PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME world_map_exploration_state COMMAND test_world_map_exploration_state)
|
|
|
|
|
register_test_target(test_world_map_exploration_state)
|
|
|
|
|
|
|
|
|
|
# ── test_world_map_zone_metadata ──────────────────────────────
|
|
|
|
|
add_executable(test_world_map_zone_metadata
|
|
|
|
|
test_world_map_zone_metadata.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/world_map/zone_metadata.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_world_map_zone_metadata PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_world_map_zone_metadata SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_world_map_zone_metadata PRIVATE catch2_main)
|
|
|
|
|
if(TARGET glm::glm)
|
|
|
|
|
target_link_libraries(test_world_map_zone_metadata PRIVATE glm::glm)
|
|
|
|
|
endif()
|
|
|
|
|
add_test(NAME world_map_zone_metadata COMMAND test_world_map_zone_metadata)
|
|
|
|
|
register_test_target(test_world_map_zone_metadata)
|
|
|
|
|
|
refactor(chat): decompose into modular architecture, add GM commands, fix protocol
- Extract ChatPanel monolith into 15+ focused modules under ui/chat/
(ChatInput, ChatTabManager, ChatTabCompleter, ChatMarkupParser,
ChatMarkupRenderer, ChatCommandRegistry, ChatBubbleManager,
ChatSettings, MacroEvaluator, GameStateAdapter, InputModifierAdapter)
- Split 2700-line chat_panel_commands.cpp into 11 command modules
- Add GM command handling: 190-command data table, dot-prefix interception,
tab-completion, /gmhelp with category filter
- Fix ChatType enum to match WoW wire protocol (SAY=0x01 not 0x00);
values 0x00-0x1B shared across Vanilla/TBC/WotLK
- Fix BG_SYSTEM_* values from 82-84 (UB in bitmask shifts) to 0x24-0x26
- Fix infinite Enter key loop after teleport (disable TOGGLE_CHAT repeat,
add 2-frame input cooldown)
- Add tests: chat_markup_parser, chat_tab_completer, gm_commands,
macro_evaluator
Signed-off-by: Pavel Okhlopkov <pavel.okhlopkov@flant.com>
2026-04-12 14:59:56 +03:00
|
|
|
# ── test_chat_markup_parser ──────────────────────────────────
|
|
|
|
|
add_executable(test_chat_markup_parser
|
|
|
|
|
test_chat_markup_parser.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/ui/chat/chat_markup_parser.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_chat_markup_parser PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_chat_markup_parser SYSTEM PRIVATE
|
|
|
|
|
${TEST_SYSTEM_INCLUDE_DIRS}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/extern/imgui
|
|
|
|
|
)
|
|
|
|
|
target_link_libraries(test_chat_markup_parser PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME chat_markup_parser COMMAND test_chat_markup_parser)
|
|
|
|
|
register_test_target(test_chat_markup_parser)
|
|
|
|
|
|
|
|
|
|
# ── test_macro_evaluator ─────────────────────────────────────
|
|
|
|
|
add_executable(test_macro_evaluator
|
|
|
|
|
test_macro_evaluator.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/ui/chat/macro_evaluator.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_macro_evaluator PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_macro_evaluator SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_macro_evaluator PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME macro_evaluator COMMAND test_macro_evaluator)
|
|
|
|
|
register_test_target(test_macro_evaluator)
|
|
|
|
|
|
|
|
|
|
# ── test_chat_tab_completer ──────────────────────────────────
|
|
|
|
|
add_executable(test_chat_tab_completer
|
|
|
|
|
test_chat_tab_completer.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/ui/chat/chat_tab_completer.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_chat_tab_completer PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_chat_tab_completer SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_chat_tab_completer PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME chat_tab_completer COMMAND test_chat_tab_completer)
|
|
|
|
|
register_test_target(test_chat_tab_completer)
|
|
|
|
|
|
|
|
|
|
# ── test_gm_commands ─────────────────────────────────────────
|
|
|
|
|
add_executable(test_gm_commands
|
|
|
|
|
test_gm_commands.cpp
|
|
|
|
|
${TEST_COMMON_SOURCES}
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_gm_commands PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_gm_commands SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_gm_commands PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME gm_commands COMMAND test_gm_commands)
|
|
|
|
|
register_test_target(test_gm_commands)
|
|
|
|
|
|
2026-05-05 14:49:05 -07:00
|
|
|
# ── test_open_formats ────────────────────────────────────────
|
|
|
|
|
add_executable(test_open_formats
|
|
|
|
|
test_open_formats.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/wowee_building.cpp
|
2026-05-05 15:23:58 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/wowee_collision.cpp
|
2026-05-05 14:49:05 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/wowee_terrain_loader.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/pipeline/wmo_loader.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/core/logger.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_open_formats PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_open_formats SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_open_formats PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME open_formats COMMAND test_open_formats)
|
|
|
|
|
register_test_target(test_open_formats)
|
|
|
|
|
|
2026-05-06 08:58:55 -07:00
|
|
|
# ── test_camera ──────────────────────────────────────────────
|
|
|
|
|
add_executable(test_camera
|
|
|
|
|
test_camera.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/rendering/camera.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/src/core/logger.cpp
|
|
|
|
|
)
|
|
|
|
|
target_include_directories(test_camera PRIVATE ${TEST_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(test_camera SYSTEM PRIVATE ${TEST_SYSTEM_INCLUDE_DIRS})
|
|
|
|
|
target_link_libraries(test_camera PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME camera COMMAND test_camera)
|
|
|
|
|
register_test_target(test_camera)
|
|
|
|
|
|
2026-05-06 07:49:26 -07:00
|
|
|
# ── test_editor_units (SQL escape, quest validation, …) ─────
|
|
|
|
|
add_executable(test_editor_units
|
|
|
|
|
test_editor_units.cpp
|
2026-05-06 07:47:58 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor/sql_exporter.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor/npc_spawner.cpp
|
|
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor/quest_editor.cpp
|
2026-05-06 08:03:02 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor/content_pack.cpp
|
2026-05-06 08:05:43 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor/editor_brush.cpp
|
2026-05-06 09:40:06 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor/object_placer.cpp
|
2026-05-06 07:47:58 -07:00
|
|
|
${CMAKE_SOURCE_DIR}/src/core/logger.cpp
|
|
|
|
|
)
|
2026-05-06 07:49:26 -07:00
|
|
|
target_include_directories(test_editor_units PRIVATE
|
2026-05-06 07:47:58 -07:00
|
|
|
${TEST_INCLUDE_DIRS}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/tools/editor
|
|
|
|
|
)
|
2026-05-06 07:49:26 -07:00
|
|
|
target_include_directories(test_editor_units SYSTEM PRIVATE
|
2026-05-06 07:47:58 -07:00
|
|
|
${TEST_SYSTEM_INCLUDE_DIRS}
|
|
|
|
|
${CMAKE_SOURCE_DIR}/extern/nlohmann
|
|
|
|
|
)
|
2026-05-06 07:49:26 -07:00
|
|
|
target_link_libraries(test_editor_units PRIVATE catch2_main)
|
|
|
|
|
add_test(NAME editor_units COMMAND test_editor_units)
|
|
|
|
|
register_test_target(test_editor_units)
|
2026-05-06 07:47:58 -07:00
|
|
|
|
2026-04-03 09:41:34 +03:00
|
|
|
# ── ASAN / UBSan for test targets ────────────────────────────
|
|
|
|
|
if(WOWEE_ENABLE_ASAN AND NOT MSVC)
|
|
|
|
|
foreach(_t IN LISTS ALL_TEST_TARGETS)
|
|
|
|
|
target_compile_options(${_t} PRIVATE -fsanitize=address,undefined -fno-omit-frame-pointer)
|
|
|
|
|
target_link_options(${_t} PRIVATE -fsanitize=address,undefined)
|
|
|
|
|
endforeach()
|
|
|
|
|
# catch2_main must also be compiled with the same flags
|
|
|
|
|
target_compile_options(catch2_main PRIVATE -fsanitize=address,undefined -fno-omit-frame-pointer)
|
|
|
|
|
target_link_options(catch2_main PRIVATE -fsanitize=address,undefined)
|
|
|
|
|
message(STATUS "Test targets: ASAN + UBSan ENABLED")
|
|
|
|
|
endif()
|