-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
911 lines (824 loc) · 42.6 KB
/
Copy pathCMakeLists.txt
File metadata and controls
911 lines (824 loc) · 42.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
cmake_minimum_required(VERSION 3.21)
project(GalaxyEggbert LANGUAGES C CXX)
include(CTest)
message(STATUS "Project: ${PROJECT_NAME}")
message(STATUS "Platform: ${CMAKE_SYSTEM_NAME}")
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
if(NOT WIN32 AND CMAKE_BINARY_DIR MATCHES "build-windows")
message(WARNING "Building in 'build-windows' directory, but WIN32 is not set. "
"Make sure you used -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64.cmake "
"on a CLEAN build directory.")
endif()
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Engine-independent shared sources (no CNA/Easy3D dependencies).
# Shared by the game target and the engine-agnostic test suite.
set(GE_SHARED_SOURCES
src/GalaxyEggbert/Worlds/BinaryIO.cpp
src/GalaxyEggbert/Worlds/BitPacking.cpp
src/GalaxyEggbert/Worlds/Chunk.cpp
src/GalaxyEggbert/Worlds/World.cpp
src/GalaxyEggbert/MoveObjectRecord.cpp
src/GalaxyEggbert/BigDecorRecord.cpp
src/GalaxyEggbert/BlockDefinitionRegistry.cpp
)
# =============================================================================
# Direct CNA + Easy3D target — GalaxyEggbertCNA (long-term direction, see CLAUDE.md
# "Current Direction Lock")
#
# ON by default; a plain `cmake -S . -B build` configures the maintained
# playable game, including terrain, objects, gameplay, HUD, sound, menus,
# persistence, and the in-game 3D editor. See CURRENT.md for verified status
# and easy3d.md/plan.md for the original migration analysis and task history.
#
# Build with:
# cmake -S . -B build-cna -DGALAXY_EGGBERT_BUILD_CNA=ON
# cmake --build build-cna --target GalaxyEggbertCNA
# =============================================================================
option(GALAXY_EGGBERT_BUILD_CNA "Build the direct CNA + Easy3D Galaxy Eggbert target (actively developed -- see CLAUDE.md)" ON)
if(GALAXY_EGGBERT_BUILD_CNA)
# Locate CNA and easy-3d: explicit option > sibling directory.
set(CNA_HOME "" CACHE PATH
"Path to the CNA source directory. Defaults to ../cna.")
if(NOT CNA_HOME)
set(CNA_HOME "${CMAKE_CURRENT_SOURCE_DIR}/../cna")
endif()
set(EASY3D_HOME "" CACHE PATH
"Path to the easy-3d source directory. Defaults to ../easy-3d.")
if(NOT EASY3D_HOME)
set(EASY3D_HOME "${CMAKE_CURRENT_SOURCE_DIR}/../easy-3d")
endif()
if(NOT EXISTS "${CNA_HOME}/CMakeLists.txt")
message(FATAL_ERROR
"CNA not found at '${CNA_HOME}'. Clone it there or set -DCNA_HOME=<path>.")
endif()
if(NOT EXISTS "${EASY3D_HOME}/CMakeLists.txt")
message(FATAL_ERROR
"easy-3d not found at '${EASY3D_HOME}'. Clone it there or set -DEASY3D_HOME=<path>.")
endif()
message(STATUS "CNA source: ${CNA_HOME}")
message(STATUS "easy-3d source: ${EASY3D_HOME}")
# Prefer the build tree's normal incremental objects over a second copy
# in ccache. On this workstation ccache occupied 3.7 GiB while only
# 22.7% of cacheable calls were hits, so misses amplified SSD writes.
# This is an unforced fresh-build default: callers can still opt in with
# -DCNA_USE_CCACHE=ON, and an existing cache choice remains untouched.
set(CNA_USE_CCACHE OFF CACHE BOOL
"Use ccache for CNA and sharp-runtime builds when available")
# Default graphics renderer for GalaxyEggbertCNA -- the EasyGL family
# (2026-07-18, user request: make EasyGL the strongest/default backend,
# while keeping the other renderers buildable for the future). Set BEFORE
# add_subdirectory(CNA_HOME) below runs CNA's own (unforced, so
# lower-priority) default `set(... CACHE ...)`. A plain (non-FORCE)
# `set(... CACHE ...)` only takes effect the FIRST time a cache variable is
# populated, so this still respects an explicit
# `-DCNA_GRAPHICS_RENDERER=...` on the configure command line or an
# existing build directory's cache -- it only changes the *default* for a
# fresh configure. Previously defaulted to VULKAN on native (2026-07-09, to
# compare the two backends) -- reverted after that session found a real
# Vulkan-only bug (missing NDC Y-flip in `../cna`'s SkinnedEffect shaders,
# plan.md `E3D-MIG-069`) that EasyGL never had, confirming EasyGL is the
# more reliable renderer for this project today.
#
# Renamed 2026-08-21 to follow `../cna`: the cache variable is now
# `CNA_GRAPHICS_RENDERER`, and "EASYGL" is no longer a public renderer
# name at all. EasyGL became an internal implementation family, selected
# through one of five public GL-profile identities -- OPENGLES2/OPENGLES3/
# OPENGL33 natively, WEBGL1/WEBGL2 under Emscripten (see
# ../cna/cmake/RendererSelection.cmake). OPENGLES3 and WEBGL2 are that
# file's own documented successors of the old "EASYGL" value on each
# platform, so they are what this project asks for. Vulkan and every other
# renderer stay fully buildable via an explicit
# `-DCNA_GRAPHICS_RENDERER=VULKAN` (etc.) -- a default choice only, not a
# removal of multi-renderer support.
if(EMSCRIPTEN)
set(_ge_default_cna_renderer "WEBGL2")
else()
set(_ge_default_cna_renderer "OPENGLES3")
endif()
set(CNA_GRAPHICS_RENDERER "${_ge_default_cna_renderer}" CACHE STRING
"CNA graphics renderer to use; OPENGLES3 (native) and WEBGL2 (Emscripten) select the EasyGL family. See ../cna/cmake/RendererSelection.cmake for the full identity list.")
# Add CNA first: easy-3d's own CMakeLists.txt auto-detects an existing
# `CNA` target from the parent project and links against it instead of
# building its own copy (see easy-3d/CMakeLists.txt "Resolve CNA linkage").
# Keep CNA's own tests/examples out of this build — we only need the library.
if(NOT TARGET CNA)
set(CNA_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(CNA_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory("${CNA_HOME}" CNA_dep)
endif()
# A CNA_BACKEND_* compile-definition shim used to live here (2026-07-17):
# easy-3d only forwarded that macro to its `easy3d` target inside its
# "build CNA myself" branch, so this project's reused-CNA path left CNA's
# own GraphicsBackendType.hpp without it and that header #error'd. Removed
# 2026-08-21: `../cna` deleted GraphicsBackendType.hpp along with the whole
# CNA_BACKEND_* macro family in the renderer rename, and `../easy-3d` no
# longer references those macros either, so the shim now defines a name
# nothing reads. Verified by grepping both sibling repositories rather than
# assumed from the build succeeding.
# Keep easy-3d's own tests/examples out of this build too.
set(EASY3D_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(EASY3D_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
if(NOT TARGET easy3d)
add_subdirectory("${EASY3D_HOME}" easy3d_dep)
endif()
add_executable(GalaxyEggbertCNA
src/GalaxyEggbertCNA/main.cpp
src/GalaxyEggbertCNA/GalaxyEggbertGame.cpp
src/GalaxyEggbert/Game/WorldRuntime.cpp
src/GalaxyEggbert/Game/TileAtlas.cpp
src/GalaxyEggbert/Game/TerrainRenderer.cpp
src/GalaxyEggbert/Game/TerrainAnimDivisor.cpp
src/GalaxyEggbert/Game/DirectionalCubeTiles.cpp
src/GalaxyEggbert/Game/SwatchUv.cpp
src/GalaxyEggbert/Game/InnerPillarBoxTiles.cpp
src/GalaxyEggbert/Game/ThinBarTiles.cpp
src/GalaxyEggbert/Game/InnerFlatPlateTiles.cpp
src/GalaxyEggbert/Game/PlateRotationMetadata.cpp
src/GalaxyEggbert/Game/BlupiController.cpp
src/GalaxyEggbert/Game/CameraShake.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
src/GalaxyEggbert/Game/Sound.cpp
src/GalaxyEggbert/Game/InteractionSystem.cpp
src/GalaxyEggbert/Game/Hud.cpp
src/GalaxyEggbert/Game/TrainingHints.cpp
src/GalaxyEggbert/Game/InputPad.cpp
src/GalaxyEggbert/Game/QuadBatch.cpp
src/GalaxyEggbert/Game/SaveData.cpp
src/GalaxyEggbert/Editor/WorldEditor.cpp
src/GalaxyEggbert/Editor/WorldEditorUpdate.cpp
src/GalaxyEggbert/Editor/VoxelRaycast.cpp
src/GalaxyEggbert/Editor/EditorHighlightRenderer.cpp
src/GalaxyEggbert/Editor/EditCommandStack.cpp
src/GalaxyEggbert/Editor/BoxRegion.cpp
src/GalaxyEggbert/Editor/PaletteCategories.cpp
src/GalaxyEggbert/Editor/EditorPalette.cpp
src/GalaxyEggbert/Editor/EditorPaletteLayout.cpp
src/GalaxyEggbert/Editor/EditorPaletteInput.cpp
src/GalaxyEggbert/Editor/EditorPaletteRenderer.cpp
src/GalaxyEggbert/Editor/CustomWorldStorage.cpp
src/GalaxyEggbert/Editor/EditorBrowserScreen.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(GalaxyEggbertCNA PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# `CNA` is an INTERFACE umbrella over the framework module libraries plus
# the selected renderer target (../cna/modules/CMakeLists.txt). Those
# archives really do reference each other in both directions -- a renderer
# implements IGraphicsRenderer while calling back into cna_graphics_core/
# cna_core/cna_math -- but `../cna` now declares those reverse edges on its
# own targets, so CMake repeats the archives on the final link line by
# itself and no manual linker group is needed here.
#
# This block used to wrap `-Wl,--start-group ... -Wl,--end-group` around a
# backend target name spelled out locally. That name
# (`cna_backend_graphics_easygl`) disappeared when `../cna` renamed its
# renderer targets to `cna_renderer_<family>`, and CMake passes an unknown
# link item through as a raw `-l` flag instead of failing the configure --
# so the stale name did not surface until `ld: cannot find
# -lcna_backend_graphics_easygl` at the very last build step. Do not
# reintroduce a renderer target name here: upstream has 49 renderer
# identities across 45 families, and `CNA` already carries whichever one
# CNA_GRAPHICS_RENDERER selected.
target_link_libraries(GalaxyEggbertCNA PRIVATE CNA SHARP_RUNTIME)
# CNA_GamerServices (Microsoft::Xna::Framework::GamerServices/*.cpp,
# includes AvatarRenderer's real-rendering extension) is a separate
# static library gated behind CNA_ENABLE_NET (default ON) -- see CNA's
# own CMakeLists.txt. Needed for the third-person placeholder model
# (NEXT.md §3, 2026-07-09), whose code unconditionally references
# AvatarRenderer/SkinnedModelEXT symbols (the std::filesystem::exists()
# guard in LoadContent() is a runtime check on avatars3d/ being present,
# not a way to avoid linking these symbols) -- if CNA_ENABLE_NET=OFF,
# this target fails to link, it does not gracefully degrade. TARGET
# check here just avoids a hard CMake configure-time error referencing a
# nonexistent target; CNA_ENABLE_NET defaults ON so this is the normal
# path in practice.
if(TARGET CNA_GamerServices)
target_link_libraries(GalaxyEggbertCNA PRIVATE CNA_GamerServices)
endif()
# Prefer the easy3d::easy3d alias if present.
if(TARGET easy3d::easy3d)
target_link_libraries(GalaxyEggbertCNA PRIVATE easy3d::easy3d)
else()
target_link_libraries(GalaxyEggbertCNA PRIVATE easy3d)
endif()
if(TARGET SDL3::SDL3main)
target_link_libraries(GalaxyEggbertCNA PRIVATE SDL3::SDL3main)
endif()
# A Windows build is a directly runnable bundle, not merely an .exe that
# works while the MinGW/SDL build environment remains on PATH. Keep the
# GCC/C++ runtime in the executable and use CNA's own helpers for the
# remaining thread and SDL DLLs. --allow-multiple-definition is the same
# MinGW static-libstdc++ workaround CNA applies to its own CnaTests:
# PE/COFF otherwise fails to coalesce std::type_info::operator==.
if(MINGW)
target_link_options(GalaxyEggbertCNA PRIVATE
-static-libgcc -static-libstdc++ -Wl,--allow-multiple-definition)
cna_copy_mingw_runtime(GalaxyEggbertCNA)
cna_copy_sdl_runtime(GalaxyEggbertCNA)
# CNA's generic helper looks for SDL3::SDL3 and its analogous aliases.
# This repository's Windows prebuilt exposes import libraries through
# package configuration without making those targets visible here.
# SDL3_DIR is nevertheless the same resolved package prefix used for
# linking, so use its bin/ directory as a safe, build-local fallback.
if(SDL3_DIR)
get_filename_component(_ge_windows_sdl_prefix "${SDL3_DIR}/../../.." ABSOLUTE)
foreach(_ge_windows_sdl_dll IN ITEMS SDL3.dll SDL3_image.dll SDL3_mixer.dll)
set(_ge_windows_sdl_dll_path
"${_ge_windows_sdl_prefix}/bin/${_ge_windows_sdl_dll}")
if(EXISTS "${_ge_windows_sdl_dll_path}")
add_custom_command(TARGET GalaxyEggbertCNA POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${_ge_windows_sdl_dll_path}"
$<TARGET_FILE_DIR:GalaxyEggbertCNA>
COMMENT "Copying ${_ge_windows_sdl_dll} next to GalaxyEggbertCNA"
VERBATIM)
endif()
endforeach()
endif()
endif()
# -------------------------------------------------------------------
# Runtime asset staging
#
# Runtime assets used by GalaxyEggbertCNA are source-tracked here. Stage
# only changed files after a relink. The old mobile-eggbert Content/
# copy rewrote ~462 MiB every time, including ~437 MiB of unused 4x
# artwork; the game only reads this repository's ~22 MiB Content tree.
# -------------------------------------------------------------------
function(ge_stage_runtime_directory sourceDirectory destinationName)
add_custom_command(TARGET GalaxyEggbertCNA POST_BUILD
COMMAND ${CMAKE_COMMAND}
"-DGE_COPY_SOURCE=${sourceDirectory}"
"-DGE_COPY_DESTINATION=$<TARGET_FILE_DIR:GalaxyEggbertCNA>/${destinationName}"
-P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyDirectoryIfDifferent.cmake"
COMMENT "Updating ${destinationName}/ runtime assets (changed files only)"
VERBATIM)
endfunction()
if(NOT EMSCRIPTEN AND NOT ANDROID AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Content")
ge_stage_runtime_directory("${CMAKE_CURRENT_SOURCE_DIR}/Content" "Content")
endif()
# galaxy-eggbert's own hand-authored 3D worlds (plan.md E3D-MIG-058) —
# committed to this repository and staged next to the executable.
if(NOT EMSCRIPTEN AND NOT ANDROID AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/worlds3d")
ge_stage_runtime_directory("${CMAKE_CURRENT_SOURCE_DIR}/worlds3d" "worlds3d")
endif()
# galaxy-eggbert's own 3D-specific textures (e.g. grass_top.png, icon 107 —
# NEXT.md §8 task 3). Same changed-files-only staging as worlds3d/ above.
if(NOT EMSCRIPTEN AND NOT ANDROID AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/textures3d")
ge_stage_runtime_directory("${CMAKE_CURRENT_SOURCE_DIR}/textures3d" "textures3d")
endif()
# Third-person-mode 3D character model(s) (NEXT.md §3, 2026-07-09) --
# loaded via CNA's ContentManager, whose RootDirectory is pointed at this
# directory in LoadContent(). Currently just a temporary
# placeholder (avatars3d/blupi_placeholder/, see its own README.md) until
# a real 3D Blupi model exists. Same copy-next-to-binary pattern as
# worlds3d//textures3d above.
if(NOT EMSCRIPTEN AND NOT ANDROID AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/avatars3d")
ge_stage_runtime_directory("${CMAKE_CURRENT_SOURCE_DIR}/avatars3d" "avatars3d")
endif()
# -------------------------------------------------------------------
# Emscripten (web) build (2026-07-17, user-requested prototype-for-web-
# publishing target). Every asset directory above is baked into the
# .wasm's virtual filesystem at link time via --preload-file instead of
# copied next to a native binary, since there is no "next to the
# binary" on the web. Only `Content/icons`, `Content/backgrounds`, and
# `Content/sounds` are preloaded from this repository's Content/ tree
# (not the full ~460MB directory) -- confirmed via direct grep that
# GalaxyEggbertCNA never reads `Content/icons4x/` or
# `Content/backgrounds4x/` (the 4x-scale variants in mobile-eggbert,
# ~437MB combined, are genuinely unused here), keeping the web download
# to a reasonable size (~25MB of assets).
# -------------------------------------------------------------------
if(EMSCRIPTEN)
set_target_properties(GalaxyEggbertCNA PROPERTIES SUFFIX ".html")
# CMake doesn't parse --shell-file/--pre-js out of target_link_options
# to discover them as link dependencies (they're just linker-flag
# strings to it) -- without LINK_DEPENDS, editing either file alone
# (no source touched) leaves `cmake --build` believing the target is
# already up to date and it silently keeps serving the OLD shell/
# pre-js baked into the previous .html/.js (found 2026-07-17: a
# shell-cna.html fix didn't take effect until a source file was
# touched to force a relink).
set_target_properties(GalaxyEggbertCNA PROPERTIES
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/web/shell-cna.html;${CMAKE_CURRENT_SOURCE_DIR}/cmake/web/pre.js")
target_link_options(GalaxyEggbertCNA PRIVATE
-sALLOW_MEMORY_GROWTH=1
-sINITIAL_MEMORY=268435456
-sNO_EXIT_RUNTIME=1
-sMIN_WEBGL_VERSION=2
-sMAX_WEBGL_VERSION=2
-sFULL_ES3=1
-lidbfs.js
"SHELL:--shell-file ${CMAKE_CURRENT_SOURCE_DIR}/cmake/web/shell-cna.html"
"SHELL:--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/cmake/web/pre.js"
)
foreach(_content_dir Content/icons Content/backgrounds Content/sounds)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_content_dir}")
target_link_options(GalaxyEggbertCNA PRIVATE
"SHELL:--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/${_content_dir}@/${_content_dir}")
else()
message(WARNING
"GalaxyEggbertCNA (web): ${_content_dir}/ not found at "
"'${CMAKE_CURRENT_SOURCE_DIR}/${_content_dir}'. The web build will still link, but "
"will have no ${_content_dir}/ in its virtual filesystem.")
endif()
endforeach()
foreach(_own_dir worlds3d textures3d avatars3d)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_own_dir}")
target_link_options(GalaxyEggbertCNA PRIVATE
"SHELL:--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/${_own_dir}@/${_own_dir}")
endif()
endforeach()
endif()
message(STATUS "GalaxyEggbertCNA target enabled (maintained playable game).")
# Scripted verification for InteractionSystem (2026-07-10, platform
# lift patrol/crate push/pickup collection) against the real
# worlds3d/world999.vwr sample world. Needs CNA linked (Sound touches
# Microsoft::Xna::Framework::Audio types) but not easy3d/SDL3main --
# Sound::LoadContent() is never called, so no live audio device is
# exercised at runtime, only symbols resolved at link time. Run from the
# repo root (relative default path "worlds3d/world999.vwr"), same
# quirk as VerifyBlupiMovement.
add_executable(VerifyInteractionSystem
tools/VerifyInteractionSystem.cpp
src/GalaxyEggbert/Game/WorldRuntime.cpp
src/GalaxyEggbert/Game/Sound.cpp
src/GalaxyEggbert/Game/InteractionSystem.cpp
src/GalaxyEggbert/Game/TrainingHints.cpp
src/GalaxyEggbert/Game/BlupiController.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
src/GalaxyEggbert/Game/Hud.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(VerifyInteractionSystem PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Web/Node test wiring: this console tool is only ever run under Node
# (via ctest, never in a browser -- no .html/SUFFIX set below), so
# NODERAWFS gives it direct access to the real host filesystem instead
# of an empty MEMFS, matching native behavior for its relative
# "worlds3d/world999.vwr" default path with no --preload-file/embed
# list to maintain.
if(EMSCRIPTEN)
target_link_options(VerifyInteractionSystem PRIVATE -sNODERAWFS=1)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT WIN32 AND _ge_cna_backend_target)
target_link_libraries(VerifyInteractionSystem PRIVATE
-Wl,--start-group CNA ${_ge_cna_backend_target} -Wl,--end-group
SHARP_RUNTIME)
else()
target_link_libraries(VerifyInteractionSystem PRIVATE CNA SHARP_RUNTIME)
endif()
if(TARGET easy3d::easy3d)
target_link_libraries(VerifyInteractionSystem PRIVATE easy3d::easy3d)
else()
target_link_libraries(VerifyInteractionSystem PRIVATE easy3d)
endif()
if(BUILD_TESTING)
# WORKING_DIRECTORY = repo root: this tool's default world path
# ("worlds3d/world999.vwr") is relative, same quirk noted above.
add_test(NAME VerifyInteractionSystem COMMAND VerifyInteractionSystem
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endif()
# Scripted verification for InputPad (2026-07-13, on-screen D-pad/
# Jump/Action/Pause + Pause-row hit-testing) -- pure layout/press-state
# math driven by synthetic MouseState values, no GraphicsDevice/window
# needed at runtime, but InputPad.cpp's LoadContent()/DrawPlay()/
# DrawPause() still reference CNA Texture2D/BasicEffect and
# Easy3D::BillboardMeshRenderer symbols, so this links the same way
# GalaxyEggbertCNA itself does (CNA + backend + SHARP_RUNTIME + easy3d).
add_executable(VerifyGEInputPad
tools/VerifyGEInputPad.cpp
src/GalaxyEggbert/Game/InputPad.cpp
src/GalaxyEggbert/Game/QuadBatch.cpp
)
target_include_directories(VerifyGEInputPad PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT WIN32 AND _ge_cna_backend_target)
target_link_libraries(VerifyGEInputPad PRIVATE
-Wl,--start-group CNA ${_ge_cna_backend_target} -Wl,--end-group
SHARP_RUNTIME)
else()
target_link_libraries(VerifyGEInputPad PRIVATE CNA SHARP_RUNTIME)
endif()
if(TARGET easy3d::easy3d)
target_link_libraries(VerifyGEInputPad PRIVATE easy3d::easy3d)
else()
target_link_libraries(VerifyGEInputPad PRIVATE easy3d)
endif()
if(BUILD_TESTING)
# No file/working-directory dependency -- LoadContent() is
# deliberately never called (see this tool's own top comment).
add_test(NAME VerifyGEInputPad COMMAND VerifyGEInputPad)
endif()
# Scripted editor verification is split by responsibility so failures
# identify the broken subsystem instead of disappearing inside one
# monolithic executable. Compile their shared real-editor support once:
# repeating it in all four executables created four identical object
# trees and rewrote them after every common editor change.
add_library(GEEditorVerifySupport OBJECT
src/GalaxyEggbert/Editor/WorldEditor.cpp
src/GalaxyEggbert/Editor/WorldEditorUpdate.cpp
src/GalaxyEggbert/Editor/VoxelRaycast.cpp
src/GalaxyEggbert/Editor/EditorHighlightRenderer.cpp
src/GalaxyEggbert/Editor/EditCommandStack.cpp
src/GalaxyEggbert/Editor/BoxRegion.cpp
src/GalaxyEggbert/Editor/PaletteCategories.cpp
src/GalaxyEggbert/Editor/EditorPalette.cpp
src/GalaxyEggbert/Editor/EditorPaletteLayout.cpp
src/GalaxyEggbert/Editor/EditorPaletteInput.cpp
src/GalaxyEggbert/Editor/EditorPaletteRenderer.cpp
src/GalaxyEggbert/Editor/CustomWorldStorage.cpp
src/GalaxyEggbert/Editor/EditorBrowserScreen.cpp
src/GalaxyEggbert/Game/QuadBatch.cpp
src/GalaxyEggbert/Game/TileAtlas.cpp
src/GalaxyEggbert/Game/Hud.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(GEEditorVerifySupport PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_link_libraries(GEEditorVerifySupport PRIVATE CNA SHARP_RUNTIME)
if(TARGET easy3d::easy3d)
target_link_libraries(GEEditorVerifySupport PRIVATE easy3d::easy3d)
else()
target_link_libraries(GEEditorVerifySupport PRIVATE easy3d)
endif()
function(ge_add_editor_verify target source)
add_executable(${target} ${source})
target_include_directories(${target} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_link_libraries(${target} PRIVATE GEEditorVerifySupport)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND NOT WIN32 AND _ge_cna_backend_target)
target_link_libraries(${target} PRIVATE
-Wl,--start-group CNA ${_ge_cna_backend_target} -Wl,--end-group
SHARP_RUNTIME)
else()
target_link_libraries(${target} PRIVATE CNA SHARP_RUNTIME)
endif()
if(TARGET easy3d::easy3d)
target_link_libraries(${target} PRIVATE easy3d::easy3d)
else()
target_link_libraries(${target} PRIVATE easy3d)
endif()
if(BUILD_TESTING)
add_test(NAME ${target} COMMAND ${target})
endif()
endfunction()
ge_add_editor_verify(VerifyGEWorldEditor tools/VerifyGEWorldEditor.cpp)
ge_add_editor_verify(VerifyGEEditorPalette tools/VerifyGEEditorPalette.cpp)
ge_add_editor_verify(VerifyGEEditorStorage tools/VerifyGEEditorStorage.cpp)
ge_add_editor_verify(VerifyGEEditorObjects tools/VerifyGEEditorObjects.cpp)
ge_add_editor_verify(VerifyDefinitionRegistries tools/VerifyDefinitionRegistries.cpp)
# -------------------------------------------------------------------
# Linux runtime bundle (BUILD-010)
#
# The game resolves all of its assets relative to its working directory.
# Install a self-contained directory layout and a launcher that enters
# that directory, then let CPack emit a portable .tar.gz bundle. The
# bundled SDL libraries remove the build-machine-specific SDL RPATH; OS
# libraries such as the graphics stack and FFmpeg intentionally remain
# distribution dependencies rather than being copied into the archive.
# -------------------------------------------------------------------
if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND NOT ANDROID)
option(GALAXY_EGGBERT_ENABLE_LINUX_BUNDLE
"Enable CPack's GalaxyEggbertCNA Linux runtime bundle" ON)
if(GALAXY_EGGBERT_ENABLE_LINUX_BUNDLE)
set_target_properties(GalaxyEggbertCNA PROPERTIES
INSTALL_RPATH "$ORIGIN/lib")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/packaging/run-galaxy-eggbert.sh.in"
"${CMAKE_CURRENT_BINARY_DIR}/run-galaxy-eggbert"
@ONLY)
install(TARGETS GalaxyEggbertCNA
RUNTIME DESTINATION "."
COMPONENT Runtime)
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/run-galaxy-eggbert"
DESTINATION "."
COMPONENT Runtime)
install(DIRECTORY Content worlds worlds3d textures3d avatars3d
DESTINATION "."
USE_SOURCE_PERMISSIONS
COMPONENT Runtime)
install(FILES LICENSE DESTINATION "." COMPONENT Runtime)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/packaging/README-linux-bundle.md"
DESTINATION "."
RENAME "README-Linux.md"
COMPONENT Runtime)
# The SDL prebuilt install used by CNA provides license files.
# Preserve them in the distributed bundle whenever SDL3_DIR points
# at that standard package-config location.
if(SDL3_DIR)
get_filename_component(_ge_sdl_prefix "${SDL3_DIR}/../../.." ABSOLUTE)
# Copy the versioned shared libraries and their SONAME
# symlinks. The executable's INSTALL_RPATH resolves these
# as $ORIGIN/lib after the bundle is extracted.
install(DIRECTORY "${_ge_sdl_prefix}/lib/"
DESTINATION "lib"
COMPONENT Runtime
FILES_MATCHING PATTERN "libSDL3*.so*")
if(EXISTS "${_ge_sdl_prefix}/share/licenses")
install(DIRECTORY "${_ge_sdl_prefix}/share/licenses/"
DESTINATION "licenses/SDL"
COMPONENT Runtime)
endif()
endif()
set(CPACK_GENERATOR "TGZ")
set(CPACK_PACKAGE_NAME "GalaxyEggbertCNA")
set(CPACK_PACKAGE_FILE_NAME "GalaxyEggbertCNA-linux-${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY ON)
set(CPACK_COMPONENTS_ALL Runtime)
# CPack otherwise invokes the root install with no component,
# which recursively installs library/test artifacts from CNA and
# Easy3D as well. Package only this project's Runtime component.
set(CPACK_INSTALL_CMAKE_PROJECTS
"${CMAKE_BINARY_DIR};${CMAKE_PROJECT_NAME};Runtime;/")
include(CPack)
endif()
endif()
endif() # GALAXY_EGGBERT_BUILD_CNA
# =============================================================================
# Tools (engine-independent — pure C++ data model, no graphics)
# =============================================================================
# ObjectIcons.hpp/.cpp is engine-agnostic (only depends on Def/
# ObjectType.hpp) despite living under src/GalaxyEggbert/Game/ -- linked here
# so the exhibition area can enumerate every ObjectType the renderer has an
# icon for (GetObjIcon), instead of duplicating that list by hand (same
# precedent as VerifyBlupiMovement linking BlupiController.cpp below).
add_executable(GenerateSampleWorld3D
tools/GenerateSampleWorld3D.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
src/GalaxyEggbert/Game/PlateRotationMetadata.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(GenerateSampleWorld3D PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# BlupiController.hpp/.cpp are deliberately engine-agnostic (only depend on
# GalaxyEggbert::Worlds) despite living under src/GalaxyEggbert/Game/ — this
# tool links them without needing CNA at all (see plan.md E3D-MIG-060).
add_executable(VerifyBlupiMovement
tools/VerifyBlupiMovement.cpp
src/GalaxyEggbert/Game/BlupiController.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(VerifyBlupiMovement PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Web/Node test wiring, same rationale as VerifyInteractionSystem above:
# Node-only console tool, NODERAWFS gives it real host filesystem access
# for its relative "worlds3d/world999.vwr" default path.
if(EMSCRIPTEN)
target_link_options(VerifyBlupiMovement PRIVATE -sNODERAWFS=1)
endif()
# SaveData.hpp/.cpp are deliberately engine-agnostic (only <string>/
# <fstream>) despite living under src/GalaxyEggbert/Game/ -- this tool links
# it without needing CNA at all, same precedent as VerifyBlupiMovement
# above.
add_executable(VerifyGESaveData
tools/VerifyGESaveData.cpp
src/GalaxyEggbert/Game/SaveData.cpp
)
target_include_directories(VerifyGESaveData PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Web/Node test wiring: unlike the NODERAWFS tools above, SaveData's own
# kSavePath is "/save/savedata.txt" under __EMSCRIPTEN__ (an absolute IDBFS
# mount point the real app's pre.js sets up for browser persistence, see
# SaveData.hpp) -- NODERAWFS would instead map that absolute path onto the
# real host's own "/save" directory, which is wrong here. Reuses a minimal
# pre-js that just creates "/save" in this tool's own in-memory MEMFS (no
# IDBFS/persistence needed -- the test runs and exits within one process).
if(EMSCRIPTEN)
set_target_properties(VerifyGESaveData PROPERTIES
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/web/pre-test-save-dir.js")
target_link_options(VerifyGESaveData PRIVATE
-sFORCE_FILESYSTEM=1
"SHELL:--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/cmake/web/pre-test-save-dir.js")
endif()
# TerrainAnimDivisor.hpp/.cpp (plan.md TEST-007, 2026-07-14) is a pure
# function of a BlockTypes icon id -- no CNA/graphics dependency at all,
# same engine-independent precedent as VerifyGESaveData/VerifyBlupiMovement
# above.
add_executable(VerifyTerrainAnimDivisor
tools/VerifyTerrainAnimDivisor.cpp
src/GalaxyEggbert/Game/TerrainAnimDivisor.cpp
src/GalaxyEggbert/BlockDefinitionRegistry.cpp
)
target_include_directories(VerifyTerrainAnimDivisor PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# INFRA-003 (plan.md §7): ObjectIcons.hpp/.cpp is engine-agnostic (only
# depends on Def/ObjectType.hpp, see GenerateSampleWorld3D's own comment
# above) -- a data-integrity regression test for its 34 historical "Fixed"
# transcription bugs, same engine-independent precedent as
# VerifyTerrainAnimDivisor above.
add_executable(VerifyGetObjIcon
tools/VerifyGetObjIcon.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
)
target_include_directories(VerifyGetObjIcon PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# INFRA-003 follow-up (plan.md §7): the independent programmatic
# reference-doc cross-check REMAKE-ANALYSIS.md's P0-2 actually asked for
# (VerifyGetObjIcon above is a regression lock, not this) -- parses
# mobile-eggbert-reference/08-animations.md's own §3.1/§3.2 tables at
# runtime and black-box-verifies GetObjIcon()'s actual cycle behavior
# against them. Same engine-independent precedent as VerifyGetObjIcon.
add_executable(VerifyObjIconAgainstReferenceDoc
tools/VerifyObjIconAgainstReferenceDoc.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
)
target_include_directories(VerifyObjIconAgainstReferenceDoc PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# BlockTypes::tileUV() (plan.md TEST-004) is a pure header-only function --
# no CNA/graphics dependency at all, same engine-independent precedent as
# VerifyGESaveData/VerifyBlupiMovement/VerifyTerrainAnimDivisor above.
add_executable(VerifyTileUvBounds
tools/VerifyTileUvBounds.cpp
)
target_include_directories(VerifyTileUvBounds PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# INFRA-004 (plan.md §7): UnverifiedRenderMapping.hpp is a header-only data
# table (no CNA/graphics dependency), same engine-independent precedent as
# VerifyTileUvBounds above.
add_executable(VerifyUnverifiedRenderMapping
tools/VerifyUnverifiedRenderMapping.cpp
)
target_include_directories(VerifyUnverifiedRenderMapping PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# CameraShake.hpp/.cpp (plan.md CAM-008..013) is deliberately
# engine-agnostic (no CNA/graphics dependency) despite living under
# src/GalaxyEggbert/Game/ -- this tool links it without needing CNA at all,
# same precedent as VerifyGESaveData/VerifyTerrainAnimDivisor above.
add_executable(VerifyCameraShake
tools/VerifyCameraShake.cpp
src/GalaxyEggbert/Game/CameraShake.cpp
)
target_include_directories(VerifyCameraShake PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# WorldRuntime.hpp/.cpp are deliberately engine-agnostic (only
# depend on GalaxyEggbert::Worlds/def, plain floats instead of a CNA/XNA
# Vector3) — this tool links it without needing CNA at all, verifying
# MoveObject: parsing (E3D-MIG-06x prerequisite) against real reference
# world files and the production game parser.
add_executable(VerifyMoveObjectTypesCna
tools/VerifyMoveObjectTypesCna.cpp
src/GalaxyEggbert/Game/WorldRuntime.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(VerifyMoveObjectTypesCna PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Web/Node test wiring, same rationale as VerifyInteractionSystem above:
# Node-only console tool, NODERAWFS gives it real host filesystem access
# for its relative "../mobile-eggbert/worlds/*.txt" reads.
if(EMSCRIPTEN)
target_link_options(VerifyMoveObjectTypesCna PRIVATE -sNODERAWFS=1)
endif()
# Same engine-agnostic-parser rationale as VerifyMoveObjectTypesCna above,
# for BigDecor: section parsing (NEXT.md §8 task 3) instead of MoveObject:.
add_executable(VerifyBigDecorParsingCna
tools/VerifyBigDecorParsingCna.cpp
src/GalaxyEggbert/Game/WorldRuntime.cpp
src/GalaxyEggbert/Game/ObjectIcons.cpp
src/GalaxyEggbert/Game/ObjectDefinitionRegistry.cpp
${GE_SHARED_SOURCES}
)
target_include_directories(VerifyBigDecorParsingCna PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Web/Node test wiring, same rationale as VerifyMoveObjectTypesCna above.
if(EMSCRIPTEN)
target_link_options(VerifyBigDecorParsingCna PRIVATE -sNODERAWFS=1)
endif()
# plan.md TEST-002/008/009/010: registers these 4 engine-agnostic tools with
# ctest (VerifyInteractionSystem/VerifyGEInputPad are registered next to
# their own add_executable() above, inside the GALAXY_EGGBERT_BUILD_CNA
# block). VerifyBlupiMovement/VerifyMoveObjectTypesCna/VerifyBigDecorParsingCna
# all default to relative paths ("worlds3d/world999.vwr", "../mobile-eggbert/
# worlds/*.txt") that only resolve from the repo root (NEXT.md §7's own
# note) -- WORKING_DIRECTORY makes that explicit instead of relying on
# whatever directory ctest happens to be invoked from. VerifyGESaveData
# needs no such override: it only touches a scratch "savedata.txt" in
# its own cwd and cleans it up itself, so the default build-dir cwd
# keeps the repo root clean.
if(BUILD_TESTING)
add_test(NAME VerifyBlupiMovement COMMAND VerifyBlupiMovement
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_test(NAME VerifyGESaveData COMMAND VerifyGESaveData)
add_test(NAME VerifyMoveObjectTypesCna COMMAND VerifyMoveObjectTypesCna
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_test(NAME VerifyBigDecorParsingCna COMMAND VerifyBigDecorParsingCna
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# No file/working-directory dependency -- AnimDivisor() is a pure
# function of a BlockTypes icon id (plan.md TEST-007).
add_test(NAME VerifyTerrainAnimDivisor COMMAND VerifyTerrainAnimDivisor)
# No file/working-directory dependency -- tileUV() is a pure header-only
# function of a BlockTypes icon id (plan.md TEST-004).
add_test(NAME VerifyTileUvBounds COMMAND VerifyTileUvBounds)
# No file/working-directory dependency -- GetObjIcon() is a pure function
# of (ObjectType, phase) (plan.md INFRA-003).
add_test(NAME VerifyGetObjIcon COMMAND VerifyGetObjIcon)
# Reads mobile-eggbert-reference/08-animations.md, a repo-root-relative
# path -- same WORKING_DIRECTORY reasoning as VerifyBlupiMovement above
# (plan.md INFRA-003 follow-up).
add_test(NAME VerifyObjIconAgainstReferenceDoc COMMAND VerifyObjIconAgainstReferenceDoc
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
# No file/working-directory dependency -- pure data-table integrity check
# (plan.md INFRA-004).
add_test(NAME VerifyUnverifiedRenderMapping COMMAND VerifyUnverifiedRenderMapping)
# No file/working-directory dependency -- CameraShake is a pure
# tick-based state machine (plan.md CAM-008..013).
add_test(NAME VerifyCameraShake COMMAND VerifyCameraShake)
endif()
# =============================================================================
# Doxygen
# =============================================================================
find_package(Doxygen)
if(DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
add_custom_target(GalaxyEggbertDocs
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)
endif()
# =============================================================================
# Tests (engine-independent — pure C++ data model, no graphics)
# =============================================================================
if(BUILD_TESTING AND NOT ANDROID AND NOT EMSCRIPTEN)
include(FetchContent)
if(NOT TARGET GTest::gtest_main)
if(NOT TARGET gtest_main)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
endif()
if(TARGET gtest AND NOT TARGET GTest::gtest)
add_library(GTest::gtest ALIAS gtest)
endif()
if(TARGET gtest_main AND NOT TARGET GTest::gtest_main)
add_library(GTest::gtest_main ALIAS gtest_main)
endif()
endif()
add_executable(GalaxyEggbertWorldsTests
tests/GalaxyEggbert/Worlds/BlockTests.cpp
tests/GalaxyEggbert/Worlds/BitPackingTests.cpp
tests/GalaxyEggbert/Worlds/ChunkTests.cpp
tests/GalaxyEggbert/Worlds/WorldTests.cpp
tests/GalaxyEggbert/Worlds/BlockMetadataTest.cpp
tests/GalaxyEggbert/MoveObjectRecordTests.cpp
tests/GalaxyEggbert/BigDecorRecordTests.cpp
src/GalaxyEggbert/Worlds/BinaryIO.cpp
src/GalaxyEggbert/Worlds/BitPacking.cpp
src/GalaxyEggbert/Worlds/Chunk.cpp
src/GalaxyEggbert/Worlds/World.cpp
src/GalaxyEggbert/MoveObjectRecord.cpp
src/GalaxyEggbert/BigDecorRecord.cpp
)
target_include_directories(GalaxyEggbertWorldsTests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(GalaxyEggbertWorldsTests PRIVATE GTest::gtest_main)
include(GoogleTest)
gtest_discover_tests(GalaxyEggbertWorldsTests)
endif()