mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Compare commits
14 commits
058f0fba61
...
c62f5808ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c62f5808ca | ||
|
|
eb793b60c2 | ||
|
|
dd2ae207e5 | ||
|
|
0af738e0ec | ||
|
|
c4e7364802 | ||
|
|
867bdf318b | ||
|
|
e64a138f92 | ||
|
|
4a7b7e7df1 | ||
|
|
fa90ddc8b6 | ||
|
|
764a420797 | ||
|
|
8a2bb10827 | ||
|
|
af9d102126 | ||
|
|
822092fcb4 | ||
|
|
6e79dc2f70 |
53 changed files with 1347 additions and 524 deletions
157
CMakeLists.txt
Normal file
157
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
cmake_minimum_required(VERSION 3.25.1...4.0.0)
|
||||||
|
|
||||||
|
project(0ad VERSION 0.29.0)
|
||||||
|
|
||||||
|
# Available Options
|
||||||
|
option(android "Use non-working Android cross-compiling mode")
|
||||||
|
option(build-docs "Enable building the doxygen documentation(requires Network access)")
|
||||||
|
option(coverage "Enable code coverage data collection (GCC only)")
|
||||||
|
option(gles "Use non-working OpenGL ES 2.0 mode")
|
||||||
|
option(jenkins-tests "Configure CxxTest to use the XmlPrinter runner which produces Jenkins-compatible output")
|
||||||
|
option(minimal-flags "Only set compiler/linker flags that are really needed. Has no effect on Windows builds")
|
||||||
|
option(sanitize-address "Enable ASAN if available")
|
||||||
|
option(sanitize-thread "Enable TSAN if available")
|
||||||
|
option(sanitize-undefined-behaviour "Enable UBSAN if available")
|
||||||
|
option(with-system-cxxtest "Search standard paths for cxxtest, instead of using bundled copy")
|
||||||
|
option(with-lto "Enable Link Time Optimization (LTO)")
|
||||||
|
option(with-system-mozjs "Search standard paths for libmozjs115, instead of using bundled copy")
|
||||||
|
option(with-system-nvtt "Search standard paths for nvidia-texture-tools library, instead of using bundled copy")
|
||||||
|
option(with-valgrind "Enable Valgrind support (non-Windows only)")
|
||||||
|
option(without-audio "Disable use of OpenAL/Ogg/Vorbis APIs")
|
||||||
|
option(without-atlas "Disable Atlas scenario/map editor and ActorEditor")
|
||||||
|
option(without-dap-interface "Disable Dap interface project")
|
||||||
|
option(without-lobby "Disable the use of gloox and the multiplayer lobby")
|
||||||
|
option(without-miniupnpc "Disable use of miniupnpc for port forwarding")
|
||||||
|
option(without-nvtt "Disable use of NVTT")
|
||||||
|
option(without-pch "Disable generation and usage of precompiled headers")
|
||||||
|
option(without-tests "Disable generation of test projects")
|
||||||
|
|
||||||
|
# Windows specific options
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
option(fetch-prebuild-libs "Fetch prebuild libraries from SVN. Defaults to ON." ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# OS X specific options
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
option(macosx-version-min "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)")
|
||||||
|
option(sysroot "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set the default build type if not specified (Only for single configuration generators)
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Install options
|
||||||
|
set(bindir "" CACHE STRING "Directory for executables (typically '/usr/games'); default is to be relocatable")
|
||||||
|
set(datadir "" CACHE STRING "Directory for data files (typically '/usr/share/games/0ad'); default is ../data/ relative to executable")
|
||||||
|
set(libdir "" CACHE STRING "Directory for libraries (typically '/usr/lib/games/0ad'); default is ./ relative to executable")
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ General Setup ++++++++++++++++++++
|
||||||
|
|
||||||
|
# Default Cache variables
|
||||||
|
# Append to the Modulepath. Allows to make custom cmake modules.
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
# Set default Arch
|
||||||
|
set(ARCH "x86" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64")
|
||||||
|
set(MACOS_ARCH "x86_64" CACHE STRING "Mac OS specific Architecture. Possible values are arm64 and x86_64")
|
||||||
|
option(link_execinfo "")
|
||||||
|
option(mozjs_is_debug_build "")
|
||||||
|
|
||||||
|
# Detect CPU architecture (simplistic). The user can target an architecture by setting '-DARCH=arch', but the game still selects some know value.
|
||||||
|
if(android)
|
||||||
|
set(ARCH "arm" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
if(NOT CMAKE_VS_PLATFORM_NAME)
|
||||||
|
if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64" OR ENV{PROCESSOR_ARCHITEW6432} STREQUAL "AMD64")
|
||||||
|
set(ARCH "amd64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(CMAKE_VS_PLATFORM_NAME MATCHES "x64")
|
||||||
|
set(ARCH "amd64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# could be parsed from the same command as premakes version
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "(x86_64|x64)")
|
||||||
|
set(MACOS_ARCH "x86_64" CACHE STRING "Mac OS specific Architecture. Possible values are arm64 and x86_64" FORCE)
|
||||||
|
elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||||
|
set(MACOS_ARCH "arm64" CACHE STRING "Mac OS specific Architecture. Possible values are arm64 and x86_64" FORCE)
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "(x86_64|x64)")
|
||||||
|
set(ARCH "amd64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE)
|
||||||
|
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "(aarch64|aarch64_be)")
|
||||||
|
set(ARCH "aarch64" CACHE STRING "CPU Architecture. Possible values are arm, aarch64, x86, amd64, e2k, ppc64, loong64, riscv64" FORCE)
|
||||||
|
else()
|
||||||
|
message(WARNING "Cannot determine architecture from GCC, assuming x86")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
if(ARCH MATCHES "amd64")
|
||||||
|
set(0AD_EXT_LIBDIR ${CMAKE_SOURCE_DIR}/libraries/win64 CACHE STRING "Extern libraries directory of 0ad. Can be referenced in other CMakeLists.txt files.")
|
||||||
|
else()
|
||||||
|
set(0AD_EXT_LIBDIR ${CMAKE_SOURCE_DIR}/libraries/win32 CACHE STRING "Extern libraries directory of 0ad. Can be referenced in other CMakeLists.txt files.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# On Windows check if wxWidgets is available, if not disable atlas and emit warning. This is because there are currently no prebuilt binaries provided.
|
||||||
|
if(NOT without-atlas AND CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
if(NOT EXISTS "${0AD_EXT_LIBDIR}/wxwidgets/include/wx/wx.h")
|
||||||
|
message(STATUS "wxWidgets not found, disabling atlas")
|
||||||
|
set(without-atlas ON CACHE BOOL "Disable Atlas scenario/map editor and ActorEditor" FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Test whether we need to link libexecinfo. This is mostly the case on musl systems, as well as on BSD systems : only glibc provides the
|
||||||
|
# backtrace symbols we require in the libc, for other libcs we use the libexecinfo library.
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||||
|
set(link_execinfo ON CACHE BOOL "" FORCE)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
file(READ ${CMAKE_SOURCE_DIR}/build/premake/tests/execinfo.c content)
|
||||||
|
check_c_source_compiles([[${content}]] LINK_EXECINFO)
|
||||||
|
if(NOT LINK_EXECINFO)
|
||||||
|
set(link_execinfo ON CACHE BOOL "" FORCE)
|
||||||
|
else()
|
||||||
|
set(link_execinfo OFF CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
|
unset(LINK_EXECINFO)
|
||||||
|
unset(content)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Test whether system mozjs is built with --enable-debug. The pc file doesn't specify the required -DDEBUG needed in that case
|
||||||
|
# Currently only working on bash shell!
|
||||||
|
if(with-system-mozjs)
|
||||||
|
execute_process(
|
||||||
|
COMMAND bash "-c" "${CMAKE_C_COMPILER} $(pkg-config mozjs-128 --cflags) ${CMAKE_SOURCE_DIR}/build/premake/tests/mozdebug.c -o /dev/null"
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
RESULT_VARIABLE errorCode
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if(NOT errorCode EQUAL 0)
|
||||||
|
set(mozjs_is_debug_build ON CACHE BOOL "" FORCE)
|
||||||
|
else()
|
||||||
|
set(mozjs_is_debug_build OFF CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Include the BuildFlags target only once after all setup is finished
|
||||||
|
include(0ad-BuildFlags)
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ Windows specific ++++++++++++++++++++
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
include(SetupWindowsLibs)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add subprojects
|
||||||
|
if(NOT without-atlas)
|
||||||
|
add_subdirectory(${CMAKE_SOURCE_DIR}/source/tools/atlas/)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add doxygen target
|
||||||
|
if(build-docs)
|
||||||
|
add_subdirectory(${CMAKE_SOURCE_DIR}/docs/doxygen)
|
||||||
|
endif()
|
||||||
260
cmake/0ad-BuildFlags.cmake
Normal file
260
cmake/0ad-BuildFlags.cmake
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
cmake_minimum_required(VERSION 3.25.1...4.0.0)
|
||||||
|
|
||||||
|
# Add an interface library with common set of build/linker flags and definitions.
|
||||||
|
|
||||||
|
set(BUILD_FLAGS_TARGET BuildFlags)
|
||||||
|
add_library(${BUILD_FLAGS_TARGET} INTERFACE)
|
||||||
|
|
||||||
|
# Enable and require C++20 standard.
|
||||||
|
target_compile_features(${BUILD_FLAGS_TARGET} INTERFACE cxx_std_20)
|
||||||
|
set_target_properties(${BUILD_FLAGS_TARGET}
|
||||||
|
PROPERTIES
|
||||||
|
CXX_STANDARD_REQUIRED ON
|
||||||
|
CXX_EXTENSIONS OFF
|
||||||
|
)
|
||||||
|
|
||||||
|
# Settings for build types
|
||||||
|
if(with-lto)
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT lto_supported OUTPUT lto_supported_error)
|
||||||
|
if(lto_supported)
|
||||||
|
set_target_properties(${BUILD_FLAGS_TARGET}
|
||||||
|
PROPERTIES
|
||||||
|
INTERPROCEDURAL_OPTIMIZATION TRUE
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "IPO / LTO not supported: <${lto_supported_error}>")
|
||||||
|
endif()
|
||||||
|
unset(lto_supported)
|
||||||
|
unset(lto_supported_error)
|
||||||
|
endif()
|
||||||
|
target_compile_definitions(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CONFIG:Release>:NDEBUG>
|
||||||
|
$<$<CONFIG:Release>:CONFIG_FINAL=1>
|
||||||
|
$<$<CONFIG:Debug>:DEBUG>
|
||||||
|
# Game Configuration Defines
|
||||||
|
$<$<BOOL:${mozjs_is_debug_build}>:DEBUG>
|
||||||
|
$<$<BOOL:${gles}>:CONFIG2_DAP_INTERFACE=0>
|
||||||
|
$<$<BOOL:${without-audio}>:CONFIG2_GLES=1>
|
||||||
|
$<$<BOOL:${without-nvtt}>:CONFIG2_NVTT=0>
|
||||||
|
$<$<BOOL:${without-lobby}>:CONFIG2_LOBBY=0>
|
||||||
|
$<$<BOOL:${without-miniupnpc}>:CONFIG2_MINIUPNPC=0>
|
||||||
|
$<$<BOOL:${without-dap-interface}>:CONFIG2_DAP_INTERFACE=0>
|
||||||
|
)
|
||||||
|
|
||||||
|
# Address Sanitizer Settings
|
||||||
|
if(sanitize-address)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=address)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=address)
|
||||||
|
endif()
|
||||||
|
if(sanitize-thread)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=thread)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=thread)
|
||||||
|
endif()
|
||||||
|
if(sanitize-undefined-behaviour)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=undefined)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET} INTERFACE -fsanitize=undefined)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# hide warnings caused by library includes (Nothing to do for gcc/clang)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/external:W0>
|
||||||
|
)
|
||||||
|
|
||||||
|
# various platform-specific build flags
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/MP>
|
||||||
|
# Since KB4088875 Windows 7 has a soft requirement for SSE2.
|
||||||
|
# Windows 8+ and Firefox ESR52 make it hard requirement.
|
||||||
|
# Finally since VS2012 it's enabled implicitely when not set.
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/arch:SSE2>
|
||||||
|
# use native wchar_t type (not typedef to unsigned short)
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/Zc:wchar_t>
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
|
||||||
|
# SpiderMonkey only supports building with MSVC on a best-effort basis,
|
||||||
|
# and the traditional MSVC preprocessor is incompatible with some headers.
|
||||||
|
# Use the modern, standard-compliant MSVC preprocessor instead.
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/Zc:preprocessor>
|
||||||
|
# enable most of the standard warnings
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/W4>
|
||||||
|
# FIXME: conversion warnings, should add -Wconversion to gcc and clang flags as well
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:/wd4267>
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<CXX_COMPILER_ID:MSVC>>:/O2>
|
||||||
|
)
|
||||||
|
|
||||||
|
# disable LNK4221 warning, to avoid spending energy ordering projects in linker invocations
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"/ignore:4221"
|
||||||
|
)
|
||||||
|
|
||||||
|
# mozilla 115 linked list destructor in debug build
|
||||||
|
target_compile_definitions(${BUILD_FLAGS_TARGET} INTERFACE "__PRETTY_FUNCTION__=__FUNCSIG__")
|
||||||
|
|
||||||
|
# disable Windows debug heap, since it makes malloc/free hugely slower when running inside a debugger
|
||||||
|
set_target_properties(${BUILD_FLAGS_TARGET}
|
||||||
|
PROPERTIES
|
||||||
|
VS_DEBUGGER_ENVIRONMENT "_NO_DEBUG_HEAP=1"
|
||||||
|
)
|
||||||
|
|
||||||
|
elseif(UNIX)
|
||||||
|
if(NOT minimal-flags)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
# most of the standard warnings
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wall>
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wextra>
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wpedantic>
|
||||||
|
# $<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wconversion> # FIXME: should seriously consider fixing so this warning can be enabled.
|
||||||
|
# add some other useful warnings that need to be enabled explicitly
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wunused-parameter> # (useful for finding some multiply-included header files)
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wredundant-decls>
|
||||||
|
# $<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wformat=2> # (useful sometimes, but a bit noisy, so skip it by default)
|
||||||
|
# $<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wcast-qual> # (useful for checking const-correctness, but a bit noisy, so skip it by default)
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wnon-virtual-dtor> # (sometimes noisy but finds real bugs)
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wundef> # (useful for finding macro name typos)
|
||||||
|
# disable some warnings that currently trigger
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wno-missing-field-initializers> # (this is common in external headers we can't fix)
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wno-reorder> # order of initialization list in constructors (lots of noise)
|
||||||
|
# enable security features (stack checking etc) that shouldn't have a significant effect on performance and can catch bugs
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-fstack-protector-strong>
|
||||||
|
# always enable strict aliasing (useful in debug builds because of the warnings)
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-fstrict-aliasing>
|
||||||
|
# don't omit frame pointers (for now), because performance will be impacted negatively by the way this breaks profilers more than it will be impacted positively by the optimisation
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-fno-omit-frame-pointer>
|
||||||
|
# FORTIFY_SOURCE needs optimizations to be enabled
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<CXX_COMPILER_ID:Clang,AppleClang,GNU>>:-U_FORTIFY_SOURCE> # (avoid redefinition warning if already defined)
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<CXX_COMPILER_ID:Clang,AppleClang,GNU>>:-D_FORTIFY_SOURCE=2>
|
||||||
|
)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<PLATFORM_ID:Darwin>:-multiply_defined>
|
||||||
|
$<$<PLATFORM_ID:Darwin>:suppress>
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT without-pch)
|
||||||
|
# do something (?) so that ccache can handle compilation with PCH enabled (ccache 3.1+ also requires CCACHE_SLOPPINESS=time_macros for this to work)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-fpch-preprocess>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_NAME MATCHES ".*BSD*")
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-fPIC>
|
||||||
|
)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"-Wl,--no-undefined"
|
||||||
|
"-Wl,--as-needed"
|
||||||
|
"-Wl,-z,relro"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ARCH STREQUAL "x86")
|
||||||
|
# To support intrinsics like __sync_bool_compare_and_swap on x86 we need to set -march to something that supports them (i686).
|
||||||
|
# We use pentium3 to also enable other features like mmx and sse, while tuning for generic to have good performance on every supported CPU.
|
||||||
|
# Note that all these features are already supported on amd64.
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-march=pentium3>
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-mtune=generic>
|
||||||
|
# This allows x86 operating systems to handle the 2GB+ INTERFACE mod.
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-mtune=generic-D_FILE_OFFSET_BITS=64>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ARCH STREQUAL "arm")
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
# disable warnings about va_list ABI change and use compile-time flags for futher configuration.
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-Wno-psabi>
|
||||||
|
# Android uses softfp, so we should too.
|
||||||
|
$<$<AND:$<CXX_COMPILER_ID:Clang,AppleClang,GNU>,$<BOOL:${android}>>:-mfloat-abi=softfp>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(coverage)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-fprofile-arcs>
|
||||||
|
$<$<CXX_COMPILER_ID:Clang,AppleClang,GNU>:-ftest-coverage>
|
||||||
|
)
|
||||||
|
target_link_libraries(${BUILD_FLAGS_TARGET} gcov)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MacOS 10.12 only supports intel processors with SSE 4.1, so enable that.
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND ARCH STREQUAL "amd64")
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"-msse4.1"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if SDK path should be used
|
||||||
|
if(sysroot)
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"-isysroot ${sysroot}"
|
||||||
|
)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"-Wl,-syslibroot, ${sysroot}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# On OS X, sometimes we need to specify the minimum API version to use
|
||||||
|
if(macosx-version-min)
|
||||||
|
# clang and llvm-gcc look at mmacosx-version-min to determine link target and CRT version, and use it to set the macosx_version_min linker flag
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"-mmacosx-version-min=${macosx-version-min}"
|
||||||
|
)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
"-mmacosx-version-min=${macosx-version-min}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Only libc++ is supported on MacOS
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
-stdlib=libc++
|
||||||
|
)
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
-stdlib=libc++
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Hide symbols in dynamic shared objects by default, for efficiency and for equivalence with Windows
|
||||||
|
# - they should be exported explicitly with __attribute__ ((visibility ("default")))
|
||||||
|
target_compile_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
-fvisibility=hidden
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
$<$<BOOL:${bindir}>:INSTALLED_BINDIR=${bindir}>
|
||||||
|
$<$<BOOL:${datadir}>:INSTALLED_DATADIR=${bindir}>
|
||||||
|
$<$<BOOL:${libdir}>:INSTALLED_LIBDIR=${bindir}>
|
||||||
|
)
|
||||||
|
|
||||||
|
# RPATH Settings. Must be done through INSTALL_RPATH on target/global base.
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES ".*BSD*")
|
||||||
|
# On FreeBSD we need to allow use of $ORIGIN
|
||||||
|
target_link_options(${BUILD_FLAGS_TARGET}
|
||||||
|
INTERFACE
|
||||||
|
-Wl,-z,origin
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
47
cmake/0ad-Functions.cmake
Normal file
47
cmake/0ad-Functions.cmake
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
cmake_minimum_required(VERSION 3.25.1...4.0.0)
|
||||||
|
|
||||||
|
# 0AD Specific Functions
|
||||||
|
|
||||||
|
# Add Precompiled Headers. If no target is given, this macro will fail with a FATAL_ERROR.
|
||||||
|
# rationale: we need one PCH per static lib, since one global header would increase dependencies. To that end, we can either include them as
|
||||||
|
# "projectdir/precompiled.h", or add "source/PCH/projectdir" to the include path and put the PCH there. The latter is better because many
|
||||||
|
# projects contain several dirs and it's unclear where there the PCH should be stored. This way is also a bit easier to use in that
|
||||||
|
# source files always include "precompiled.h".
|
||||||
|
# Notes:
|
||||||
|
# * Visual Assist manages to use the project include path and can correctly open these files from the IDE.
|
||||||
|
# * precompiled.cpp (needed to "Create" the PCH) also goes in the abovementioned dir.
|
||||||
|
# * using CMakes precompiled Header is not possible, as it does not allow for a custom name like used here.
|
||||||
|
function(add_pch)
|
||||||
|
set(single_args TARGET PCH_DIR)
|
||||||
|
cmake_parse_arguments(args "" "${single_args}" "" ${ARGN})
|
||||||
|
if(NOT args_TARGET)
|
||||||
|
message(FATAL_ERROR "add_pch: Missing target!!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(PrecompiledHeader)
|
||||||
|
if(NOT args_PCH_DIR)
|
||||||
|
get_target_property(source_root ${args_TARGET} SOURCE_DIR)
|
||||||
|
set(args_PCH_DIR ${source_root}/pch/${args_TARGET})
|
||||||
|
endif()
|
||||||
|
# Put the project-specific PCH directory at the start of the include path, so '#include "precompiled.h"' will look in there first
|
||||||
|
target_include_directories(${args_TARGET}
|
||||||
|
BEFORE PRIVATE
|
||||||
|
${args_PCH_DIR}/
|
||||||
|
)
|
||||||
|
if (CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
|
set(pch_header "precompiled.h")
|
||||||
|
elseif(CMAKE_GENERATOR MATCHES "Xcode")
|
||||||
|
set(pch_header "../${args_PCH_DIR}/precompiled.h")
|
||||||
|
else()
|
||||||
|
set(pch_header "${args_PCH_DIR}/precompiled.h")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
precompile_header(${args_TARGET} ${pch_header} ${args_PCH_DIR}/precompiled.cpp)
|
||||||
|
|
||||||
|
target_sources(${args_TARGET}
|
||||||
|
PRIVATE
|
||||||
|
${args_PCH_DIR}/precompiled.cpp
|
||||||
|
${args_PCH_DIR}/precompiled.h
|
||||||
|
)
|
||||||
|
target_compile_definitions(${args_TARGET} PRIVATE CONFIG_ENABLE_PCH=1)
|
||||||
|
endfunction(add_pch)
|
||||||
54
cmake/FindPrebuildLibrary.cmake
Normal file
54
cmake/FindPrebuildLibrary.cmake
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
function(find_prebuild_library _name)
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
set(multi_args COMPONENTS PATHS)
|
||||||
|
set(single_args INC_PATH VERSION)
|
||||||
|
cmake_parse_arguments(args "${multi_args}" "${single_args}" "" ${ARGN})
|
||||||
|
|
||||||
|
string(TOLOWER ${_name} libname)
|
||||||
|
string(TOUPPER ${_name} target_name)
|
||||||
|
# ++++++++ Handle COMPONENTS +++++++++++++++++++++
|
||||||
|
if(args_COMPONENTS)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ++++++++ Find relevant elements ++++++++++++++++
|
||||||
|
find_library(Lib${_name} NAMES ${libname} ${libname}${args_VERSION})
|
||||||
|
if(NOT args_INC_PATH)
|
||||||
|
find_path(Lib${_name}_inc NAMES ${libname}.h PATHS ${0AD_EXT_LIBDIR}/${_name}/include/)
|
||||||
|
# recursive add all paths beneth included...
|
||||||
|
else()
|
||||||
|
set(Lib${_name}_inc ${args_INC_PATH})
|
||||||
|
endif()
|
||||||
|
if(NOT Lib${_name}_inc)
|
||||||
|
set(Lib${_name}_inc ${0AD_EXT_LIBDIR}/${_name}/include/)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package_handle_standard_args(Lib${_name} REQUIRED_VARS Lib${_name})
|
||||||
|
message(STATUS "${Lib${_name}} - ${Lib${_name}_inc} - ${Lib${_name}_FOUND} - ${target_name}::${target_name}")
|
||||||
|
|
||||||
|
if (Lib${_name}_FOUND)
|
||||||
|
mark_as_advanced(
|
||||||
|
Lib${_name}
|
||||||
|
Lib${_name}_inc
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(Lib${_name} MATCHES "LibBoost")
|
||||||
|
add_library(${target_name}::headers INTERFACE IMPORTED)
|
||||||
|
set_target_properties(${target_name}::headers PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${Lib${_name}_inc}
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${Lib${_name}_inc}
|
||||||
|
)
|
||||||
|
elseif(Lib${_name} MATCHES "SDL2")
|
||||||
|
add_library(${target_name}::${target_name} UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(${target_name}::${target_name} PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${Lib${_name}}
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${Lib${_name}_inc}/SDL
|
||||||
|
)
|
||||||
|
elseif (Lib${_name} AND NOT TARGET ${target_name}::${target_name})
|
||||||
|
add_library(${target_name}::${target_name} UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(${target_name}::${target_name} PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${Lib${_name}}
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${Lib${_name}_inc}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
35
cmake/PrecompiledHeader.cmake
Normal file
35
cmake/PrecompiledHeader.cmake
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Adds a custom precompiled header. This header must be included in the code if not added with FORCE_INCLUDE
|
||||||
|
function(precompile_header _target _header _source)
|
||||||
|
set(single_args FORCE_INCLUDE)
|
||||||
|
cmake_parse_arguments(args "" "${single_args}" "" ${ARGN})
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
# Solution based opon https://www.dominikgrabiec.com/posts/2022/10/18/precompiled_header_snippet.html
|
||||||
|
target_compile_options(${_target}
|
||||||
|
PRIVATE
|
||||||
|
"/Yu${_header}"
|
||||||
|
)
|
||||||
|
set_source_files_properties(${_source}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_OPTIONS "/Yc${_header}"
|
||||||
|
)
|
||||||
|
if(${args_FORCE_INCLUDE})
|
||||||
|
set_source_files_properties(${_source}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_OPTIONS /FI${_header}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU|AppleClang" OR CMAKE_C_COMPILER_ID MATCHES "Clang|GNU|AppleClang")
|
||||||
|
# Solution is based on internal cmake code
|
||||||
|
set_source_files_properties(${_source}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_OPTIONS -Winvalid-pch -x ${_header}.gch
|
||||||
|
)
|
||||||
|
if(${args_FORCE_INCLUDE})
|
||||||
|
set_source_files_properties(${_source}
|
||||||
|
PROPERTIES
|
||||||
|
COMPILE_OPTIONS include ${_header}.gch
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
33
cmake/SetupWindowsLibs.cmake
Normal file
33
cmake/SetupWindowsLibs.cmake
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Checks out the SVN Revision of windows libraries. Additionally sets up the environment for cmake.
|
||||||
|
# To update the libraries change the 'SVN_REVISION'. Important: the '-r' in the Revision must be retained.
|
||||||
|
message(STATUS "Fetching Windows prebuild Libraries for ${ARCH}")
|
||||||
|
if(fetch-prebuild-libs)
|
||||||
|
include(FetchContent)
|
||||||
|
if(ARCH STREQUAL "amd64")
|
||||||
|
set(REPO_NAME windows-libs-amd64)
|
||||||
|
else()
|
||||||
|
set(REPO_NAME windows-libs)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FetchContent_Populate(
|
||||||
|
prebuild_libs
|
||||||
|
SVN_REPOSITORY https://svn.wildfiregames.com/public/${REPO_NAME}/trunk
|
||||||
|
SVN_REVISION -r28278
|
||||||
|
SOURCE_DIR ${0AD_EXT_LIBDIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
message(STATUS "Copy dependencies' binaries to 'binaries/system/' and adding to 'CMAKE_PREFIX_PATH'")
|
||||||
|
set(DIR_LIST cpp-httplib enet fcollada freetype gloox iconv icu libcurl libpng libsodium libxml2 microsoft miniupnpc nvtt openal sdl2 spidermonkey vorbis zlib)
|
||||||
|
foreach(dir ${DIR_LIST})
|
||||||
|
file(COPY ${0AD_EXT_LIBDIR}/${dir}/bin DESTINATION ${CMAKE_SOURCE_DIR}/binaries/system)
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH ${0AD_EXT_LIBDIR}/${dir})
|
||||||
|
endforeach()
|
||||||
|
# Add the whole libraries directory to CMAKE_PREFIX_PATH. May be redundand but needed for wxWidgets
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH ${0AD_EXT_LIBDIR})
|
||||||
|
# Add libraries not set during binary copy
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH ${0AD_EXT_LIBDIR}/fmt)
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH ${0AD_EXT_LIBDIR}/libzip)
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH ${0AD_EXT_LIBDIR}/cxxtest-4.4)
|
||||||
|
|
||||||
|
message(STATUS "Copy build tools to 'build/bin'")
|
||||||
|
file(COPY ${0AD_EXT_LIBDIR}/cxxtest-4.4/bin DESTINATION ${CMAKE_SOURCE_DIR}/build/bin)
|
||||||
|
|
@ -6,7 +6,11 @@
|
||||||
|
|
||||||
## Building the Doxygen documentation
|
## Building the Doxygen documentation
|
||||||
|
|
||||||
To generate the Doxygen documentation: run "cmake -S . -B output && cmake --build output".
|
To generate the Doxygen documentation:
|
||||||
|
|
||||||
|
```console
|
||||||
|
cmake -S 0ad/rootdir -B output && cmake --build output --target docs
|
||||||
|
```
|
||||||
|
|
||||||
If you build the documentation with cmake, the output is located in the folder html inside your
|
If you build the documentation with cmake, the output is located in the folder html inside your
|
||||||
specified build directory.
|
specified build directory.
|
||||||
|
|
|
||||||
|
|
@ -1,64 +1,66 @@
|
||||||
cmake_minimum_required(VERSION 3.18.4...3.28.0)
|
cmake_minimum_required(VERSION 3.25.1...4.0.0)
|
||||||
|
|
||||||
project(Pyrogenesis DESCRIPTION "Pyrogenesis, a RTS Engine" LANGUAGES NONE)
|
|
||||||
|
|
||||||
# Check if Doxygen and graphviz are installed.
|
# Check if Doxygen and graphviz are installed.
|
||||||
find_package(Doxygen 1.9.1 REQUIRED dot)
|
find_package(Doxygen 1.9.1 REQUIRED dot)
|
||||||
|
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(doxygen_awesome_css
|
message(STATUS "Fetching doxygen_awesome_css")
|
||||||
GIT_REPOSITORY https://github.com/jothepro/doxygen-awesome-css
|
FetchContent_Declare(doxygen_awesome_css
|
||||||
GIT_TAG v2.3.3
|
GIT_REPOSITORY https://github.com/jothepro/doxygen-awesome-css
|
||||||
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/styling
|
GIT_TAG v2.4.2
|
||||||
)
|
SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/styling
|
||||||
FetchContent_MakeAvailable(doxygen_awesome_css)
|
)
|
||||||
|
FetchContent_MakeAvailable(doxygen_awesome_css)
|
||||||
|
|
||||||
# Get current Branch Name to set it as the Project Number.
|
# Get current Branch Name to set it as the Project Number.
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
if(Git_FOUND)
|
if(Git_FOUND)
|
||||||
set(ENV{GIT_DISCOVERY_ACROSS_FILESYSTEM} 1)
|
set(ENV{GIT_DISCOVERY_ACROSS_FILESYSTEM} 1)
|
||||||
execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --is-inside-work-tree OUTPUT_VARIABLE IS_GIT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
|
execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --is-inside-work-tree OUTPUT_VARIABLE IS_GIT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
|
||||||
if(IS_GIT)
|
if(IS_GIT)
|
||||||
execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --abbrev-ref HEAD OUTPUT_VARIABLE CURRENT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --abbrev-ref HEAD OUTPUT_VARIABLE CURRENT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Doxygen Configuration.
|
# Doxygen Configuration.
|
||||||
if(CURRENT_BRANCH)
|
set(DOXYGEN_PROJECT_NAME "Pyrogenesis")
|
||||||
set(DOXYGEN_PROJECT_NUMBER ${CURRENT_BRANCH})
|
set(DOXYGEN_PROJECT_BRIEF "Pyrogenesis, a RTS Engine")
|
||||||
else()
|
if(CURRENT_BRANCH)
|
||||||
set(DOXYGEN_PROJECT_NUMBER main)
|
set(DOXYGEN_PROJECT_NUMBER ${CURRENT_BRANCH})
|
||||||
endif()
|
else()
|
||||||
set(DOXYGEN_PROJECT_LOGO ${CMAKE_CURRENT_SOURCE_DIR}/pyrogenesis.png)
|
set(DOXYGEN_PROJECT_NUMBER main)
|
||||||
set(DOXYGEN_TAB_SIZE 4)
|
endif()
|
||||||
set(DOXYGEN_EXCLUDE_PATTERNS */.svn* */tests/test_*)
|
set(DOXYGEN_PROJECT_LOGO ${CMAKE_CURRENT_SOURCE_DIR}/pyrogenesis.png)
|
||||||
set(DOXYGEN_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../source)
|
set(DOXYGEN_TAB_SIZE 4)
|
||||||
set(DOXYGEN_EXAMPLE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../source)
|
set(DOXYGEN_EXCLUDE_PATTERNS */.svn* */tests/test_*)
|
||||||
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../../source/tools ${CMAKE_CURRENT_SOURCE_DIR}/../../source/third_party)
|
set(DOXYGEN_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/source)
|
||||||
set(DOXYGEN_GENERATE_TREEVIEW YES)
|
set(DOXYGEN_EXAMPLE_PATH ${CMAKE_SOURCE_DIR}/source)
|
||||||
set(DOXYGEN_HTML_EXTRA_STYLESHEET ${doxygen_awesome_css_SOURCE_DIR}/doxygen-awesome.css ${CMAKE_CURRENT_SOURCE_DIR}/style.css)
|
set(DOXYGEN_EXCLUDE ${CMAKE_SOURCE_DIR}/source/tools ${CMAKE_SOURCE_DIR}/source/third_party)
|
||||||
set(DOXYGEN_JAVADOC_AUTOBRIEF YES)
|
set(DOXYGEN_GENERATE_TREEVIEW YES)
|
||||||
set(DOXYGEN_EXTRACT_ALL YES)
|
set(DOXYGEN_HTML_EXTRA_STYLESHEET ${doxygen_awesome_css_SOURCE_DIR}/doxygen-awesome.css ${CMAKE_CURRENT_SOURCE_DIR}/style.css)
|
||||||
set(DOXYGEN_EXTRACT_PRIVATE YES)
|
set(DOXYGEN_JAVADOC_AUTOBRIEF YES)
|
||||||
set(DOXYGEN_EXTRACT_STATIC YES)
|
set(DOXYGEN_EXTRACT_ALL YES)
|
||||||
set(DOXYGEN_EXTRACT_ANON_NSPACES YES)
|
set(DOXYGEN_EXTRACT_PRIVATE YES)
|
||||||
set(DOXYGEN_SHOW_DIRECTORIES YES)
|
set(DOXYGEN_EXTRACT_STATIC YES)
|
||||||
set(DOXYGEN_STRIP_CODE_COMMENTS NO)
|
set(DOXYGEN_EXTRACT_ANON_NSPACES YES)
|
||||||
set(DOXYGEN_MACRO_EXPANSION YES)
|
set(DOXYGEN_SHOW_DIRECTORIES YES)
|
||||||
set(DOXYGEN_EXPAND_ONLY_PREDEF YES)
|
set(DOXYGEN_STRIP_CODE_COMMENTS NO)
|
||||||
set(DOXYGEN_GENERATE_TODOLIST NO)
|
set(DOXYGEN_MACRO_EXPANSION YES)
|
||||||
set(DOXYGEN_PREDEFINED "UNUSED(x)=x" "METHODDEF(x)=static x" "GLOBAL(x)=x")
|
set(DOXYGEN_EXPAND_ONLY_PREDEF YES)
|
||||||
set(DOXYGEN_EXPAND_AS_DEFINED DEFAULT_COMPONENT_ALLOCATOR DEFAULT_SCRIPT_WRAPPER DEFAULT_INTERFACE_WRAPPER DEFAULT_MESSAGE_IMPL MESSAGE INTERFACE COMPONENT GUISTDTYPE)
|
set(DOXYGEN_GENERATE_TODOLIST NO)
|
||||||
set(DOXYGEN_WARN_LOGFILE doxygen.log)
|
set(DOXYGEN_PREDEFINED "UNUSED(x)=x" "METHODDEF(x)=static x" "GLOBAL(x)=x")
|
||||||
|
set(DOXYGEN_EXPAND_AS_DEFINED DEFAULT_COMPONENT_ALLOCATOR DEFAULT_SCRIPT_WRAPPER DEFAULT_INTERFACE_WRAPPER DEFAULT_MESSAGE_IMPL MESSAGE INTERFACE COMPONENT GUISTDTYPE)
|
||||||
|
set(DOXYGEN_WARN_LOGFILE doxygen.log)
|
||||||
|
|
||||||
doxygen_add_docs(${CMAKE_PROJECT_NAME}
|
doxygen_add_docs(docs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../source
|
${CMAKE_SOURCE_DIR}/source
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mainpage.dox
|
${CMAKE_CURRENT_SOURCE_DIR}/mainpage.dox
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../LICENSE.md
|
${CMAKE_SOURCE_DIR}/LICENSE.md
|
||||||
ALL)
|
COMMENT "Creating Doxygen for the engine."
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
message(SEND_ERROR "Make sure Doxygen is installed and usable")
|
message(SEND_ERROR "Make sure Doxygen is installed and usable")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -53,25 +53,6 @@ public:
|
||||||
void SetElevation(float f);
|
void SetElevation(float f);
|
||||||
void SetRotation(float f);
|
void SetRotation(float f);
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate brightness of a point of a unit with the given normal vector,
|
|
||||||
* for rendering with CPU lighting.
|
|
||||||
* The resulting color contains both ambient and diffuse light.
|
|
||||||
* To cope with sun overbrightness, the color is scaled by 0.5.
|
|
||||||
*
|
|
||||||
* @param normal normal vector (must have length 1)
|
|
||||||
*/
|
|
||||||
RGBColor EvaluateUnitScaled(const CVector3D& normal) const
|
|
||||||
{
|
|
||||||
float dot = -normal.Dot(m_SunDir);
|
|
||||||
|
|
||||||
RGBColor color = m_AmbientColor;
|
|
||||||
if (dot > 0)
|
|
||||||
color += m_SunColor * dot;
|
|
||||||
|
|
||||||
return color * 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparison operators
|
// Comparison operators
|
||||||
bool operator==(const CLightEnv& o) const
|
bool operator==(const CLightEnv& o) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Renderer::Backend { class IDeviceCommandContext; }
|
||||||
* This computes and binds per-vertex data; the modifier is responsible
|
* This computes and binds per-vertex data; the modifier is responsible
|
||||||
* for setting any shader uniforms etc.
|
* for setting any shader uniforms etc.
|
||||||
*/
|
*/
|
||||||
class CPUSkinnedModelVertexRenderer : public ModelVertexRenderer
|
class CPUSkinnedModelVertexRenderer final : public ModelVertexRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CPUSkinnedModelVertexRenderer();
|
CPUSkinnedModelVertexRenderer();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2025 Wildfire Games.
|
/* Copyright (C) 2026 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Renderer::Backend { class IShaderProgram; }
|
||||||
* This computes and binds per-vertex data; the modifier is responsible
|
* This computes and binds per-vertex data; the modifier is responsible
|
||||||
* for setting any shader uniforms etc.
|
* for setting any shader uniforms etc.
|
||||||
*/
|
*/
|
||||||
class GPUSkinnedModelModelRenderer : public ModelVertexRenderer
|
class GPUSkinnedModelModelRenderer final : public ModelVertexRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPUSkinnedModelModelRenderer();
|
GPUSkinnedModelModelRenderer();
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ struct InstancingModelRendererInternals;
|
||||||
* This computes and binds per-vertex data; the modifier is responsible
|
* This computes and binds per-vertex data; the modifier is responsible
|
||||||
* for setting any shader uniforms etc (including the instancing transform).
|
* for setting any shader uniforms etc (including the instancing transform).
|
||||||
*/
|
*/
|
||||||
class InstancingModelRenderer : public ModelVertexRenderer
|
class InstancingModelRenderer final : public ModelVertexRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InstancingModelRenderer();
|
InstancingModelRenderer();
|
||||||
|
|
|
||||||
|
|
@ -102,15 +102,11 @@ CMaterial::Pass GetMaterialPassFromCullGroup(const int cullGroup, const ERenderM
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelRenderer::Init()
|
// static
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to copy object-space position and normal vectors into arrays.
|
|
||||||
void ModelRenderer::CopyPositionAndNormals(
|
void ModelRenderer::CopyPositionAndNormals(
|
||||||
const CModelDefPtr& mdef,
|
const CModelDefPtr& mdef,
|
||||||
const VertexArrayIterator<CVector3D>& Position,
|
const VertexArrayIterator<CVector3D>& Position,
|
||||||
const VertexArrayIterator<CVector3D>& Normal)
|
const VertexArrayIterator<CVector3D>& Normal)
|
||||||
{
|
{
|
||||||
size_t numVertices = mdef->GetNumVertices();
|
size_t numVertices = mdef->GetNumVertices();
|
||||||
SModelVertex* vertices = mdef->GetVertices();
|
SModelVertex* vertices = mdef->GetVertices();
|
||||||
|
|
@ -122,11 +118,11 @@ void ModelRenderer::CopyPositionAndNormals(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to transform position and normal vectors into world-space.
|
// static
|
||||||
void ModelRenderer::BuildPositionAndNormals(
|
void ModelRenderer::BuildPositionAndNormals(
|
||||||
CModel* model,
|
CModel* model,
|
||||||
const VertexArrayIterator<CVector3D>& Position,
|
const VertexArrayIterator<CVector3D>& Position,
|
||||||
const VertexArrayIterator<CVector3D>& Normal)
|
const VertexArrayIterator<CVector3D>& Normal)
|
||||||
{
|
{
|
||||||
CModelDefPtr mdef = model->GetModelDef();
|
CModelDefPtr mdef = model->GetModelDef();
|
||||||
size_t numVertices = mdef->GetNumVertices();
|
size_t numVertices = mdef->GetNumVertices();
|
||||||
|
|
@ -160,43 +156,16 @@ void ModelRenderer::BuildPositionAndNormals(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
// Helper function for lighting
|
|
||||||
void ModelRenderer::BuildColor4ub(
|
|
||||||
CModel* model,
|
|
||||||
const VertexArrayIterator<CVector3D>& Normal,
|
|
||||||
const VertexArrayIterator<SColor4ub>& Color)
|
|
||||||
{
|
|
||||||
PROFILE("lighting vertices");
|
|
||||||
|
|
||||||
CModelDefPtr mdef = model->GetModelDef();
|
|
||||||
size_t numVertices = mdef->GetNumVertices();
|
|
||||||
const CLightEnv& lightEnv = g_Renderer.GetSceneRenderer().GetLightEnv();
|
|
||||||
CColor shadingColor = model->GetShadingColor();
|
|
||||||
|
|
||||||
for (size_t j = 0; j < numVertices; ++j)
|
|
||||||
{
|
|
||||||
RGBColor tempcolor = lightEnv.EvaluateUnitScaled(Normal[j]);
|
|
||||||
tempcolor.X *= shadingColor.r;
|
|
||||||
tempcolor.Y *= shadingColor.g;
|
|
||||||
tempcolor.Z *= shadingColor.b;
|
|
||||||
Color[j] = ConvertRGBColorTo4ub(tempcolor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ModelRenderer::GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning)
|
void ModelRenderer::GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning)
|
||||||
{
|
{
|
||||||
MikkTSpace ms(mdef, newVertices, gpuSkinning);
|
MikkTSpace ms(mdef, newVertices, gpuSkinning);
|
||||||
ms.Generate();
|
ms.Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
// Copy UV coordinates
|
|
||||||
void ModelRenderer::BuildUV(
|
void ModelRenderer::BuildUV(
|
||||||
const CModelDefPtr& mdef,
|
const CModelDefPtr& mdef, const VertexArrayIterator<float[2]>& UV, int UVset)
|
||||||
const VertexArrayIterator<float[2]>& UV,
|
|
||||||
int UVset)
|
|
||||||
{
|
{
|
||||||
const size_t numVertices = mdef->GetNumVertices();
|
const size_t numVertices = mdef->GetNumVertices();
|
||||||
const size_t numberOfUVPerVertex = mdef->GetNumUVsPerVertex();
|
const size_t numberOfUVPerVertex = mdef->GetNumUVsPerVertex();
|
||||||
|
|
@ -209,11 +178,9 @@ void ModelRenderer::BuildUV(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
// Build default indices array.
|
|
||||||
void ModelRenderer::BuildIndices(
|
void ModelRenderer::BuildIndices(
|
||||||
const CModelDefPtr& mdef,
|
const CModelDefPtr& mdef, const VertexArrayIterator<u16>& Indices)
|
||||||
const VertexArrayIterator<u16>& Indices)
|
|
||||||
{
|
{
|
||||||
size_t idxidx = 0;
|
size_t idxidx = 0;
|
||||||
SModelFace* faces = mdef->GetFaces();
|
SModelFace* faces = mdef->GetFaces();
|
||||||
|
|
@ -227,105 +194,6 @@ void ModelRenderer::BuildIndices(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ShaderModelRenderer implementation
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal data of the ShaderModelRenderer.
|
|
||||||
*
|
|
||||||
* Separated into the source file to increase implementation hiding (and to
|
|
||||||
* avoid some causes of recompiles).
|
|
||||||
*/
|
|
||||||
struct ShaderModelRenderer::ShaderModelRendererInternals
|
|
||||||
{
|
|
||||||
ShaderModelRendererInternals(ShaderModelRenderer* r) : m_Renderer(r) { }
|
|
||||||
|
|
||||||
/// Back-link to "our" renderer
|
|
||||||
ShaderModelRenderer* m_Renderer;
|
|
||||||
|
|
||||||
/// ModelVertexRenderer used for vertex transformations
|
|
||||||
ModelVertexRendererPtr vertexRenderer;
|
|
||||||
|
|
||||||
/// List of submitted models for rendering in this frame
|
|
||||||
std::vector<CModel*> submissions[CSceneRenderer::CULL_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Construction/Destruction
|
|
||||||
ShaderModelRenderer::ShaderModelRenderer(ModelVertexRendererPtr vertexrenderer)
|
|
||||||
{
|
|
||||||
m = new ShaderModelRendererInternals(this);
|
|
||||||
m->vertexRenderer = vertexrenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShaderModelRenderer::~ShaderModelRenderer()
|
|
||||||
{
|
|
||||||
delete m;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit one model.
|
|
||||||
void ShaderModelRenderer::Submit(int cullGroup, CModel* model)
|
|
||||||
{
|
|
||||||
CModelRData* rdata = (CModelRData*)model->GetRenderData();
|
|
||||||
|
|
||||||
// Ensure model data is valid
|
|
||||||
const void* key = m->vertexRenderer.get();
|
|
||||||
if (!rdata || rdata->GetKey() != key)
|
|
||||||
{
|
|
||||||
model->InvalidatePosition();
|
|
||||||
rdata = m->vertexRenderer->CreateModelData(key, model);
|
|
||||||
model->SetRenderData(rdata);
|
|
||||||
model->SetDirty(~0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->submissions[cullGroup].push_back(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Call update for all submitted models and enter the rendering phase
|
|
||||||
void ShaderModelRenderer::PrepareModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
|
||||||
{
|
|
||||||
for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
|
||||||
{
|
|
||||||
for (CModel* model : m->submissions[cullGroup])
|
|
||||||
{
|
|
||||||
model->ValidatePosition();
|
|
||||||
|
|
||||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
|
||||||
ENSURE(rdata->GetKey() == m->vertexRenderer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
m->vertexRenderer->UpdateModelsData(deviceCommandContext, m->submissions[cullGroup]);
|
|
||||||
|
|
||||||
for (CModel* model : m->submissions[cullGroup])
|
|
||||||
{
|
|
||||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
|
||||||
rdata->m_UpdateFlags = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShaderModelRenderer::UploadModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
|
||||||
{
|
|
||||||
for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
|
||||||
{
|
|
||||||
m->vertexRenderer->UploadModelsData(deviceCommandContext, m->submissions[cullGroup]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the submissions list
|
|
||||||
void ShaderModelRenderer::EndFrame()
|
|
||||||
{
|
|
||||||
for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
|
||||||
m->submissions[cullGroup].clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Helper structs for ShaderModelRenderer::Render():
|
// Helper structs for ShaderModelRenderer::Render():
|
||||||
|
|
||||||
struct SMRSortByDistItem
|
struct SMRSortByDistItem
|
||||||
|
|
@ -413,12 +281,12 @@ struct SMRCompareTechBucket
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void ShaderModelRenderer::Render(
|
void ModelRenderer::Render(
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||||
const RenderModifierPtr& modifier, const CShaderDefines& context,
|
ModelVertexRenderer& modelVertexRenderer, RenderModifier& modifier, const CShaderDefines& context,
|
||||||
int cullGroup, int flags, const ERenderMode renderMode)
|
int cullGroup, int flags, const ERenderMode renderMode, std::span<CModel*> submissions)
|
||||||
{
|
{
|
||||||
if (m->submissions[cullGroup].empty())
|
if (submissions.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CMatrix3D worldToCam;
|
CMatrix3D worldToCam;
|
||||||
|
|
@ -429,7 +297,7 @@ void ShaderModelRenderer::Render(
|
||||||
/*
|
/*
|
||||||
* Rendering approach:
|
* Rendering approach:
|
||||||
*
|
*
|
||||||
* m->submissions contains the list of CModels to render.
|
* submissions contains the list of CModels to render.
|
||||||
*
|
*
|
||||||
* The data we need to render a model is:
|
* The data we need to render a model is:
|
||||||
* - CShaderTechnique
|
* - CShaderTechnique
|
||||||
|
|
@ -497,10 +365,9 @@ void ShaderModelRenderer::Render(
|
||||||
{
|
{
|
||||||
PROFILE3("bucketing by material");
|
PROFILE3("bucketing by material");
|
||||||
|
|
||||||
for (size_t i = 0; i < m->submissions[cullGroup].size(); ++i)
|
for (CModel* model : submissions)
|
||||||
{
|
{
|
||||||
CModel* model = m->submissions[cullGroup][i];
|
const CMaterial& material{model->GetMaterial()};
|
||||||
const CMaterial material{model->GetMaterial()};
|
|
||||||
const CShaderDefines& defines{material.GetShaderDefines()};
|
const CShaderDefines& defines{material.GetShaderDefines()};
|
||||||
const CStrIntern shaderEffect{material.GetShaderEffect(materialPass)};
|
const CStrIntern shaderEffect{material.GetShaderEffect(materialPass)};
|
||||||
SMRMaterialBucketKey key(shaderEffect, defines);
|
SMRMaterialBucketKey key(shaderEffect, defines);
|
||||||
|
|
@ -683,7 +550,7 @@ void ShaderModelRenderer::Render(
|
||||||
|
|
||||||
Renderer::Backend::IShaderProgram* shader = currentTech->GetShader(pass);
|
Renderer::Backend::IShaderProgram* shader = currentTech->GetShader(pass);
|
||||||
|
|
||||||
modifier->BeginPass(deviceCommandContext, shader);
|
modifier.BeginPass(deviceCommandContext, shader);
|
||||||
|
|
||||||
// TODO: Use a more generic approach to handle bound queries.
|
// TODO: Use a more generic approach to handle bound queries.
|
||||||
bool boundTime = false;
|
bool boundTime = false;
|
||||||
|
|
@ -753,7 +620,7 @@ void ShaderModelRenderer::Render(
|
||||||
if (newModeldef != currentModeldef)
|
if (newModeldef != currentModeldef)
|
||||||
{
|
{
|
||||||
currentModeldef = newModeldef;
|
currentModeldef = newModeldef;
|
||||||
m->vertexRenderer->PrepareModelDef(deviceCommandContext, *currentModeldef);
|
modelVertexRenderer.PrepareModelDef(deviceCommandContext, *currentModeldef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind all uniforms when any change
|
// Bind all uniforms when any change
|
||||||
|
|
@ -813,12 +680,12 @@ void ShaderModelRenderer::Render(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier->PrepareModel(deviceCommandContext, model);
|
modifier.PrepareModel(deviceCommandContext, model);
|
||||||
|
|
||||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||||
ENSURE(rdata->GetKey() == m->vertexRenderer.get());
|
ENSURE(rdata->GetKey() == &modelVertexRenderer);
|
||||||
|
|
||||||
m->vertexRenderer->RenderModel(deviceCommandContext, shader, model, rdata);
|
modelVertexRenderer.RenderModel(deviceCommandContext, shader, model, rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "lib/types.h"
|
#include "lib/types.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CModel;
|
class CModel;
|
||||||
|
|
@ -39,17 +40,8 @@ namespace Renderer::Backend { class IDeviceCommandContext; }
|
||||||
struct SColor4ub;
|
struct SColor4ub;
|
||||||
template <typename T> class VertexArrayIterator;
|
template <typename T> class VertexArrayIterator;
|
||||||
|
|
||||||
class RenderModifier;
|
|
||||||
typedef std::shared_ptr<RenderModifier> RenderModifierPtr;
|
|
||||||
|
|
||||||
class LitRenderModifier;
|
|
||||||
typedef std::shared_ptr<LitRenderModifier> LitRenderModifierPtr;
|
|
||||||
|
|
||||||
class ModelVertexRenderer;
|
class ModelVertexRenderer;
|
||||||
typedef std::shared_ptr<ModelVertexRenderer> ModelVertexRendererPtr;
|
class RenderModifier;
|
||||||
|
|
||||||
class ModelRenderer;
|
|
||||||
typedef std::shared_ptr<ModelRenderer> ModelRendererPtr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CModelRData: Render data that is maintained per CModel.
|
* Class CModelRData: Render data that is maintained per CModel.
|
||||||
|
|
@ -83,25 +75,12 @@ private:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ModelRenderer: Abstract base class for all model renders.
|
* ModelRenderer renders a per-frame list of models. It loads the appropriate
|
||||||
|
* shaders for rendering each model, and that batches by shader technique (and
|
||||||
|
* by mesh and texture).
|
||||||
*
|
*
|
||||||
* A ModelRenderer manages a per-frame list of models.
|
* ModelRenderer delegates vertex transformation/setup to a
|
||||||
*
|
* ModelVertexRenderer. It delegates fragment stage setup to a RenderModifier.
|
||||||
* It is supposed to be derived in order to create new ways in which
|
|
||||||
* the per-frame list of models can be managed (for batching, for
|
|
||||||
* transparent rendering, etc.) or potentially for rarely used special
|
|
||||||
* effects.
|
|
||||||
*
|
|
||||||
* A typical ModelRenderer will delegate vertex transformation/setup
|
|
||||||
* to a ModelVertexRenderer.
|
|
||||||
* It will delegate fragment stage setup to a RenderModifier.
|
|
||||||
*
|
|
||||||
* For most purposes, you should use a BatchModelRenderer with
|
|
||||||
* specialized ModelVertexRenderer and RenderModifier implementations.
|
|
||||||
*
|
|
||||||
* It is suggested that a derived class implement the provided generic
|
|
||||||
* Render function, however in some cases it may be necessary to supply
|
|
||||||
* a Render function with a different prototype.
|
|
||||||
*
|
*
|
||||||
* ModelRenderer also contains a number of static helper functions
|
* ModelRenderer also contains a number of static helper functions
|
||||||
* for building vertex arrays.
|
* for building vertex arrays.
|
||||||
|
|
@ -109,61 +88,10 @@ private:
|
||||||
class ModelRenderer
|
class ModelRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModelRenderer() { }
|
|
||||||
virtual ~ModelRenderer() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise global settings.
|
|
||||||
* Should be called before using the class.
|
|
||||||
*/
|
|
||||||
static void Init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit: Submit a model for rendering this frame.
|
|
||||||
*
|
|
||||||
* preconditions : The model must not have been submitted to any
|
|
||||||
* ModelRenderer in this frame. Submit may only be called
|
|
||||||
* after EndFrame and before PrepareModels.
|
|
||||||
*
|
|
||||||
* @param model The model that will be added to the list of models
|
|
||||||
* submitted this frame.
|
|
||||||
*/
|
|
||||||
virtual void Submit(int cullGroup, CModel* model) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PrepareModels: Calculate renderer data for all previously
|
|
||||||
* submitted models.
|
|
||||||
*
|
|
||||||
* Must be called before any rendering calls and after all models
|
|
||||||
* for this frame have been submitted.
|
|
||||||
*/
|
|
||||||
virtual void PrepareModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload renderer data for all previously submitted models to backend.
|
|
||||||
*
|
|
||||||
* Must be called before any rendering calls and after all models
|
|
||||||
* for this frame have been prepared.
|
|
||||||
*/
|
|
||||||
virtual void UploadModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EndFrame: Remove all models from the list of submitted
|
|
||||||
* models.
|
|
||||||
*/
|
|
||||||
virtual void EndFrame() = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render: Render submitted models, using the given RenderModifier to setup
|
* Render: Render submitted models, using the given RenderModifier to setup
|
||||||
* the fragment stage.
|
* the fragment stage.
|
||||||
*
|
*
|
||||||
* @note It is suggested that derived model renderers implement and use
|
|
||||||
* this Render functions. However, a highly specialized model renderer
|
|
||||||
* may need to "disable" this function and provide its own Render function
|
|
||||||
* with a different prototype.
|
|
||||||
*
|
|
||||||
* preconditions : PrepareModels must be called after all models have been
|
* preconditions : PrepareModels must be called after all models have been
|
||||||
* submitted and before calling Render.
|
* submitted and before calling Render.
|
||||||
*
|
*
|
||||||
|
|
@ -172,10 +100,10 @@ public:
|
||||||
* If flags is non-zero, only models that contain flags in their
|
* If flags is non-zero, only models that contain flags in their
|
||||||
* CModel::GetFlags() are rendered.
|
* CModel::GetFlags() are rendered.
|
||||||
*/
|
*/
|
||||||
virtual void Render(
|
void Render(
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||||
const RenderModifierPtr& modifier, const CShaderDefines& context,
|
ModelVertexRenderer& modelVertexRenderer, RenderModifier& modifier, const CShaderDefines& context,
|
||||||
int cullGroup, int flags, const ERenderMode renderMode) = 0;
|
int cullGroup, int flags, const ERenderMode renderMode, std::span<CModel*> submissions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
||||||
|
|
@ -190,9 +118,9 @@ public:
|
||||||
* The array behind the iterator must be as large as the Position array.
|
* The array behind the iterator must be as large as the Position array.
|
||||||
*/
|
*/
|
||||||
static void CopyPositionAndNormals(
|
static void CopyPositionAndNormals(
|
||||||
const CModelDefPtr& mdef,
|
const CModelDefPtr& mdef,
|
||||||
const VertexArrayIterator<CVector3D>& Position,
|
const VertexArrayIterator<CVector3D>& Position,
|
||||||
const VertexArrayIterator<CVector3D>& Normal);
|
const VertexArrayIterator<CVector3D>& Normal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BuildPositionAndNormals: Build animated vertices and normals,
|
* BuildPositionAndNormals: Build animated vertices and normals,
|
||||||
|
|
@ -209,25 +137,9 @@ public:
|
||||||
* the Position array.
|
* the Position array.
|
||||||
*/
|
*/
|
||||||
static void BuildPositionAndNormals(
|
static void BuildPositionAndNormals(
|
||||||
CModel* model,
|
CModel* model,
|
||||||
const VertexArrayIterator<CVector3D>& Position,
|
const VertexArrayIterator<CVector3D>& Position,
|
||||||
const VertexArrayIterator<CVector3D>& Normal);
|
const VertexArrayIterator<CVector3D>& Normal);
|
||||||
|
|
||||||
/**
|
|
||||||
* BuildColor4ub: Build lighting colors for the given model,
|
|
||||||
* based on previously calculated world space normals.
|
|
||||||
*
|
|
||||||
* @param model The model that is to be lit.
|
|
||||||
* @param Normal Array of the model's normal vectors, animated and
|
|
||||||
* transformed into world space.
|
|
||||||
* @param Color Points to the array that will receive the lit vertex color.
|
|
||||||
* The array behind the iterator must large enough to hold
|
|
||||||
* model->GetModelDef()->GetNumVertices() vertices.
|
|
||||||
*/
|
|
||||||
static void BuildColor4ub(
|
|
||||||
CModel* model,
|
|
||||||
const VertexArrayIterator<CVector3D>& Normal,
|
|
||||||
const VertexArrayIterator<SColor4ub>& Color);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BuildUV: Copy UV coordinates into the given vertex array.
|
* BuildUV: Copy UV coordinates into the given vertex array.
|
||||||
|
|
@ -238,9 +150,9 @@ public:
|
||||||
* mdef->GetNumVertices() vertices.
|
* mdef->GetNumVertices() vertices.
|
||||||
*/
|
*/
|
||||||
static void BuildUV(
|
static void BuildUV(
|
||||||
const CModelDefPtr& mdef,
|
const CModelDefPtr& mdef,
|
||||||
const VertexArrayIterator<float[2]>& UV,
|
const VertexArrayIterator<float[2]>& UV,
|
||||||
int UVset);
|
int UVset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BuildIndices: Create the indices array for the given CModelDef.
|
* BuildIndices: Create the indices array for the given CModelDef.
|
||||||
|
|
@ -250,8 +162,7 @@ public:
|
||||||
* mdef->GetNumFaces()*3 elements.
|
* mdef->GetNumFaces()*3 elements.
|
||||||
*/
|
*/
|
||||||
static void BuildIndices(
|
static void BuildIndices(
|
||||||
const CModelDefPtr& mdef,
|
const CModelDefPtr& mdef, const VertexArrayIterator<u16>& Indices);
|
||||||
const VertexArrayIterator<u16>& Indices);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GenTangents: Generate tangents for the given CModelDef.
|
* GenTangents: Generate tangents for the given CModelDef.
|
||||||
|
|
@ -263,33 +174,4 @@ public:
|
||||||
static void GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning);
|
static void GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of ModelRenderer that loads the appropriate shaders for
|
|
||||||
* rendering each model, and that batches by shader technique (and by mesh and texture).
|
|
||||||
*/
|
|
||||||
class ShaderModelRenderer : public ModelRenderer
|
|
||||||
{
|
|
||||||
friend struct ShaderModelRendererInternals;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ShaderModelRenderer(ModelVertexRendererPtr vertexrender);
|
|
||||||
~ShaderModelRenderer() override;
|
|
||||||
|
|
||||||
// Batching implementations
|
|
||||||
void Submit(int cullGroup, CModel* model) override;
|
|
||||||
void PrepareModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext) override;
|
|
||||||
void UploadModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext) override;
|
|
||||||
void EndFrame() override;
|
|
||||||
void Render(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
|
||||||
const RenderModifierPtr& modifier, const CShaderDefines& context,
|
|
||||||
int cullGroup, int flags, const ERenderMode renderMode) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct ShaderModelRendererInternals;
|
|
||||||
ShaderModelRendererInternals* m;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDED_MODELRENDERER
|
#endif // INCLUDED_MODELRENDERER
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@
|
||||||
#include "ps/VideoMode.h"
|
#include "ps/VideoMode.h"
|
||||||
#include "ps/World.h"
|
#include "ps/World.h"
|
||||||
#include "renderer/DebugRenderer.h"
|
#include "renderer/DebugRenderer.h"
|
||||||
#include "renderer/ModelRenderer.h"
|
|
||||||
#include "renderer/PostprocManager.h"
|
#include "renderer/PostprocManager.h"
|
||||||
#include "renderer/RenderingOptions.h"
|
#include "renderer/RenderingOptions.h"
|
||||||
#include "renderer/SceneRenderer.h"
|
#include "renderer/SceneRenderer.h"
|
||||||
|
|
@ -456,7 +455,6 @@ CRenderer::CRenderer(Renderer::Backend::IDevice* device)
|
||||||
|
|
||||||
ModelDefActivateFastImpl();
|
ModelDefActivateFastImpl();
|
||||||
ColorActivateFastImpl();
|
ColorActivateFastImpl();
|
||||||
ModelRenderer::Init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CRenderer::~CRenderer()
|
CRenderer::~CRenderer()
|
||||||
|
|
|
||||||
|
|
@ -212,17 +212,17 @@ void CRenderingOptions::ReadConfigAndSetupHooks()
|
||||||
m_ConfigHooks->Setup("silhouettes", m_Silhouettes);
|
m_ConfigHooks->Setup("silhouettes", m_Silhouettes);
|
||||||
|
|
||||||
m_ConfigHooks->Setup("gpuskinning", [this]() {
|
m_ConfigHooks->Setup("gpuskinning", [this]() {
|
||||||
const Renderer::Backend::IDevice::Capabilities& capabilities{
|
if (g_ConfigDB.Get("gpuskinning", false))
|
||||||
g_VideoMode.GetBackendDevice()->GetCapabilities()};
|
|
||||||
if (!g_ConfigDB.Get("gpuskinning", false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (capabilities.computeShaders && capabilities.storage)
|
|
||||||
m_GPUSkinning = true;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
m_GPUSkinning = false;
|
const Renderer::Backend::IDevice::Capabilities& capabilities{
|
||||||
LOGMESSAGE("GPU skinning isn't supported on the current hardware.");
|
g_VideoMode.GetBackendDevice()->GetCapabilities()};
|
||||||
|
if (capabilities.computeShaders && capabilities.storage)
|
||||||
|
m_GPUSkinning = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_GPUSkinning = false;
|
||||||
|
LOGMESSAGE("GPU skinning isn't supported on the current hardware.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CRenderer::IsInitialised())
|
if (CRenderer::IsInitialised())
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
struct SScreenRect
|
struct SScreenRect
|
||||||
{
|
{
|
||||||
|
|
@ -115,78 +116,192 @@ public:
|
||||||
|
|
||||||
SilhouetteRenderer silhouetteRenderer;
|
SilhouetteRenderer silhouetteRenderer;
|
||||||
|
|
||||||
/// Various model renderers
|
// Various model renderers
|
||||||
struct Models
|
struct Models
|
||||||
{
|
{
|
||||||
// NOTE: The current renderer design (with ModelRenderer, ModelVertexRenderer,
|
|
||||||
// RenderModifier, etc) is mostly a relic of an older design that implemented
|
|
||||||
// the different materials and rendering modes through extensive subclassing
|
|
||||||
// and hooking objects together in various combinations.
|
|
||||||
// The new design uses the CShaderManager API to abstract away the details
|
|
||||||
// of rendering, and uses a data-driven approach to materials, so there are
|
|
||||||
// now a small number of generic subclasses instead of many specialised subclasses,
|
|
||||||
// but most of the old infrastructure hasn't been refactored out yet and leads to
|
|
||||||
// some unwanted complexity.
|
|
||||||
|
|
||||||
// Submitted models are split on two axes:
|
// Submitted models are split on two axes:
|
||||||
// - Normal vs Transp[arent] - alpha-blended models are stored in a separate
|
// - Opaque vs Transparent - alpha-blended models are stored in a separate
|
||||||
// list so we can draw them above/below the alpha-blended water plane correctly
|
// list so we can draw them above/below the alpha-blended water plane correctly
|
||||||
// - Skinned vs Unskinned - with hardware lighting we don't need to
|
// - Skinned vs Unskinned - we don't need to duplicate mesh data per
|
||||||
// duplicate mesh data per model instance (except for skinned models),
|
// model instance (except for skinned models), so non-skinned models
|
||||||
// so non-skinned models get different ModelVertexRenderers
|
// get different ModelVertexRenderers
|
||||||
|
|
||||||
ModelRendererPtr NormalSkinned;
|
struct Submissions
|
||||||
ModelRendererPtr NormalUnskinned; // == NormalSkinned if unskinned shader instancing not supported
|
{
|
||||||
ModelRendererPtr TranspSkinned;
|
std::vector<CModel*> submissions[CSceneRenderer::CULL_MAX];
|
||||||
ModelRendererPtr TranspUnskinned; // == TranspSkinned if unskinned shader instancing not supported
|
};
|
||||||
|
|
||||||
ModelVertexRendererPtr VertexRendererShader;
|
// Unskinned submissions should be prepared and rendered with
|
||||||
ModelVertexRendererPtr VertexInstancingShader;
|
// VertexInstancingShader. Skinned - with Vertex*SkinningShader
|
||||||
ModelVertexRendererPtr VertexGPUSkinningShader;
|
// depending on whether GPU skinning is enabled.
|
||||||
|
Submissions OpaqueSkinned;
|
||||||
|
Submissions OpaqueUnskinned;
|
||||||
|
Submissions TransparentSkinned;
|
||||||
|
Submissions TransparentUnskinned;
|
||||||
|
|
||||||
LitRenderModifierPtr ModShader;
|
ModelRenderer modelRenderer;
|
||||||
|
|
||||||
|
InstancingModelRenderer VertexInstancingShader;
|
||||||
|
CPUSkinnedModelVertexRenderer VertexCPUSkinningShader;
|
||||||
|
// We can't create GPU skinning renderer for renderer devices without
|
||||||
|
// its support.
|
||||||
|
std::optional<GPUSkinnedModelModelRenderer> VertexGPUSkinningShader;
|
||||||
|
|
||||||
|
ShaderRenderModifier ModShader;
|
||||||
|
|
||||||
|
bool GPUSkinningEnabled{false};
|
||||||
} Model;
|
} Model;
|
||||||
|
|
||||||
CShaderDefines globalContext;
|
CShaderDefines globalContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload renderer data for all previously submitted models to backend.
|
||||||
|
*
|
||||||
|
* Must be called before any rendering calls and after all models
|
||||||
|
* for this frame have been prepared.
|
||||||
|
*/
|
||||||
|
void UploadModels(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
||||||
|
{
|
||||||
|
PROFILE3("upload models");
|
||||||
|
|
||||||
|
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||||
|
Model.GPUSkinningEnabled
|
||||||
|
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||||
|
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||||
|
|
||||||
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
|
{
|
||||||
|
modelVertexSkinningRenderer.UploadModelsData(deviceCommandContext, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||||
|
modelVertexSkinningRenderer.UploadModelsData(deviceCommandContext, Model.TransparentSkinned.submissions[cullGroup]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
|
{
|
||||||
|
Model.VertexInstancingShader.UploadModelsData(deviceCommandContext, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||||
|
Model.VertexInstancingShader.UploadModelsData(deviceCommandContext, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PrepareModels: Calculate renderer data for all previously
|
||||||
|
* submitted models.
|
||||||
|
*
|
||||||
|
* Must be called before any rendering calls and after all models
|
||||||
|
* for this frame have been submitted.
|
||||||
|
*/
|
||||||
|
void PrepareModels(
|
||||||
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
||||||
|
{
|
||||||
|
PROFILE3("prepare models");
|
||||||
|
|
||||||
|
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||||
|
Model.GPUSkinningEnabled
|
||||||
|
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||||
|
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||||
|
|
||||||
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
|
{
|
||||||
|
PrepareModels(deviceCommandContext, modelVertexSkinningRenderer, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||||
|
PrepareModels(deviceCommandContext, modelVertexSkinningRenderer, Model.TransparentSkinned.submissions[cullGroup]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
|
{
|
||||||
|
PrepareModels(deviceCommandContext, Model.VertexInstancingShader, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||||
|
PrepareModels(deviceCommandContext, Model.VertexInstancingShader, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrepareModels(
|
||||||
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, ModelVertexRenderer& modelVertexRenderer, std::span<CModel*> submissions)
|
||||||
|
{
|
||||||
|
for (CModel* model : submissions)
|
||||||
|
{
|
||||||
|
model->ValidatePosition();
|
||||||
|
|
||||||
|
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||||
|
ENSURE(rdata->GetKey() == &modelVertexRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
modelVertexRenderer.UpdateModelsData(deviceCommandContext, submissions);
|
||||||
|
|
||||||
|
for (CModel* model : submissions)
|
||||||
|
{
|
||||||
|
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||||
|
rdata->m_UpdateFlags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit: Submit a model for rendering this frame.
|
||||||
|
*
|
||||||
|
* preconditions : The model must not have been submitted to any
|
||||||
|
* ModelRenderer in this frame. Submit may only be called
|
||||||
|
* after EndFrame and before PrepareModels.
|
||||||
|
*
|
||||||
|
* @param model The model that will be added to the list of models
|
||||||
|
* submitted this frame.
|
||||||
|
*/
|
||||||
|
void Submit(const int cullGroup, ModelVertexRenderer& modelVertexRenderer, Models::Submissions& submissions, CModel* model)
|
||||||
|
{
|
||||||
|
CModelRData* rdata{static_cast<CModelRData*>(model->GetRenderData())};
|
||||||
|
|
||||||
|
// Ensure model data is valid.
|
||||||
|
// TODO: using a pointer as a key is unsafe.
|
||||||
|
const void* key{&modelVertexRenderer};
|
||||||
|
if (!rdata || rdata->GetKey() != key)
|
||||||
|
{
|
||||||
|
model->InvalidatePosition();
|
||||||
|
rdata = modelVertexRenderer.CreateModelData(key, model);
|
||||||
|
model->SetRenderData(rdata);
|
||||||
|
model->SetDirty(~0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
submissions.submissions[cullGroup].push_back(model);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders all non-alpha-blended models with the given context.
|
* Renders all non-alpha-blended models with the given context.
|
||||||
*/
|
*/
|
||||||
void CallModelRenderers(
|
void CallOpaqueModelRenderers(
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||||
const CShaderDefines& context, int cullGroup, int flags, const ERenderMode renderMode)
|
const CShaderDefines& context, int cullGroup, int flags, const ERenderMode renderMode)
|
||||||
{
|
{
|
||||||
CShaderDefines contextSkinned = context;
|
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||||
if (g_RenderingOptions.GetGPUSkinning())
|
Model.GPUSkinningEnabled
|
||||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||||
Model.NormalSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags, renderMode);
|
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||||
|
|
||||||
if (Model.NormalUnskinned != Model.NormalSkinned)
|
CShaderDefines contextSkinned = context;
|
||||||
{
|
if (Model.GPUSkinningEnabled)
|
||||||
CShaderDefines contextUnskinned = context;
|
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
Model.modelRenderer.Render(deviceCommandContext, modelVertexSkinningRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||||
Model.NormalUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode);
|
|
||||||
}
|
CShaderDefines contextUnskinned = context;
|
||||||
|
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||||
|
Model.modelRenderer.Render(deviceCommandContext, Model.VertexInstancingShader, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders all alpha-blended models with the given context.
|
* Renders all alpha-blended models with the given context.
|
||||||
*/
|
*/
|
||||||
void CallTranspModelRenderers(
|
void CallTransparentModelRenderers(
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||||
const CShaderDefines& context, int cullGroup, int flags, const ERenderMode renderMode)
|
const CShaderDefines& context, int cullGroup, int flags, const ERenderMode renderMode)
|
||||||
{
|
{
|
||||||
CShaderDefines contextSkinned = context;
|
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||||
if (g_RenderingOptions.GetGPUSkinning())
|
Model.GPUSkinningEnabled
|
||||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||||
Model.TranspSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags, renderMode);
|
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||||
|
|
||||||
if (Model.TranspUnskinned != Model.TranspSkinned)
|
CShaderDefines contextSkinned = context;
|
||||||
{
|
if (Model.GPUSkinningEnabled)
|
||||||
CShaderDefines contextUnskinned = context;
|
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
Model.modelRenderer.Render(deviceCommandContext, modelVertexSkinningRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.TransparentSkinned.submissions[cullGroup]);
|
||||||
Model.TranspUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode);
|
|
||||||
}
|
CShaderDefines contextUnskinned = context;
|
||||||
|
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||||
|
Model.modelRenderer.Render(deviceCommandContext, Model.VertexInstancingShader, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -239,26 +354,12 @@ void CSceneRenderer::ReloadShaders([[maybe_unused]] Renderer::Backend::IDevice*
|
||||||
m->globalContext.Add(str_RENDER_DEBUG_MODE,
|
m->globalContext.Add(str_RENDER_DEBUG_MODE,
|
||||||
RenderDebugModeEnum::ToString(g_RenderingOptions.GetRenderDebugMode()));
|
RenderDebugModeEnum::ToString(g_RenderingOptions.GetRenderDebugMode()));
|
||||||
|
|
||||||
m->Model.ModShader = LitRenderModifierPtr(new ShaderRenderModifier());
|
m->Model.GPUSkinningEnabled = g_RenderingOptions.GetGPUSkinning();
|
||||||
|
if (m->Model.GPUSkinningEnabled)
|
||||||
m->Model.VertexRendererShader = ModelVertexRendererPtr(new CPUSkinnedModelVertexRenderer());
|
|
||||||
m->Model.VertexInstancingShader = ModelVertexRendererPtr(new InstancingModelRenderer());
|
|
||||||
|
|
||||||
if (g_RenderingOptions.GetGPUSkinning())
|
|
||||||
{
|
{
|
||||||
m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new GPUSkinnedModelModelRenderer());
|
if (!m->Model.VertexGPUSkinningShader.has_value())
|
||||||
m->Model.NormalSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexGPUSkinningShader));
|
m->Model.VertexGPUSkinningShader.emplace();
|
||||||
m->Model.TranspSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexGPUSkinningShader));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
m->Model.VertexGPUSkinningShader.reset();
|
|
||||||
m->Model.NormalSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexRendererShader));
|
|
||||||
m->Model.TranspSkinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexRendererShader));
|
|
||||||
}
|
|
||||||
|
|
||||||
m->Model.NormalUnskinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexInstancingShader));
|
|
||||||
m->Model.TranspUnskinned = ModelRendererPtr(new ShaderModelRenderer(m->Model.VertexInstancingShader));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneRenderer::Initialize()
|
void CSceneRenderer::Initialize()
|
||||||
|
|
@ -282,8 +383,8 @@ void CSceneRenderer::Resize(int /*width*/, int /*height*/)
|
||||||
void CSceneRenderer::BeginFrame()
|
void CSceneRenderer::BeginFrame()
|
||||||
{
|
{
|
||||||
// choose model renderers for this frame
|
// choose model renderers for this frame
|
||||||
m->Model.ModShader->SetShadowMap(&m->shadow);
|
m->Model.ModShader.SetShadowMap(&m->shadow);
|
||||||
m->Model.ModShader->SetLightEnv(m_LightEnv);
|
m->Model.ModShader.SetLightEnv(m_LightEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneRenderer::SetSimulation(CSimulation2* simulation)
|
void CSceneRenderer::SetSimulation(CSimulation2* simulation)
|
||||||
|
|
@ -315,12 +416,12 @@ void CSceneRenderer::RenderShadowMap(
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE("render models");
|
PROFILE("render models");
|
||||||
m->CallModelRenderers(deviceCommandContext, {}, cullGroup, ModelFlag::CAST_SHADOWS, ERenderMode::SOLID);
|
m->CallOpaqueModelRenderers(deviceCommandContext, {}, cullGroup, ModelFlag::CAST_SHADOWS, ERenderMode::SOLID);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE("render transparent models");
|
PROFILE("render transparent models");
|
||||||
m->CallTranspModelRenderers(deviceCommandContext, {}, cullGroup, ModelFlag::CAST_SHADOWS, ERenderMode::SOLID);
|
m->CallTransparentModelRenderers(deviceCommandContext, {}, cullGroup, ModelFlag::CAST_SHADOWS, ERenderMode::SOLID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,10 +464,10 @@ void CSceneRenderer::RenderModels(
|
||||||
const ERenderMode modelRenderMode{
|
const ERenderMode modelRenderMode{
|
||||||
m_ModelRenderMode == WIREFRAME ? WIREFRAME : SOLID};
|
m_ModelRenderMode == WIREFRAME ? WIREFRAME : SOLID};
|
||||||
|
|
||||||
m->CallModelRenderers(deviceCommandContext, context, cullGroup, flags, modelRenderMode);
|
m->CallOpaqueModelRenderers(deviceCommandContext, context, cullGroup, flags, modelRenderMode);
|
||||||
|
|
||||||
if (m_ModelRenderMode == EDGED_FACES)
|
if (m_ModelRenderMode == EDGED_FACES)
|
||||||
m->CallModelRenderers(deviceCommandContext, {}, cullGroup, flags, EDGED_FACES);
|
m->CallOpaqueModelRenderers(deviceCommandContext, {}, cullGroup, flags, EDGED_FACES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneRenderer::RenderTransparentModels(
|
void CSceneRenderer::RenderTransparentModels(
|
||||||
|
|
@ -388,13 +489,13 @@ void CSceneRenderer::RenderTransparentModels(
|
||||||
m_ModelRenderMode == WIREFRAME ? WIREFRAME : SOLID};
|
m_ModelRenderMode == WIREFRAME ? WIREFRAME : SOLID};
|
||||||
|
|
||||||
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_OPAQUE)
|
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_OPAQUE)
|
||||||
m->CallTranspModelRenderers(deviceCommandContext, contextOpaque, cullGroup, flags, modelRenderMode);
|
m->CallTransparentModelRenderers(deviceCommandContext, contextOpaque, cullGroup, flags, modelRenderMode);
|
||||||
|
|
||||||
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_BLEND)
|
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_BLEND)
|
||||||
m->CallTranspModelRenderers(deviceCommandContext, contextBlend, cullGroup, flags, modelRenderMode);
|
m->CallTransparentModelRenderers(deviceCommandContext, contextBlend, cullGroup, flags, modelRenderMode);
|
||||||
|
|
||||||
if (m_ModelRenderMode == EDGED_FACES)
|
if (m_ModelRenderMode == EDGED_FACES)
|
||||||
m->CallTranspModelRenderers(deviceCommandContext, {}, cullGroup, flags, EDGED_FACES);
|
m->CallTransparentModelRenderers(deviceCommandContext, {}, cullGroup, flags, EDGED_FACES);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetObliqueFrustumClipping: change the near plane to the given clip plane (in world space)
|
// SetObliqueFrustumClipping: change the near plane to the given clip plane (in world space)
|
||||||
|
|
@ -709,24 +810,24 @@ void CSceneRenderer::RenderSilhouettes(
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE("render model occluders");
|
PROFILE("render model occluders");
|
||||||
m->CallModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_OCCLUDER, 0, ERenderMode::SOLID);
|
m->CallOpaqueModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_OCCLUDER, 0, ERenderMode::SOLID);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE("render transparent occluders");
|
PROFILE("render transparent occluders");
|
||||||
m->CallTranspModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_OCCLUDER, 0, ERenderMode::SOLID);
|
m->CallTransparentModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_OCCLUDER, 0, ERenderMode::SOLID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we can't sort, we'll use the stencil buffer to ensure we only draw
|
// Since we can't sort, we'll use the stencil buffer to ensure we only draw
|
||||||
// a pixel once (using the color of whatever model happens to be drawn first).
|
// a pixel once (using the color of whatever model happens to be drawn first).
|
||||||
{
|
{
|
||||||
PROFILE("render model casters");
|
PROFILE("render model casters");
|
||||||
m->CallModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_CASTER, 0, ERenderMode::SOLID);
|
m->CallOpaqueModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_CASTER, 0, ERenderMode::SOLID);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE("render transparent casters");
|
PROFILE("render transparent casters");
|
||||||
m->CallTranspModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_CASTER, 0, ERenderMode::SOLID);
|
m->CallTransparentModelRenderers(deviceCommandContext, {}, CULL_SILHOUETTE_CASTER, 0, ERenderMode::SOLID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -770,15 +871,7 @@ void CSceneRenderer::PrepareSubmissions(
|
||||||
CShaderDefines context = m->globalContext;
|
CShaderDefines context = m->globalContext;
|
||||||
|
|
||||||
// Prepare model renderers
|
// Prepare model renderers
|
||||||
{
|
m->PrepareModels(deviceCommandContext);
|
||||||
PROFILE3("prepare models");
|
|
||||||
m->Model.NormalSkinned->PrepareModels(deviceCommandContext);
|
|
||||||
m->Model.TranspSkinned->PrepareModels(deviceCommandContext);
|
|
||||||
if (m->Model.NormalUnskinned != m->Model.NormalSkinned)
|
|
||||||
m->Model.NormalUnskinned->PrepareModels(deviceCommandContext);
|
|
||||||
if (m->Model.TranspUnskinned != m->Model.TranspSkinned)
|
|
||||||
m->Model.TranspUnskinned->PrepareModels(deviceCommandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->terrainRenderer.PrepareForRendering();
|
m->terrainRenderer.PrepareForRendering();
|
||||||
|
|
||||||
|
|
@ -786,15 +879,7 @@ void CSceneRenderer::PrepareSubmissions(
|
||||||
|
|
||||||
m->particleRenderer.PrepareForRendering(context);
|
m->particleRenderer.PrepareForRendering(context);
|
||||||
|
|
||||||
{
|
m->UploadModels(deviceCommandContext);
|
||||||
PROFILE3("upload models");
|
|
||||||
m->Model.NormalSkinned->UploadModels(deviceCommandContext);
|
|
||||||
m->Model.TranspSkinned->UploadModels(deviceCommandContext);
|
|
||||||
if (m->Model.NormalUnskinned != m->Model.NormalSkinned)
|
|
||||||
m->Model.NormalUnskinned->UploadModels(deviceCommandContext);
|
|
||||||
if (m->Model.TranspUnskinned != m->Model.TranspSkinned)
|
|
||||||
m->Model.TranspUnskinned->UploadModels(deviceCommandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->overlayRenderer.Upload(deviceCommandContext);
|
m->overlayRenderer.Upload(deviceCommandContext);
|
||||||
|
|
||||||
|
|
@ -908,13 +993,13 @@ void CSceneRenderer::EndFrame()
|
||||||
m->particleRenderer.EndFrame();
|
m->particleRenderer.EndFrame();
|
||||||
m->silhouetteRenderer.EndFrame();
|
m->silhouetteRenderer.EndFrame();
|
||||||
|
|
||||||
// Finish model renderers
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
m->Model.NormalSkinned->EndFrame();
|
{
|
||||||
m->Model.TranspSkinned->EndFrame();
|
m->Model.OpaqueSkinned.submissions[cullGroup].clear();
|
||||||
if (m->Model.NormalUnskinned != m->Model.NormalSkinned)
|
m->Model.TransparentSkinned.submissions[cullGroup].clear();
|
||||||
m->Model.NormalUnskinned->EndFrame();
|
m->Model.OpaqueUnskinned.submissions[cullGroup].clear();
|
||||||
if (m->Model.TranspUnskinned != m->Model.TranspSkinned)
|
m->Model.TransparentUnskinned.submissions[cullGroup].clear();
|
||||||
m->Model.TranspUnskinned->EndFrame();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneRenderer::DisplayFrustum(Renderer::Backend::IDeviceCommandContext& deviceCommandContext)
|
void CSceneRenderer::DisplayFrustum(Renderer::Backend::IDeviceCommandContext& deviceCommandContext)
|
||||||
|
|
@ -1029,21 +1114,25 @@ void CSceneRenderer::SubmitNonRecursive(CModel* model)
|
||||||
m->shadow.AddShadowCasterBound(cascade, model->GetWorldBounds());
|
m->shadow.AddShadowCasterBound(cascade, model->GetWorldBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool requiresSkinning = (model->GetModelDef()->GetNumBones() != 0);
|
const bool requiresSkinning{model->GetModelDef()->GetNumBones() != 0};
|
||||||
|
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||||
|
m->Model.GPUSkinningEnabled
|
||||||
|
? static_cast<ModelVertexRenderer&>(*m->Model.VertexGPUSkinningShader)
|
||||||
|
: static_cast<ModelVertexRenderer&>(m->Model.VertexCPUSkinningShader)};
|
||||||
|
|
||||||
if (model->GetMaterial().UsesAlphaBlending())
|
if (model->GetMaterial().UsesAlphaBlending())
|
||||||
{
|
{
|
||||||
if (requiresSkinning)
|
if (requiresSkinning)
|
||||||
m->Model.TranspSkinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, modelVertexSkinningRenderer, m->Model.TransparentSkinned, model);
|
||||||
else
|
else
|
||||||
m->Model.TranspUnskinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, m->Model.VertexInstancingShader, m->Model.TransparentUnskinned, model);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (requiresSkinning)
|
if (requiresSkinning)
|
||||||
m->Model.NormalSkinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, modelVertexSkinningRenderer, m->Model.OpaqueSkinned, model);
|
||||||
else
|
else
|
||||||
m->Model.NormalUnskinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, m->Model.VertexInstancingShader, m->Model.OpaqueUnskinned, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
5
source/tools/atlas/AtlasFrontends/CMakeLists.txt
Normal file
5
source/tools/atlas/AtlasFrontends/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(ActorEditor
|
||||||
|
PRIVATE
|
||||||
|
$<$<PLATFORM_ID:Windows>: ActorEditor.rc> # Caution, the blank before the File is needed
|
||||||
|
ActorEditor.cpp
|
||||||
|
)
|
||||||
15
source/tools/atlas/AtlasObject/CMakeLists.txt
Normal file
15
source/tools/atlas/AtlasObject/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
target_sources(AtlasObject
|
||||||
|
PRIVATE
|
||||||
|
AtlasObject.h
|
||||||
|
AtlasObjectImpl.cpp
|
||||||
|
AtlasObjectImpl.h
|
||||||
|
AtlasObjectJS.cpp
|
||||||
|
AtlasObjectText.cpp
|
||||||
|
AtlasObjectText.h
|
||||||
|
AtlasObjectXML.cpp
|
||||||
|
JSONSpiritInclude.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT without-tests)
|
||||||
|
add_subdirectory(tests/)
|
||||||
|
endif()
|
||||||
13
source/tools/atlas/AtlasObject/tests/CMakeLists.txt
Normal file
13
source/tools/atlas/AtlasObject/tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
cxxtest_add_test(test_atlas_object_xml testAtlasObjectXML.cpp ${CMAKE_CURRENT_LIST_DIR}/test_AtlasObjectXML.h)
|
||||||
|
|
||||||
|
target_include_directories(test_atlas_object_xml
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}/source
|
||||||
|
${CXXTEST_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(test_atlas_object_xml
|
||||||
|
PRIVATE
|
||||||
|
${BUILD_FLAGS_TARGET}
|
||||||
|
AtlasObject
|
||||||
|
)
|
||||||
13
source/tools/atlas/AtlasUI/ActorEditor/CMakeLists.txt
Normal file
13
source/tools/atlas/AtlasUI/ActorEditor/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
ActorEditor.cpp
|
||||||
|
ActorEditor.h
|
||||||
|
ActorEditorListCtrl.cpp
|
||||||
|
ActorEditorListCtrl.h
|
||||||
|
AnimListEditor.cpp
|
||||||
|
AnimListEditor.h
|
||||||
|
PropListEditor.cpp
|
||||||
|
PropListEditor.h
|
||||||
|
TexListEditor.cpp
|
||||||
|
TexListEditor.h
|
||||||
|
)
|
||||||
5
source/tools/atlas/AtlasUI/CMakeLists.txt
Normal file
5
source/tools/atlas/AtlasUI/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
add_subdirectory(ActorEditor/)
|
||||||
|
add_subdirectory(CustomControls/)
|
||||||
|
add_subdirectory(General/)
|
||||||
|
add_subdirectory(Misc/)
|
||||||
|
add_subdirectory(ScenarioEditor/)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
ToolButton.cpp
|
||||||
|
ToolButton.h
|
||||||
|
)
|
||||||
12
source/tools/atlas/AtlasUI/CustomControls/CMakeLists.txt
Normal file
12
source/tools/atlas/AtlasUI/CustomControls/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
add_subdirectory(Buttons/)
|
||||||
|
add_subdirectory(Canvas/)
|
||||||
|
add_subdirectory(ColorDialog/)
|
||||||
|
add_subdirectory(DraggableListCtrl/)
|
||||||
|
add_subdirectory(EditableListCtrl/)
|
||||||
|
add_subdirectory(FileHistory/)
|
||||||
|
add_subdirectory(HighResTimer/)
|
||||||
|
add_subdirectory(MapDialog/)
|
||||||
|
add_subdirectory(MapResizeDialog/)
|
||||||
|
add_subdirectory(SnapSplitterWindow/)
|
||||||
|
add_subdirectory(VirtualDirTreeCtrl/)
|
||||||
|
add_subdirectory(Windows/)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Canvas.cpp
|
||||||
|
Canvas.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
ColorDialog.cpp
|
||||||
|
ColorDialog.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
DraggableListCtrl.cpp
|
||||||
|
DraggableListCtrl.h
|
||||||
|
DraggableListCtrlCommands.cpp
|
||||||
|
DraggableListCtrlCommands.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
EditableListCtrl.cpp
|
||||||
|
EditableListCtrl.h
|
||||||
|
EditableListCtrlCommands.cpp
|
||||||
|
EditableListCtrlCommands.h
|
||||||
|
FieldEditCtrl.cpp
|
||||||
|
FieldEditCtrl.h
|
||||||
|
ListCtrlValidator.cpp
|
||||||
|
ListCtrlValidator.h
|
||||||
|
QuickComboBox.cpp
|
||||||
|
QuickComboBox.h
|
||||||
|
QuickFileCtrl.cpp
|
||||||
|
QuickFileCtrl.h
|
||||||
|
QuickTextCtrl.cpp
|
||||||
|
QuickTextCtrl.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
FileHistory.cpp
|
||||||
|
FileHistory.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
HighResTimer.cpp
|
||||||
|
HighResTimer.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
MapDialog.cpp
|
||||||
|
MapDialog.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
MapResizeDialog.cpp
|
||||||
|
MapResizeDialog.h
|
||||||
|
PseudoMiniMapPanel.cpp
|
||||||
|
PseudoMiniMapPanel.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
SnapSplitterWindow.cpp
|
||||||
|
SnapSplitterWindow.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
virtualdirtreectrl.cpp
|
||||||
|
virtualdirtreectrl.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
AtlasDialog.cpp
|
||||||
|
AtlasDialog.h
|
||||||
|
AtlasWindow.cpp
|
||||||
|
AtlasWindow.h
|
||||||
|
)
|
||||||
16
source/tools/atlas/AtlasUI/General/CMakeLists.txt
Normal file
16
source/tools/atlas/AtlasUI/General/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
AtlasClipboard.cpp
|
||||||
|
AtlasClipboard.h
|
||||||
|
AtlasEventLoop.cpp
|
||||||
|
AtlasEventLoop.h
|
||||||
|
AtlasWindowCommand.cpp
|
||||||
|
AtlasWindowCommand.h
|
||||||
|
AtlasWindowCommandProc.cpp
|
||||||
|
AtlasWindowCommandProc.h
|
||||||
|
Datafile.cpp
|
||||||
|
Datafile.h
|
||||||
|
IAtlasSerialiser.h
|
||||||
|
Observable.cpp
|
||||||
|
Observable.h
|
||||||
|
)
|
||||||
13
source/tools/atlas/AtlasUI/Misc/CMakeLists.txt
Normal file
13
source/tools/atlas/AtlasUI/Misc/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
DLLInterface.cpp
|
||||||
|
DLLInterface.h
|
||||||
|
KeyMap.cpp
|
||||||
|
KeyMap.h
|
||||||
|
actored.h
|
||||||
|
precompiled.cpp
|
||||||
|
precompiled.h
|
||||||
|
$<$<PLATFORM_ID:Windows>: atlas.rc> # Caution, the blank before the File is needed
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(Graphics/)
|
||||||
12
source/tools/atlas/AtlasUI/Misc/Graphics/CMakeLists.txt
Normal file
12
source/tools/atlas/AtlasUI/Misc/Graphics/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/ActorEditor.ico
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/ArchiveViewer.ico
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/FileConverter.ico
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/ScenarioEditor.ico
|
||||||
|
DESTINATION
|
||||||
|
${CMAKE_INSTALL_DATADIR}/0ad/tools/ActorEditor/icons
|
||||||
|
)
|
||||||
|
endif()
|
||||||
10
source/tools/atlas/AtlasUI/ScenarioEditor/CMakeLists.txt
Normal file
10
source/tools/atlas/AtlasUI/ScenarioEditor/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
ScenarioEditor.cpp
|
||||||
|
ScenarioEditor.h
|
||||||
|
SectionLayout.cpp
|
||||||
|
SectionLayout.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(Sections/)
|
||||||
|
add_subdirectory(Tools/)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
add_subdirectory(Cinema/)
|
||||||
|
add_subdirectory(Common/)
|
||||||
|
add_subdirectory(Environment/)
|
||||||
|
add_subdirectory(Map/)
|
||||||
|
add_subdirectory(Object/)
|
||||||
|
add_subdirectory(Player/)
|
||||||
|
add_subdirectory(Terrain/)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Cinema.cpp
|
||||||
|
Cinema.h
|
||||||
|
)
|
||||||
|
|
@ -45,21 +45,15 @@
|
||||||
|
|
||||||
using AtlasMessage::Shareable;
|
using AtlasMessage::Shareable;
|
||||||
|
|
||||||
enum {
|
|
||||||
ID_PathsDrawing,
|
|
||||||
ID_PathsList,
|
|
||||||
ID_AddPath,
|
|
||||||
ID_DeletePath
|
|
||||||
};
|
|
||||||
|
|
||||||
CinemaSidebar::CinemaSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
CinemaSidebar::CinemaSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer)
|
||||||
: Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer)
|
: Sidebar(scenarioEditor, sidebarContainer, bottomBarContainer)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
auto* sizer = new wxStaticBoxSizer(wxVERTICAL, this, _T("Common settings"));
|
auto* sizer = new wxStaticBoxSizer(wxVERTICAL, this, _T("Common settings"));
|
||||||
|
|
||||||
m_DrawPath = new wxCheckBox(sizer->GetStaticBox(), ID_PathsDrawing, _("Draw all paths"));
|
m_DrawPath = new wxCheckBox(sizer->GetStaticBox(), wxID_ANY, _("Draw all paths"));
|
||||||
m_DrawPath->SetToolTip(_("Display every cinematic path added to the map"));
|
m_DrawPath->SetToolTip(_("Display every cinematic path added to the map"));
|
||||||
|
m_DrawPath->Bind(wxEVT_CHECKBOX, [this](auto&){ SetPathsDrawing(m_DrawPath->IsChecked()); });
|
||||||
|
|
||||||
sizer->Add(m_DrawPath, wxSizerFlags().Expand().Border(wxALL, Atlas::Style::STATICBOX_PADDING));
|
sizer->Add(m_DrawPath, wxSizerFlags().Expand().Border(wxALL, Atlas::Style::STATICBOX_PADDING));
|
||||||
|
|
||||||
|
|
@ -70,20 +64,22 @@ CinemaSidebar::CinemaSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarCo
|
||||||
auto* boxSizer = new wxStaticBoxSizer(wxVERTICAL, this, _T("Paths"));
|
auto* boxSizer = new wxStaticBoxSizer(wxVERTICAL, this, _T("Paths"));
|
||||||
auto* box = boxSizer->GetStaticBox();
|
auto* box = boxSizer->GetStaticBox();
|
||||||
|
|
||||||
m_PathList = new wxListBox(box, ID_PathsList, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE | wxLB_SORT);
|
m_PathList = new wxListBox(box, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE | wxLB_SORT);
|
||||||
|
|
||||||
auto* deleteButton = new wxButton(box, ID_DeletePath, _("Delete"));
|
auto* deleteButton = new wxButton(box, wxID_ANY, _("Delete"));
|
||||||
deleteButton->SetToolTip(_T("Delete selected path"));
|
deleteButton->SetToolTip(_T("Delete selected path"));
|
||||||
|
deleteButton->Bind(wxEVT_BUTTON, [this](auto&){ DeleteSelectedPath(); });
|
||||||
|
|
||||||
m_NewPathName = new wxTextCtrl(box, wxID_ANY);
|
auto* newPathName = new wxTextCtrl(box, wxID_ANY);
|
||||||
|
|
||||||
auto* addButton = new wxButton(box, ID_AddPath, _("Add"));
|
auto* addButton = new wxButton(box, wxID_ANY, _("Add"));
|
||||||
|
addButton->Bind(wxEVT_BUTTON, [this, newPathName](auto&){ AddPath(newPathName->GetValue()); newPathName->Clear(); });
|
||||||
|
|
||||||
wxFlexGridSizer* pathsSizer = new wxFlexGridSizer(1, 5, 5);
|
wxFlexGridSizer* pathsSizer = new wxFlexGridSizer(1, 5, 5);
|
||||||
pathsSizer->AddGrowableCol(0);
|
pathsSizer->AddGrowableCol(0);
|
||||||
pathsSizer->Add(m_PathList, wxSizerFlags().Proportion(1).Expand());
|
pathsSizer->Add(m_PathList, wxSizerFlags().Proportion(1).Expand());
|
||||||
pathsSizer->Add(deleteButton, wxSizerFlags().Expand());
|
pathsSizer->Add(deleteButton, wxSizerFlags().Expand());
|
||||||
pathsSizer->Add(m_NewPathName, wxSizerFlags().Expand());
|
pathsSizer->Add(newPathName, wxSizerFlags().Expand());
|
||||||
pathsSizer->Add(addButton, wxSizerFlags().Expand());
|
pathsSizer->Add(addButton, wxSizerFlags().Expand());
|
||||||
|
|
||||||
boxSizer->Add(pathsSizer, wxSizerFlags().Expand().Border(wxALL, Atlas::Style::STATICBOX_PADDING));
|
boxSizer->Add(pathsSizer, wxSizerFlags().Expand().Border(wxALL, Atlas::Style::STATICBOX_PADDING));
|
||||||
|
|
@ -106,22 +102,21 @@ void CinemaSidebar::OnMapReload()
|
||||||
ReloadPathList();
|
ReloadPathList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CinemaSidebar::OnTogglePathsDrawing(wxCommandEvent& evt)
|
void CinemaSidebar::SetPathsDrawing(const bool enable)
|
||||||
{
|
{
|
||||||
POST_COMMAND(SetCinemaPathsDrawing, (evt.IsChecked()));
|
POST_COMMAND(SetCinemaPathsDrawing, (enable));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CinemaSidebar::OnAddPath(wxCommandEvent&)
|
void CinemaSidebar::AddPath(wxString name)
|
||||||
{
|
{
|
||||||
if (m_NewPathName->GetValue().empty())
|
if (name.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
POST_COMMAND(AddCinemaPath, (m_NewPathName->GetValue().ToStdWstring()));
|
POST_COMMAND(AddCinemaPath, (name.ToStdWstring()));
|
||||||
m_NewPathName->Clear();
|
|
||||||
ReloadPathList();
|
ReloadPathList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CinemaSidebar::OnDeletePath(wxCommandEvent&)
|
void CinemaSidebar::DeleteSelectedPath()
|
||||||
{
|
{
|
||||||
int index = m_PathList->GetSelection();
|
int index = m_PathList->GetSelection();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
|
|
@ -148,9 +143,3 @@ void CinemaSidebar::ReloadPathList()
|
||||||
|
|
||||||
m_PathList->SetStringSelection(selection);
|
m_PathList->SetStringSelection(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(CinemaSidebar, Sidebar)
|
|
||||||
EVT_CHECKBOX(ID_PathsDrawing, CinemaSidebar::OnTogglePathsDrawing)
|
|
||||||
EVT_BUTTON(ID_AddPath, CinemaSidebar::OnAddPath)
|
|
||||||
EVT_BUTTON(ID_DeletePath, CinemaSidebar::OnDeletePath)
|
|
||||||
wxEND_EVENT_TABLE();
|
|
||||||
|
|
|
||||||
|
|
@ -37,15 +37,12 @@ protected:
|
||||||
void OnFirstDisplay() override;
|
void OnFirstDisplay() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnTogglePathsDrawing(wxCommandEvent& evt);
|
void SetPathsDrawing(const bool enable);
|
||||||
void OnAddPath(wxCommandEvent& evt);
|
void AddPath(wxString name);
|
||||||
void OnDeletePath(wxCommandEvent& evt);
|
void DeleteSelectedPath();
|
||||||
|
|
||||||
void ReloadPathList();
|
void ReloadPathList();
|
||||||
|
|
||||||
wxCheckBox* m_DrawPath;
|
wxCheckBox* m_DrawPath;
|
||||||
wxListBox* m_PathList;
|
wxListBox* m_PathList;
|
||||||
wxTextCtrl* m_NewPathName;
|
|
||||||
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Sidebar.cpp
|
||||||
|
Sidebar.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Environment.cpp
|
||||||
|
Environment.h
|
||||||
|
LightControl.cpp
|
||||||
|
LightControl.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Map.cpp
|
||||||
|
Map.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Object.cpp
|
||||||
|
Object.h
|
||||||
|
VariationControl.cpp
|
||||||
|
VariationControl.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Player.cpp
|
||||||
|
Player.h
|
||||||
|
)
|
||||||
|
|
@ -262,7 +262,7 @@ public:
|
||||||
wxGridSizer* gridSizer = new wxGridSizer(3, 5, 5);
|
wxGridSizer* gridSizer = new wxGridSizer(3, 5, 5);
|
||||||
wxButton* cameraSet = new wxButton(cameraSizer->GetStaticBox(), ID_CameraSet, _("Set"), wxDefaultPosition, wxSize(48, -1));
|
wxButton* cameraSet = new wxButton(cameraSizer->GetStaticBox(), ID_CameraSet, _("Set"), wxDefaultPosition, wxSize(48, -1));
|
||||||
gridSizer->Add(Tooltipped(cameraSet,
|
gridSizer->Add(Tooltipped(cameraSet,
|
||||||
_("Set player camera to cameraSizer->GetStaticBox() view")), wxSizerFlags().Expand());
|
_("Set player camera to this view")), wxSizerFlags().Expand());
|
||||||
wxButton* cameraView = new wxButton(cameraSizer->GetStaticBox(), ID_CameraView, _("View"), wxDefaultPosition, wxSize(48, -1));
|
wxButton* cameraView = new wxButton(cameraSizer->GetStaticBox(), ID_CameraView, _("View"), wxDefaultPosition, wxSize(48, -1));
|
||||||
cameraView->Enable(false);
|
cameraView->Enable(false);
|
||||||
gridSizer->Add(Tooltipped(cameraView,
|
gridSizer->Add(Tooltipped(cameraView,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Terrain.cpp
|
||||||
|
Terrain.h
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
ActorViewerTool.cpp
|
||||||
|
AlterElevation.cpp
|
||||||
|
FillTerrain.cpp
|
||||||
|
FlattenElevation.cpp
|
||||||
|
PaintTerrain.cpp
|
||||||
|
PickWaterHeight.cpp
|
||||||
|
PikeElevation.cpp
|
||||||
|
PlaceObject.cpp
|
||||||
|
ReplaceTerrain.cpp
|
||||||
|
SmoothElevation.cpp
|
||||||
|
TransformObject.cpp
|
||||||
|
TransformPath.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(Common/)
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
target_sources(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
Brushes.cpp
|
||||||
|
Brushes.h
|
||||||
|
MiscState.cpp
|
||||||
|
MiscState.h
|
||||||
|
ObjectSettings.cpp
|
||||||
|
ObjectSettings.h
|
||||||
|
Tools.cpp
|
||||||
|
Tools.h
|
||||||
|
)
|
||||||
162
source/tools/atlas/CMakeLists.txt
Normal file
162
source/tools/atlas/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
cmake_minimum_required(VERSION 3.25.1...4.0.0)
|
||||||
|
|
||||||
|
project(AtlasMisc LANGUAGES CXX)
|
||||||
|
|
||||||
|
include(0ad-Functions)
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ Project Macros ++++++++++++++++++++
|
||||||
|
macro(set_atlas_build_flags _target)
|
||||||
|
target_link_options(${_target}
|
||||||
|
PRIVATE
|
||||||
|
$<$<PLATFORM_ID:Linux,FreeBSD>:-fPIC>
|
||||||
|
$<$<PLATFORM_ID:Linux>:-rdynamic>
|
||||||
|
)
|
||||||
|
target_compile_options(${_target}
|
||||||
|
PRIVATE
|
||||||
|
$<$<PLATFORM_ID:Linux,FreeBSD>:-fPIC>
|
||||||
|
$<$<PLATFORM_ID:Linux,Darwin>:-Wno-unused-local-typedefs>
|
||||||
|
)
|
||||||
|
target_link_libraries(${_target}
|
||||||
|
PRIVATE
|
||||||
|
$<$<PLATFORM_ID:Windows>:winmm delayimp>
|
||||||
|
)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ Required Packages ++++++++++++++++++
|
||||||
|
find_package(wxWidgets 3.0.4 REQUIRED COMPONENTS gl xml)
|
||||||
|
find_package(Iconv 1.0 REQUIRED)
|
||||||
|
find_package(ZLIB 1.2 REQUIRED)
|
||||||
|
find_package(LibXml2 2.9 REQUIRED)
|
||||||
|
find_package(CxxTest 4.4 REQUIRED)
|
||||||
|
if(UNIX)
|
||||||
|
find_package(Boost 1.69.0 REQUIRED CONFIG)
|
||||||
|
find_package(SDL2 2.0.2 REQUIRED)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
include(FindPrebuildLibrary)
|
||||||
|
find_prebuild_library(Sdl2)
|
||||||
|
find_prebuild_library(Boost INC_PATH ${0AD_EXT_LIBDIR}/boost/include/)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ Project Targets ++++++++++++++++++++
|
||||||
|
add_library(AtlasObject STATIC)
|
||||||
|
add_library(AtlasUI SHARED)
|
||||||
|
add_executable(ActorEditor)
|
||||||
|
|
||||||
|
# Set Macos Bundle and Windows Window Application
|
||||||
|
set_target_properties(ActorEditor
|
||||||
|
PROPERTIES
|
||||||
|
WIN32_EXECUTABLE $<$<PLATFORM_ID:Windows>:TRUE>
|
||||||
|
MACOSX_BUNDLE $<$<PLATFORM_ID:Darwin>:TRUE>
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(AtlasFrontends/)
|
||||||
|
add_subdirectory(AtlasObject/)
|
||||||
|
add_subdirectory(AtlasUI/)
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ Set Output Paths +++++++++++++++++++
|
||||||
|
set_target_properties(AtlasObject
|
||||||
|
PROPERTIES
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/binaries/system
|
||||||
|
)
|
||||||
|
set_target_properties(AtlasUI
|
||||||
|
PROPERTIES
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/binaries/system
|
||||||
|
)
|
||||||
|
set_target_properties(ActorEditor
|
||||||
|
PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/binaries/system
|
||||||
|
)
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ AtlasObject ++++++++++++++++++++++++
|
||||||
|
set_atlas_build_flags(AtlasObject)
|
||||||
|
target_include_directories(AtlasObject PRIVATE ${CMAKE_SOURCE_DIR}/source)
|
||||||
|
target_link_libraries(AtlasObject
|
||||||
|
PRIVATE
|
||||||
|
${BUILD_FLAGS_TARGET}
|
||||||
|
$<$<PLATFORM_ID:Linux>:Boost::headers>
|
||||||
|
$<$<PLATFORM_ID:Windows>:BOOST::headers>
|
||||||
|
Iconv::Iconv
|
||||||
|
LibXml2::LibXml2
|
||||||
|
SDL2::SDL2
|
||||||
|
)
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ AtlasUI ++++++++++++++++++++++++++++
|
||||||
|
if(NOT without-pch)
|
||||||
|
add_pch(TARGET AtlasUI PCH_DIR ${PROJECT_SOURCE_DIR}/AtlasUI/Misc)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(AtlasUI PRIVATE CONFIG_ENABLE_PCH=0)
|
||||||
|
set_target_properties(AtlasUI PROPERTIES
|
||||||
|
DISABLE_PRECOMPILE_HEADERS TRUE
|
||||||
|
)
|
||||||
|
target_include_directories(AtlasUI
|
||||||
|
BEFORE PRIVATE
|
||||||
|
${PROJECT_SOURCE_DIR}/AtlasUI/Misc
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_atlas_build_flags(AtlasUI)
|
||||||
|
|
||||||
|
target_include_directories(AtlasUI PRIVATE ${CMAKE_SOURCE_DIR}/source/)
|
||||||
|
target_link_libraries(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
${BUILD_FLAGS_TARGET}
|
||||||
|
LibXml2::LibXml2
|
||||||
|
Iconv::Iconv
|
||||||
|
$<$<PLATFORM_ID:Linux>:Boost::headers>
|
||||||
|
$<$<PLATFORM_ID:Windows>:BOOST::headers>
|
||||||
|
SDL2::SDL2
|
||||||
|
ZLIB::ZLIB
|
||||||
|
AtlasObject
|
||||||
|
wxWidgets::wxWidgets
|
||||||
|
)
|
||||||
|
target_compile_definitions(AtlasUI
|
||||||
|
PRIVATE
|
||||||
|
$<$<VERSION_GREATER_EQUAL:${wxWidgets_VERSION},3.3.0>:wxNO_REQUIRE_LITERAL_MSGIDS>
|
||||||
|
)
|
||||||
|
|
||||||
|
# +++++++++++++++++++++ ActorEditor ++++++++++++++++++++++++
|
||||||
|
target_include_directories(ActorEditor
|
||||||
|
PRIVATE
|
||||||
|
${PROJECT_SOURCE_DIR}/
|
||||||
|
)
|
||||||
|
target_link_libraries(ActorEditor
|
||||||
|
PRIVATE
|
||||||
|
${BUILD_FLAGS_TARGET}
|
||||||
|
$<$<NOT:$<PLATFORM_ID:Windows>>:AtlasObject>
|
||||||
|
AtlasUI
|
||||||
|
)
|
||||||
|
target_link_options(ActorEditor
|
||||||
|
PRIVATE
|
||||||
|
$<$<AND:$<PLATFORM_ID:Windows>,$<STREQUAL:${ARCH},amd64>>:/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df'>
|
||||||
|
$<$<AND:$<PLATFORM_ID:Windows>,$<STREQUAL:${ARCH},x86>>:/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df'>
|
||||||
|
$<$<PLATFORM_ID:Darwin>:-arch ${MACOS_ARCH}>
|
||||||
|
)
|
||||||
|
target_compile_options(ActorEditor
|
||||||
|
PRIVATE
|
||||||
|
$<$<PLATFORM_ID:Darwin>:-arch ${MACOS_ARCH}>
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
set_target_properties(ActorEditor PROPERTIES
|
||||||
|
XCODE_ATTRIBUTE_ARCHS ${MACOS_ARCH}
|
||||||
|
XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET $<$<BOOL:${macosx-version-min}>:${macosx-version-min}>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# get_target_property(win32 ActorEditor WIN32_EXECUTABLE)
|
||||||
|
# get_target_property(macos ActorEditor MACOSX_BUNDLE)
|
||||||
|
# file(GENERATE OUTPUT debugexpr.txt CONTENT "${win32} ${macos}" TARGET ActorEditor)
|
||||||
|
# include(CMakePrintHelpers)
|
||||||
|
# cmake_print_properties(TARGETS AtlasUI
|
||||||
|
# PROPERTIES
|
||||||
|
# # INCLUDE_DIRECTORIES
|
||||||
|
# # LINK_LIBRARIES
|
||||||
|
# # COMPILE_OPTIONS
|
||||||
|
# # COMPILE_DEFINITIONS
|
||||||
|
# # WIN32_EXECUTABLE
|
||||||
|
# # MACOSX_BUNDLE
|
||||||
|
# # IMPORTED_LOCATION
|
||||||
|
# # INTERFACE_INCLUDE_DIRECTORIES
|
||||||
|
# # CXX_EXTENSIONS
|
||||||
|
# # CXX_STANDARD_REQUIRED
|
||||||
|
# )
|
||||||
Loading…
Reference in a new issue