Files
dota_factory/src/CMakeLists.txt
Malte Langkabel 246cfc3935 give the selection cards their own parts instead of label blobs
The cards were assembled from plain labels carrying whole blocks of text.
Replace those with the widget vocabulary the requirements describe, so a part
means the same thing wherever it appears and a card is a list of parts rather
than a string builder.

The parts, all free of Simulation and GameConfig -- they take prepared values,
and the contents work out what those are:
- StatRow, BarRow, SectionBox: label/value line, captioned fill bar, captioned
  group. The bar is one part for three things: construction progress,
  production progress, and HP.
- ItemChip / ItemChipRow: buffered items as icon, count and sub-line
  (REQ-UI-SINGLE-SELECTION). An input chip carries its per-cycle amount, an
  output chip its count against the buffer capacity. The chips are rebuilt only
  when the set of items changes, so a 30 Hz refresh moves numbers rather than
  widgets.
- RecipeSummaryRow: inputs, arrow, outputs, cycle time (REQ-UI-RECIPE-SUMMARY),
  which is now the panel's only display of the cycle time.
- CountRow, StatusPill, EmptyNote.

Behaviour that changed with them:
- The station card shows damage, range and fire rate as the requirement asks
  (REQ-UI-STATION-STATS-PANEL) rather than the combined DPS it showed before.
- A ship's behaviour moves from a stats row into the card header
  (REQ-UI-SHIP-BEHAVIOR). ShipStatsPanel keeps setBehavior for the balancing
  tool's inspect window, which has no header to put it in.
- A construction site's card shows a progress bar and the "no buffers until
  built" note (REQ-UI-SELECTION-CARD), and now also its recipe summary, since
  that is configuration and a site carries it (REQ-BLD-SITE-CONFIG). Costing a
  shipyard site's schematic needed computeShipyardRequiredMaterials to take a
  stored configuration as well as a live building -- one overload, so the
  module sum still exists once.

ShipStatsPanel is rebuilt on StatRow, BarRow and SectionBox, so the selection
card, the layout dialog's design preview and the balancing tool read alike.
Those three parts are compiled into the balancing target, which does not link
the ui library; keeping them sim-free is what makes that possible, and the
build enforces it.

Build clean, 541 tests pass, app and balancing tool both run with no Qt
warnings. Visual check pending.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
2026-08-07 12:37:11 +02:00

313 lines
9.8 KiB
CMake

set(TARGET_BASE_NAME "${PRODUCT_NAME}")
set(TARGET_APP_NAME "${TARGET_BASE_NAME}")
set(TARGET_LIB_NAME "${TARGET_BASE_NAME}_lib")
set(TARGET_UI_NAME "${TARGET_BASE_NAME}_ui")
set(TARGET_TEST_NAME "${TARGET_BASE_NAME}_test")
set(TARGET_BALANCING_NAME "${TARGET_BASE_NAME}_balancing")
set(TARGET_LIB_INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/lib"
"${CMAKE_CURRENT_SOURCE_DIR}/external"
)
set(TARGET_UI_INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/ui"
# The balancing target compiles a few ui files into itself rather than linking the
# ui library, and the ship stats panel is built from the selection card's parts.
"${CMAKE_CURRENT_SOURCE_DIR}/ui/selection"
)
set(TARGET_TEST_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/test")
set(TARGET_BALANCING_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/balancing")
set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# ============================================================
# lib — simulation + config
# Depends on Qt Core, toml++, tinyexpr only (no QtWidgets).
# ============================================================
set(HDRS)
set(SRCS)
set(LIB_INCLUDE_PATH)
add_subdirectory(external)
add_subdirectory(lib)
set_source_files_properties(${EXTERNAL_FILES} PROPERTIES COMPILE_FLAGS "-w")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(RELATIVE_HDRS)
foreach (_file ${HDRS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_HDRS "${_relPath}")
endforeach()
set(RELATIVE_SRCS)
foreach (_file ${SRCS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_SRCS "${_relPath}")
endforeach()
add_files(LIB_FILES ${RELATIVE_HDRS} ${RELATIVE_SRCS})
add_library(${TARGET_LIB_NAME} ${LIB_FILES} ${EXTERNAL_FILES})
create_source_groups(${LIB_FILES})
create_source_groups(${EXTERNAL_FILES})
set_property(TARGET ${TARGET_LIB_NAME} PROPERTY CXX_STANDARD 17)
set_property(TARGET ${TARGET_LIB_NAME} PROPERTY INCLUDE_DIRECTORIES
"${TARGET_LIB_INCLUDE_DIRS}"
"${LIB_INCLUDE_PATH}"
)
target_link_libraries(${TARGET_LIB_NAME} Qt5::Core Qt5::Gui)
target_compile_definitions(${TARGET_LIB_NAME} PRIVATE TOML_FLOAT_CHARCONV=0)
set(CMAKE_AUTOMOC OFF)
unset(LIB_FILES)
unset(RELATIVE_HDRS)
unset(RELATIVE_SRCS)
unset(HDRS)
unset(SRCS)
# LIB_INCLUDE_PATH (populated by lib/ and external/ subdirectories) is kept
# in scope so the test target below can also reach those headers.
# ============================================================
# ui — QtWidgets + QOpenGLWidget
# Depends on lib.
# ============================================================
set(HDRS)
set(SRCS)
set(UI_INCLUDE_PATH)
add_subdirectory(ui)
set(CMAKE_AUTOMOC ON)
set(RELATIVE_HDRS)
foreach (_file ${HDRS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_HDRS "${_relPath}")
endforeach()
set(RELATIVE_SRCS)
foreach (_file ${SRCS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_SRCS "${_relPath}")
endforeach()
add_files(UI_FILES ${RELATIVE_HDRS} ${RELATIVE_SRCS})
add_library(${TARGET_UI_NAME} STATIC ${UI_FILES})
create_source_groups(${UI_FILES})
set_target_properties(${TARGET_UI_NAME} PROPERTIES
AUTOMOC ON
CXX_STANDARD 17
)
target_include_directories(${TARGET_UI_NAME} PUBLIC
"${TARGET_UI_INCLUDE_DIRS}"
"${UI_INCLUDE_PATH}"
"${TARGET_LIB_INCLUDE_DIRS}"
"${LIB_INCLUDE_PATH}"
)
target_link_libraries(${TARGET_UI_NAME}
${TARGET_LIB_NAME}
Qt5::Widgets
${OPENGL_LIBRARIES}
Qt5::Network
Qt5::Multimedia
Qt5::Charts
Qt5::Svg
)
target_compile_definitions(${TARGET_UI_NAME} PRIVATE TOML_FLOAT_CHARCONV=0)
set(CMAKE_AUTOMOC OFF)
unset(UI_FILES)
unset(RELATIVE_HDRS)
unset(RELATIVE_SRCS)
unset(HDRS)
unset(SRCS)
# ============================================================
# app — thin main(); depends on ui
# ============================================================
set(OUTPUT_ROOT_PATH "${CMAKE_BINARY_DIR}/${TARGET_BASE_NAME}")
if (WIN32)
COPY_QT_BINARIES("${OUTPUT_ROOT_PATH}/Debug/app/" True)
COPY_QT_BINARIES("${OUTPUT_ROOT_PATH}/Release/app/" False)
string(REGEX REPLACE "/" "\\\\" BACKSLASHED_CMAKE_SOURCE_DIR ${CMAKE_SOURCE_DIR})
string(REGEX REPLACE "/" "\\\\" BACKSLASHED_OUTPUT_ROOT_PATH ${OUTPUT_ROOT_PATH})
execute_process(
COMMAND "cmd.exe" "/k" "rmdir" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Debug\\app\\data" & "mklink" "/d" "/j" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Debug\\app\\data" "${BACKSLASHED_CMAKE_SOURCE_DIR}\\bin\\app\\data" & exit
COMMAND "cmd.exe" "/k" "rmdir" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Release\\app\\data" & "mklink" "/d" "/j" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Release\\app\\data" "${BACKSLASHED_CMAKE_SOURCE_DIR}\\bin\\app\\data" & exit
)
endif ()
foreach (OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${OUTPUT_ROOT_PATH}/${OUTPUTCONFIG}/app/")
endforeach ()
set(HDRS)
set(SRCS)
add_subdirectory(app)
set(RELATIVE_HDRS)
foreach (_file ${HDRS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_HDRS "${_relPath}")
endforeach()
set(RELATIVE_SRCS)
foreach (_file ${SRCS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_SRCS "${_relPath}")
endforeach()
add_files(APP_FILES ${RELATIVE_HDRS} ${RELATIVE_SRCS})
add_executable(${TARGET_APP_NAME} ${APP_FILES})
create_source_groups(${APP_FILES})
set_property(TARGET ${TARGET_APP_NAME} PROPERTY CXX_STANDARD 17)
set_target_properties(${TARGET_APP_NAME} PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY "${OUTPUT_ROOT_PATH}/$(Configuration)/app/"
)
target_compile_definitions(${TARGET_APP_NAME} PRIVATE
CONFIG_DIR="${CMAKE_SOURCE_DIR}/bin/app/data/config"
)
target_link_libraries(${TARGET_APP_NAME} ${TARGET_UI_NAME})
# Embed the Windows version resource so the version shows on the executable's
# Details tab (right-click -> Properties). Values come from cmake/version.cmake
# (version numbers) and the product identity variables in the top-level
# CMakeLists.txt. MSVC compiles the .rc automatically once it is a target source.
if (WIN32)
configure_file(
"${CMAKE_SOURCE_DIR}/cmake/version.rc.in"
"${CMAKE_CURRENT_BINARY_DIR}/version.rc"
@ONLY
)
target_sources(${TARGET_APP_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/version.rc")
endif ()
unset(APP_FILES)
unset(RELATIVE_HDRS)
unset(RELATIVE_SRCS)
unset(HDRS)
unset(SRCS)
# ============================================================
# balancing — ship balancing tool; depends on lib + QtWidgets
# ============================================================
if (WIN32)
COPY_QT_BINARIES("${OUTPUT_ROOT_PATH}/Debug/balancing/" True)
COPY_QT_BINARIES("${OUTPUT_ROOT_PATH}/Release/balancing/" False)
execute_process(
COMMAND "cmd.exe" "/k" "rmdir" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Debug\\balancing\\data" & "mklink" "/d" "/j" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Debug\\balancing\\data" "${BACKSLASHED_CMAKE_SOURCE_DIR}\\bin\\balancing\\data" & exit
COMMAND "cmd.exe" "/k" "rmdir" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Release\\balancing\\data" & "mklink" "/d" "/j" "${BACKSLASHED_OUTPUT_ROOT_PATH}\\Release\\balancing\\data" "${BACKSLASHED_CMAKE_SOURCE_DIR}\\bin\\balancing\\data" & exit
)
endif ()
set(HDRS)
set(SRCS)
add_subdirectory(balancing)
set(RELATIVE_HDRS)
foreach (_file ${HDRS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_HDRS "${_relPath}")
endforeach()
set(RELATIVE_SRCS)
foreach (_file ${SRCS})
file(RELATIVE_PATH _relPath "${SRC_DIR}" "${_file}")
list(APPEND RELATIVE_SRCS "${_relPath}")
endforeach()
add_files(BALANCING_FILES ${RELATIVE_HDRS} ${RELATIVE_SRCS})
add_executable(${TARGET_BALANCING_NAME} ${BALANCING_FILES})
create_source_groups(${BALANCING_FILES})
foreach (OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set_target_properties(${TARGET_BALANCING_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${OUTPUT_ROOT_PATH}/${OUTPUTCONFIG}/balancing/"
)
endforeach ()
set_target_properties(${TARGET_BALANCING_NAME} PROPERTIES
AUTOMOC ON
CXX_STANDARD 17
VS_DEBUGGER_WORKING_DIRECTORY "${OUTPUT_ROOT_PATH}/$(Configuration)/balancing/"
)
target_include_directories(${TARGET_BALANCING_NAME} PRIVATE
"${TARGET_BALANCING_INCLUDE_DIRS}"
"${TARGET_LIB_INCLUDE_DIRS}"
"${TARGET_UI_INCLUDE_DIRS}"
"${LIB_INCLUDE_PATH}"
)
target_compile_definitions(${TARGET_BALANCING_NAME} PRIVATE
CONFIG_DIR="${CMAKE_SOURCE_DIR}/bin/app/data/config"
BALANCING_CONFIG="${CMAKE_SOURCE_DIR}/bin/balancing/data/balancing.toml"
TOML_FLOAT_CHARCONV=0
)
target_link_libraries(${TARGET_BALANCING_NAME} ${TARGET_LIB_NAME} Qt5::Widgets ${OPENGL_LIBRARIES})
unset(BALANCING_FILES)
unset(RELATIVE_HDRS)
unset(RELATIVE_SRCS)
unset(HDRS)
unset(SRCS)
# ============================================================
# tests — Catch2 tests; links against lib only (no QtWidgets)
# ============================================================
add_subdirectory(test)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(${TARGET_TEST_NAME} ${TEST_FILES})
create_source_groups(${TEST_FILES})
set_property(TARGET ${TARGET_TEST_NAME} PROPERTY CXX_STANDARD 17)
set_property(TARGET ${TARGET_TEST_NAME} PROPERTY INCLUDE_DIRECTORIES
"${TARGET_TEST_INCLUDE_DIRS}"
"${TARGET_LIB_INCLUDE_DIRS}"
"${LIB_INCLUDE_PATH}"
)
target_compile_definitions(${TARGET_TEST_NAME} PRIVATE
CONFIG_DIR="${CMAKE_SOURCE_DIR}/bin/test/data/config"
)
target_link_libraries(${TARGET_TEST_NAME} ${TARGET_LIB_NAME})
# ============================================================
# Export
# ============================================================
set(TARGET_LIB_NAME "${TARGET_LIB_NAME}" PARENT_SCOPE)
set(TARGET_UI_NAME "${TARGET_UI_NAME}" PARENT_SCOPE)
set(TARGET_APP_NAME "${TARGET_APP_NAME}" PARENT_SCOPE)
set(TARGET_BALANCING_NAME "${TARGET_BALANCING_NAME}" PARENT_SCOPE)