diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..6791cc3ff --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,83 @@ +name: CI +on: + pull_request: + push: + +jobs: + build-windows: + name: Build (Windows) + runs-on: windows-2019 + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + submodules: true + path: openspades + + - name: Cache vcpkg and dependencies + uses: actions/cache@v2 + with: + path: | + vcpkg/installed + !.git + key: ${{ runner.os }}-${{ hashFiles('vcpkg_x86-windows.txt', '.gitmodules') }} + + - name: Bootstrap vcpkg + run: vcpkg/bootstrap-vcpkg.bat + + - name: Build dependencies + run: vcpkg/vcpkg install @vcpkg_x86-windows.txt + + - name: Build application + uses: ashutoshvarma/action-cmake-build@master + with: + build-dir: ${{ runner.workspace }}/openspades.mk + build-type: RelWithDebInfo + configure-options: -A Win32 -D CMAKE_BUILD_TYPE=RelWithDebInfo -D CMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/openspades/vcpkg/scripts/buildsystems/vcpkg.cmake -D VCPKG_TARGET_TRIPLET=x86-windows-static + parallel: 8 + + build-macos: + name: Build (macOS) + runs-on: macos-12 + steps: + - name: Checkout + uses: actions/checkout@v1 + with: + submodules: true + path: openspades + + - name: Cache vcpkg and dependencies + uses: actions/cache@v2 + with: + path: | + vcpkg/installed + !.git + key: ${{ runner.os }}-${{ hashFiles('vcpkg_x86_64-darwin.txt', '.gitmodules') }} + + - name: Bootstrap vcpkg + run: vcpkg/bootstrap-vcpkg.sh + + - name: Build dependencies + run: vcpkg/vcpkg install @vcpkg_x86_64-darwin.txt + + - name: Build application + uses: ashutoshvarma/action-cmake-build@master + with: + build-dir: ${{ runner.workspace }}/openspades.mk + build-type: RelWithDebInfo + configure-options: -D CMAKE_BUILD_TYPE=RelWithDebInfo -D CMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/openspades/vcpkg/scripts/buildsystems/vcpkg.cmake -D VCPKG_TARGET_TRIPLET=x64-osx -D CMAKE_OSX_ARCHITECTURES=x86_64 + parallel: 8 + + build-nix: + name: Build (Linux + Nix) + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Nix + uses: cachix/install-nix-action@v17 + + - name: Build Nix flake + run: nix build + diff --git a/.gitignore b/.gitignore index 843e7309a..d3fb3824c 100644 --- a/.gitignore +++ b/.gitignore @@ -34,10 +34,6 @@ CMakeCache.txt *CMakeFiles/ *.cmake -# cmake input dir (optional) -Sources/Externals/include/ -Sources/Externals/lib/ - # mac related *.DS_Store @@ -67,6 +63,10 @@ OpenSpades.msvc/ # Linux build path openspades.mk/ +# Nix +/outputs +/result + # fltk / fluid output leftovers Sources/Gui/DetailConfigWindow.txt Sources/Gui/MainWindow.txt diff --git a/.gitmodules b/.gitmodules index ff138137b..80d29f205 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "flatpak/shared-modules"] path = flatpak/shared-modules url = https://github.com/flathub/shared-modules.git +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 34496013e..000000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: cpp -dist: xenial - -compiler: - - gcc - -cache: apt - -install: - - sudo apt-get install pkg-config libglew-dev libcurl3-openssl-dev libjpeg-dev libxinerama-dev libxft-dev libsdl2-dev libsdl2-image-dev libfreetype6-dev libopus-dev libopusfile-dev gcc - -before_script: - - mkdir openspades.mk - - cd openspades.mk - -script: - - cmake -DOPENSPADES_RESOURCES=off .. - - cat CMakeCache.txt - - make -k \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 528b7188a..a16a6d27c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,60 +3,101 @@ project(OpenSpades) set(OpenSpades_VERSION_MAJOR 0) set(OpenSpades_VERSION_MINOR 1) -set(OpenSpades_VERSION_REVISION 3) +set(OpenSpades_VERSION_REVISION 5) set(OPENSPADES_FULL_VERSION "${OpenSpades_VERSION_MAJOR}.${OpenSpades_VERSION_MINOR}.${OpenSpades_VERSION_REVISION}") set(OS_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(CMAKE_PREFIX_PATH Sources/Externals) +if(VCPKG_TARGET_TRIPLET) + set(USE_VCPKG ON) +else() + set(USE_VCPKG OFF) +endif() # Prefer GLVND OpenGL if(POLICY CMP0072) cmake_policy(SET CMP0072 NEW) endif() -include(cmake/FindSDL2.cmake) -if(NOT SDL2_FOUND) - message(FATAL_ERROR "SDL 2.0 not found, set ENV{SDL2DIR} to point to SDL 2.0, and optionally set the cmake var SDL2_LIBRARY_TEMP to the lib dir") -endif() +if(USE_VCPKG) + find_package(Ogg CONFIG REQUIRED) + find_package(Opus CONFIG REQUIRED) + find_package(sdl2-image CONFIG REQUIRED) + find_package(SDL2 CONFIG REQUIRED) + find_package(freetype CONFIG REQUIRED) + + if(NOT APPLE) + find_package(GLEW REQUIRED) + set(GLEW_LIBRARY GLEW::GLEW) + + find_package(CURL REQUIRED) + set(CURL_LIBRARY CURL::libcurl) + endif() + + set(SDL2_LIBRARY SDL2::SDL2main SDL2::SDL2-static) + set(SDL2_IMAGE_LIBRARY SDL2::SDL2_image) + set(FREETYPE_LIBRARIES freetype) + + if(APPLE) + # Use system libraries + include(FindOpenGL) + include(FindCURL) + endif() + + FIND_LIBRARY(OpusFile_LIBRARY + NAMES opusfile + PATH_SUFFIXES lib64 lib + PATHS ${CMAKE_PREFIX_PATH} + ) +else() + include(cmake/FindSDL2.cmake) + if(NOT SDL2_FOUND) + message(FATAL_ERROR "SDL 2.0 not found, set ENV{SDL2DIR} to point to SDL 2.0, and optionally set the cmake var SDL2_LIBRARY_TEMP to the lib dir") + endif() -include(cmake/FindSDL2_image.cmake) -if(NOT SDL2_IMAGE_FOUND) - message(FATAL_ERROR "SDL_image 2.0 not found, set ENV{SDL2DIR} to point to SDL 2.0, and optionally set the cmake var SDL2_LIBRARY_TEMP to the lib dir") -endif() + include(cmake/FindSDL2_image.cmake) + if(NOT SDL2_IMAGE_FOUND) + message(FATAL_ERROR "SDL_image 2.0 not found, set ENV{SDL2DIR} to point to SDL 2.0, and optionally set the cmake var SDL2_LIBRARY_TEMP to the lib dir") + endif() -include(FindOpenGL) -if(NOT OPENGL_FOUND AND NOT OPENGL_XMESA_FOUND AND NOT OPENGL_GLU_FOUND) - message(FATAL_ERROR "OpenGL not found, please install it") -endif() -if(NOT APPLE) - include(cmake/FindGLEW2.cmake) - if(NOT GLEW_FOUND) - message(FATAL_ERROR "GLEW not found, please install it and make sure CMake can find it (add it to the PATH)") + include(FindOpenGL) + if(NOT OPENGL_FOUND AND NOT OPENGL_XMESA_FOUND AND NOT OPENGL_GLU_FOUND) + message(FATAL_ERROR "OpenGL not found, please install it") + endif() + if(NOT APPLE) + include(cmake/FindGLEW2.cmake) + if(NOT GLEW_FOUND) + message(FATAL_ERROR "GLEW not found, please install it and make sure CMake can find it (add it to the PATH)") + endif() endif() -endif() -include(FindZLIB) -if(NOT ZLIB_FOUND) - message(FATAL_ERROR "ZLIB not found, manually set ZLIB_ROOT in CMake") -endif() + include(FindZLIB) + if(NOT ZLIB_FOUND) + message(FATAL_ERROR "ZLIB not found, manually set ZLIB_ROOT in CMake") + endif() -include(FindCURL) -if(NOT CURL_FOUND) - message(FATAL_ERROR "cURL not found, please install it (and make sure it's in your path)") -endif() + include(FindCURL) + if(NOT CURL_FOUND) + message(FATAL_ERROR "cURL not found, please install it (and make sure it's in your path)") + endif() -include(FindFreetype) -if(NOT FREETYPE_FOUND) - message(FATAL_ERROR "FreeType not found, please install it (and make sure it's in your path)") -endif() + include(FindFreetype) + if(NOT FREETYPE_FOUND) + message(FATAL_ERROR "FreeType not found, please install it (and make sure it's in your path)") + endif() -include(cmake/FindOpus.cmake) -if(NOT OpusFile_FOUND) - message(FATAL_ERROR "libopus/libopusfile not found, please install it (and make sure it's in your path)") + include(cmake/FindOpus.cmake) + if(NOT OpusFile_FOUND) + message(FATAL_ERROR "libopus/libopusfile not found, please install it (and make sure it's in your path)") + endif() + include(cmake/FindXext.cmake) + if(NOT XEXT_FOUND) + message(FATAL_ERROR "libXext, please install it (and make sure it's in your path)") + endif() endif() + if(CMAKE_COMPILER_IS_GNUCXX) # GCC C++11 support # from http://stackoverflow.com/questions/10984442/how-to-detect-c11-support-of-a-compiler-with-cmake @@ -152,7 +193,9 @@ if(HAS_SOCKLEN_T) add_definitions(-DHAS_SOCKLEN_T=1) endif() -option(OPENSPADES_RESOURCES "NO_OPENSPADES_RESOURCES" ON) +option(OPENSPADES_RESOURCES "Build game assets" ON) +option(OPENSPADES_NONFREE_RESOURCES "Download non-GPL game assets" ON) +option(OPENSPADES_YSR "Download YSRSpades (closed-source audio backend; macOS only)" ON) # note that all paths are without trailing slash set(OPENSPADES_INSTALL_DOC "share/doc/openspades" CACHE STRING "Directory for installing documentation. ") @@ -193,24 +236,29 @@ endif() configure_file("${PROJECT_SOURCE_DIR}/OpenSpades.h.in" "${PROJECT_BINARY_DIR}/OpenSpades.h") configure_file("${PROJECT_SOURCE_DIR}/OpenSpades.rc.in" "${PROJECT_BINARY_DIR}/OpenSpades.rc") include_directories(BEFORE "${PROJECT_BINARY_DIR}") -include_directories("${SDL2_INCLUDE_DIR}") -include_directories("${SDL2_IMAGE_INCLUDE_DIR}") -if(OPENGL_INCLUDE_DIR) - include_directories("${OPENGL_INCLUDE_DIR}") -endif() -if(NOT APPLE) -include_directories("${GLEW_INCLUDE_DIR}") +if(USE_VCPKG) + include_directories("${PROJECT_SOURCE_DIR}/vcpkg/installed/${VCPKG_TARGET_TRIPLET}/include") +else() + include_directories("${SDL2_INCLUDE_DIR}") + include_directories("${SDL2_IMAGE_INCLUDE_DIR}") + if(OPENGL_INCLUDE_DIR) + include_directories("${OPENGL_INCLUDE_DIR}") + endif() + if(NOT APPLE) + include_directories("${GLEW_INCLUDE_DIR}") + endif() + include_directories("${ZLIB_INCLUDE_DIR}") + include_directories(${CURL_INCLUDE_DIRS}) + include_directories(${FREETYPE_INCLUDE_DIRS}) + include_directories(${OpusFile_INCLUDE_DIR}) + include_directories(${Opus_INCLUDE_DIR}) + include_directories(${Ogg_INCLUDE_DIR}) endif() -include_directories("${ZLIB_INCLUDE_DIR}") -include_directories(${CURL_INCLUDE_DIRS}) -include_directories(${FREETYPE_INCLUDE_DIRS}) -include_directories(${OpusFile_INCLUDE_DIR}) add_subdirectory(Resources) add_subdirectory(Sources) - -if(UNIX) +if(UNIX AND NOT APPLE) # various texts INSTALL(FILES AUTHORS LICENSE README.md DESTINATION ${OPENSPADES_INSTALL_DOC}/) @@ -228,15 +276,7 @@ if(UNIX) if(OPENSPADES_RESOURCES) # install asset paks (including non-GPL one) - install(FILES - ${CMAKE_BINARY_DIR}/Resources/pak000-Nonfree.pak - ${CMAKE_BINARY_DIR}/Resources/pak002-Base.pak - ${CMAKE_BINARY_DIR}/Resources/pak005-Models.pak - ${CMAKE_BINARY_DIR}/Resources/pak010-BaseSkin.pak - ${CMAKE_BINARY_DIR}/Resources/pak050-Locales.pak - ${CMAKE_BINARY_DIR}/Resources/pak999-References.pak - ${CMAKE_BINARY_DIR}/Resources/font-unifont.pak - DESTINATION ${OPENSPADES_INSTALL_RESOURCES}) + install(FILES ${PAK_FILES} DESTINATION ${OPENSPADES_INSTALL_RESOURCES}) endif(OPENSPADES_RESOURCES) # Package info (used for automatic update check) @@ -259,9 +299,50 @@ if(UNIX) # Currently there is no files in lib/openspades. But if you reading this message in future and want to # place somewhere libs, binaries or other non-media stuff, place them in lib/openspades. Thank you. -endif(UNIX) - - +endif(UNIX AND NOT APPLE) + +if(APPLE) + # Create a macOS application bundle + set_target_properties(OpenSpades PROPERTIES + MACOSX_BUNDLE ON + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/XSpades/XSpades-Info.plist + MACOSX_BUNDLE_BUNDLE_VERSION ${OPENSPADES_FULL_VERSION} + MACOSX_BUNDLE_LONG_VERSION_STRING ${OPENSPADES_FULL_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${OPENSPADES_FULL_VERSION} + MACOSX_BUNDLE_GUI_IDENTIFIER jp.yvt.openspades + MACOSX_BUNDLE_BUNDLE_NAME OpenSpades) + + set(BUNDLE_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Resources/Icons/OpenSpades.icns) + list(APPEND BUNDLE_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) + if(OPENSPADES_RESOURCES) + list(APPEND BUNDLE_RESOURCES ${PAK_FILES}) + set_source_files_properties(${PAK_FILES} + PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + add_dependencies(OpenSpades OpenSpades_Resources_DevPaks OpenSpades_Resources) + endif(OPENSPADES_RESOURCES) + list(APPEND BUNDLE_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Resources/PackageInfo.json) + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/Resources/PackageInfo.json + PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + if (OPENSPADES_YSR) + list(APPEND BUNDLE_RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/libysrspades.dylib) + + # Download `libysrspades.dylib` automatically + add_dependencies(OpenSpades OpenSpades_YSRSpades_Prebuilt) + add_custom_target(OpenSpades_YSRSpades_Prebuilt ALL COMMENT "Downloading libysrspades.dylib" + DEPENDS ${PROJECT_BINARY_DIR}/libysrspades.dylib) + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/libysrspades.dylib + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMAND + wget -c + https://openspadesmedia.yvt.jp/development-packages/YSRSpades/libysrspades.dylib + ) + endif (OPENSPADES_YSR) + + set_target_properties(OpenSpades PROPERTIES RESOURCE "${BUNDLE_RESOURCES}") + target_sources(OpenSpades PRIVATE "${BUNDLE_RESOURCES}") +endif(APPLE) #see http://www.cmake.org/cmake/help/v2.8.11/cpack.html set(CPACK_PACKAGE_NAME "OpenSpades") diff --git a/OpenSpades.h b/OpenSpades.h deleted file mode 100644 index 56b91dcea..000000000 --- a/OpenSpades.h +++ /dev/null @@ -1,17 +0,0 @@ -// This header file is provided for the Xcode project. -// In other platforms, please use OpenSpades.h generated by CMake. - -#define OpenSpades_VERSION_MAJOR 0 -#define OpenSpades_VERSION_MINOR 1 -#define OpenSpades_VERSION_REVISION 3 - -#define OS_STRINGIFY2(x) #x -#define OS_STRINGIFY(x) OS_STRINGIFY2(x) - -#define OpenSpades_VER_STR "OpenSpades 0.1.3-rc for OS X" -#define PACKAGE_STRING OpenSpades_VER_STR - -/* #undef HAS_OPENAL */ - -/* #undef RESDIR_DEFINED */ -//#define RESDIR "" diff --git a/OpenSpades.xcodeproj/project.pbxproj b/OpenSpades.xcodeproj/project.pbxproj index 8fea11213..e69de29bb 100644 --- a/OpenSpades.xcodeproj/project.pbxproj +++ b/OpenSpades.xcodeproj/project.pbxproj @@ -1,2569 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - E809500A1E17F66500AECDF2 /* GLSSAOFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80950081E17F66500AECDF2 /* GLSSAOFilter.cpp */; }; - E81012311E1D7301009955D3 /* Icon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E810122F1E1D7301009955D3 /* Icon.cpp */; }; - E82E66ED18EA7914004DBA18 /* StartupScreenHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E842888C18A3D1520060743D /* StartupScreenHelper.cpp */; }; - E82E66EE18EA7954004DBA18 /* GLBloomFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89E811F179C2C800059C649 /* GLBloomFilter.cpp */; }; - E82E66EF18EA7954004DBA18 /* GLQuadRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8D88AAF179C3004004C2451 /* GLQuadRenderer.cpp */; }; - E82E66F018EA7954004DBA18 /* GLLensFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8D88AB2179C45B7004C2451 /* GLLensFilter.cpp */; }; - E82E66F118EA7954004DBA18 /* GLCameraBlurFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E4469C179D59A900BE8855 /* GLCameraBlurFilter.cpp */; }; - E82E66F218EA7954004DBA18 /* GLFogFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E859510A17C5DA060012810C /* GLFogFilter.cpp */; }; - E82E66F318EA7954004DBA18 /* GLLensFlareFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E859510D17C61F850012810C /* GLLensFlareFilter.cpp */; }; - E82E66F418EA7954004DBA18 /* GLFXAAFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E859511017C645000012810C /* GLFXAAFilter.cpp */; }; - E82E66F518EA7954004DBA18 /* GLColorCorrectionFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8D2ACE117D704E600BE5490 /* GLColorCorrectionFilter.cpp */; }; - E82E66F618EA7954004DBA18 /* GLDepthOfFieldFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6E317E165A400E35523 /* GLDepthOfFieldFilter.cpp */; }; - E82E66F718EA7954004DBA18 /* GLLensDustFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72917E6095800E35523 /* GLLensDustFilter.cpp */; }; - E82E66F818EA7954004DBA18 /* GLImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF0400178FB52F000683D4 /* GLImage.cpp */; }; - E82E66F918EA7954004DBA18 /* GLFlatMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AF9B179A5BC200C6B5A9 /* GLFlatMapRenderer.cpp */; }; - E82E66FA18EA7954004DBA18 /* IGLSpriteRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E44696179D2CA100BE8855 /* IGLSpriteRenderer.cpp */; }; - E82E66FB18EA7954004DBA18 /* GLSpriteRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFA7179ACDDD00C6B5A9 /* GLSpriteRenderer.cpp */; }; - E82E66FC18EA7954004DBA18 /* GLSoftSpriteRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E44699179D2EDC00BE8855 /* GLSoftSpriteRenderer.cpp */; }; - E82E66FD18EA7954004DBA18 /* GLImageRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AF881798278000C6B5A9 /* GLImageRenderer.cpp */; }; - E82E66FE18EA7954004DBA18 /* GLImageManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318D6179176F3002ABE6D /* GLImageManager.cpp */; }; - E82E66FF18EA7954004DBA18 /* GLModelManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E741793D60E009D83E0 /* GLModelManager.cpp */; }; - E82E670018EA7954004DBA18 /* GLModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E7A1793E105009D83E0 /* GLModel.cpp */; }; - E82E670118EA7954004DBA18 /* GLVoxelModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E7D1793E1B3009D83E0 /* GLVoxelModel.cpp */; }; - E82E670218EA7954004DBA18 /* GLMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318AF1790F73F002ABE6D /* GLMapRenderer.cpp */; }; - E82E670318EA7954004DBA18 /* GLMapChunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318B217911A73002ABE6D /* GLMapChunk.cpp */; }; - E82E670418EA7954004DBA18 /* GLModelRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89A648C17A11B4E00FDA893 /* GLModelRenderer.cpp */; }; - E82E670518EA7954004DBA18 /* GLOptimizedVoxelModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B286F17A4CA2B0056179E /* GLOptimizedVoxelModel.cpp */; }; - E82E670618EA7954004DBA18 /* GLWaterRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B289717AA63FC0056179E /* GLWaterRenderer.cpp */; }; - E82E670718EA7954004DBA18 /* GLLongSpriteRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E844886017CFB32B005105D0 /* GLLongSpriteRenderer.cpp */; }; - E82E670818EA7954004DBA18 /* GLSoftLitSpriteRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72C17E68B1B00E35523 /* GLSoftLitSpriteRenderer.cpp */; }; - E82E670918EA7954004DBA18 /* GLShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF04191790CCAB000683D4 /* GLShader.cpp */; }; - E82E670A18EA7954004DBA18 /* GLProgramUniform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318A91790EBAA002ABE6D /* GLProgramUniform.cpp */; }; - E82E670B18EA7954004DBA18 /* GLProgramAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318AC1790EDDF002ABE6D /* GLProgramAttribute.cpp */; }; - E82E670C18EA7954004DBA18 /* GLProgram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF04061790455B000683D4 /* GLProgram.cpp */; }; - E82E670D18EA7954004DBA18 /* GLMapShadowRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E446A2179EA60900BE8855 /* GLMapShadowRenderer.cpp */; }; - E82E670E18EA7954004DBA18 /* GLShadowShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E446A5179EAC7800BE8855 /* GLShadowShader.cpp */; }; - E82E670F18EA7954004DBA18 /* GLDynamicLightShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89A648F17A12FF800FDA893 /* GLDynamicLightShader.cpp */; }; - E82E671018EA7954004DBA18 /* IGLShadowMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89A649817A2402500FDA893 /* IGLShadowMapRenderer.cpp */; }; - E82E671118EA7954004DBA18 /* GLShadowMapShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B286017A2462D0056179E /* GLShadowMapShader.cpp */; }; - E82E671218EA7954004DBA18 /* GLBasicShadowMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B286317A24AED0056179E /* GLBasicShadowMapRenderer.cpp */; }; - E82E671318EA7954004DBA18 /* GLDynamicLight.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B289417A9D6B40056179E /* GLDynamicLight.cpp */; }; - E82E671418EA7954004DBA18 /* GLAmbientShadowRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B28BF17AE7FEB0056179E /* GLAmbientShadowRenderer.cpp */; }; - E82E671518EA7954004DBA18 /* GLRadiosityRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8EE089F17B8F4B000631987 /* GLRadiosityRenderer.cpp */; }; - E82E671618EA7954004DBA18 /* GLSparseShadowMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6BD17DF456E00E35523 /* GLSparseShadowMapRenderer.cpp */; }; - E82E671718EA7954004DBA18 /* GLRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03A9178EDF74000683D4 /* GLRenderer.cpp */; }; - E82E671818EA7954004DBA18 /* IGLDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03AC178EDFCD000683D4 /* IGLDevice.cpp */; }; - E82E671918EA7954004DBA18 /* GLFramebufferManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFB6179C0F2800C6B5A9 /* GLFramebufferManager.cpp */; }; - E82E671A18EA7954004DBA18 /* GLProgramManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF041C1790D6D5000683D4 /* GLProgramManager.cpp */; }; - E82E671B18EA7954004DBA18 /* GLProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E859511317C96B260012810C /* GLProfiler.cpp */; }; - E82E671C18EA7954004DBA18 /* Main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03BE178EE50E000683D4 /* Main.cpp */; }; - E82E671D18EA7954004DBA18 /* SDLGLDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03BB178EE502000683D4 /* SDLGLDevice.cpp */; }; - E82E671E18EA7954004DBA18 /* SDLRunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03E1178EF57E000683D4 /* SDLRunner.cpp */; }; - E82E672018EA7954004DBA18 /* MainScreen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81CE4A7183F7F2000F22685 /* MainScreen.cpp */; }; - E82E672118EA7954004DBA18 /* MainScreenHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CED183FBA9C0085AA54 /* MainScreenHelper.cpp */; }; - E82E672218EA7954004DBA18 /* View.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CE3183F86AE0085AA54 /* View.cpp */; }; - E82E672318EA7954004DBA18 /* Runner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CE7183F8B9D0085AA54 /* Runner.cpp */; }; - E82E672418EA7954004DBA18 /* StartupScreen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E842888918A3CF6C0060743D /* StartupScreen.cpp */; }; - E82E672518EA7967004DBA18 /* json_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E844887B17D2633C005105D0 /* json_reader.cpp */; }; - E82E672618EA7967004DBA18 /* json_value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E844887C17D2633C005105D0 /* json_value.cpp */; }; - E82E672718EA7967004DBA18 /* json_writer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E844887E17D2633C005105D0 /* json_writer.cpp */; }; - E82E672818EA7967004DBA18 /* scriptany.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70017E4193A00E35523 /* scriptany.cpp */; }; - E82E672918EA7967004DBA18 /* scriptarray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70217E4193A00E35523 /* scriptarray.cpp */; }; - E82E672A18EA7967004DBA18 /* scriptbuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70417E4193A00E35523 /* scriptbuilder.cpp */; }; - E82E672B18EA7967004DBA18 /* scriptdictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70617E4193A00E35523 /* scriptdictionary.cpp */; }; - E82E672C18EA7967004DBA18 /* scripthandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70817E4193A00E35523 /* scripthandle.cpp */; }; - E82E672D18EA7967004DBA18 /* scripthelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70A17E4193A00E35523 /* scripthelper.cpp */; }; - E82E672E18EA7967004DBA18 /* scriptmath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70C17E4193A00E35523 /* scriptmath.cpp */; }; - E82E672F18EA7967004DBA18 /* scriptmathcomplex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B70E17E4193A00E35523 /* scriptmathcomplex.cpp */; }; - E82E673018EA7967004DBA18 /* scriptstdstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B71017E4193A00E35523 /* scriptstdstring.cpp */; }; - E82E673118EA7967004DBA18 /* scriptstdstring_utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B71217E4193A00E35523 /* scriptstdstring_utils.cpp */; }; - E82E673218EA7967004DBA18 /* weakref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B71317E4193A00E35523 /* weakref.cpp */; }; - E82E673318EA7972004DBA18 /* as_atomic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64217DE27B500E35523 /* as_atomic.cpp */; }; - E82E673418EA7972004DBA18 /* as_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64417DE27B500E35523 /* as_builder.cpp */; }; - E82E673518EA7972004DBA18 /* as_bytecode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64617DE27B500E35523 /* as_bytecode.cpp */; }; - E82E673618EA7972004DBA18 /* as_callfunc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64817DE27B500E35523 /* as_callfunc.cpp */; }; - E82E673718EA7972004DBA18 /* as_callfunc_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64A17DE27B500E35523 /* as_callfunc_arm.cpp */; }; - E82E673818EA7972004DBA18 /* as_callfunc_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64E17DE27B500E35523 /* as_callfunc_mips.cpp */; }; - E82E673918EA7972004DBA18 /* as_callfunc_ppc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B64F17DE27B500E35523 /* as_callfunc_ppc.cpp */; }; - E82E673A18EA7972004DBA18 /* as_callfunc_ppc_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65017DE27B500E35523 /* as_callfunc_ppc_64.cpp */; }; - E82E673B18EA7972004DBA18 /* as_callfunc_sh4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65117DE27B500E35523 /* as_callfunc_sh4.cpp */; }; - E82E673C18EA7972004DBA18 /* as_callfunc_x64_gcc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65217DE27B500E35523 /* as_callfunc_x64_gcc.cpp */; }; - E82E673D18EA7972004DBA18 /* as_callfunc_x64_mingw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65317DE27B500E35523 /* as_callfunc_x64_mingw.cpp */; }; - E82E673E18EA7972004DBA18 /* as_callfunc_x64_msvc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65417DE27B500E35523 /* as_callfunc_x64_msvc.cpp */; }; - E82E673F18EA7972004DBA18 /* as_callfunc_x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65617DE27B500E35523 /* as_callfunc_x86.cpp */; }; - E82E674018EA7972004DBA18 /* as_callfunc_xenon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65717DE27B500E35523 /* as_callfunc_xenon.cpp */; }; - E82E674118EA7972004DBA18 /* as_compiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65817DE27B500E35523 /* as_compiler.cpp */; }; - E82E674218EA7972004DBA18 /* as_configgroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65B17DE27B500E35523 /* as_configgroup.cpp */; }; - E82E674318EA7972004DBA18 /* as_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B65D17DE27B500E35523 /* as_context.cpp */; }; - E82E674418EA7972004DBA18 /* as_datatype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66017DE27B500E35523 /* as_datatype.cpp */; }; - E82E674518EA7972004DBA18 /* as_gc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66317DE27B500E35523 /* as_gc.cpp */; }; - E82E674618EA7972004DBA18 /* as_generic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66517DE27B500E35523 /* as_generic.cpp */; }; - E82E674718EA7972004DBA18 /* as_globalproperty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66717DE27B500E35523 /* as_globalproperty.cpp */; }; - E82E674818EA7972004DBA18 /* as_memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66917DE27B500E35523 /* as_memory.cpp */; }; - E82E674918EA7972004DBA18 /* as_module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66B17DE27B500E35523 /* as_module.cpp */; }; - E82E674A18EA7972004DBA18 /* as_objecttype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66D17DE27B500E35523 /* as_objecttype.cpp */; }; - E82E674B18EA7972004DBA18 /* as_outputbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B66F17DE27B500E35523 /* as_outputbuffer.cpp */; }; - E82E674C18EA7972004DBA18 /* as_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67117DE27B500E35523 /* as_parser.cpp */; }; - E82E674D18EA7972004DBA18 /* as_restore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67417DE27B500E35523 /* as_restore.cpp */; }; - E82E674E18EA7972004DBA18 /* as_scriptcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67617DE27B500E35523 /* as_scriptcode.cpp */; }; - E82E674F18EA7972004DBA18 /* as_scriptengine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67817DE27B500E35523 /* as_scriptengine.cpp */; }; - E82E675018EA7972004DBA18 /* as_scriptfunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67A17DE27B500E35523 /* as_scriptfunction.cpp */; }; - E82E675118EA7972004DBA18 /* as_scriptnode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67C17DE27B500E35523 /* as_scriptnode.cpp */; }; - E82E675218EA7972004DBA18 /* as_scriptobject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B67E17DE27B500E35523 /* as_scriptobject.cpp */; }; - E82E675318EA7972004DBA18 /* as_string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B68017DE27B500E35523 /* as_string.cpp */; }; - E82E675418EA7972004DBA18 /* as_string_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B68217DE27B500E35523 /* as_string_util.cpp */; }; - E82E675518EA7972004DBA18 /* as_thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B68617DE27B500E35523 /* as_thread.cpp */; }; - E82E675618EA7972004DBA18 /* as_tokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B68917DE27B500E35523 /* as_tokenizer.cpp */; }; - E82E675718EA7972004DBA18 /* as_typeinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B68B17DE27B500E35523 /* as_typeinfo.cpp */; }; - E82E675818EA7972004DBA18 /* as_variablescope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B68D17DE27B500E35523 /* as_variablescope.cpp */; }; - E82E675918EA7972004DBA18 /* ALDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E581792BEFC009D83E0 /* ALDevice.cpp */; }; - E82E675A18EA7972004DBA18 /* ALFuncs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E5C1792C089009D83E0 /* ALFuncs.cpp */; }; - E82E675B18EA7972004DBA18 /* YsrDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88EB02D185D9DC500565D07 /* YsrDevice.cpp */; }; - E82E675C18EA7972004DBA18 /* NullDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E842889118A3D9C40060743D /* NullDevice.cpp */; }; - E82E675D18EA7972004DBA18 /* PngWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E895D66318D614DE00F5B9CA /* PngWriter.cpp */; }; - E82E675E18EA7972004DBA18 /* jpge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E895D65B18D4A10E00F5B9CA /* jpge.cpp */; }; - E82E675F18EA7972004DBA18 /* IBitmapCodec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E44684179CC4FF00BE8855 /* IBitmapCodec.cpp */; }; - E82E676018EA7972004DBA18 /* TargaReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E44687179CC65900BE8855 /* TargaReader.cpp */; }; - E82E676118EA7972004DBA18 /* TargaWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E446A8179F822D00BE8855 /* TargaWriter.cpp */; }; - E82E676218EA7972004DBA18 /* SdlImageReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E87AB82118BB3957006B7D73 /* SdlImageReader.cpp */; }; - E82E676318EA7972004DBA18 /* JpegWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E895D65E18D4A15900F5B9CA /* JpegWriter.cpp */; }; - E82E676418EA7972004DBA18 /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318D3179172AF002ABE6D /* Bitmap.cpp */; }; - E82E676518EA7972004DBA18 /* VoxelModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E771793DC37009D83E0 /* VoxelModel.cpp */; }; - E82E676618EA7972004DBA18 /* IAudioStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E611792CA12009D83E0 /* IAudioStream.cpp */; }; - E82E676718EA7972004DBA18 /* WavAudioStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E641792CCE5009D83E0 /* WavAudioStream.cpp */; }; - E82E676818EA7972004DBA18 /* BitmapAtlasGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B288617A52AB60056179E /* BitmapAtlasGenerator.cpp */; }; - E82E676918EA7972004DBA18 /* ServerAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72617E5AC9C00E35523 /* ServerAddress.cpp */; }; - E82E676A18EA7972004DBA18 /* IFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF04091790471D000683D4 /* IFileSystem.cpp */; }; - E82E676B18EA7972004DBA18 /* FileManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF040C17904970000683D4 /* FileManager.cpp */; }; - E82E676C18EA7972004DBA18 /* IStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF040F17904ABC000683D4 /* IStream.cpp */; }; - E82E676D18EA7972004DBA18 /* StdStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF041217904E8B000683D4 /* StdStream.cpp */; }; - E82E676E18EA7972004DBA18 /* SdlFileStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E849654E18E94F1200B9706D /* SdlFileStream.cpp */; }; - E82E676F18EA7972004DBA18 /* DirectoryFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF0415179052F6000683D4 /* DirectoryFileSystem.cpp */; }; - E82E677018EA7972004DBA18 /* DeflateStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F55D17950E41004EBE88 /* DeflateStream.cpp */; }; - E82E677118EA7972004DBA18 /* MemoryStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F56317951B1A004EBE88 /* MemoryStream.cpp */; }; - E82E677218EA7972004DBA18 /* ZipFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B28DC17B39EEE0056179E /* ZipFileSystem.cpp */; }; - E82E677318EA7972004DBA18 /* DynamicMemoryStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B28DF17B4FDD40056179E /* DynamicMemoryStream.cpp */; }; - E82E677418EA7972004DBA18 /* VersionInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E85233791839B28C00F40541 /* VersionInfo.cpp */; }; - E82E677518EA7972004DBA18 /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03B0178EE300000683D4 /* Thread.cpp */; }; - E82E677618EA7972004DBA18 /* Semaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03CF178EEF80000683D4 /* Semaphore.cpp */; }; - E82E677818EA7972004DBA18 /* ILockable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03D5178EF09C000683D4 /* ILockable.cpp */; }; - E82E677A18EA7972004DBA18 /* IRunnable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03DE178EF4E9000683D4 /* IRunnable.cpp */; }; - E82E677B18EA7972004DBA18 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF0403178FF776000683D4 /* Exception.cpp */; }; - E82E677C18EA7972004DBA18 /* DynamicLibrary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E5E1792C0FF009D83E0 /* DynamicLibrary.cpp */; }; - E82E677D18EA7972004DBA18 /* ConcurrentDispatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B286C17A3B0570056179E /* ConcurrentDispatch.cpp */; }; - E82E677E18EA7972004DBA18 /* ThreadLocalStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B288B17A5FFB30056179E /* ThreadLocalStorage.cpp */; }; - E82E677F18EA7972004DBA18 /* CpuID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C92A0E186A902500740C9F /* CpuID.cpp */; }; - E82E678018EA7972004DBA18 /* MathScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6E717E40AF500E35523 /* MathScript.cpp */; }; - E82E678118EA7972004DBA18 /* StringsScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E838D42018ADDE2800EE3C53 /* StringsScript.cpp */; }; - E82E678218EA7972004DBA18 /* ScriptManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6E817E40AF500E35523 /* ScriptManager.cpp */; }; - E82E678318EA7972004DBA18 /* IImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6EC17E40B5900E35523 /* IImage.cpp */; }; - E82E678418EA7972004DBA18 /* IModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6F217E40E8200E35523 /* IModel.cpp */; }; - E82E678518EA7972004DBA18 /* IRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6F517E40F9900E35523 /* IRenderer.cpp */; }; - E82E678618EA7972004DBA18 /* GameMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6F817E4130E00E35523 /* GameMap.cpp */; }; - E82E678718EA7972004DBA18 /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6FB17E413AB00E35523 /* Bitmap.cpp */; }; - E82E678818EA7972004DBA18 /* VoxelModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6FD17E4141000E35523 /* VoxelModel.cpp */; }; - E82E678918EA7972004DBA18 /* IAudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72017E4508C00E35523 /* IAudioDevice.cpp */; }; - E82E678A18EA7972004DBA18 /* IAudioChunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72217E452EC00E35523 /* IAudioChunk.cpp */; }; - E82E678B18EA7972004DBA18 /* PrimitiveArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72417E46C1B00E35523 /* PrimitiveArray.cpp */; }; - E82E678C18EA7972004DBA18 /* IToolSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B72F17E8C4ED00E35523 /* IToolSkin.cpp */; }; - E82E678D18EA7972004DBA18 /* ScriptFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B73217E8CE1300E35523 /* ScriptFunction.cpp */; }; - E82E678E18EA7972004DBA18 /* ISpadeSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B73817E9E8CF00E35523 /* ISpadeSkin.cpp */; }; - E82E678F18EA7972004DBA18 /* IBlockSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B73B17E9F49700E35523 /* IBlockSkin.cpp */; }; - E82E679018EA7972004DBA18 /* IViewToolSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B73E17EA060900E35523 /* IViewToolSkin.cpp */; }; - E82E679118EA7972004DBA18 /* IThirdPersonToolSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B74117EA0B1500E35523 /* IThirdPersonToolSkin.cpp */; }; - E82E679218EA7972004DBA18 /* IGrenadeSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B74417EA0F1B00E35523 /* IGrenadeSkin.cpp */; }; - E82E679318EA7972004DBA18 /* IWeaponSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B74717EA12E100E35523 /* IWeaponSkin.cpp */; }; - E82E679418EA7972004DBA18 /* IFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81CE4A4183F7A3000F22685 /* IFont.cpp */; }; - E82E679518EA7972004DBA18 /* MainScreenHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CF0183FBB070085AA54 /* MainScreenHelper.cpp */; }; - E82E679618EA7972004DBA18 /* StartupScreenHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E842888F18A3D6470060743D /* StartupScreenHelper.cpp */; }; - E82E679718EA7972004DBA18 /* Config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CF31840D4CC0085AA54 /* Config.cpp */; }; - E82E679818EA7972004DBA18 /* ClientUIHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CFC1845C8D50085AA54 /* ClientUIHelper.cpp */; }; - E82E679918EA7972004DBA18 /* Clipboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CFE184C753F0085AA54 /* Clipboard.cpp */; }; - E82E679A18EA7972004DBA18 /* Math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03CC178EE95F000683D4 /* Math.cpp */; }; - E82E679B18EA7972004DBA18 /* Deque.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318DF17925F2E002ABE6D /* Deque.cpp */; }; - E82E679C18EA7972004DBA18 /* Stopwatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318E21792698D002ABE6D /* Stopwatch.cpp */; }; - E82E679D18EA7972004DBA18 /* Debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F5541794BBD4004EBE88 /* Debug.cpp */; }; - E82E679E18EA7972004DBA18 /* Settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFB3179BF25B00C6B5A9 /* Settings.cpp */; }; - E82E679F18EA7972004DBA18 /* FltkPreferenceImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E849654B18E9487300B9706D /* FltkPreferenceImporter.cpp */; }; - E82E67A018EA7972004DBA18 /* RefCountedObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B6EF17E40DA700E35523 /* RefCountedObject.cpp */; }; - E82E67A118EA7972004DBA18 /* MiniHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C7B1865A2E900BF3FCE /* MiniHeap.cpp */; }; - E82E67A218EA7972004DBA18 /* CP437.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E890F30E187046990090AAB8 /* CP437.cpp */; }; - E82E67A318EA7972004DBA18 /* Strings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E838D41D18AC726B00EE3C53 /* Strings.cpp */; }; - E82E67A418EA7972004DBA18 /* IRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03A6178EDF6A000683D4 /* IRenderer.cpp */; }; - E82E67A518EA7972004DBA18 /* SceneDefinition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03F7178FABA4000683D4 /* SceneDefinition.cpp */; }; - E82E67A618EA7972004DBA18 /* IAudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03C6178EE81A000683D4 /* IAudioDevice.cpp */; }; - E82E67A718EA7972004DBA18 /* IAudioChunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E551792B24D009D83E0 /* IAudioChunk.cpp */; }; - E82E67A818EA7972004DBA18 /* IInputInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03C9178EE869000683D4 /* IInputInterface.cpp */; }; - E82E67A918EA7972004DBA18 /* IImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03F4178FAA8B000683D4 /* IImage.cpp */; }; - E82E67AA18EA7972004DBA18 /* IModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E711793D5AD009D83E0 /* IModel.cpp */; }; - E82E67AC18EA7972004DBA18 /* NetClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F55117944778004EBE88 /* NetClient.cpp */; }; - E82E67AD18EA7972004DBA18 /* ILocalEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFAA179ADC2100C6B5A9 /* ILocalEntity.cpp */; }; - E82E67AE18EA7972004DBA18 /* ParticleSpriteEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFAD179ADDCB00C6B5A9 /* ParticleSpriteEntity.cpp */; }; - E82E67AF18EA7972004DBA18 /* SmokeSpriteEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFB0179AF4E600C6B5A9 /* SmokeSpriteEntity.cpp */; }; - E82E67B018EA7972004DBA18 /* FallingBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89A649217A1677F00FDA893 /* FallingBlock.cpp */; }; - E82E67B118EA7972004DBA18 /* GunCasing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89A649517A1835900FDA893 /* GunCasing.cpp */; }; - E82E67B218EA7972004DBA18 /* Tracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E844886417D0C43B005105D0 /* Tracer.cpp */; }; - E82E67B318EA7972004DBA18 /* ClientPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8B6B73517E9C70000E35523 /* ClientPlayer.cpp */; }; - E82E67B418EA7972004DBA18 /* Client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03C1178EE6D8000683D4 /* Client.cpp */; }; - E82E67B518EA7972004DBA18 /* Client_Input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE748B18CC6AA100291338 /* Client_Input.cpp */; }; - E82E67B618EA7972004DBA18 /* Client_Update.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE748D18CC6C2B00291338 /* Client_Update.cpp */; }; - E82E67B718EA7972004DBA18 /* Client_NetHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE748F18CC6CE000291338 /* Client_NetHandler.cpp */; }; - E82E67B818EA7972004DBA18 /* Client_LocalEnts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE749118CC6E4900291338 /* Client_LocalEnts.cpp */; }; - E82E67B918EA7972004DBA18 /* Client_Draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE749318CC6EB500291338 /* Client_Draw.cpp */; }; - E82E67BA18EA7972004DBA18 /* Client_Scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE749518CC6F2900291338 /* Client_Scene.cpp */; }; - E82E67BB18EA7972004DBA18 /* Client_FPSCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E82E66B218E9A35C004DBA18 /* Client_FPSCounter.cpp */; }; - E82E67BC18EA7972004DBA18 /* ChatWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F56D1797D92F004EBE88 /* ChatWindow.cpp */; }; - E82E67BD18EA7972004DBA18 /* Corpse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AF92179942DB00C6B5A9 /* Corpse.cpp */; }; - E82E67BE18EA7972004DBA18 /* CenterMessageView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AF95179980F500C6B5A9 /* CenterMessageView.cpp */; }; - E82E67BF18EA7972004DBA18 /* HurtRingView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AF98179996A100C6B5A9 /* HurtRingView.cpp */; }; - E82E67C018EA7972004DBA18 /* MapView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AF9E179A698800C6B5A9 /* MapView.cpp */; }; - E82E67C118EA7972004DBA18 /* ScoreboardView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFA1179A8F1000C6B5A9 /* ScoreboardView.cpp */; }; - E82E67C218EA7972004DBA18 /* LimboView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8E0AFA4179AA31B00C6B5A9 /* LimboView.cpp */; }; - E82E67C318EA7972004DBA18 /* PaletteView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B28CB17AFCCC40056179E /* PaletteView.cpp */; }; - E82E67C418EA7972004DBA18 /* TCProgressView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B28D117AFF77B0056179E /* TCProgressView.cpp */; }; - E82E67C518EA7972004DBA18 /* ClientUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CF61845C5000085AA54 /* ClientUI.cpp */; }; - E82E67C618EA7972004DBA18 /* ClientUIHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F74CF91845C64B0085AA54 /* ClientUIHelper.cpp */; }; - E82E67C718EA7972004DBA18 /* Quake3Font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F56617979F55004EBE88 /* Quake3Font.cpp */; }; - E82E67C818EA7972004DBA18 /* IFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F56917979FD3004EBE88 /* IFont.cpp */; }; - E82E67C918EA7972004DBA18 /* Fonts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E842889418A667930060743D /* Fonts.cpp */; }; - E82E67CA18EA7972004DBA18 /* IGameMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F5571794DCF9004EBE88 /* IGameMode.cpp */; }; - E82E67CB18EA7972004DBA18 /* CTFGameMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F55A1794DDA2004EBE88 /* CTFGameMode.cpp */; }; - E82E67CC18EA7972004DBA18 /* TCGameMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E80B28CE17AFE68A0056179E /* TCGameMode.cpp */; }; - E82E67CD18EA7972004DBA18 /* Player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318D9179256E4002ABE6D /* Player.cpp */; }; - E82E67CE18EA7972004DBA18 /* Grenade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E834F54E17942C43004EBE88 /* Grenade.cpp */; }; - E82E67CF18EA7972004DBA18 /* Weapon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E6E1793AA45009D83E0 /* Weapon.cpp */; }; - E82E67D018EA7972004DBA18 /* GameMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03FA178FACFF000683D4 /* GameMap.cpp */; }; - E82E67D118EA7972004DBA18 /* IGameMapListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CF03FD178FB1E1000683D4 /* IGameMapListener.cpp */; }; - E82E67D218EA7972004DBA18 /* GameMapWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318DC179257F0002ABE6D /* GameMapWrapper.cpp */; }; - E82E67D318EA7972004DBA18 /* World.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E88318E617928F84002ABE6D /* World.cpp */; }; - E82E67D418EA7972004DBA18 /* IWorldListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8567E6A1792F398009D83E0 /* IWorldListener.cpp */; }; - E82E67D518EA7972004DBA18 /* HitTestDebugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8FE748818CB329C00291338 /* HitTestDebugger.cpp */; }; - E82E67D618EA7972004DBA18 /* SWRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C6218610AA900BF3FCE /* SWRenderer.cpp */; }; - E82E67D718EA7972004DBA18 /* SWPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C6518610BE400BF3FCE /* SWPort.cpp */; }; - E82E67D818EA7972004DBA18 /* SWImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C691861525D00BF3FCE /* SWImage.cpp */; }; - E82E67D918EA7972004DBA18 /* SWModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C6C186152A400BF3FCE /* SWModel.cpp */; }; - E82E67DA18EA7972004DBA18 /* SWImageRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C6F1861F4E200BF3FCE /* SWImageRenderer.cpp */; }; - E82E67DB18EA7972004DBA18 /* SWFeatureLevel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C731863566200BF3FCE /* SWFeatureLevel.cpp */; }; - E82E67DC18EA7972004DBA18 /* SWMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C751864171100BF3FCE /* SWMapRenderer.cpp */; }; - E82E67DD18EA7972004DBA18 /* SWFlatMapRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E81A7C7818642BCA00BF3FCE /* SWFlatMapRenderer.cpp */; }; - E82E67DE18EA7972004DBA18 /* SWModelRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C92A0A18695EA500740C9F /* SWModelRenderer.cpp */; }; - E82E67DF18EA7A05004DBA18 /* SDL2_image.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E87AB82418BB3A04006B7D73 /* SDL2_image.framework */; }; - E82E67E018EA7A05004DBA18 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8B93AD418559EC600BD01E1 /* SDL2.framework */; }; - E82E67E218EA7A1E004DBA18 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF039B178EDAC9000683D4 /* libz.tbd */; }; - E82E67E318EA7A51004DBA18 /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = E80B28D617B39D160056179E /* ioapi.c */; }; - E82E67E418EA7A51004DBA18 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = E80B28D817B39D160056179E /* unzip.c */; }; - E82E67E518EA7A51004DBA18 /* kiss_fft.c in Sources */ = {isa = PBXBuildFile; fileRef = E80B28B817ABAC790056179E /* kiss_fft.c */; }; - E82E67E618EA7A51004DBA18 /* callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319021792A7CC002ABE6D /* callbacks.c */; }; - E82E67E718EA7A51004DBA18 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319031792A7CC002ABE6D /* compress.c */; }; - E82E67E818EA7A51004DBA18 /* host.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319041792A7CC002ABE6D /* host.c */; }; - E82E67E918EA7A51004DBA18 /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319111792A7CC002ABE6D /* list.c */; }; - E82E67EA18EA7A51004DBA18 /* packet.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319121792A7CC002ABE6D /* packet.c */; }; - E82E67EB18EA7A51004DBA18 /* peer.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319131792A7CC002ABE6D /* peer.c */; }; - E82E67EC18EA7A51004DBA18 /* protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319141792A7CC002ABE6D /* protocol.c */; }; - E82E67ED18EA7A51004DBA18 /* unix.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319161792A7CC002ABE6D /* unix.c */; }; - E82E67EE18EA7A51004DBA18 /* win32.c in Sources */ = {isa = PBXBuildFile; fileRef = E88319171792A7CC002ABE6D /* win32.c */; }; - E82E67EF18EA7A51004DBA18 /* pnglite.c in Sources */ = {isa = PBXBuildFile; fileRef = E895D66118D614DE00F5B9CA /* pnglite.c */; }; - E82E67F018EA7A60004DBA18 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF03C4178EE78C000683D4 /* OpenGL.framework */; }; - E82E67FA18EA7EAB004DBA18 /* font-unifont.pak in Resources */ = {isa = PBXBuildFile; fileRef = E82E67F318EA7EAB004DBA18 /* font-unifont.pak */; }; - E82E680418EA7F60004DBA18 /* libysrspades.dylib in Resources */ = {isa = PBXBuildFile; fileRef = E82E680318EA7F60004DBA18 /* libysrspades.dylib */; }; - E83668AF1E05757B00977A63 /* OpusAudioStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E83668AD1E05757B00977A63 /* OpusAudioStream.cpp */; }; - E83668B21E05844E00977A63 /* AudioStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E83668B01E05844E00977A63 /* AudioStream.cpp */; }; - E8403CA8229061BF00093C3E /* RandomAccessAdaptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8403CA6229061BE00093C3E /* RandomAccessAdaptor.cpp */; }; - E8403CAB229123CF00093C3E /* PipeStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8403CA9229123CF00093C3E /* PipeStream.cpp */; }; - E8403CAE2291280800093C3E /* GameMapLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8403CAD2291280700093C3E /* GameMapLoader.cpp */; }; - E8403CB12299073400093C3E /* VoxelModelLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8403CB02299073400093C3E /* VoxelModelLoader.cpp */; }; - E8626EAE1E1009D7003365BF /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E844888617D26699005105D0 /* libcurl.tbd */; }; - E8626EB61E100EC6003365BF /* libfreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E8626EB51E100EC6003365BF /* libfreetype.a */; }; - E8626EB81E100FB2003365BF /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E8626EB71E100FB2003365BF /* libogg.a */; }; - E8626EBB1E101072003365BF /* libopus.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E8626EB91E101072003365BF /* libopus.a */; }; - E8626EBC1E101072003365BF /* libopusfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E8626EBA1E101072003365BF /* libopusfile.a */; }; - E8626EBE1E1010CA003365BF /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E8626EBD1E1010CA003365BF /* libbz2.tbd */; }; - E8655AA81DFC0A6E00D5058A /* FTFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8655AA61DFC0A6E00D5058A /* FTFont.cpp */; }; - E8690AEC1D3920C800DBC331 /* pak000-Nonfree.pak in Resources */ = {isa = PBXBuildFile; fileRef = E8690AE61D3920C800DBC331 /* pak000-Nonfree.pak */; }; - E8690AED1D3920C800DBC331 /* pak002-Base.pak in Resources */ = {isa = PBXBuildFile; fileRef = E8690AE71D3920C800DBC331 /* pak002-Base.pak */; }; - E8690AEE1D3920C800DBC331 /* pak005-Models.pak in Resources */ = {isa = PBXBuildFile; fileRef = E8690AE81D3920C800DBC331 /* pak005-Models.pak */; }; - E8690AEF1D3920C800DBC331 /* pak010-BaseSkin.pak in Resources */ = {isa = PBXBuildFile; fileRef = E8690AE91D3920C800DBC331 /* pak010-BaseSkin.pak */; }; - E8690AF01D3920C800DBC331 /* pak050-Locales.pak in Resources */ = {isa = PBXBuildFile; fileRef = E8690AEA1D3920C800DBC331 /* pak050-Locales.pak */; }; - E8690AF11D3920C800DBC331 /* pak999-References.pak in Resources */ = {isa = PBXBuildFile; fileRef = E8690AEB1D3920C800DBC331 /* pak999-References.pak */; }; - E8725DAD1DE33B4D003BC987 /* NoiseSampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8725DAB1DE33B4D003BC987 /* NoiseSampler.cpp */; }; - E874834718EACF0300C29033 /* OpenSpades.icns in Resources */ = {isa = PBXBuildFile; fileRef = E874834618EACF0300C29033 /* OpenSpades.icns */; }; - E874834918ED1BE500C29033 /* SDL2_image.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E87AB82418BB3A04006B7D73 /* SDL2_image.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; - E874834A18ED1BE500C29033 /* SDL2.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E8B93AD418559EC600BD01E1 /* SDL2.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; - E88344101E03244F000C3E39 /* FontManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E883440F1E03244F000C3E39 /* FontManager.cpp */; }; - E88F46591DE1B192009E85E5 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8CF03F2178EF916000683D4 /* Cocoa.framework */; }; - E893A3611E3E141D000654A4 /* PackageUpdateManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E893A35F1E3E141D000654A4 /* PackageUpdateManager.cpp */; }; - E893A3631E3E3331000654A4 /* PackageUpdateManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E893A3621E3E3331000654A4 /* PackageUpdateManager.cpp */; }; - E893A3651E3E4181000654A4 /* PackageInfo.json in Resources */ = {isa = PBXBuildFile; fileRef = E893A3641E3E4181000654A4 /* PackageInfo.json */; }; - E89A5F1E1DF8732200857F65 /* ShellApi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89A5F1C1DF8732200857F65 /* ShellApi.cpp */; }; - E89A5F201DF8759200857F65 /* ShellApi.mm in Sources */ = {isa = PBXBuildFile; fileRef = E89A5F1F1DF8759200857F65 /* ShellApi.mm */; }; - E89BBDC31B3559CD00F53EE9 /* GLAutoExposureFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E89BBDC01B3559CD00F53EE9 /* GLAutoExposureFilter.cpp */; }; - E8A2EBA01F5BE16D00E39CD9 /* GameProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8A2EB9E1F5BE16D00E39CD9 /* GameProperties.cpp */; }; - E8C7D7AE22DA34F500F78763 /* ConsoleHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7AB22DA34F400F78763 /* ConsoleHelper.cpp */; }; - E8C7D7AF22DA34F500F78763 /* ConsoleScreen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7AC22DA34F400F78763 /* ConsoleScreen.cpp */; }; - E8C7D7B122DA35F000F78763 /* ConsoleHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7B022DA35F000F78763 /* ConsoleHelper.cpp */; }; - E8C7D7B422DAF5B500F78763 /* ConsoleCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7B322DAF5B400F78763 /* ConsoleCommand.cpp */; }; - E8C7D7BA22DB220300F78763 /* ConfigConsoleResponder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7B822DB220200F78763 /* ConfigConsoleResponder.cpp */; }; - E8C7D7BE22DB2A4400F78763 /* ConsoleCommandCandidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7BD22DB2A4400F78763 /* ConsoleCommandCandidate.cpp */; }; - E8C7D7C022DB3AE000F78763 /* ConsoleCommandCandidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7BF22DB3AE000F78763 /* ConsoleCommandCandidate.cpp */; }; - E8C7D7C222DB636000F78763 /* Client_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8C7D7C122DB635F00F78763 /* Client_Console.cpp */; }; - E8CB47CE1DE071CA00BF606A /* SWUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CB47CC1DE071CA00BF606A /* SWUtils.cpp */; }; - E8CB47D21DE07CF000BF606A /* SettingSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CB47CF1DE07CF000BF606A /* SettingSet.cpp */; }; - E8CB47D61DE084AB00BF606A /* GLSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8CB47D41DE084AB00BF606A /* GLSettings.cpp */; }; - E8D0E5D318F321E300DE3BDB /* GLNonlinearizeFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8D0E5D018F3215000DE3BDB /* GLNonlinearizeFilter.cpp */; }; - E8EF8B571E1D70D900E0829C /* SplashWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8EF8B551E1D70D900E0829C /* SplashWindow.cpp */; }; - E8F6E6E71DCF503500FE76BB /* MumbleLink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8F6E6E41DCF503200FE76BB /* MumbleLink.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - E874834818ED1BDD00C29033 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - E874834918ED1BE500C29033 /* SDL2_image.framework in CopyFiles */, - E874834A18ED1BE500C29033 /* SDL2.framework in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - E80950081E17F66500AECDF2 /* GLSSAOFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLSSAOFilter.cpp; sourceTree = ""; }; - E80950091E17F66500AECDF2 /* GLSSAOFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLSSAOFilter.h; sourceTree = ""; }; - E80B286017A2462D0056179E /* GLShadowMapShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLShadowMapShader.cpp; sourceTree = ""; }; - E80B286117A2462D0056179E /* GLShadowMapShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLShadowMapShader.h; sourceTree = ""; }; - E80B286317A24AED0056179E /* GLBasicShadowMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLBasicShadowMapRenderer.cpp; sourceTree = ""; }; - E80B286417A24AED0056179E /* GLBasicShadowMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLBasicShadowMapRenderer.h; sourceTree = ""; }; - E80B286C17A3B0570056179E /* ConcurrentDispatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConcurrentDispatch.cpp; sourceTree = ""; }; - E80B286D17A3B0570056179E /* ConcurrentDispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentDispatch.h; sourceTree = ""; }; - E80B286F17A4CA2B0056179E /* GLOptimizedVoxelModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLOptimizedVoxelModel.cpp; sourceTree = ""; }; - E80B287017A4CA2C0056179E /* GLOptimizedVoxelModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLOptimizedVoxelModel.h; sourceTree = ""; }; - E80B288617A52AB60056179E /* BitmapAtlasGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitmapAtlasGenerator.cpp; sourceTree = ""; }; - E80B288717A52AB70056179E /* BitmapAtlasGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitmapAtlasGenerator.h; sourceTree = ""; }; - E80B288A17A52CBB0056179E /* binpack2d.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = binpack2d.hpp; sourceTree = ""; }; - E80B288B17A5FFB30056179E /* ThreadLocalStorage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadLocalStorage.cpp; sourceTree = ""; }; - E80B288C17A5FFB40056179E /* ThreadLocalStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocalStorage.h; sourceTree = ""; }; - E80B289417A9D6B40056179E /* GLDynamicLight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLDynamicLight.cpp; sourceTree = ""; }; - E80B289517A9D6B50056179E /* GLDynamicLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLDynamicLight.h; sourceTree = ""; }; - E80B289717AA63FC0056179E /* GLWaterRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLWaterRenderer.cpp; sourceTree = ""; }; - E80B289817AA63FF0056179E /* GLWaterRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLWaterRenderer.h; sourceTree = ""; }; - E80B28B217ABAC790056179E /* .hg_archival.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .hg_archival.txt; sourceTree = ""; }; - E80B28B317ABAC790056179E /* .hgignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .hgignore; sourceTree = ""; }; - E80B28B417ABAC790056179E /* .hgtags */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .hgtags; sourceTree = ""; }; - E80B28B517ABAC790056179E /* _kiss_fft_guts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _kiss_fft_guts.h; sourceTree = ""; }; - E80B28B617ABAC790056179E /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = ""; }; - E80B28B717ABAC790056179E /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = ""; }; - E80B28B817ABAC790056179E /* kiss_fft.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kiss_fft.c; sourceTree = ""; }; - E80B28B917ABAC790056179E /* kiss_fft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kiss_fft.h; sourceTree = ""; }; - E80B28BA17ABAC790056179E /* kissfft.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = kissfft.hh; sourceTree = ""; }; - E80B28BB17ABAC790056179E /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; - E80B28BC17ABAC790056179E /* README.simd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.simd; sourceTree = ""; }; - E80B28BF17AE7FEB0056179E /* GLAmbientShadowRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLAmbientShadowRenderer.cpp; sourceTree = ""; }; - E80B28C017AE7FEE0056179E /* GLAmbientShadowRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLAmbientShadowRenderer.h; sourceTree = ""; }; - E80B28CB17AFCCC40056179E /* PaletteView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaletteView.cpp; sourceTree = ""; }; - E80B28CC17AFCCC70056179E /* PaletteView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PaletteView.h; sourceTree = ""; }; - E80B28CE17AFE68A0056179E /* TCGameMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCGameMode.cpp; sourceTree = ""; }; - E80B28CF17AFE68A0056179E /* TCGameMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCGameMode.h; sourceTree = ""; }; - E80B28D117AFF77B0056179E /* TCProgressView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCProgressView.cpp; sourceTree = ""; }; - E80B28D217AFF77E0056179E /* TCProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCProgressView.h; sourceTree = ""; }; - E80B28D617B39D160056179E /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; }; - E80B28D717B39D160056179E /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; - E80B28D817B39D160056179E /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = ""; }; - E80B28D917B39D160056179E /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; }; - E80B28DC17B39EEE0056179E /* ZipFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZipFileSystem.cpp; sourceTree = ""; }; - E80B28DD17B39EEF0056179E /* ZipFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipFileSystem.h; sourceTree = ""; }; - E80B28DF17B4FDD40056179E /* DynamicMemoryStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicMemoryStream.cpp; sourceTree = ""; }; - E80B28E017B4FDD70056179E /* DynamicMemoryStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicMemoryStream.h; sourceTree = ""; }; - E810122F1E1D7301009955D3 /* Icon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Icon.cpp; sourceTree = ""; }; - E81012301E1D7301009955D3 /* Icon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Icon.h; sourceTree = ""; }; - E81A7C6218610AA900BF3FCE /* SWRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWRenderer.cpp; sourceTree = ""; }; - E81A7C6318610AA900BF3FCE /* SWRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWRenderer.h; sourceTree = ""; }; - E81A7C6518610BE400BF3FCE /* SWPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWPort.cpp; sourceTree = ""; }; - E81A7C6618610BE400BF3FCE /* SWPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWPort.h; sourceTree = ""; }; - E81A7C691861525D00BF3FCE /* SWImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWImage.cpp; sourceTree = ""; }; - E81A7C6A1861525D00BF3FCE /* SWImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWImage.h; sourceTree = ""; }; - E81A7C6C186152A400BF3FCE /* SWModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWModel.cpp; sourceTree = ""; }; - E81A7C6D186152A400BF3FCE /* SWModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWModel.h; sourceTree = ""; }; - E81A7C6F1861F4E200BF3FCE /* SWImageRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWImageRenderer.cpp; sourceTree = ""; }; - E81A7C701861F4E200BF3FCE /* SWImageRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWImageRenderer.h; sourceTree = ""; }; - E81A7C721863562A00BF3FCE /* SWFeatureLevel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SWFeatureLevel.h; sourceTree = ""; }; - E81A7C731863566200BF3FCE /* SWFeatureLevel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWFeatureLevel.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - E81A7C751864171100BF3FCE /* SWMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWMapRenderer.cpp; sourceTree = ""; }; - E81A7C761864171100BF3FCE /* SWMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWMapRenderer.h; sourceTree = ""; }; - E81A7C7818642BCA00BF3FCE /* SWFlatMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWFlatMapRenderer.cpp; sourceTree = ""; }; - E81A7C7918642BCA00BF3FCE /* SWFlatMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWFlatMapRenderer.h; sourceTree = ""; }; - E81A7C7B1865A2E900BF3FCE /* MiniHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MiniHeap.cpp; sourceTree = ""; }; - E81A7C7C1865A2E900BF3FCE /* MiniHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MiniHeap.h; sourceTree = ""; }; - E81CE4A4183F7A3000F22685 /* IFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IFont.cpp; sourceTree = ""; }; - E81CE4A7183F7F2000F22685 /* MainScreen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainScreen.cpp; sourceTree = ""; }; - E81CE4A8183F7F2000F22685 /* MainScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainScreen.h; sourceTree = ""; }; - E82E66B218E9A35C004DBA18 /* Client_FPSCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_FPSCounter.cpp; sourceTree = ""; }; - E82E66B918EA78F5004DBA18 /* OpenSpades.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenSpades.app; sourceTree = BUILT_PRODUCTS_DIR; }; - E82E67F318EA7EAB004DBA18 /* font-unifont.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "font-unifont.pak"; path = "Resources/font-unifont.pak"; sourceTree = ""; }; - E82E680318EA7F60004DBA18 /* libysrspades.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libysrspades.dylib; path = lib/libysrspades.dylib; sourceTree = ""; }; - E82E680618EA9502004DBA18 /* XSpades.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = XSpades.entitlements; path = XSpades/XSpades.entitlements; sourceTree = ""; }; - E831D8661FD65BD5003C0D97 /* ClientCameraMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClientCameraMode.h; sourceTree = ""; }; - E834F54E17942C43004EBE88 /* Grenade.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Grenade.cpp; sourceTree = ""; }; - E834F54F17942C43004EBE88 /* Grenade.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Grenade.h; sourceTree = ""; }; - E834F55117944778004EBE88 /* NetClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetClient.cpp; sourceTree = ""; }; - E834F55217944779004EBE88 /* NetClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetClient.h; sourceTree = ""; }; - E834F5541794BBD4004EBE88 /* Debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Debug.cpp; sourceTree = ""; }; - E834F5551794BBD4004EBE88 /* Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Debug.h; sourceTree = ""; }; - E834F5571794DCF9004EBE88 /* IGameMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IGameMode.cpp; sourceTree = ""; }; - E834F5581794DCFB004EBE88 /* IGameMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGameMode.h; sourceTree = ""; }; - E834F55A1794DDA2004EBE88 /* CTFGameMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CTFGameMode.cpp; sourceTree = ""; }; - E834F55B1794DDA4004EBE88 /* CTFGameMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CTFGameMode.h; sourceTree = ""; }; - E834F55D17950E41004EBE88 /* DeflateStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeflateStream.cpp; sourceTree = ""; }; - E834F55E17950E42004EBE88 /* DeflateStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeflateStream.h; sourceTree = ""; }; - E834F56317951B1A004EBE88 /* MemoryStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStream.cpp; sourceTree = ""; }; - E834F56417951B1B004EBE88 /* MemoryStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStream.h; sourceTree = ""; }; - E834F56617979F55004EBE88 /* Quake3Font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Quake3Font.cpp; sourceTree = ""; }; - E834F56717979F57004EBE88 /* Quake3Font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Quake3Font.h; sourceTree = ""; }; - E834F56917979FD3004EBE88 /* IFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IFont.cpp; sourceTree = ""; }; - E834F56A17979FD5004EBE88 /* IFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IFont.h; sourceTree = ""; }; - E834F56C1797AA2C004EBE88 /* FontData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontData.h; sourceTree = ""; }; - E834F56D1797D92F004EBE88 /* ChatWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChatWindow.cpp; sourceTree = ""; }; - E834F56E1797D932004EBE88 /* ChatWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChatWindow.h; sourceTree = ""; }; - E83668AD1E05757B00977A63 /* OpusAudioStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpusAudioStream.cpp; sourceTree = ""; }; - E83668AE1E05757B00977A63 /* OpusAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpusAudioStream.h; sourceTree = ""; }; - E83668B01E05844E00977A63 /* AudioStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioStream.cpp; sourceTree = ""; }; - E83668B11E05844E00977A63 /* AudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioStream.h; sourceTree = ""; }; - E838D41D18AC726B00EE3C53 /* Strings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Strings.cpp; sourceTree = ""; }; - E838D41E18AC726B00EE3C53 /* Strings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Strings.h; sourceTree = ""; }; - E838D42018ADDE2800EE3C53 /* StringsScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringsScript.cpp; sourceTree = ""; }; - E8403CA6229061BE00093C3E /* RandomAccessAdaptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RandomAccessAdaptor.cpp; sourceTree = ""; }; - E8403CA7229061BE00093C3E /* RandomAccessAdaptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomAccessAdaptor.h; sourceTree = ""; }; - E8403CA9229123CF00093C3E /* PipeStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipeStream.cpp; sourceTree = ""; }; - E8403CAA229123CF00093C3E /* PipeStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PipeStream.h; sourceTree = ""; }; - E8403CAC2291280700093C3E /* GameMapLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameMapLoader.h; sourceTree = ""; }; - E8403CAD2291280700093C3E /* GameMapLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameMapLoader.cpp; sourceTree = ""; }; - E8403CAF2299073400093C3E /* VoxelModelLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VoxelModelLoader.h; sourceTree = ""; }; - E8403CB02299073400093C3E /* VoxelModelLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VoxelModelLoader.cpp; sourceTree = ""; }; - E842888918A3CF6C0060743D /* StartupScreen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StartupScreen.cpp; sourceTree = ""; }; - E842888A18A3CF6C0060743D /* StartupScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StartupScreen.h; sourceTree = ""; }; - E842888C18A3D1520060743D /* StartupScreenHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StartupScreenHelper.cpp; sourceTree = ""; }; - E842888D18A3D1520060743D /* StartupScreenHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StartupScreenHelper.h; sourceTree = ""; }; - E842888F18A3D6470060743D /* StartupScreenHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StartupScreenHelper.cpp; sourceTree = ""; }; - E842889118A3D9C40060743D /* NullDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NullDevice.cpp; sourceTree = ""; }; - E842889218A3D9C40060743D /* NullDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullDevice.h; sourceTree = ""; }; - E842889418A667930060743D /* Fonts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Fonts.cpp; sourceTree = ""; }; - E842889518A667930060743D /* Fonts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fonts.h; sourceTree = ""; }; - E842D48B17C0D06300381B49 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; }; - E844886017CFB32B005105D0 /* GLLongSpriteRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLLongSpriteRenderer.cpp; sourceTree = ""; }; - E844886117CFB32B005105D0 /* GLLongSpriteRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLLongSpriteRenderer.h; sourceTree = ""; }; - E844886417D0C43B005105D0 /* Tracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Tracer.cpp; sourceTree = ""; }; - E844886517D0C43B005105D0 /* Tracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tracer.h; sourceTree = ""; }; - E844886717D262C1005105D0 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - E844886D17D2633C005105D0 /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS; sourceTree = ""; }; - E844887017D2633C005105D0 /* autolink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = autolink.h; sourceTree = ""; }; - E844887117D2633C005105D0 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; - E844887217D2633C005105D0 /* features.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = features.h; sourceTree = ""; }; - E844887317D2633C005105D0 /* forwards.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = forwards.h; sourceTree = ""; }; - E844887417D2633C005105D0 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = ""; }; - E844887517D2633C005105D0 /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; - E844887617D2633C005105D0 /* value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = value.h; sourceTree = ""; }; - E844887717D2633C005105D0 /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = ""; }; - E844887817D2633C005105D0 /* json_batchallocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json_batchallocator.h; sourceTree = ""; }; - E844887917D2633C005105D0 /* json_internalarray.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = json_internalarray.inl; sourceTree = ""; }; - E844887A17D2633C005105D0 /* json_internalmap.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = json_internalmap.inl; sourceTree = ""; }; - E844887B17D2633C005105D0 /* json_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_reader.cpp; sourceTree = ""; }; - E844887C17D2633C005105D0 /* json_value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_value.cpp; sourceTree = ""; }; - E844887D17D2633C005105D0 /* json_valueiterator.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = json_valueiterator.inl; sourceTree = ""; }; - E844887E17D2633C005105D0 /* json_writer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = json_writer.cpp; sourceTree = ""; }; - E844887F17D2633C005105D0 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - E844888017D2633C005105D0 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - E844888117D2633C005105D0 /* version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = version; sourceTree = ""; }; - E844888517D26411005105D0 /* OpenSpades.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenSpades.h; sourceTree = SOURCE_ROOT; }; - E844888617D26699005105D0 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; - E844888B17D3A059005105D0 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - E8493DB61A7349030055731A /* Config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = ""; }; - E849654B18E9487300B9706D /* FltkPreferenceImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FltkPreferenceImporter.cpp; sourceTree = ""; }; - E849654C18E9487300B9706D /* FltkPreferenceImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FltkPreferenceImporter.h; sourceTree = ""; }; - E849654E18E94F1200B9706D /* SdlFileStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SdlFileStream.cpp; sourceTree = ""; }; - E849654F18E94F1200B9706D /* SdlFileStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SdlFileStream.h; sourceTree = ""; }; - E84E221318BB449A001282B0 /* FindGLEW2.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindGLEW2.cmake; sourceTree = ""; }; - E84E221418BB449A001282B0 /* FindSDL2.cmake */ = {isa = PBXFileReference; lastKnownFileType = text; path = FindSDL2.cmake; sourceTree = ""; }; - E84E221818BB4BA0001282B0 /* Credits.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = Credits.inc; sourceTree = ""; }; - E85233791839B28C00F40541 /* VersionInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VersionInfo.cpp; sourceTree = ""; }; - E852337A1839B28C00F40541 /* VersionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionInfo.h; sourceTree = ""; }; - E8567E551792B24D009D83E0 /* IAudioChunk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IAudioChunk.cpp; sourceTree = ""; }; - E8567E561792B24D009D83E0 /* IAudioChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAudioChunk.h; sourceTree = ""; }; - E8567E581792BEFC009D83E0 /* ALDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALDevice.cpp; sourceTree = ""; }; - E8567E591792BEFC009D83E0 /* ALDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALDevice.h; sourceTree = ""; }; - E8567E5B1792BFFE009D83E0 /* ALFuncs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALFuncs.h; sourceTree = ""; }; - E8567E5C1792C089009D83E0 /* ALFuncs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALFuncs.cpp; sourceTree = ""; }; - E8567E5E1792C0FF009D83E0 /* DynamicLibrary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLibrary.cpp; sourceTree = ""; }; - E8567E5F1792C0FF009D83E0 /* DynamicLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLibrary.h; sourceTree = ""; }; - E8567E611792CA12009D83E0 /* IAudioStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IAudioStream.cpp; sourceTree = ""; }; - E8567E621792CA12009D83E0 /* IAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAudioStream.h; sourceTree = ""; }; - E8567E641792CCE5009D83E0 /* WavAudioStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WavAudioStream.cpp; sourceTree = ""; }; - E8567E651792CCE5009D83E0 /* WavAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WavAudioStream.h; sourceTree = ""; }; - E8567E6A1792F398009D83E0 /* IWorldListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IWorldListener.cpp; sourceTree = ""; }; - E8567E6B1792F399009D83E0 /* IWorldListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWorldListener.h; sourceTree = ""; }; - E8567E6D1792FEEB009D83E0 /* AL */ = {isa = PBXFileReference; lastKnownFileType = folder; path = AL; sourceTree = ""; }; - E8567E6E1793AA45009D83E0 /* Weapon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Weapon.cpp; sourceTree = ""; }; - E8567E6F1793AA46009D83E0 /* Weapon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Weapon.h; sourceTree = ""; }; - E8567E711793D5AD009D83E0 /* IModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IModel.cpp; sourceTree = ""; }; - E8567E721793D5AD009D83E0 /* IModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IModel.h; sourceTree = ""; }; - E8567E741793D60E009D83E0 /* GLModelManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLModelManager.cpp; sourceTree = ""; }; - E8567E751793D60E009D83E0 /* GLModelManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLModelManager.h; sourceTree = ""; }; - E8567E771793DC37009D83E0 /* VoxelModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VoxelModel.cpp; sourceTree = ""; }; - E8567E781793DC37009D83E0 /* VoxelModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VoxelModel.h; sourceTree = ""; }; - E8567E7A1793E105009D83E0 /* GLModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLModel.cpp; sourceTree = ""; }; - E8567E7B1793E105009D83E0 /* GLModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLModel.h; sourceTree = ""; }; - E8567E7D1793E1B3009D83E0 /* GLVoxelModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLVoxelModel.cpp; sourceTree = ""; }; - E8567E7E1793E1B3009D83E0 /* GLVoxelModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLVoxelModel.h; sourceTree = ""; }; - E859510A17C5DA060012810C /* GLFogFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLFogFilter.cpp; sourceTree = ""; }; - E859510B17C5DA060012810C /* GLFogFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFogFilter.h; sourceTree = ""; }; - E859510D17C61F850012810C /* GLLensFlareFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLLensFlareFilter.cpp; sourceTree = ""; }; - E859510E17C61F850012810C /* GLLensFlareFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLLensFlareFilter.h; sourceTree = ""; }; - E859511017C645000012810C /* GLFXAAFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLFXAAFilter.cpp; sourceTree = ""; }; - E859511117C645000012810C /* GLFXAAFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFXAAFilter.h; sourceTree = ""; }; - E859511317C96B260012810C /* GLProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLProfiler.cpp; sourceTree = ""; }; - E859511417C96B270012810C /* GLProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLProfiler.h; sourceTree = ""; }; - E8626EB51E100EC6003365BF /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfreetype.a; path = lib/libfreetype.a; sourceTree = ""; }; - E8626EB71E100FB2003365BF /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = lib/libogg.a; sourceTree = ""; }; - E8626EB91E101072003365BF /* libopus.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopus.a; path = lib/libopus.a; sourceTree = ""; }; - E8626EBA1E101072003365BF /* libopusfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopusfile.a; path = lib/libopusfile.a; sourceTree = ""; }; - E8626EBD1E1010CA003365BF /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; - E8655AA61DFC0A6E00D5058A /* FTFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FTFont.cpp; sourceTree = ""; }; - E8655AA71DFC0A6E00D5058A /* FTFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FTFont.h; sourceTree = ""; }; - E8655AA91DFC0AAA00D5058A /* TMPUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TMPUtils.h; sourceTree = ""; }; - E867B6E31DD49D7F0093E4E0 /* as_namespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_namespace.h; sourceTree = ""; }; - E8690AE61D3920C800DBC331 /* pak000-Nonfree.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "pak000-Nonfree.pak"; path = "Resources/pak000-Nonfree.pak"; sourceTree = ""; }; - E8690AE71D3920C800DBC331 /* pak002-Base.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "pak002-Base.pak"; path = "Resources/pak002-Base.pak"; sourceTree = ""; }; - E8690AE81D3920C800DBC331 /* pak005-Models.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "pak005-Models.pak"; path = "Resources/pak005-Models.pak"; sourceTree = ""; }; - E8690AE91D3920C800DBC331 /* pak010-BaseSkin.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "pak010-BaseSkin.pak"; path = "Resources/pak010-BaseSkin.pak"; sourceTree = ""; }; - E8690AEA1D3920C800DBC331 /* pak050-Locales.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "pak050-Locales.pak"; path = "Resources/pak050-Locales.pak"; sourceTree = ""; }; - E8690AEB1D3920C800DBC331 /* pak999-References.pak */ = {isa = PBXFileReference; lastKnownFileType = file; name = "pak999-References.pak"; path = "Resources/pak999-References.pak"; sourceTree = ""; }; - E86D20D12171BF9700964257 /* Disposable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Disposable.h; sourceTree = ""; }; - E8725DAB1DE33B4D003BC987 /* NoiseSampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NoiseSampler.cpp; sourceTree = ""; }; - E8725DAC1DE33B4D003BC987 /* NoiseSampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoiseSampler.h; sourceTree = ""; }; - E874834618EACF0300C29033 /* OpenSpades.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = OpenSpades.icns; path = Resources/Icons/OpenSpades.icns; sourceTree = ""; }; - E87AB82118BB3957006B7D73 /* SdlImageReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SdlImageReader.cpp; sourceTree = ""; }; - E87AB82418BB3A04006B7D73 /* SDL2_image.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2_image.framework; path = lib/SDL2_image.framework; sourceTree = ""; }; - E88318A91790EBAA002ABE6D /* GLProgramUniform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLProgramUniform.cpp; sourceTree = ""; }; - E88318AA1790EBAA002ABE6D /* GLProgramUniform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLProgramUniform.h; sourceTree = ""; }; - E88318AC1790EDDF002ABE6D /* GLProgramAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLProgramAttribute.cpp; sourceTree = ""; }; - E88318AD1790EDDF002ABE6D /* GLProgramAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLProgramAttribute.h; sourceTree = ""; }; - E88318AF1790F73F002ABE6D /* GLMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLMapRenderer.cpp; sourceTree = ""; }; - E88318B01790F73F002ABE6D /* GLMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLMapRenderer.h; sourceTree = ""; }; - E88318B217911A73002ABE6D /* GLMapChunk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLMapChunk.cpp; sourceTree = ""; }; - E88318B317911A73002ABE6D /* GLMapChunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLMapChunk.h; sourceTree = ""; }; - E88318D3179172AF002ABE6D /* Bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Bitmap.cpp; sourceTree = ""; }; - E88318D4179172AF002ABE6D /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = ""; }; - E88318D6179176F3002ABE6D /* GLImageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLImageManager.cpp; sourceTree = ""; }; - E88318D7179176F3002ABE6D /* GLImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLImageManager.h; sourceTree = ""; }; - E88318D9179256E4002ABE6D /* Player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Player.cpp; sourceTree = ""; }; - E88318DA179256E5002ABE6D /* Player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Player.h; sourceTree = ""; }; - E88318DC179257F0002ABE6D /* GameMapWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameMapWrapper.cpp; sourceTree = ""; }; - E88318DD179257F0002ABE6D /* GameMapWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameMapWrapper.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - E88318DF17925F2E002ABE6D /* Deque.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Deque.cpp; sourceTree = ""; }; - E88318E017925F2E002ABE6D /* Deque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deque.h; sourceTree = ""; }; - E88318E21792698D002ABE6D /* Stopwatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Stopwatch.cpp; sourceTree = ""; }; - E88318E31792698D002ABE6D /* Stopwatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Stopwatch.h; sourceTree = ""; }; - E88318E517928EAC002ABE6D /* PhysicsConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhysicsConstants.h; sourceTree = ""; }; - E88318E617928F84002ABE6D /* World.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = World.cpp; sourceTree = ""; }; - E88318E717928F85002ABE6D /* World.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = World.h; sourceTree = ""; }; - E88319021792A7CC002ABE6D /* callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = callbacks.c; sourceTree = ""; }; - E88319031792A7CC002ABE6D /* compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = ""; }; - E88319041792A7CC002ABE6D /* host.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = host.c; sourceTree = ""; }; - E88319071792A7CC002ABE6D /* callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = callbacks.h; sourceTree = ""; }; - E88319081792A7CC002ABE6D /* enet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = enet.h; sourceTree = ""; }; - E88319091792A7CC002ABE6D /* list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = ""; }; - E883190A1792A7CC002ABE6D /* protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protocol.h; sourceTree = ""; }; - E883190B1792A7CC002ABE6D /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = ""; }; - E883190C1792A7CC002ABE6D /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; - E883190D1792A7CC002ABE6D /* unix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unix.h; sourceTree = ""; }; - E883190E1792A7CC002ABE6D /* utility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utility.h; sourceTree = ""; }; - E883190F1792A7CC002ABE6D /* win32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = win32.h; sourceTree = ""; }; - E88319101792A7CC002ABE6D /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - E88319111792A7CC002ABE6D /* list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = list.c; sourceTree = ""; }; - E88319121792A7CC002ABE6D /* packet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = packet.c; sourceTree = ""; }; - E88319131792A7CC002ABE6D /* peer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = peer.c; sourceTree = ""; }; - E88319141792A7CC002ABE6D /* protocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protocol.c; sourceTree = ""; }; - E88319151792A7CC002ABE6D /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; - E88319161792A7CC002ABE6D /* unix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unix.c; sourceTree = ""; }; - E88319171792A7CC002ABE6D /* win32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = win32.c; sourceTree = ""; }; - E883440F1E03244F000C3E39 /* FontManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontManager.cpp; sourceTree = ""; }; - E88EB02D185D9DC500565D07 /* YsrDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YsrDevice.cpp; sourceTree = ""; }; - E88EB02E185D9DC500565D07 /* YsrDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YsrDevice.h; sourceTree = ""; }; - E890F30E187046990090AAB8 /* CP437.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CP437.cpp; sourceTree = ""; }; - E890F30F187046990090AAB8 /* CP437.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CP437.h; sourceTree = ""; }; - E893A35F1E3E141D000654A4 /* PackageUpdateManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PackageUpdateManager.cpp; sourceTree = ""; }; - E893A3601E3E141D000654A4 /* PackageUpdateManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PackageUpdateManager.h; sourceTree = ""; }; - E893A3621E3E3331000654A4 /* PackageUpdateManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PackageUpdateManager.cpp; sourceTree = ""; }; - E893A3641E3E4181000654A4 /* PackageInfo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = PackageInfo.json; path = XSpades/PackageInfo.json; sourceTree = ""; }; - E895D65B18D4A10E00F5B9CA /* jpge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jpge.cpp; sourceTree = ""; }; - E895D65C18D4A10E00F5B9CA /* jpge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpge.h; sourceTree = ""; }; - E895D65E18D4A15900F5B9CA /* JpegWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JpegWriter.cpp; sourceTree = ""; }; - E895D66118D614DE00F5B9CA /* pnglite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pnglite.c; sourceTree = ""; }; - E895D66218D614DE00F5B9CA /* pnglite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pnglite.h; sourceTree = ""; }; - E895D66318D614DE00F5B9CA /* PngWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PngWriter.cpp; sourceTree = ""; }; - E89A5F1C1DF8732200857F65 /* ShellApi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShellApi.cpp; sourceTree = ""; }; - E89A5F1D1DF8732200857F65 /* ShellApi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShellApi.h; sourceTree = ""; }; - E89A5F1F1DF8759200857F65 /* ShellApi.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ShellApi.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - E89A648C17A11B4E00FDA893 /* GLModelRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLModelRenderer.cpp; sourceTree = ""; }; - E89A648D17A11B4E00FDA893 /* GLModelRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLModelRenderer.h; sourceTree = ""; }; - E89A648F17A12FF800FDA893 /* GLDynamicLightShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLDynamicLightShader.cpp; sourceTree = ""; }; - E89A649017A12FF800FDA893 /* GLDynamicLightShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLDynamicLightShader.h; sourceTree = ""; }; - E89A649217A1677F00FDA893 /* FallingBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FallingBlock.cpp; sourceTree = ""; }; - E89A649317A1677F00FDA893 /* FallingBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FallingBlock.h; sourceTree = ""; }; - E89A649517A1835900FDA893 /* GunCasing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GunCasing.cpp; sourceTree = ""; }; - E89A649617A1835900FDA893 /* GunCasing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GunCasing.h; sourceTree = ""; }; - E89A649817A2402500FDA893 /* IGLShadowMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IGLShadowMapRenderer.cpp; sourceTree = ""; }; - E89A649917A2402700FDA893 /* IGLShadowMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGLShadowMapRenderer.h; sourceTree = ""; }; - E89BBDC01B3559CD00F53EE9 /* GLAutoExposureFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLAutoExposureFilter.cpp; sourceTree = ""; }; - E89BBDC11B3559CD00F53EE9 /* GLAutoExposureFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLAutoExposureFilter.h; sourceTree = ""; }; - E89E811F179C2C800059C649 /* GLBloomFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLBloomFilter.cpp; sourceTree = ""; }; - E89E8120179C2C800059C649 /* GLBloomFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLBloomFilter.h; sourceTree = ""; }; - E8A2EB9E1F5BE16D00E39CD9 /* GameProperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameProperties.cpp; sourceTree = ""; }; - E8A2EB9F1F5BE16D00E39CD9 /* GameProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameProperties.h; sourceTree = ""; }; - E8B6B63F17DE27B500E35523 /* angelscript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = angelscript.h; sourceTree = ""; }; - E8B6B64117DE27B500E35523 /* as_array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_array.h; sourceTree = ""; }; - E8B6B64217DE27B500E35523 /* as_atomic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_atomic.cpp; sourceTree = ""; }; - E8B6B64317DE27B500E35523 /* as_atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_atomic.h; sourceTree = ""; }; - E8B6B64417DE27B500E35523 /* as_builder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_builder.cpp; sourceTree = ""; }; - E8B6B64517DE27B500E35523 /* as_builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_builder.h; sourceTree = ""; }; - E8B6B64617DE27B500E35523 /* as_bytecode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_bytecode.cpp; sourceTree = ""; }; - E8B6B64717DE27B500E35523 /* as_bytecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_bytecode.h; sourceTree = ""; }; - E8B6B64817DE27B500E35523 /* as_callfunc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc.cpp; sourceTree = ""; }; - E8B6B64917DE27B500E35523 /* as_callfunc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_callfunc.h; sourceTree = ""; }; - E8B6B64A17DE27B500E35523 /* as_callfunc_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_arm.cpp; sourceTree = ""; }; - E8B6B64B17DE27B500E35523 /* as_callfunc_arm_gcc.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = as_callfunc_arm_gcc.S; sourceTree = ""; }; - E8B6B64C17DE27B500E35523 /* as_callfunc_arm_msvc.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = as_callfunc_arm_msvc.asm; sourceTree = ""; }; - E8B6B64D17DE27B500E35523 /* as_callfunc_arm_xcode.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = as_callfunc_arm_xcode.S; sourceTree = ""; }; - E8B6B64E17DE27B500E35523 /* as_callfunc_mips.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_mips.cpp; sourceTree = ""; }; - E8B6B64F17DE27B500E35523 /* as_callfunc_ppc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_ppc.cpp; sourceTree = ""; }; - E8B6B65017DE27B500E35523 /* as_callfunc_ppc_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_ppc_64.cpp; sourceTree = ""; }; - E8B6B65117DE27B500E35523 /* as_callfunc_sh4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_sh4.cpp; sourceTree = ""; }; - E8B6B65217DE27B500E35523 /* as_callfunc_x64_gcc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_x64_gcc.cpp; sourceTree = ""; }; - E8B6B65317DE27B500E35523 /* as_callfunc_x64_mingw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_x64_mingw.cpp; sourceTree = ""; }; - E8B6B65417DE27B500E35523 /* as_callfunc_x64_msvc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_x64_msvc.cpp; sourceTree = ""; }; - E8B6B65517DE27B500E35523 /* as_callfunc_x64_msvc_asm.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; path = as_callfunc_x64_msvc_asm.asm; sourceTree = ""; }; - E8B6B65617DE27B500E35523 /* as_callfunc_x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_x86.cpp; sourceTree = ""; }; - E8B6B65717DE27B500E35523 /* as_callfunc_xenon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_callfunc_xenon.cpp; sourceTree = ""; }; - E8B6B65817DE27B500E35523 /* as_compiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_compiler.cpp; sourceTree = ""; }; - E8B6B65917DE27B500E35523 /* as_compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_compiler.h; sourceTree = ""; }; - E8B6B65A17DE27B500E35523 /* as_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_config.h; sourceTree = ""; }; - E8B6B65B17DE27B500E35523 /* as_configgroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_configgroup.cpp; sourceTree = ""; }; - E8B6B65C17DE27B500E35523 /* as_configgroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_configgroup.h; sourceTree = ""; }; - E8B6B65D17DE27B500E35523 /* as_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_context.cpp; sourceTree = ""; }; - E8B6B65E17DE27B500E35523 /* as_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_context.h; sourceTree = ""; }; - E8B6B65F17DE27B500E35523 /* as_criticalsection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_criticalsection.h; sourceTree = ""; }; - E8B6B66017DE27B500E35523 /* as_datatype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_datatype.cpp; sourceTree = ""; }; - E8B6B66117DE27B500E35523 /* as_datatype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_datatype.h; sourceTree = ""; }; - E8B6B66217DE27B500E35523 /* as_debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_debug.h; sourceTree = ""; }; - E8B6B66317DE27B500E35523 /* as_gc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_gc.cpp; sourceTree = ""; }; - E8B6B66417DE27B500E35523 /* as_gc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_gc.h; sourceTree = ""; }; - E8B6B66517DE27B500E35523 /* as_generic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_generic.cpp; sourceTree = ""; }; - E8B6B66617DE27B500E35523 /* as_generic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_generic.h; sourceTree = ""; }; - E8B6B66717DE27B500E35523 /* as_globalproperty.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_globalproperty.cpp; sourceTree = ""; }; - E8B6B66817DE27B500E35523 /* as_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_map.h; sourceTree = ""; }; - E8B6B66917DE27B500E35523 /* as_memory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_memory.cpp; sourceTree = ""; }; - E8B6B66A17DE27B500E35523 /* as_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_memory.h; sourceTree = ""; }; - E8B6B66B17DE27B500E35523 /* as_module.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_module.cpp; sourceTree = ""; }; - E8B6B66C17DE27B500E35523 /* as_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_module.h; sourceTree = ""; }; - E8B6B66D17DE27B500E35523 /* as_objecttype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_objecttype.cpp; sourceTree = ""; }; - E8B6B66E17DE27B500E35523 /* as_objecttype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_objecttype.h; sourceTree = ""; }; - E8B6B66F17DE27B500E35523 /* as_outputbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_outputbuffer.cpp; sourceTree = ""; }; - E8B6B67017DE27B500E35523 /* as_outputbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_outputbuffer.h; sourceTree = ""; }; - E8B6B67117DE27B500E35523 /* as_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_parser.cpp; sourceTree = ""; }; - E8B6B67217DE27B500E35523 /* as_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_parser.h; sourceTree = ""; }; - E8B6B67317DE27B500E35523 /* as_property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_property.h; sourceTree = ""; }; - E8B6B67417DE27B500E35523 /* as_restore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_restore.cpp; sourceTree = ""; }; - E8B6B67517DE27B500E35523 /* as_restore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_restore.h; sourceTree = ""; }; - E8B6B67617DE27B500E35523 /* as_scriptcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_scriptcode.cpp; sourceTree = ""; }; - E8B6B67717DE27B500E35523 /* as_scriptcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_scriptcode.h; sourceTree = ""; }; - E8B6B67817DE27B500E35523 /* as_scriptengine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_scriptengine.cpp; sourceTree = ""; }; - E8B6B67917DE27B500E35523 /* as_scriptengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_scriptengine.h; sourceTree = ""; }; - E8B6B67A17DE27B500E35523 /* as_scriptfunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_scriptfunction.cpp; sourceTree = ""; }; - E8B6B67B17DE27B500E35523 /* as_scriptfunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_scriptfunction.h; sourceTree = ""; }; - E8B6B67C17DE27B500E35523 /* as_scriptnode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_scriptnode.cpp; sourceTree = ""; }; - E8B6B67D17DE27B500E35523 /* as_scriptnode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_scriptnode.h; sourceTree = ""; }; - E8B6B67E17DE27B500E35523 /* as_scriptobject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_scriptobject.cpp; sourceTree = ""; }; - E8B6B67F17DE27B500E35523 /* as_scriptobject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_scriptobject.h; sourceTree = ""; }; - E8B6B68017DE27B500E35523 /* as_string.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_string.cpp; sourceTree = ""; }; - E8B6B68117DE27B500E35523 /* as_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_string.h; sourceTree = ""; }; - E8B6B68217DE27B500E35523 /* as_string_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_string_util.cpp; sourceTree = ""; }; - E8B6B68317DE27B500E35523 /* as_string_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_string_util.h; sourceTree = ""; }; - E8B6B68417DE27B500E35523 /* as_symboltable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_symboltable.h; sourceTree = ""; }; - E8B6B68517DE27B500E35523 /* as_texts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_texts.h; sourceTree = ""; }; - E8B6B68617DE27B500E35523 /* as_thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_thread.cpp; sourceTree = ""; }; - E8B6B68717DE27B500E35523 /* as_thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_thread.h; sourceTree = ""; }; - E8B6B68817DE27B500E35523 /* as_tokendef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_tokendef.h; sourceTree = ""; }; - E8B6B68917DE27B500E35523 /* as_tokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_tokenizer.cpp; sourceTree = ""; }; - E8B6B68A17DE27B500E35523 /* as_tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_tokenizer.h; sourceTree = ""; }; - E8B6B68B17DE27B500E35523 /* as_typeinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_typeinfo.cpp; sourceTree = ""; }; - E8B6B68C17DE27B500E35523 /* as_typeinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_typeinfo.h; sourceTree = ""; }; - E8B6B68D17DE27B500E35523 /* as_variablescope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = as_variablescope.cpp; sourceTree = ""; }; - E8B6B68E17DE27B500E35523 /* as_variablescope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = as_variablescope.h; sourceTree = ""; }; - E8B6B6BC17DE2F5500E35523 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; - E8B6B6BD17DF456E00E35523 /* GLSparseShadowMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLSparseShadowMapRenderer.cpp; sourceTree = ""; }; - E8B6B6BE17DF456F00E35523 /* GLSparseShadowMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLSparseShadowMapRenderer.h; sourceTree = ""; }; - E8B6B6E317E165A400E35523 /* GLDepthOfFieldFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLDepthOfFieldFilter.cpp; sourceTree = ""; }; - E8B6B6E417E165A500E35523 /* GLDepthOfFieldFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLDepthOfFieldFilter.h; sourceTree = ""; }; - E8B6B6E717E40AF500E35523 /* MathScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathScript.cpp; sourceTree = ""; }; - E8B6B6E817E40AF500E35523 /* ScriptManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptManager.cpp; sourceTree = ""; }; - E8B6B6E917E40AF500E35523 /* ScriptManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptManager.h; sourceTree = ""; }; - E8B6B6EC17E40B5900E35523 /* IImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IImage.cpp; sourceTree = ""; }; - E8B6B6EF17E40DA700E35523 /* RefCountedObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefCountedObject.cpp; sourceTree = ""; }; - E8B6B6F017E40DAA00E35523 /* RefCountedObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedObject.h; sourceTree = ""; }; - E8B6B6F217E40E8200E35523 /* IModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IModel.cpp; sourceTree = ""; }; - E8B6B6F517E40F9900E35523 /* IRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IRenderer.cpp; sourceTree = ""; }; - E8B6B6F817E4130E00E35523 /* GameMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameMap.cpp; sourceTree = ""; }; - E8B6B6FB17E413AB00E35523 /* Bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Bitmap.cpp; sourceTree = ""; }; - E8B6B6FD17E4141000E35523 /* VoxelModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VoxelModel.cpp; sourceTree = ""; }; - E8B6B70017E4193A00E35523 /* scriptany.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptany.cpp; sourceTree = ""; }; - E8B6B70117E4193A00E35523 /* scriptany.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptany.h; sourceTree = ""; }; - E8B6B70217E4193A00E35523 /* scriptarray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptarray.cpp; sourceTree = ""; }; - E8B6B70317E4193A00E35523 /* scriptarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptarray.h; sourceTree = ""; }; - E8B6B70417E4193A00E35523 /* scriptbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptbuilder.cpp; sourceTree = ""; }; - E8B6B70517E4193A00E35523 /* scriptbuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptbuilder.h; sourceTree = ""; }; - E8B6B70617E4193A00E35523 /* scriptdictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptdictionary.cpp; sourceTree = ""; }; - E8B6B70717E4193A00E35523 /* scriptdictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptdictionary.h; sourceTree = ""; }; - E8B6B70817E4193A00E35523 /* scripthandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scripthandle.cpp; sourceTree = ""; }; - E8B6B70917E4193A00E35523 /* scripthandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scripthandle.h; sourceTree = ""; }; - E8B6B70A17E4193A00E35523 /* scripthelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scripthelper.cpp; sourceTree = ""; }; - E8B6B70B17E4193A00E35523 /* scripthelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scripthelper.h; sourceTree = ""; }; - E8B6B70C17E4193A00E35523 /* scriptmath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptmath.cpp; sourceTree = ""; }; - E8B6B70D17E4193A00E35523 /* scriptmath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptmath.h; sourceTree = ""; }; - E8B6B70E17E4193A00E35523 /* scriptmathcomplex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptmathcomplex.cpp; sourceTree = ""; }; - E8B6B70F17E4193A00E35523 /* scriptmathcomplex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptmathcomplex.h; sourceTree = ""; }; - E8B6B71017E4193A00E35523 /* scriptstdstring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptstdstring.cpp; sourceTree = ""; }; - E8B6B71117E4193A00E35523 /* scriptstdstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptstdstring.h; sourceTree = ""; }; - E8B6B71217E4193A00E35523 /* scriptstdstring_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptstdstring_utils.cpp; sourceTree = ""; }; - E8B6B71317E4193A00E35523 /* weakref.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = weakref.cpp; sourceTree = ""; }; - E8B6B71417E4193A00E35523 /* weakref.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = weakref.h; sourceTree = ""; }; - E8B6B72017E4508C00E35523 /* IAudioDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IAudioDevice.cpp; sourceTree = ""; }; - E8B6B72217E452EC00E35523 /* IAudioChunk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IAudioChunk.cpp; sourceTree = ""; }; - E8B6B72417E46C1B00E35523 /* PrimitiveArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrimitiveArray.cpp; sourceTree = ""; }; - E8B6B72617E5AC9C00E35523 /* ServerAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServerAddress.cpp; sourceTree = ""; }; - E8B6B72717E5AC9C00E35523 /* ServerAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerAddress.h; sourceTree = ""; }; - E8B6B72917E6095800E35523 /* GLLensDustFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLLensDustFilter.cpp; sourceTree = ""; }; - E8B6B72A17E6095800E35523 /* GLLensDustFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLLensDustFilter.h; sourceTree = ""; }; - E8B6B72C17E68B1B00E35523 /* GLSoftLitSpriteRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLSoftLitSpriteRenderer.cpp; sourceTree = ""; }; - E8B6B72D17E68B1B00E35523 /* GLSoftLitSpriteRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLSoftLitSpriteRenderer.h; sourceTree = ""; }; - E8B6B72F17E8C4ED00E35523 /* IToolSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IToolSkin.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - E8B6B73117E8CB1800E35523 /* IToolSkin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IToolSkin.h; sourceTree = ""; }; - E8B6B73217E8CE1300E35523 /* ScriptFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptFunction.cpp; sourceTree = ""; }; - E8B6B73317E8CE1700E35523 /* ScriptFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptFunction.h; sourceTree = ""; }; - E8B6B73517E9C70000E35523 /* ClientPlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientPlayer.cpp; sourceTree = ""; }; - E8B6B73617E9C70000E35523 /* ClientPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientPlayer.h; sourceTree = ""; }; - E8B6B73817E9E8CF00E35523 /* ISpadeSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ISpadeSkin.cpp; sourceTree = ""; }; - E8B6B73917E9E8D300E35523 /* ISpadeSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISpadeSkin.h; sourceTree = ""; }; - E8B6B73B17E9F49700E35523 /* IBlockSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IBlockSkin.cpp; sourceTree = ""; }; - E8B6B73C17E9F49C00E35523 /* IBlockSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IBlockSkin.h; sourceTree = ""; }; - E8B6B73E17EA060900E35523 /* IViewToolSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IViewToolSkin.cpp; sourceTree = ""; }; - E8B6B73F17EA060D00E35523 /* IViewToolSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IViewToolSkin.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - E8B6B74117EA0B1500E35523 /* IThirdPersonToolSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IThirdPersonToolSkin.cpp; sourceTree = ""; }; - E8B6B74217EA0B1900E35523 /* IThirdPersonToolSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IThirdPersonToolSkin.h; sourceTree = ""; }; - E8B6B74417EA0F1B00E35523 /* IGrenadeSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IGrenadeSkin.cpp; sourceTree = ""; }; - E8B6B74517EA0F1E00E35523 /* IGrenadeSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGrenadeSkin.h; sourceTree = ""; }; - E8B6B74717EA12E100E35523 /* IWeaponSkin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IWeaponSkin.cpp; sourceTree = ""; }; - E8B6B74817EA12E500E35523 /* IWeaponSkin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWeaponSkin.h; sourceTree = ""; }; - E8B8082718E05B920001013E /* CellToTriangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CellToTriangle.h; sourceTree = ""; }; - E8B93AD418559EC600BD01E1 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = lib/SDL2.framework; sourceTree = ""; }; - E8C7D7AA22DA34F400F78763 /* ConsoleHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleHelper.h; sourceTree = ""; }; - E8C7D7AB22DA34F400F78763 /* ConsoleHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleHelper.cpp; sourceTree = ""; }; - E8C7D7AC22DA34F400F78763 /* ConsoleScreen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleScreen.cpp; sourceTree = ""; }; - E8C7D7AD22DA34F500F78763 /* ConsoleScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleScreen.h; sourceTree = ""; }; - E8C7D7B022DA35F000F78763 /* ConsoleHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleHelper.cpp; sourceTree = ""; }; - E8C7D7B222DAF5B400F78763 /* ConsoleCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleCommand.h; sourceTree = ""; }; - E8C7D7B322DAF5B400F78763 /* ConsoleCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleCommand.cpp; sourceTree = ""; }; - E8C7D7B822DB220200F78763 /* ConfigConsoleResponder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConfigConsoleResponder.cpp; sourceTree = ""; }; - E8C7D7B922DB220300F78763 /* ConfigConsoleResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigConsoleResponder.h; sourceTree = ""; }; - E8C7D7BB22DB263200F78763 /* Iterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Iterator.h; sourceTree = ""; }; - E8C7D7BC22DB2A4400F78763 /* ConsoleCommandCandidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleCommandCandidate.h; sourceTree = ""; }; - E8C7D7BD22DB2A4400F78763 /* ConsoleCommandCandidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleCommandCandidate.cpp; sourceTree = ""; }; - E8C7D7BF22DB3AE000F78763 /* ConsoleCommandCandidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConsoleCommandCandidate.cpp; sourceTree = ""; }; - E8C7D7C122DB635F00F78763 /* Client_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_Console.cpp; sourceTree = ""; }; - E8C92A0A18695EA500740C9F /* SWModelRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWModelRenderer.cpp; sourceTree = ""; }; - E8C92A0B18695EA500740C9F /* SWModelRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWModelRenderer.h; sourceTree = ""; }; - E8C92A0D186A8D3600740C9F /* CpuID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CpuID.h; sourceTree = ""; }; - E8C92A0E186A902500740C9F /* CpuID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CpuID.cpp; sourceTree = ""; }; - E8CB47CC1DE071CA00BF606A /* SWUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SWUtils.cpp; sourceTree = ""; }; - E8CB47CF1DE07CF000BF606A /* SettingSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SettingSet.cpp; sourceTree = ""; }; - E8CB47D01DE07CF000BF606A /* SettingSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingSet.h; sourceTree = ""; }; - E8CB47D31DE0844400BF606A /* GLSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GLSettings.h; sourceTree = ""; }; - E8CB47D41DE084AB00BF606A /* GLSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLSettings.cpp; sourceTree = ""; }; - E8CF039B178EDAC9000683D4 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - E8CF03A6178EDF6A000683D4 /* IRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRenderer.cpp; path = Sources/Client/IRenderer.cpp; sourceTree = SOURCE_ROOT; }; - E8CF03A7178EDF6A000683D4 /* IRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRenderer.h; path = Sources/Client/IRenderer.h; sourceTree = SOURCE_ROOT; }; - E8CF03A9178EDF74000683D4 /* GLRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GLRenderer.cpp; path = Sources/Draw/GLRenderer.cpp; sourceTree = SOURCE_ROOT; }; - E8CF03AA178EDF74000683D4 /* GLRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLRenderer.h; path = Sources/Draw/GLRenderer.h; sourceTree = SOURCE_ROOT; }; - E8CF03AC178EDFCD000683D4 /* IGLDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IGLDevice.cpp; sourceTree = ""; }; - E8CF03AD178EDFCD000683D4 /* IGLDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGLDevice.h; sourceTree = ""; }; - E8CF03B0178EE300000683D4 /* Thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Thread.cpp; sourceTree = ""; }; - E8CF03B1178EE300000683D4 /* Thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Thread.h; sourceTree = ""; }; - E8CF03B4178EE39A000683D4 /* SDL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL.h; sourceTree = ""; }; - E8CF03BB178EE502000683D4 /* SDLGLDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDLGLDevice.cpp; sourceTree = ""; }; - E8CF03BC178EE502000683D4 /* SDLGLDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLGLDevice.h; sourceTree = ""; }; - E8CF03BE178EE50E000683D4 /* Main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Main.cpp; sourceTree = ""; }; - E8CF03C0178EE5B6000683D4 /* OpenGL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenGL.h; sourceTree = ""; }; - E8CF03C1178EE6D8000683D4 /* Client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client.cpp; sourceTree = ""; }; - E8CF03C2178EE6D8000683D4 /* Client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Client.h; sourceTree = ""; }; - E8CF03C4178EE78C000683D4 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; - E8CF03C6178EE81A000683D4 /* IAudioDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IAudioDevice.cpp; sourceTree = ""; }; - E8CF03C7178EE81A000683D4 /* IAudioDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IAudioDevice.h; sourceTree = ""; }; - E8CF03C9178EE869000683D4 /* IInputInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IInputInterface.cpp; sourceTree = ""; }; - E8CF03CA178EE869000683D4 /* IInputInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IInputInterface.h; sourceTree = ""; }; - E8CF03CC178EE95F000683D4 /* Math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Math.cpp; sourceTree = ""; }; - E8CF03CD178EE95F000683D4 /* Math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Math.h; sourceTree = ""; }; - E8CF03CF178EEF80000683D4 /* Semaphore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Semaphore.cpp; sourceTree = ""; }; - E8CF03D0178EEF80000683D4 /* Semaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Semaphore.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - E8CF03D5178EF09C000683D4 /* ILockable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ILockable.cpp; sourceTree = ""; }; - E8CF03D6178EF09C000683D4 /* ILockable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ILockable.h; sourceTree = ""; }; - E8CF03DE178EF4E9000683D4 /* IRunnable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IRunnable.cpp; sourceTree = ""; }; - E8CF03DF178EF4E9000683D4 /* IRunnable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRunnable.h; sourceTree = ""; }; - E8CF03E1178EF57E000683D4 /* SDLRunner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SDLRunner.cpp; sourceTree = ""; }; - E8CF03E2178EF57E000683D4 /* SDLRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLRunner.h; sourceTree = ""; }; - E8CF03F2178EF916000683D4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; - E8CF03F4178FAA8B000683D4 /* IImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IImage.cpp; sourceTree = ""; }; - E8CF03F5178FAA8B000683D4 /* IImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IImage.h; sourceTree = ""; }; - E8CF03F7178FABA4000683D4 /* SceneDefinition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneDefinition.cpp; sourceTree = ""; }; - E8CF03F8178FABA4000683D4 /* SceneDefinition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneDefinition.h; sourceTree = ""; }; - E8CF03FA178FACFF000683D4 /* GameMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameMap.cpp; sourceTree = ""; }; - E8CF03FB178FACFF000683D4 /* GameMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameMap.h; sourceTree = ""; }; - E8CF03FD178FB1E1000683D4 /* IGameMapListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IGameMapListener.cpp; sourceTree = ""; }; - E8CF03FE178FB1E1000683D4 /* IGameMapListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGameMapListener.h; sourceTree = ""; }; - E8CF0400178FB52F000683D4 /* GLImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLImage.cpp; sourceTree = ""; }; - E8CF0401178FB52F000683D4 /* GLImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLImage.h; sourceTree = ""; }; - E8CF0403178FF776000683D4 /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = ""; }; - E8CF0404178FF776000683D4 /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = ""; }; - E8CF04061790455B000683D4 /* GLProgram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLProgram.cpp; sourceTree = ""; }; - E8CF04071790455B000683D4 /* GLProgram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLProgram.h; sourceTree = ""; }; - E8CF04091790471D000683D4 /* IFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IFileSystem.cpp; sourceTree = ""; }; - E8CF040A1790471D000683D4 /* IFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IFileSystem.h; sourceTree = ""; }; - E8CF040C17904970000683D4 /* FileManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileManager.cpp; sourceTree = ""; }; - E8CF040D17904971000683D4 /* FileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileManager.h; sourceTree = ""; }; - E8CF040F17904ABC000683D4 /* IStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IStream.cpp; sourceTree = ""; }; - E8CF041017904ABC000683D4 /* IStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IStream.h; sourceTree = ""; }; - E8CF041217904E8B000683D4 /* StdStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdStream.cpp; sourceTree = ""; }; - E8CF041317904E8C000683D4 /* StdStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdStream.h; sourceTree = ""; }; - E8CF0415179052F6000683D4 /* DirectoryFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectoryFileSystem.cpp; sourceTree = ""; }; - E8CF0416179052F7000683D4 /* DirectoryFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryFileSystem.h; sourceTree = ""; }; - E8CF041817905609000683D4 /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Resources; sourceTree = ""; }; - E8CF04191790CCAB000683D4 /* GLShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLShader.cpp; sourceTree = ""; }; - E8CF041A1790CCAB000683D4 /* GLShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLShader.h; sourceTree = ""; }; - E8CF041C1790D6D5000683D4 /* GLProgramManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLProgramManager.cpp; sourceTree = ""; }; - E8CF041D1790D6D5000683D4 /* GLProgramManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLProgramManager.h; sourceTree = ""; }; - E8D0E5D018F3215000DE3BDB /* GLNonlinearizeFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLNonlinearizeFilter.cpp; sourceTree = ""; }; - E8D0E5D118F3215000DE3BDB /* GLNonlinearizeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLNonlinearizeFilter.h; sourceTree = ""; }; - E8D2ACE117D704E600BE5490 /* GLColorCorrectionFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLColorCorrectionFilter.cpp; sourceTree = ""; }; - E8D2ACE217D704E600BE5490 /* GLColorCorrectionFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLColorCorrectionFilter.h; sourceTree = ""; }; - E8D88AAF179C3004004C2451 /* GLQuadRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLQuadRenderer.cpp; sourceTree = ""; }; - E8D88AB0179C3004004C2451 /* GLQuadRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLQuadRenderer.h; sourceTree = ""; }; - E8D88AB2179C45B7004C2451 /* GLLensFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLLensFilter.cpp; sourceTree = ""; }; - E8D88AB3179C45B7004C2451 /* GLLensFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLLensFilter.h; sourceTree = ""; }; - E8E0AF881798278000C6B5A9 /* GLImageRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLImageRenderer.cpp; sourceTree = ""; }; - E8E0AF891798278000C6B5A9 /* GLImageRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLImageRenderer.h; sourceTree = ""; }; - E8E0AF92179942DB00C6B5A9 /* Corpse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Corpse.cpp; sourceTree = ""; }; - E8E0AF93179942DB00C6B5A9 /* Corpse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Corpse.h; sourceTree = ""; }; - E8E0AF95179980F500C6B5A9 /* CenterMessageView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CenterMessageView.cpp; sourceTree = ""; }; - E8E0AF96179980F500C6B5A9 /* CenterMessageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CenterMessageView.h; sourceTree = ""; }; - E8E0AF98179996A100C6B5A9 /* HurtRingView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HurtRingView.cpp; sourceTree = ""; }; - E8E0AF99179996A100C6B5A9 /* HurtRingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HurtRingView.h; sourceTree = ""; }; - E8E0AF9B179A5BC200C6B5A9 /* GLFlatMapRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLFlatMapRenderer.cpp; sourceTree = ""; }; - E8E0AF9C179A5BC200C6B5A9 /* GLFlatMapRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFlatMapRenderer.h; sourceTree = ""; }; - E8E0AF9E179A698800C6B5A9 /* MapView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MapView.cpp; sourceTree = ""; }; - E8E0AF9F179A698800C6B5A9 /* MapView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapView.h; sourceTree = ""; }; - E8E0AFA1179A8F1000C6B5A9 /* ScoreboardView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScoreboardView.cpp; sourceTree = ""; }; - E8E0AFA2179A8F1000C6B5A9 /* ScoreboardView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScoreboardView.h; sourceTree = ""; }; - E8E0AFA4179AA31B00C6B5A9 /* LimboView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LimboView.cpp; sourceTree = ""; }; - E8E0AFA5179AA31C00C6B5A9 /* LimboView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LimboView.h; sourceTree = ""; }; - E8E0AFA7179ACDDD00C6B5A9 /* GLSpriteRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLSpriteRenderer.cpp; sourceTree = ""; }; - E8E0AFA8179ACDDD00C6B5A9 /* GLSpriteRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLSpriteRenderer.h; sourceTree = ""; }; - E8E0AFAA179ADC2100C6B5A9 /* ILocalEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ILocalEntity.cpp; sourceTree = ""; }; - E8E0AFAB179ADC2100C6B5A9 /* ILocalEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ILocalEntity.h; sourceTree = ""; }; - E8E0AFAD179ADDCB00C6B5A9 /* ParticleSpriteEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSpriteEntity.cpp; sourceTree = ""; }; - E8E0AFAE179ADDCB00C6B5A9 /* ParticleSpriteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSpriteEntity.h; sourceTree = ""; }; - E8E0AFB0179AF4E600C6B5A9 /* SmokeSpriteEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmokeSpriteEntity.cpp; sourceTree = ""; }; - E8E0AFB1179AF4E600C6B5A9 /* SmokeSpriteEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmokeSpriteEntity.h; sourceTree = ""; }; - E8E0AFB3179BF25B00C6B5A9 /* Settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Settings.cpp; sourceTree = ""; }; - E8E0AFB4179BF25B00C6B5A9 /* Settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Settings.h; sourceTree = ""; }; - E8E0AFB6179C0F2800C6B5A9 /* GLFramebufferManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLFramebufferManager.cpp; sourceTree = ""; }; - E8E0AFB7179C0F2800C6B5A9 /* GLFramebufferManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLFramebufferManager.h; sourceTree = ""; }; - E8E44684179CC4FF00BE8855 /* IBitmapCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IBitmapCodec.cpp; sourceTree = ""; }; - E8E44685179CC4FF00BE8855 /* IBitmapCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IBitmapCodec.h; sourceTree = ""; }; - E8E44687179CC65900BE8855 /* TargaReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TargaReader.cpp; sourceTree = ""; }; - E8E44696179D2CA100BE8855 /* IGLSpriteRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IGLSpriteRenderer.cpp; sourceTree = ""; }; - E8E44697179D2CA100BE8855 /* IGLSpriteRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IGLSpriteRenderer.h; sourceTree = ""; }; - E8E44699179D2EDC00BE8855 /* GLSoftSpriteRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLSoftSpriteRenderer.cpp; sourceTree = ""; }; - E8E4469A179D2EDC00BE8855 /* GLSoftSpriteRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLSoftSpriteRenderer.h; sourceTree = ""; }; - E8E4469C179D59A900BE8855 /* GLCameraBlurFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLCameraBlurFilter.cpp; sourceTree = ""; }; - E8E4469D179D59A900BE8855 /* GLCameraBlurFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLCameraBlurFilter.h; sourceTree = ""; }; - E8E446A2179EA60900BE8855 /* GLMapShadowRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLMapShadowRenderer.cpp; sourceTree = ""; }; - E8E446A3179EA60900BE8855 /* GLMapShadowRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLMapShadowRenderer.h; sourceTree = ""; }; - E8E446A5179EAC7800BE8855 /* GLShadowShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLShadowShader.cpp; sourceTree = ""; }; - E8E446A6179EAC7800BE8855 /* GLShadowShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLShadowShader.h; sourceTree = ""; }; - E8E446A8179F822D00BE8855 /* TargaWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TargaWriter.cpp; sourceTree = ""; }; - E8EE089F17B8F4B000631987 /* GLRadiosityRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GLRadiosityRenderer.cpp; sourceTree = ""; }; - E8EE08A017B8F4B000631987 /* GLRadiosityRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLRadiosityRenderer.h; sourceTree = ""; }; - E8EE08A217BA016F00631987 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; path = AUTHORS; sourceTree = ""; }; - E8EF8B551E1D70D900E0829C /* SplashWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SplashWindow.cpp; sourceTree = ""; }; - E8EF8B561E1D70D900E0829C /* SplashWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SplashWindow.h; sourceTree = ""; }; - E8F6E6E41DCF503200FE76BB /* MumbleLink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MumbleLink.cpp; sourceTree = ""; }; - E8F6E6E51DCF503200FE76BB /* MumbleLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MumbleLink.h; sourceTree = ""; }; - E8F74CE3183F86AE0085AA54 /* View.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = View.cpp; sourceTree = ""; }; - E8F74CE4183F86AE0085AA54 /* View.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = View.h; sourceTree = ""; }; - E8F74CE6183F8A110085AA54 /* Main.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Main.h; sourceTree = ""; }; - E8F74CE7183F8B9D0085AA54 /* Runner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Runner.cpp; sourceTree = ""; }; - E8F74CE8183F8B9D0085AA54 /* Runner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Runner.h; sourceTree = ""; }; - E8F74CEA183F92DA0085AA54 /* SDLmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLmain.m; sourceTree = ""; }; - E8F74CEC183F931F0085AA54 /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLMain.h; sourceTree = ""; }; - E8F74CED183FBA9C0085AA54 /* MainScreenHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainScreenHelper.cpp; sourceTree = ""; }; - E8F74CEE183FBA9C0085AA54 /* MainScreenHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainScreenHelper.h; sourceTree = ""; }; - E8F74CF0183FBB070085AA54 /* MainScreenHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainScreenHelper.cpp; sourceTree = ""; }; - E8F74CF31840D4CC0085AA54 /* Config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Config.cpp; sourceTree = ""; }; - E8F74CF61845C5000085AA54 /* ClientUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientUI.cpp; sourceTree = ""; }; - E8F74CF71845C5000085AA54 /* ClientUI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientUI.h; sourceTree = ""; }; - E8F74CF91845C64B0085AA54 /* ClientUIHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientUIHelper.cpp; sourceTree = ""; }; - E8F74CFA1845C64B0085AA54 /* ClientUIHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientUIHelper.h; sourceTree = ""; }; - E8F74CFC1845C8D50085AA54 /* ClientUIHelper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ClientUIHelper.cpp; sourceTree = ""; }; - E8F74CFE184C753F0085AA54 /* Clipboard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Clipboard.cpp; sourceTree = ""; }; - E8FC02D8186829BC00F84A0D /* SWUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SWUtils.h; sourceTree = ""; }; - E8FE748818CB329C00291338 /* HitTestDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HitTestDebugger.cpp; sourceTree = ""; }; - E8FE748918CB329C00291338 /* HitTestDebugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HitTestDebugger.h; sourceTree = ""; }; - E8FE748B18CC6AA100291338 /* Client_Input.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Client_Input.cpp; sourceTree = ""; }; - E8FE748D18CC6C2B00291338 /* Client_Update.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_Update.cpp; sourceTree = ""; }; - E8FE748F18CC6CE000291338 /* Client_NetHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_NetHandler.cpp; sourceTree = ""; }; - E8FE749118CC6E4900291338 /* Client_LocalEnts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_LocalEnts.cpp; sourceTree = ""; }; - E8FE749318CC6EB500291338 /* Client_Draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_Draw.cpp; sourceTree = ""; }; - E8FE749518CC6F2900291338 /* Client_Scene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Client_Scene.cpp; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - E82E66B618EA78F5004DBA18 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - E8626EBE1E1010CA003365BF /* libbz2.tbd in Frameworks */, - E8626EBC1E101072003365BF /* libopusfile.a in Frameworks */, - E8626EAE1E1009D7003365BF /* libcurl.tbd in Frameworks */, - E82E67E218EA7A1E004DBA18 /* libz.tbd in Frameworks */, - E8626EBB1E101072003365BF /* libopus.a in Frameworks */, - E8626EB81E100FB2003365BF /* libogg.a in Frameworks */, - E8626EB61E100EC6003365BF /* libfreetype.a in Frameworks */, - E88F46591DE1B192009E85E5 /* Cocoa.framework in Frameworks */, - E82E67F018EA7A60004DBA18 /* OpenGL.framework in Frameworks */, - E82E67DF18EA7A05004DBA18 /* SDL2_image.framework in Frameworks */, - E82E67E018EA7A05004DBA18 /* SDL2.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - E80B288917A52CB70056179E /* binpack2d */ = { - isa = PBXGroup; - children = ( - E80B288A17A52CBB0056179E /* binpack2d.hpp */, - ); - name = binpack2d; - path = Sources/binpack2d; - sourceTree = ""; - }; - E80B28B117ABAC6C0056179E /* kiss_fft130 */ = { - isa = PBXGroup; - children = ( - E80B28B217ABAC790056179E /* .hg_archival.txt */, - E80B28B317ABAC790056179E /* .hgignore */, - E80B28B417ABAC790056179E /* .hgtags */, - E80B28B517ABAC790056179E /* _kiss_fft_guts.h */, - E80B28B617ABAC790056179E /* CHANGELOG */, - E80B28B717ABAC790056179E /* COPYING */, - E80B28B817ABAC790056179E /* kiss_fft.c */, - E80B28B917ABAC790056179E /* kiss_fft.h */, - E80B28BA17ABAC790056179E /* kissfft.hh */, - E80B28BB17ABAC790056179E /* README */, - E80B28BC17ABAC790056179E /* README.simd */, - ); - name = kiss_fft130; - path = Sources/kiss_fft130; - sourceTree = ""; - }; - E80B28D517B39CFE0056179E /* unzip */ = { - isa = PBXGroup; - children = ( - E80B28D617B39D160056179E /* ioapi.c */, - E80B28D717B39D160056179E /* ioapi.h */, - E80B28D817B39D160056179E /* unzip.c */, - E80B28D917B39D160056179E /* unzip.h */, - ); - name = unzip; - path = Sources/unzip; - sourceTree = ""; - }; - E81A7C68186140B000BF3FCE /* Software Renderer */ = { - isa = PBXGroup; - children = ( - E81A7C6218610AA900BF3FCE /* SWRenderer.cpp */, - E81A7C6318610AA900BF3FCE /* SWRenderer.h */, - E81A7C6518610BE400BF3FCE /* SWPort.cpp */, - E81A7C6618610BE400BF3FCE /* SWPort.h */, - E81A7C691861525D00BF3FCE /* SWImage.cpp */, - E81A7C6A1861525D00BF3FCE /* SWImage.h */, - E81A7C6C186152A400BF3FCE /* SWModel.cpp */, - E81A7C6D186152A400BF3FCE /* SWModel.h */, - E81A7C6F1861F4E200BF3FCE /* SWImageRenderer.cpp */, - E81A7C701861F4E200BF3FCE /* SWImageRenderer.h */, - E81A7C721863562A00BF3FCE /* SWFeatureLevel.h */, - E81A7C731863566200BF3FCE /* SWFeatureLevel.cpp */, - E81A7C751864171100BF3FCE /* SWMapRenderer.cpp */, - E81A7C761864171100BF3FCE /* SWMapRenderer.h */, - E81A7C7818642BCA00BF3FCE /* SWFlatMapRenderer.cpp */, - E81A7C7918642BCA00BF3FCE /* SWFlatMapRenderer.h */, - E8CB47CC1DE071CA00BF606A /* SWUtils.cpp */, - E8FC02D8186829BC00F84A0D /* SWUtils.h */, - E8C92A0A18695EA500740C9F /* SWModelRenderer.cpp */, - E8C92A0B18695EA500740C9F /* SWModelRenderer.h */, - ); - name = "Software Renderer"; - sourceTree = ""; - }; - E82E66BA18EA78F5004DBA18 /* Frameworks */ = { - isa = PBXGroup; - children = ( - E8626EBD1E1010CA003365BF /* libbz2.tbd */, - E844888617D26699005105D0 /* libcurl.tbd */, - E8CF039B178EDAC9000683D4 /* libz.tbd */, - E8CF03F2178EF916000683D4 /* Cocoa.framework */, - E8CF03C4178EE78C000683D4 /* OpenGL.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - E844886317D0C404005105D0 /* Local Entities */ = { - isa = PBXGroup; - children = ( - E8E0AFAA179ADC2100C6B5A9 /* ILocalEntity.cpp */, - E8E0AFAB179ADC2100C6B5A9 /* ILocalEntity.h */, - E8E0AFAD179ADDCB00C6B5A9 /* ParticleSpriteEntity.cpp */, - E8E0AFAE179ADDCB00C6B5A9 /* ParticleSpriteEntity.h */, - E8E0AFB0179AF4E600C6B5A9 /* SmokeSpriteEntity.cpp */, - E8E0AFB1179AF4E600C6B5A9 /* SmokeSpriteEntity.h */, - E89A649217A1677F00FDA893 /* FallingBlock.cpp */, - E89A649317A1677F00FDA893 /* FallingBlock.h */, - E89A649517A1835900FDA893 /* GunCasing.cpp */, - E89A649617A1835900FDA893 /* GunCasing.h */, - E844886417D0C43B005105D0 /* Tracer.cpp */, - E844886517D0C43B005105D0 /* Tracer.h */, - E8B6B73517E9C70000E35523 /* ClientPlayer.cpp */, - E8B6B73617E9C70000E35523 /* ClientPlayer.h */, - ); - name = "Local Entities"; - sourceTree = ""; - }; - E844886C17D26337005105D0 /* json */ = { - isa = PBXGroup; - children = ( - E844886D17D2633C005105D0 /* AUTHORS */, - E844886E17D2633C005105D0 /* include */, - E844887817D2633C005105D0 /* json_batchallocator.h */, - E844887917D2633C005105D0 /* json_internalarray.inl */, - E844887A17D2633C005105D0 /* json_internalmap.inl */, - E844887B17D2633C005105D0 /* json_reader.cpp */, - E844887C17D2633C005105D0 /* json_value.cpp */, - E844887D17D2633C005105D0 /* json_valueiterator.inl */, - E844887E17D2633C005105D0 /* json_writer.cpp */, - E844887F17D2633C005105D0 /* LICENSE */, - E844888017D2633C005105D0 /* README.txt */, - E844888117D2633C005105D0 /* version */, - ); - name = json; - path = Sources/json; - sourceTree = ""; - }; - E844886E17D2633C005105D0 /* include */ = { - isa = PBXGroup; - children = ( - E844886F17D2633C005105D0 /* json */, - ); - path = include; - sourceTree = ""; - }; - E844886F17D2633C005105D0 /* json */ = { - isa = PBXGroup; - children = ( - E844887017D2633C005105D0 /* autolink.h */, - E844887117D2633C005105D0 /* config.h */, - E844887217D2633C005105D0 /* features.h */, - E844887317D2633C005105D0 /* forwards.h */, - E844887417D2633C005105D0 /* json.h */, - E844887517D2633C005105D0 /* reader.h */, - E844887617D2633C005105D0 /* value.h */, - E844887717D2633C005105D0 /* writer.h */, - ); - path = json; - sourceTree = ""; - }; - E84E221218BB449A001282B0 /* cmake */ = { - isa = PBXGroup; - children = ( - E84E221318BB449A001282B0 /* FindGLEW2.cmake */, - E84E221418BB449A001282B0 /* FindSDL2.cmake */, - ); - path = cmake; - sourceTree = ""; - }; - E8567E541792B119009D83E0 /* Audio */ = { - isa = PBXGroup; - children = ( - E8567E6D1792FEEB009D83E0 /* AL */, - E8567E581792BEFC009D83E0 /* ALDevice.cpp */, - E8567E591792BEFC009D83E0 /* ALDevice.h */, - E8567E5B1792BFFE009D83E0 /* ALFuncs.h */, - E8567E5C1792C089009D83E0 /* ALFuncs.cpp */, - E88EB02D185D9DC500565D07 /* YsrDevice.cpp */, - E88EB02E185D9DC500565D07 /* YsrDevice.h */, - E842889118A3D9C40060743D /* NullDevice.cpp */, - E842889218A3D9C40060743D /* NullDevice.h */, - ); - path = Audio; - sourceTree = ""; - }; - E8626EA21E1008F9003365BF /* Externals */ = { - isa = PBXGroup; - children = ( - E8626EA31E10090C003365BF /* lib */, - ); - name = Externals; - path = Sources/Externals; - sourceTree = ""; - }; - E8626EA31E10090C003365BF /* lib */ = { - isa = PBXGroup; - children = ( - E87AB82418BB3A04006B7D73 /* SDL2_image.framework */, - E8B93AD418559EC600BD01E1 /* SDL2.framework */, - E82E680318EA7F60004DBA18 /* libysrspades.dylib */, - E8626EB71E100FB2003365BF /* libogg.a */, - E8626EB91E101072003365BF /* libopus.a */, - E8626EBA1E101072003365BF /* libopusfile.a */, - E8626EB51E100EC6003365BF /* libfreetype.a */, - ); - name = lib; - sourceTree = ""; - }; - E88319011792A7C5002ABE6D /* ENet */ = { - isa = PBXGroup; - children = ( - E88319021792A7CC002ABE6D /* callbacks.c */, - E88319031792A7CC002ABE6D /* compress.c */, - E88319041792A7CC002ABE6D /* host.c */, - E88319051792A7CC002ABE6D /* include */, - E88319101792A7CC002ABE6D /* LICENSE */, - E88319111792A7CC002ABE6D /* list.c */, - E88319121792A7CC002ABE6D /* packet.c */, - E88319131792A7CC002ABE6D /* peer.c */, - E88319141792A7CC002ABE6D /* protocol.c */, - E88319151792A7CC002ABE6D /* README */, - E88319161792A7CC002ABE6D /* unix.c */, - E88319171792A7CC002ABE6D /* win32.c */, - ); - name = ENet; - path = Sources/ENet; - sourceTree = ""; - }; - E88319051792A7CC002ABE6D /* include */ = { - isa = PBXGroup; - children = ( - E88319061792A7CC002ABE6D /* enet */, - ); - path = include; - sourceTree = ""; - }; - E88319061792A7CC002ABE6D /* enet */ = { - isa = PBXGroup; - children = ( - E88319071792A7CC002ABE6D /* callbacks.h */, - E88319081792A7CC002ABE6D /* enet.h */, - E88319091792A7CC002ABE6D /* list.h */, - E883190A1792A7CC002ABE6D /* protocol.h */, - E883190B1792A7CC002ABE6D /* time.h */, - E883190C1792A7CC002ABE6D /* types.h */, - E883190D1792A7CC002ABE6D /* unix.h */, - E883190E1792A7CC002ABE6D /* utility.h */, - E883190F1792A7CC002ABE6D /* win32.h */, - ); - path = enet; - sourceTree = ""; - }; - E88F46571DE1AF48009E85E5 /* Built-in Paks */ = { - isa = PBXGroup; - children = ( - E8690AE61D3920C800DBC331 /* pak000-Nonfree.pak */, - E8690AE71D3920C800DBC331 /* pak002-Base.pak */, - E8690AE81D3920C800DBC331 /* pak005-Models.pak */, - E8690AE91D3920C800DBC331 /* pak010-BaseSkin.pak */, - E8690AEA1D3920C800DBC331 /* pak050-Locales.pak */, - E8690AEB1D3920C800DBC331 /* pak999-References.pak */, - E82E67F318EA7EAB004DBA18 /* font-unifont.pak */, - ); - name = "Built-in Paks"; - sourceTree = ""; - }; - E88F46581DE1AF8D009E85E5 /* Libraries */ = { - isa = PBXGroup; - children = ( - E8626EA21E1008F9003365BF /* Externals */, - E844886C17D26337005105D0 /* json */, - E80B28D517B39CFE0056179E /* unzip */, - E80B28B117ABAC6C0056179E /* kiss_fft130 */, - E80B288917A52CB70056179E /* binpack2d */, - E8B6B63D17DE27B200E35523 /* AngelScript */, - E88319011792A7C5002ABE6D /* ENet */, - ); - name = Libraries; - sourceTree = ""; - }; - E89A649B17A2407100FDA893 /* Lighting */ = { - isa = PBXGroup; - children = ( - E8E446A2179EA60900BE8855 /* GLMapShadowRenderer.cpp */, - E8E446A3179EA60900BE8855 /* GLMapShadowRenderer.h */, - E8E446A5179EAC7800BE8855 /* GLShadowShader.cpp */, - E8E446A6179EAC7800BE8855 /* GLShadowShader.h */, - E89A648F17A12FF800FDA893 /* GLDynamicLightShader.cpp */, - E89A649017A12FF800FDA893 /* GLDynamicLightShader.h */, - E89A649817A2402500FDA893 /* IGLShadowMapRenderer.cpp */, - E89A649917A2402700FDA893 /* IGLShadowMapRenderer.h */, - E80B286017A2462D0056179E /* GLShadowMapShader.cpp */, - E80B286117A2462D0056179E /* GLShadowMapShader.h */, - E80B286317A24AED0056179E /* GLBasicShadowMapRenderer.cpp */, - E80B286417A24AED0056179E /* GLBasicShadowMapRenderer.h */, - E80B289417A9D6B40056179E /* GLDynamicLight.cpp */, - E80B289517A9D6B50056179E /* GLDynamicLight.h */, - E80B28BF17AE7FEB0056179E /* GLAmbientShadowRenderer.cpp */, - E80B28C017AE7FEE0056179E /* GLAmbientShadowRenderer.h */, - E8EE089F17B8F4B000631987 /* GLRadiosityRenderer.cpp */, - E8EE08A017B8F4B000631987 /* GLRadiosityRenderer.h */, - E8B6B6BD17DF456E00E35523 /* GLSparseShadowMapRenderer.cpp */, - E8B6B6BE17DF456F00E35523 /* GLSparseShadowMapRenderer.h */, - ); - name = Lighting; - sourceTree = ""; - }; - E89E811E179C2BDC0059C649 /* Post Filters */ = { - isa = PBXGroup; - children = ( - E89BBDC01B3559CD00F53EE9 /* GLAutoExposureFilter.cpp */, - E89BBDC11B3559CD00F53EE9 /* GLAutoExposureFilter.h */, - E89E811F179C2C800059C649 /* GLBloomFilter.cpp */, - E89E8120179C2C800059C649 /* GLBloomFilter.h */, - E8D88AAF179C3004004C2451 /* GLQuadRenderer.cpp */, - E8D88AB0179C3004004C2451 /* GLQuadRenderer.h */, - E8D88AB2179C45B7004C2451 /* GLLensFilter.cpp */, - E8D88AB3179C45B7004C2451 /* GLLensFilter.h */, - E8E4469C179D59A900BE8855 /* GLCameraBlurFilter.cpp */, - E8E4469D179D59A900BE8855 /* GLCameraBlurFilter.h */, - E859510A17C5DA060012810C /* GLFogFilter.cpp */, - E859510B17C5DA060012810C /* GLFogFilter.h */, - E859510D17C61F850012810C /* GLLensFlareFilter.cpp */, - E859510E17C61F850012810C /* GLLensFlareFilter.h */, - E859511017C645000012810C /* GLFXAAFilter.cpp */, - E859511117C645000012810C /* GLFXAAFilter.h */, - E8D2ACE117D704E600BE5490 /* GLColorCorrectionFilter.cpp */, - E8D2ACE217D704E600BE5490 /* GLColorCorrectionFilter.h */, - E8B6B6E317E165A400E35523 /* GLDepthOfFieldFilter.cpp */, - E8B6B6E417E165A500E35523 /* GLDepthOfFieldFilter.h */, - E8B6B72917E6095800E35523 /* GLLensDustFilter.cpp */, - E8B6B72A17E6095800E35523 /* GLLensDustFilter.h */, - E8D0E5D018F3215000DE3BDB /* GLNonlinearizeFilter.cpp */, - E8D0E5D118F3215000DE3BDB /* GLNonlinearizeFilter.h */, - E80950081E17F66500AECDF2 /* GLSSAOFilter.cpp */, - E80950091E17F66500AECDF2 /* GLSSAOFilter.h */, - ); - name = "Post Filters"; - sourceTree = ""; - }; - E8B6B63D17DE27B200E35523 /* AngelScript */ = { - isa = PBXGroup; - children = ( - E8B6B6FF17E4193800E35523 /* addons */, - E8B6B6BA17DE2F5500E35523 /* projects */, - E8B6B63E17DE27B500E35523 /* include */, - E8B6B64017DE27B500E35523 /* source */, - ); - name = AngelScript; - path = Sources/AngelScript; - sourceTree = ""; - }; - E8B6B63E17DE27B500E35523 /* include */ = { - isa = PBXGroup; - children = ( - E8B6B63F17DE27B500E35523 /* angelscript.h */, - ); - path = include; - sourceTree = ""; - }; - E8B6B64017DE27B500E35523 /* source */ = { - isa = PBXGroup; - children = ( - E867B6E31DD49D7F0093E4E0 /* as_namespace.h */, - E8B6B64117DE27B500E35523 /* as_array.h */, - E8B6B64217DE27B500E35523 /* as_atomic.cpp */, - E8B6B64317DE27B500E35523 /* as_atomic.h */, - E8B6B64417DE27B500E35523 /* as_builder.cpp */, - E8B6B64517DE27B500E35523 /* as_builder.h */, - E8B6B64617DE27B500E35523 /* as_bytecode.cpp */, - E8B6B64717DE27B500E35523 /* as_bytecode.h */, - E8B6B64817DE27B500E35523 /* as_callfunc.cpp */, - E8B6B64917DE27B500E35523 /* as_callfunc.h */, - E8B6B64A17DE27B500E35523 /* as_callfunc_arm.cpp */, - E8B6B64B17DE27B500E35523 /* as_callfunc_arm_gcc.S */, - E8B6B64C17DE27B500E35523 /* as_callfunc_arm_msvc.asm */, - E8B6B64D17DE27B500E35523 /* as_callfunc_arm_xcode.S */, - E8B6B64E17DE27B500E35523 /* as_callfunc_mips.cpp */, - E8B6B64F17DE27B500E35523 /* as_callfunc_ppc.cpp */, - E8B6B65017DE27B500E35523 /* as_callfunc_ppc_64.cpp */, - E8B6B65117DE27B500E35523 /* as_callfunc_sh4.cpp */, - E8B6B65217DE27B500E35523 /* as_callfunc_x64_gcc.cpp */, - E8B6B65317DE27B500E35523 /* as_callfunc_x64_mingw.cpp */, - E8B6B65417DE27B500E35523 /* as_callfunc_x64_msvc.cpp */, - E8B6B65517DE27B500E35523 /* as_callfunc_x64_msvc_asm.asm */, - E8B6B65617DE27B500E35523 /* as_callfunc_x86.cpp */, - E8B6B65717DE27B500E35523 /* as_callfunc_xenon.cpp */, - E8B6B65817DE27B500E35523 /* as_compiler.cpp */, - E8B6B65917DE27B500E35523 /* as_compiler.h */, - E8B6B65A17DE27B500E35523 /* as_config.h */, - E8B6B65B17DE27B500E35523 /* as_configgroup.cpp */, - E8B6B65C17DE27B500E35523 /* as_configgroup.h */, - E8B6B65D17DE27B500E35523 /* as_context.cpp */, - E8B6B65E17DE27B500E35523 /* as_context.h */, - E8B6B65F17DE27B500E35523 /* as_criticalsection.h */, - E8B6B66017DE27B500E35523 /* as_datatype.cpp */, - E8B6B66117DE27B500E35523 /* as_datatype.h */, - E8B6B66217DE27B500E35523 /* as_debug.h */, - E8B6B66317DE27B500E35523 /* as_gc.cpp */, - E8B6B66417DE27B500E35523 /* as_gc.h */, - E8B6B66517DE27B500E35523 /* as_generic.cpp */, - E8B6B66617DE27B500E35523 /* as_generic.h */, - E8B6B66717DE27B500E35523 /* as_globalproperty.cpp */, - E8B6B66817DE27B500E35523 /* as_map.h */, - E8B6B66917DE27B500E35523 /* as_memory.cpp */, - E8B6B66A17DE27B500E35523 /* as_memory.h */, - E8B6B66B17DE27B500E35523 /* as_module.cpp */, - E8B6B66C17DE27B500E35523 /* as_module.h */, - E8B6B66D17DE27B500E35523 /* as_objecttype.cpp */, - E8B6B66E17DE27B500E35523 /* as_objecttype.h */, - E8B6B66F17DE27B500E35523 /* as_outputbuffer.cpp */, - E8B6B67017DE27B500E35523 /* as_outputbuffer.h */, - E8B6B67117DE27B500E35523 /* as_parser.cpp */, - E8B6B67217DE27B500E35523 /* as_parser.h */, - E8B6B67317DE27B500E35523 /* as_property.h */, - E8B6B67417DE27B500E35523 /* as_restore.cpp */, - E8B6B67517DE27B500E35523 /* as_restore.h */, - E8B6B67617DE27B500E35523 /* as_scriptcode.cpp */, - E8B6B67717DE27B500E35523 /* as_scriptcode.h */, - E8B6B67817DE27B500E35523 /* as_scriptengine.cpp */, - E8B6B67917DE27B500E35523 /* as_scriptengine.h */, - E8B6B67A17DE27B500E35523 /* as_scriptfunction.cpp */, - E8B6B67B17DE27B500E35523 /* as_scriptfunction.h */, - E8B6B67C17DE27B500E35523 /* as_scriptnode.cpp */, - E8B6B67D17DE27B500E35523 /* as_scriptnode.h */, - E8B6B67E17DE27B500E35523 /* as_scriptobject.cpp */, - E8B6B67F17DE27B500E35523 /* as_scriptobject.h */, - E8B6B68017DE27B500E35523 /* as_string.cpp */, - E8B6B68117DE27B500E35523 /* as_string.h */, - E8B6B68217DE27B500E35523 /* as_string_util.cpp */, - E8B6B68317DE27B500E35523 /* as_string_util.h */, - E8B6B68417DE27B500E35523 /* as_symboltable.h */, - E8B6B68517DE27B500E35523 /* as_texts.h */, - E8B6B68617DE27B500E35523 /* as_thread.cpp */, - E8B6B68717DE27B500E35523 /* as_thread.h */, - E8B6B68817DE27B500E35523 /* as_tokendef.h */, - E8B6B68917DE27B500E35523 /* as_tokenizer.cpp */, - E8B6B68A17DE27B500E35523 /* as_tokenizer.h */, - E8B6B68B17DE27B500E35523 /* as_typeinfo.cpp */, - E8B6B68C17DE27B500E35523 /* as_typeinfo.h */, - E8B6B68D17DE27B500E35523 /* as_variablescope.cpp */, - E8B6B68E17DE27B500E35523 /* as_variablescope.h */, - ); - path = source; - sourceTree = ""; - }; - E8B6B6BA17DE2F5500E35523 /* projects */ = { - isa = PBXGroup; - children = ( - E8B6B6BB17DE2F5500E35523 /* cmake */, - ); - path = projects; - sourceTree = ""; - }; - E8B6B6BB17DE2F5500E35523 /* cmake */ = { - isa = PBXGroup; - children = ( - E8B6B6BC17DE2F5500E35523 /* CMakeLists.txt */, - ); - path = cmake; - sourceTree = ""; - }; - E8B6B6E617E40AF300E35523 /* ScriptBindings */ = { - isa = PBXGroup; - children = ( - E8C7D7BF22DB3AE000F78763 /* ConsoleCommandCandidate.cpp */, - E8C7D7B022DA35F000F78763 /* ConsoleHelper.cpp */, - E8B6B6E717E40AF500E35523 /* MathScript.cpp */, - E838D42018ADDE2800EE3C53 /* StringsScript.cpp */, - E8B6B6E817E40AF500E35523 /* ScriptManager.cpp */, - E8B6B6E917E40AF500E35523 /* ScriptManager.h */, - E8B6B6EC17E40B5900E35523 /* IImage.cpp */, - E8B6B6F217E40E8200E35523 /* IModel.cpp */, - E8B6B6F517E40F9900E35523 /* IRenderer.cpp */, - E8B6B6F817E4130E00E35523 /* GameMap.cpp */, - E8B6B6FB17E413AB00E35523 /* Bitmap.cpp */, - E8B6B6FD17E4141000E35523 /* VoxelModel.cpp */, - E8B6B72017E4508C00E35523 /* IAudioDevice.cpp */, - E8B6B72217E452EC00E35523 /* IAudioChunk.cpp */, - E8B6B72417E46C1B00E35523 /* PrimitiveArray.cpp */, - E8B6B72F17E8C4ED00E35523 /* IToolSkin.cpp */, - E8B6B73117E8CB1800E35523 /* IToolSkin.h */, - E8B6B73217E8CE1300E35523 /* ScriptFunction.cpp */, - E8B6B73317E8CE1700E35523 /* ScriptFunction.h */, - E8B6B73817E9E8CF00E35523 /* ISpadeSkin.cpp */, - E8B6B73917E9E8D300E35523 /* ISpadeSkin.h */, - E8B6B73B17E9F49700E35523 /* IBlockSkin.cpp */, - E8B6B73C17E9F49C00E35523 /* IBlockSkin.h */, - E8B6B73E17EA060900E35523 /* IViewToolSkin.cpp */, - E8B6B73F17EA060D00E35523 /* IViewToolSkin.h */, - E8B6B74117EA0B1500E35523 /* IThirdPersonToolSkin.cpp */, - E8B6B74217EA0B1900E35523 /* IThirdPersonToolSkin.h */, - E8B6B74417EA0F1B00E35523 /* IGrenadeSkin.cpp */, - E8B6B74517EA0F1E00E35523 /* IGrenadeSkin.h */, - E8B6B74717EA12E100E35523 /* IWeaponSkin.cpp */, - E8B6B74817EA12E500E35523 /* IWeaponSkin.h */, - E81CE4A4183F7A3000F22685 /* IFont.cpp */, - E8F74CF0183FBB070085AA54 /* MainScreenHelper.cpp */, - E842888F18A3D6470060743D /* StartupScreenHelper.cpp */, - E8F74CF31840D4CC0085AA54 /* Config.cpp */, - E8493DB61A7349030055731A /* Config.h */, - E8F74CFC1845C8D50085AA54 /* ClientUIHelper.cpp */, - E8F74CFE184C753F0085AA54 /* Clipboard.cpp */, - E883440F1E03244F000C3E39 /* FontManager.cpp */, - E893A3621E3E3331000654A4 /* PackageUpdateManager.cpp */, - ); - name = ScriptBindings; - path = Sources/ScriptBindings; - sourceTree = SOURCE_ROOT; - }; - E8B6B6FF17E4193800E35523 /* addons */ = { - isa = PBXGroup; - children = ( - E8B6B70017E4193A00E35523 /* scriptany.cpp */, - E8B6B70117E4193A00E35523 /* scriptany.h */, - E8B6B70217E4193A00E35523 /* scriptarray.cpp */, - E8B6B70317E4193A00E35523 /* scriptarray.h */, - E8B6B70417E4193A00E35523 /* scriptbuilder.cpp */, - E8B6B70517E4193A00E35523 /* scriptbuilder.h */, - E8B6B70617E4193A00E35523 /* scriptdictionary.cpp */, - E8B6B70717E4193A00E35523 /* scriptdictionary.h */, - E8B6B70817E4193A00E35523 /* scripthandle.cpp */, - E8B6B70917E4193A00E35523 /* scripthandle.h */, - E8B6B70A17E4193A00E35523 /* scripthelper.cpp */, - E8B6B70B17E4193A00E35523 /* scripthelper.h */, - E8B6B70C17E4193A00E35523 /* scriptmath.cpp */, - E8B6B70D17E4193A00E35523 /* scriptmath.h */, - E8B6B70E17E4193A00E35523 /* scriptmathcomplex.cpp */, - E8B6B70F17E4193A00E35523 /* scriptmathcomplex.h */, - E8B6B71017E4193A00E35523 /* scriptstdstring.cpp */, - E8B6B71117E4193A00E35523 /* scriptstdstring.h */, - E8B6B71217E4193A00E35523 /* scriptstdstring_utils.cpp */, - E8B6B71317E4193A00E35523 /* weakref.cpp */, - E8B6B71417E4193A00E35523 /* weakref.h */, - ); - path = addons; - sourceTree = ""; - }; - E8CF037C178ED9D2000683D4 = { - isa = PBXGroup; - children = ( - E893A3641E3E4181000654A4 /* PackageInfo.json */, - E874834618EACF0300C29033 /* OpenSpades.icns */, - E82E680618EA9502004DBA18 /* XSpades.entitlements */, - E88F46571DE1AF48009E85E5 /* Built-in Paks */, - E8E446AB17A02EC700BE8855 /* Supporting Files */, - E8CF041817905609000683D4 /* Resources */, - E88F46581DE1AF8D009E85E5 /* Libraries */, - E8CF0387178ED9D2000683D4 /* Sources */, - E82E66BA18EA78F5004DBA18 /* Frameworks */, - E8CF0386178ED9D2000683D4 /* Products */, - ); - sourceTree = ""; - }; - E8CF0386178ED9D2000683D4 /* Products */ = { - isa = PBXGroup; - children = ( - E82E66B918EA78F5004DBA18 /* OpenSpades.app */, - ); - name = Products; - sourceTree = ""; - }; - E8CF0387178ED9D2000683D4 /* Sources */ = { - isa = PBXGroup; - children = ( - E844888B17D3A059005105D0 /* CMakeLists.txt */, - E844888517D26411005105D0 /* OpenSpades.h */, - E8CF03B3178EE38C000683D4 /* Imports */, - E8567E541792B119009D83E0 /* Audio */, - E8CF03AF178EE2CD000683D4 /* Core */, - E8CF03A2178EDE56000683D4 /* Client */, - E8CF039E178EDDCF000683D4 /* Draw */, - E8CF039D178EDDBF000683D4 /* Gui */, - ); - path = Sources; - sourceTree = ""; - }; - E8CF039D178EDDBF000683D4 /* Gui */ = { - isa = PBXGroup; - children = ( - E8C7D7BD22DB2A4400F78763 /* ConsoleCommandCandidate.cpp */, - E8C7D7BC22DB2A4400F78763 /* ConsoleCommandCandidate.h */, - E8C7D7B822DB220200F78763 /* ConfigConsoleResponder.cpp */, - E8C7D7B922DB220300F78763 /* ConfigConsoleResponder.h */, - E8C7D7B322DAF5B400F78763 /* ConsoleCommand.cpp */, - E8C7D7B222DAF5B400F78763 /* ConsoleCommand.h */, - E8C7D7AB22DA34F400F78763 /* ConsoleHelper.cpp */, - E8C7D7AA22DA34F400F78763 /* ConsoleHelper.h */, - E8C7D7AC22DA34F400F78763 /* ConsoleScreen.cpp */, - E8C7D7AD22DA34F500F78763 /* ConsoleScreen.h */, - E8F74CEC183F931F0085AA54 /* SDLMain.h */, - E8F74CEA183F92DA0085AA54 /* SDLmain.m */, - E8CF03BE178EE50E000683D4 /* Main.cpp */, - E8F74CE6183F8A110085AA54 /* Main.h */, - E8EF8B551E1D70D900E0829C /* SplashWindow.cpp */, - E8EF8B561E1D70D900E0829C /* SplashWindow.h */, - E8CF03BB178EE502000683D4 /* SDLGLDevice.cpp */, - E8CF03BC178EE502000683D4 /* SDLGLDevice.h */, - E8CF03E1178EF57E000683D4 /* SDLRunner.cpp */, - E8CF03E2178EF57E000683D4 /* SDLRunner.h */, - E81CE4A7183F7F2000F22685 /* MainScreen.cpp */, - E81CE4A8183F7F2000F22685 /* MainScreen.h */, - E8F74CED183FBA9C0085AA54 /* MainScreenHelper.cpp */, - E8F74CEE183FBA9C0085AA54 /* MainScreenHelper.h */, - E8F74CE3183F86AE0085AA54 /* View.cpp */, - E8F74CE4183F86AE0085AA54 /* View.h */, - E8F74CE7183F8B9D0085AA54 /* Runner.cpp */, - E8F74CE8183F8B9D0085AA54 /* Runner.h */, - E842888918A3CF6C0060743D /* StartupScreen.cpp */, - E842888A18A3CF6C0060743D /* StartupScreen.h */, - E842888C18A3D1520060743D /* StartupScreenHelper.cpp */, - E842888D18A3D1520060743D /* StartupScreenHelper.h */, - E84E221818BB4BA0001282B0 /* Credits.inc */, - E810122F1E1D7301009955D3 /* Icon.cpp */, - E81012301E1D7301009955D3 /* Icon.h */, - E893A35F1E3E141D000654A4 /* PackageUpdateManager.cpp */, - E893A3601E3E141D000654A4 /* PackageUpdateManager.h */, - ); - path = Gui; - sourceTree = ""; - }; - E8CF039E178EDDCF000683D4 /* Draw */ = { - isa = PBXGroup; - children = ( - E81A7C68186140B000BF3FCE /* Software Renderer */, - E89E811E179C2BDC0059C649 /* Post Filters */, - E8E0AFBA179C0F5B00C6B5A9 /* Client Object */, - E8E0AFB9179C0F3500C6B5A9 /* Low Level */, - E89A649B17A2407100FDA893 /* Lighting */, - E8CF03A9178EDF74000683D4 /* GLRenderer.cpp */, - E8CF03AA178EDF74000683D4 /* GLRenderer.h */, - E8CF03AC178EDFCD000683D4 /* IGLDevice.cpp */, - E8CF03AD178EDFCD000683D4 /* IGLDevice.h */, - E8E0AFB6179C0F2800C6B5A9 /* GLFramebufferManager.cpp */, - E8E0AFB7179C0F2800C6B5A9 /* GLFramebufferManager.h */, - E8CF041C1790D6D5000683D4 /* GLProgramManager.cpp */, - E8CF041D1790D6D5000683D4 /* GLProgramManager.h */, - E859511317C96B260012810C /* GLProfiler.cpp */, - E859511417C96B270012810C /* GLProfiler.h */, - E8CB47D31DE0844400BF606A /* GLSettings.h */, - E8CB47D41DE084AB00BF606A /* GLSettings.cpp */, - ); - path = Draw; - sourceTree = ""; - }; - E8CF03A2178EDE56000683D4 /* Client */ = { - isa = PBXGroup; - children = ( - E8E0AF8D17993CB100C6B5A9 /* I/O Interfaces */, - E8E0AF9017993D1800C6B5A9 /* Net */, - E8E0AF8B17993C2300C6B5A9 /* Client Main */, - E8E0AF8E17993CD600C6B5A9 /* Utilities */, - E8E0AF8C17993C8500C6B5A9 /* World */, - ); - path = Client; - sourceTree = ""; - }; - E8CF03AF178EE2CD000683D4 /* Core */ = { - isa = PBXGroup; - children = ( - E8C7D7BB22DB263200F78763 /* Iterator.h */, - E8E44682179CC4A400BE8855 /* Media */, - E8E44681179CC49C00BE8855 /* I/O */, - E8E44680179CC48B00BE8855 /* System */, - E8B6B6E617E40AF300E35523 /* ScriptBindings */, - E8CF03CC178EE95F000683D4 /* Math.cpp */, - E8CF03CD178EE95F000683D4 /* Math.h */, - E88318DF17925F2E002ABE6D /* Deque.cpp */, - E88318E017925F2E002ABE6D /* Deque.h */, - E88318E21792698D002ABE6D /* Stopwatch.cpp */, - E88318E31792698D002ABE6D /* Stopwatch.h */, - E834F5541794BBD4004EBE88 /* Debug.cpp */, - E834F5551794BBD4004EBE88 /* Debug.h */, - E8E0AFB3179BF25B00C6B5A9 /* Settings.cpp */, - E8E0AFB4179BF25B00C6B5A9 /* Settings.h */, - E849654B18E9487300B9706D /* FltkPreferenceImporter.cpp */, - E849654C18E9487300B9706D /* FltkPreferenceImporter.h */, - E8B6B6EF17E40DA700E35523 /* RefCountedObject.cpp */, - E8B6B6F017E40DAA00E35523 /* RefCountedObject.h */, - E81A7C7B1865A2E900BF3FCE /* MiniHeap.cpp */, - E81A7C7C1865A2E900BF3FCE /* MiniHeap.h */, - E890F30E187046990090AAB8 /* CP437.cpp */, - E890F30F187046990090AAB8 /* CP437.h */, - E838D41D18AC726B00EE3C53 /* Strings.cpp */, - E838D41E18AC726B00EE3C53 /* Strings.h */, - E8CB47CF1DE07CF000BF606A /* SettingSet.cpp */, - E8CB47D01DE07CF000BF606A /* SettingSet.h */, - E89A5F1C1DF8732200857F65 /* ShellApi.cpp */, - E89A5F1D1DF8732200857F65 /* ShellApi.h */, - E89A5F1F1DF8759200857F65 /* ShellApi.mm */, - E8655AA91DFC0AAA00D5058A /* TMPUtils.h */, - E86D20D12171BF9700964257 /* Disposable.h */, - ); - path = Core; - sourceTree = ""; - }; - E8CF03B3178EE38C000683D4 /* Imports */ = { - isa = PBXGroup; - children = ( - E8CF03B4178EE39A000683D4 /* SDL.h */, - E8CF03C0178EE5B6000683D4 /* OpenGL.h */, - ); - path = Imports; - sourceTree = ""; - }; - E8E0AF8B17993C2300C6B5A9 /* Client Main */ = { - isa = PBXGroup; - children = ( - E844886317D0C404005105D0 /* Local Entities */, - E8CF03C1178EE6D8000683D4 /* Client.cpp */, - E8C7D7C122DB635F00F78763 /* Client_Console.cpp */, - E8FE748B18CC6AA100291338 /* Client_Input.cpp */, - E8FE748D18CC6C2B00291338 /* Client_Update.cpp */, - E8FE748F18CC6CE000291338 /* Client_NetHandler.cpp */, - E8FE749118CC6E4900291338 /* Client_LocalEnts.cpp */, - E8FE749318CC6EB500291338 /* Client_Draw.cpp */, - E8FE749518CC6F2900291338 /* Client_Scene.cpp */, - E82E66B218E9A35C004DBA18 /* Client_FPSCounter.cpp */, - E8CF03C2178EE6D8000683D4 /* Client.h */, - E831D8661FD65BD5003C0D97 /* ClientCameraMode.h */, - E834F56D1797D92F004EBE88 /* ChatWindow.cpp */, - E834F56E1797D932004EBE88 /* ChatWindow.h */, - E8E0AF92179942DB00C6B5A9 /* Corpse.cpp */, - E8E0AF93179942DB00C6B5A9 /* Corpse.h */, - E8E0AF95179980F500C6B5A9 /* CenterMessageView.cpp */, - E8E0AF96179980F500C6B5A9 /* CenterMessageView.h */, - E8E0AF98179996A100C6B5A9 /* HurtRingView.cpp */, - E8E0AF99179996A100C6B5A9 /* HurtRingView.h */, - E8E0AF9E179A698800C6B5A9 /* MapView.cpp */, - E8E0AF9F179A698800C6B5A9 /* MapView.h */, - E8E0AFA1179A8F1000C6B5A9 /* ScoreboardView.cpp */, - E8E0AFA2179A8F1000C6B5A9 /* ScoreboardView.h */, - E8E0AFA4179AA31B00C6B5A9 /* LimboView.cpp */, - E8E0AFA5179AA31C00C6B5A9 /* LimboView.h */, - E80B28CB17AFCCC40056179E /* PaletteView.cpp */, - E80B28CC17AFCCC70056179E /* PaletteView.h */, - E80B28D117AFF77B0056179E /* TCProgressView.cpp */, - E80B28D217AFF77E0056179E /* TCProgressView.h */, - E8F74CF61845C5000085AA54 /* ClientUI.cpp */, - E8F74CF71845C5000085AA54 /* ClientUI.h */, - E8F74CF91845C64B0085AA54 /* ClientUIHelper.cpp */, - E8F74CFA1845C64B0085AA54 /* ClientUIHelper.h */, - ); - name = "Client Main"; - sourceTree = ""; - }; - E8E0AF8C17993C8500C6B5A9 /* World */ = { - isa = PBXGroup; - children = ( - E8E0AF9117993D2B00C6B5A9 /* Game Modes */, - E8E0AF8F17993CEB00C6B5A9 /* Elements */, - E8CF03FA178FACFF000683D4 /* GameMap.cpp */, - E8CF03FB178FACFF000683D4 /* GameMap.h */, - E8CF03FD178FB1E1000683D4 /* IGameMapListener.cpp */, - E8CF03FE178FB1E1000683D4 /* IGameMapListener.h */, - E88318DC179257F0002ABE6D /* GameMapWrapper.cpp */, - E88318DD179257F0002ABE6D /* GameMapWrapper.h */, - E88318E617928F84002ABE6D /* World.cpp */, - E88318E717928F85002ABE6D /* World.h */, - E8567E6A1792F398009D83E0 /* IWorldListener.cpp */, - E8567E6B1792F399009D83E0 /* IWorldListener.h */, - E88318E517928EAC002ABE6D /* PhysicsConstants.h */, - E8FE748818CB329C00291338 /* HitTestDebugger.cpp */, - E8FE748918CB329C00291338 /* HitTestDebugger.h */, - E8A2EB9E1F5BE16D00E39CD9 /* GameProperties.cpp */, - E8A2EB9F1F5BE16D00E39CD9 /* GameProperties.h */, - ); - name = World; - sourceTree = ""; - }; - E8E0AF8D17993CB100C6B5A9 /* I/O Interfaces */ = { - isa = PBXGroup; - children = ( - E8CF03A6178EDF6A000683D4 /* IRenderer.cpp */, - E8CF03A7178EDF6A000683D4 /* IRenderer.h */, - E8CF03F7178FABA4000683D4 /* SceneDefinition.cpp */, - E8CF03F8178FABA4000683D4 /* SceneDefinition.h */, - E8CF03C6178EE81A000683D4 /* IAudioDevice.cpp */, - E8CF03C7178EE81A000683D4 /* IAudioDevice.h */, - E8567E551792B24D009D83E0 /* IAudioChunk.cpp */, - E8567E561792B24D009D83E0 /* IAudioChunk.h */, - E8CF03C9178EE869000683D4 /* IInputInterface.cpp */, - E8CF03CA178EE869000683D4 /* IInputInterface.h */, - E8CF03F4178FAA8B000683D4 /* IImage.cpp */, - E8CF03F5178FAA8B000683D4 /* IImage.h */, - E8567E711793D5AD009D83E0 /* IModel.cpp */, - E8567E721793D5AD009D83E0 /* IModel.h */, - ); - name = "I/O Interfaces"; - sourceTree = ""; - }; - E8E0AF8E17993CD600C6B5A9 /* Utilities */ = { - isa = PBXGroup; - children = ( - E834F56617979F55004EBE88 /* Quake3Font.cpp */, - E834F56717979F57004EBE88 /* Quake3Font.h */, - E834F56917979FD3004EBE88 /* IFont.cpp */, - E834F56A17979FD5004EBE88 /* IFont.h */, - E834F56C1797AA2C004EBE88 /* FontData.h */, - E842889418A667930060743D /* Fonts.cpp */, - E842889518A667930060743D /* Fonts.h */, - E8725DAB1DE33B4D003BC987 /* NoiseSampler.cpp */, - E8725DAC1DE33B4D003BC987 /* NoiseSampler.h */, - E8655AA61DFC0A6E00D5058A /* FTFont.cpp */, - E8655AA71DFC0A6E00D5058A /* FTFont.h */, - ); - name = Utilities; - sourceTree = ""; - }; - E8E0AF8F17993CEB00C6B5A9 /* Elements */ = { - isa = PBXGroup; - children = ( - E88318D9179256E4002ABE6D /* Player.cpp */, - E88318DA179256E5002ABE6D /* Player.h */, - E834F54E17942C43004EBE88 /* Grenade.cpp */, - E834F54F17942C43004EBE88 /* Grenade.h */, - E8567E6E1793AA45009D83E0 /* Weapon.cpp */, - E8567E6F1793AA46009D83E0 /* Weapon.h */, - ); - name = Elements; - sourceTree = ""; - }; - E8E0AF9017993D1800C6B5A9 /* Net */ = { - isa = PBXGroup; - children = ( - E8403CAD2291280700093C3E /* GameMapLoader.cpp */, - E8403CAC2291280700093C3E /* GameMapLoader.h */, - E8F6E6E41DCF503200FE76BB /* MumbleLink.cpp */, - E8F6E6E51DCF503200FE76BB /* MumbleLink.h */, - E834F55117944778004EBE88 /* NetClient.cpp */, - E834F55217944779004EBE88 /* NetClient.h */, - ); - name = Net; - sourceTree = ""; - }; - E8E0AF9117993D2B00C6B5A9 /* Game Modes */ = { - isa = PBXGroup; - children = ( - E834F5571794DCF9004EBE88 /* IGameMode.cpp */, - E834F5581794DCFB004EBE88 /* IGameMode.h */, - E834F55A1794DDA2004EBE88 /* CTFGameMode.cpp */, - E834F55B1794DDA4004EBE88 /* CTFGameMode.h */, - E80B28CE17AFE68A0056179E /* TCGameMode.cpp */, - E80B28CF17AFE68A0056179E /* TCGameMode.h */, - ); - name = "Game Modes"; - sourceTree = ""; - }; - E8E0AFB9179C0F3500C6B5A9 /* Low Level */ = { - isa = PBXGroup; - children = ( - E8CF04191790CCAB000683D4 /* GLShader.cpp */, - E8CF041A1790CCAB000683D4 /* GLShader.h */, - E88318A91790EBAA002ABE6D /* GLProgramUniform.cpp */, - E88318AA1790EBAA002ABE6D /* GLProgramUniform.h */, - E88318AC1790EDDF002ABE6D /* GLProgramAttribute.cpp */, - E88318AD1790EDDF002ABE6D /* GLProgramAttribute.h */, - E8CF04061790455B000683D4 /* GLProgram.cpp */, - E8CF04071790455B000683D4 /* GLProgram.h */, - ); - name = "Low Level"; - sourceTree = ""; - }; - E8E0AFBA179C0F5B00C6B5A9 /* Client Object */ = { - isa = PBXGroup; - children = ( - E8CF0400178FB52F000683D4 /* GLImage.cpp */, - E8CF0401178FB52F000683D4 /* GLImage.h */, - E8E0AF9B179A5BC200C6B5A9 /* GLFlatMapRenderer.cpp */, - E8E0AF9C179A5BC200C6B5A9 /* GLFlatMapRenderer.h */, - E8E44696179D2CA100BE8855 /* IGLSpriteRenderer.cpp */, - E8E44697179D2CA100BE8855 /* IGLSpriteRenderer.h */, - E8E0AFA7179ACDDD00C6B5A9 /* GLSpriteRenderer.cpp */, - E8E0AFA8179ACDDD00C6B5A9 /* GLSpriteRenderer.h */, - E8E44699179D2EDC00BE8855 /* GLSoftSpriteRenderer.cpp */, - E8E4469A179D2EDC00BE8855 /* GLSoftSpriteRenderer.h */, - E8E0AF881798278000C6B5A9 /* GLImageRenderer.cpp */, - E8E0AF891798278000C6B5A9 /* GLImageRenderer.h */, - E88318D6179176F3002ABE6D /* GLImageManager.cpp */, - E88318D7179176F3002ABE6D /* GLImageManager.h */, - E8567E741793D60E009D83E0 /* GLModelManager.cpp */, - E8567E751793D60E009D83E0 /* GLModelManager.h */, - E8567E7A1793E105009D83E0 /* GLModel.cpp */, - E8567E7B1793E105009D83E0 /* GLModel.h */, - E8567E7D1793E1B3009D83E0 /* GLVoxelModel.cpp */, - E8567E7E1793E1B3009D83E0 /* GLVoxelModel.h */, - E88318AF1790F73F002ABE6D /* GLMapRenderer.cpp */, - E88318B01790F73F002ABE6D /* GLMapRenderer.h */, - E88318B217911A73002ABE6D /* GLMapChunk.cpp */, - E88318B317911A73002ABE6D /* GLMapChunk.h */, - E89A648C17A11B4E00FDA893 /* GLModelRenderer.cpp */, - E89A648D17A11B4E00FDA893 /* GLModelRenderer.h */, - E80B286F17A4CA2B0056179E /* GLOptimizedVoxelModel.cpp */, - E80B287017A4CA2C0056179E /* GLOptimizedVoxelModel.h */, - E80B289717AA63FC0056179E /* GLWaterRenderer.cpp */, - E80B289817AA63FF0056179E /* GLWaterRenderer.h */, - E844886017CFB32B005105D0 /* GLLongSpriteRenderer.cpp */, - E844886117CFB32B005105D0 /* GLLongSpriteRenderer.h */, - E8B6B72C17E68B1B00E35523 /* GLSoftLitSpriteRenderer.cpp */, - E8B6B72D17E68B1B00E35523 /* GLSoftLitSpriteRenderer.h */, - E8B8082718E05B920001013E /* CellToTriangle.h */, - ); - name = "Client Object"; - sourceTree = ""; - }; - E8E44680179CC48B00BE8855 /* System */ = { - isa = PBXGroup; - children = ( - E85233791839B28C00F40541 /* VersionInfo.cpp */, - E852337A1839B28C00F40541 /* VersionInfo.h */, - E8CF03B0178EE300000683D4 /* Thread.cpp */, - E8CF03B1178EE300000683D4 /* Thread.h */, - E8CF03CF178EEF80000683D4 /* Semaphore.cpp */, - E8CF03D0178EEF80000683D4 /* Semaphore.h */, - E8CF03D5178EF09C000683D4 /* ILockable.cpp */, - E8CF03D6178EF09C000683D4 /* ILockable.h */, - E8CF03DE178EF4E9000683D4 /* IRunnable.cpp */, - E8CF03DF178EF4E9000683D4 /* IRunnable.h */, - E8CF0403178FF776000683D4 /* Exception.cpp */, - E8CF0404178FF776000683D4 /* Exception.h */, - E8567E5E1792C0FF009D83E0 /* DynamicLibrary.cpp */, - E8567E5F1792C0FF009D83E0 /* DynamicLibrary.h */, - E80B286C17A3B0570056179E /* ConcurrentDispatch.cpp */, - E80B286D17A3B0570056179E /* ConcurrentDispatch.h */, - E80B288B17A5FFB30056179E /* ThreadLocalStorage.cpp */, - E80B288C17A5FFB40056179E /* ThreadLocalStorage.h */, - E8C92A0D186A8D3600740C9F /* CpuID.h */, - E8C92A0E186A902500740C9F /* CpuID.cpp */, - ); - name = System; - sourceTree = ""; - }; - E8E44681179CC49C00BE8855 /* I/O */ = { - isa = PBXGroup; - children = ( - E8403CA9229123CF00093C3E /* PipeStream.cpp */, - E8403CAA229123CF00093C3E /* PipeStream.h */, - E8403CA6229061BE00093C3E /* RandomAccessAdaptor.cpp */, - E8403CA7229061BE00093C3E /* RandomAccessAdaptor.h */, - E8B6B72617E5AC9C00E35523 /* ServerAddress.cpp */, - E8B6B72717E5AC9C00E35523 /* ServerAddress.h */, - E8CF04091790471D000683D4 /* IFileSystem.cpp */, - E8CF040A1790471D000683D4 /* IFileSystem.h */, - E8CF040C17904970000683D4 /* FileManager.cpp */, - E8CF040D17904971000683D4 /* FileManager.h */, - E8CF040F17904ABC000683D4 /* IStream.cpp */, - E8CF041017904ABC000683D4 /* IStream.h */, - E8CF041217904E8B000683D4 /* StdStream.cpp */, - E8CF041317904E8C000683D4 /* StdStream.h */, - E849654E18E94F1200B9706D /* SdlFileStream.cpp */, - E849654F18E94F1200B9706D /* SdlFileStream.h */, - E8CF0415179052F6000683D4 /* DirectoryFileSystem.cpp */, - E8CF0416179052F7000683D4 /* DirectoryFileSystem.h */, - E834F55D17950E41004EBE88 /* DeflateStream.cpp */, - E834F55E17950E42004EBE88 /* DeflateStream.h */, - E834F56317951B1A004EBE88 /* MemoryStream.cpp */, - E834F56417951B1B004EBE88 /* MemoryStream.h */, - E80B28DC17B39EEE0056179E /* ZipFileSystem.cpp */, - E80B28DD17B39EEF0056179E /* ZipFileSystem.h */, - E80B28DF17B4FDD40056179E /* DynamicMemoryStream.cpp */, - E80B28E017B4FDD70056179E /* DynamicMemoryStream.h */, - ); - name = I/O; - sourceTree = ""; - }; - E8E44682179CC4A400BE8855 /* Media */ = { - isa = PBXGroup; - children = ( - E8403CB02299073400093C3E /* VoxelModelLoader.cpp */, - E8403CAF2299073400093C3E /* VoxelModelLoader.h */, - E8E44683179CC4DE00BE8855 /* Bitmap Codecs */, - E88318D3179172AF002ABE6D /* Bitmap.cpp */, - E88318D4179172AF002ABE6D /* Bitmap.h */, - E8567E771793DC37009D83E0 /* VoxelModel.cpp */, - E8567E781793DC37009D83E0 /* VoxelModel.h */, - E8567E611792CA12009D83E0 /* IAudioStream.cpp */, - E8567E621792CA12009D83E0 /* IAudioStream.h */, - E8567E641792CCE5009D83E0 /* WavAudioStream.cpp */, - E8567E651792CCE5009D83E0 /* WavAudioStream.h */, - E80B288617A52AB60056179E /* BitmapAtlasGenerator.cpp */, - E80B288717A52AB70056179E /* BitmapAtlasGenerator.h */, - E83668AD1E05757B00977A63 /* OpusAudioStream.cpp */, - E83668AE1E05757B00977A63 /* OpusAudioStream.h */, - E83668B01E05844E00977A63 /* AudioStream.cpp */, - E83668B11E05844E00977A63 /* AudioStream.h */, - ); - name = Media; - sourceTree = ""; - }; - E8E44683179CC4DE00BE8855 /* Bitmap Codecs */ = { - isa = PBXGroup; - children = ( - E895D66118D614DE00F5B9CA /* pnglite.c */, - E895D66218D614DE00F5B9CA /* pnglite.h */, - E895D66318D614DE00F5B9CA /* PngWriter.cpp */, - E895D65B18D4A10E00F5B9CA /* jpge.cpp */, - E895D65C18D4A10E00F5B9CA /* jpge.h */, - E8E44684179CC4FF00BE8855 /* IBitmapCodec.cpp */, - E8E44685179CC4FF00BE8855 /* IBitmapCodec.h */, - E8E44687179CC65900BE8855 /* TargaReader.cpp */, - E8E446A8179F822D00BE8855 /* TargaWriter.cpp */, - E87AB82118BB3957006B7D73 /* SdlImageReader.cpp */, - E895D65E18D4A15900F5B9CA /* JpegWriter.cpp */, - ); - name = "Bitmap Codecs"; - sourceTree = ""; - }; - E8E446AB17A02EC700BE8855 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - E84E221218BB449A001282B0 /* cmake */, - E844886717D262C1005105D0 /* CMakeLists.txt */, - E8EE08A217BA016F00631987 /* AUTHORS */, - E842D48B17C0D06300381B49 /* README.md */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - E82E66B818EA78F5004DBA18 /* OpenSpades */ = { - isa = PBXNativeTarget; - buildConfigurationList = E82E66E718EA78F5004DBA18 /* Build configuration list for PBXNativeTarget "OpenSpades" */; - buildPhases = ( - E82E66B518EA78F5004DBA18 /* Sources */, - E82E66B618EA78F5004DBA18 /* Frameworks */, - E82E67F218EA7E35004DBA18 /* ShellScript */, - E82E66B718EA78F5004DBA18 /* Resources */, - E874834818ED1BDD00C29033 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = OpenSpades; - productName = XSpades; - productReference = E82E66B918EA78F5004DBA18 /* OpenSpades.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - E8CF037D178ED9D2000683D4 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1010; - ORGANIZATIONNAME = yvt.jp; - TargetAttributes = { - E82E66B818EA78F5004DBA18 = { - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 0; - }; - }; - }; - }; - }; - buildConfigurationList = E8CF0380178ED9D2000683D4 /* Build configuration list for PBXProject "OpenSpades" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - en, - Base, - ); - mainGroup = E8CF037C178ED9D2000683D4; - productRefGroup = E8CF0386178ED9D2000683D4 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - E82E66B818EA78F5004DBA18 /* OpenSpades */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - E82E66B718EA78F5004DBA18 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E8690AEC1D3920C800DBC331 /* pak000-Nonfree.pak in Resources */, - E8690AED1D3920C800DBC331 /* pak002-Base.pak in Resources */, - E8690AEE1D3920C800DBC331 /* pak005-Models.pak in Resources */, - E8690AEF1D3920C800DBC331 /* pak010-BaseSkin.pak in Resources */, - E893A3651E3E4181000654A4 /* PackageInfo.json in Resources */, - E8690AF01D3920C800DBC331 /* pak050-Locales.pak in Resources */, - E8690AF11D3920C800DBC331 /* pak999-References.pak in Resources */, - E874834718EACF0300C29033 /* OpenSpades.icns in Resources */, - E82E680418EA7F60004DBA18 /* libysrspades.dylib in Resources */, - E82E67FA18EA7EAB004DBA18 /* font-unifont.pak in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - E82E67F218EA7E35004DBA18 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "cd Resources\n./mkpak.sh"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - E82E66B518EA78F5004DBA18 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - E82E67E318EA7A51004DBA18 /* ioapi.c in Sources */, - E82E67E418EA7A51004DBA18 /* unzip.c in Sources */, - E82E67E518EA7A51004DBA18 /* kiss_fft.c in Sources */, - E82E67E618EA7A51004DBA18 /* callbacks.c in Sources */, - E82E67E718EA7A51004DBA18 /* compress.c in Sources */, - E82E67E818EA7A51004DBA18 /* host.c in Sources */, - E82E67E918EA7A51004DBA18 /* list.c in Sources */, - E82E67EA18EA7A51004DBA18 /* packet.c in Sources */, - E8C7D7AE22DA34F500F78763 /* ConsoleHelper.cpp in Sources */, - E8C7D7AF22DA34F500F78763 /* ConsoleScreen.cpp in Sources */, - E82E67EB18EA7A51004DBA18 /* peer.c in Sources */, - E8403CAB229123CF00093C3E /* PipeStream.cpp in Sources */, - E81012311E1D7301009955D3 /* Icon.cpp in Sources */, - E8A2EBA01F5BE16D00E39CD9 /* GameProperties.cpp in Sources */, - E82E67EC18EA7A51004DBA18 /* protocol.c in Sources */, - E8C7D7B422DAF5B500F78763 /* ConsoleCommand.cpp in Sources */, - E82E67ED18EA7A51004DBA18 /* unix.c in Sources */, - E82E67EE18EA7A51004DBA18 /* win32.c in Sources */, - E82E67EF18EA7A51004DBA18 /* pnglite.c in Sources */, - E82E673318EA7972004DBA18 /* as_atomic.cpp in Sources */, - E8CB47CE1DE071CA00BF606A /* SWUtils.cpp in Sources */, - E82E673418EA7972004DBA18 /* as_builder.cpp in Sources */, - E82E673518EA7972004DBA18 /* as_bytecode.cpp in Sources */, - E82E673618EA7972004DBA18 /* as_callfunc.cpp in Sources */, - E82E673718EA7972004DBA18 /* as_callfunc_arm.cpp in Sources */, - E82E673818EA7972004DBA18 /* as_callfunc_mips.cpp in Sources */, - E82E673918EA7972004DBA18 /* as_callfunc_ppc.cpp in Sources */, - E82E673A18EA7972004DBA18 /* as_callfunc_ppc_64.cpp in Sources */, - E82E673B18EA7972004DBA18 /* as_callfunc_sh4.cpp in Sources */, - E82E673C18EA7972004DBA18 /* as_callfunc_x64_gcc.cpp in Sources */, - E82E673D18EA7972004DBA18 /* as_callfunc_x64_mingw.cpp in Sources */, - E82E673E18EA7972004DBA18 /* as_callfunc_x64_msvc.cpp in Sources */, - E82E673F18EA7972004DBA18 /* as_callfunc_x86.cpp in Sources */, - E82E674018EA7972004DBA18 /* as_callfunc_xenon.cpp in Sources */, - E82E674118EA7972004DBA18 /* as_compiler.cpp in Sources */, - E82E674218EA7972004DBA18 /* as_configgroup.cpp in Sources */, - E8403CA8229061BF00093C3E /* RandomAccessAdaptor.cpp in Sources */, - E82E674318EA7972004DBA18 /* as_context.cpp in Sources */, - E82E674418EA7972004DBA18 /* as_datatype.cpp in Sources */, - E82E674518EA7972004DBA18 /* as_gc.cpp in Sources */, - E8725DAD1DE33B4D003BC987 /* NoiseSampler.cpp in Sources */, - E82E674618EA7972004DBA18 /* as_generic.cpp in Sources */, - E82E674718EA7972004DBA18 /* as_globalproperty.cpp in Sources */, - E8EF8B571E1D70D900E0829C /* SplashWindow.cpp in Sources */, - E82E674818EA7972004DBA18 /* as_memory.cpp in Sources */, - E82E674918EA7972004DBA18 /* as_module.cpp in Sources */, - E82E674A18EA7972004DBA18 /* as_objecttype.cpp in Sources */, - E82E674B18EA7972004DBA18 /* as_outputbuffer.cpp in Sources */, - E82E674C18EA7972004DBA18 /* as_parser.cpp in Sources */, - E8C7D7C022DB3AE000F78763 /* ConsoleCommandCandidate.cpp in Sources */, - E82E674D18EA7972004DBA18 /* as_restore.cpp in Sources */, - E82E674E18EA7972004DBA18 /* as_scriptcode.cpp in Sources */, - E8C7D7BE22DB2A4400F78763 /* ConsoleCommandCandidate.cpp in Sources */, - E82E674F18EA7972004DBA18 /* as_scriptengine.cpp in Sources */, - E82E675018EA7972004DBA18 /* as_scriptfunction.cpp in Sources */, - E82E675118EA7972004DBA18 /* as_scriptnode.cpp in Sources */, - E82E675218EA7972004DBA18 /* as_scriptobject.cpp in Sources */, - E82E675318EA7972004DBA18 /* as_string.cpp in Sources */, - E82E675418EA7972004DBA18 /* as_string_util.cpp in Sources */, - E82E675518EA7972004DBA18 /* as_thread.cpp in Sources */, - E8CB47D21DE07CF000BF606A /* SettingSet.cpp in Sources */, - E82E675618EA7972004DBA18 /* as_tokenizer.cpp in Sources */, - E82E675718EA7972004DBA18 /* as_typeinfo.cpp in Sources */, - E82E675818EA7972004DBA18 /* as_variablescope.cpp in Sources */, - E82E675918EA7972004DBA18 /* ALDevice.cpp in Sources */, - E82E675A18EA7972004DBA18 /* ALFuncs.cpp in Sources */, - E82E675B18EA7972004DBA18 /* YsrDevice.cpp in Sources */, - E82E675C18EA7972004DBA18 /* NullDevice.cpp in Sources */, - E8403CB12299073400093C3E /* VoxelModelLoader.cpp in Sources */, - E82E675D18EA7972004DBA18 /* PngWriter.cpp in Sources */, - E82E675E18EA7972004DBA18 /* jpge.cpp in Sources */, - E82E675F18EA7972004DBA18 /* IBitmapCodec.cpp in Sources */, - E82E676018EA7972004DBA18 /* TargaReader.cpp in Sources */, - E82E676118EA7972004DBA18 /* TargaWriter.cpp in Sources */, - E82E676218EA7972004DBA18 /* SdlImageReader.cpp in Sources */, - E82E676318EA7972004DBA18 /* JpegWriter.cpp in Sources */, - E82E676418EA7972004DBA18 /* Bitmap.cpp in Sources */, - E82E676518EA7972004DBA18 /* VoxelModel.cpp in Sources */, - E82E676618EA7972004DBA18 /* IAudioStream.cpp in Sources */, - E82E676718EA7972004DBA18 /* WavAudioStream.cpp in Sources */, - E82E676818EA7972004DBA18 /* BitmapAtlasGenerator.cpp in Sources */, - E82E676918EA7972004DBA18 /* ServerAddress.cpp in Sources */, - E82E676A18EA7972004DBA18 /* IFileSystem.cpp in Sources */, - E82E676B18EA7972004DBA18 /* FileManager.cpp in Sources */, - E82E676C18EA7972004DBA18 /* IStream.cpp in Sources */, - E82E676D18EA7972004DBA18 /* StdStream.cpp in Sources */, - E82E676E18EA7972004DBA18 /* SdlFileStream.cpp in Sources */, - E82E676F18EA7972004DBA18 /* DirectoryFileSystem.cpp in Sources */, - E82E677018EA7972004DBA18 /* DeflateStream.cpp in Sources */, - E82E677118EA7972004DBA18 /* MemoryStream.cpp in Sources */, - E82E677218EA7972004DBA18 /* ZipFileSystem.cpp in Sources */, - E82E677318EA7972004DBA18 /* DynamicMemoryStream.cpp in Sources */, - E82E677418EA7972004DBA18 /* VersionInfo.cpp in Sources */, - E82E677518EA7972004DBA18 /* Thread.cpp in Sources */, - E82E677618EA7972004DBA18 /* Semaphore.cpp in Sources */, - E82E677818EA7972004DBA18 /* ILockable.cpp in Sources */, - E82E677A18EA7972004DBA18 /* IRunnable.cpp in Sources */, - E82E677B18EA7972004DBA18 /* Exception.cpp in Sources */, - E82E677C18EA7972004DBA18 /* DynamicLibrary.cpp in Sources */, - E82E677D18EA7972004DBA18 /* ConcurrentDispatch.cpp in Sources */, - E82E677E18EA7972004DBA18 /* ThreadLocalStorage.cpp in Sources */, - E82E677F18EA7972004DBA18 /* CpuID.cpp in Sources */, - E82E678018EA7972004DBA18 /* MathScript.cpp in Sources */, - E82E678118EA7972004DBA18 /* StringsScript.cpp in Sources */, - E82E678218EA7972004DBA18 /* ScriptManager.cpp in Sources */, - E82E678318EA7972004DBA18 /* IImage.cpp in Sources */, - E82E678418EA7972004DBA18 /* IModel.cpp in Sources */, - E89BBDC31B3559CD00F53EE9 /* GLAutoExposureFilter.cpp in Sources */, - E82E678518EA7972004DBA18 /* IRenderer.cpp in Sources */, - E82E678618EA7972004DBA18 /* GameMap.cpp in Sources */, - E82E678718EA7972004DBA18 /* Bitmap.cpp in Sources */, - E82E678818EA7972004DBA18 /* VoxelModel.cpp in Sources */, - E82E678918EA7972004DBA18 /* IAudioDevice.cpp in Sources */, - E82E678A18EA7972004DBA18 /* IAudioChunk.cpp in Sources */, - E82E678B18EA7972004DBA18 /* PrimitiveArray.cpp in Sources */, - E82E678C18EA7972004DBA18 /* IToolSkin.cpp in Sources */, - E82E678D18EA7972004DBA18 /* ScriptFunction.cpp in Sources */, - E82E678E18EA7972004DBA18 /* ISpadeSkin.cpp in Sources */, - E82E678F18EA7972004DBA18 /* IBlockSkin.cpp in Sources */, - E82E679018EA7972004DBA18 /* IViewToolSkin.cpp in Sources */, - E82E679118EA7972004DBA18 /* IThirdPersonToolSkin.cpp in Sources */, - E82E679218EA7972004DBA18 /* IGrenadeSkin.cpp in Sources */, - E82E679318EA7972004DBA18 /* IWeaponSkin.cpp in Sources */, - E82E679418EA7972004DBA18 /* IFont.cpp in Sources */, - E82E679518EA7972004DBA18 /* MainScreenHelper.cpp in Sources */, - E8D0E5D318F321E300DE3BDB /* GLNonlinearizeFilter.cpp in Sources */, - E82E679618EA7972004DBA18 /* StartupScreenHelper.cpp in Sources */, - E82E679718EA7972004DBA18 /* Config.cpp in Sources */, - E82E679818EA7972004DBA18 /* ClientUIHelper.cpp in Sources */, - E82E679918EA7972004DBA18 /* Clipboard.cpp in Sources */, - E82E679A18EA7972004DBA18 /* Math.cpp in Sources */, - E89A5F1E1DF8732200857F65 /* ShellApi.cpp in Sources */, - E82E679B18EA7972004DBA18 /* Deque.cpp in Sources */, - E82E679C18EA7972004DBA18 /* Stopwatch.cpp in Sources */, - E82E679D18EA7972004DBA18 /* Debug.cpp in Sources */, - E82E679E18EA7972004DBA18 /* Settings.cpp in Sources */, - E82E679F18EA7972004DBA18 /* FltkPreferenceImporter.cpp in Sources */, - E82E67A018EA7972004DBA18 /* RefCountedObject.cpp in Sources */, - E82E67A118EA7972004DBA18 /* MiniHeap.cpp in Sources */, - E82E67A218EA7972004DBA18 /* CP437.cpp in Sources */, - E82E67A318EA7972004DBA18 /* Strings.cpp in Sources */, - E82E67A418EA7972004DBA18 /* IRenderer.cpp in Sources */, - E82E67A518EA7972004DBA18 /* SceneDefinition.cpp in Sources */, - E82E67A618EA7972004DBA18 /* IAudioDevice.cpp in Sources */, - E89A5F201DF8759200857F65 /* ShellApi.mm in Sources */, - E82E67A718EA7972004DBA18 /* IAudioChunk.cpp in Sources */, - E82E67A818EA7972004DBA18 /* IInputInterface.cpp in Sources */, - E82E67A918EA7972004DBA18 /* IImage.cpp in Sources */, - E82E67AA18EA7972004DBA18 /* IModel.cpp in Sources */, - E82E67AC18EA7972004DBA18 /* NetClient.cpp in Sources */, - E82E67AD18EA7972004DBA18 /* ILocalEntity.cpp in Sources */, - E82E67AE18EA7972004DBA18 /* ParticleSpriteEntity.cpp in Sources */, - E82E67AF18EA7972004DBA18 /* SmokeSpriteEntity.cpp in Sources */, - E82E67B018EA7972004DBA18 /* FallingBlock.cpp in Sources */, - E82E67B118EA7972004DBA18 /* GunCasing.cpp in Sources */, - E82E67B218EA7972004DBA18 /* Tracer.cpp in Sources */, - E82E67B318EA7972004DBA18 /* ClientPlayer.cpp in Sources */, - E82E67B418EA7972004DBA18 /* Client.cpp in Sources */, - E82E67B518EA7972004DBA18 /* Client_Input.cpp in Sources */, - E82E67B618EA7972004DBA18 /* Client_Update.cpp in Sources */, - E8F6E6E71DCF503500FE76BB /* MumbleLink.cpp in Sources */, - E82E67B718EA7972004DBA18 /* Client_NetHandler.cpp in Sources */, - E82E67B818EA7972004DBA18 /* Client_LocalEnts.cpp in Sources */, - E82E67B918EA7972004DBA18 /* Client_Draw.cpp in Sources */, - E809500A1E17F66500AECDF2 /* GLSSAOFilter.cpp in Sources */, - E82E67BA18EA7972004DBA18 /* Client_Scene.cpp in Sources */, - E82E67BB18EA7972004DBA18 /* Client_FPSCounter.cpp in Sources */, - E82E67BC18EA7972004DBA18 /* ChatWindow.cpp in Sources */, - E82E67BD18EA7972004DBA18 /* Corpse.cpp in Sources */, - E82E67BE18EA7972004DBA18 /* CenterMessageView.cpp in Sources */, - E82E67BF18EA7972004DBA18 /* HurtRingView.cpp in Sources */, - E82E67C018EA7972004DBA18 /* MapView.cpp in Sources */, - E82E67C118EA7972004DBA18 /* ScoreboardView.cpp in Sources */, - E82E67C218EA7972004DBA18 /* LimboView.cpp in Sources */, - E82E67C318EA7972004DBA18 /* PaletteView.cpp in Sources */, - E82E67C418EA7972004DBA18 /* TCProgressView.cpp in Sources */, - E82E67C518EA7972004DBA18 /* ClientUI.cpp in Sources */, - E82E67C618EA7972004DBA18 /* ClientUIHelper.cpp in Sources */, - E82E67C718EA7972004DBA18 /* Quake3Font.cpp in Sources */, - E82E67C818EA7972004DBA18 /* IFont.cpp in Sources */, - E82E67C918EA7972004DBA18 /* Fonts.cpp in Sources */, - E82E67CA18EA7972004DBA18 /* IGameMode.cpp in Sources */, - E82E67CB18EA7972004DBA18 /* CTFGameMode.cpp in Sources */, - E8403CAE2291280800093C3E /* GameMapLoader.cpp in Sources */, - E82E67CC18EA7972004DBA18 /* TCGameMode.cpp in Sources */, - E82E67CD18EA7972004DBA18 /* Player.cpp in Sources */, - E82E67CE18EA7972004DBA18 /* Grenade.cpp in Sources */, - E82E67CF18EA7972004DBA18 /* Weapon.cpp in Sources */, - E82E67D018EA7972004DBA18 /* GameMap.cpp in Sources */, - E82E67D118EA7972004DBA18 /* IGameMapListener.cpp in Sources */, - E82E67D218EA7972004DBA18 /* GameMapWrapper.cpp in Sources */, - E8655AA81DFC0A6E00D5058A /* FTFont.cpp in Sources */, - E82E67D318EA7972004DBA18 /* World.cpp in Sources */, - E82E67D418EA7972004DBA18 /* IWorldListener.cpp in Sources */, - E82E67D518EA7972004DBA18 /* HitTestDebugger.cpp in Sources */, - E82E67D618EA7972004DBA18 /* SWRenderer.cpp in Sources */, - E82E67D718EA7972004DBA18 /* SWPort.cpp in Sources */, - E82E67D818EA7972004DBA18 /* SWImage.cpp in Sources */, - E82E67D918EA7972004DBA18 /* SWModel.cpp in Sources */, - E82E67DA18EA7972004DBA18 /* SWImageRenderer.cpp in Sources */, - E82E67DB18EA7972004DBA18 /* SWFeatureLevel.cpp in Sources */, - E893A3611E3E141D000654A4 /* PackageUpdateManager.cpp in Sources */, - E82E67DC18EA7972004DBA18 /* SWMapRenderer.cpp in Sources */, - E82E67DD18EA7972004DBA18 /* SWFlatMapRenderer.cpp in Sources */, - E82E67DE18EA7972004DBA18 /* SWModelRenderer.cpp in Sources */, - E83668B21E05844E00977A63 /* AudioStream.cpp in Sources */, - E82E672518EA7967004DBA18 /* json_reader.cpp in Sources */, - E82E672618EA7967004DBA18 /* json_value.cpp in Sources */, - E82E672718EA7967004DBA18 /* json_writer.cpp in Sources */, - E82E672818EA7967004DBA18 /* scriptany.cpp in Sources */, - E82E672918EA7967004DBA18 /* scriptarray.cpp in Sources */, - E83668AF1E05757B00977A63 /* OpusAudioStream.cpp in Sources */, - E82E672A18EA7967004DBA18 /* scriptbuilder.cpp in Sources */, - E82E672B18EA7967004DBA18 /* scriptdictionary.cpp in Sources */, - E82E672C18EA7967004DBA18 /* scripthandle.cpp in Sources */, - E82E672D18EA7967004DBA18 /* scripthelper.cpp in Sources */, - E82E672E18EA7967004DBA18 /* scriptmath.cpp in Sources */, - E82E672F18EA7967004DBA18 /* scriptmathcomplex.cpp in Sources */, - E82E673018EA7967004DBA18 /* scriptstdstring.cpp in Sources */, - E82E673118EA7967004DBA18 /* scriptstdstring_utils.cpp in Sources */, - E82E673218EA7967004DBA18 /* weakref.cpp in Sources */, - E82E66EE18EA7954004DBA18 /* GLBloomFilter.cpp in Sources */, - E82E66EF18EA7954004DBA18 /* GLQuadRenderer.cpp in Sources */, - E82E66F018EA7954004DBA18 /* GLLensFilter.cpp in Sources */, - E82E66F118EA7954004DBA18 /* GLCameraBlurFilter.cpp in Sources */, - E82E66F218EA7954004DBA18 /* GLFogFilter.cpp in Sources */, - E8C7D7C222DB636000F78763 /* Client_Console.cpp in Sources */, - E82E66F318EA7954004DBA18 /* GLLensFlareFilter.cpp in Sources */, - E82E66F418EA7954004DBA18 /* GLFXAAFilter.cpp in Sources */, - E8CB47D61DE084AB00BF606A /* GLSettings.cpp in Sources */, - E82E66F518EA7954004DBA18 /* GLColorCorrectionFilter.cpp in Sources */, - E82E66F618EA7954004DBA18 /* GLDepthOfFieldFilter.cpp in Sources */, - E82E66F718EA7954004DBA18 /* GLLensDustFilter.cpp in Sources */, - E82E66F818EA7954004DBA18 /* GLImage.cpp in Sources */, - E82E66F918EA7954004DBA18 /* GLFlatMapRenderer.cpp in Sources */, - E82E66FA18EA7954004DBA18 /* IGLSpriteRenderer.cpp in Sources */, - E82E66FB18EA7954004DBA18 /* GLSpriteRenderer.cpp in Sources */, - E82E66FC18EA7954004DBA18 /* GLSoftSpriteRenderer.cpp in Sources */, - E82E66FD18EA7954004DBA18 /* GLImageRenderer.cpp in Sources */, - E82E66FE18EA7954004DBA18 /* GLImageManager.cpp in Sources */, - E82E66FF18EA7954004DBA18 /* GLModelManager.cpp in Sources */, - E82E670018EA7954004DBA18 /* GLModel.cpp in Sources */, - E82E670118EA7954004DBA18 /* GLVoxelModel.cpp in Sources */, - E82E670218EA7954004DBA18 /* GLMapRenderer.cpp in Sources */, - E82E670318EA7954004DBA18 /* GLMapChunk.cpp in Sources */, - E82E670418EA7954004DBA18 /* GLModelRenderer.cpp in Sources */, - E82E670518EA7954004DBA18 /* GLOptimizedVoxelModel.cpp in Sources */, - E82E670618EA7954004DBA18 /* GLWaterRenderer.cpp in Sources */, - E82E670718EA7954004DBA18 /* GLLongSpriteRenderer.cpp in Sources */, - E82E670818EA7954004DBA18 /* GLSoftLitSpriteRenderer.cpp in Sources */, - E82E670918EA7954004DBA18 /* GLShader.cpp in Sources */, - E8C7D7B122DA35F000F78763 /* ConsoleHelper.cpp in Sources */, - E82E670A18EA7954004DBA18 /* GLProgramUniform.cpp in Sources */, - E82E670B18EA7954004DBA18 /* GLProgramAttribute.cpp in Sources */, - E82E670C18EA7954004DBA18 /* GLProgram.cpp in Sources */, - E82E670D18EA7954004DBA18 /* GLMapShadowRenderer.cpp in Sources */, - E82E670E18EA7954004DBA18 /* GLShadowShader.cpp in Sources */, - E82E670F18EA7954004DBA18 /* GLDynamicLightShader.cpp in Sources */, - E82E671018EA7954004DBA18 /* IGLShadowMapRenderer.cpp in Sources */, - E82E671118EA7954004DBA18 /* GLShadowMapShader.cpp in Sources */, - E82E671218EA7954004DBA18 /* GLBasicShadowMapRenderer.cpp in Sources */, - E82E671318EA7954004DBA18 /* GLDynamicLight.cpp in Sources */, - E82E671418EA7954004DBA18 /* GLAmbientShadowRenderer.cpp in Sources */, - E82E671518EA7954004DBA18 /* GLRadiosityRenderer.cpp in Sources */, - E82E671618EA7954004DBA18 /* GLSparseShadowMapRenderer.cpp in Sources */, - E82E671718EA7954004DBA18 /* GLRenderer.cpp in Sources */, - E82E671818EA7954004DBA18 /* IGLDevice.cpp in Sources */, - E82E671918EA7954004DBA18 /* GLFramebufferManager.cpp in Sources */, - E82E671A18EA7954004DBA18 /* GLProgramManager.cpp in Sources */, - E82E671B18EA7954004DBA18 /* GLProfiler.cpp in Sources */, - E82E671C18EA7954004DBA18 /* Main.cpp in Sources */, - E82E671D18EA7954004DBA18 /* SDLGLDevice.cpp in Sources */, - E82E671E18EA7954004DBA18 /* SDLRunner.cpp in Sources */, - E82E672018EA7954004DBA18 /* MainScreen.cpp in Sources */, - E82E672118EA7954004DBA18 /* MainScreenHelper.cpp in Sources */, - E82E672218EA7954004DBA18 /* View.cpp in Sources */, - E88344101E03244F000C3E39 /* FontManager.cpp in Sources */, - E893A3631E3E3331000654A4 /* PackageUpdateManager.cpp in Sources */, - E82E672318EA7954004DBA18 /* Runner.cpp in Sources */, - E8C7D7BA22DB220300F78763 /* ConfigConsoleResponder.cpp in Sources */, - E82E672418EA7954004DBA18 /* StartupScreen.cpp in Sources */, - E82E66ED18EA7914004DBA18 /* StartupScreenHelper.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - E82E66E818EA78F5004DBA18 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Sources/Externals/lib", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - HEADER_SEARCH_PATHS = ( - Sources/Externals/lib/SDL2.framework/Headers, - Sources/Externals/lib/SDL2_image.framework/Headers, - Sources/Externals/include, - Sources/ENet/include, - "$(SRCROOT)", - Sources, - Sources/json/include, - Sources/Externals/include/opus, - ); - INFOPLIST_FILE = "XSpades/XSpades-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Sources/Externals/lib", - ); - PRODUCT_BUNDLE_IDENTIFIER = "jp.yvt.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - E82E66E918EA78F5004DBA18 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Sources/Externals/lib", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ""; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - HEADER_SEARCH_PATHS = ( - Sources/Externals/lib/SDL2.framework/Headers, - Sources/Externals/lib/SDL2_image.framework/Headers, - Sources/Externals/include, - Sources/ENet/include, - "$(SRCROOT)", - Sources, - Sources/json/include, - Sources/Externals/include/opus, - ); - INFOPLIST_FILE = "XSpades/XSpades-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Sources/Externals/lib", - ); - PRODUCT_BUNDLE_IDENTIFIER = "jp.yvt.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - E8CF038C178ED9D2000683D4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(NATIVE_ARCH_ACTUAL)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = NO; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ""; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - "HAS_SOCKLEN_T=1", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ""; - LIBRARY_SEARCH_PATHS = ""; - MACOSX_DEPLOYMENT_TARGET = 10.12; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - USER_HEADER_SEARCH_PATHS = ""; - }; - name = Debug; - }; - E8CF038D178ED9D2000683D4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(NATIVE_ARCH_ACTUAL)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = NO; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ""; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 3; - GCC_PREPROCESSOR_DEFINITIONS = ( - "NDEBUG=1", - "HAS_SOCKLEN_T=1", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ""; - LIBRARY_SEARCH_PATHS = ""; - MACOSX_DEPLOYMENT_TARGET = 10.12; - SDKROOT = macosx; - USER_HEADER_SEARCH_PATHS = ""; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - E82E66E718EA78F5004DBA18 /* Build configuration list for PBXNativeTarget "OpenSpades" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E82E66E818EA78F5004DBA18 /* Debug */, - E82E66E918EA78F5004DBA18 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E8CF0380178ED9D2000683D4 /* Build configuration list for PBXProject "OpenSpades" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E8CF038C178ED9D2000683D4 /* Debug */, - E8CF038D178ED9D2000683D4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = E8CF037D178ED9D2000683D4 /* Project object */; -} diff --git a/OpenSpades.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/OpenSpades.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 0b41a0f30..000000000 --- a/OpenSpades.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/README.md b/README.md index d847024bb..60c9b23af 100644 --- a/README.md +++ b/README.md @@ -37,22 +37,40 @@ flatpak install flathub jp.yvt.OpenSpades Once installed, you'll be able to launch OpenSpades from inside the desktop menu or from your terminal with `flatpak run jp.yvt.OpenSpades` -#### Building and installing from source -GCC 4.9 / Clang 3.2 or later is recommended because OpenSpades relies on C++11 features heavily. +### On Unixes (from source) +#### Building 1. Install dependencies: *On Debian-derived distributions*: ``` - sudo apt-get install pkg-config libglew-dev libcurl3-openssl-dev libsdl2-dev \ + sudo apt-get install build-essential pkg-config libglew-dev libcurl4-openssl-dev libsdl2-dev \ libsdl2-image-dev libalut-dev xdg-utils libfreetype6-dev libopus-dev \ - libopusfile-dev cmake imagemagick + libopusfile-dev cmake imagemagick zip unzip ``` (because of a bug in some distributions, you might also have to install more packages by `sudo apt-get install libjpeg-dev libxinerama-dev libxft-dev`) + + *On Fedora or other RHEL-derived distributions*: + ``` + sudo dnf install make automake gcc gcc-c++ kernel-devel pkgconf-pkg-config glew-devel \ + openssl-devel libcurl-devel SDL2-devel SDL2_image-devel \ + freealut-devel xdg-utils freetype-devel opus-devel opusfile-devel \ + libjpeg-devel libXinerama-devel libXft-devel cmake ImageMagick \ + zip unzip + ``` + + *On FreeBSD*: + ``` + sudo pkg install gmake automake pkgconf glew openssl curl sdl2 sdl2-image \ + freealut xdg-utils freetype2 opus opusfile jpeg-turbo libXinerama libXft \ + cmake ImageMagick7 zip unzip + ``` *On other distributions*: Install corresponding packages from your repository (or compile from source). + + Building OpenSpades requires a C++ compiler, which is included in the dependencies above in case you don't have one installed yet. 2. Clone OpenSpades repository: @@ -68,16 +86,58 @@ GCC 4.9 / Clang 3.2 or later is recommended because OpenSpades relies on C++11 f cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo && make ``` -4. Install OpenSpades (optional but recommended): +#### Installing and launching - `sudo make install` +To launch the built game without installing: +``` +cd $REPO_DIRECTORY/openspades.mk; bin/openspades +``` - **note**: If you have a previous installation of OpenSpades, you have to uninstall it manually by `sudo rm -rf /usr/local/share/games/openspades` before installing a new one. +To install the game to your system (recommended), take the following steps: + 1. Execute the following command: + ``` + sudo make install + ``` + **note**: If you have a previous installation of OpenSpades, you have to uninstall it manually by `sudo rm -rf /usr/local/share/games/openspades` before installing a new one, or else it might load old resources. -5. Launch: + 2. Launch the game by typing `openspades` into command line, or search for it from start menu. + +Alternatively, to install the game to a different directory, take the following steps: + + 1. Copy the Resources directory into bin (or else the game won't launch): + + ``` + cp -r ./Resources ./bin/ + ``` + **note**: If you plan on distributing it, remember to remove CMake files and folders from Resources. + + 2. Move the "/openspades.mk" folder somewhere else, for example `/home/user/Games`, or `/opt/games` and rename it to "/OpenSpades". + + 3. The game's launcher is located at `bin/openspades`. You can create a shortcut for it on the desktop or a `.desktop` file placed in `/usr/share/applications/` for it to appear in Start Menu. Make sure to set the `bin` directory as the shortcut's working directory, or else you will get an error about missing resources. + + **note**: If you choose a directory outside of your `/home/user`, for example `/opt/games`, remember to *chmod* the game launcher's permissions to 755. + +After successful installation, optionally you can remove the source code and build outputs to save disk space (~100MB). + +#### On Linux (from source, by Nix Flakes) +To build and run OpenSpades from the latest source code: + +```bash +nix shell github:yvt/openspades -c openspades +``` - `openspades` (if installed) or `cd $REPO_DIRECTORY/openspades.mk; bin/OpenSpades` and enjoy +To build and run OpenSpades for development: +```bash +git clone https://github.com/yvt/openspades.git && cd openspades +nix develop +# note: this will patch CMake files in the source tree +cmakeBuildType=RelWithDebInfo cmakeConfigurePhase +buildPhase +bin/openspades +``` + +**note**: Nix Flakes are an experimental feature of Nix and must be enabled manually. See [this wiki article](https://nixos.wiki/wiki/Flakes) for how to do that. ### On Windows (with Visual Studio) 1. Get the required software if you haven't already: @@ -85,41 +145,106 @@ GCC 4.9 / Clang 3.2 or later is recommended because OpenSpades relies on C++11 f * PowerShell 5.0 * Integrated with Windows 10. * Older versions are not tested, but might work - * *Visual Studio 2017* + * *Visual Studio 2017* or later * VS2015 is also supported, but VS2017 is more recommended * VS2013 is no longer supported, but might work 2. Grab the source code: * Stable version: https://github.com/yvt/openspades/releases * Latest development version (0.1.x): https://github.com/yvt/openspades/archive/master.zip -3. Extract or checkout the source +3. Checkout the source * All examples will assume `E:/Projects/openspades`, update paths in the examples to reflect yours -4. Get (pre-compiled) copies of glew, curl, sdl2 and zlib, and place them in `E:/Projects/openspades/Sources/Externals` - * See the file `E:/Projects/openspades/Sources/Externals/readme.txt` for details and links to pre-compiled sets of libraries for your version of Visual Studio + * Make sure to update all git submodules, e.g., by `git clone ... --recurse-submodules`). Note that the GitHub website's ZIP download currently does not support submodules. +4. Build libraries using vcpkg: + ```bat + cd E:\Projects\openspades + vcpkg\bootstrap-vcpkg.bat + vcpkg\vcpkg install @vcpkg_x86-windows.txt + ``` + 5. Run CMake: - * Source: `E:/Projects/openspades` - * Binaries: `E:/Projects/openspades/OpenSpades.msvc` + * Source: `E:\Projects\openspades` + * Binaries: `E:\Projects\openspades\OpenSpades.msvc` * Generator: - * For VS2017: `Visual Studio 15 (2017)` (not Win64!) - * For VS2015: `Visual Studio 14 (2015)` (not Win64!) - -6. Open `E:/Projects/openspades/OpenSpades.msvc/OpenSpades.sln` in Visual Studio. + * For VS2019: `Visual Studio 16 (2019)` + * For VS2017: `Visual Studio 15 (2017)` + * For VS2015: `Visual Studio 14 (2015)` + * Platform: `Win32` + * Toolchain file: `E:\Projects\openspades\vcpkg\scripts\buildsystems\vcpkg.cmake` + * Add a new string entry `VCPKG_TARGET_TRIPLET=x86-windows-static` + +6. Open `E:\Projects\openspades\OpenSpades.msvc\OpenSpades.sln` in Visual Studio. 7. Build the solution. * The recommended build configuration is `MinSizeRel` or `Release` if you're not an developer - * The default build output directory is `E:/projects/OpenSpades/OpenSpades.msvc/bin/BUILD_TYPE/` -8. Copy all `.dll` files from `Source/Externals/lib` to the build output directory. -9. To get audio working, download a [Windows release of OpenSpades](https://github.com/yvt/openspades/releases), extract it, and copy the following dlls to the build output directory: + * The default build output directory is `E:\projects\OpenSpades\OpenSpades.msvc\bin\BUILD_TYPE\` +8. To get audio working, download a [Windows release of OpenSpades](https://github.com/yvt/openspades/releases), extract it, and copy the following dlls to the build output directory: * For OpenAL audio: `openal32.dll` * For YSR audio: `YSRSpades.dll`, `libgcc_s_dw2-1.dll`, `libstdc++-6.dll`, `pthreadGC2.dll` -10. Download the [Non-free pak](https://github.com/yvt/openspades-paks/releases/download/r33/OpenSpadesDevPackage-r33.zip), extract it, and copy `Nonfree/pak000-Nonfree.pak` to the `Resources` folder inside your build output directory, which is probably `E:/Projects/openspades/openspades.msvc/bin/BUILD_TYPE/Resources`. You can also copy the paks contained in `Official Mods/` folder of OpenSpades 0.0.12b to add more fonts and improve localization support of your build. -11. Copy `Resources/PackageInfo.json` to the `Resources` folder inside your build output directory. - -### On macOS (with Xcode) -1. Get the latest version of Xcode and OpenSpades source. -2. Get (pre-compiled) copies of libraries, and place them in `Sources/Externals` - * See the file `Sources/Externals/readme.txt` for details -4. Download [macOS release of OpenSpades](https://github.com/yvt/openspades/releases), show the package contents, and copy `libysrspades.dylib` to `Sources/Externals/lib`. -5. Download and extract the [Non-free pak](https://github.com/yvt/openspades-paks/releases/download/r33/OpenSpadesDevPackage-r33.zip). After that, copy `Nonfree/pak000-Nonfree.pak` and `font-unifont.pak` to `Resources/`. -6. Open `OpenSpades.xcodeproj` and build. +9. Download the [Non-free pak](https://github.com/yvt/openspades-paks/releases/download/r33/OpenSpadesDevPackage-r33.zip), extract it, and copy `Nonfree\pak000-Nonfree.pak` to the `Resources` folder inside your build output directory, which is probably `E:\Projects\openspades\openspades.msvc\bin\BUILD_TYPE\Resources`. You can also copy the paks contained in `Official Mods` folder of OpenSpades 0.0.12b to add more fonts and improve localization support of your build. + +### On macOS (with Ninja) + +#### Requirements +- Xcode Command Line Tools +- CMake +- pkg-config +- gcc 6 or newer (not clang!) — macOS 10.14 (Mojave) or earlier only +- ninja + +#### Building +1. Install the Xcode Command Line Tools and other required build tools. + + ```bash + xcode-select --install + ``` + Using Homebrew: + ``` + brew install cmake pkg-config ninja + + # If you are using macOS 10.14 (Mojave) or earlier: + brew install gcc + ``` + Using Nix: + - Add `$(nix-build '' -A pkg-config-unwrapped --no-out-link)/bin` to `PATH`. + + +2. Clone the Openspades repository: + + ```bash + git clone https://github.com/yvt/openspades.git --recurse-submodules && cd openspades + ``` + +3. Bootstrap `vcpkg` and install the required packages: + + ```bash + vcpkg/bootstrap-vcpkg.sh + vcpkg/vcpkg install @vcpkg_x86_64-darwin.txt + ``` + +4. Create directory `openspades.mk` in the cloned/downloaded openspades repo and compile: + + ```bash + mkdir openspades.mk + cd openspades.mk + cmake -G Ninja .. -D CMAKE_BUILD_TYPE=RelWithDebInfo -D CMAKE_OSX_ARCHITECTURES=x86_64 -D CMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -D VCPKG_TARGET_TRIPLET=x64-osx + ninja + ``` + +5. Launch: + + ```bash + open bin/OpenSpades.app + ``` + + (Universal builds aren't supported yet.) + +### Network usage during building + +OpenSpades' build process automatically downloads prebuilt game assets and libraries as needed. Specifically: + +- `pak000-Nonfree.pak` and `font-uniform.pak` from . Can be disabled by passing `-D OPENSPADES_NONFREE_RESOURCES=NO` to CMake. +- The prebuilt binaries of YSRSpades (audio engine) from . Can be disabled by passing `-D OPENSPADES_YSR=NO` to CMake. + +In addition, vcpkg (sort of package manager only used for Windows and macOS builds) [collects and sends telemetry data to Microsoft](https://vcpkg.readthedocs.io/en/latest/about/privacy/). You can opt out of this behavior by passing `-disableMetrics` option when running `vcpkg/bootstrap-vcpkg.sh` command. ## Troubleshooting For troubleshooting and common problems see [TROUBLESHOOTING](TROUBLESHOOTING.md). diff --git a/Resources/CMakeLists.txt b/Resources/CMakeLists.txt index b24e7384a..adf307f31 100644 --- a/Resources/CMakeLists.txt +++ b/Resources/CMakeLists.txt @@ -1,57 +1,117 @@ +set(COMPILED_PAK_FILES + ${CMAKE_CURRENT_BINARY_DIR}/pak002-Base.pak + ${CMAKE_CURRENT_BINARY_DIR}/pak005-Models.pak + ${CMAKE_CURRENT_BINARY_DIR}/pak010-BaseSkin.pak + ${CMAKE_CURRENT_BINARY_DIR}/pak050-Locales.pak + ${CMAKE_CURRENT_BINARY_DIR}/pak999-References.pak) -if(OPENSPADES_RESOURCES) +if(OPENSPADES_RESOURCES AND OPENSPADES_NONFREE_RESOURCES) + set(NONFREE_PAK_FILES + ${CMAKE_CURRENT_BINARY_DIR}/pak000-Nonfree.pak + ${CMAKE_CURRENT_BINARY_DIR}/font-unifont.pak) +endif(OPENSPADES_NONFREE_RESOURCES) - if (WIN32) - # No automatic downloading for Windows (for now) - elseif (UNIX) - add_custom_target(OpenSpades_Resources_DevPaks ALL COMMENT "Downloading non-GPL assets") - add_custom_command( - TARGET OpenSpades_Resources_DevPaks - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/downloadpak.sh - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endif() +set(PAK_FILES + ${COMPILED_PAK_FILES} + ${NONFREE_PAK_FILES} + PARENT_SCOPE) - # TODO: subgroups for script files +if(OPENSPADES_RESOURCES) + if(OPENSPADES_NONFREE_RESOURCES) + if (WIN32) + # No automatic downloading for Windows (for now) + elseif (UNIX) + add_custom_target(OpenSpades_Resources_DevPaks ALL COMMENT "Downloading non-GPL assets" + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/pak000-Nonfree.pak + ${CMAKE_CURRENT_BINARY_DIR}/font-unifont.pak) + add_custom_command( + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/downloadpak.sh + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/pak000-Nonfree.pak + ${CMAKE_CURRENT_BINARY_DIR}/font-unifont.pak + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + endif() + endif(OPENSPADES_NONFREE_RESOURCES) + + file(GLOB_RECURSE GFX_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Gfx/*) + file(GLOB_RECURSE LICENSE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/License/*) + file(GLOB_RECURSE LOCALE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Locales/*) + file(GLOB_RECURSE MAP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Maps/*.vxl) + file(GLOB_RECURSE MODEL_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Models/*) file(GLOB_RECURSE SCRIPT_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Scripts/*.as) file(GLOB_RECURSE SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/*.fs ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/*.program ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/*.vs) + file(GLOB_RECURSE SOUND_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Sounds/*) + file(GLOB_RECURSE TEXTURE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Textures/*) + set(PAK_IN_FILES + ${GFX_FILES} ${LICENSE_FILES} ${LOCALE_FILES} ${MAP_FILES} + ${MODEL_FILES} ${SCRIPT_FILES} ${SHADER_FILES} ${SOUND_FILES} + ${TEXTURE_FILES}) + set(PACKAGE_INFO_IN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/PackageInfo.json) + set(PACKAGE_INFO_OUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/PackageInfo.json) + source_group("Gfx" FILES ${GFX_FILES}) + source_group("License Texts" FILES ${LICENSE_FILES}) + source_group("Translations" FILES ${LOCALE_FILES}) + source_group("Maps" FILES ${MAP_FILES}) + source_group("Models" FILES ${MODEL_FILES}) source_group("Scripts" FILES ${SCRIPT_FILES}) source_group("Shaders" FILES ${SHADER_FILES}) + source_group("Sounds" FILES ${SOUND_FILES}) + source_group("Textures" FILES ${TEXTURE_FILES}) add_custom_target(OpenSpades_Resources ALL - COMMENT "Packing assets" - SOURCES ${SCRIPT_FILES} ${SHADER_FILES} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}) + COMMENT "Building assets" + SOURCES ${PAK_IN_FILES} ${PACKAGE_INFO_IN_FILE} + DEPENDS + ${PACKAGE_INFO_OUT_FILE} + ${COMPILED_PAK_FILES}) if(WIN32) - if(MSVC) - # multi-config - add_custom_command( - TARGET OpenSpades_Resources - COMMAND powershell -ExecutionPolicy Bypass ${CMAKE_CURRENT_SOURCE_DIR}/mkpak.ps1 - ${CMAKE_BINARY_DIR}/bin/$/Resources - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - else() - add_custom_command( - TARGET OpenSpades_Resources - COMMAND powershell -ExecutionPolicy Bypass ${CMAKE_CURRENT_SOURCE_DIR}/mkpak.ps1 - ${CMAKE_BINARY_DIR}/bin/Resources - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endif() + add_custom_command( + OUTPUT ${COMPILED_PAK_FILES} + COMMAND powershell -ExecutionPolicy Bypass + ${CMAKE_CURRENT_SOURCE_DIR}/mkpak.ps1 + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Building paks" + DEPENDS ${PAK_IN_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/mkpak.ps1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) elseif (UNIX) add_custom_command( - TARGET OpenSpades_Resources + OUTPUT ${COMPILED_PAK_FILES} COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/mkpak.sh + COMMENT "Building paks" + DEPENDS ${PAK_IN_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/mkpak.sh WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endif() - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/PackageInfo.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_command( + OUTPUT ${PACKAGE_INFO_OUT_FILE} + DEPENDS ${PACKAGE_INFO_IN_FILE} + COMMENT "Copying PackageInfo.json" + COMMAND ${CMAKE_COMMAND} -E copy + ${PACKAGE_INFO_IN_FILE} ${PACKAGE_INFO_OUT_FILE}) + + if (WIN32 AND MSVC) + # copy the output files to the multi-config binary directory + # (you can't use generator expressions (`$<...>`) in `add_custom_command`'s + # `OUTPUT` parameter; it's not supported by CMake.) + add_custom_command( + TARGET OpenSpades_Resources POST_BUILD + COMMENT "Copying assets to the currently-selected configuration's build directory" + COMMAND + ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/bin/$/Resources + COMMAND + ${CMAKE_COMMAND} -E copy_if_different + ${COMPILED_PAK_FILES} ${PACKAGE_INFO_OUT_FILE} + ${CMAKE_BINARY_DIR}/bin/$/Resources) + endif (WIN32 AND MSVC) endif() -if(UNIX) +if(UNIX AND NOT APPLE) add_custom_target(OpenSpades_Unix ALL COMMENT "Process unix stuff") file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Icons) @@ -77,4 +137,4 @@ if(UNIX) COMMAND sh -c \"gzip -9 -c ${CMAKE_CURRENT_BINARY_DIR}/Unix/Man/openspades.6 > openspades.6.gz\" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Unix/Man ) -endif(UNIX) +endif(UNIX AND NOT APPLE) diff --git a/Resources/Gfx/Glare.png b/Resources/Gfx/Glare.png deleted file mode 100644 index 50bcfb479..000000000 Binary files a/Resources/Gfx/Glare.png and /dev/null differ diff --git a/Resources/Gfx/Spotlight.jpg b/Resources/Gfx/Spotlight.jpg new file mode 100644 index 000000000..29a0485dc Binary files /dev/null and b/Resources/Gfx/Spotlight.jpg differ diff --git a/Resources/Gfx/Spotlight.png b/Resources/Gfx/Spotlight.png deleted file mode 100644 index 47865c16a..000000000 Binary files a/Resources/Gfx/Spotlight.png and /dev/null differ diff --git a/Resources/Locales/nb/openspades.po b/Resources/Locales/nb/openspades.po index 3255e114a..8950f6600 100644 --- a/Resources/Locales/nb/openspades.po +++ b/Resources/Locales/nb/openspades.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: openspades\n" "Report-Msgid-Bugs-To: i at yvt.jp\n" "POT-Creation-Date: 2016-12-25 23:47-0200\n" -"PO-Revision-Date: 2020-04-19 14:46\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2020-12-20 06:27\n" +"Last-Translator: \n" "Language-Team: Norwegian Bokmal\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -13,8 +13,10 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Crowdin-Project: openspades\n" +"X-Crowdin-Project-ID: 246828\n" "X-Crowdin-Language: nb\n" "X-Crowdin-File: openspades.pot\n" +"X-Crowdin-File-ID: 1\n" "Language: nb_NO\n" #: Sources/Client/Client.cpp:585 Sources/Client/Client.cpp:586 @@ -95,7 +97,7 @@ msgstr "Trykk [{0}] for Ã¥ lade om" #: Sources/Client/Client_Draw.cpp:584 Sources/Client/Client_Draw.cpp:608 msgctxt "Client" msgid "You will respawn in: {0}" -msgstr "Du vil bli gjenopplivet innen: {0}" +msgstr "Du vil gjenoppstÃ¥ innen: {0}" #: Sources/Client/Client_Draw.cpp:586 Sources/Client/Client_Draw.cpp:610 msgctxt "Client" @@ -183,7 +185,7 @@ msgstr "{0} mistet {1} sitt intel" #: Sources/Client/Client_NetHandler.cpp:255 msgctxt "Client" msgid "Player {0} has left" -msgstr "Spiller {0} har forlatt serveren" +msgstr "Spiller {0} har forlatt tjeneren" #: Sources/Client/Client_NetHandler.cpp:257 #: Sources/Client/Client_NetHandler.cpp:264 @@ -335,7 +337,7 @@ msgstr "Laster inn øyeblikksbilde ({0}/{1})" #: Sources/Client/NetClient.cpp:546 Sources/Client/NetClient.cpp:609 msgctxt "NetClient" msgid "Connected" -msgstr "Koblet til" +msgstr "Tilkoblet" #: Sources/Client/NetClient.cpp:540 Sources/Client/NetClient.cpp:575 #: Sources/Client/NetClient.cpp:627 Sources/Client/NetClient.cpp:558 @@ -432,7 +434,7 @@ msgstr "Tilbake til spillet" #: Resources/Scripts/Gui/ClientUI.as:205 Resources/Scripts/Gui/ClientUI.as:205 msgctxt "Client" msgid "Chat Log" -msgstr "Prate log" +msgstr "Nettpratlogg" #: Resources/Scripts/Gui/ClientUI.as:212 Resources/Scripts/Gui/ClientUI.as:212 msgctxt "Client" @@ -457,7 +459,7 @@ msgstr "Avbryt" #: Resources/Scripts/Gui/ClientUI.as:500 Resources/Scripts/Gui/ClientUI.as:500 msgctxt "Client" msgid "Chat Text" -msgstr "Prate tekst" +msgstr "Nettprat" #: Resources/Scripts/Gui/ClientUI.as:508 Resources/Scripts/Gui/ClientUI.as:508 msgctxt "Client" @@ -712,7 +714,7 @@ msgstr "Skift" #: Resources/Scripts/Gui/Preferences.as:425 msgctxt "Preferences" msgid "Control" -msgstr "Kontrol" +msgstr "Kontroll" #: Resources/Scripts/Gui/Preferences.as:427 #: Resources/Scripts/Gui/Preferences.as:427 @@ -742,7 +744,7 @@ msgstr "Høyre museknapp" #: Resources/Scripts/Gui/Preferences.as:435 msgctxt "Preferences" msgid "Middle Mouse Button" -msgstr "Mellom museknapp" +msgstr "Midterste museknapp" #: Resources/Scripts/Gui/Preferences.as:437 #: Resources/Scripts/Gui/Preferences.as:437 @@ -866,7 +868,7 @@ msgstr "Tilbakemelding" #: Resources/Scripts/Gui/Preferences.as:655 msgctxt "Preferences" msgid "Chat Notify Sounds" -msgstr "Varslingslyder for prat" +msgstr "Varslingslyder for nettprat" #: Resources/Scripts/Gui/Preferences.as:656 #: Resources/Scripts/Gui/Preferences.as:656 @@ -908,7 +910,7 @@ msgstr "Synsfelt" #: Resources/Scripts/Gui/Preferences.as:666 msgctxt "Preferences" msgid "Minimap size" -msgstr "Minimap størrelse" +msgstr "Minikart størrelse" #: Resources/Scripts/Gui/Preferences.as:668 #: Resources/Scripts/Gui/Preferences.as:668 @@ -938,7 +940,7 @@ msgstr "Alt. Angrep" #: Resources/Scripts/Gui/Preferences.as:681 msgctxt "Preferences" msgid "Hold Aim Down Sight" -msgstr "Hold Aim Down Sight" +msgstr "Hold ned siktet" #: Resources/Scripts/Gui/Preferences.as:682 #: Resources/Scripts/Gui/Preferences.as:682 @@ -962,7 +964,7 @@ msgstr "Eksponentiell kraft" #: Resources/Scripts/Gui/Preferences.as:688 msgctxt "Preferences" msgid "Invert Y-axis Mouse Input" -msgstr "Inverter Y-akse museinngang" +msgstr "Inverter Y-akse musinngang" #: Resources/Scripts/Gui/Preferences.as:689 #: Resources/Scripts/Gui/Preferences.as:689 @@ -1010,7 +1012,7 @@ msgstr "Sist brukte verktøy" #: Resources/Scripts/Gui/Preferences.as:696 msgctxt "Preferences" msgid "Switch Tools by Wheel" -msgstr "Bytte verktøy med hjulet" +msgstr "Bytt verktøy med hjulet" #: Resources/Scripts/Gui/Preferences.as:698 #: Resources/Scripts/Gui/Preferences.as:698 @@ -1088,13 +1090,13 @@ msgstr "Lommelykt" #: Resources/Scripts/Gui/Preferences.as:712 msgctxt "Preferences" msgid "Global Chat" -msgstr "Global prat" +msgstr "Global nettprat" #: Resources/Scripts/Gui/Preferences.as:713 #: Resources/Scripts/Gui/Preferences.as:713 msgctxt "Preferences" msgid "Team Chat" -msgstr "Lag prat" +msgstr "Lag nettprat" #: Resources/Scripts/Gui/Preferences.as:714 #: Resources/Scripts/Gui/Preferences.as:714 @@ -1204,7 +1206,7 @@ msgstr "Lukk" #: Resources/Scripts/Gui/StartupScreen.as:1085 msgctxt "StartupScreen" msgid "Graphics Settings" -msgstr "Graffikinnstillinger" +msgstr "Grafikkinnstillinger" #: Resources/Scripts/Gui/StartupScreen.as:1090 #: Resources/Scripts/Gui/StartupScreen.as:1090 @@ -1242,7 +1244,7 @@ msgstr "OpenGL" #: Resources/Scripts/Gui/StartupScreen.as:1117 msgctxt "StartupScreen" msgid "OpenGL renderer uses your computer's graphics accelerator to generate the game screen." -msgstr "OpenGLgjengiveren bruker maskinens grafikkakselerator til Ã¥ generere spillskjermen." +msgstr "OpenGL-gjengiveren bruker maskinens grafikkakselerator til Ã¥ generere spillskjermen." #: Resources/Scripts/Gui/StartupScreen.as:1125 #: Resources/Scripts/Gui/StartupScreen.as:1125 @@ -1254,7 +1256,7 @@ msgstr "Programvare" #: Resources/Scripts/Gui/StartupScreen.as:1129 msgctxt "StartupScreen" msgid "Software renderer uses CPU to generate the game screen. Its quality and performance might be inferior to OpenGL renderer, but it works even with an unsupported GPU." -msgstr "Programvaregjengiveren bruker prosessoren til Ã¥ generere spillskjermen. Kvaliteten og ytelsen er muligens verre en OpenGLgjengiveren, men virker selv med en ustøttet grafikkakselerator." +msgstr "Programvaregjengiveren bruker prosessoren til Ã¥ generere spillskjermen. Kvaliteten og ytelsen er muligens verre en OpenGL-gjengiveren, men virker selv med en ustøttet grafikkakselerator." #: Resources/Scripts/Gui/StartupScreen.as:1143 #: Resources/Scripts/Gui/StartupScreen.as:1143 @@ -1270,7 +1272,7 @@ msgstr "Anti-alias: Aktiverer en teknikk som forbedrer utsendet til kanter med h #: Resources/Scripts/Gui/StartupScreen.as:1150 msgctxt "StartupScreen" msgid "Global Illumination" -msgstr "Global Illumination" +msgstr "Global belysning" #: Resources/Scripts/Gui/StartupScreen.as:1152 #: Resources/Scripts/Gui/StartupScreen.as:1152 @@ -1306,7 +1308,7 @@ msgstr "Slører skjermen nÃ¥r du snur deg kjapt." #: Resources/Scripts/Gui/StartupScreen.as:1167 msgctxt "StartupScreen" msgid "Lens Effect" -msgstr "Linse effekt" +msgstr "Linseeffekt" #: Resources/Scripts/Gui/StartupScreen.as:1168 #: Resources/Scripts/Gui/StartupScreen.as:1168 @@ -1324,7 +1326,7 @@ msgstr "Linsespredningsfilter" #: Resources/Scripts/Gui/StartupScreen.as:1171 msgctxt "StartupScreen" msgid "Simulates light being scattered by dust on the camera lens." -msgstr "Simulerer linsesprednings forÃ¥rsaket av støv pÃ¥ kameralinsen." +msgstr "Simulerer linsespredning forÃ¥rsaket av støv pÃ¥ kameralinsen." #: Resources/Scripts/Gui/StartupScreen.as:1174 #: Resources/Scripts/Gui/StartupScreen.as:1174 @@ -1378,7 +1380,7 @@ msgstr "Slører til objekter som er ute av fokus." #: Resources/Scripts/Gui/StartupScreen.as:1186 msgctxt "StartupScreen" msgid "Screen Space Ambient Occlusion" -msgstr "Screen Space Ambient Occlusion" +msgstr "Omgivelses okklusjon pÃ¥ skjermplass" #: Resources/Scripts/Gui/StartupScreen.as:1187 #: Resources/Scripts/Gui/StartupScreen.as:1187 @@ -1516,7 +1518,7 @@ msgstr "Med" #: Resources/Scripts/Gui/StartupScreen.as:1256 msgctxt "StartupScreen" msgid "Shader Effects" -msgstr "Shadereffekter" +msgstr "Shader-effekter" #: Resources/Scripts/Gui/StartupScreen.as:1256 #: Resources/Scripts/Gui/StartupScreen.as:1256 @@ -1546,7 +1548,7 @@ msgstr "OpenAL" #: Resources/Scripts/Gui/StartupScreen.as:1499 msgctxt "StartupScreen" msgid "Uses an OpenAL-capable sound card to process sound. In most cases where there isn't such a sound card, software emulation is used." -msgstr "Bruker et OpenAL kompatibelt lydkort til Ã¥ prosessere lyden. I det fleste tilfeller det det ikke er er kompatibelt lydkort, sÃ¥ brukes programvare emulering." +msgstr "Bruker et OpenAL kompatibelt lydkort til Ã¥ prosessere lyden. I det fleste tilfeller det det ikke er et kompatibelt lydkort, sÃ¥ brukes programvareemulering." #: Resources/Scripts/Gui/StartupScreen.as:1508 #: Resources/Scripts/Gui/StartupScreen.as:1508 @@ -1558,7 +1560,7 @@ msgstr "YSR" #: Resources/Scripts/Gui/StartupScreen.as:1512 msgctxt "StartupScreen" msgid "YSR is an experimental 3D HDR sound engine optimized for OpenSpades. It features several enhanced features including automatic load control, dynamics compressor, HRTF-based 3D audio, and high quality reverb." -msgstr "YSR er en eksperimentell 3D HDR lydmotor som er optimisert for OpenSpades. Det inneholder flere forbedrede egenskaper som automatisk belastningskontroll, dynamisk compressor, HRTF-basert 3D lyd og høg kvalitets ekko." +msgstr "YSR er en eksperimentell 3D HDR lydmotor som er optimisert for OpenSpades. Det inneholder flere forbedrede egenskaper som automatisk belastningskontroll, dynamisk compressor, HRTF-basert 3D lyd og ekko av høg kvalitet." #. ! The name of audio driver that outputs no audio. #: Resources/Scripts/Gui/StartupScreen.as:1523 @@ -1579,13 +1581,13 @@ msgstr "Deaktiverer lyd." #: Resources/Scripts/Gui/StartupScreen.as:1562 msgctxt "StartupScreen" msgid "Polyphonics" -msgstr "Polyphonics" +msgstr "Polyfonikk" #: Resources/Scripts/Gui/StartupScreen.as:1539 #: Resources/Scripts/Gui/StartupScreen.as:1539 msgctxt "StartupScreen" msgid "Specifies how many sounds can be played simultaneously. Higher value needs more processing power, so setting this too high might cause an overload (especially with a software emulation)." -msgstr "Spesifiserer hvor mange lyder som kan bli spilt av samtidig. Høyere verdier trenger mer prosesseringskraft, sÃ¥ vis du setter av denne innstillingen for høyt, sÃ¥ kan det forÃ¥rsake en overbelastning (spesielt med programvare emulering)." +msgstr "Spesifiserer hvor mange lyder som kan spilles samtidig. Høyere verdier trenger mer prosesseringskraft, sÃ¥ vis du setter denne innstillingen for høyt, sÃ¥ kan det forÃ¥rsake en overbelastning (spesielt med programvareemulering)." #: Resources/Scripts/Gui/StartupScreen.as:1546 #: Resources/Scripts/Gui/StartupScreen.as:1546 @@ -1597,7 +1599,7 @@ msgstr "EAX" #: Resources/Scripts/Gui/StartupScreen.as:1547 msgctxt "StartupScreen" msgid "Enables extended features provided by the OpenAL driver to create more ambience." -msgstr "Aktiverer utvidede egenskaper fra OpenAL driveren for Ã¥ skape mer atmosfære." +msgstr "Aktiverer utvidede egenskaper fra OpenAL-driveren for Ã¥ skape mer atmosfære." #: Resources/Scripts/Gui/StartupScreen.as:1563 #: Resources/Scripts/Gui/StartupScreen.as:1563 @@ -1615,19 +1617,19 @@ msgstr "SprÃ¥k" #: Resources/Scripts/Gui/StartupScreen.as:1635 msgctxt "StartupScreen" msgid "Tools" -msgstr "Redskaper" +msgstr "Verktøy" #: Resources/Scripts/Gui/StartupScreen.as:1638 #: Resources/Scripts/Gui/StartupScreen.as:1638 msgctxt "StartupScreen" msgid "Reset All Settings" -msgstr "Tilbakestill alle innstillinger" +msgstr "Nullstill instillinger" #: Resources/Scripts/Gui/StartupScreen.as:1647 #: Resources/Scripts/Gui/StartupScreen.as:1647 msgctxt "StartupScreen" msgid "Open Config Folder in Explorer" -msgstr "Ã…pne konfigmappe i explorer" +msgstr "Ã…pne konfigmappen i utforskeren" #: Resources/Scripts/Gui/StartupScreen.as:1649 #: Resources/Scripts/Gui/StartupScreen.as:1649 @@ -1663,7 +1665,7 @@ msgstr "Grafikk/lydinnstillinger" #: Resources/Scripts/Gui/StartupScreen.as:1676 msgctxt "StartupScreen" msgid "All key bindings" -msgstr "Bundne taster" +msgstr "Alle tastebindinger" #: Resources/Scripts/Gui/StartupScreen.as:1677 #: Resources/Scripts/Gui/StartupScreen.as:1677 diff --git a/Resources/Locales/tr/openspades.po b/Resources/Locales/tr/openspades.po index 1e55a033a..7a9e372de 100644 --- a/Resources/Locales/tr/openspades.po +++ b/Resources/Locales/tr/openspades.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: openspades\n" "Report-Msgid-Bugs-To: i at yvt.jp\n" "POT-Creation-Date: 2016-12-25 23:47-0200\n" -"PO-Revision-Date: 2020-04-19 14:46\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2020-12-20 06:27\n" +"Last-Translator: \n" "Language-Team: Turkish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -13,8 +13,10 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Crowdin-Project: openspades\n" +"X-Crowdin-Project-ID: 246828\n" "X-Crowdin-Language: tr\n" "X-Crowdin-File: openspades.pot\n" +"X-Crowdin-File-ID: 1\n" "Language: tr_TR\n" #: Sources/Client/Client.cpp:585 Sources/Client/Client.cpp:586 @@ -157,25 +159,25 @@ msgstr "{1} istihbaratını {0} ele geçirdi." #: Sources/Client/Client_NetHandler.cpp:159 msgctxt "Client" msgid "{0} picked up {1}'s intel" -msgstr "" +msgstr "{0} {1}'in istihbaratını aldı" #: Sources/Client/Client_NetHandler.cpp:165 #: Sources/Client/Client_NetHandler.cpp:166 msgctxt "Client" msgid "{0} picked up {1}'s Intel." -msgstr "" +msgstr "{0} {1}'in istihbaratını aldı." #: Sources/Client/Client_NetHandler.cpp:183 #: Sources/Client/Client_NetHandler.cpp:184 msgctxt "Client" msgid "{0} dropped {1}'s intel" -msgstr "" +msgstr "{0} {1}'in istihbaratını düşürdü" #: Sources/Client/Client_NetHandler.cpp:190 #: Sources/Client/Client_NetHandler.cpp:191 msgctxt "Client" msgid "{0} dropped {1}'s Intel" -msgstr "" +msgstr "{0} {1}'in istihbaratını düşürdü" #: Sources/Client/Client_NetHandler.cpp:237 #: Sources/Client/Client_NetHandler.cpp:243 @@ -319,7 +321,7 @@ msgstr "BaÄŸlantı yok" #: Sources/Client/NetClient.cpp:498 Sources/Client/NetClient.cpp:516 msgctxt "NetClient" msgid "Awaiting for state" -msgstr "" +msgstr "Bölge için bekleniyor" #: Sources/Client/NetClient.cpp:508 Sources/Client/NetClient.cpp:1277 #: Sources/Client/NetClient.cpp:526 Sources/Client/NetClient.cpp:1346 @@ -358,7 +360,7 @@ msgstr "Hata" #: Sources/Client/NetClient.cpp:702 Sources/Client/NetClient.cpp:749 msgctxt "NetClient" msgid "You are banned from this server." -msgstr "Bu sunucudan banlandınız." +msgstr "Bu sunucudan yasaklandınız." #: Sources/Client/NetClient.cpp:707 Sources/Client/NetClient.cpp:710 #: Sources/Client/NetClient.cpp:754 Sources/Client/NetClient.cpp:757 @@ -369,7 +371,7 @@ msgstr "Bu sunucudan atıldınız." #: Sources/Client/NetClient.cpp:708 Sources/Client/NetClient.cpp:755 msgctxt "NetClient" msgid "Incompatible client protocol version." -msgstr "Uyumsuz client protokol versiyonu." +msgstr "Uyumsuz kullanıcı protokol versiyonu." #: Sources/Client/NetClient.cpp:709 Sources/Client/NetClient.cpp:756 msgctxt "NetClient" @@ -386,8 +388,10 @@ msgstr "Bilinmeyen Neden" msgctxt "Client" msgid "Spectator{1}" msgid_plural "Spectators{1}" -msgstr[0] "Ä°zleyici {1}" -msgstr[1] "Ä°zleyiciler {1}" +msgstr[0] "Ä°zleyici{1}\n" +"Ä°zleyiciler{1}" +msgstr[1] "Ä°zleyici{1}\n" +"Ä°zleyiciler{1}" #: Sources/Client/TCProgressView.cpp:151 Sources/Client/TCProgressView.cpp:151 msgctxt "Client" @@ -402,7 +406,7 @@ msgstr "{0} takımının bölgesi" #: Sources/Gui/Main.cpp:548 Sources/Gui/Main.cpp:577 msgctxt "Main" msgid "Localization System Loaded" -msgstr "" +msgstr "Yer Belirleme Sistemi Yüklendi" #: Sources/Gui/Main.cpp:604 Sources/Gui/Runner.cpp:56 Sources/Gui/Main.cpp:633 #: Sources/Gui/Runner.cpp:56 @@ -410,126 +414,128 @@ msgctxt "Main" msgid "A serious error caused OpenSpades to stop working:\n\n" "{0}\n\n" "See SystemMessages.log for more details." -msgstr "" +msgstr "Ciddi bir hata OpenSpades'in çalışmayı durdurmasına neden oldu:\n\n" +"{0}\n\n" +"Daha fazla bilgi için SystemMessages.log dosyasına bakın." #: Sources/Gui/Main.cpp:612 Sources/Gui/Runner.cpp:62 Sources/Gui/Main.cpp:641 #: Sources/Gui/Runner.cpp:62 msgctxt "Main" msgid "OpenSpades Fatal Error" -msgstr "" +msgstr "OpenSpades Ciddi Bir Hata Verdi" #: Sources/Gui/MainScreen.cpp:225 Sources/Gui/MainScreen.cpp:220 msgctxt "MainScreen" msgid "NOW LOADING" -msgstr "" +msgstr "ŞİMDÄ° YÃœKLENÄ°YOR" #: Resources/Scripts/Gui/ClientUI.as:198 Resources/Scripts/Gui/ClientUI.as:198 msgctxt "Client" msgid "Back to Game" -msgstr "" +msgstr "Oyuna dön" #: Resources/Scripts/Gui/ClientUI.as:205 Resources/Scripts/Gui/ClientUI.as:205 msgctxt "Client" msgid "Chat Log" -msgstr "" +msgstr "Sohbet günlüğü" #: Resources/Scripts/Gui/ClientUI.as:212 Resources/Scripts/Gui/ClientUI.as:212 msgctxt "Client" msgid "Setup" -msgstr "" +msgstr "Kurulum" #: Resources/Scripts/Gui/ClientUI.as:219 Resources/Scripts/Gui/ClientUI.as:219 msgctxt "Client" msgid "Disconnect" -msgstr "" +msgstr "BaÄŸlantıyı Kes" #: Resources/Scripts/Gui/ClientUI.as:484 Resources/Scripts/Gui/ClientUI.as:484 msgctxt "Client" msgid "Say" -msgstr "" +msgstr "Söyle" #: Resources/Scripts/Gui/ClientUI.as:492 Resources/Scripts/Gui/ClientUI.as:492 msgctxt "Client" msgid "Cancel" -msgstr "" +msgstr "Ä°ptal Et" #: Resources/Scripts/Gui/ClientUI.as:500 Resources/Scripts/Gui/ClientUI.as:500 msgctxt "Client" msgid "Chat Text" -msgstr "" +msgstr "Sohbet Metni" #: Resources/Scripts/Gui/ClientUI.as:508 Resources/Scripts/Gui/ClientUI.as:508 msgctxt "Client" msgid "Global" -msgstr "" +msgstr "Küresel" #: Resources/Scripts/Gui/ClientUI.as:517 Resources/Scripts/Gui/ClientUI.as:517 msgctxt "Client" msgid "Team" -msgstr "" +msgstr "Ekip" #: Resources/Scripts/Gui/ClientUI.as:661 Resources/Scripts/Gui/ClientUI.as:662 msgctxt "Client" msgid "Close" -msgstr "" +msgstr "Kapat" #: Resources/Scripts/Gui/ClientUI.as:671 Resources/Scripts/Gui/ClientUI.as:672 msgctxt "Client" msgid "Say Global" -msgstr "" +msgstr "Küresele söyle" #: Resources/Scripts/Gui/ClientUI.as:682 Resources/Scripts/Gui/ClientUI.as:683 msgctxt "Client" msgid "Say Team" -msgstr "" +msgstr "Takıma söyle" #: Resources/Scripts/Gui/CreateProfileScreen.as:58 #: Resources/Scripts/Gui/CreateProfileScreen.as:58 msgctxt "CreateProfileScreen" msgid "OK" -msgstr "" +msgstr "Tamam" #: Resources/Scripts/Gui/CreateProfileScreen.as:70 #: Resources/Scripts/Gui/CreateProfileScreen.as:70 msgctxt "CreateProfileScreen" msgid "Decide later" -msgstr "" +msgstr "Daha sonra karar ver" #: Resources/Scripts/Gui/CreateProfileScreen.as:80 #: Resources/Scripts/Gui/CreateProfileScreen.as:80 msgctxt "CreateProfileScreen" msgid "Welcome to OpenSpades" -msgstr "" +msgstr "OpenSpades'e HoÅŸ Geldin" #: Resources/Scripts/Gui/CreateProfileScreen.as:88 #: Resources/Scripts/Gui/CreateProfileScreen.as:88 msgctxt "CreateProfileScreen" msgid "Choose a player name:" -msgstr "" +msgstr "Oyuncu Adını Seç:" #: Resources/Scripts/Gui/CreateProfileScreen.as:96 #: Resources/Scripts/Gui/CreateProfileScreen.as:96 msgctxt "CreateProfileScreen" msgid "Player name" -msgstr "" +msgstr "Oyuncu adı" #: Resources/Scripts/Gui/CreateProfileScreen.as:104 #: Resources/Scripts/Gui/CreateProfileScreen.as:104 msgctxt "CreateProfileScreen" msgid "You can change it later in the Setup dialog." -msgstr "" +msgstr "Daha sonra ayarlardan deÄŸiÅŸtirebilirsiniz." #: Resources/Scripts/Gui/MainScreen.as:376 #: Resources/Scripts/Gui/MainScreen.as:376 msgctxt "MainScreen" msgid "Connect" -msgstr "" +msgstr "BaÄŸlan" #: Resources/Scripts/Gui/MainScreen.as:384 #: Resources/Scripts/Gui/MainScreen.as:384 msgctxt "MainScreen" msgid "Quick Connect" -msgstr "" +msgstr "Hızlı BaÄŸlan" #: Resources/Scripts/Gui/MainScreen.as:393 #: Resources/Scripts/Gui/MainScreen.as:447 @@ -537,7 +543,7 @@ msgstr "" #: Resources/Scripts/Gui/MainScreen.as:447 msgctxt "MainScreen" msgid "0.75" -msgstr "" +msgstr "0.75" #: Resources/Scripts/Gui/MainScreen.as:403 #: Resources/Scripts/Gui/MainScreen.as:456 @@ -545,25 +551,25 @@ msgstr "" #: Resources/Scripts/Gui/MainScreen.as:456 msgctxt "MainScreen" msgid "0.76" -msgstr "" +msgstr "0.76" #: Resources/Scripts/Gui/MainScreen.as:411 #: Resources/Scripts/Gui/MainScreen.as:411 msgctxt "MainScreen" msgid "Quit" -msgstr "" +msgstr "Çıkış" #: Resources/Scripts/Gui/MainScreen.as:418 #: Resources/Scripts/Gui/MainScreen.as:418 msgctxt "MainScreen" msgid "Credits" -msgstr "" +msgstr "Yapımcılar" #: Resources/Scripts/Gui/MainScreen.as:425 #: Resources/Scripts/Gui/MainScreen.as:425 msgctxt "MainScreen" msgid "Setup" -msgstr "" +msgstr "Kurulum" #: Resources/Scripts/Gui/MainScreen.as:438 #: Resources/Scripts/Gui/MainScreen.as:482 @@ -571,74 +577,75 @@ msgstr "" #: Resources/Scripts/Gui/MainScreen.as:482 msgctxt "MainScreen" msgid "Filter" -msgstr "" +msgstr "Filtre" #: Resources/Scripts/Gui/MainScreen.as:465 #: Resources/Scripts/Gui/MainScreen.as:465 msgctxt "MainScreen" msgid "Empty" -msgstr "" +msgstr "BoÅŸ" #: Resources/Scripts/Gui/MainScreen.as:474 #: Resources/Scripts/Gui/MainScreen.as:474 msgctxt "MainScreen" msgid "Not Full" -msgstr "" +msgstr "Dolu DeÄŸil" #: Resources/Scripts/Gui/MainScreen.as:494 #: Resources/Scripts/Gui/MainScreen.as:494 msgctxt "MainScreen" msgid "Server Name" -msgstr "" +msgstr "Sunucu Adı" #: Resources/Scripts/Gui/MainScreen.as:501 #: Resources/Scripts/Gui/MainScreen.as:501 msgctxt "MainScreen" msgid "Players" -msgstr "" +msgstr "Oyuncular" #: Resources/Scripts/Gui/MainScreen.as:508 #: Resources/Scripts/Gui/MainScreen.as:508 msgctxt "MainScreen" msgid "Map Name" -msgstr "" +msgstr "Harita Adı" #: Resources/Scripts/Gui/MainScreen.as:515 #: Resources/Scripts/Gui/MainScreen.as:515 msgctxt "MainScreen" msgid "Game Mode" -msgstr "" +msgstr "Oyun Modu" #: Resources/Scripts/Gui/MainScreen.as:522 #: Resources/Scripts/Gui/MainScreen.as:522 msgctxt "MainScreen" msgid "Ver." -msgstr "" +msgstr "Ver." #: Resources/Scripts/Gui/MainScreen.as:529 #: Resources/Scripts/Gui/MainScreen.as:529 msgctxt "MainScreen" msgid "Loc." -msgstr "" +msgstr "Loc." #: Resources/Scripts/Gui/MainScreen.as:787 #: Resources/Scripts/Gui/MainScreen.as:787 msgctxt "MainScreen" msgid "You were disconnected from the server because of the following reason:\n\n" "{0}" -msgstr "" +msgstr "AÅŸağıdaki nedenden dolayı sunucu ile baÄŸlantınız kesildi:\n\n" +"{0}" #: Resources/Scripts/Gui/MainScreen.as:807 #: Resources/Scripts/Gui/MainScreen.as:807 msgctxt "MainScreen" msgid "Loading..." -msgstr "" +msgstr "Yükleniyor..." #: Resources/Scripts/Gui/MainScreen.as:825 #: Resources/Scripts/Gui/MainScreen.as:825 msgctxt "MainScreen" msgid "Failed to fetch the server list." -msgstr "" +msgstr "Sunucu listesi getirilemedi." #: Resources/Scripts/Gui/MessageBox.as:130 #: Resources/Scripts/Gui/MessageBox.as:144 @@ -646,25 +653,25 @@ msgstr "" #: Resources/Scripts/Gui/MessageBox.as:144 msgctxt "MessageBox" msgid "OK" -msgstr "" +msgstr "Tamam" #: Resources/Scripts/Gui/MessageBox.as:144 #: Resources/Scripts/Gui/MessageBox.as:144 msgctxt "MessageBox" msgid "Cancel" -msgstr "" +msgstr "Ä°ptal" #: Resources/Scripts/Gui/Preferences.as:60 #: Resources/Scripts/Gui/Preferences.as:60 msgctxt "Preferences" msgid "Game Options" -msgstr "" +msgstr "Oyun Ayarları" #: Resources/Scripts/Gui/Preferences.as:61 #: Resources/Scripts/Gui/Preferences.as:61 msgctxt "Preferences" msgid "Controls" -msgstr "" +msgstr "Denetimler" #: Resources/Scripts/Gui/Preferences.as:62 #: Resources/Scripts/Gui/Preferences.as:663 @@ -674,85 +681,85 @@ msgstr "" #: Resources/Scripts/Gui/Preferences.as:708 msgctxt "Preferences" msgid "Misc" -msgstr "" +msgstr "ÇeÅŸitli" #: Resources/Scripts/Gui/Preferences.as:66 #: Resources/Scripts/Gui/Preferences.as:66 msgctxt "Preferences" msgid "Back" -msgstr "" +msgstr "Geri" #: Resources/Scripts/Gui/Preferences.as:407 #: Resources/Scripts/Gui/Preferences.as:407 msgctxt "Preferences" msgid "Press Key to Bind or [Escape] to Cancel..." -msgstr "" +msgstr "BaÄŸlamak için TuÅŸa veya Ä°ptal Etmek için [Escape] tuÅŸuna basın..." #: Resources/Scripts/Gui/Preferences.as:418 #: Resources/Scripts/Gui/Preferences.as:418 msgctxt "Preferences" msgid "Space" -msgstr "" +msgstr "BoÅŸluk" #: Resources/Scripts/Gui/Preferences.as:420 #: Resources/Scripts/Gui/Preferences.as:420 msgctxt "Preferences" msgid "Unbound" -msgstr "" +msgstr "BaÄŸlı deÄŸil" #: Resources/Scripts/Gui/Preferences.as:423 #: Resources/Scripts/Gui/Preferences.as:423 msgctxt "Preferences" msgid "Shift" -msgstr "" +msgstr "Shift" #: Resources/Scripts/Gui/Preferences.as:425 #: Resources/Scripts/Gui/Preferences.as:425 msgctxt "Preferences" msgid "Control" -msgstr "" +msgstr "Control" #: Resources/Scripts/Gui/Preferences.as:427 #: Resources/Scripts/Gui/Preferences.as:427 msgctxt "Preferences" msgid "Meta" -msgstr "" +msgstr "Meta" #: Resources/Scripts/Gui/Preferences.as:429 #: Resources/Scripts/Gui/Preferences.as:429 msgctxt "Preferences" msgid "Alt" -msgstr "" +msgstr "Alt" #: Resources/Scripts/Gui/Preferences.as:431 #: Resources/Scripts/Gui/Preferences.as:431 msgctxt "Preferences" msgid "Left Mouse Button" -msgstr "" +msgstr "Sol fare tuÅŸu" #: Resources/Scripts/Gui/Preferences.as:433 #: Resources/Scripts/Gui/Preferences.as:433 msgctxt "Preferences" msgid "Right Mouse Button" -msgstr "" +msgstr "SaÄŸ Fare TuÅŸu" #: Resources/Scripts/Gui/Preferences.as:435 #: Resources/Scripts/Gui/Preferences.as:435 msgctxt "Preferences" msgid "Middle Mouse Button" -msgstr "" +msgstr "Orta Fare TuÅŸu" #: Resources/Scripts/Gui/Preferences.as:437 #: Resources/Scripts/Gui/Preferences.as:437 msgctxt "Preferences" msgid "Mouse Button 4" -msgstr "" +msgstr "Fare TuÅŸu 4" #: Resources/Scripts/Gui/Preferences.as:439 #: Resources/Scripts/Gui/Preferences.as:439 msgctxt "Preferences" msgid "Mouse Button 5" -msgstr "" +msgstr "Fare TuÅŸu 5" #: Resources/Scripts/Gui/Preferences.as:613 #: Resources/Scripts/Gui/Preferences.as:619 @@ -760,7 +767,7 @@ msgstr "" #: Resources/Scripts/Gui/Preferences.as:619 msgctxt "Preferences" msgid "ON" -msgstr "" +msgstr "Açık" #: Resources/Scripts/Gui/Preferences.as:613 #: Resources/Scripts/Gui/Preferences.as:619 @@ -772,67 +779,67 @@ msgstr "" #: Resources/Scripts/Gui/Preferences.as:651 msgctxt "Preferences" msgid "OFF" -msgstr "" +msgstr "Kapalı" #: Resources/Scripts/Gui/Preferences.as:619 #: Resources/Scripts/Gui/Preferences.as:619 msgctxt "Preferences" msgid "REVERSED" -msgstr "" +msgstr "Ters" #: Resources/Scripts/Gui/Preferences.as:637 #: Resources/Scripts/Gui/Preferences.as:637 msgctxt "Preferences" msgid "Player Information" -msgstr "" +msgstr "Oyuncu bilgileri" #: Resources/Scripts/Gui/Preferences.as:638 #: Resources/Scripts/Gui/Preferences.as:638 msgctxt "Preferences" msgid "Player Name" -msgstr "" +msgstr "Oyuncu adı" #: Resources/Scripts/Gui/Preferences.as:642 #: Resources/Scripts/Gui/Preferences.as:642 msgctxt "Preferences" msgid "Effects" -msgstr "" +msgstr "Efektler" #: Resources/Scripts/Gui/Preferences.as:643 #: Resources/Scripts/Gui/Preferences.as:643 msgctxt "Preferences" msgid "Blood" -msgstr "" +msgstr "Kan" #: Resources/Scripts/Gui/Preferences.as:644 #: Resources/Scripts/Gui/Preferences.as:644 msgctxt "Preferences" msgid "Ejecting Brass" -msgstr "" +msgstr "Kovan Çıkarma" #: Resources/Scripts/Gui/Preferences.as:645 #: Resources/Scripts/Gui/Preferences.as:645 msgctxt "Preferences" msgid "Ragdoll" -msgstr "" +msgstr "Ragdoll" #: Resources/Scripts/Gui/Preferences.as:646 #: Resources/Scripts/Gui/Preferences.as:646 msgctxt "Preferences" msgid "Animations" -msgstr "" +msgstr "Animasyonlar" #: Resources/Scripts/Gui/Preferences.as:647 #: Resources/Scripts/Gui/Preferences.as:647 msgctxt "Preferences" msgid "Camera Shake" -msgstr "" +msgstr "Kamera sarsıntısı" #: Resources/Scripts/Gui/Preferences.as:648 #: Resources/Scripts/Gui/Preferences.as:648 msgctxt "Preferences" msgid "MORE" -msgstr "" +msgstr "DAHA FAZLA" #: Resources/Scripts/Gui/Preferences.as:648 #: Resources/Scripts/Gui/Preferences.as:651 @@ -840,337 +847,337 @@ msgstr "" #: Resources/Scripts/Gui/Preferences.as:651 msgctxt "Preferences" msgid "NORMAL" -msgstr "" +msgstr "Normal" #: Resources/Scripts/Gui/Preferences.as:650 #: Resources/Scripts/Gui/Preferences.as:650 msgctxt "Preferences" msgid "Particles" -msgstr "" +msgstr "Parçacıklar" #: Resources/Scripts/Gui/Preferences.as:651 #: Resources/Scripts/Gui/Preferences.as:651 msgctxt "Preferences" msgid "LESS" -msgstr "" +msgstr "AZ" #: Resources/Scripts/Gui/Preferences.as:654 #: Resources/Scripts/Gui/Preferences.as:654 msgctxt "Preferences" msgid "Feedbacks" -msgstr "" +msgstr "Geri bildirim" #: Resources/Scripts/Gui/Preferences.as:655 #: Resources/Scripts/Gui/Preferences.as:655 msgctxt "Preferences" msgid "Chat Notify Sounds" -msgstr "" +msgstr "Sohbet Bildirim Sesleri" #: Resources/Scripts/Gui/Preferences.as:656 #: Resources/Scripts/Gui/Preferences.as:656 msgctxt "Preferences" msgid "Hit Indicator" -msgstr "" +msgstr "Ä°sabet Göstergesi" #: Resources/Scripts/Gui/Preferences.as:657 #: Resources/Scripts/Gui/Preferences.as:657 msgctxt "Preferences" msgid "Show Alerts" -msgstr "" +msgstr "Uyarıları göster" #: Resources/Scripts/Gui/Preferences.as:659 #: Resources/Scripts/Gui/Preferences.as:659 msgctxt "Preferences" msgid "AoS 0.75/0.76 Compatibility" -msgstr "" +msgstr "AoS 0.75/0.76 UyumluluÄŸu" #: Resources/Scripts/Gui/Preferences.as:660 #: Resources/Scripts/Gui/Preferences.as:660 msgctxt "Preferences" msgid "Allow Unicode" -msgstr "" +msgstr "Unicode'a izin ver" #: Resources/Scripts/Gui/Preferences.as:661 #: Resources/Scripts/Gui/Preferences.as:661 msgctxt "Preferences" msgid "Server Alert" -msgstr "" +msgstr "Sunucu uyarıları" #: Resources/Scripts/Gui/Preferences.as:664 #: Resources/Scripts/Gui/Preferences.as:664 msgctxt "Preferences" msgid "Field of View" -msgstr "" +msgstr "Görüş açısı" #: Resources/Scripts/Gui/Preferences.as:666 #: Resources/Scripts/Gui/Preferences.as:666 msgctxt "Preferences" msgid "Minimap size" -msgstr "" +msgstr "Küçük Harita boyutu" #: Resources/Scripts/Gui/Preferences.as:668 #: Resources/Scripts/Gui/Preferences.as:668 msgctxt "Preferences" msgid "Show Statistics" -msgstr "" +msgstr "Ä°statistikleri göster" #: Resources/Scripts/Gui/Preferences.as:678 #: Resources/Scripts/Gui/Preferences.as:678 msgctxt "Preferences" msgid "Weapons/Tools" -msgstr "" +msgstr "Silahlar / Araçlar" #: Resources/Scripts/Gui/Preferences.as:679 #: Resources/Scripts/Gui/Preferences.as:679 msgctxt "Preferences" msgid "Attack" -msgstr "" +msgstr "Saldırı" #: Resources/Scripts/Gui/Preferences.as:680 #: Resources/Scripts/Gui/Preferences.as:680 msgctxt "Preferences" msgid "Alt. Attack" -msgstr "" +msgstr "Alt. Saldırı" #: Resources/Scripts/Gui/Preferences.as:681 #: Resources/Scripts/Gui/Preferences.as:681 msgctxt "Preferences" msgid "Hold Aim Down Sight" -msgstr "" +msgstr "Hedefi AÅŸağı Görüşte Tut" #: Resources/Scripts/Gui/Preferences.as:682 #: Resources/Scripts/Gui/Preferences.as:682 msgctxt "Preferences" msgid "Mouse Sensitivity" -msgstr "" +msgstr "Fare Hassasiyeti" #: Resources/Scripts/Gui/Preferences.as:684 #: Resources/Scripts/Gui/Preferences.as:684 msgctxt "Preferences" msgid "ADS Mouse Sens. Scale" -msgstr "" +msgstr "ADS Fare Hassas. ölçüsü" #: Resources/Scripts/Gui/Preferences.as:686 #: Resources/Scripts/Gui/Preferences.as:686 msgctxt "Preferences" msgid "Exponential Power" -msgstr "" +msgstr "Ãœstel Güç" #: Resources/Scripts/Gui/Preferences.as:688 #: Resources/Scripts/Gui/Preferences.as:688 msgctxt "Preferences" msgid "Invert Y-axis Mouse Input" -msgstr "" +msgstr "Y ekseni Fare GiriÅŸini Ters Çevir" #: Resources/Scripts/Gui/Preferences.as:689 #: Resources/Scripts/Gui/Preferences.as:689 msgctxt "Preferences" msgid "Reload" -msgstr "" +msgstr "Tekrar yükle" #: Resources/Scripts/Gui/Preferences.as:690 #: Resources/Scripts/Gui/Preferences.as:690 msgctxt "Preferences" msgid "Capture Color" -msgstr "" +msgstr "Çekim Rengi" #: Resources/Scripts/Gui/Preferences.as:691 #: Resources/Scripts/Gui/Preferences.as:691 msgctxt "Preferences" msgid "Equip Spade" -msgstr "" +msgstr "KüreÄŸi Kullan" #: Resources/Scripts/Gui/Preferences.as:692 #: Resources/Scripts/Gui/Preferences.as:692 msgctxt "Preferences" msgid "Equip Block" -msgstr "" +msgstr "BloÄŸu Donan" #: Resources/Scripts/Gui/Preferences.as:693 #: Resources/Scripts/Gui/Preferences.as:693 msgctxt "Preferences" msgid "Equip Weapon" -msgstr "" +msgstr "Silahı Donan" #: Resources/Scripts/Gui/Preferences.as:694 #: Resources/Scripts/Gui/Preferences.as:694 msgctxt "Preferences" msgid "Equip Grenade" -msgstr "" +msgstr "Bombayı Donan" #: Resources/Scripts/Gui/Preferences.as:695 #: Resources/Scripts/Gui/Preferences.as:695 msgctxt "Preferences" msgid "Last Used Tool" -msgstr "" +msgstr "Son Kullanılan Araç" #: Resources/Scripts/Gui/Preferences.as:696 #: Resources/Scripts/Gui/Preferences.as:696 msgctxt "Preferences" msgid "Switch Tools by Wheel" -msgstr "" +msgstr "Aletleri Tekerlekle DeÄŸiÅŸtir" #: Resources/Scripts/Gui/Preferences.as:698 #: Resources/Scripts/Gui/Preferences.as:698 msgctxt "Preferences" msgid "Movement" -msgstr "" +msgstr "Hareket" #: Resources/Scripts/Gui/Preferences.as:699 #: Resources/Scripts/Gui/Preferences.as:699 msgctxt "Preferences" msgid "Walk Forward" -msgstr "" +msgstr "Ä°leri Yürü" #: Resources/Scripts/Gui/Preferences.as:700 #: Resources/Scripts/Gui/Preferences.as:700 msgctxt "Preferences" msgid "Backpedal" -msgstr "" +msgstr "Geriye Git" #: Resources/Scripts/Gui/Preferences.as:701 #: Resources/Scripts/Gui/Preferences.as:701 msgctxt "Preferences" msgid "Move Left" -msgstr "" +msgstr "Sola hareket et" #: Resources/Scripts/Gui/Preferences.as:702 #: Resources/Scripts/Gui/Preferences.as:702 msgctxt "Preferences" msgid "Move Right" -msgstr "" +msgstr "SaÄŸa hareket et" #: Resources/Scripts/Gui/Preferences.as:703 #: Resources/Scripts/Gui/Preferences.as:703 msgctxt "Preferences" msgid "Crouch" -msgstr "" +msgstr "EÄŸil" #: Resources/Scripts/Gui/Preferences.as:704 #: Resources/Scripts/Gui/Preferences.as:704 msgctxt "Preferences" msgid "Sneak" -msgstr "" +msgstr "Gizli" #: Resources/Scripts/Gui/Preferences.as:705 #: Resources/Scripts/Gui/Preferences.as:705 msgctxt "Preferences" msgid "Jump" -msgstr "" +msgstr "Zıpla" #: Resources/Scripts/Gui/Preferences.as:706 #: Resources/Scripts/Gui/Preferences.as:706 msgctxt "Preferences" msgid "Sprint" -msgstr "" +msgstr "KoÅŸ" #: Resources/Scripts/Gui/Preferences.as:709 #: Resources/Scripts/Gui/Preferences.as:709 msgctxt "Preferences" msgid "Minimap Scale" -msgstr "" +msgstr "Küçük Harita ÖlçeÄŸi" #: Resources/Scripts/Gui/Preferences.as:710 #: Resources/Scripts/Gui/Preferences.as:710 msgctxt "Preferences" msgid "Toggle Map" -msgstr "" +msgstr "Haritayı Aç / Kapat" #: Resources/Scripts/Gui/Preferences.as:711 #: Resources/Scripts/Gui/Preferences.as:711 msgctxt "Preferences" msgid "Flashlight" -msgstr "" +msgstr "El Feneri" #: Resources/Scripts/Gui/Preferences.as:712 #: Resources/Scripts/Gui/Preferences.as:712 msgctxt "Preferences" msgid "Global Chat" -msgstr "" +msgstr "Genel Sohbet" #: Resources/Scripts/Gui/Preferences.as:713 #: Resources/Scripts/Gui/Preferences.as:713 msgctxt "Preferences" msgid "Team Chat" -msgstr "" +msgstr "Takım Sohbeti" #: Resources/Scripts/Gui/Preferences.as:714 #: Resources/Scripts/Gui/Preferences.as:714 msgctxt "Preferences" msgid "Limbo Menu" -msgstr "" +msgstr "Limbo Menüsü" #: Resources/Scripts/Gui/Preferences.as:715 #: Resources/Scripts/Gui/Preferences.as:715 msgctxt "Preferences" msgid "Save Map" -msgstr "" +msgstr "Haritayı Kayıt Et" #: Resources/Scripts/Gui/Preferences.as:716 #: Resources/Scripts/Gui/Preferences.as:716 msgctxt "Preferences" msgid "Save Sceneshot" -msgstr "" +msgstr "Sahneyi Kaydet" #: Resources/Scripts/Gui/Preferences.as:717 #: Resources/Scripts/Gui/Preferences.as:717 msgctxt "Preferences" msgid "Save Screenshot" -msgstr "" +msgstr "Ekran görüntüsünü kaydet" #: Resources/Scripts/Gui/Preferences.as:736 #: Resources/Scripts/Gui/Preferences.as:736 msgctxt "Preferences" msgid "Enable Startup Window" -msgstr "" +msgstr "Açılır pencereyi etkinleÅŸtir" #: Resources/Scripts/Gui/Preferences.as:757 #: Resources/Scripts/Gui/Preferences.as:757 msgctxt "Preferences" msgid "Quit and restart OpenSpades to access the startup window." -msgstr "" +msgstr "BaÅŸlangıç ​​penceresine eriÅŸmek için OpenSpades'ten çıkın ve yeniden baÅŸlatın." #: Resources/Scripts/Gui/Preferences.as:758 #: Resources/Scripts/Gui/Preferences.as:758 msgctxt "Preferences" msgid "Some settings only can be changed in the startup window." -msgstr "" +msgstr "Bazı ayarlar yalnızca baÅŸlangıç ​​penceresinde deÄŸiÅŸtirilebilir." #: Resources/Scripts/Gui/StartupScreen.as:160 #: Resources/Scripts/Gui/StartupScreen.as:160 msgctxt "StartupScreen" msgid "Start" -msgstr "" +msgstr "BaÅŸlat" #: Resources/Scripts/Gui/StartupScreen.as:167 #: Resources/Scripts/Gui/StartupScreen.as:167 msgctxt "StartupScreen" msgid "Skip this screen next time" -msgstr "" +msgstr "Bir Daha ki sefere bu ekranı geç" #: Resources/Scripts/Gui/StartupScreen.as:211 #: Resources/Scripts/Gui/StartupScreen.as:211 msgctxt "StartupScreen" msgid "Graphics" -msgstr "" +msgstr "Grafikler" #: Resources/Scripts/Gui/StartupScreen.as:212 #: Resources/Scripts/Gui/StartupScreen.as:212 msgctxt "StartupScreen" msgid "Audio" -msgstr "" +msgstr "Sesler" #: Resources/Scripts/Gui/StartupScreen.as:213 #: Resources/Scripts/Gui/StartupScreen.as:213 msgctxt "StartupScreen" msgid "Generic" -msgstr "" +msgstr "Genel" #: Resources/Scripts/Gui/StartupScreen.as:214 #: Resources/Scripts/Gui/StartupScreen.as:214 msgctxt "StartupScreen" msgid "System Info" -msgstr "" +msgstr "Sistem Bilgisi" #: Resources/Scripts/Gui/StartupScreen.as:215 #: Resources/Scripts/Gui/StartupScreen.as:1679 @@ -1178,49 +1185,49 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1679 msgctxt "StartupScreen" msgid "Advanced" -msgstr "" +msgstr "GeliÅŸmiÅŸ" #: Resources/Scripts/Gui/StartupScreen.as:288 #: Resources/Scripts/Gui/StartupScreen.as:288 msgctxt "StartupScreen" msgid "An unknown error has occurred while opening the update info website." -msgstr "" +msgstr "Güncelleme bilgi sitesini açarken bilinmeyen bir sorun oluÅŸtu." #: Resources/Scripts/Gui/StartupScreen.as:853 #: Resources/Scripts/Gui/StartupScreen.as:853 msgctxt "StartupScreen" msgid "Custom" -msgstr "" +msgstr "ÖzelleÅŸtir" #: Resources/Scripts/Gui/StartupScreen.as:979 #: Resources/Scripts/Gui/StartupScreen.as:979 msgctxt "StartupScreen" msgid "Close" -msgstr "" +msgstr "Kapat" #: Resources/Scripts/Gui/StartupScreen.as:1085 #: Resources/Scripts/Gui/StartupScreen.as:1085 msgctxt "StartupScreen" msgid "Graphics Settings" -msgstr "" +msgstr "Grafik Ayarları" #: Resources/Scripts/Gui/StartupScreen.as:1090 #: Resources/Scripts/Gui/StartupScreen.as:1090 msgctxt "StartupScreen" msgid "Resolution" -msgstr "" +msgstr "Çözünürlük" #: Resources/Scripts/Gui/StartupScreen.as:1100 #: Resources/Scripts/Gui/StartupScreen.as:1100 msgctxt "StartupScreen" msgid "Fullscreen Mode" -msgstr "" +msgstr "Tam Ekran Modu" #: Resources/Scripts/Gui/StartupScreen.as:1103 #: Resources/Scripts/Gui/StartupScreen.as:1103 msgctxt "StartupScreen" msgid "By running in fullscreen mode OpenSpades occupies the screen, making it easier for you to concentrate on playing the game." -msgstr "" +msgstr "Tam ekran modunda çalışarak OpenSpades ekranı kaplar ve oyunu oynama ve konsantre olmanızı kolaylaÅŸtırır." #: Resources/Scripts/Gui/StartupScreen.as:1110 #: Resources/Scripts/Gui/StartupScreen.as:1492 @@ -1228,31 +1235,31 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1492 msgctxt "StartupScreen" msgid "Backend" -msgstr "" +msgstr "Backend" #: Resources/Scripts/Gui/StartupScreen.as:1113 #: Resources/Scripts/Gui/StartupScreen.as:1113 msgctxt "StartupScreen" msgid "OpenGL" -msgstr "" +msgstr "OpenGL" #: Resources/Scripts/Gui/StartupScreen.as:1117 #: Resources/Scripts/Gui/StartupScreen.as:1117 msgctxt "StartupScreen" msgid "OpenGL renderer uses your computer's graphics accelerator to generate the game screen." -msgstr "" +msgstr "OpenGL oluÅŸturucu, oyun ekranını yaratmak için bilgisayarınızın grafik iÅŸlemcisini kullanır." #: Resources/Scripts/Gui/StartupScreen.as:1125 #: Resources/Scripts/Gui/StartupScreen.as:1125 msgctxt "StartupScreen" msgid "Software" -msgstr "" +msgstr "Software" #: Resources/Scripts/Gui/StartupScreen.as:1129 #: Resources/Scripts/Gui/StartupScreen.as:1129 msgctxt "StartupScreen" msgid "Software renderer uses CPU to generate the game screen. Its quality and performance might be inferior to OpenGL renderer, but it works even with an unsupported GPU." -msgstr "" +msgstr "Software oluÅŸturucu, oyun ekranını yaratmak için bilgisayarınızın sadece iÅŸlemcisini kullanır. Bunun kalitesi ve performansı OpenGL oluÅŸturucudan daha düşük olabilir, ancak desteklenmeyen bir GPU ile bile çalışır." #: Resources/Scripts/Gui/StartupScreen.as:1143 #: Resources/Scripts/Gui/StartupScreen.as:1143 @@ -1260,127 +1267,129 @@ msgctxt "StartupScreen" msgid "Antialias:Enables a technique to improve the appearance of high-contrast edges.\n\n" "MSAA: Performs antialiasing by generating an intermediate high-resolution image. Looks best, but doesn't cope with some settings.\n\n" "FXAA: Performs antialiasing by smoothing artifacts out as a post-process.|Off|MSAA 2x|4x|FXAA" -msgstr "" +msgstr "Kenar yumuÅŸatma: Yüksek kontrastlı kenarların görünümünü iyileÅŸtirmek için bir yöntem saÄŸlar.\n\n" +"MSAA: Ara yüksek çözünürlüklü bir görüntü oluÅŸturarak kenar yumuÅŸatma uygular. En iyi olarak görünüyor, ancak bazı ayarlarla baÅŸa çıkmıyor.\n\n" +"FXAA: Ä°ÅŸlem sonrası olarak yapay nesneleri yumuÅŸatarak kenar yumuÅŸatma uygular. | Kapalı | MSAA 2x | 4x | FXAA" #: Resources/Scripts/Gui/StartupScreen.as:1150 #: Resources/Scripts/Gui/StartupScreen.as:1150 msgctxt "StartupScreen" msgid "Global Illumination" -msgstr "" +msgstr "Küresel aydınlatma" #: Resources/Scripts/Gui/StartupScreen.as:1152 #: Resources/Scripts/Gui/StartupScreen.as:1152 msgctxt "StartupScreen" msgid "Enables a physically based simulation of light path for more realistic lighting." -msgstr "" +msgstr "Daha gerçekçi aydınlatma için fiziksel olarak bir ışık yolu simülasyonu saÄŸlar." #: Resources/Scripts/Gui/StartupScreen.as:1155 #: Resources/Scripts/Gui/StartupScreen.as:1155 msgctxt "StartupScreen" msgid "Linear HDR Rendering" -msgstr "" +msgstr "DoÄŸrusal HDR OluÅŸturma" #: Resources/Scripts/Gui/StartupScreen.as:1157 #: Resources/Scripts/Gui/StartupScreen.as:1157 msgctxt "StartupScreen" msgid "Uses a number representation which allows wider dynamic range during rendering process. Additionally, this allows color calculation whose value is in linear correspondence with actual energy, that is, physically accurate blending can be achieved." -msgstr "" +msgstr "Görüntü oluÅŸturma iÅŸlemi sırasında daha geniÅŸ dinamik aralığa izin veren bir sayı gösterimi kullanır. Ek olarak bu, deÄŸeri gerçek enerjiyle doÄŸrusal bir uyum içinde olan, yani fiziksel olarak doÄŸru karıştırma elde edilebilen renk hesaplamasına izin verir." #: Resources/Scripts/Gui/StartupScreen.as:1164 #: Resources/Scripts/Gui/StartupScreen.as:1164 msgctxt "StartupScreen" msgid "Camera Blur" -msgstr "" +msgstr "Kamera Bulanıklığı" #: Resources/Scripts/Gui/StartupScreen.as:1165 #: Resources/Scripts/Gui/StartupScreen.as:1165 msgctxt "StartupScreen" msgid "Blurs the screen when you turn quickly." -msgstr "" +msgstr "Hızlı döndüğünüzde ekranı bulanıklaÅŸtırır." #: Resources/Scripts/Gui/StartupScreen.as:1167 #: Resources/Scripts/Gui/StartupScreen.as:1167 msgctxt "StartupScreen" msgid "Lens Effect" -msgstr "" +msgstr "Lens efekti" #: Resources/Scripts/Gui/StartupScreen.as:1168 #: Resources/Scripts/Gui/StartupScreen.as:1168 msgctxt "StartupScreen" msgid "Simulates distortion caused by a real camera lens." -msgstr "" +msgstr "Gerçek bir kamera merceÄŸinin neden olduÄŸu bozulmayı simüle eder." #: Resources/Scripts/Gui/StartupScreen.as:1170 #: Resources/Scripts/Gui/StartupScreen.as:1170 msgctxt "StartupScreen" msgid "Lens Scattering Filter" -msgstr "" +msgstr "Lens Saçılma Filtresi" #: Resources/Scripts/Gui/StartupScreen.as:1171 #: Resources/Scripts/Gui/StartupScreen.as:1171 msgctxt "StartupScreen" msgid "Simulates light being scattered by dust on the camera lens." -msgstr "" +msgstr "Kamera merceÄŸindeki toz tarafından dağılan ışığın benzetimini yapar." #: Resources/Scripts/Gui/StartupScreen.as:1174 #: Resources/Scripts/Gui/StartupScreen.as:1174 msgctxt "StartupScreen" msgid "Lens Flare" -msgstr "" +msgstr "Mercek parlaması" #: Resources/Scripts/Gui/StartupScreen.as:1175 #: Resources/Scripts/Gui/StartupScreen.as:1175 msgctxt "StartupScreen" msgid "The Sun causes lens flare." -msgstr "" +msgstr "GüneÅŸ mercek parlamasına neden olur." #: Resources/Scripts/Gui/StartupScreen.as:1177 #: Resources/Scripts/Gui/StartupScreen.as:1177 msgctxt "StartupScreen" msgid "Flares for Dynamic Lights" -msgstr "" +msgstr "Dinamik Işıklar için parlamalar" #: Resources/Scripts/Gui/StartupScreen.as:1178 #: Resources/Scripts/Gui/StartupScreen.as:1178 msgctxt "StartupScreen" msgid "Enables lens flare for light sources other than the Sun." -msgstr "" +msgstr "GüneÅŸ dışındaki ışık kaynakları için mercek parlamasını etkinleÅŸtirir." #: Resources/Scripts/Gui/StartupScreen.as:1180 #: Resources/Scripts/Gui/StartupScreen.as:1180 msgctxt "StartupScreen" msgid "Color Correction" -msgstr "" +msgstr "Renk Düzeltme" #: Resources/Scripts/Gui/StartupScreen.as:1181 #: Resources/Scripts/Gui/StartupScreen.as:1181 msgctxt "StartupScreen" msgid "Applies cinematic color correction to make the image look better." -msgstr "" +msgstr "Görüntünün daha iyi görünmesi için sinematik renk düzeltmesi uygular." #: Resources/Scripts/Gui/StartupScreen.as:1183 #: Resources/Scripts/Gui/StartupScreen.as:1183 msgctxt "StartupScreen" msgid "Depth of Field" -msgstr "" +msgstr "Alan derinliÄŸi" #: Resources/Scripts/Gui/StartupScreen.as:1184 #: Resources/Scripts/Gui/StartupScreen.as:1184 msgctxt "StartupScreen" msgid "Blurs out-of-focus objects." -msgstr "" +msgstr "Odak dışı nesneleri bulanıklaÅŸtırır." #: Resources/Scripts/Gui/StartupScreen.as:1186 #: Resources/Scripts/Gui/StartupScreen.as:1186 msgctxt "StartupScreen" msgid "Screen Space Ambient Occlusion" -msgstr "" +msgstr "Ekran alanı Çevresel perdeleme" #: Resources/Scripts/Gui/StartupScreen.as:1187 #: Resources/Scripts/Gui/StartupScreen.as:1187 msgctxt "StartupScreen" msgid "Simulates soft shadows that occur between nearby objects." -msgstr "" +msgstr "Yakındaki nesneler arasında oluÅŸan yumuÅŸak gölgeleri simüle eder." #: Resources/Scripts/Gui/StartupScreen.as:1189 #: Resources/Scripts/Gui/StartupScreen.as:1228 @@ -1390,7 +1399,7 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1250 msgctxt "StartupScreen" msgid "Low" -msgstr "" +msgstr "Düşük" #: Resources/Scripts/Gui/StartupScreen.as:1190 #: Resources/Scripts/Gui/StartupScreen.as:1229 @@ -1398,7 +1407,7 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1229 msgctxt "StartupScreen" msgid "Medium" -msgstr "" +msgstr "Orta" #: Resources/Scripts/Gui/StartupScreen.as:1191 #: Resources/Scripts/Gui/StartupScreen.as:1230 @@ -1408,7 +1417,7 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1252 msgctxt "StartupScreen" msgid "High" -msgstr "" +msgstr "Yüksek" #: Resources/Scripts/Gui/StartupScreen.as:1192 #: Resources/Scripts/Gui/StartupScreen.as:1253 @@ -1416,158 +1425,158 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1253 msgctxt "StartupScreen" msgid "Ultra" -msgstr "" +msgstr "Maksimum" #: Resources/Scripts/Gui/StartupScreen.as:1195 #: Resources/Scripts/Gui/StartupScreen.as:1195 msgctxt "StartupScreen" msgid "Post-process" -msgstr "" +msgstr "Ä°ÅŸlem Sonrası" #: Resources/Scripts/Gui/StartupScreen.as:1196 #: Resources/Scripts/Gui/StartupScreen.as:1196 msgctxt "StartupScreen" msgid "Post-process modifies the image to make it look better and more realistic." -msgstr "" +msgstr "Ä°ÅŸlem sonrası, görüntüyü daha iyi ve daha gerçekçi görünmesi için deÄŸiÅŸtirir." #: Resources/Scripts/Gui/StartupScreen.as:1203 #: Resources/Scripts/Gui/StartupScreen.as:1203 msgctxt "StartupScreen" msgid "Particles|Low:Artifact occurs when a particle intersects other objects.|Medium:Particle intersects objects smoothly.|High:Particle intersects objects smoothly, and some objects casts their shadow to particles." -msgstr "" +msgstr "Parçacıklar|Düşük:Bir parçacık diÄŸer nesnelerle kesiÅŸtiÄŸinde yapaylık oluÅŸur.|Orta:Parçacık nesneleri düzgün bir ÅŸekilde keser.|Yüksek:Parçacık, nesneleri düzgün bir ÅŸekilde keser ve bazı nesneler gölgelerini parçacıklara verir." #: Resources/Scripts/Gui/StartupScreen.as:1213 #: Resources/Scripts/Gui/StartupScreen.as:1213 msgctxt "StartupScreen" msgid "Dynamic Lights" -msgstr "" +msgstr "Dinamik ışıklar" #: Resources/Scripts/Gui/StartupScreen.as:1215 #: Resources/Scripts/Gui/StartupScreen.as:1215 msgctxt "StartupScreen" msgid "Gives some objects an ability to emit light to give them an energy-emitting impression." -msgstr "" +msgstr "Bazı nesnelere enerji yayan bir izlenim vermek için ışık yayma yeteneÄŸi verir." #: Resources/Scripts/Gui/StartupScreen.as:1218 #: Resources/Scripts/Gui/StartupScreen.as:1218 msgctxt "StartupScreen" msgid "Shadows" -msgstr "" +msgstr "Gölgeler" #: Resources/Scripts/Gui/StartupScreen.as:1219 #: Resources/Scripts/Gui/StartupScreen.as:1219 msgctxt "StartupScreen" msgid "Non-static object casts a shadow." -msgstr "" +msgstr "Sabit olmayan bir nesne gölge verir." #: Resources/Scripts/Gui/StartupScreen.as:1221 #: Resources/Scripts/Gui/StartupScreen.as:1221 msgctxt "StartupScreen" msgid "Volumetric Fog" -msgstr "" +msgstr "Volumetrik Sis" #: Resources/Scripts/Gui/StartupScreen.as:1222 #: Resources/Scripts/Gui/StartupScreen.as:1222 msgctxt "StartupScreen" msgid "Simulates shadow being casted to the fog particles using a super highly computationally demanding algorithm. " -msgstr "" +msgstr "Süper yüksek hesaplama gerektiren bir algoritma kullanarak sis parçacıklarına dökülen gölgeyi simüle eder. " #: Resources/Scripts/Gui/StartupScreen.as:1225 #: Resources/Scripts/Gui/StartupScreen.as:1225 msgctxt "StartupScreen" msgid "Physically Based Lighting" -msgstr "" +msgstr "Fiziksel Tabanlı Aydınlatma" #: Resources/Scripts/Gui/StartupScreen.as:1226 #: Resources/Scripts/Gui/StartupScreen.as:1226 msgctxt "StartupScreen" msgid "Uses more accurate approximation techniques to decide the brightness of objects." -msgstr "" +msgstr "Nesnelerin parlaklığına karar vermek için daha doÄŸru yaklaşım teknikleri kullanır." #: Resources/Scripts/Gui/StartupScreen.as:1233 #: Resources/Scripts/Gui/StartupScreen.as:1233 msgctxt "StartupScreen" msgid "Direct Lights" -msgstr "" +msgstr "Direkt Işıklar" #: Resources/Scripts/Gui/StartupScreen.as:1234 #: Resources/Scripts/Gui/StartupScreen.as:1234 msgctxt "StartupScreen" msgid "Controls how light encounting a material and atmosphere directly affects its appearance." -msgstr "" +msgstr "Bir malzeme ve atmosferle karşılaÅŸan ışığın görünüşünü doÄŸrudan nasıl etkilediÄŸini kontrol eder." #: Resources/Scripts/Gui/StartupScreen.as:1244 #: Resources/Scripts/Gui/StartupScreen.as:1244 msgctxt "StartupScreen" msgid "Water Shader|None:Water is rendered in the same way that normal blocks are done.|Level 1:Refraction and the reflected Sun are simulated.|Level 2:Waving water is simulated as well as reflection and refraction.|Level 3:Reflections and refractions are rendered at the highest quality using screen-space techniques." -msgstr "" +msgstr "Su Gölgelendirici | Yok: Su, normal blokların yapıldığı gibi iÅŸlenir. | Seviye 1: Kırılma ve yansıyan GüneÅŸ simüle edilir. | Seviye 2: Dalgalanan su, yansıma ve kırılma gibi simüle edilir. | Seviye 3: Yansımalar ve kırılmalar ekran boÅŸluÄŸu teknikleri kullanılarak en yüksek kalitede gerçekleÅŸtirilir." #: Resources/Scripts/Gui/StartupScreen.as:1251 #: Resources/Scripts/Gui/StartupScreen.as:1251 msgctxt "StartupScreen" msgid "Med" -msgstr "" +msgstr "Ä°laç" #: Resources/Scripts/Gui/StartupScreen.as:1256 #: Resources/Scripts/Gui/StartupScreen.as:1256 msgctxt "StartupScreen" msgid "Shader Effects" -msgstr "" +msgstr "Gölgelendirici Efektler" #: Resources/Scripts/Gui/StartupScreen.as:1256 #: Resources/Scripts/Gui/StartupScreen.as:1256 msgctxt "StartupScreen" msgid "Special effects." -msgstr "" +msgstr "Özel Efektler." #: Resources/Scripts/Gui/StartupScreen.as:1273 #: Resources/Scripts/Gui/StartupScreen.as:1273 msgctxt "StartupScreen" msgid "Fast Mode:Reduces the image resolution to make the rendering faster.|Off|2x|4x" -msgstr "" +msgstr "Hızlı Mod: Ä°ÅŸlemeyi hızlandırmak için görüntü çözünürlüğünü azaltır. | Kapalı | 2x | 4x" #: Resources/Scripts/Gui/StartupScreen.as:1486 #: Resources/Scripts/Gui/StartupScreen.as:1486 msgctxt "StartupScreen" msgid "Audio Settings" -msgstr "" +msgstr "Ses Ayarları" #: Resources/Scripts/Gui/StartupScreen.as:1495 #: Resources/Scripts/Gui/StartupScreen.as:1495 msgctxt "StartupScreen" msgid "OpenAL" -msgstr "" +msgstr "OpenAL" #: Resources/Scripts/Gui/StartupScreen.as:1499 #: Resources/Scripts/Gui/StartupScreen.as:1499 msgctxt "StartupScreen" msgid "Uses an OpenAL-capable sound card to process sound. In most cases where there isn't such a sound card, software emulation is used." -msgstr "" +msgstr "Sesi iÅŸlemek için OpenAL özellikli bir ses kartı kullanır. Böyle bir ses kartı bulunmayan çoÄŸu durumda, yazılım benzemesi kullanılır." #: Resources/Scripts/Gui/StartupScreen.as:1508 #: Resources/Scripts/Gui/StartupScreen.as:1508 msgctxt "StartupScreen" msgid "YSR" -msgstr "" +msgstr "YSR" #: Resources/Scripts/Gui/StartupScreen.as:1512 #: Resources/Scripts/Gui/StartupScreen.as:1512 msgctxt "StartupScreen" msgid "YSR is an experimental 3D HDR sound engine optimized for OpenSpades. It features several enhanced features including automatic load control, dynamics compressor, HRTF-based 3D audio, and high quality reverb." -msgstr "" +msgstr "YSR, OpenSpades için optimize edilmiÅŸ deneysel bir 3D HDR ses motorudur. Otomatik yük kontrolü, dinamik kompresör, HRTF tabanlı 3D ses ve yüksek kaliteli yankı dahil olmak üzere çeÅŸitli geliÅŸmiÅŸ özelliklere sahiptir." #. ! The name of audio driver that outputs no audio. #: Resources/Scripts/Gui/StartupScreen.as:1523 #: Resources/Scripts/Gui/StartupScreen.as:1523 msgctxt "StartupScreen" msgid "Null" -msgstr "" +msgstr "BoÅŸ" #: Resources/Scripts/Gui/StartupScreen.as:1527 #: Resources/Scripts/Gui/StartupScreen.as:1527 msgctxt "StartupScreen" msgid "Disables audio output." -msgstr "" +msgstr "Ses çıkışını devre dışı bırakır." #: Resources/Scripts/Gui/StartupScreen.as:1538 #: Resources/Scripts/Gui/StartupScreen.as:1562 @@ -1575,109 +1584,110 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1562 msgctxt "StartupScreen" msgid "Polyphonics" -msgstr "" +msgstr "Polyphonics" #: Resources/Scripts/Gui/StartupScreen.as:1539 #: Resources/Scripts/Gui/StartupScreen.as:1539 msgctxt "StartupScreen" msgid "Specifies how many sounds can be played simultaneously. Higher value needs more processing power, so setting this too high might cause an overload (especially with a software emulation)." -msgstr "" +msgstr "Aynı anda kaç sesin çalınabileceÄŸini belirtir. Daha yüksek deÄŸer daha fazla iÅŸlem gücüne ihtiyaç duyar, bu nedenle bu deÄŸerin çok yüksek ayarlanması aşırı yüke neden olabilir (özellikle yazılım benzemesi ile)." #: Resources/Scripts/Gui/StartupScreen.as:1546 #: Resources/Scripts/Gui/StartupScreen.as:1546 msgctxt "StartupScreen" msgid "EAX" -msgstr "" +msgstr "EAX" #: Resources/Scripts/Gui/StartupScreen.as:1547 #: Resources/Scripts/Gui/StartupScreen.as:1547 msgctxt "StartupScreen" msgid "Enables extended features provided by the OpenAL driver to create more ambience." -msgstr "" +msgstr "Daha fazla ortam yaratmak için OpenAL sürücüsü tarafından saÄŸlanan geniÅŸletilmiÅŸ özellikleri etkinleÅŸtirir." #: Resources/Scripts/Gui/StartupScreen.as:1563 #: Resources/Scripts/Gui/StartupScreen.as:1563 msgctxt "StartupScreen" msgid "Specifies how many sounds can be played simultaneously. No matter what value is set, YSR might reduce the number of sounds when an overload is detected." -msgstr "" +msgstr "EÅŸ zamanlı kaç sesin çalınabileceÄŸini belirtir. Hangi deÄŸer ayarlanmış olursa olsun, YSR aşırı yük algılandığında ses sayısını azaltabilir." #: Resources/Scripts/Gui/StartupScreen.as:1623 #: Resources/Scripts/Gui/StartupScreen.as:1623 msgctxt "StartupScreen" msgid "Language" -msgstr "" +msgstr "Dil" #: Resources/Scripts/Gui/StartupScreen.as:1635 #: Resources/Scripts/Gui/StartupScreen.as:1635 msgctxt "StartupScreen" msgid "Tools" -msgstr "" +msgstr "Araçlar" #: Resources/Scripts/Gui/StartupScreen.as:1638 #: Resources/Scripts/Gui/StartupScreen.as:1638 msgctxt "StartupScreen" msgid "Reset All Settings" -msgstr "" +msgstr "Tüm ayarları Sıfırla" #: Resources/Scripts/Gui/StartupScreen.as:1647 #: Resources/Scripts/Gui/StartupScreen.as:1647 msgctxt "StartupScreen" msgid "Open Config Folder in Explorer" -msgstr "" +msgstr "Config Dosyasını Windows Gezgini'nde Aç" #: Resources/Scripts/Gui/StartupScreen.as:1649 #: Resources/Scripts/Gui/StartupScreen.as:1649 msgctxt "StartupScreen" msgid "Reveal Config Folder in Finder" -msgstr "" +msgstr "Bulucuya Yapılandırma Klasörünü Göster" #: Resources/Scripts/Gui/StartupScreen.as:1651 #: Resources/Scripts/Gui/StartupScreen.as:1651 msgctxt "StartupScreen" msgid "Browse Config Folder" -msgstr "" +msgstr "Yapılandırma Klasörüne Gözat" #: Resources/Scripts/Gui/StartupScreen.as:1668 #: Resources/Scripts/Gui/StartupScreen.as:1668 msgctxt "StartupScreen" msgid "An unknown error has occurred while opening the config directory." -msgstr "" +msgstr "Yapılandırma dizinini açarken bilinmeyen bir hata oluÅŸtu." #: Resources/Scripts/Gui/StartupScreen.as:1674 #: Resources/Scripts/Gui/StartupScreen.as:1674 msgctxt "StartupScreen" msgid "Are you sure to reset all settings? They include (but are not limited to):" -msgstr "" +msgstr "Tüm ayarları sıfırlamak istediÄŸinizden emin misiniz? Bunlar içerir (\n" +"ancak bunlarla sınırlı deÄŸildirler):" #: Resources/Scripts/Gui/StartupScreen.as:1675 #: Resources/Scripts/Gui/StartupScreen.as:1675 msgctxt "StartupScreen" msgid "All graphics/audio settings" -msgstr "" +msgstr "Tüm grafik/ses ayarları" #: Resources/Scripts/Gui/StartupScreen.as:1676 #: Resources/Scripts/Gui/StartupScreen.as:1676 msgctxt "StartupScreen" msgid "All key bindings" -msgstr "" +msgstr "Tüm tuÅŸ atamaları" #: Resources/Scripts/Gui/StartupScreen.as:1677 #: Resources/Scripts/Gui/StartupScreen.as:1677 msgctxt "StartupScreen" msgid "Your player name" -msgstr "" +msgstr "Oyuncu adınız" #: Resources/Scripts/Gui/StartupScreen.as:1678 #: Resources/Scripts/Gui/StartupScreen.as:1678 msgctxt "StartupScreen" msgid "Other advanced settings only accessible through '{0}' tab and in-game commands" -msgstr "" +msgstr "DiÄŸer geliÅŸmiÅŸ ayarlara yalnızca '{0}' sekmesi ve oyun içi komutlarla eriÅŸilebilir" #: Resources/Scripts/Gui/StartupScreen.as:1748 #: Resources/Scripts/Gui/StartupScreen.as:1748 msgctxt "StartupScreen" msgid "Unknown ({0})" -msgstr "" +msgstr "Bilinmeyen ({0})" #: Resources/Scripts/Gui/StartupScreen.as:1750 #: Resources/Scripts/Gui/StartupScreen.as:1764 @@ -1685,107 +1695,107 @@ msgstr "" #: Resources/Scripts/Gui/StartupScreen.as:1764 msgctxt "StartupScreen" msgid "System default" -msgstr "" +msgstr "Sistem varsayılanı" #: Resources/Scripts/Gui/StartupScreen.as:1813 #: Resources/Scripts/Gui/StartupScreen.as:1813 msgctxt "StartupScreen" msgid "Copy to Clipboard" -msgstr "" +msgstr "Panoya kopyala" #: Resources/Scripts/Gui/StartupScreen.as:1849 #: Resources/Scripts/Gui/StartupScreen.as:1849 msgctxt "StartupScreen" msgid "Advanced Settings" -msgstr "" +msgstr "GeliÅŸmiÅŸ Ayarlar" #: Resources/Scripts/Gui/StartupScreen.as:1858 #: Resources/Scripts/Gui/StartupScreen.as:1858 msgctxt "StartupScreen" msgid "Filter" -msgstr "" +msgstr "Filtre" #: Resources/Scripts/Gui/UpdateCheckView.as:40 #: Resources/Scripts/Gui/UpdateCheckView.as:40 msgctxt "UpdateCheck" msgid "Enable" -msgstr "" +msgstr "EtkinleÅŸtir" #: Resources/Scripts/Gui/UpdateCheckView.as:47 #: Resources/Scripts/Gui/UpdateCheckView.as:47 msgctxt "UpdateCheck" msgid "Show details..." -msgstr "" +msgstr "Detayları göster..." #: Resources/Scripts/Gui/UpdateCheckView.as:102 #: Resources/Scripts/Gui/UpdateCheckView.as:102 msgctxt "UpdateCheck" msgid "Version {0} is available! (You currently have {1})" -msgstr "" +msgstr "{0} sürümü mevcut! (Åžu anda {1} sürümü var)" #: Resources/Scripts/Gui/UpdateCheckView.as:105 #: Resources/Scripts/Gui/UpdateCheckView.as:105 msgctxt "UpdateCheck" msgid "You're using the latest version of OpenSpades. ({0})" -msgstr "" +msgstr "OpenSpades'in en güncel versiyonunu kullanıyorsunuz. ({0})" #: Resources/Scripts/Gui/UpdateCheckView.as:110 #: Resources/Scripts/Gui/UpdateCheckView.as:110 msgctxt "UpdateCheck" msgid "Checking for updates..." -msgstr "" +msgstr "Güncellemeler kontrol ediliyor..." #: Resources/Scripts/Gui/UpdateCheckView.as:113 #: Resources/Scripts/Gui/UpdateCheckView.as:113 msgctxt "UpdateCheck" msgid "Failed to check for updates." -msgstr "" +msgstr "Güncellemeler kontrol edilemedi." #: Resources/Scripts/Gui/UpdateCheckView.as:116 #: Resources/Scripts/Gui/UpdateCheckView.as:116 msgctxt "UpdateCheck" msgid "Automatic update check is not enabled." -msgstr "" +msgstr "Otomatik Güncelleme etkin deÄŸil." #: Resources/Scripts/Gui/UpdateCheckView.as:119 #: Resources/Scripts/Gui/UpdateCheckView.as:119 msgctxt "UpdateCheck" msgid "Automatic update check is not available." -msgstr "" +msgstr "Otomatik güncelleÅŸtirme kullanılabilir deÄŸil." #: Sources/Client/Client_NetHandler.cpp:258 #: Sources/Client/Client_NetHandler.cpp:271 msgctxt "Client" msgid "Spectator" -msgstr "" +msgstr "Ä°zleyici" #: Sources/Client/Client_Draw.cpp:99 msgctxt "Client" msgid "Unbound" -msgstr "" +msgstr "BaÄŸlı deÄŸil" #: Sources/Client/Client_Draw.cpp:655 msgctxt "Client" msgid "[{0}] Cycle camera mode" -msgstr "" +msgstr "[{0}] Kamera modunu çevir" #: Sources/Client/Client_Draw.cpp:657 msgctxt "Client" msgid "[{0}/{1}] Next/previous player" -msgstr "" +msgstr "[{0} / {1}] Sonraki / önceki oyuncu" #: Sources/Client/Client_Draw.cpp:661 msgctxt "Client" msgid "[{0}] Unfollow" -msgstr "" +msgstr "[{0}]'u Takibi Bırak" #: Sources/Client/Client_Draw.cpp:664 msgctxt "Client" msgid "[{0}/{1}] Follow a player" -msgstr "" +msgstr "[{0}/{1}] Bir oyuncuyu takip etti" #: Sources/Client/Client_Draw.cpp:669 msgctxt "Client" msgid "[{0}/{1}] Go up/down" -msgstr "" +msgstr "[{0} / {1}] Yukarı / aÅŸağı git" diff --git a/Resources/PackageInfo.json b/Resources/PackageInfo.json index 024f80649..af05064ec 100644 --- a/Resources/PackageInfo.json +++ b/Resources/PackageInfo.json @@ -1,6 +1,6 @@ { - "Version": [0, 1, 3, 0], - "VersionText": "0.1.3-rc", + "Version": [0, 1, 5, 0], + "VersionText": "0.1.5-beta", "UpdateFeed": { "Type": "Standard", "Platform": "SourceCode", diff --git a/Resources/Scripts/Gui/Preferences.as b/Resources/Scripts/Gui/Preferences.as index 80dee63df..6cf1bd1ec 100644 --- a/Resources/Scripts/Gui/Preferences.as +++ b/Resources/Scripts/Gui/Preferences.as @@ -214,6 +214,7 @@ namespace spades { int digits; string suffix; string prefix; + float prescale = 1; ConfigNumberFormatter(int digits, string suffix) { this.digits = digits; this.suffix = suffix; @@ -224,11 +225,19 @@ namespace spades { this.suffix = suffix; this.prefix = prefix; } + ConfigNumberFormatter(int digits, string suffix, string prefix, float prescale) { + this.digits = digits; + this.suffix = suffix; + this.prefix = prefix; + this.prescale = prescale; + } private string FormatInternal(float value) { if (value < 0.f) { return "-" + Format(-value); } + value *= prescale; + // do rounding float rounding = 0.5f; for (int i = digits; i > 0; i--) @@ -556,6 +565,10 @@ namespace spades { return slider; } + ConfigSlider @AddVolumeSlider(string caption, string configName) { + return AddSliderField(caption, configName, 0, 1, 0.01, ConfigNumberFormatter(0, "%", "", 100)); + } + void AddControl(string caption, string configName, bool enabled = true) { spades::ui::UIElement @container = CreateItem(); @@ -645,9 +658,10 @@ namespace spades { array = {2, 1, 0}); layouter.AddHeading(_Tr("Preferences", "Feedbacks")); - layouter.AddToggleField(_Tr("Preferences", "Chat Notify Sounds"), "cg_chatBeep"); + layouter.AddVolumeSlider(_Tr("Preferences", "Chat Notify Sounds"), "cg_chatBeep"); layouter.AddToggleField(_Tr("Preferences", "Hit Indicator"), "cg_hitIndicator"); layouter.AddToggleField(_Tr("Preferences", "Show Alerts"), "cg_alerts"); + layouter.AddVolumeSlider(_Tr("Preferences", "Alert Sounds"), "cg_alertSounds"); layouter.AddHeading(_Tr("Preferences", "AoS 0.75/0.76 Compatibility")); layouter.AddToggleField(_Tr("Preferences", "Allow Unicode"), "cg_unicode"); diff --git a/Resources/Scripts/Gui/StartupScreen/ConfigViewTabs.as b/Resources/Scripts/Gui/StartupScreen/ConfigViewTabs.as index 31aa379d9..ca4bdfe9e 100644 --- a/Resources/Scripts/Gui/StartupScreen/ConfigViewTabs.as +++ b/Resources/Scripts/Gui/StartupScreen/ConfigViewTabs.as @@ -113,6 +113,7 @@ namespace spades { { StartupScreenConfigView cfg(Manager); + // TODO: Add r_temporalAA when it's more complete cfg.AddRow(StartupScreenConfigSelectItemEditor( ui, StartupScreenGraphicsAntialiasConfig(ui), "0|2|4|fxaa", _Tr("StartupScreen", @@ -130,6 +131,11 @@ namespace spades { _Tr("StartupScreen", "Uses a number representation which allows wider dynamic range during rendering process. " "Additionally, this allows color calculation whose value is in linear correspondence with actual energy, " "that is, physically accurate blending can be achieved."))); + cfg.AddRow(StartupScreenConfigSelectItemEditor( + ui, StartupScreenConfig(ui, "r_vsync"), "0|1|-1", + _Tr("StartupScreen", + "Vertical Sync:Synchronizes screen updates to a monitor's refresh rate.|" "Off|" "On|" "Adaptive"))); + { StartupScreenComplexConfig cplx; cplx.AddEditor(StartupScreenConfigCheckItemEditor( @@ -191,6 +197,20 @@ namespace spades { _Tr("StartupScreen", "Particles|" "Low:Artifact occurs when a particle intersects other objects.|" "Medium:Particle intersects objects smoothly.|" "High:Particle intersects objects smoothly, and some objects casts " "their shadow to particles."))); + cfg.AddRow(StartupScreenConfigSelectItemEditor( + ui, StartupScreenConfig(ui, "r_fogShadow"), "0|1|2", + _Tr("StartupScreen", "Volumetric Fog") + "|" + + _Tr("StartupScreen", "None") + ":" + + _Tr("StartupScreen", "Disables the volumetric fog effect.") + "|" + + _Tr("StartupScreen", "Level 1") + ":" + + _Tr("StartupScreen", + "Applies local illumination to the fog.") + "|" + + _Tr("StartupScreen", "Level 2") + ":" + + _Tr("StartupScreen", + "Applies both local illumination and global illumination to the fog.") + "\n\n" + + _Tr("StartupScreen", + "Warning: {0} must be enabled.", _Tr("StartupScreen", "Global Illumination")))); + { StartupScreenComplexConfig cplx; // r_mapSoftShadow is currently no-op @@ -203,11 +223,6 @@ namespace spades { ui, StartupScreenConfig(ui, "r_modelShadows"), "0", "1", _Tr("StartupScreen", "Shadows"), _Tr("StartupScreen", "Non-static object casts a shadow."))); - cplx.AddEditor(StartupScreenConfigCheckItemEditor( - ui, StartupScreenConfig(ui, "r_fogShadow"), "0", "1", - _Tr("StartupScreen", "Volumetric Fog"), - _Tr("StartupScreen", - "Simulates shadow being casted to the fog particles using a " "super highly computationally demanding algorithm. "))); cplx.AddEditor(StartupScreenConfigCheckItemEditor( ui, StartupScreenConfig(ui, "r_physicalLighting"), "0", "1", _Tr("StartupScreen", "Physically Based Lighting"), @@ -215,11 +230,11 @@ namespace spades { "Uses more accurate approximation techniques to decide the brightness of objects."))); cplx.AddPreset( - StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "1|0|0|0")); + StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Low"), "1|0|0")); cplx.AddPreset(StartupScreenComplexConfigPreset(_Tr("StartupScreen", "Medium"), - "1|1|0|0")); + "1|1|0")); cplx.AddPreset( - StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "1|1|0|1")); + StartupScreenComplexConfigPreset(_Tr("StartupScreen", "High"), "1|1|1")); cfg.AddRow(StartupScreenConfigComplexItemEditor( ui, cplx, _Tr("StartupScreen", "Direct Lights"), @@ -457,8 +472,11 @@ namespace spades { StartupScreenConfigView @configViewOpenAL; StartupScreenConfigView @configViewYSR; + StartupScreenAudioOpenALEditor @editOpenAL; + private ConfigItem s_audioDriver("s_audioDriver"); private ConfigItem s_eax("s_eax"); + private ConfigItem s_openalDevice("s_openalDevice"); StartupScreenAudioTab(StartupScreenUI @ui, Vector2 size) { super(ui.manager); @@ -520,6 +538,7 @@ namespace spades { { StartupScreenConfigView cfg(Manager); + cfg.AddRow(StartupScreenConfigSliderItemEditor( ui, StartupScreenConfig(ui, "s_maxPolyphonics"), 16.0, 256.0, 8.0, _Tr("StartupScreen", "Polyphonics"), @@ -531,6 +550,13 @@ namespace spades { ui, StartupScreenConfig(ui, "s_eax"), "0", "1", _Tr("StartupScreen", "EAX"), _Tr("StartupScreen", "Enables extended features provided by the OpenAL driver to create " "more ambience."))); + AddLabel(0.f, 90.f, 20.f, _Tr("StartupScreen", "Devices")); + { + StartupScreenAudioOpenALEditor e(ui); + AddChild(e); + @editOpenAL = e; + cfg.AddRow(editOpenAL); + } cfg.Finalize(); cfg.SetHelpTextHandler(HelpTextHandler(this.HandleHelpText)); @@ -593,6 +619,71 @@ namespace spades { ui.helper.CheckConfigCapability("s_audioDriver", "null").length == 0; configViewOpenAL.LoadConfig(); configViewYSR.LoadConfig(); + editOpenAL.LoadConfig(); + + s_openalDevice.StringValue = editOpenAL.openal.StringValue; + } + } + + class StartupScreenAudioOpenALEditor : spades::ui::UIElement, LabelAddable { + StartupScreenUI @ui; + StartupScreenHelper @helper; + ConfigItem openal("openal"); + + spades::ui::Button @dropdownButton; + + StartupScreenAudioOpenALEditor(StartupScreenUI @ui) { + super(ui.manager); + @this.ui = ui; + @helper = ui.helper; + { + StartupScreenDropdownListDropdownButton e(Manager); + AddChild(e); + e.Bounds = AABB2(80.f, 0.f, 400.f, 20.f); + @e.Activated = spades::ui::EventHandler(this.ShowDropdown); + @dropdownButton = e; + } + } + + void LoadConfig() { + string drivername = openal.StringValue; + string name = _Tr("StartupScreen", "Default device", drivername); + if (drivername == "") { + name = _Tr("StartupScreen", "Default device"); + } + + int cnt = helper.GetNumAudioOpenALDevices(); + for (int i = 0; i < cnt; i++) { + if (drivername == helper.GetAudioOpenALDevice(i)) { + name = helper.GetAudioOpenALDevice(i); + } + } + + dropdownButton.Caption = name; + } + + private void ShowDropdown(spades::ui::UIElement @) { + string[] items = {_Tr("StartupScreen", "Default device")}; + int cnt = helper.GetNumAudioOpenALDevices(); + for (int i = 0; i < cnt; i++) { + string s = helper.GetAudioOpenALDevice(i); + items.insertLast(s); + } + spades::ui::ShowDropDownList(this, items, + spades::ui::DropDownListHandler(this.DropdownHandler)); + } + + private void DropdownHandler(int index) { + if (index >= 0) { + if (index == 0) { + openal = "default"; + } else { + openal = helper.GetAudioOpenALDevice(index - 1); + } + + // Reload the startup screen so the language config takes effect + ui.Reload(); + } } } diff --git a/Resources/Scripts/Gui/StartupScreen/MainMenu.as b/Resources/Scripts/Gui/StartupScreen/MainMenu.as index 6a8d87add..ecd2e2a59 100644 --- a/Resources/Scripts/Gui/StartupScreen/MainMenu.as +++ b/Resources/Scripts/Gui/StartupScreen/MainMenu.as @@ -69,6 +69,10 @@ namespace spades { @bypassStartupWindowCheck = button; @button.Activated = spades::ui::EventHandler(this.OnBypassStartupWindowCheckChanged); + + if (ui.isPrereleaseVersion) { + button.Visible = false; + } } { UpdateCheckView view(Manager, ui.helper.PackageUpdateManager); diff --git a/Resources/Scripts/Gui/StartupScreen/StartupScreenUI.as b/Resources/Scripts/Gui/StartupScreen/StartupScreenUI.as index ad8e4c03d..304519725 100644 --- a/Resources/Scripts/Gui/StartupScreen/StartupScreenUI.as +++ b/Resources/Scripts/Gui/StartupScreen/StartupScreenUI.as @@ -33,6 +33,7 @@ namespace spades { StartupScreenMainMenu @mainMenu; bool shouldExit = false; + bool isPrereleaseVersion; StartupScreenUI(Renderer @renderer, AudioDevice @audioDevice, FontManager @fontManager, StartupScreenHelper @helper) { @@ -49,6 +50,10 @@ namespace spades { } private void Init() { + // As per + PackageUpdateManager@ updateManager = this.helper.PackageUpdateManager; + isPrereleaseVersion = updateManager.CurrentVersionInfo.Build < 4; + @mainMenu = StartupScreenMainMenu(this); mainMenu.Bounds = manager.RootElement.Bounds; manager.RootElement.AddChild(mainMenu); @@ -96,7 +101,19 @@ namespace spades { renderer.ColorNP = Vector4(1.f, 1.f, 1.f, 1.f); renderer.DrawImage(img, AABB2(10.f, 10.f, img.Width, img.Height)); - manager.RunFrame(dt); + if (isPrereleaseVersion) { + Font @font = manager.RootElement.Font; + string text = "Pre-release Version"; + Vector2 position(225.0f, 34.0f); + font.DrawShadow(text, position, + 1.0, Vector4(0.0f, 0.0f, 0.0f, 1.0f), + Vector4(1.0f, 0.5f, 0.5f, 1.0f)); + font.DrawShadow(text, position, + 1.0, Vector4(1.0f, 0.7f, 0.7f, 1.0f), + Vector4(1.0f, 0.5f, 0.5f, 1.0f)); + } + + manager.RunFrame(dt); manager.Render(); } diff --git a/Resources/Scripts/Reference/API/Renderer.as b/Resources/Scripts/Reference/API/Renderer.as index b73496a65..f2e9973fb 100644 --- a/Resources/Scripts/Reference/API/Renderer.as +++ b/Resources/Scripts/Reference/API/Renderer.as @@ -227,6 +227,7 @@ namespace spades { class DynamicLightParam { DynamicLightType type; Vector3 origin; + Vector3 point2; float radius; Vector3 color; diff --git a/Resources/Scripts/Reference/Skin/IWeaponSkin.as b/Resources/Scripts/Reference/Skin/IWeaponSkin.as index 2c73f5eb3..4f2a073c1 100644 --- a/Resources/Scripts/Reference/Skin/IWeaponSkin.as +++ b/Resources/Scripts/Reference/Skin/IWeaponSkin.as @@ -60,4 +60,9 @@ namespace spades { void ReloadedWeapon(); } + // TODO: IWeaponSkin2 + + interface IWeaponSkin3 { + Vector3 MuzzlePosition { get; } + } } diff --git a/Resources/Scripts/Skin/BasicViewWeapon.as b/Resources/Scripts/Skin/BasicViewWeapon.as index 81bb0aa1f..51ecfad9a 100644 --- a/Resources/Scripts/Skin/BasicViewWeapon.as +++ b/Resources/Scripts/Skin/BasicViewWeapon.as @@ -19,7 +19,13 @@ */ namespace spades { - class BasicViewWeapon : IToolSkin, IViewToolSkin, IWeaponSkin, IWeaponSkin2 { + class BasicViewWeapon : + IToolSkin, + IViewToolSkin, + IWeaponSkin, + IWeaponSkin2, + IWeaponSkin3 + { // IToolSkin protected float sprintState; protected float raiseState; @@ -131,6 +137,15 @@ namespace spades { set {} } + // IWeaponSkin3 + Vector3 MuzzlePosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, 0.35f, -0.05f); } + } + + Vector3 CaseEjectPosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, -0.1f, -0.05f); } + } + protected Renderer @renderer; protected Image @sightImage; diff --git a/Resources/Scripts/Skin/Rifle/ThirdPerson.as b/Resources/Scripts/Skin/Rifle/ThirdPerson.as index 34fc81764..7da6fca86 100644 --- a/Resources/Scripts/Skin/Rifle/ThirdPerson.as +++ b/Resources/Scripts/Skin/Rifle/ThirdPerson.as @@ -19,7 +19,13 @@ */ namespace spades { - class ThirdPersonRifleSkin : IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 { + class ThirdPersonRifleSkin : + IToolSkin, + IThirdPersonToolSkin, + IWeaponSkin, + IWeaponSkin2, + IWeaponSkin3 + { private float sprintState; private float raiseState; private Vector3 teamColor; @@ -91,6 +97,15 @@ namespace spades { set { soundOrigin = value; } } + // IWeaponSkin3 + Vector3 MuzzlePosition { + get { return originMatrix * Vector3(0.35f, -1.85f, -0.125f); } + } + + Vector3 CaseEjectPosition { + get { return originMatrix * Vector3(0.35f, -0.7f, -0.125f); } + } + private Renderer @renderer; private AudioDevice @audioDevice; private Model @model; diff --git a/Resources/Scripts/Skin/Rifle/View.as b/Resources/Scripts/Skin/Rifle/View.as index 82f365e40..f6074f864 100644 --- a/Resources/Scripts/Skin/Rifle/View.as +++ b/Resources/Scripts/Skin/Rifle/View.as @@ -19,7 +19,13 @@ */ namespace spades { - class ViewRifleSkin : IToolSkin, IViewToolSkin, IWeaponSkin, BasicViewWeapon { + class ViewRifleSkin : + IToolSkin, + IViewToolSkin, + IWeaponSkin, + IWeaponSkin3, + BasicViewWeapon + { private AudioDevice @audioDevice; private Model @gunModel; @@ -88,6 +94,15 @@ namespace spades { float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.0520f; } + // IWeaponSkin3 (override BasicViewWeapon::{get_MuzzlePosition, get_CaseEjectPosition}) + Vector3 MuzzlePosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, 0.7f, -0.05f); } + } + + Vector3 CaseEjectPosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, -0.1f, -0.05f); } + } + // rotates gun matrix to ensure the sight is in // the center of screen (0, ?, 0). Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) { diff --git a/Resources/Scripts/Skin/SMG/ThirdPerson.as b/Resources/Scripts/Skin/SMG/ThirdPerson.as index fd9bb5649..80c0a5264 100644 --- a/Resources/Scripts/Skin/SMG/ThirdPerson.as +++ b/Resources/Scripts/Skin/SMG/ThirdPerson.as @@ -19,7 +19,13 @@ */ namespace spades { - class ThirdPersonSMGSkin : IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 { + class ThirdPersonSMGSkin : + IToolSkin, + IThirdPersonToolSkin, + IWeaponSkin, + IWeaponSkin2, + IWeaponSkin3 + { private float sprintState; private float raiseState; private Vector3 teamColor; @@ -91,6 +97,15 @@ namespace spades { set { soundOrigin = value; } } + // IWeaponSkin3 + Vector3 MuzzlePosition { + get { return originMatrix * Vector3(0.35f, -1.4f, -0.125f); } + } + + Vector3 CaseEjectPosition { + get { return originMatrix * Vector3(0.35f, -0.8f, -0.125f); } + } + private Renderer @renderer; private AudioDevice @audioDevice; private Model @model; diff --git a/Resources/Scripts/Skin/SMG/View.as b/Resources/Scripts/Skin/SMG/View.as index 588dd22d2..9b230044d 100644 --- a/Resources/Scripts/Skin/SMG/View.as +++ b/Resources/Scripts/Skin/SMG/View.as @@ -19,7 +19,14 @@ */ namespace spades { - class ViewSMGSkin : IToolSkin, IViewToolSkin, IWeaponSkin, IWeaponSkin2, BasicViewWeapon { + class ViewSMGSkin : + IToolSkin, + IViewToolSkin, + IWeaponSkin, + IWeaponSkin2, + IWeaponSkin3, + BasicViewWeapon + { private AudioDevice @audioDevice; private Model @gunModel; @@ -106,6 +113,15 @@ namespace spades { float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.038f; } + // IWeaponSkin3 (override BasicViewWeapon::{get_MuzzlePosition, get_CaseEjectPosition}) + Vector3 MuzzlePosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, 0.35f, -0.05f); } + } + + Vector3 CaseEjectPosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, -0.1f, -0.05f); } + } + // rotates gun matrix to ensure the sight is in // the center of screen (0, ?, 0). Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) { diff --git a/Resources/Scripts/Skin/Shotgun/ThirdPerson.as b/Resources/Scripts/Skin/Shotgun/ThirdPerson.as index b4167483c..7000f0683 100644 --- a/Resources/Scripts/Skin/Shotgun/ThirdPerson.as +++ b/Resources/Scripts/Skin/Shotgun/ThirdPerson.as @@ -19,7 +19,13 @@ */ namespace spades { - class ThirdPersonShotgunSkin : IToolSkin, IThirdPersonToolSkin, IWeaponSkin, IWeaponSkin2 { + class ThirdPersonShotgunSkin : + IToolSkin, + IThirdPersonToolSkin, + IWeaponSkin, + IWeaponSkin2, + IWeaponSkin3 + { private float sprintState; private float raiseState; private Vector3 teamColor; @@ -91,6 +97,15 @@ namespace spades { set { soundOrigin = value; } } + // IWeaponSkin3 + Vector3 MuzzlePosition { + get { return originMatrix * Vector3(0.35f, -1.55f, -0.15f); } + } + + Vector3 CaseEjectPosition { + get { return originMatrix * Vector3(0.35f, -0.8f, -0.15f); } + } + private Renderer @renderer; private AudioDevice @audioDevice; private Model @model; diff --git a/Resources/Scripts/Skin/Shotgun/View.as b/Resources/Scripts/Skin/Shotgun/View.as index a9ba6a7a7..9c2a33063 100644 --- a/Resources/Scripts/Skin/Shotgun/View.as +++ b/Resources/Scripts/Skin/Shotgun/View.as @@ -19,7 +19,13 @@ */ namespace spades { - class ViewShotgunSkin : IToolSkin, IViewToolSkin, IWeaponSkin, BasicViewWeapon { + class ViewShotgunSkin : + IToolSkin, + IViewToolSkin, + IWeaponSkin, + IWeaponSkin3, + BasicViewWeapon + { private AudioDevice @audioDevice; private Model @gunModel; @@ -99,6 +105,15 @@ namespace spades { float GetZPos() { return 0.2f - AimDownSightStateSmooth * 0.0535f; } + // IWeaponSkin3 (override BasicViewWeapon::{get_MuzzlePosition, get_CaseEjectPosition}) + Vector3 MuzzlePosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, 0.35f, -0.1f); } + } + + Vector3 CaseEjectPosition { + get { return eyeMatrix * GetViewWeaponMatrix() * Vector3(0.0, -0.1f, -0.1f); } + } + // rotates gun matrix to ensure the sight is in // the center of screen (0, ?, 0). Matrix4 AdjustToAlignSight(Matrix4 mat, Vector3 sightPos, float fade) { diff --git a/Resources/Shaders/BasicBlock.vs b/Resources/Shaders/BasicBlock.vs index efa622848..2ce810382 100644 --- a/Resources/Shaders/BasicBlock.vs +++ b/Resources/Shaders/BasicBlock.vs @@ -71,7 +71,6 @@ void main() { vec3 fixedPosition = chunkPosition; fixedPosition += fixedPositionAttribute * 0.5; - fixedPosition += normalAttribute * 0.1; vec3 normal = normalAttribute; vec3 shadowVertexPos = vertexPos.xyz; diff --git a/Resources/Shaders/BasicBlockPhys.vs b/Resources/Shaders/BasicBlockPhys.vs index 733662d06..6f5281a5f 100644 --- a/Resources/Shaders/BasicBlockPhys.vs +++ b/Resources/Shaders/BasicBlockPhys.vs @@ -80,7 +80,6 @@ void main() { vec3 fixedPosition = chunkPosition; fixedPosition += fixedPositionAttribute * 0.5; - fixedPosition += normalAttribute * 0.1; vec3 normal = normalAttribute; vec3 shadowVertexPos = vertexPos.xyz; diff --git a/Resources/Shaders/DynamicLight/Common.vs b/Resources/Shaders/DynamicLight/Common.vs index b6adbb233..c1e9349ca 100644 --- a/Resources/Shaders/DynamicLight/Common.vs +++ b/Resources/Shaders/DynamicLight/Common.vs @@ -23,6 +23,10 @@ uniform vec3 dynamicLightOrigin; uniform mat4 dynamicLightSpotMatrix; +uniform bool dynamicLightIsLinear; +uniform vec3 dynamicLightLinearDirection; +uniform float dynamicLightLinearLength; + void PrepareForShadow_Map(vec3 vertexCoord) ; @@ -32,8 +36,18 @@ varying vec3 lightTexCoord; void PrepareForDynamicLightNoBump(vec3 vertexCoord, vec3 normal) { PrepareForShadow_Map(vertexCoord); - - lightPos = dynamicLightOrigin - vertexCoord; + + vec3 lightPosition = dynamicLightOrigin; + + if (dynamicLightIsLinear) { + // Linear light approximation - choose the closest point on the light + // geometry as the representative light source + float d = dot((vertexCoord - dynamicLightOrigin), dynamicLightLinearDirection); + d = clamp(d, 0.0, dynamicLightLinearLength); + lightPosition += dynamicLightLinearDirection * d; + } + + lightPos = lightPosition - vertexCoord; lightNormal = normal; // projection diff --git a/Resources/Shaders/PostFilters/BilateralFilter.fs b/Resources/Shaders/PostFilters/BilateralFilter.fs index 975069f28..5d10a39a6 100644 --- a/Resources/Shaders/PostFilters/BilateralFilter.fs +++ b/Resources/Shaders/PostFilters/BilateralFilter.fs @@ -33,13 +33,19 @@ float decodeDepth(float w, float near, float far){ } void main() { - float centerDepth = texture2D(depthTexture, texCoord).x; - if (centerDepth >= 0.999999) { + float centerDepthRaw = texture2D(depthTexture, texCoord).x; + + // A tangent at `texCoord` in `depthTexture` + float centerDepthRawDfdx = dFdx(centerDepthRaw); + float centerDepthRawDfdy = dFdy(centerDepthRaw); + float centerDepthRawDfdi = + dot(vec2(centerDepthRawDfdx, centerDepthRawDfdy), unitShift / vec2(dFdx(texCoord.x), dFdy(texCoord.y))); + + if (centerDepthRaw >= 0.999999) { // skip background gl_FragColor = vec4(1.0); return; } - centerDepth = decodeDepth(centerDepth, zNearFar.x, zNearFar.y); vec2 sum = vec2(0.0000001); if (isUpsampling) { @@ -47,6 +53,10 @@ void main() { inputOriginCoord *= pixelShift.xy * 2.0; for (float i = -4.0; i <= 4.0; i += 2.0) { + // Extrapolate the depth value using the tangent + float centerDepthRawInterpolated = centerDepthRaw + centerDepthRawDfdi * i; + float centerDepth = decodeDepth(centerDepthRawInterpolated, zNearFar.x, zNearFar.y); + vec2 sampledCoord = inputOriginCoord + unitShift * i; float sampledDepth = texture2D(depthTexture, sampledCoord).x; sampledDepth = decodeDepth(sampledDepth, zNearFar.x, zNearFar.y); @@ -61,6 +71,10 @@ void main() { } else { for (float i = -4.0; i <= 4.0; i += 1.0) { + // Extrapolate the depth value using the tangent + float centerDepthRawInterpolated = centerDepthRaw + centerDepthRawDfdi * i; + float centerDepth = decodeDepth(centerDepthRawInterpolated, zNearFar.x, zNearFar.y); + vec2 sampledCoord = texCoord + unitShift * i; float sampledDepth = texture2D(depthTexture, sampledCoord).x; sampledDepth = decodeDepth(sampledDepth, zNearFar.x, zNearFar.y); diff --git a/Resources/Shaders/PostFilters/ColorCorrection.fs b/Resources/Shaders/PostFilters/ColorCorrection.fs index 6e707b517..04e05ee45 100644 --- a/Resources/Shaders/PostFilters/ColorCorrection.fs +++ b/Resources/Shaders/PostFilters/ColorCorrection.fs @@ -20,22 +20,93 @@ uniform sampler2D mainTexture; +uniform sampler2D blurredTexture; varying vec2 texCoord; uniform float enhancement; uniform float saturation; uniform vec3 tint; +uniform float sharpening; +uniform float sharpeningFinalGain; +uniform float blurPixelShift; vec3 acesToneMapping(vec3 x) { return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0); } +// 1/(dacesToneMapping(x)/dx) +float acesToneMappingDiffRcp(float color) { + float denom = 0.0576132 + color * (0.242798 + color); + return (denom * denom) / (0.0007112 + color * (0.11902 + color * 0.238446)); +} + void main() { // Input is in the device color space gl_FragColor = texture2D(mainTexture, texCoord); + if (sharpeningFinalGain > 0.0) { + // generated by ./1dgaussGen.rb + // pixelShift is texture coord shift / texture pixel + float pixelShift = blurPixelShift; + float shift1 = pixelShift * -2.30654399138844; + const float scale1 = 0.178704407070903; + float shift2 = pixelShift * -0.629455560633963; + const float scale2 = 0.321295592929097; + float shift3 = pixelShift * 0.629455560633963; + const float scale3 = 0.321295592929097; + float shift4 = pixelShift * 2.30654399138844; + const float scale4 = 0.178704407070903; + + vec4 blurred = texture2D(blurredTexture, texCoord + vec2(0.0, shift1)) * scale1; + blurred += texture2D(blurredTexture, texCoord + vec2(0.0, shift2)) * scale2; + blurred += texture2D(blurredTexture, texCoord + vec2(0.0, shift3)) * scale3; + blurred += texture2D(blurredTexture, texCoord + vec2(0.0, shift4)) * scale4; + + // `sharpening` tells to what extent we must enhance the edges based on + // global factors. + float enhancingFactor = sharpening; +#if USE_HDR + // Now we take the derivative of `acesToneMapping` into consideration. + // Specifially, when `acesToneMapping` reduces the color contrast + // around the current pixel by N times, we compensate by scaling + // `enhancingFactor` by N. + float localLuminance = dot(blurred.xyz, vec3(1. / 3.)); + float localLuminanceLinear = clamp(localLuminance * localLuminance, 0.0, 1.0); + enhancingFactor *= acesToneMappingDiffRcp(localLuminanceLinear * 0.8); + + // We don't want specular highlights to cause black edges, so weaken the + // effect if the local luminance is high. + localLuminance = max(localLuminance, dot(gl_FragColor.xyz, vec3(1. / 3.))); + if (localLuminance > 1.0) { + localLuminance -= 1.0; + enhancingFactor *= 1.0 - (localLuminance + localLuminance * localLuminance) * 100.0; + } +#endif + + // Clamp the sharpening effect's intensity. + enhancingFactor = clamp(enhancingFactor, 1.0, 4.0); + + // Derive the value of `localSharpening` that achieves the desired + // contrast enhancement. When `sharpeningFinalGain = 1`, the sharpening + // effect multiplies the color contrast exactly by `enhancingFactor`. + float localSharpening = (enhancingFactor - 1.0) * sharpeningFinalGain; + + // Given a parameter value `localSharpening`, the sharpening kernel defined + // in here enhances the color difference across a horizontal or vertical + // edge by the following factor: + // + // r_sharp = 1 + localSharpening + + // Sharpening is done by reversing the effect of the blur kernel. + // Clamp the lower bound to suppress the black edges around specular highlights. + vec3 lowerBound = gl_FragColor.xyz * 0.6; + gl_FragColor.xyz += (gl_FragColor.xyz - blurred.xyz) * localSharpening; + gl_FragColor.xyz = max(gl_FragColor.xyz, lowerBound); + } + + // Apply tinting and manual exposure gl_FragColor.xyz *= tint; vec3 gray = vec3(dot(gl_FragColor.xyz, vec3(1. / 3.))); diff --git a/Resources/Shaders/PostFilters/Fog2.fs b/Resources/Shaders/PostFilters/Fog2.fs new file mode 100644 index 000000000..8bc1c4e86 --- /dev/null +++ b/Resources/Shaders/PostFilters/Fog2.fs @@ -0,0 +1,213 @@ +/* + Copyright (c) 2021 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +uniform sampler2D colorTexture; +uniform sampler2D depthTexture; +uniform sampler2D shadowMapTexture; +uniform sampler2D ditherTexture; +uniform sampler3D ambientShadowTexture; +uniform sampler3D radiosityTexture; +uniform sampler2D noiseTexture; + +const int NoiseTextureSize = 128; + +uniform vec3 viewOrigin; +uniform vec3 sunlightScale; +uniform vec3 ambientScale; +uniform vec3 radiosityScale; +uniform float fogDistance; +uniform mat4 viewProjectionMatrixInv; +uniform vec2 ditherOffset; + +varying vec2 texCoord; +varying vec4 viewcentricWorldPositionPartial; + +/** + * Transform the given world-space coordinates to the map-shadow space coordinates. + * This function is linear. + */ +vec3 transformToShadow(vec3 v) { + v.y -= v.z; + v *= vec3(1. / 512., 1. / 512., 1. / 255.); + return v; +} + +vec3 DecodeRadiosityValue(vec3 val) { + // reverse bias + val *= 1023. / 1022.; + val = (val * 2.) - 1.; +#if USE_RADIOSITY == 1 + // the low-precision radiosity texture uses a non-linear encoding + val *= val * sign(val); +#endif + return val; +} + +void main() { + float localClipZ = texture2D(depthTexture, texCoord).x; + vec4 viewcentricWorldPosition = + viewcentricWorldPositionPartial + viewProjectionMatrixInv * vec4(0.0, 0.0, localClipZ, 0.0); + viewcentricWorldPosition.xyz /= viewcentricWorldPosition.w; + + // Clip the ray by the VOXLAP fog end distance. (We don't want objects outside + // the view distance to affect the fog shading.) + float voxlapDistanceSq = dot(viewcentricWorldPosition.xy, viewcentricWorldPosition.xy); + viewcentricWorldPosition /= max(sqrt(voxlapDistanceSq) / fogDistance, 1.0); + voxlapDistanceSq = min(voxlapDistanceSq, fogDistance * fogDistance); + + // Calculate the supposed fog factor of the current pixel based on the + // VOXLAP's cylindrical fog density model. + float goalFogFactor = min(voxlapDistanceSq / (fogDistance * fogDistance), 1.0); + if (localClipZ == 1.0) { + // The sky should have the fog color. + goalFogFactor = 1.0; + } + + // OpenSpades' fog model uses a Rayleigh-scattering-style wavelength- + // dependent fog density. (See `Shaders/Fog.vs`) + vec3 goalFogFactorColor; + { + float weakenedDensity = 1. - goalFogFactor; + weakenedDensity *= weakenedDensity; + goalFogFactorColor = + mix(vec3(goalFogFactor), vec3(1. - weakenedDensity), vec3(0., 0.3, 1.0)); + } + + // --------------------------------------------------------------------- + // Calculate the in-scattering radiance (the amount of incoming light scattered + // toward the camera). + + float weightSum = 0.0; + const int numSamples = 16; + + // Dithered sampling + float dither2a = + texture2D(ditherTexture, gl_FragCoord.yx * 0.25 + ditherOffset + vec2(0.25, 0.0)).x * 15.0 / + 16.0 - + 0.5; + float dither2b = + texture2D(ditherTexture, gl_FragCoord.yx * 0.25 + ditherOffset.yx + vec2(0.0, 0.5)).x * 15.0 / + 16.0 - + 0.5; + + // Add jitter based on a noise texture because the dither pattern solely + // does not remove banding. The dither pattern is mostly useless for the + // raymarching sampling position offset (`dither`). On the other hand, it's + // more effective for soft shadowing. + vec4 noiseValue = texture2D(noiseTexture, gl_FragCoord.xy / float(NoiseTextureSize)); + float dither = noiseValue.x; + dither2a = (dither2a * 7.0 / 8.0) + (noiseValue.y - 0.5) / 8.0; + dither2b = (dither2b * 7.0 / 8.0) + (noiseValue.z - 0.5) / 8.0; + + // Shadows closer to the camera should be more visible + float weight = 1.0; + float weightDelta = sqrt(voxlapDistanceSq) / fogDistance / float(numSamples); + + weight -= weightDelta * dither; + + // Shadow map sampling + vec3 currentShadowPosition = transformToShadow(viewOrigin); + vec3 shadowPositionDelta = transformToShadow(viewcentricWorldPosition.xyz / float(numSamples)); + + currentShadowPosition += shadowPositionDelta * dither; + currentShadowPosition += + vec3(dither2a, dither2b, max(0.0, -dither2b)) / 512.0; // cheap soft shadowing + + float sunlightFactor = 0.0; + + // AO sampling + vec3 currentRadiosityTextureCoord = (viewOrigin + vec3(0., 0., 0.)) / vec3(512., 512., 64.); + vec3 radiosityTextureCoordDelta = + viewcentricWorldPosition.xyz / float(numSamples) / vec3(512., 512., 64.); + + currentRadiosityTextureCoord += radiosityTextureCoordDelta * dither; + + float ambientFactor = 0.0; + + // Secondary diffuse reflection sampling + vec3 currentAmbientShadowTextureCoord = + (viewOrigin + vec3(0.0, 0.0, 1.0)) / vec3(512., 512., 65.); + vec3 ambientShadowTextureCoordDelta = + viewcentricWorldPosition.xyz / float(numSamples) / vec3(512., 512., 65.); + vec3 radiosityFactor = vec3(0.0); + float currentRadiosityCutoff = currentAmbientShadowTextureCoord.z * 10.0 + 1.0; + float radiosityCutoffDelta = ambientShadowTextureCoordDelta.z * 10.0; + + currentAmbientShadowTextureCoord += ambientShadowTextureCoordDelta * dither; + + for (int i = 0; i < numSamples; ++i) { + // Shadow map sampling + float val = texture2D(shadowMapTexture, currentShadowPosition.xy).w; + val = step(currentShadowPosition.z, val); + sunlightFactor += val * weight; + + // AO sampling + float aoFactor = texture3D(ambientShadowTexture, currentAmbientShadowTextureCoord).x; + aoFactor = max(aoFactor, 0.); // for some reason, mainTexture value becomes negative(?) + ambientFactor += aoFactor * weight; + + // Secondary diffuse reflection sampling + // + // Since the radiosity texture doesn't have the information above the `z = 0` plane, + // gradually reduce the influence above the plane by multiplying `currentRadiosityCutoff`. + vec3 radiosity = + DecodeRadiosityValue(texture3D(radiosityTexture, currentRadiosityTextureCoord).xyz); + radiosityFactor += radiosity * (weight * clamp(currentRadiosityCutoff, 0.0, 1.0)); + + currentShadowPosition += shadowPositionDelta; + currentRadiosityTextureCoord += radiosityTextureCoordDelta; + currentAmbientShadowTextureCoord += ambientShadowTextureCoordDelta; + currentRadiosityCutoff += radiosityCutoffDelta; + weightSum += weight; + + weight -= weightDelta; + } + + vec3 sunlightFactorColor = sunlightFactor * sunlightScale; + vec3 ambientFactorColor = ambientFactor * ambientScale; + radiosityFactor *= radiosityScale; + + // Rescale the in-scattering term according to the desired fog density + vec3 scale = goalFogFactorColor / (weightSum + 1.0e-4); + radiosityFactor *= scale; + sunlightFactorColor *= scale; + ambientFactorColor *= scale; + + // --------------------------------------------------------------------- + + // add gradient + vec3 sunDir = normalize(vec3(0., -1., -1.)); + float bright = dot(sunDir, normalize(viewcentricWorldPosition.xyz)); + sunlightFactorColor *= bright * 0.5 + 1.0; + ambientFactorColor *= bright * 0.5 + 1.0; + + // --------------------------------------------------------------------- + + gl_FragColor = texture2D(colorTexture, texCoord); +#if !LINEAR_FRAMEBUFFER + gl_FragColor.xyz *= gl_FragColor.xyz; // linearize +#endif + + gl_FragColor.xyz += sunlightFactorColor + ambientFactorColor + radiosityFactor; + +#if !LINEAR_FRAMEBUFFER + gl_FragColor.xyz = sqrt(gl_FragColor.xyz); +#endif +} diff --git a/Resources/Shaders/PostFilters/Fog2.program b/Resources/Shaders/PostFilters/Fog2.program new file mode 100644 index 000000000..a67e5e082 --- /dev/null +++ b/Resources/Shaders/PostFilters/Fog2.program @@ -0,0 +1,2 @@ +Shaders/PostFilters/Fog2.fs +Shaders/PostFilters/Fog2.vs diff --git a/Resources/Shaders/PostFilters/Fog2.vs b/Resources/Shaders/PostFilters/Fog2.vs new file mode 100644 index 000000000..a5a3b2a1a --- /dev/null +++ b/Resources/Shaders/PostFilters/Fog2.vs @@ -0,0 +1,38 @@ +/* + Copyright (c) 2021 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +attribute vec2 positionAttribute; +attribute vec4 colorAttribute; + +uniform mat4 viewProjectionMatrixInv; + +varying vec2 texCoord; +varying vec4 viewcentricWorldPositionPartial; + +void main() { + vec2 pos = positionAttribute; + + vec2 scrPos = pos * 2. - 1.; + gl_Position = vec4(scrPos, 0.5, 1.); + + texCoord = pos; + + viewcentricWorldPositionPartial = viewProjectionMatrixInv * vec4(pos, 0.0, 1.0); +} diff --git a/Resources/Shaders/PostFilters/ResampleBicubic.fs b/Resources/Shaders/PostFilters/ResampleBicubic.fs new file mode 100644 index 000000000..c6bbdf682 --- /dev/null +++ b/Resources/Shaders/PostFilters/ResampleBicubic.fs @@ -0,0 +1,88 @@ +/* + Copyright (c) 2021 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +/* + * This bi-cubic spline interpolation code is based on + * + * http://www.dannyruijters.nl/cubicinterpolation/ + * https://github.com/DannyRuijters/CubicInterpolationCUDA + * + * @license Copyright (c) 2008-2013, Danny Ruijters. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + */ +void bspline_weights(vec2 fraction, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) { + vec2 one_frac = 1.0 - fraction; + vec2 squared = fraction * fraction; + vec2 one_sqd = one_frac * one_frac; + + w0 = 1.0 / 6.0 * one_sqd * one_frac; + w1 = 2.0 / 3.0 - 0.5 * squared * (2.0 - fraction); + w2 = 2.0 / 3.0 - 0.5 * one_sqd * (2.0 - one_frac); + w3 = 1.0 / 6.0 * squared * fraction; +} + +vec3 cubicTex2D(sampler2D tex, vec2 coord, vec2 inverseTexSize) { + // transform the coordinate from [0,extent] to [-0.5, extent-0.5] + vec2 coord_grid = coord - 0.5; + vec2 index = floor(coord_grid); + vec2 fraction = coord_grid - index; + vec2 w0, w1, w2, w3; + bspline_weights(fraction, w0, w1, w2, w3); + + vec2 g0 = w0 + w1; + vec2 g1 = w2 + w3; + vec2 h0 = + (w1 / g0) - vec2(0.5) + index; // h0 = w1/g0 - 1, move from [-0.5, extent-0.5] to [0, extent] + vec2 h1 = + (w3 / g1) + vec2(1.5) + index; // h1 = w3/g1 + 1, move from [-0.5, extent-0.5] to [0, extent] + + // fetch the four linear interpolations + vec3 tex00 = texture2D(tex, vec2(h0.x, h0.y) * inverseTexSize).xyz; + vec3 tex10 = texture2D(tex, vec2(h1.x, h0.y) * inverseTexSize).xyz; + vec3 tex01 = texture2D(tex, vec2(h0.x, h1.y) * inverseTexSize).xyz; + vec3 tex11 = texture2D(tex, vec2(h1.x, h1.y) * inverseTexSize).xyz; + + // weigh along the y-direction + tex00 = g0.y * tex00 + g1.y * tex01; + tex10 = g0.y * tex10 + g1.y * tex11; + + // weigh along the x-direction + return (g0.x * tex00 + g1.x * tex10); +} + +uniform sampler2D mainTexture; +uniform vec2 inverseVP; + +varying vec2 texCoord; + +void main() { + gl_FragColor.xyz = cubicTex2D(mainTexture, texCoord, inverseVP); + gl_FragColor.w = 1.0; +} diff --git a/Resources/Shaders/PostFilters/ResampleBicubic.program b/Resources/Shaders/PostFilters/ResampleBicubic.program new file mode 100644 index 000000000..41151d7bd --- /dev/null +++ b/Resources/Shaders/PostFilters/ResampleBicubic.program @@ -0,0 +1,2 @@ +Shaders/PostFilters/ResampleBicubic.fs +Shaders/PostFilters/ResampleBicubic.vs diff --git a/Sources/Core/Deque.cpp b/Resources/Shaders/PostFilters/ResampleBicubic.vs similarity index 72% rename from Sources/Core/Deque.cpp rename to Resources/Shaders/PostFilters/ResampleBicubic.vs index ea5db5b26..19e0f8159 100644 --- a/Sources/Core/Deque.cpp +++ b/Resources/Shaders/PostFilters/ResampleBicubic.vs @@ -1,5 +1,5 @@ /* - Copyright (c) 2013 yvt + Copyright (c) 2021 yvt This file is part of OpenSpades. @@ -18,4 +18,15 @@ */ -#include "Deque.h" +attribute vec2 positionAttribute; + +varying vec2 texCoord; +uniform vec2 inverseVP; + +void main() { + vec2 scrPos = positionAttribute * 2. - 1.; + + gl_Position = vec4(scrPos, 0.5, 1.); + + texCoord = positionAttribute / inverseVP; +} diff --git a/Resources/Shaders/PostFilters/TemporalAA.fs b/Resources/Shaders/PostFilters/TemporalAA.fs new file mode 100644 index 000000000..f1be81480 --- /dev/null +++ b/Resources/Shaders/PostFilters/TemporalAA.fs @@ -0,0 +1,161 @@ +/* + Copyright (c) 2017 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + + +uniform sampler2D inputTexture; +uniform sampler2D depthTexture; +uniform sampler2D previousTexture; +uniform sampler2D processedInputTexture; +uniform vec2 inverseVP; +uniform mat4 reprojectionMatrix; +uniform mat4 viewProjectionMatrixInv; +uniform float fogDistance; + +varying vec2 texCoord; +varying vec4 viewcentricWorldPositionPartial; +/* UE4-style temporal AA. Implementation is based on my ShaderToy submission */ + +// YUV-RGB conversion routine from Hyper3D +vec3 encodePalYuv(vec3 rgb) +{ + return vec3( + dot(rgb, vec3(0.299, 0.587, 0.114)), + dot(rgb, vec3(-0.14713, -0.28886, 0.436)), + dot(rgb, vec3(0.615, -0.51499, -0.10001)) + ); +} + +vec3 decodePalYuv(vec3 yuv) +{ + return vec3( + dot(yuv, vec3(1., 0., 1.13983)), + dot(yuv, vec3(1., -0.39465, -0.58060)), + dot(yuv, vec3(1., 2.03211, 0.)) + ); +} + + +void main() { + // ------------------------------------------------------------------------ + // Reprojection + // + // Calulate the Z position of the current pixel. Take the minimum Z value + // of the neighboring pixels to preserve the antialiasing of foreground + // objects. + vec2 off = inverseVP; + float inputZ0 = texture2D(depthTexture, texCoord).x; + float inputZ1 = texture2D(depthTexture, texCoord + vec2(+off.x, 0.0)).x; + float inputZ2 = texture2D(depthTexture, texCoord + vec2(-off.x, 0.0)).x; + float inputZ3 = texture2D(depthTexture, texCoord + vec2(0.0, +off.y)).x; + float inputZ4 = texture2D(depthTexture, texCoord + vec2(0.0, -off.y)).x; + float inputZ5 = texture2D(depthTexture, texCoord + vec2(+off.x, +off.y)).x; + float inputZ6 = texture2D(depthTexture, texCoord + vec2(-off.x, +off.y)).x; + float inputZ7 = texture2D(depthTexture, texCoord + vec2(+off.x, -off.y)).x; + float inputZ8 = texture2D(depthTexture, texCoord + vec2(-off.x, -off.y)).x; + float inputZ = min(min(min(inputZ0, inputZ1), min(inputZ2, inputZ3)), + min(min(inputZ4, inputZ5), min(inputZ6, min(inputZ7, inputZ8)))); + + // Predict where the point was in the previous frame. The Z range [0, 0.1] + // is for a view weapon, so assume no movement in this range. + vec4 reprojectedTexCoord; + if (inputZ < 0.1) { + reprojectedTexCoord.xy = texCoord.xy; + } else { + reprojectedTexCoord = reprojectionMatrix * vec4(texCoord, inputZ, 1.0); + reprojectedTexCoord.xy /= reprojectedTexCoord.w; + } + + vec4 lastColor = texture2D(previousTexture, reprojectedTexCoord.xy); + + // ------------------------------------------------------------------------ + // Calculate the approximate fog factor + // + // It's used to prevent barely-visible objects from being blurred away. + vec4 viewcentricWorldPosition = + viewcentricWorldPositionPartial + viewProjectionMatrixInv * vec4(0.0, 0.0, inputZ, 0.0); + viewcentricWorldPosition.xyz /= viewcentricWorldPosition.w; + + float voxlapDistanceSq = dot(viewcentricWorldPosition.xy, viewcentricWorldPosition.xy); + voxlapDistanceSq = min(voxlapDistanceSq, fogDistance * fogDistance); + + float fogFactor = min(voxlapDistanceSq / (fogDistance * fogDistance), 1.0); + + // ------------------------------------------------------------------------ + vec3 antialiased = lastColor.xyz; + float mixRate = min(lastColor.w, 0.5); + + vec3 in0 = texture2D(processedInputTexture, texCoord).xyz; + + antialiased = mix(antialiased, in0, mixRate); + + vec3 in1 = texture2D(inputTexture, texCoord + vec2(+off.x, 0.0)).xyz; + vec3 in2 = texture2D(inputTexture, texCoord + vec2(-off.x, 0.0)).xyz; + vec3 in3 = texture2D(inputTexture, texCoord + vec2(0.0, +off.y)).xyz; + vec3 in4 = texture2D(inputTexture, texCoord + vec2(0.0, -off.y)).xyz; + vec3 in5 = texture2D(inputTexture, texCoord + vec2(+off.x, +off.y)).xyz; + vec3 in6 = texture2D(inputTexture, texCoord + vec2(-off.x, +off.y)).xyz; + vec3 in7 = texture2D(inputTexture, texCoord + vec2(+off.x, -off.y)).xyz; + vec3 in8 = texture2D(inputTexture, texCoord + vec2(-off.x, -off.y)).xyz; + + antialiased = encodePalYuv(antialiased); + in0 = encodePalYuv(in0); + in1 = encodePalYuv(in1); + in2 = encodePalYuv(in2); + in3 = encodePalYuv(in3); + in4 = encodePalYuv(in4); + in5 = encodePalYuv(in5); + in6 = encodePalYuv(in6); + in7 = encodePalYuv(in7); + in8 = encodePalYuv(in8); + + vec3 minColor = min(min(min(in0, in1), min(in2, in3)), in4); + vec3 maxColor = max(max(max(in0, in1), max(in2, in3)), in4); + minColor = mix(minColor, + min(min(min(in5, in6), min(in7, in8)), minColor), 0.5); + maxColor = mix(maxColor, + max(max(max(in5, in6), max(in7, in8)), maxColor), 0.5); + + vec3 preclamping = antialiased; + antialiased = clamp(antialiased, minColor, maxColor); + + mixRate = 1.0 / (1.0 / mixRate + 1.0); + + // Increase the mix rate if the prediction is unreliable + { + vec3 diff = abs(antialiased - preclamping); + float clampAmount = max(max(diff.x, diff.y), diff.z); + mixRate += clampAmount * 8.0; + } + + // Increase the mix rate if the fog factor is high + // (Prevents barely-visible objects from being blurred away) + { + float contrast = 1.0 - fogFactor; + const float contrastThreshold = 0.1; + const float contrastFactor = 2.0; + mixRate += max(0.0, contrastThreshold - contrast) / contrastThreshold * contrastFactor; + } + + mixRate = clamp(mixRate, 0.05, 0.5); + + antialiased = decodePalYuv(antialiased); + + gl_FragColor = vec4(max(antialiased, vec3(0.0)), mixRate); +} diff --git a/Resources/Shaders/PostFilters/TemporalAA.program b/Resources/Shaders/PostFilters/TemporalAA.program new file mode 100644 index 000000000..b1a53ab86 --- /dev/null +++ b/Resources/Shaders/PostFilters/TemporalAA.program @@ -0,0 +1,2 @@ +Shaders/PostFilters/TemporalAA.fs +Shaders/PostFilters/TemporalAA.vs diff --git a/Resources/Shaders/PostFilters/TemporalAA.vs b/Resources/Shaders/PostFilters/TemporalAA.vs new file mode 100644 index 000000000..dae5d9639 --- /dev/null +++ b/Resources/Shaders/PostFilters/TemporalAA.vs @@ -0,0 +1,40 @@ +/* + Copyright (c) 2017 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + + + +attribute vec2 positionAttribute; + +uniform mat4 viewProjectionMatrixInv; + +varying vec2 texCoord; +varying vec4 viewcentricWorldPositionPartial; + +void main() { + vec2 pos = positionAttribute; + + vec2 scrPos = pos * 2. - 1.; + + gl_Position = vec4(scrPos, 0.5, 1.); + + texCoord = pos; + viewcentricWorldPositionPartial = viewProjectionMatrixInv * vec4(pos, 0.0, 1.0); +} + diff --git a/Resources/Shaders/Shadow/Common.vs b/Resources/Shaders/Shadow/Common.vs index c3de17db2..7f9c6a5dd 100644 --- a/Resources/Shaders/Shadow/Common.vs +++ b/Resources/Shaders/Shadow/Common.vs @@ -1,21 +1,21 @@ /* Copyright (c) 2013 yvt - + This file is part of OpenSpades. - + OpenSpades is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + OpenSpades is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with OpenSpades. If not, see . - + */ @@ -23,6 +23,7 @@ void PrepareForShadow_Map(vec3 vertexCoord, vec3 normal) ; void PrepareForShadow_Model(vec3 vertexCoord, vec3 normal); void PrepareForRadiosity_Map(vec3 vertexCoord, vec3 normal); +void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 centerCoord, vec3 normal); void PrepareForShadow(vec3 vertexCoord, vec3 normal) { PrepareForShadow_Map(vertexCoord, normal); @@ -30,9 +31,9 @@ void PrepareForShadow(vec3 vertexCoord, vec3 normal) { PrepareForRadiosity_Map(vertexCoord, normal); } -// map uses specialized shadow coordinate calculation to avoid glitch -void PrepareForShadowForMap(vec3 vertexCoord, vec3 fixedVertexCoord, vec3 normal) { - PrepareForShadow_Map(fixedVertexCoord, normal); +void PrepareForShadowForMap(vec3 vertexCoord, vec3 centerCoord, vec3 normal) { + // map uses specialized shadow coordinate calculation to avoid glitch + PrepareForShadow_Map(centerCoord + normal * 0.1, normal); PrepareForShadow_Model(vertexCoord, normal); - PrepareForRadiosity_Map(vertexCoord, normal); + PrepareForRadiosityForMap_Map(vertexCoord, centerCoord, normal); } diff --git a/Resources/Shaders/Shadow/MapRadiosity.fs b/Resources/Shaders/Shadow/MapRadiosity.fs index 59d9c3a3e..52d85983e 100644 --- a/Resources/Shaders/Shadow/MapRadiosity.fs +++ b/Resources/Shaders/Shadow/MapRadiosity.fs @@ -35,6 +35,10 @@ vec3 DecodeRadiosityValue(vec3 val){ // reverse bias val *= 1023. / 1022.; val = (val * 2.) - 1.; +#if USE_RADIOSITY == 1 + // the low-precision radiosity texture uses a non-linear encoding + val *= val * sign(val); +#endif return val; } @@ -58,7 +62,8 @@ vec3 Radiosity_Map(float detailAmbientOcclusion, float ssao) { detailAmbientOcclusion *= ssao; // ambient occlusion - float amb = texture3D(ambientShadowTexture, ambientShadowTextureCoord).x; + vec2 ambTexVal = texture3D(ambientShadowTexture, ambientShadowTextureCoord).xy; + float amb = ambTexVal.x / max(ambTexVal.y, 0.25); amb = max(amb, 0.); // for some reason, mainTexture value becomes negative // mix ambient occlusion values generated by two different methods somehow diff --git a/Resources/Shaders/Shadow/MapRadiosity.vs b/Resources/Shaders/Shadow/MapRadiosity.vs index 7c5b15c0d..c4cc7a0a5 100644 --- a/Resources/Shaders/Shadow/MapRadiosity.vs +++ b/Resources/Shaders/Shadow/MapRadiosity.vs @@ -1,33 +1,80 @@ /* Copyright (c) 2013 yvt - + This file is part of OpenSpades. - + OpenSpades is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + OpenSpades is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with OpenSpades. If not, see . - + */ /**** CPU RADIOSITY (FASTER?) *****/ +uniform sampler3D ambientShadowTexture; + varying vec3 radiosityTextureCoord; varying vec3 ambientShadowTextureCoord; varying vec3 normalVarying; void PrepareForRadiosity_Map(vec3 vertexCoord, vec3 normal) { - radiosityTextureCoord = (vertexCoord + vec3(0., 0., 0.)) / vec3(512., 512., 64.); - ambientShadowTextureCoord = (vertexCoord + vec3(0.5, 0.5, 1.5)) / vec3(512., 512., 65.); - + ambientShadowTextureCoord = (vertexCoord + vec3(0., 0., 1.)) / vec3(512., 512., 65.); + normalVarying = normal; } + +void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 centerCoord, vec3 normal) { + radiosityTextureCoord = (vertexCoord + vec3(0., 0., 0.)) / vec3(512., 512., 64.); + ambientShadowTextureCoord = (vertexCoord + vec3(0., 0., 1.) + normal * 0.5) / vec3(512., 512., 65.); + + vec3 centerAST = (centerCoord + vec3(0., 0., 1.) + normal * 0.5) / vec3(512., 512., 65.); + vec3 rel = vertexCoord - centerCoord; + vec3 relAST = rel * 2.0 / vec3(512., 512., 65.); + + // Detect the following pattern: + // + // +-----+-----+ + // |#####| | + // |#####| | + // |#####| | + // +-----+-----+ + // | V|#####| + // | C |#####| + // | |#####| + // +-----+-----+ + // + // C = centerCoord, V = vertexCoord, # = covered by a solid voxel + // + float weightSum; + if (normal.x != 0.0) { + weightSum = texture3D(ambientShadowTexture, centerAST + vec3(0.0, relAST.y, 0.0)).y + + texture3D(ambientShadowTexture, centerAST + vec3(0.0, 0.0, relAST.z)).y - + texture3D(ambientShadowTexture, centerAST + vec3(0.0, relAST.y, relAST.z)).y; + } else if (normal.y != 0.0) { + weightSum = texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, 0.0, 0.0)).y + + texture3D(ambientShadowTexture, centerAST + vec3(0.0, 0.0, relAST.z)).y - + texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, 0.0, relAST.z)).y; + } else { + weightSum = texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, 0.0, 0.0)).y + + texture3D(ambientShadowTexture, centerAST + vec3(0.0, relAST.y, 0.0)).y - + texture3D(ambientShadowTexture, centerAST + vec3(relAST.x, relAST.y, 0.0)).y; + } + + // Hide the light leaks by corners by modifying the AO texture coordinates + if (weightSum < -0.5) { + radiosityTextureCoord -= rel / vec3(512., 512., 64.); + ambientShadowTextureCoord = centerAST; + } + + normalVarying = normal; +} \ No newline at end of file diff --git a/Resources/Shaders/Shadow/MapRadiosityLow.fs b/Resources/Shaders/Shadow/MapRadiosityLow.fs deleted file mode 100644 index 7d69fee1d..000000000 --- a/Resources/Shaders/Shadow/MapRadiosityLow.fs +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (c) 2013 yvt - - This file is part of OpenSpades. - - OpenSpades is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenSpades is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenSpades. If not, see . - - */ - -/**** CPU RADIOSITY (FASTER?) *****/ - -uniform sampler3D ambientShadowTexture; -uniform sampler3D radiosityTextureFlat; -uniform sampler3D radiosityTextureX; -uniform sampler3D radiosityTextureY; -uniform sampler3D radiosityTextureZ; -varying vec3 radiosityTextureCoord; -varying vec3 ambientShadowTextureCoord; -varying vec3 normalVarying; -uniform vec3 ambientColor; -uniform vec3 fogColor; - -vec3 DecodeRadiosityValue(vec3 val){ - // reverse bias - val *= 1023. / 1022.; - val = (val * 2.) - 1.; - val *= val * sign(val); - return val; -} - -vec3 Radiosity_Map(float detailAmbientOcclusion, float ssao) { - vec3 col = DecodeRadiosityValue - (texture3D(radiosityTextureFlat, - radiosityTextureCoord).xyz); - vec3 normal = normalize(normalVarying); - col += normal.x * DecodeRadiosityValue - (texture3D(radiosityTextureX, - radiosityTextureCoord).xyz); - col += normal.y * DecodeRadiosityValue - (texture3D(radiosityTextureY, - radiosityTextureCoord).xyz); - col += normal.z * DecodeRadiosityValue - (texture3D(radiosityTextureZ, - radiosityTextureCoord).xyz); - col = max(col, 0.); - col *= 1.5 * ssao; - - detailAmbientOcclusion *= ssao; - - // ambient occlusion - float amb = texture3D(ambientShadowTexture, ambientShadowTextureCoord).x; - amb = max(amb, 0.); // by some reason, mainTexture value becomes negative - - // mix ambient occlusion values generated by two different methods somehow - amb = mix(sqrt(amb * detailAmbientOcclusion), min(amb, detailAmbientOcclusion), 0.5); - - amb *= .8 - normalVarying.z * .2; - col += amb * ambientColor; - - return col; -} - -vec3 BlurredReflection_Map(float detailAmbientOcclusion, vec3 direction, float ssao) -{ - vec3 col = DecodeRadiosityValue - (texture3D(radiosityTextureFlat, - radiosityTextureCoord).xyz); - vec3 normal = normalize(normalVarying); - col += normal.x * DecodeRadiosityValue - (texture3D(radiosityTextureX, - radiosityTextureCoord).xyz); - col += normal.y * DecodeRadiosityValue - (texture3D(radiosityTextureY, - radiosityTextureCoord).xyz); - col += normal.z * DecodeRadiosityValue - (texture3D(radiosityTextureZ, - radiosityTextureCoord).xyz); - col = max(col, 0.); - col *= 1.5 * ssao; - - detailAmbientOcclusion *= ssao; - - // ambient occlusion - float amb = texture3D(ambientShadowTexture, ambientShadowTextureCoord).x; - amb = max(amb, 0.); // for some reason, mainTexture value becomes negative - amb *= amb; // darken - - // mix ambient occlusion values generated by two different methods somehow - amb = mix(sqrt(amb * detailAmbientOcclusion), min(amb, detailAmbientOcclusion), 0.5); - - amb *= .8 - normalVarying.z * .2; - - return col + fogColor * amb; -} \ No newline at end of file diff --git a/Resources/Shaders/Shadow/MapRadiosityNull.vs b/Resources/Shaders/Shadow/MapRadiosityNull.vs index 2b730b067..a05b79155 100644 --- a/Resources/Shaders/Shadow/MapRadiosityNull.vs +++ b/Resources/Shaders/Shadow/MapRadiosityNull.vs @@ -24,3 +24,7 @@ void PrepareForRadiosity_Map(vec3 vertexCoord, vec3 normal) { hemisphereLighting = 1. - normal.z * .2; } +void PrepareForRadiosityForMap_Map(vec3 vertexCoord, vec3 centerCoord, vec3 normal) { + hemisphereLighting = 1. - normal.z * .2; +} + diff --git a/Resources/Shaders/VoxelModel.fs b/Resources/Shaders/VoxelModel.fs index 11a78cfcb..7cf866963 100644 --- a/Resources/Shaders/VoxelModel.fs +++ b/Resources/Shaders/VoxelModel.fs @@ -25,6 +25,7 @@ varying vec3 emissionColor; varying vec2 ambientOcclusionCoord; //varying vec2 detailCoord; varying vec3 fogDensity; +varying float sunlightShading; uniform sampler2D ambientOcclusionTexture; uniform sampler2D detailTexture; @@ -38,7 +39,7 @@ void main() { // color is linearized gl_FragColor = color; - vec3 shading = vec3(color.w); + vec3 shading = vec3(sunlightShading); // FIXME: prepare for shadow? shading *= EvaluateSunLight(); diff --git a/Resources/Shaders/VoxelModel.vs b/Resources/Shaders/VoxelModel.vs index e84dff23d..acfc308be 100644 --- a/Resources/Shaders/VoxelModel.vs +++ b/Resources/Shaders/VoxelModel.vs @@ -46,6 +46,7 @@ varying vec2 ambientOcclusionCoord; varying vec4 color; varying vec3 emissionColor; varying vec3 fogDensity; +varying float sunlightShading; //varying vec2 detailCoord; void PrepareForShadow(vec3 worldOrigin, vec3 normal); @@ -85,7 +86,7 @@ void main() { normal = normalize(normal); float sunlight = dot(normal, sunLightDirection); sunlight = max(sunlight, 0.); - color.w *= sunlight; + sunlightShading = sunlight; // ambient occlusion float aoID = positionAttribute.w / 256.; diff --git a/Resources/downloadpak.sh b/Resources/downloadpak.sh index 2d19b455e..8bb46a1f2 100755 --- a/Resources/downloadpak.sh +++ b/Resources/downloadpak.sh @@ -13,11 +13,11 @@ OS_BASE="`uname`" SRC_DIR="`dirname "$0"`" # no color, not -m flag for OpenBSD -if [[ "$OS_BASE" != 'OpenBSD' ]]; then +if [[ "$OS_BASE" != 'OpenBSD' ]] && [[ "$OS_BASE" != 'SunOS' ]]; then PAK_URL=$(grep --max-count=1 --no-filename --context=0 --color=never \ "OpenSpadesDevPackage" "$SRC_DIR/PakLocation.txt") else - PAK_URL=$(grep --no-filename \ + PAK_URL=$(grep -h \ "OpenSpadesDevPackage" "$SRC_DIR/PakLocation.txt" | head -n1) fi echo "BASEURL ************ $PAK_URL" @@ -27,8 +27,13 @@ OUTPUT_DIR="." if [ -f "$PAK_NAME" ]; then exit 0 fi +# TODO: Check if the extracted files are present and up-to-date (#988) -wget "$PAK_URL" -O "$PAK_NAME" +if [ -n "$OPENSPADES_DEVPAK_PATH" ]; then + cp "$OPENSPADES_DEVPAK_PATH" "$PAK_NAME" +else + wget "$PAK_URL" -O "$PAK_NAME" +fi unzip -o "$PAK_NAME" -d "$OUTPUT_DIR" # relocate paks to the proper location diff --git a/Sources/AngelScript/addons/scriptbuilder.cpp b/Sources/AngelScript/addons/scriptbuilder.cpp index 0de22dd09..c883dbaaa 100755 --- a/Sources/AngelScript/addons/scriptbuilder.cpp +++ b/Sources/AngelScript/addons/scriptbuilder.cpp @@ -1015,7 +1015,7 @@ string GetCurrentDir() #else return _getcwd(buffer, (int)1024); #endif // _MSC_VER -#elif defined(__APPLE__) || defined(__linux__) +#elif defined(__APPLE__) || defined(__linux__) || defined(__sun) return getcwd(buffer, 1024); #else return ""; diff --git a/Sources/AngelScript/source/as_config.h b/Sources/AngelScript/source/as_config.h index 5005d8311..8c0160c77 100755 --- a/Sources/AngelScript/source/as_config.h +++ b/Sources/AngelScript/source/as_config.h @@ -1079,15 +1079,23 @@ // Haiku OS #elif __HAIKU__ #define AS_HAIKU - // Only x86-32 is currently supported by Haiku, but they do plan to support - // x86-64 and PowerPC in the future, so should go ahead and check the platform - // for future compatibility #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__) #define AS_X86 #define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK #define THISCALL_RETURN_SIMPLE_IN_MEMORY #define CDECL_RETURN_SIMPLE_IN_MEMORY #define STDCALL_RETURN_SIMPLE_IN_MEMORY + #elif defined(__x86_64__) + #define AS_X64_GCC + #define HAS_128_BIT_PRIMITIVES + #undef COMPLEX_MASK + #define COMPLEX_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR) + #undef COMPLEX_RETURN_MASK + #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR) + #define AS_LARGE_OBJS_PASSED_BY_REF + #define AS_LARGE_OBJ_MIN_SIZE 5 + #undef STDCALL + #define STDCALL #else #define AS_MAX_PORTABILITY #endif diff --git a/Sources/AngelScript/source/as_scriptengine.cpp b/Sources/AngelScript/source/as_scriptengine.cpp index 8a88fcc61..023ef7059 100755 --- a/Sources/AngelScript/source/as_scriptengine.cpp +++ b/Sources/AngelScript/source/as_scriptengine.cpp @@ -2447,7 +2447,7 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as int asCScriptEngine::SetTemplateRestrictions(asCObjectType *templateType, asCScriptFunction *func, const char *caller, const char *decl) { - asASSERT(templateType->flags && asOBJ_TEMPLATE); + asASSERT(templateType->flags & asOBJ_TEMPLATE); for (asUINT subTypeIdx = 0; subTypeIdx < templateType->templateSubTypes.GetLength(); subTypeIdx++) { diff --git a/Sources/Audio/ALDevice.cpp b/Sources/Audio/ALDevice.cpp index a035d30be..547870682 100644 --- a/Sources/Audio/ALDevice.cpp +++ b/Sources/Audio/ALDevice.cpp @@ -39,6 +39,7 @@ DEFINE_SPADES_SETTING(s_maxPolyphonics, "96"); DEFINE_SPADES_SETTING(s_eax, "1"); DEFINE_SPADES_SETTING(s_alPreciseErrorCheck, "1"); DEFINE_SPADES_SETTING(s_gain, "1"); +DEFINE_SPADES_SETTING(s_openalDevice, ""); // lm: seems to be missing for me.. #ifndef ALC_ALL_DEVICES_SPECIFIER @@ -421,6 +422,7 @@ namespace spades { Internal() { SPADES_MARK_FUNCTION(); + const char *ext, *dev; if (al::qalGetString(AL_EXTENSIONS)) { std::vector strs = Split(al::qalGetString(AL_EXTENSIONS), " "); @@ -430,28 +432,13 @@ namespace spades { } } - SPLog("--- All devices ---"); - const ALCchar *ext = al::qalcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); - while (ext && *ext) { - SPLog("%s", ext); - ext += (std::strlen(ext) + 1); - } - SPLog("-------------------"); - - SPLog("--- Devices ---"); - ext = al::qalcGetString(NULL, ALC_DEVICE_SPECIFIER); - while (ext && *ext) { - SPLog("%s", ext); - ext += (std::strlen(ext) + 1); - } - SPLog("---------------"); - const ALCchar *dev = al::qalcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); - if (dev && *dev) { - SPLog("Default device: %s", dev); - } + dev = s_openalDevice.CString(); + SPLog("OpenAL opening device: %s", dev); + if (!strcmp(dev, "default")) + dev = NULL; + alDevice = al::qalcOpenDevice(dev); - alDevice = al::qalcOpenDevice(NULL); - if (!alDevice) { + if (UNLIKELY(!alDevice)) { if ((ext = al::qalcGetString(NULL, ALC_EXTENSIONS))) { std::vector strs = Split(ext, " "); SPLog("OpenAL ALC Extensions (NULL):"); @@ -476,7 +463,7 @@ namespace spades { } alContext = al::qalcCreateContext(alDevice, NULL); - if (!alContext) { + if (UNLIKELY(!alContext)) { al::qalcCloseDevice(alDevice); SPRaise("Failed to create OpenAL context."); } @@ -558,7 +545,7 @@ namespace spades { ALSrc *AllocChunk() { SPADES_MARK_FUNCTION(); - size_t start = SampleRandomInt(0, srcs.size() - 1); + size_t start = SampleRandomInt(0, srcs.size() - 1); for (size_t i = 0; i < srcs.size(); i++) { ALSrc *src = srcs[(i + start) % srcs.size()]; if (src->IsPlaying()) @@ -566,7 +553,7 @@ namespace spades { return src; } - ALSrc *src = SampleRandomElement(srcs); + ALSrc *src = SampleRandomElement(srcs); src->Terminate(); return src; } @@ -575,7 +562,7 @@ namespace spades { SPADES_MARK_FUNCTION(); ALSrc *src = AllocChunk(); - if (!src) + if (UNLIKELY(!src)) return; src->stereo = chunk->GetFormat() == AL_FORMAT_STEREO16; @@ -755,6 +742,19 @@ namespace spades { d = new Internal(); } + std::vector ALDevice::DeviceList() { + std::vector devs; + const ALCchar *ext = al::qalcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); + if (!ext || *ext == '\0') + ext = al::qalcGetString(NULL, ALC_DEVICE_SPECIFIER); + while (ext && *ext) { + devs.push_back(ext); + ext += std::strlen(ext) + 1; + } + + return devs; + } + bool ALDevice::TryLoad() { try { al::Link(); diff --git a/Sources/Audio/ALDevice.h b/Sources/Audio/ALDevice.h index 17972352f..1ff47e767 100644 --- a/Sources/Audio/ALDevice.h +++ b/Sources/Audio/ALDevice.h @@ -45,6 +45,8 @@ namespace spades { client::IAudioChunk *RegisterSound(const char *name) override; + static std::vector DeviceList(); + void ClearCache() override; void SetGameMap(client::GameMap *) override; diff --git a/Sources/Audio/YsrDevice.cpp b/Sources/Audio/YsrDevice.cpp index 7ef3448c0..dff7559dc 100644 --- a/Sources/Audio/YsrDevice.cpp +++ b/Sources/Audio/YsrDevice.cpp @@ -341,8 +341,8 @@ namespace spades { spec.samples = (int)s_ysrBufferSize; spec.channels = 2; - sdlAudioDevice = std::unique_ptr( - new SdlAudioDevice(nullptr, SDL_FALSE, spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE)); + sdlAudioDevice = stmp::make_unique(nullptr, SDL_FALSE, spec, + SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); YsrContext::InitParam param; param.maxPolyphonics = s_maxPolyphonics; diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt index ef0b9b366..1304bf023 100644 --- a/Sources/CMakeLists.txt +++ b/Sources/CMakeLists.txt @@ -47,6 +47,31 @@ set_target_properties(OpenSpades PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BIN set_target_properties(OpenSpades PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set_target_properties(OpenSpades PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +if(APPLE OR WIN32) + # This value is reflected to the macOS application bundle's name, so use + # the correct capitalization. + # We also want the correct capitalization on Windows. + set_target_properties(OpenSpades PROPERTIES OUTPUT_NAME OpenSpades) +else(APPLE) + set_target_properties(OpenSpades PROPERTIES OUTPUT_NAME openspades) +endif(APPLE) + +if (APPLE) + # The built pak files are copied into the macOS application bundle. CMake + # won't copy unless they are included in the target's source files. + # + # Since they are specified as `add_custom_command`'s output files, so they + # have the `GENERATED` property. However, `GENERATED` is a directory-local + # property (until [cmake!5308] lands in CMake 3.20). This means it needs to + # be set again here. + # + # [cmake!5308]: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5308 + set_source_files_properties(${PAK_FILES} PROPERTIES GENERATED 1) + + # The same goes for `libysrspades.dylib`. + set_source_files_properties(${PROJECT_BINARY_DIR}/libysrspades.dylib PROPERTIES GENERATED 1) +endif(APPLE) + if(WIN32) # Use a single output directory for all configs # (Without this, the generated binary cannot find pak files created by mkpak.ps1 unless @@ -101,6 +126,9 @@ target_link_libraries(OpenSpades ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARY} ${OPENGL_ if(NOT APPLE) target_link_libraries(OpenSpades ${GLEW_LIBRARY}) endif() +if(USE_VCPKG) + target_link_libraries(OpenSpades Ogg::ogg Opus::opus) +endif() #todo: MACOSX_BUNDLE_ICON_FILE ? @@ -112,12 +140,20 @@ endif() if(WIN32) target_link_libraries(OpenSpades ws2_32.lib winmm.lib) elseif(UNIX AND NOT APPLE) - target_link_libraries(OpenSpades Xext) + target_link_libraries(OpenSpades ${XEXT_LIBRARY}) + include_directories(${XEXT_INCLUDE_DIR}) endif() if(UNIX) - if(NOT(CMAKE_SYSTEM_NAME MATCHES "BSD" OR APPLE)) - target_link_libraries(OpenSpades rt) + if(NOT(${CMAKE_SYSTEM_NAME} MATCHES "BSD" OR APPLE)) + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku") + target_link_libraries(OpenSpades rt) + if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + target_link_libraries(OpenSpades socket nsl ogg vorbis vorbisfile opus) + endif() + else() + target_link_libraries(OpenSpades network) + endif() endif() target_link_libraries(OpenSpades pthread) endif() diff --git a/Sources/Client/CTFGameMode.cpp b/Sources/Client/CTFGameMode.cpp index f3d7dfab9..a195a012e 100644 --- a/Sources/Client/CTFGameMode.cpp +++ b/Sources/Client/CTFGameMode.cpp @@ -21,8 +21,8 @@ #include "CTFGameMode.h" #include -#include "World.h" #include "Player.h" +#include "World.h" namespace spades { namespace client { @@ -51,5 +51,5 @@ namespace spades { team.hasIntel = false; } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/CTFGameMode.h b/Sources/Client/CTFGameMode.h index 28f4a3b6c..4db2eb627 100644 --- a/Sources/Client/CTFGameMode.h +++ b/Sources/Client/CTFGameMode.h @@ -45,6 +45,9 @@ namespace spades { CTFGameMode(); ~CTFGameMode(); + CTFGameMode(const CTFGameMode &) = delete; + void operator=(const CTFGameMode &) = delete; + Team &GetTeam(int t); int GetCaptureLimit() { return captureLimit; } void SetCaptureLimit(int v) { captureLimit = v; } @@ -59,5 +62,5 @@ namespace spades { */ void ResetTeamScoreAndIntelHoldingStatus(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/CenterMessageView.cpp b/Sources/Client/CenterMessageView.cpp index 183603c0e..702c5a482 100644 --- a/Sources/Client/CenterMessageView.cpp +++ b/Sources/Client/CenterMessageView.cpp @@ -86,7 +86,7 @@ namespace spades { fade = 1.f; float y = 100.f + 32.f * (float)ent.line; - float x = (renderer->ScreenWidth() - size.x) * .5f; + float x = (renderer.ScreenWidth() - size.x) * .5f; Vector4 shadow = {0, 0, 0, fade * 0.5f}; Vector4 color = {1, 1, 1, fade}; @@ -94,5 +94,5 @@ namespace spades { font->DrawShadow(ent.msg, MakeVector2(x, y), 1.f, color, shadow); } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/CenterMessageView.h b/Sources/Client/CenterMessageView.h index e63477bcb..1391e1377 100644 --- a/Sources/Client/CenterMessageView.h +++ b/Sources/Client/CenterMessageView.h @@ -38,7 +38,7 @@ namespace spades { }; Client *client; - IRenderer *renderer; + IRenderer &renderer; IFont *font; std::vector lineUsing; std::list entries; @@ -53,5 +53,5 @@ namespace spades { void Update(float dt); void Draw(); }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades diff --git a/Sources/Client/ChatWindow.cpp b/Sources/Client/ChatWindow.cpp index 6d2553b52..46bfde6ac 100644 --- a/Sources/Client/ChatWindow.cpp +++ b/Sources/Client/ChatWindow.cpp @@ -307,5 +307,5 @@ namespace spades { y += ent.height; } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ChatWindow.h b/Sources/Client/ChatWindow.h index 9f792615a..13b9dcdc2 100644 --- a/Sources/Client/ChatWindow.h +++ b/Sources/Client/ChatWindow.h @@ -86,5 +86,5 @@ namespace spades { void Update(float dt); void Draw(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client.cpp b/Sources/Client/Client.cpp index 5fcca46a2..feb840cdb 100644 --- a/Sources/Client/Client.cpp +++ b/Sources/Client/Client.cpp @@ -56,6 +56,7 @@ #include "NetClient.h" DEFINE_SPADES_SETTING(cg_chatBeep, "1"); +DEFINE_SPADES_SETTING(cg_alertSounds, "1"); DEFINE_SPADES_SETTING(cg_serverAlert, "1"); @@ -111,19 +112,23 @@ namespace spades { renderer->SetFogDistance(128.f); renderer->SetFogColor(MakeVector3(.8f, 1.f, 1.f)); - chatWindow.reset(new ChatWindow(this, GetRenderer(), fontManager->GetGuiFont(), false)); - killfeedWindow.reset( - new ChatWindow(this, GetRenderer(), fontManager->GetGuiFont(), true)); - - hurtRingView.reset(new HurtRingView(this)); - centerMessageView.reset(new CenterMessageView(this, fontManager->GetLargeFont())); - mapView.reset(new MapView(this, false)); - largeMapView.reset(new MapView(this, true)); - scoreboard.reset(new ScoreboardView(this)); - limbo.reset(new LimboView(this)); - paletteView.reset(new PaletteView(this)); - tcView.reset(new TCProgressView(this)); - scriptedUI.Set(new ClientUI(renderer, audioDev, fontManager, this), false); + chatWindow = stmp::make_unique(this, &GetRenderer(), + &fontManager->GetGuiFont(), false); + killfeedWindow = + stmp::make_unique(this, &GetRenderer(), &fontManager->GetGuiFont(), true); + + hurtRingView = stmp::make_unique(this); + centerMessageView = + stmp::make_unique(this, &fontManager->GetLargeFont()); + mapView = stmp::make_unique(this, false); + largeMapView = stmp::make_unique(this, true); + scoreboard = stmp::make_unique(this); + limbo = stmp::make_unique(this); + paletteView = stmp::make_unique(this); + tcView = stmp::make_unique(*this); + scriptedUI = + Handle::New(renderer.GetPointerOrNull(), audioDev.GetPointerOrNull(), + fontManager.GetPointerOrNull(), this); renderer->SetGameMap(nullptr); } @@ -146,11 +151,6 @@ namespace spades { scoreboardVisible = false; flashlightOn = false; - for (size_t i = 0; i < clientPlayers.size(); i++) { - if (clientPlayers[i]) { - clientPlayers[i]->Invalidate(); - } - } clientPlayers.clear(); if (world) { @@ -167,9 +167,9 @@ namespace spades { // initialize player view objects clientPlayers.resize(world->GetNumPlayerSlots()); for (size_t i = 0; i < world->GetNumPlayerSlots(); i++) { - Player *p = world->GetPlayer(static_cast(i)); + auto p = world->GetPlayer(static_cast(i)); if (p) { - clientPlayers[i] = new ClientPlayer(p, this); + clientPlayers[i] = Handle::New(*p, *this); } else { clientPlayers[i] = nullptr; } @@ -178,7 +178,7 @@ namespace spades { world->SetListener(this); map = world->GetMap(); renderer->SetGameMap(map); - audioDevice->SetGameMap(map); + audioDevice->SetGameMap(map.GetPointerOrNull()); NetLog("------ World Loaded ------"); } else { @@ -220,11 +220,6 @@ namespace spades { renderer->SetGameMap(nullptr); audioDevice->SetGameMap(nullptr); - for (size_t i = 0; i < clientPlayers.size(); i++) { - if (clientPlayers[i]) { - clientPlayers[i]->Invalidate(); - } - } clientPlayers.clear(); scriptedUI->ClientDestroyed(); @@ -244,7 +239,7 @@ namespace spades { /** Initiate an initialization which likely to take some time */ void Client::DoInit() { renderer->Init(); - SmokeSpriteEntity::Preload(renderer); + SmokeSpriteEntity::Preload(renderer.GetPointerOrNull()); renderer->RegisterImage("Textures/Fluid.png"); renderer->RegisterImage("Textures/WaterExpl.png"); @@ -297,8 +292,7 @@ namespace spades { audioDevice->RegisterSound("Sounds/Weapons/AimDownSightLocal.opus"); renderer->RegisterImage("Gfx/Ball.png"); renderer->RegisterModel("Models/Player/Dead.kv6"); - renderer->RegisterImage("Gfx/Spotlight.png"); - renderer->RegisterImage("Gfx/Glare.png"); + renderer->RegisterImage("Gfx/Spotlight.jpg"); renderer->RegisterModel("Models/Weapons/Spade/Spade.kv6"); renderer->RegisterModel("Models/Weapons/Block/Block2.kv6"); renderer->RegisterModel("Models/Weapons/Grenade/Grenade.kv6"); @@ -341,7 +335,7 @@ namespace spades { mumbleLink.setIdentity(playerName); SPLog("Started connecting to '%s'", hostname.ToString(true).c_str()); - net.reset(new NetClient(this)); + net = stmp::make_unique(this); net->Connect(hostname); // decide log file name @@ -368,7 +362,7 @@ namespace spades { fn2 = "NetLogs/" + fn2 + ".log"; try { - logStream.reset(FileManager::OpenForWriting(fn2.c_str())); + logStream = FileManager::OpenForWriting(fn2.c_str()); SPLog("Netlog Started at '%s'", fn2.c_str()); } catch (const std::exception &ex) { SPLog("Failed to open netlog file '%s' (%s)", fn2.c_str(), ex.what()); @@ -421,7 +415,7 @@ namespace spades { if (world) { UpdateWorld(dt); - mumbleLink.update(world->GetLocalPlayer()); + mumbleLink.update(world->GetLocalPlayer().get_pointer()); } else { renderer->SetFogColor(MakeVector3(0.f, 0.f, 0.f)); } @@ -448,6 +442,7 @@ namespace spades { // CreateSceneDefinition also can be used for sounds SceneDefinition sceneDef = CreateSceneDefinition(); lastSceneDef = sceneDef; + UpdateMatrices(); // Update sounds try { @@ -512,11 +507,11 @@ namespace spades { } net->SendJoin(team, weap, playerName, lastKills); } else { - Player *p = world->GetLocalPlayer(); - if (p->GetTeamId() != team) { + Player &p = world->GetLocalPlayer().value(); + if (p.GetTeamId() != team) { net->SendTeamChange(team); } - if (team != 2 && p->GetWeapon()->GetWeaponType() != weap) { + if (team != 2 && p.GetWeapon().GetWeaponType() != weap) { net->SendWeaponChange(weap); } } @@ -575,7 +570,9 @@ namespace spades { void Client::PlayAlertSound() { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/Alert.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + AudioParam params; + params.volume = (float)cg_alertSounds; + audioDevice->PlayLocal(chunk.GetPointerOrNull(), params); } /** Records chat message/game events to the log file. */ @@ -619,8 +616,8 @@ namespace spades { { std::unique_ptr stream(FileManager::OpenForWriting(name.c_str())); try { - GameMap *map = GetWorld()->GetMap(); - if (map == nullptr) { + const Handle &map = GetWorld()->GetMap(); + if (!map) { SPRaise("No map loaded"); } map->Save(stream.get()); @@ -667,8 +664,7 @@ namespace spades { #pragma mark - Chat Messages - void Client::PlayerSentChatMessage(spades::client::Player *p, bool global, - const std::string &msg) { + void Client::PlayerSentChatMessage(Player &p, bool global, const std::string &msg) { { std::string s; if (global) @@ -680,7 +676,7 @@ namespace spades { //! but it actually can be. //! The extra whitespace is not a typo. s = _Tr("Client", "[Global] "); - s += ChatWindow::TeamColorMessage(p->GetName(), p->GetTeamId()); + s += ChatWindow::TeamColorMessage(p.GetName(), p.GetTeamId()); s += ": "; s += msg; chatWindow->AddMessage(s); @@ -689,26 +685,28 @@ namespace spades { std::string s; if (global) s = "[Global] "; - s += p->GetName(); + s += p.GetName(); s += ": "; s += msg; - auto col = p->GetTeamId() < 2 ? world->GetTeam(p->GetTeamId()).color - : IntVector3::Make(255, 255, 255); + auto col = p.GetTeamId() < 2 ? world->GetTeam(p.GetTeamId()).color + : IntVector3::Make(255, 255, 255); scriptedUI->RecordChatLog( s, MakeVector4(col.x / 255.f, col.y / 255.f, col.z / 255.f, 0.8f)); } if (global) - NetLog("[Global] %s (%s): %s", p->GetName().c_str(), - world->GetTeam(p->GetTeamId()).name.c_str(), msg.c_str()); + NetLog("[Global] %s (%s): %s", p.GetName().c_str(), + world->GetTeam(p.GetTeamId()).name.c_str(), msg.c_str()); else - NetLog("[Team] %s (%s): %s", p->GetName().c_str(), - world->GetTeam(p->GetTeamId()).name.c_str(), msg.c_str()); + NetLog("[Team] %s (%s): %s", p.GetName().c_str(), + world->GetTeam(p.GetTeamId()).name.c_str(), msg.c_str()); - if ((!IsMuted()) && (int)cg_chatBeep) { + if (!IsMuted()) { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/Chat.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + AudioParam params; + params.volume = (float)cg_chatBeep; + audioDevice->PlayLocal(chunk.GetPointerOrNull(), params); } } @@ -748,8 +746,9 @@ namespace spades { bool localPlayerIsSpectator = localPlayer.IsSpectator(); - int nextId = FollowsNonLocalPlayer(GetCameraMode()) ? followedPlayerId - : world->GetLocalPlayerIndex(); + int nextId = FollowsNonLocalPlayer(GetCameraMode()) + ? followedPlayerId + : world->GetLocalPlayerIndex().value(); do { reverse ? --nextId : ++nextId; @@ -758,8 +757,8 @@ namespace spades { if (nextId < 0) nextId = static_cast(world->GetNumPlayerSlots() - 1); - Player *p = world->GetPlayer(nextId); - if (p == nullptr || p->IsSpectator()) { + stmp::optional p = world->GetPlayer(nextId); + if (!p || p->IsSpectator()) { // Do not follow a non-existent player or spectator continue; } diff --git a/Sources/Client/Client.h b/Sources/Client/Client.h index d267d9ac6..fdb2b30ed 100644 --- a/Sources/Client/Client.h +++ b/Sources/Client/Client.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "ClientCameraMode.h" #include "ILocalEntity.h" @@ -180,14 +181,16 @@ namespace spades { */ bool CanLocalPlayerUseToolNow(); - /** Retrieves `ClientPlayer` for the local player, or `nullptr` if it does not exist. */ - ClientPlayer *GetLocalClientPlayer(); + /** Retrieves `ClientPlayer` for the local player, or `{}` if it does not exist. */ + stmp::optional GetLocalClientPlayer(); float toolRaiseState; void SetSelectedTool(Player::ToolType, bool quiet = false); // view SceneDefinition lastSceneDef; + /** Derived from `lastSceneDef`. */ + Matrix4 lastViewProjectionScreenMatrix; float localFireVibrationTime; float grenadeVibration; float grenadeVibrationSlow; @@ -301,7 +304,7 @@ namespace spades { void SpawnPressed(); void NextSpawnPressed(); - Player *HotTrackedPlayer(hitTag_t *hitFlag); + stmp::optional> HotTrackedPlayer(); // effects (local entity, etc) std::vector flashDlights; @@ -340,8 +343,13 @@ namespace spades { int nextScreenShotIndex; int nextMapShotIndex; + /** Project the specified world-space position to a screen space. */ Vector3 Project(Vector3); + /** Recalculate `lastViewProjectionScreenMatrix` based on the current value of + * `lastSceneDef`. */ + void UpdateMatrices(); + void DrawSplash(); void DrawStartupScreen(); void DrawDisconnectScreen(); @@ -388,7 +396,7 @@ namespace spades { void DrawStats(); void DrawScene(); - void AddGrenadeToScene(Grenade *); + void AddGrenadeToScene(Grenade &); void AddDebugObjectToScene(const OBB3 &, const Vector4 &col = MakeVector4(1, 1, 1, 1)); void DrawCTFObjects(); void DrawTCObjects(); @@ -428,24 +436,26 @@ namespace spades { void SetWorld(World *); World *GetWorld() const { return world.get(); } - void AddLocalEntity(ILocalEntity *ent) { localEntities.emplace_back(ent); } + void AddLocalEntity(std::unique_ptr &&ent) { + localEntities.emplace_back(std::move(ent)); + } void MarkWorldUpdate(); - IRenderer *GetRenderer() { return renderer; } + IRenderer &GetRenderer() { return *renderer; } SceneDefinition GetLastSceneDef() { return lastSceneDef; } - IAudioDevice *GetAudioDevice() { return audioDevice; } + IAudioDevice &GetAudioDevice() { return *audioDevice; } bool WantsToBeClosed() override; bool IsMuted(); - void PlayerSentChatMessage(Player *, bool global, const std::string &); + void PlayerSentChatMessage(Player &, bool global, const std::string &); void ServerSentMessage(const std::string &); - void PlayerCapturedIntel(Player *); - void PlayerCreatedBlock(Player *); - void PlayerPickedIntel(Player *); - void PlayerDropIntel(Player *); + void PlayerCapturedIntel(Player &); + void PlayerCreatedBlock(Player &); + void PlayerPickedIntel(Player &); + void PlayerDropIntel(Player &); void TeamCapturedTerritory(int teamId, int territoryId); void TeamWon(int); void JoinedGame(); @@ -453,34 +463,36 @@ namespace spades { void PlayerDestroyedBlockWithWeaponOrTool(IntVector3); void PlayerDiggedBlock(IntVector3); void GrenadeDestroyedBlock(IntVector3); - void PlayerLeaving(Player *); - void PlayerJoinedTeam(Player *); - void PlayerSpawned(Player *); + void PlayerLeaving(Player &); + void PlayerJoinedTeam(Player &); + void PlayerSpawned(Player &); + // IWorldListener begin void PlayerObjectSet(int) override; - void PlayerMadeFootstep(Player *) override; - void PlayerJumped(Player *) override; - void PlayerLanded(Player *, bool hurt) override; - void PlayerFiredWeapon(Player *) override; - void PlayerDryFiredWeapon(Player *) override; - void PlayerReloadingWeapon(Player *) override; - void PlayerReloadedWeapon(Player *) override; - void PlayerChangedTool(Player *) override; - void PlayerThrownGrenade(Player *, Grenade *) override; - void PlayerMissedSpade(Player *) override; - void PlayerRestocked(Player *) override; + void PlayerMadeFootstep(Player &) override; + void PlayerJumped(Player &) override; + void PlayerLanded(Player &, bool hurt) override; + void PlayerFiredWeapon(Player &) override; + void PlayerDryFiredWeapon(Player &) override; + void PlayerReloadingWeapon(Player &) override; + void PlayerReloadedWeapon(Player &) override; + void PlayerChangedTool(Player &) override; + void PlayerThrewGrenade(Player &, stmp::optional) override; + void PlayerMissedSpade(Player &) override; + void PlayerRestocked(Player &) override; /** @deprecated use BulletHitPlayer */ - void PlayerHitBlockWithSpade(Player *, Vector3 hitPos, IntVector3 blockPos, + void PlayerHitBlockWithSpade(Player &, Vector3 hitPos, IntVector3 blockPos, IntVector3 normal) override; - void PlayerKilledPlayer(Player *killer, Player *victim, KillType) override; + void PlayerKilledPlayer(Player &killer, Player &victim, KillType) override; - void BulletHitPlayer(Player *hurtPlayer, HitType, Vector3 hitPos, Player *by) override; + void BulletHitPlayer(Player &hurtPlayer, HitType, Vector3 hitPos, Player &by, + std::unique_ptr &stateCell) override; void BulletHitBlock(Vector3, IntVector3 blockPos, IntVector3 normal) override; - void AddBulletTracer(Player *player, Vector3 muzzlePos, Vector3 hitPos) override; - void GrenadeExploded(Grenade *) override; - void GrenadeBounced(Grenade *) override; - void GrenadeDroppedIntoWater(Grenade *) override; + void AddBulletTracer(Player &player, Vector3 muzzlePos, Vector3 hitPos) override; + void GrenadeExploded(const Grenade &) override; + void GrenadeBounced(const Grenade &) override; + void GrenadeDroppedIntoWater(const Grenade &) override; void BlocksFell(std::vector) override; @@ -489,6 +501,7 @@ namespace spades { void LocalPlayerCreatedLineBlock(IntVector3, IntVector3) override; void LocalPlayerHurt(HurtType type, bool sourceGiven, Vector3 source) override; void LocalPlayerBuildError(BuildFailureReason reason) override; + // IWorldListener end }; } // namespace client } // namespace spades diff --git a/Sources/Client/ClientCameraMode.h b/Sources/Client/ClientCameraMode.h index dcd465735..ee389317b 100644 --- a/Sources/Client/ClientCameraMode.h +++ b/Sources/Client/ClientCameraMode.h @@ -68,11 +68,9 @@ namespace spades { case ClientCameraMode::NotJoined: case ClientCameraMode::FirstPersonLocal: case ClientCameraMode::FirstPersonFollow: - case ClientCameraMode::Free: - return false; + case ClientCameraMode::Free: return false; case ClientCameraMode::ThirdPersonLocal: - case ClientCameraMode::ThirdPersonFollow: - return true; + case ClientCameraMode::ThirdPersonFollow: return true; } SPUnreachable(); } @@ -83,11 +81,9 @@ namespace spades { case ClientCameraMode::NotJoined: case ClientCameraMode::ThirdPersonLocal: case ClientCameraMode::ThirdPersonFollow: - case ClientCameraMode::Free: - return false; + case ClientCameraMode::Free: return false; case ClientCameraMode::FirstPersonLocal: - case ClientCameraMode::FirstPersonFollow: - return true; + case ClientCameraMode::FirstPersonFollow: return true; } SPUnreachable(); } @@ -96,13 +92,11 @@ namespace spades { switch (mode) { case ClientCameraMode::None: case ClientCameraMode::NotJoined: - case ClientCameraMode::Free: - return false; + case ClientCameraMode::Free: return false; case ClientCameraMode::ThirdPersonLocal: case ClientCameraMode::ThirdPersonFollow: case ClientCameraMode::FirstPersonLocal: - case ClientCameraMode::FirstPersonFollow: - return true; + case ClientCameraMode::FirstPersonFollow: return true; } SPUnreachable(); } @@ -113,13 +107,11 @@ namespace spades { case ClientCameraMode::NotJoined: case ClientCameraMode::Free: case ClientCameraMode::ThirdPersonLocal: - case ClientCameraMode::FirstPersonLocal: - return false; + case ClientCameraMode::FirstPersonLocal: return false; case ClientCameraMode::ThirdPersonFollow: - case ClientCameraMode::FirstPersonFollow: - return true; + case ClientCameraMode::FirstPersonFollow: return true; } SPUnreachable(); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ClientPlayer.cpp b/Sources/Client/ClientPlayer.cpp index e0f5fc58e..d50c3abc0 100644 --- a/Sources/Client/ClientPlayer.cpp +++ b/Sources/Client/ClientPlayer.cpp @@ -36,6 +36,7 @@ #include "Player.h" #include "Weapon.h" #include "World.h" +#include #include #include #include @@ -50,10 +51,12 @@ SPADES_SETTING(cg_ragdoll); SPADES_SETTING(cg_ejectBrass); DEFINE_SPADES_SETTING(cg_animations, "1"); SPADES_SETTING(cg_shake); +SPADES_SETTING(r_hdr); DEFINE_SPADES_SETTING(cg_environmentalAudio, "1"); DEFINE_SPADES_SETTING(cg_viewWeaponX, "0"); DEFINE_SPADES_SETTING(cg_viewWeaponY, "0"); DEFINE_SPADES_SETTING(cg_viewWeaponZ, "0"); +DEFINE_SPADES_SETTING(cg_debugToolSkinAnchors, "0"); namespace spades { namespace client { @@ -80,7 +83,7 @@ namespace spades { ~SandboxedRenderer() {} public: - SandboxedRenderer(IRenderer *base) : base(base) {} + SandboxedRenderer(Handle base) : base(std::move(base)) {} void SetClipBox(const AABB3 &b) { clipBox = b; } void SetAllowDepthHack(bool h) { allowDepthHack = h; } @@ -88,13 +91,17 @@ namespace spades { void Init() { OnProhibitedAction(); } void Shutdown() { OnProhibitedAction(); } - IImage *RegisterImage(const char *filename) { return base->RegisterImage(filename); } - IModel *RegisterModel(const char *filename) { return base->RegisterModel(filename); } + Handle RegisterImage(const char *filename) { + return base->RegisterImage(filename); + } + Handle RegisterModel(const char *filename) { + return base->RegisterModel(filename); + } - IImage *CreateImage(Bitmap *bmp) { return base->CreateImage(bmp); } - IModel *CreateModel(VoxelModel *m) { return base->CreateModel(m); } + Handle CreateImage(Bitmap &bmp) { return base->CreateImage(bmp); } + Handle CreateModel(VoxelModel &m) { return base->CreateModel(m); } - void SetGameMap(GameMap *) { OnProhibitedAction(); } + void SetGameMap(stmp::optional) { OnProhibitedAction(); } void SetFogDistance(float) { OnProhibitedAction(); } void SetFogColor(Vector3) { OnProhibitedAction(); } @@ -102,25 +109,30 @@ namespace spades { void StartScene(const SceneDefinition &) { OnProhibitedAction(); } void AddLight(const client::DynamicLightParam &light) { - Vector3 rad(light.radius, light.radius, light.radius); - if (CheckVisibility(AABB3(light.origin - rad, light.origin + rad))) { + AABB3 aabb{light.origin, light.origin}; + if (light.type == DynamicLightTypeLinear) { + aabb += light.point2; + } + + if (CheckVisibility(aabb.Inflate(light.radius))) { base->AddLight(light); } } - void RenderModel(IModel *model, const ModelRenderParam &_p) { + void RenderModel(IModel &model, const ModelRenderParam &_p) { ModelRenderParam p = _p; - if (!model) { - SPInvalidArgument("model"); - return; - } - if (p.depthHack && !allowDepthHack) { OnProhibitedAction(); return; } + // Disable depth hack when `cg_debugToolSkinAnchors` is set + // so that the drawn debug lines intersect with the weapon model + if (cg_debugToolSkinAnchors) { + p.depthHack = false; + } + // Overbright surfaces bypass the fog p.customColor.x = std::max(std::min(p.customColor.x, 1.0f), 0.0f); p.customColor.y = std::max(std::min(p.customColor.y, 1.0f), 0.0f); @@ -133,20 +145,20 @@ namespace spades { return; } - auto bounds = (p.matrix * OBB3(model->GetBoundingBox())).GetBoundingAABB(); + auto bounds = (p.matrix * OBB3(model.GetBoundingBox())).GetBoundingAABB(); if (CheckVisibility(bounds)) { base->RenderModel(model, p); } } void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) { OnProhibitedAction(); } - void AddSprite(IImage *image, Vector3 center, float radius, float rotation) { + void AddSprite(IImage &image, Vector3 center, float radius, float rotation) { Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f); if (CheckVisibility(AABB3(center - rad, center + rad))) { base->AddSprite(image, center, radius, rotation); } } - void AddLongSprite(IImage *image, Vector3 p1, Vector3 p2, float radius) { + void AddLongSprite(IImage &image, Vector3 p1, Vector3 p2, float radius) { Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f); AABB3 bounds1(p1 - rad, p1 + rad); AABB3 bounds2(p2 - rad, p2 + rad); @@ -169,32 +181,35 @@ namespace spades { /** Sets color for image drawing. Always alpha premultiplied. */ void SetColorAlphaPremultiplied(Vector4 col) { base->SetColorAlphaPremultiplied(col); } - void DrawImage(IImage *img, const Vector2 &outTopLeft) { + void DrawImage(stmp::optional img, const Vector2 &outTopLeft) { if (allowDepthHack) base->DrawImage(img, outTopLeft); else OnProhibitedAction(); } - void DrawImage(IImage *img, const AABB2 &outRect) { + void DrawImage(stmp::optional img, const AABB2 &outRect) { if (allowDepthHack) base->DrawImage(img, outRect); else OnProhibitedAction(); } - void DrawImage(IImage *img, const Vector2 &outTopLeft, const AABB2 &inRect) { + void DrawImage(stmp::optional img, const Vector2 &outTopLeft, + const AABB2 &inRect) { if (allowDepthHack) base->DrawImage(img, outTopLeft, inRect); else OnProhibitedAction(); } - void DrawImage(IImage *img, const AABB2 &outRect, const AABB2 &inRect) { + void DrawImage(stmp::optional img, const AABB2 &outRect, + const AABB2 &inRect) { if (allowDepthHack) base->DrawImage(img, outRect, inRect); else OnProhibitedAction(); } - void DrawImage(IImage *img, const Vector2 &outTopLeft, const Vector2 &outTopRight, - const Vector2 &outBottomLeft, const AABB2 &inRect) { + void DrawImage(stmp::optional img, const Vector2 &outTopLeft, + const Vector2 &outTopRight, const Vector2 &outBottomLeft, + const AABB2 &inRect) { if (allowDepthHack) base->DrawImage(img, outTopLeft, outTopRight, outBottomLeft, inRect); else @@ -209,34 +224,34 @@ namespace spades { void Flip() { OnProhibitedAction(); } - Bitmap *ReadBitmap() { + Handle ReadBitmap() { OnProhibitedAction(); - return nullptr; + return {}; } float ScreenWidth() { return base->ScreenWidth(); } float ScreenHeight() { return base->ScreenHeight(); } }; - ClientPlayer::ClientPlayer(Player *p, Client *c) : client(c), player(p), hasValidOriginMatrix(false) { + ClientPlayer::ClientPlayer(Player &p, Client &c) + : client(c), player(p), hasValidOriginMatrix(false) { SPADES_MARK_FUNCTION(); sprintState = 0.f; aimDownState = 0.f; toolRaiseState = 0.f; - currentTool = p->GetTool(); + currentTool = p.GetTool(); localFireVibrationTime = -100.f; time = 0.f; viewWeaponOffset = MakeVector3(0, 0, 0); lastFront = MakeVector3(0, 0, 0); - flashlightOrientation = p->GetFront(); + flashlightOrientation = p.GetFront(); ScriptContextHandle ctx; - IRenderer *renderer = client->GetRenderer(); - IAudioDevice *audio = client->GetAudioDevice(); + IAudioDevice &audio = client.GetAudioDevice(); - sandboxedRenderer.Set(new SandboxedRenderer(renderer), false); - renderer = sandboxedRenderer; + sandboxedRenderer = Handle::New(client.GetRenderer()); + IRenderer &renderer = *sandboxedRenderer; static ScriptFunction spadeFactory( "ISpadeSkin@ CreateThirdPersonSpadeSkin(Renderer@, AudioDevice@)"); @@ -274,7 +289,7 @@ namespace spades { "IWeaponSkin@ CreateViewSMGSkin(Renderer@, AudioDevice@)"); static ScriptFunction shotgunViewFactory( "IWeaponSkin@ CreateViewShotgunSkin(Renderer@, AudioDevice@)"); - switch (p->GetWeapon()->GetWeaponType()) { + switch (p.GetWeapon().GetWeaponType()) { case RIFLE_WEAPON: weaponSkin = initScriptFactory(rifleFactory, renderer, audio); weaponViewSkin = initScriptFactory(rifleViewFactory, renderer, audio); @@ -303,20 +318,18 @@ namespace spades { } asIScriptObject *ClientPlayer::initScriptFactory(ScriptFunction &creator, - IRenderer *renderer, IAudioDevice *audio) { + IRenderer &renderer, IAudioDevice &audio) { ScriptContextHandle ctx = creator.Prepare(); - ctx->SetArgObject(0, reinterpret_cast(renderer)); - ctx->SetArgObject(1, reinterpret_cast(audio)); + ctx->SetArgObject(0, reinterpret_cast(&renderer)); + ctx->SetArgObject(1, reinterpret_cast(&audio)); ctx.ExecuteChecked(); asIScriptObject *result = reinterpret_cast(ctx->GetReturnObject()); result->AddRef(); return result; } - void ClientPlayer::Invalidate() { player = NULL; } - bool ClientPlayer::IsChangingTool() { - return currentTool != player->GetTool() || toolRaiseState < .999f; + return currentTool != player.GetTool() || toolRaiseState < .999f; } float ClientPlayer::GetLocalFireVibration() { @@ -331,9 +344,9 @@ namespace spades { void ClientPlayer::Update(float dt) { time += dt; - PlayerInput actualInput = player->GetInput(); - WeaponInput actualWeapInput = player->GetWeaponInput(); - if (actualInput.sprint && player->IsAlive()) { + PlayerInput actualInput = player.GetInput(); + WeaponInput actualWeapInput = player.GetWeaponInput(); + if (actualInput.sprint && player.IsAlive()) { sprintState += dt * 4.f; if (sprintState > 1.f) sprintState = 1.f; @@ -343,7 +356,7 @@ namespace spades { sprintState = 0.f; } - if (actualWeapInput.secondary && player->IsToolWeapon() && player->IsAlive()) { + if (actualWeapInput.secondary && player.IsToolWeapon() && player.IsAlive()) { // This is the only animation that can be turned off // here; others affect the gameplay directly and // turning them off would be considered cheating @@ -364,7 +377,7 @@ namespace spades { } } - if (currentTool == player->GetTool()) { + if (currentTool == player.GetTool()) { toolRaiseState += dt * 4.f; if (toolRaiseState > 1.f) toolRaiseState = 1.f; @@ -374,44 +387,45 @@ namespace spades { toolRaiseState -= dt * 4.f; if (toolRaiseState < 0.f) { toolRaiseState = 0.f; - currentTool = player->GetTool(); + currentTool = player.GetTool(); // play tool change sound - if (player->IsLocalPlayer()) { - auto *audioDevice = client->GetAudioDevice(); + if (player.IsLocalPlayer()) { + IAudioDevice &audioDevice = client.GetAudioDevice(); Handle c; - switch (player->GetTool()) { + switch (player.GetTool()) { case Player::ToolSpade: - c = audioDevice->RegisterSound( - "Sounds/Weapons/Spade/RaiseLocal.opus"); + c = + audioDevice.RegisterSound("Sounds/Weapons/Spade/RaiseLocal.opus"); break; case Player::ToolBlock: - c = audioDevice->RegisterSound( - "Sounds/Weapons/Block/RaiseLocal.opus"); + c = + audioDevice.RegisterSound("Sounds/Weapons/Block/RaiseLocal.opus"); break; case Player::ToolWeapon: - switch (player->GetWeapon()->GetWeaponType()) { + switch (player.GetWeapon().GetWeaponType()) { case RIFLE_WEAPON: - c = audioDevice->RegisterSound( + c = audioDevice.RegisterSound( "Sounds/Weapons/Rifle/RaiseLocal.opus"); break; case SMG_WEAPON: - c = audioDevice->RegisterSound( + c = audioDevice.RegisterSound( "Sounds/Weapons/SMG/RaiseLocal.opus"); break; case SHOTGUN_WEAPON: - c = audioDevice->RegisterSound( + c = audioDevice.RegisterSound( "Sounds/Weapons/Shotgun/RaiseLocal.opus"); break; } break; case Player::ToolGrenade: - c = audioDevice->RegisterSound( + c = audioDevice.RegisterSound( "Sounds/Weapons/Grenade/RaiseLocal.opus"); break; } - audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam()); + audioDevice.PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, -.3f, .5f), + AudioParam()); } } else if (toolRaiseState > 1.f) { toolRaiseState = 1.f; @@ -420,10 +434,10 @@ namespace spades { { float scale = dt; - Vector3 vel = player->GetVelocity(); - Vector3 front = player->GetFront(); - Vector3 right = player->GetRight(); - Vector3 up = player->GetUp(); + Vector3 vel = player.GetVelocity(); + Vector3 front = player.GetFront(); + Vector3 right = player.GetRight(); + Vector3 up = player.GetUp(); // Offset the view weapon according to the player movement viewWeaponOffset.x += Vector3::Dot(vel, right) * scale; @@ -459,7 +473,7 @@ namespace spades { // When the player is aiming down the sight, the weapon's movement // must be restricted so that other parts of the weapon don't // cover the ironsight. - if (currentTool == Player::ToolWeapon && player->GetWeaponInput().secondary) { + if (currentTool == Player::ToolWeapon && player.GetWeaponInput().secondary) { if (dt > 0.f) viewWeaponOffset *= powf(.01f, dt); @@ -473,14 +487,14 @@ namespace spades { { // Smooth the flashlight's movement - Vector3 diff = player->GetFront() - flashlightOrientation; + Vector3 diff = player.GetFront() - flashlightOrientation; float sq = diff.GetLength(); if (sq > 0.1) { flashlightOrientation += diff.Normalize() * (sq - 0.1); } flashlightOrientation = - Mix(flashlightOrientation, player->GetFront(), 1.0f - powf(1.0e-6, dt)) + Mix(flashlightOrientation, player.GetFront(), 1.0f - powf(1.0e-6, dt)) .Normalize(); } @@ -518,12 +532,12 @@ namespace spades { } Matrix4 ClientPlayer::GetEyeMatrix() { - Vector3 eye = player->GetEye(); + Vector3 eye = player.GetEye(); if ((int)cg_shake >= 2) { float sp = SmoothStep(GetSprintState()); float p = - cosf(player->GetWalkAnimationProgress() * static_cast(M_PI) * 2.f - 0.8f); + cosf(player.GetWalkAnimationProgress() * static_cast(M_PI) * 2.f - 0.8f); p = p * p; p *= p; p *= p; @@ -531,26 +545,25 @@ namespace spades { eye.z -= p * 0.06f * sp; } - return Matrix4::FromAxis(-player->GetRight(), player->GetFront(), -player->GetUp(), - eye); + return Matrix4::FromAxis(-player.GetRight(), player.GetFront(), -player.GetUp(), eye); } void ClientPlayer::SetSkinParameterForTool(Player::ToolType type, asIScriptObject *skin) { - Player *p = player; + Player &p = player; if (currentTool == Player::ToolSpade) { ScriptISpadeSkin interface(skin); - WeaponInput inp = p->GetWeaponInput(); - if (p->GetTool() != Player::ToolSpade) { + WeaponInput inp = p.GetWeaponInput(); + if (p.GetTool() != Player::ToolSpade) { interface.SetActionType(SpadeActionTypeIdle); interface.SetActionProgress(0.f); } else if (inp.primary) { interface.SetActionType(SpadeActionTypeBash); - interface.SetActionProgress(p->GetSpadeAnimationProgress()); + interface.SetActionProgress(p.GetSpadeAnimationProgress()); } else if (inp.secondary) { - interface.SetActionType(p->IsFirstDig() ? SpadeActionTypeDigStart - : SpadeActionTypeDig); - interface.SetActionProgress(p->GetDigAnimationProgress()); + interface.SetActionType(p.IsFirstDig() ? SpadeActionTypeDigStart + : SpadeActionTypeDig); + interface.SetActionProgress(p.GetDigAnimationProgress()); } else { interface.SetActionType(SpadeActionTypeIdle); interface.SetActionProgress(0.f); @@ -559,38 +572,37 @@ namespace spades { // TODO: smooth ready state ScriptIBlockSkin interface(skin); - if (p->GetTool() != Player::ToolBlock) { + if (p.GetTool() != Player::ToolBlock) { // FIXME: use block's IsReadyToUseTool // for smoother transition interface.SetReadyState(0.f); - } else if (p->IsReadyToUseTool()) { + } else if (p.IsReadyToUseTool()) { interface.SetReadyState(1.f); } else { interface.SetReadyState(0.f); } - interface.SetBlockColor(MakeVector3(p->GetBlockColor()) / 255.f); + interface.SetBlockColor(MakeVector3(p.GetBlockColor()) / 255.f); } else if (currentTool == Player::ToolGrenade) { ScriptIGrenadeSkin interface(skin); - interface.SetReadyState(1.f - p->GetTimeToNextGrenade() / 0.5f); + interface.SetReadyState(1.f - p.GetTimeToNextGrenade() / 0.5f); - WeaponInput inp = p->GetWeaponInput(); + WeaponInput inp = p.GetWeaponInput(); if (inp.primary) { - interface.SetCookTime(p->GetGrenadeCookTime()); + interface.SetCookTime(p.GetGrenadeCookTime()); } else { interface.SetCookTime(0.f); } } else if (currentTool == Player::ToolWeapon) { - - Weapon *w = p->GetWeapon(); + Weapon &w = p.GetWeapon(); ScriptIWeaponSkin interface(skin); - interface.SetReadyState(1.f - w->TimeToNextFire() / w->GetDelay()); + interface.SetReadyState(1.f - w.TimeToNextFire() / w.GetDelay()); interface.SetAimDownSightState(aimDownState); - interface.SetAmmo(w->GetAmmo()); - interface.SetClipSize(w->GetClipSize()); - interface.SetReloading(w->IsReloading()); - interface.SetReloadProgress(w->GetReloadProgress()); + interface.SetAmmo(w.GetAmmo()); + interface.SetClipSize(w.GetClipSize()); + interface.SetReloading(w.IsReloading()); + interface.SetReloadProgress(w.GetReloadProgress()); } else { SPInvalidEnum("currentTool", currentTool); } @@ -632,7 +644,7 @@ namespace spades { ScriptIToolSkin interface(skin); interface.SetRaiseState((skin == curSkin) ? (1.f - putdown) : 0.f); interface.SetSprintState(sprint); - interface.SetMuted(client->IsMuted()); + interface.SetMuted(client.IsMuted()); } } @@ -640,16 +652,16 @@ namespace spades { std::array axes; axes[2] = flashlightOrientation; - axes[0] = Vector3::Cross(flashlightOrientation, player->GetUp()).Normalize(); + axes[0] = Vector3::Cross(flashlightOrientation, player.GetUp()).Normalize(); axes[1] = Vector3::Cross(axes[0], axes[2]); return axes; } void ClientPlayer::AddToSceneFirstPersonView() { - Player *p = player; - IRenderer *renderer = client->GetRenderer(); - World *world = client->GetWorld(); + Player &p = player; + IRenderer &renderer = client.GetRenderer(); + World *world = client.GetWorld(); Matrix4 eyeMatrix = GetEyeMatrix(); sandboxedRenderer->SetClipBox(AABB3(eyeMatrix.GetOrigin() - Vector3(20.f, 20.f, 20.f), @@ -657,33 +669,28 @@ namespace spades { sandboxedRenderer->SetAllowDepthHack(true); // no flashlight if spectating other players while dead - if (client->flashlightOn && world->GetLocalPlayer()->IsAlive()) { - float brightness; - brightness = client->time - client->flashlightOnTime; + if (client.flashlightOn && world->GetLocalPlayer()->IsAlive()) { + float brightness = client.time - client.flashlightOnTime; brightness = 1.f - expf(-brightness * 5.f); + brightness *= r_hdr ? 3.0f : 1.5f; // add flash light DynamicLightParam light; + Handle image = renderer.RegisterImage("Gfx/Spotlight.jpg"); light.origin = (eyeMatrix * MakeVector3(0, -0.05f, -0.1f)).GetXYZ(); - light.color = MakeVector3(1, .7f, .5f) * 1.5f * brightness; - light.radius = 40.f; + light.color = MakeVector3(1.0f, 0.7f, 0.5f) * brightness; + light.radius = 60.f; light.type = DynamicLightTypeSpotlight; - light.spotAngle = 30.f * M_PI / 180.f; + light.spotAngle = 90.f * M_PI / 180.f; light.spotAxis = GetFlashlightAxes(); - light.image = renderer->RegisterImage("Gfx/Spotlight.png"); - renderer->AddLight(light); + light.image = image.GetPointerOrNull(); + renderer.AddLight(light); light.color *= .3f; light.radius = 10.f; light.type = DynamicLightTypePoint; light.image = NULL; - renderer->AddLight(light); - - // add glare - renderer->SetColorAlphaPremultiplied(MakeVector4(1, .7f, .5f, 0) * brightness * - .3f); - renderer->AddSprite(renderer->RegisterImage("Gfx/Glare.png"), - (eyeMatrix * MakeVector3(0, 0.3f, -0.3f)).GetXYZ(), .8f, 0.f); + renderer.AddLight(light); } Vector3 leftHand, rightHand; @@ -698,10 +705,10 @@ namespace spades { { float sp = 1.f - aimDownState; sp *= .3f; - sp *= std::min(1.f, p->GetVelocity().GetLength() * 5.f); + sp *= std::min(1.f, p.GetVelocity().GetLength() * 5.f); viewWeaponOffset.x += - sinf(p->GetWalkAnimationProgress() * M_PI * 2.f) * 0.013f * sp; - float vl = cosf(p->GetWalkAnimationProgress() * M_PI * 2.f); + sinf(p.GetWalkAnimationProgress() * M_PI * 2.f) * 0.013f * sp; + float vl = cosf(p.GetWalkAnimationProgress() * M_PI * 2.f); vl *= vl; viewWeaponOffset.z += vl * 0.018f * sp; } @@ -717,7 +724,8 @@ namespace spades { } // manual adjustment - viewWeaponOffset += Vector3{cg_viewWeaponX, cg_viewWeaponY, cg_viewWeaponZ} * (1.f - aimDownState); + viewWeaponOffset += + Vector3{cg_viewWeaponX, cg_viewWeaponY, cg_viewWeaponZ} * (1.f - aimDownState); asIScriptObject *skin; @@ -759,10 +767,10 @@ namespace spades { ModelRenderParam param; param.depthHack = true; - IModel *model = renderer->RegisterModel("Models/Player/Arm.kv6"); - IModel *model2 = renderer->RegisterModel("Models/Player/UpperArm.kv6"); + Handle model = renderer.RegisterModel("Models/Player/Arm.kv6"); + Handle model2 = renderer.RegisterModel("Models/Player/UpperArm.kv6"); - IntVector3 col = p->GetColor(); + IntVector3 col = p.GetColor(); param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f); const float armlen = 0.5f; @@ -800,7 +808,7 @@ namespace spades { mat = eyeMatrix * mat; param.matrix = mat; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); } { @@ -815,7 +823,7 @@ namespace spades { mat = eyeMatrix * mat; param.matrix = mat; - renderer->RenderModel(model2, param); + renderer.RenderModel(*model2, param); } } } @@ -824,26 +832,25 @@ namespace spades { } void ClientPlayer::AddToSceneThirdPersonView() { + Player &p = player; + IRenderer &renderer = client.GetRenderer(); + World *world = client.GetWorld(); - Player *p = player; - IRenderer *renderer = client->GetRenderer(); - World *world = client->GetWorld(); - - if (!p->IsAlive()) { + if (!p.IsAlive()) { if (!cg_ragdoll) { ModelRenderParam param; - param.matrix = Matrix4::Translate(p->GetOrigin() + MakeVector3(0, 0, 1)); + param.matrix = Matrix4::Translate(p.GetOrigin() + MakeVector3(0, 0, 1)); param.matrix = param.matrix * Matrix4::Scale(.1f); - IntVector3 col = p->GetColor(); + IntVector3 col = p.GetColor(); param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f); - IModel *model = renderer->RegisterModel("Models/Player/Dead.kv6"); - renderer->RenderModel(model, param); + Handle model = renderer.RegisterModel("Models/Player/Dead.kv6"); + renderer.RenderModel(*model, param); } return; } - auto origin = p->GetOrigin(); + auto origin = p.GetOrigin(); sandboxedRenderer->SetClipBox( AABB3(origin - Vector3(2.f, 2.f, 4.f), origin + Vector3(2.f, 2.f, 2.f))); sandboxedRenderer->SetAllowDepthHack(false); @@ -874,22 +881,22 @@ namespace spades { } ModelRenderParam param; - IModel *model; - Vector3 front = p->GetFront(); - IntVector3 col = p->GetColor(); + Handle model; + Vector3 front = p.GetFront(); + IntVector3 col = p.GetColor(); param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f); float yaw = atan2(front.y, front.x) + M_PI * .5f; float pitch = -atan2(front.z, sqrt(front.x * front.x + front.y * front.y)); // lower axis - Matrix4 lower = Matrix4::Translate(p->GetOrigin()); + Matrix4 lower = Matrix4::Translate(p.GetOrigin()); lower = lower * Matrix4::Rotate(MakeVector3(0, 0, 1), yaw); Matrix4 scaler = Matrix4::Scale(0.1f); scaler = scaler * Matrix4::Scale(-1, -1, 1); - PlayerInput inp = p->GetInput(); + PlayerInput inp = p.GetInput(); // lower Matrix4 torso, head, arms; @@ -897,30 +904,30 @@ namespace spades { Matrix4 leg1 = Matrix4::Translate(-0.25f, 0.2f, -0.1f); Matrix4 leg2 = Matrix4::Translate(0.25f, 0.2f, -0.1f); - float ang = sinf(p->GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f; - float walkVel = Vector3::Dot(p->GetVelocity(), p->GetFront2D()) * 4.f; + float ang = sinf(p.GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f; + float walkVel = Vector3::Dot(p.GetVelocity(), p.GetFront2D()) * 4.f; leg1 = leg1 * Matrix4::Rotate(MakeVector3(1, 0, 0), ang * walkVel); leg2 = leg2 * Matrix4::Rotate(MakeVector3(1, 0, 0), -ang * walkVel); - walkVel = Vector3::Dot(p->GetVelocity(), p->GetRight()) * 3.f; + walkVel = Vector3::Dot(p.GetVelocity(), p.GetRight()) * 3.f; leg1 = leg1 * Matrix4::Rotate(MakeVector3(0, 1, 0), ang * walkVel); leg2 = leg2 * Matrix4::Rotate(MakeVector3(0, 1, 0), -ang * walkVel); leg1 = lower * leg1; leg2 = lower * leg2; - model = renderer->RegisterModel("Models/Player/LegCrouch.kv6"); + model = renderer.RegisterModel("Models/Player/LegCrouch.kv6"); param.matrix = leg1 * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); param.matrix = leg2 * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); torso = Matrix4::Translate(0.f, 0.f, -0.55f); torso = lower * torso; - model = renderer->RegisterModel("Models/Player/TorsoCrouch.kv6"); + model = renderer.RegisterModel("Models/Player/TorsoCrouch.kv6"); param.matrix = torso * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); head = Matrix4::Translate(0.f, 0.f, -0.0f); head = torso * head; @@ -931,30 +938,30 @@ namespace spades { Matrix4 leg1 = Matrix4::Translate(-0.25f, 0.f, -0.1f); Matrix4 leg2 = Matrix4::Translate(0.25f, 0.f, -0.1f); - float ang = sinf(p->GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f; - float walkVel = Vector3::Dot(p->GetVelocity(), p->GetFront2D()) * 4.f; + float ang = sinf(p.GetWalkAnimationProgress() * M_PI * 2.f) * 0.6f; + float walkVel = Vector3::Dot(p.GetVelocity(), p.GetFront2D()) * 4.f; leg1 = leg1 * Matrix4::Rotate(MakeVector3(1, 0, 0), ang * walkVel); leg2 = leg2 * Matrix4::Rotate(MakeVector3(1, 0, 0), -ang * walkVel); - walkVel = Vector3::Dot(p->GetVelocity(), p->GetRight()) * 3.f; + walkVel = Vector3::Dot(p.GetVelocity(), p.GetRight()) * 3.f; leg1 = leg1 * Matrix4::Rotate(MakeVector3(0, 1, 0), ang * walkVel); leg2 = leg2 * Matrix4::Rotate(MakeVector3(0, 1, 0), -ang * walkVel); leg1 = lower * leg1; leg2 = lower * leg2; - model = renderer->RegisterModel("Models/Player/Leg.kv6"); + model = renderer.RegisterModel("Models/Player/Leg.kv6"); param.matrix = leg1 * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); param.matrix = leg2 * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); torso = Matrix4::Translate(0.f, 0.f, -1.0f); torso = lower * torso; - model = renderer->RegisterModel("Models/Player/Torso.kv6"); + model = renderer.RegisterModel("Models/Player/Torso.kv6"); param.matrix = torso * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); head = Matrix4::Translate(0.f, 0.f, -0.0f); head = torso * head; @@ -975,15 +982,15 @@ namespace spades { arms = arms * Matrix4::Rotate(MakeVector3(1, 0, 0), armPitch); - model = renderer->RegisterModel("Models/Player/Arms.kv6"); + model = renderer.RegisterModel("Models/Player/Arms.kv6"); param.matrix = arms * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); head = head * Matrix4::Rotate(MakeVector3(1, 0, 0), pitch); - model = renderer->RegisterModel("Models/Player/Head.kv6"); + model = renderer.RegisterModel("Models/Player/Head.kv6"); param.matrix = head * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); // draw tool { @@ -998,22 +1005,22 @@ namespace spades { hasValidOriginMatrix = true; // draw intel in ctf - IGameMode *mode = world->GetMode(); + stmp::optional mode = world->GetMode(); if (mode && IGameMode::m_CTF == mode->ModeType()) { - CTFGameMode *ctfMode = static_cast(world->GetMode()); - int tId = p->GetTeamId(); + CTFGameMode &ctfMode = dynamic_cast(*mode); + int tId = p.GetTeamId(); if (tId < 3) { - CTFGameMode::Team &team = ctfMode->GetTeam(p->GetTeamId()); - if (team.hasIntel && team.carrier == p->GetId()) { + CTFGameMode::Team &team = ctfMode.GetTeam(p.GetTeamId()); + if (team.hasIntel && team.carrier == p.GetId()) { - IntVector3 col2 = world->GetTeam(1 - p->GetTeamId()).color; + IntVector3 col2 = world->GetTeam(1 - p.GetTeamId()).color; param.customColor = MakeVector3(col2.x / 255.f, col2.y / 255.f, col2.z / 255.f); Matrix4 mIntel = torso * Matrix4::Translate(0, 0.6f, 0.5f); - model = renderer->RegisterModel("Models/MapObjects/Intel.kv6"); + model = renderer.RegisterModel("Models/MapObjects/Intel.kv6"); param.matrix = mIntel * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); param.customColor = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f); @@ -1027,17 +1034,17 @@ namespace spades { void ClientPlayer::AddToScene() { SPADES_MARK_FUNCTION(); - Player *p = player; - const SceneDefinition &lastSceneDef = client->GetLastSceneDef(); + Player &p = player; + const SceneDefinition &lastSceneDef = client.GetLastSceneDef(); hasValidOriginMatrix = false; - if (p->GetTeamId() >= 2) { + if (p.GetTeamId() >= 2) { // spectator, or dummy player return; } - float distancePowered = (p->GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength(); + float distancePowered = (p.GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength(); if (distancePowered > 140.f * 140.f) { return; } @@ -1047,10 +1054,33 @@ namespace spades { } else { AddToSceneThirdPersonView(); } + + if (cg_debugToolSkinAnchors && currentTool == Player::ToolWeapon && + player.IsLocalPlayer()) { + IRenderer &renderer = client.GetRenderer(); + + auto drawAxes = [&renderer](Vector3 p) { + renderer.AddDebugLine(Vector3{p.x - 0.2f, p.y, p.z}, + Vector3{p.x + 0.2f, p.y, p.z}, + Vector4{1.0f, 0.0f, 0.0f, 1.0f}); + renderer.AddDebugLine(Vector3{p.x, p.y - 0.2f, p.z}, + Vector3{p.x, p.y + 0.2f, p.z}, + Vector4{0.0f, 0.6f, 0.0f, 1.0f}); + renderer.AddDebugLine(Vector3{p.x, p.y, p.z - 0.2f}, + Vector3{p.x, p.y, p.z + 0.2f}, + Vector4{0.0f, 0.0f, 1.0f, 1.0f}); + }; + + drawAxes(ShouldRenderInThirdPersonView() ? GetMuzzlePosition() + : GetMuzzlePositionInFirstPersonView()); + + drawAxes(ShouldRenderInThirdPersonView() ? GetCaseEjectPosition() + : GetCaseEjectPositionInFirstPersonView()); + } } void ClientPlayer::Draw2D() { - if (!ShouldRenderInThirdPersonView() && player->IsAlive()) { + if (!ShouldRenderInThirdPersonView() && player.IsAlive()) { asIScriptObject *skin; if (currentTool == Player::ToolSpade) { @@ -1081,7 +1111,60 @@ namespace spades { bool ClientPlayer::ShouldRenderInThirdPersonView() { // The player from whom's perspective the game is - return !IsFirstPerson(client->GetCameraMode()) || player != &client->GetCameraTargetPlayer(); + return !IsFirstPerson(client.GetCameraMode()) || + &player != &client.GetCameraTargetPlayer(); + } + + Vector3 ClientPlayer::GetMuzzlePosition() { + ScriptIWeaponSkin3 interface(weaponSkin); + if (interface.ImplementsInterface()) { + Vector3 muzzle = interface.GetMuzzlePosition(); + + // The skin should return a legit position. Return the default + // position if it didn't. + Vector3 origin = player.GetOrigin(); + AABB3 clip = AABB3(origin - Vector3(2.f, 2.f, 4.f), origin + Vector3(2.f, 2.f, 2.f)); + if (clip.Contains(muzzle)) { + return muzzle; + } + } + + return (GetEyeMatrix() * MakeVector3(-0.13f, 1.5f, 0.2f)).GetXYZ(); + } + + Vector3 ClientPlayer::GetMuzzlePositionInFirstPersonView() { + ScriptIWeaponSkin3 interface(weaponViewSkin); + if (interface.ImplementsInterface()) { + return interface.GetMuzzlePosition(); + } + + return (GetEyeMatrix() * MakeVector3(-0.13f, 1.5f, 0.2f)).GetXYZ(); + } + + Vector3 ClientPlayer::GetCaseEjectPosition() { + ScriptIWeaponSkin3 interface(weaponSkin); + if (interface.ImplementsInterface()) { + Vector3 CaseEject = interface.GetCaseEjectPosition(); + + // The skin should return a legit position. Return the default + // position if it didn't. + Vector3 origin = player.GetOrigin(); + AABB3 clip = AABB3(origin - Vector3(2.f, 2.f, 4.f), origin + Vector3(2.f, 2.f, 2.f)); + if (clip.Contains(CaseEject)) { + return CaseEject; + } + } + + return (GetEyeMatrix() * MakeVector3(-0.13f, .5f, 0.2f)).GetXYZ(); + } + + Vector3 ClientPlayer::GetCaseEjectPositionInFirstPersonView() { + ScriptIWeaponSkin3 interface(weaponViewSkin); + if (interface.ImplementsInterface()) { + return interface.GetCaseEjectPosition(); + } + + return (GetEyeMatrix() * MakeVector3(-0.13f, .5f, 0.2f)).GetXYZ(); } struct ClientPlayer::AmbienceInfo { @@ -1091,21 +1174,20 @@ namespace spades { }; ClientPlayer::AmbienceInfo ClientPlayer::ComputeAmbience() { - const SceneDefinition &lastSceneDef = client->GetLastSceneDef(); + const SceneDefinition &lastSceneDef = client.GetLastSceneDef(); if (!cg_environmentalAudio) { AmbienceInfo result; result.room = 0.0f; - result.distance = (lastSceneDef.viewOrigin - player->GetEye()).GetLength(); + result.distance = (lastSceneDef.viewOrigin - player.GetEye()).GetLength(); result.size = 0.0f; return result; } float maxDistance = 40.f; - GameMap *map = client->map; - SPAssert(map); + GameMap &map = *client.map; - Vector3 rayFrom = player->GetEye(); + Vector3 rayFrom = player.GetEye(); // uniformly distributed random unit vectors const Vector3 directions[24] = { {-0.4806003057749437f, -0.42909622618705534f, 0.7647874049440525f}, @@ -1144,7 +1226,7 @@ namespace spades { const Vector3 &rayTo = directions[i]; IntVector3 hitPos; - bool hit = map->CastRay(rayFrom, rayTo, maxDistance, hitPos); + bool hit = map.CastRay(rayFrom, rayTo, maxDistance, hitPos); if (hit) { Vector3 hitPosf = {(float)hitPos.x, (float)hitPos.y, (float)hitPos.z}; distance = (hitPosf - rayFrom).GetLength(); @@ -1153,7 +1235,7 @@ namespace spades { } if (hit) { - bool hit2 = map->CastRay(rayFrom, -rayTo, maxDistance, hitPos); + bool hit2 = map.CastRay(rayFrom, -rayTo, maxDistance, hitPos); if (hit2) feedbackness = 1.f; else @@ -1190,7 +1272,7 @@ namespace spades { AmbienceInfo result; result.room = reflections * feedbackness; - result.distance = (lastSceneDef.viewOrigin - player->GetEye()).GetLength(); + result.distance = (lastSceneDef.viewOrigin - player.GetEye()).GetLength(); result.size = std::max(std::min(roomSize / 15.0f, 1.0f), 0.0f); result.room *= std::max(0.0f, std::min((result.size - 0.1f) * 4.0f, 1.0f)); result.room *= 1.0f - result.size * 0.3f; @@ -1199,72 +1281,70 @@ namespace spades { } void ClientPlayer::FiredWeapon() { - World *world = player->GetWorld(); - Vector3 muzzle; - const SceneDefinition &lastSceneDef = client->GetLastSceneDef(); - IRenderer *renderer = client->GetRenderer(); - IAudioDevice *audioDevice = client->GetAudioDevice(); - Player *p = player; + World &world = player.GetWorld(); + const SceneDefinition &lastSceneDef = client.GetLastSceneDef(); + IRenderer &renderer = client.GetRenderer(); + IAudioDevice &audioDevice = client.GetAudioDevice(); + Player &p = player; - // make dlight - { - Vector3 vec; - Matrix4 eyeMatrix = GetEyeMatrix(); - Matrix4 mat; - mat = Matrix4::Translate(-0.13f, .5f, 0.2f); - mat = eyeMatrix * mat; + Vector3 muzzle = ShouldRenderInThirdPersonView() ? GetMuzzlePosition() + : GetMuzzlePositionInFirstPersonView(); - vec = (mat * MakeVector3(0, 1, 0)).GetXYZ(); - muzzle = vec; - client->MuzzleFire(vec, player->GetFront(), player == world->GetLocalPlayer()); - } + // make dlight + client.MuzzleFire(muzzle, player.GetFront(), &player == world.GetLocalPlayer()); if (cg_ejectBrass) { - float dist = (player->GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength(); + float dist = (player.GetOrigin() - lastSceneDef.viewOrigin).GetPoweredLength(); if (dist < 130.f * 130.f) { - IModel *model = NULL; + Handle model; Handle snd = NULL; Handle snd2 = NULL; - switch (player->GetWeapon()->GetWeaponType()) { + switch (player.GetWeapon().GetWeaponType()) { case RIFLE_WEAPON: - model = renderer->RegisterModel("Models/Weapons/Rifle/Casing.kv6"); + model = renderer.RegisterModel("Models/Weapons/Rifle/Casing.kv6"); snd = SampleRandomBool() - ? audioDevice->RegisterSound("Sounds/Weapons/Rifle/ShellDrop1.opus") - : audioDevice->RegisterSound( - "Sounds/Weapons/Rifle/ShellDrop2.opus"); + ? audioDevice.RegisterSound("Sounds/Weapons/Rifle/ShellDrop1.opus") + : audioDevice.RegisterSound("Sounds/Weapons/Rifle/ShellDrop2.opus"); snd2 = - audioDevice->RegisterSound("Sounds/Weapons/Rifle/ShellWater.opus"); + audioDevice.RegisterSound("Sounds/Weapons/Rifle/ShellWater.opus"); break; case SHOTGUN_WEAPON: // FIXME: don't want to show shotgun't casing // because it isn't ejected when firing - // model = renderer->RegisterModel("Models/Weapons/Shotgun/Casing.kv6"); + // model = renderer.RegisterModel("Models/Weapons/Shotgun/Casing.kv6"); break; case SMG_WEAPON: - model = renderer->RegisterModel("Models/Weapons/SMG/Casing.kv6"); + model = renderer.RegisterModel("Models/Weapons/SMG/Casing.kv6"); snd = SampleRandomBool() - ? audioDevice->RegisterSound("Sounds/Weapons/SMG/ShellDrop1.opus") - : audioDevice->RegisterSound("Sounds/Weapons/SMG/ShellDrop2.opus"); - snd2 = audioDevice->RegisterSound("Sounds/Weapons/SMG/ShellWater.opus"); + ? audioDevice.RegisterSound("Sounds/Weapons/SMG/ShellDrop1.opus") + : audioDevice.RegisterSound("Sounds/Weapons/SMG/ShellDrop2.opus"); + snd2 = audioDevice.RegisterSound("Sounds/Weapons/SMG/ShellWater.opus"); break; } if (model) { - Vector3 origin; - origin = muzzle - p->GetFront() * 0.5f; + Vector3 origin = ShouldRenderInThirdPersonView() + ? GetCaseEjectPosition() + : GetCaseEjectPositionInFirstPersonView(); Vector3 vel; - vel = p->GetFront() * 0.5f + p->GetRight() + p->GetUp() * 0.2f; - switch (p->GetWeapon()->GetWeaponType()) { - case SMG_WEAPON: vel -= p->GetFront() * 0.7f; break; + vel = p.GetFront() * 0.5f + p.GetRight() + p.GetUp() * 0.2f; + switch (p.GetWeapon().GetWeaponType()) { + case SMG_WEAPON: + vel -= p.GetFront() * (0.6f + SampleRandomFloat()/5); + vel += p.GetRight() * (SampleRandomFloat()/5 - 0.1f); + vel += p.GetUp() * (SampleRandomFloat()/5 - 0.1f); + break; case SHOTGUN_WEAPON: vel *= .5f; break; default: break; } - ILocalEntity *ent; - ent = new GunCasing(client, model, snd, snd2, origin, p->GetFront(), vel); - client->AddLocalEntity(ent); + auto ent = stmp::make_unique( + &client, model.GetPointerOrNull(), snd.GetPointerOrNull(), + snd2.GetPointerOrNull(), origin, p.GetFront(), vel); + + client.AddLocalEntity(std::move(ent)); } } } @@ -1284,7 +1364,7 @@ namespace spades { ScriptIWeaponSkin2 interface(skin); if (interface.ImplementsInterface()) { interface.SetSoundEnvironment(ambience.room, ambience.size, ambience.distance); - interface.SetSoundOrigin(player->GetEye()); + interface.SetSoundOrigin(player.GetEye()); } else if (ShouldRenderInThirdPersonView() && !hasValidOriginMatrix) { // Legacy skin scripts rely on OriginMatrix which is only updated when // the player's location is within the fog range. @@ -1314,7 +1394,7 @@ namespace spades { ScriptIWeaponSkin2 interface(skin); if (interface.ImplementsInterface()) { interface.SetSoundEnvironment(ambience.room, ambience.size, ambience.distance); - interface.SetSoundOrigin(player->GetEye()); + interface.SetSoundOrigin(player.GetEye()); } else if (ShouldRenderInThirdPersonView() && !hasValidOriginMatrix) { // Legacy skin scripts rely on OriginMatrix which is only updated when // the player's location is within the fog range. @@ -1342,5 +1422,5 @@ namespace spades { interface.ReloadedWeapon(); } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ClientPlayer.h b/Sources/Client/ClientPlayer.h index 574f2a8a9..cb29bfa13 100644 --- a/Sources/Client/ClientPlayer.h +++ b/Sources/Client/ClientPlayer.h @@ -39,11 +39,12 @@ namespace spades { class SandboxedRenderer; + // TODO: Use `shared_ptr` instead of `RefCountedObject` /** Representation of player which is used by * drawing/view layer of game client. */ class ClientPlayer : public RefCountedObject { - Client *client; - Player *player; + Client &client; + Player &player; float sprintState; float aimDownState; @@ -88,19 +89,16 @@ namespace spades { float GetLocalFireVibration(); - bool ShouldRenderInThirdPersonView(); - - asIScriptObject *initScriptFactory(ScriptFunction &creator, IRenderer *renderer, - IAudioDevice *audio); + // TODO: Naming convention violation + asIScriptObject *initScriptFactory(ScriptFunction &creator, IRenderer &renderer, + IAudioDevice &audio); protected: ~ClientPlayer(); public: - ClientPlayer(Player *p, Client *); - Player *GetPlayer() const { return player; } - - void Invalidate(); + ClientPlayer(Player &p, Client &); + Player &GetPlayer() const { return player; } void Update(float dt); void AddToScene(); @@ -114,7 +112,33 @@ namespace spades { float GetAimDownState() { return aimDownState; } float GetSprintState() { return sprintState; } + bool ShouldRenderInThirdPersonView(); + + /** + * Get the world coordinates representing the position of the currently wielded weapon's + * muzzle. + */ + Vector3 GetMuzzlePosition(); + + /** + * Get the world coordinates representing the position of the currently wielded weapon's + * muzzle, based on the player's first-person view rendering. + */ + Vector3 GetMuzzlePositionInFirstPersonView(); + + /** + * Get the world coordinates representing the position of the currently wielded weapon's + * case ejection port. + */ + Vector3 GetCaseEjectPosition(); + + /** + * Get the world coordinates representing the position of the currently wielded weapon's + * case ejection port, based on the player's first-person view rendering. + */ + Vector3 GetCaseEjectPositionInFirstPersonView(); + Matrix4 GetEyeMatrix(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ClientUI.cpp b/Sources/Client/ClientUI.cpp index a2142cc06..0b4424ebf 100644 --- a/Sources/Client/ClientUI.cpp +++ b/Sources/Client/ClientUI.cpp @@ -35,20 +35,20 @@ namespace spades { ClientUI::ClientUI(IRenderer *r, IAudioDevice *a, FontManager *fontManager, Client *client) : renderer(r), audioDevice(a), fontManager(fontManager), client(client) { SPADES_MARK_FUNCTION(); - if (r == NULL) - SPInvalidArgument("r"); - if (a == NULL) - SPInvalidArgument("a"); + if (!renderer) + SPInvalidArgument("renderer"); + if (!audioDevice) + SPInvalidArgument("audioDevice"); - helper.Set(new ClientUIHelper(this), false); + helper = Handle::New(this); ScopedPrivilegeEscalation privilege; static ScriptFunction uiFactory( "ClientUI@ CreateClientUI(Renderer@, AudioDevice@, FontManager@, ClientUIHelper@)"); { ScriptContextHandle ctx = uiFactory.Prepare(); - ctx->SetArgObject(0, renderer); - ctx->SetArgObject(1, audioDevice); + ctx->SetArgObject(0, renderer.GetPointerOrNull()); + ctx->SetArgObject(1, audioDevice.GetPointerOrNull()); ctx->SetArgObject(2, fontManager); ctx->SetArgObject(3, &*helper); @@ -327,5 +327,5 @@ namespace spades { return !ignoreInput.empty() && EqualsIgnoringCase(ignoreInput, key); } void ClientUI::setIgnored(const std::string &key) { ignoreInput = key; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ClientUI.h b/Sources/Client/ClientUI.h index 44cbeb11b..12b383442 100644 --- a/Sources/Client/ClientUI.h +++ b/Sources/Client/ClientUI.h @@ -89,5 +89,5 @@ namespace spades { void setIgnored(const std::string &key); }; ; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ClientUIHelper.cpp b/Sources/Client/ClientUIHelper.cpp index 592c46df9..54a6cf826 100644 --- a/Sources/Client/ClientUIHelper.cpp +++ b/Sources/Client/ClientUIHelper.cpp @@ -54,5 +54,5 @@ namespace spades { return; ui->AlertError(text); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ClientUIHelper.h b/Sources/Client/ClientUIHelper.h index 26deb65d4..7ebf58bda 100644 --- a/Sources/Client/ClientUIHelper.h +++ b/Sources/Client/ClientUIHelper.h @@ -42,5 +42,5 @@ namespace spades { void AlertWarning(const std::string &); void AlertError(const std::string &); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_Draw.cpp b/Sources/Client/Client_Draw.cpp index dc5efdefe..93bb3f531 100644 --- a/Sources/Client/Client_Draw.cpp +++ b/Sources/Client/Client_Draw.cpp @@ -32,6 +32,7 @@ #include "IAudioChunk.h" #include "IAudioDevice.h" +#include "CTFGameMode.h" #include "CenterMessageView.h" #include "ChatWindow.h" #include "ClientPlayer.h" @@ -41,6 +42,7 @@ #include "Fonts.h" #include "HurtRingView.h" #include "IFont.h" +#include "IGameMode.h" #include "ILocalEntity.h" #include "LimboView.h" #include "MapView.h" @@ -50,8 +52,6 @@ #include "SmokeSpriteEntity.h" #include "TCProgressView.h" #include "Tracer.h" -#include "IGameMode.h" -#include "CTFGameMode.h" #include "GameMap.h" #include "Grenade.h" @@ -103,11 +103,12 @@ namespace spades { return name; } } - } + } // namespace void Client::TakeScreenShot(bool sceneOnly) { SceneDefinition sceneDef = CreateSceneDefinition(); lastSceneDef = sceneDef; + UpdateMatrices(); // render scene flashDlights = flashDlightsOld; @@ -120,9 +121,9 @@ namespace spades { // Well done! renderer->FrameDone(); - Handle bmp(renderer->ReadBitmap(), false); - // force 100% opacity + Handle bmp = renderer->ReadBitmap(); + // force 100% opacity uint32_t *pixels = bmp->GetPixels(); for (size_t i = bmp->GetWidth() * bmp->GetHeight(); i > 0; i--) { *(pixels++) |= 0xff000000UL; @@ -212,12 +213,12 @@ namespace spades { DrawSplash(); - IFont *font = fontManager->GetGuiFont(); + IFont &font = fontManager->GetGuiFont(); std::string str = _Tr("Client", "NOW LOADING"); - Vector2 size = font->Measure(str); + Vector2 size = font.Measure(str); Vector2 pos = MakeVector2(scrSize.x - 16.f, scrSize.y - 16.f); pos -= size; - font->DrawShadow(str, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(str, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.5)); renderer->FrameDone(); renderer->Flip(); @@ -269,11 +270,11 @@ namespace spades { float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); float wTime = world->GetTime(); - Player *p = GetWorld()->GetLocalPlayer(); + Player &p = GetWorld()->GetLocalPlayer().value(); if (wTime < lastHurtTime + .35f && wTime >= lastHurtTime) { float per = (wTime - lastHurtTime) / .35f; per = 1.f - per; - per *= .3f + (1.f - p->GetHealth() / 100.f) * .7f; + per *= .3f + (1.f - p.GetHealth() / 100.f) * .7f; per = std::min(per, 0.9f); per = 1.f - per; Vector3 color = {1.f, per, per}; @@ -291,30 +292,31 @@ namespace spades { if ((int)cg_playerNames == 0) return; - Player *p = GetWorld()->GetLocalPlayer(); + Player &p = GetWorld()->GetLocalPlayer().value(); - hitTag_t tag = hit_None; - Player *hottracked = HotTrackedPlayer(&tag); + auto hottracked = HotTrackedPlayer(); if (hottracked) { - Vector3 posxyz = Project(hottracked->GetEye()); + Player &hottrackedPlayer = std::get<0>(*hottracked); + + Vector3 posxyz = Project(hottrackedPlayer.GetEye()); Vector2 pos = {posxyz.x, posxyz.y}; char buf[64]; if ((int)cg_playerNames == 1) { - float dist = (hottracked->GetEye() - p->GetEye()).GetLength(); + float dist = (hottrackedPlayer.GetEye() - p.GetEye()).GetLength(); int idist = (int)floorf(dist + .5f); - sprintf(buf, "%s [%d%s]", hottracked->GetName().c_str(), idist, + sprintf(buf, "%s [%d%s]", hottrackedPlayer.GetName().c_str(), idist, (idist == 1) ? "block" : "blocks"); } else - sprintf(buf, "%s", hottracked->GetName().c_str()); + sprintf(buf, "%s", hottrackedPlayer.GetName().c_str()); pos.y += (int)cg_playerNameY; pos.x += (int)cg_playerNameX; - IFont *font = fontManager->GetGuiFont(); - Vector2 size = font->Measure(buf); + IFont &font = fontManager->GetGuiFont(); + Vector2 size = font.Measure(buf); pos.x -= size.x * .5f; pos.y -= size.y; - font->DrawShadow(buf, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(buf, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.5)); } } @@ -327,7 +329,7 @@ namespace spades { Player &p = GetCameraTargetPlayer(); // IFont *font; - Weapon &w = *p.GetWeapon(); + Weapon &w = p.GetWeapon(); float spread = w.GetSpread(); AABB2 boundary(0, 0, 0, 0); @@ -402,7 +404,7 @@ namespace spades { clientPlayers[playerId]->Draw2D(); if (cg_hitIndicator && hitFeedbackIconState > 0.f && !cg_hideHud) { - Handle img(renderer->RegisterImage("Gfx/HitFeedback.png"), false); + Handle img = renderer->RegisterImage("Gfx/HitFeedback.png"); Vector2 pos = {scrWidth * .5f, scrHeight * .5f}; pos.x -= img->GetWidth() * .5f; pos.y -= img->GetHeight() * .5f; @@ -426,10 +428,10 @@ namespace spades { if (mode.ModeType() == IGameMode::m_CTF) { auto &ctfMode = static_cast(mode); if (ctfMode.PlayerHasIntel(*world, player)) { - Handle img(renderer->RegisterImage("Gfx/Intel.png"), false); + Handle img = renderer->RegisterImage("Gfx/Intel.png"); // Strobe - Vector4 color {1.0f, 1.0f, 1.0f, 1.0f}; + Vector4 color{1.0f, 1.0f, 1.0f, 1.0f}; color *= std::fabs(std::sin(world->GetTime() * 2.0f)); renderer->SetColorAlphaPremultiplied(color); @@ -448,8 +450,7 @@ namespace spades { float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); - Player *p = GetWorld()->GetLocalPlayer(); - IFont *font; + Player &p = GetWorld()->GetLocalPlayer().value(); // Draw damage rings if (!cg_hideHud) @@ -459,15 +460,15 @@ namespace spades { // Draw ammo amount // (Note: this cannot be displayed for a spectated player --- the server // does not submit sufficient information) - Weapon *weap = p->GetWeapon(); + Weapon &weap = p.GetWeapon(); Handle ammoIcon; float iconWidth, iconHeight; float spacing = 2.f; int stockNum; int warnLevel; - if (p->IsToolWeapon()) { - switch (weap->GetWeaponType()) { + if (p.IsToolWeapon()) { + switch (weap.GetWeaponType()) { case RIFLE_WEAPON: ammoIcon = renderer->RegisterImage("Gfx/Bullet/7.62mm.png"); iconWidth = 6.f; @@ -484,11 +485,11 @@ namespace spades { iconHeight = iconWidth / 4.f; spacing = -6.f; break; - default: SPInvalidEnum("weap->GetWeaponType()", weap->GetWeaponType()); + default: SPInvalidEnum("weap->GetWeaponType()", weap.GetWeaponType()); } - int clipSize = weap->GetClipSize(); - int clip = weap->GetAmmo(); + int clipSize = weap.GetClipSize(); + int clip = weap.GetAmmo(); clipSize = std::max(clipSize, clip); @@ -505,17 +506,17 @@ namespace spades { renderer->DrawImage(ammoIcon, AABB2(x, y, iconWidth, iconHeight)); } - stockNum = weap->GetStock(); - warnLevel = weap->GetMaxStock() / 3; + stockNum = weap.GetStock(); + warnLevel = weap.GetMaxStock() / 3; } else { iconHeight = 0.f; warnLevel = 0; - switch (p->GetTool()) { + switch (p.GetTool()) { case Player::ToolSpade: - case Player::ToolBlock: stockNum = p->GetNumBlocks(); break; - case Player::ToolGrenade: stockNum = p->GetNumGrenades(); break; - default: SPInvalidEnum("p->GetTool()", p->GetTool()); + case Player::ToolBlock: stockNum = p.GetNumBlocks(); break; + case Player::ToolGrenade: stockNum = p.GetNumGrenades(); break; + default: SPInvalidEnum("p->GetTool()", p.GetTool()); } } @@ -530,36 +531,36 @@ namespace spades { char buf[64]; sprintf(buf, "%d", stockNum); - font = fontManager->GetSquareDesignFont(); + IFont &font = fontManager->GetSquareDesignFont(); std::string stockStr = buf; - Vector2 size = font->Measure(stockStr); + Vector2 size = font.Measure(stockStr); Vector2 pos = MakeVector2(scrWidth - 16.f, scrHeight - 16.f - iconHeight); pos -= size; - font->DrawShadow(stockStr, pos, 1.f, numberColor, MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(stockStr, pos, 1.f, numberColor, MakeVector4(0, 0, 0, 0.5)); // draw "press ... to reload" { std::string msg = ""; - switch (p->GetTool()) { + switch (p.GetTool()) { case Player::ToolBlock: - if (p->GetNumBlocks() == 0) { + if (p.GetNumBlocks() == 0) { msg = _Tr("Client", "Out of Block"); } break; case Player::ToolGrenade: - if (p->GetNumGrenades() == 0) { + if (p.GetNumGrenades() == 0) { msg = _Tr("Client", "Out of Grenade"); } break; case Player::ToolWeapon: { - Weapon *weap = p->GetWeapon(); - if (weap->IsReloading() || p->IsAwaitingReloadCompletion()) { + Weapon &weap = p.GetWeapon(); + if (weap.IsReloading() || p.IsAwaitingReloadCompletion()) { msg = _Tr("Client", "Reloading"); - } else if (weap->GetAmmo() == 0 && weap->GetStock() == 0) { + } else if (weap.GetAmmo() == 0 && weap.GetStock() == 0) { msg = _Tr("Client", "Out of Ammo"); - } else if (weap->GetStock() > 0 && - weap->GetAmmo() < weap->GetClipSize() / 4) { + } else if (weap.GetStock() > 0 && + weap.GetAmmo() < weap.GetClipSize() / 4) { msg = _Tr("Client", "Press [{0}] to Reload", TranslateKeyName(cg_keyReloadWeapon)); } @@ -569,15 +570,15 @@ namespace spades { } if (!msg.empty()) { - font = fontManager->GetGuiFont(); - Vector2 size = font->Measure(msg); + IFont &font = fontManager->GetGuiFont(); + Vector2 size = font.Measure(msg); Vector2 pos = MakeVector2((scrWidth - size.x) * .5f, scrHeight * 2.f / 3.f); - font->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), + MakeVector4(0, 0, 0, 0.5)); } } - if (p->GetTool() == Player::ToolBlock) { + if (p.GetTool() == Player::ToolBlock) { paletteView->Draw(); } @@ -591,17 +592,16 @@ namespace spades { void Client::DrawDeadPlayerHUD() { SPADES_MARK_FUNCTION(); - Player *p = GetWorld()->GetLocalPlayer(); - IFont *font; + Player &p = GetWorld()->GetLocalPlayer().value(); float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); if (!cg_hideHud) { // draw respawn tme - if (!p->IsAlive()) { + if (!p.IsAlive()) { std::string msg; - float secs = p->GetRespawnTime() - world->GetTime(); + float secs = p.GetRespawnTime() - world->GetTime(); if (secs > 0.f) msg = _Tr("Client", "You will respawn in: {0}", (int)ceilf(secs)); @@ -609,12 +609,12 @@ namespace spades { msg = _Tr("Client", "Waiting for respawn"); if (!msg.empty()) { - font = fontManager->GetGuiFont(); - Vector2 size = font->Measure(msg); + IFont &font = fontManager->GetGuiFont(); + Vector2 size = font.Measure(msg); Vector2 pos = MakeVector2((scrWidth - size.x) * .5f, scrHeight / 3.f); - font->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), + MakeVector4(0, 0, 0, 0.5)); } } } @@ -627,7 +627,7 @@ namespace spades { return; } - IFont &font = *fontManager->GetGuiFont(); + IFont &font = fontManager->GetGuiFont(); float scrWidth = renderer->ScreenWidth(); float textX = scrWidth - 8.0f; @@ -675,7 +675,7 @@ namespace spades { void Client::DrawAlert() { SPADES_MARK_FUNCTION(); - IFont *font = fontManager->GetGuiFont(); + IFont &font = fontManager->GetGuiFont(); float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); auto &r = renderer; @@ -692,9 +692,9 @@ namespace spades { borderFade = std::max(std::min(borderFade, 1.f), 0.f); borderFade *= fade; - Handle alertIcon(renderer->RegisterImage("Gfx/AlertIcon.png"), false); + Handle alertIcon = renderer->RegisterImage("Gfx/AlertIcon.png"); - Vector2 textSize = font->Measure(alertContents); + Vector2 textSize = font.Measure(alertContents); Vector2 contentsSize = textSize; contentsSize.y = std::max(contentsSize.y, 16.f); if (alertType != AlertType::Notice) { @@ -756,35 +756,35 @@ namespace spades { color = Vector4(1.f, 1.f, 1.f, 1.f); color *= fade; - font->DrawShadow(alertContents, Vector2(pos.x + contentsSize.x - textSize.x - margin, - pos.y + (contentsSize.y - textSize.y) * 0.5f), - 1.f, color, Vector4(0.f, 0.f, 0.f, fade * 0.5f)); + font.DrawShadow(alertContents, + Vector2(pos.x + contentsSize.x - textSize.x - margin, + pos.y + (contentsSize.y - textSize.y) * 0.5f), + 1.f, color, Vector4(0.f, 0.f, 0.f, fade * 0.5f)); } void Client::DrawHealth() { SPADES_MARK_FUNCTION(); - Player *p = GetWorld()->GetLocalPlayer(); - IFont *font; + Player &p = GetWorld()->GetLocalPlayer().value(); // float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); - std::string str = std::to_string(p->GetHealth()); + std::string str = std::to_string(p.GetHealth()); Vector4 numberColor = {1, 1, 1, 1}; - if (p->GetHealth() == 0) { + if (p.GetHealth() == 0) { numberColor.y = 0.3f; numberColor.z = 0.3f; - } else if (p->GetHealth() <= 50) { + } else if (p.GetHealth() <= 50) { numberColor.z = 0.3f; } - font = fontManager->GetSquareDesignFont(); - Vector2 size = font->Measure(str); + IFont &font = fontManager->GetSquareDesignFont(); + Vector2 size = font.Measure(str); Vector2 pos = MakeVector2(16.f, scrHeight - 16.f); pos.y -= size.y; - font->DrawShadow(str, pos, 1.f, numberColor, MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(str, pos, 1.f, numberColor, MakeVector4(0, 0, 0, 0.5)); } void Client::Draw2DWithWorld() { @@ -794,7 +794,7 @@ namespace spades { ent->Render2D(); } - Player *p = GetWorld()->GetLocalPlayer(); + stmp::optional p = GetWorld()->GetLocalPlayer(); if (p) { DrawHurtSprites(); DrawHurtScreenEffect(); @@ -854,17 +854,16 @@ namespace spades { // no world; loading? float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); - IFont *font; DrawSplash(); Handle img; std::string msg = net->GetStatusString(); - font = fontManager->GetGuiFont(); - Vector2 textSize = font->Measure(msg); - font->Draw(msg, MakeVector2(scrWidth - 16.f, scrHeight - 24.f) - textSize, 1.f, - MakeVector4(1, 1, 1, 0.95f)); + IFont &font = fontManager->GetGuiFont(); + Vector2 textSize = font.Measure(msg); + font.Draw(msg, MakeVector2(scrWidth - 16.f, scrHeight - 24.f) - textSize, 1.f, + MakeVector4(1, 1, 1, 0.95f)); img = renderer->RegisterImage("Gfx/White.tga"); @@ -940,19 +939,18 @@ namespace spades { float scrWidth = renderer->ScreenWidth(); float scrHeight = renderer->ScreenHeight(); - IFont *font = fontManager->GetGuiFont(); + IFont &font = fontManager->GetGuiFont(); float margin = 5.f; - IRenderer *r = renderer; - auto size = font->Measure(str); + auto size = font.Measure(str); size += Vector2(margin * 2.f, margin * 2.f); auto pos = (Vector2(scrWidth, scrHeight) - size) * Vector2(0.5f, 1.f); - r->SetColorAlphaPremultiplied(Vector4(0.f, 0.f, 0.f, 0.5f)); - r->DrawImage(nullptr, AABB2(pos.x, pos.y, size.x, size.y)); - font->DrawShadow(str, pos + Vector2(margin, margin), 1.f, Vector4(1.f, 1.f, 1.f, 1.f), - Vector4(0.f, 0.f, 0.f, 0.5f)); + renderer->SetColorAlphaPremultiplied(Vector4(0.f, 0.f, 0.f, 0.5f)); + renderer->DrawImage(nullptr, AABB2(pos.x, pos.y, size.x, size.y)); + font.DrawShadow(str, pos + Vector2(margin, margin), 1.f, Vector4(1.f, 1.f, 1.f, 1.f), + Vector4(0.f, 0.f, 0.f, 0.5f)); } void Client::Draw2D() { @@ -966,5 +964,5 @@ namespace spades { DrawStats(); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_FPSCounter.cpp b/Sources/Client/Client_FPSCounter.cpp index e4a9883bf..df5b864ed 100644 --- a/Sources/Client/Client_FPSCounter.cpp +++ b/Sources/Client/Client_FPSCounter.cpp @@ -37,5 +37,5 @@ namespace spades { sw.Reset(); } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_Input.cpp b/Sources/Client/Client_Input.cpp index 0c1179b71..4031cf472 100644 --- a/Sources/Client/Client_Input.cpp +++ b/Sources/Client/Client_Input.cpp @@ -27,8 +27,8 @@ #include "IAudioChunk.h" #include "IAudioDevice.h" -#include "ClientUI.h" #include "ChatWindow.h" +#include "ClientUI.h" #include "Corpse.h" #include "LimboView.h" #include "MapView.h" @@ -155,8 +155,8 @@ namespace spades { SPAssert(world); SPAssert(world->GetLocalPlayer()); - Player *p = world->GetLocalPlayer(); - if (p->IsAlive()) { + Player &p = world->GetLocalPlayer().value(); + if (p.IsAlive()) { float aimDownState = GetAimDownState(); x /= GetAimDownZoomScale(); y /= GetAimDownZoomScale(); @@ -194,7 +194,7 @@ namespace spades { if (cg_invertMouseY) y = -y; - p->Turn(x * 0.003f, y * 0.003f); + p.Turn(x * 0.003f, y * 0.003f); } break; } @@ -329,7 +329,7 @@ namespace spades { if (cameraMode == ClientCameraMode::Free || cameraMode == ClientCameraMode::ThirdPersonLocal) { // Start with the local player - followedPlayerId = world->GetLocalPlayerIndex(); + followedPlayerId = world->GetLocalPlayerIndex().value(); } if (world->GetLocalPlayer()->IsSpectator() || time > lastAliveTime + 1.3f) { @@ -342,7 +342,7 @@ namespace spades { if (cameraMode == ClientCameraMode::Free || cameraMode == ClientCameraMode::ThirdPersonLocal) { // Start with the local player - followedPlayerId = world->GetLocalPlayerIndex(); + followedPlayerId = world->GetLocalPlayerIndex().value(); } if (world->GetLocalPlayer()->IsSpectator() || time > lastAliveTime + 1.3f) { @@ -369,9 +369,9 @@ namespace spades { } if (world->GetLocalPlayer()) { - Player *p = world->GetLocalPlayer(); + Player &p = world->GetLocalPlayer().value(); - if (p->IsAlive() && p->GetTool() == Player::ToolBlock && down) { + if (p.IsAlive() && p.GetTool() == Player::ToolBlock && down) { if (paletteView->KeyInput(name)) { return; } @@ -379,11 +379,10 @@ namespace spades { if (cg_debugCorpse) { if (name == "p" && down) { - Corpse *corp; - Player *victim = world->GetLocalPlayer(); - corp = new Corpse(renderer, map, victim); - corp->AddImpulse(victim->GetFront() * 32.f); - corpses.emplace_back(corp); + Player &victim = world->GetLocalPlayer().value(); + auto corp = stmp::make_unique(*renderer, *map, victim); + corp->AddImpulse(victim.GetFront() * 32.f); + corpses.emplace_back(std::move(corp)); if (corpses.size() > corpseHardLimit) { corpses.pop_front(); @@ -433,27 +432,29 @@ namespace spades { } else if (CheckKey(cg_keyAltAttack, name)) { auto lastVal = weapInput.secondary; if (world->GetLocalPlayer()->IsToolWeapon() && (!cg_holdAimDownSight)) { - if (down && !world->GetLocalPlayer()->GetWeapon()->IsReloading()) { + if (down && !world->GetLocalPlayer()->GetWeapon().IsReloading()) { weapInput.secondary = !weapInput.secondary; } } else { weapInput.secondary = down; } if (world->GetLocalPlayer()->IsToolWeapon() && weapInput.secondary && - !lastVal && world->GetLocalPlayer()->GetWeapon()->TimeToNextFire() <= 0 && - !world->GetLocalPlayer()->GetWeapon()->IsReloading() && + !lastVal && + world->GetLocalPlayer()->GetWeapon().TimeToNextFire() <= 0 && + !world->GetLocalPlayer()->GetWeapon().IsReloading() && GetSprintState() == 0.0f) { AudioParam params; params.volume = 0.08f; Handle chunk = audioDevice->RegisterSound("Sounds/Weapons/AimDownSightLocal.opus"); - audioDevice->PlayLocal(chunk, MakeVector3(.4f, -.3f, .5f), params); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), + MakeVector3(.4f, -.3f, .5f), params); } } else if (CheckKey(cg_keyReloadWeapon, name) && down) { - Weapon *w = world->GetLocalPlayer()->GetWeapon(); - if (w->GetAmmo() < w->GetClipSize() && w->GetStock() > 0 && + Weapon &w = world->GetLocalPlayer()->GetWeapon(); + if (w.GetAmmo() < w.GetClipSize() && w.GetStock() > 0 && (!world->GetLocalPlayer()->IsAwaitingReloadCompletion()) && - (!w->IsReloading()) && + (!w.IsReloading()) && world->GetLocalPlayer()->GetTool() == Player::ToolWeapon) { if (world->GetLocalPlayer()->IsToolWeapon()) { if (weapInput.secondary) { @@ -537,23 +538,23 @@ namespace spades { mapView->SwitchScale(); Handle chunk = audioDevice->RegisterSound("Sounds/Misc/SwitchMapZoom.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } else if (CheckKey(cg_keyToggleMapZoom, name) && down) { if (largeMapView->ToggleZoom()) { Handle chunk = audioDevice->RegisterSound("Sounds/Misc/OpenMap.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } else { Handle chunk = audioDevice->RegisterSound("Sounds/Misc/CloseMap.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } } else if (CheckKey(cg_keyScoreboard, name)) { scoreboardVisible = down; } else if (CheckKey(cg_keyLimbo, name) && down) { limbo->SetSelectedTeam(world->GetLocalPlayer()->GetTeamId()); limbo->SetSelectedWeapon( - world->GetLocalPlayer()->GetWeapon()->GetWeaponType()); + world->GetLocalPlayer()->GetWeapon().GetWeaponType()); inGameLimbo = true; } else if (CheckKey(cg_keySceneshot, name) && down) { TakeScreenShot(true); @@ -563,13 +564,14 @@ namespace spades { TakeMapShot(); } else if (CheckKey(cg_keyFlashlight, name) && down) { // spectators and dead players should not be able to toggle the flashlight - if (world->GetLocalPlayer()->IsSpectator() || !world->GetLocalPlayer()->IsAlive()) + if (world->GetLocalPlayer()->IsSpectator() || + !world->GetLocalPlayer()->IsAlive()) return; flashlightOn = !flashlightOn; flashlightOnTime = time; Handle chunk = audioDevice->RegisterSound("Sounds/Player/Flashlight.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } else if (CheckKey(cg_keyAutoFocus, name) && down && (int)cg_manualFocus) { autoFocusEnabled = true; } else if (down) { @@ -626,5 +628,5 @@ namespace spades { } } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_LocalEnts.cpp b/Sources/Client/Client_LocalEnts.cpp index aadd477b3..8b27d2e53 100644 --- a/Sources/Client/Client_LocalEnts.cpp +++ b/Sources/Client/Client_LocalEnts.cpp @@ -111,26 +111,30 @@ namespace spades { } } - Player *Client::HotTrackedPlayer(hitTag_t *hitFlag) { + stmp::optional> Client::HotTrackedPlayer() { if (!IsFirstPerson(GetCameraMode())) - return nullptr; + return {}; - auto &p = GetCameraTargetPlayer(); + SPAssert(world); + + auto &cameraTargetPlayer = GetCameraTargetPlayer(); + + Vector3 origin = cameraTargetPlayer.GetEye(); + Vector3 dir = cameraTargetPlayer.GetFront(); + World::WeaponRayCastResult result = + world->WeaponRayCast(origin, dir, cameraTargetPlayer.GetId()); - Vector3 origin = p.GetEye(); - Vector3 dir = p.GetFront(); - World::WeaponRayCastResult result = world->WeaponRayCast(origin, dir, &p); + if (result.hit == false || !result.playerId) + return {}; - if (result.hit == false || result.player == nullptr) - return nullptr; + Player &player = world->GetPlayer(result.playerId.value()).value(); // don't hot track enemies (non-spectator only) - if (result.player->GetTeamId() != p.GetTeamId() && p.GetTeamId() < 2) - return nullptr; - if (hitFlag) { - *hitFlag = result.hitFlag; + if (player.GetTeamId() != cameraTargetPlayer.GetTeamId() && + cameraTargetPlayer.GetTeamId() < 2) { + return {}; } - return result.player; + return std::tuple{player, result.hitFlag}; } bool Client::IsMuted() { @@ -151,21 +155,21 @@ namespace spades { if ((int)cg_particles < 1) return; - + Handle img = renderer->RegisterImage("Gfx/White.tga"); Vector4 color = {0.5f, 0.02f, 0.04f, 1.f}; for (int i = 0; i < 10; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(v, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()) * 10.f, 1.f, 0.7f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(0.1f + SampleRandomFloat() * SampleRandomFloat() * 0.2f); ent->SetLifeTime(3.f, 0.f, 1.f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } if ((int)cg_particles < 2) @@ -173,36 +177,36 @@ namespace spades { color = MakeVector4(.7f, .35f, .37f, .6f); for (int i = 0; i < 2; i++) { - ParticleSpriteEntity *ent = - new SmokeSpriteEntity(this, color, 100.f, SmokeSpriteEntity::Type::Explosion); + auto ent = stmp::make_unique(*this, color, 100.f, + SmokeSpriteEntity::Type::Explosion); ent->SetTrajectory(v, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()) * .7f, .8f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(.5f + SampleRandomFloat() * SampleRandomFloat() * 0.2f, 2.f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(.20f + SampleRandomFloat() * .2f, 0.06f, .20f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } color.w *= .1f; for (int i = 0; i < 1; i++) { - ParticleSpriteEntity *ent = - new SmokeSpriteEntity(this, color, 40.f, SmokeSpriteEntity::Type::Steady); + auto ent = stmp::make_unique(*this, color, 40.f, + SmokeSpriteEntity::Type::Steady); ent->SetTrajectory(v, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()) * .7f, .8f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(.7f + SampleRandomFloat() * SampleRandomFloat() * 0.2f, 2.f, 0.1f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(.80f + SampleRandomFloat() * 0.4f, 0.06f, 1.0f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } } @@ -220,10 +224,10 @@ namespace spades { Handle img = renderer->RegisterImage("Gfx/White.tga"); Vector4 color = {c.x / 255.f, c.y / 255.f, c.z / 255.f, 1.f}; for (int i = 0; i < 7; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(origin, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()) * 7.f, 1.f, .9f); @@ -231,8 +235,8 @@ namespace spades { ent->SetRadius(0.2f + SampleRandomFloat() * SampleRandomFloat() * 0.1f); ent->SetLifeTime(2.f, 0.f, 1.f); if (distPowered < 16.f * 16.f) - ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::BounceWeak); + localEntities.emplace_back(std::move(ent)); } if ((int)cg_particles < 2) @@ -240,36 +244,37 @@ namespace spades { if (distPowered < 32.f * 32.f) { for (int i = 0; i < 16; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); - ent->SetTrajectory(origin, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat()) * - 12.f, + auto ent = stmp::make_unique(*this, img, color); + ent->SetTrajectory(origin, + MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat()) * + 12.f, 1.f, .9f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(0.1f + SampleRandomFloat() * SampleRandomFloat() * 0.14f); ent->SetLifeTime(2.f, 0.f, 1.f); if (distPowered < 16.f * 16.f) - ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::BounceWeak); + localEntities.emplace_back(std::move(ent)); } } color += (MakeVector4(1, 1, 1, 1) - color) * .2f; color.w *= .2f; for (int i = 0; i < 2; i++) { - ParticleSpriteEntity *ent = new SmokeSpriteEntity(this, color, 100.f); + auto ent = stmp::make_unique(*this, color, 100.f); ent->SetTrajectory(origin, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()) * .7f, 1.f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(.6f + SampleRandomFloat() * SampleRandomFloat() * 0.2f, 0.8f); ent->SetLifeTime(.3f + SampleRandomFloat() * .3f, 0.06f, .4f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::Ignore); + localEntities.emplace_back(std::move(ent)); } } @@ -288,18 +293,18 @@ namespace spades { Handle img = renderer->RegisterImage("Gfx/White.tga"); Vector4 color = {c.x / 255.f, c.y / 255.f, c.z / 255.f, 1.f}; for (int i = 0; i < 8; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(origin, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()) * 7.f, 1.f, 1.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(0.3f + SampleRandomFloat() * SampleRandomFloat() * 0.2f); ent->SetLifeTime(2.f, 0.f, 1.f); - ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::BounceWeak); + localEntities.emplace_back(std::move(ent)); } } @@ -320,20 +325,20 @@ namespace spades { // rapid smoke for (int i = 0; i < 2; i++) { - ParticleSpriteEntity *ent = - new SmokeSpriteEntity(this, color, 120.f, SmokeSpriteEntity::Type::Explosion); - ent->SetTrajectory( - origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat()) + - velBias * .5f) * - 0.3f, - 1.f, 0.f); + auto ent = stmp::make_unique(*this, color, 120.f, + SmokeSpriteEntity::Type::Explosion); + ent->SetTrajectory(origin, + (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat()) + + velBias * .5f) * + 0.3f, + 1.f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(.4f, 3.f, 0.0000005f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(0.2f + SampleRandomFloat() * 0.1f, 0.f, .30f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } } @@ -385,51 +390,52 @@ namespace spades { color = MakeVector4(.6f, .6f, .6f, 1.f); // rapid smoke for (int i = 0; i < 4; i++) { - ParticleSpriteEntity *ent = - new SmokeSpriteEntity(this, color, 60.f, SmokeSpriteEntity::Type::Explosion); - ent->SetTrajectory( - origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat()) + - velBias * .5f) * - 2.f, - 1.f, 0.f); + auto ent = stmp::make_unique(*this, color, 60.f, + SmokeSpriteEntity::Type::Explosion); + ent->SetTrajectory(origin, + (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat()) + + velBias * .5f) * + 2.f, + 1.f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(.6f + SampleRandomFloat() * SampleRandomFloat() * 0.4f, 2.f, .2f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(1.8f + SampleRandomFloat() * 0.1f, 0.f, .20f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } // slow smoke color.w = .25f; for (int i = 0; i < 8; i++) { - ParticleSpriteEntity *ent = new SmokeSpriteEntity(this, color, 20.f); + auto ent = stmp::make_unique(*this, color, 20.f); ent->SetTrajectory( - origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), - (SampleRandomFloat() - SampleRandomFloat()) * .2f)) * - 2.f, + origin, + (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), + (SampleRandomFloat() - SampleRandomFloat()) * .2f)) * + 2.f, 1.f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(1.5f + SampleRandomFloat() * SampleRandomFloat() * 0.8f, 0.2f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); switch ((int)cg_particles) { case 1: ent->SetLifeTime(0.8f + SampleRandomFloat() * 1.f, 0.1f, 8.f); break; case 2: ent->SetLifeTime(1.5f + SampleRandomFloat() * 2.f, 0.1f, 8.f); break; case 3: default: ent->SetLifeTime(2.f + SampleRandomFloat() * 5.f, 0.1f, 8.f); break; } - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } // fragments Handle img = renderer->RegisterImage("Gfx/White.tga"); color = MakeVector4(0.01, 0.03, 0, 1.f); for (int i = 0; i < 42; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); Vector3 dir = MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat()); dir += velBias * .5f; float radius = 0.1f + SampleRandomFloat() * SampleRandomFloat() * 0.2f; @@ -437,27 +443,28 @@ namespace spades { ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(radius); ent->SetLifeTime(3.5f + SampleRandomFloat() * 2.f, 0.f, 1.f); - ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::BounceWeak); + localEntities.emplace_back(std::move(ent)); } // fire smoke color = MakeVector4(1.f, .7f, .4f, .2f) * 5.f; for (int i = 0; i < 4; i++) { - ParticleSpriteEntity *ent = - new SmokeSpriteEntity(this, color, 120.f, SmokeSpriteEntity::Type::Explosion); - ent->SetTrajectory( - origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat()) + - velBias) * - 6.f, - 1.f, 0.f); + auto ent = stmp::make_unique(*this, color, 120.f, + SmokeSpriteEntity::Type::Explosion); + ent->SetTrajectory(origin, + (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat()) + + velBias) * + 6.f, + 1.f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(.3f + SampleRandomFloat() * SampleRandomFloat() * 0.4f, 3.f, .1f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(.18f + SampleRandomFloat() * 0.03f, 0.f, .10f); // ent->SetAdditive(true); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } } @@ -479,17 +486,18 @@ namespace spades { if ((int)cg_particles < 2) color.w = .3f; for (int i = 0; i < 7; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), -SampleRandomFloat() * 7.f)) * + SampleRandomFloat() - SampleRandomFloat(), + -SampleRandomFloat() * 7.f)) * 2.5f, .3f, .6f); ent->SetRotation(0.f); ent->SetRadius(1.5f + SampleRandomFloat() * SampleRandomFloat() * 0.4f, 1.3f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(3.f + SampleRandomFloat() * 0.3f, 0.f, .60f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } // water2 @@ -498,17 +506,18 @@ namespace spades { if ((int)cg_particles < 2) color.w = .4f; for (int i = 0; i < 16; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), -SampleRandomFloat() * 10.f)) * + SampleRandomFloat() - SampleRandomFloat(), + -SampleRandomFloat() * 10.f)) * 3.5f, 1.f, 1.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(0.9f + SampleRandomFloat() * SampleRandomFloat() * 0.4f, 0.7f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(3.f + SampleRandomFloat() * 0.3f, .7f, .60f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } // slow smoke @@ -516,30 +525,33 @@ namespace spades { if ((int)cg_particles < 2) color.w = .2f; for (int i = 0; i < 8; i++) { - ParticleSpriteEntity *ent = new SmokeSpriteEntity(this, color, 20.f); + auto ent = stmp::make_unique(*this, color, 20.f); ent->SetTrajectory( - origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat(), - (SampleRandomFloat() - SampleRandomFloat()) * .2f)) * - 2.f, + origin, + (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), + (SampleRandomFloat() - SampleRandomFloat()) * .2f)) * + 2.f, 1.f, 0.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(1.4f + SampleRandomFloat() * SampleRandomFloat() * 0.8f, 0.2f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); switch ((int)cg_particles) { case 1: ent->SetLifeTime(3.f + SampleRandomFloat() * 5.f, 0.1f, 8.f); break; case 2: case 3: default: ent->SetLifeTime(6.f + SampleRandomFloat() * 5.f, 0.1f, 8.f); break; } - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } // fragments img = renderer->RegisterImage("Gfx/White.tga"); color = MakeVector4(1, 1, 1, 0.7f); for (int i = 0; i < 42; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); - Vector3 dir = MakeVector3(SampleRandomFloat() - SampleRandomFloat(), SampleRandomFloat() - SampleRandomFloat(), + auto ent = stmp::make_unique(*this, img, color); + Vector3 dir = MakeVector3(SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), -SampleRandomFloat() * 3.f); dir += velBias * .5f; float radius = 0.1f + SampleRandomFloat() * SampleRandomFloat() * 0.2f; @@ -548,8 +560,8 @@ namespace spades { ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(radius); ent->SetLifeTime(3.5f + SampleRandomFloat() * 2.f, 0.f, 1.f); - ent->SetBlockHitAction(ParticleSpriteEntity::Delete); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::Delete); + localEntities.emplace_back(std::move(ent)); } // TODO: wave? @@ -564,7 +576,7 @@ namespace spades { if ((int)cg_particles < 1) return; - + Vector4 color; color = MakeVector4(.95f, .95f, .95f, .3f); // water1 @@ -572,17 +584,18 @@ namespace spades { if ((int)cg_particles < 2) color.w = .2f; for (int i = 0; i < 2; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), -SampleRandomFloat() * 7.f)) * + SampleRandomFloat() - SampleRandomFloat(), + -SampleRandomFloat() * 7.f)) * 1.f, .3f, .6f); ent->SetRotation(0.f); ent->SetRadius(0.6f + SampleRandomFloat() * SampleRandomFloat() * 0.4f, .7f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(3.f + SampleRandomFloat() * 0.3f, 0.1f, .60f); - localEntities.emplace_back(ent); + localEntities.emplace_back(std::move(ent)); } // water2 @@ -591,26 +604,28 @@ namespace spades { if ((int)cg_particles < 2) color.w = .4f; for (int i = 0; i < 6; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); ent->SetTrajectory(origin, (MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), -SampleRandomFloat() * 10.f)) * + SampleRandomFloat() - SampleRandomFloat(), + -SampleRandomFloat() * 10.f)) * 2.f, 1.f, 1.f); ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(0.6f + SampleRandomFloat() * SampleRandomFloat() * 0.6f, 0.6f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); - ent->SetLifeTime(3.f + SampleRandomFloat() * 0.3f, SampleRandomFloat() * 0.3f, .60f); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::Ignore); + ent->SetLifeTime(3.f + SampleRandomFloat() * 0.3f, SampleRandomFloat() * 0.3f, + .60f); + localEntities.emplace_back(std::move(ent)); } // fragments img = renderer->RegisterImage("Gfx/White.tga"); color = MakeVector4(1, 1, 1, 0.7f); for (int i = 0; i < 10; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(this, img, color); + auto ent = stmp::make_unique(*this, img, color); Vector3 dir = MakeVector3(SampleRandomFloat() - SampleRandomFloat(), - SampleRandomFloat() - SampleRandomFloat(), + SampleRandomFloat() - SampleRandomFloat(), -SampleRandomFloat() * 3.f); float radius = 0.03f + SampleRandomFloat() * SampleRandomFloat() * 0.05f; ent->SetTrajectory(origin + dir * .2f + MakeVector3(0, 0, -1.2f), dir * 5.f, @@ -618,8 +633,8 @@ namespace spades { ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(radius); ent->SetLifeTime(3.5f + SampleRandomFloat() * 2.f, 0.f, 1.f); - ent->SetBlockHitAction(ParticleSpriteEntity::Delete); - localEntities.emplace_back(ent); + ent->SetBlockHitAction(BlockHitAction::Delete); + localEntities.emplace_back(std::move(ent)); } // TODO: wave? @@ -692,12 +707,12 @@ namespace spades { SPAssert(world); const auto &lastSceneDef = this->lastSceneDef; - World::WeaponRayCastResult result = world->WeaponRayCast(origin, direction, nullptr); + World::WeaponRayCastResult result = world->WeaponRayCast(origin, direction, {}); if (result.hit) { return Vector3::Dot(result.hitPos - origin, lastSceneDef.viewAxis[2]); } - return std::nan(nullptr); + return NAN; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_NetHandler.cpp b/Sources/Client/Client_NetHandler.cpp index d20e5cda6..499e235c6 100644 --- a/Sources/Client/Client_NetHandler.cpp +++ b/Sources/Client/Client_NetHandler.cpp @@ -25,17 +25,16 @@ #include #include -#include #include "IAudioChunk.h" #include "IAudioDevice.h" #include "CTFGameMode.h" #include "GameMap.h" +#include "GameProperties.h" #include "IGameMode.h" #include "TCGameMode.h" #include "World.h" -#include "GameProperties.h" #include "CenterMessageView.h" #include "ChatWindow.h" @@ -68,20 +67,20 @@ namespace spades { freeCameraState.velocity = MakeVector3(0, 0, 0); } - void Client::PlayerCreatedBlock(spades::client::Player *p) { + void Client::PlayerCreatedBlock(Player &p) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { Handle c = audioDevice->RegisterSound("Sounds/Weapons/Block/Build.opus"); - audioDevice->Play(c, p->GetEye() + p->GetFront(), AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), p.GetEye() + p.GetFront(), AudioParam()); } } void Client::TeamCapturedTerritory(int teamId, int terId) { - TCGameMode::Territory *ter = - static_cast(world->GetMode())->GetTerritory(terId); - int old = ter->ownerTeamId; + TCGameMode::Territory &ter = + dynamic_cast(*world->GetMode()).GetTerritory(terId); + int old = ter.ownerTeamId; std::string msg; std::string teamName = chatWindow->TeamColorMessage(world->GetTeam(teamId).name, teamId); @@ -109,60 +108,60 @@ namespace spades { if (teamId == world->GetLocalPlayer()->GetTeamId()) { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/TC/YourTeamCaptured.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } else { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/TC/EnemyCaptured.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } } } - void Client::PlayerCapturedIntel(spades::client::Player *p) { + void Client::PlayerCapturedIntel(Player &p) { std::string msg; { - std::string holderName = chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId()); + std::string holderName = chatWindow->TeamColorMessage(p.GetName(), p.GetTeamId()); std::string otherTeamName = chatWindow->TeamColorMessage( - world->GetTeam(1 - p->GetTeamId()).name, 1 - p->GetTeamId()); + world->GetTeam(1 - p.GetTeamId()).name, 1 - p.GetTeamId()); msg = _Tr("Client", "{0} captured {1}'s intel", holderName, otherTeamName); chatWindow->AddMessage(msg); } if ((int)cg_centerMessage != 0) { - std::string holderName = p->GetName(); - std::string otherTeamName = world->GetTeam(1 - p->GetTeamId()).name; + std::string holderName = p.GetName(); + std::string otherTeamName = world->GetTeam(1 - p.GetTeamId()).name; msg = _Tr("Client", "{0} captured {1}'s Intel.", holderName, otherTeamName); NetLog("%s", msg.c_str()); centerMessageView->AddMessage(msg); } if (world->GetLocalPlayer() && !IsMuted()) { - if (p->GetTeamId() == world->GetLocalPlayer()->GetTeamId()) { + if (p.GetTeamId() == world->GetLocalPlayer()->GetTeamId()) { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/CTF/YourTeamCaptured.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } else { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/CTF/EnemyCaptured.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } } } - void Client::PlayerPickedIntel(spades::client::Player *p) { + void Client::PlayerPickedIntel(Player &p) { std::string msg; { - std::string holderName = chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId()); + std::string holderName = chatWindow->TeamColorMessage(p.GetName(), p.GetTeamId()); std::string otherTeamName = chatWindow->TeamColorMessage( - world->GetTeam(1 - p->GetTeamId()).name, 1 - p->GetTeamId()); + world->GetTeam(1 - p.GetTeamId()).name, 1 - p.GetTeamId()); msg = _Tr("Client", "{0} picked up {1}'s intel", holderName, otherTeamName); chatWindow->AddMessage(msg); } if ((int)cg_centerMessage != 0) { - std::string holderName = p->GetName(); - std::string otherTeamName = world->GetTeam(1 - p->GetTeamId()).name; + std::string holderName = p.GetName(); + std::string otherTeamName = world->GetTeam(1 - p.GetTeamId()).name; msg = _Tr("Client", "{0} picked up {1}'s Intel.", holderName, otherTeamName); NetLog("%s", msg.c_str()); centerMessageView->AddMessage(msg); @@ -171,23 +170,23 @@ namespace spades { if (!IsMuted()) { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/CTF/PickedUp.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } } - void Client::PlayerDropIntel(spades::client::Player *p) { + void Client::PlayerDropIntel(Player &p) { std::string msg; { - std::string holderName = chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId()); + std::string holderName = chatWindow->TeamColorMessage(p.GetName(), p.GetTeamId()); std::string otherTeamName = chatWindow->TeamColorMessage( - world->GetTeam(1 - p->GetTeamId()).name, 1 - p->GetTeamId()); + world->GetTeam(1 - p.GetTeamId()).name, 1 - p.GetTeamId()); msg = _Tr("Client", "{0} dropped {1}'s intel", holderName, otherTeamName); chatWindow->AddMessage(msg); } if ((int)cg_centerMessage != 0) { - std::string holderName = p->GetName(); - std::string otherTeamName = world->GetTeam(1 - p->GetTeamId()).name; + std::string holderName = p.GetName(); + std::string otherTeamName = world->GetTeam(1 - p.GetTeamId()).name; msg = _Tr("Client", "{0} dropped {1}'s Intel", holderName, otherTeamName); NetLog("%s", msg.c_str()); centerMessageView->AddMessage(msg); @@ -195,6 +194,8 @@ namespace spades { } void Client::PlayerDestroyedBlockWithWeaponOrTool(spades::IntVector3 blk) { + SPAssert(map); + Vector3 origin = {blk.x + .5f, blk.y + .5f, blk.z + .5f}; if (!map->IsSolid(blk.x, blk.y, blk.z)) @@ -203,7 +204,7 @@ namespace spades { Handle c = audioDevice->RegisterSound("Sounds/Misc/BlockDestroy.opus"); if (!IsMuted()) { - audioDevice->Play(c, origin, AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), origin, AudioParam()); } uint32_t col = map->GetColor(blk.x, blk.y, blk.z); @@ -217,9 +218,11 @@ namespace spades { Handle c = audioDevice->RegisterSound("Sounds/Misc/BlockDestroy.opus"); if (!IsMuted()) { - audioDevice->Play(c, origin, AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), origin, AudioParam()); } + SPAssert(map); + for (int z = blk.z - 1; z <= blk.z + 1; z++) { if (z < 0 || z > 61) continue; @@ -232,13 +235,13 @@ namespace spades { } } - void Client::PlayerLeaving(spades::client::Player *p) { + void Client::PlayerLeaving(Player &p) { // Choose the next player if a follow cam is active on this player - if (FollowsNonLocalPlayer(GetCameraMode()) && &GetCameraTargetPlayer() == p) { + if (FollowsNonLocalPlayer(GetCameraMode()) && &GetCameraTargetPlayer() == &p) { FollowNextPlayer(false); // Still unable to find a substitute? - if (&GetCameraTargetPlayer() == p) { + if (&GetCameraTargetPlayer() == &p) { // Turn off the follow cam mode followCameraState.enabled = false; } @@ -247,42 +250,42 @@ namespace spades { { std::string msg; msg = _Tr("Client", "Player {0} has left", - chatWindow->TeamColorMessage(p->GetName(), p->GetTeamId())); + chatWindow->TeamColorMessage(p.GetName(), p.GetTeamId())); chatWindow->AddMessage(msg); } { std::string msg; - msg = _Tr("Client", "Player {0} has left", p->GetName()); + msg = _Tr("Client", "Player {0} has left", p.GetName()); - auto col = p->GetTeamId() < 2 ? world->GetTeam(p->GetTeamId()).color - : IntVector3::Make(255, 255, 255); + auto col = p.GetTeamId() < 2 ? world->GetTeam(p.GetTeamId()).color + : IntVector3::Make(255, 255, 255); NetLog("%s", msg.c_str()); scriptedUI->RecordChatLog( msg, MakeVector4(col.x / 255.f, col.y / 255.f, col.z / 255.f, 0.8f)); } - RemoveCorpseForPlayer(p->GetId()); + RemoveCorpseForPlayer(p.GetId()); } - void Client::PlayerJoinedTeam(spades::client::Player *p) { - std::string teamName = world->GetTeam(p->GetTeamId()).name; + void Client::PlayerJoinedTeam(Player &p) { + std::string teamName = world->GetTeam(p.GetTeamId()).name; - if (p->GetTeamId() >= 2) { + if (p.GetTeamId() >= 2) { teamName = _Tr("Client", "Spectator"); } { std::string msg; - msg = _Tr("Client", "{0} joined {1} team", p->GetName(), - chatWindow->TeamColorMessage(teamName, p->GetTeamId())); + msg = _Tr("Client", "{0} joined {1} team", p.GetName(), + chatWindow->TeamColorMessage(teamName, p.GetTeamId())); chatWindow->AddMessage(msg); } { std::string msg; - msg = _Tr("Client", "{0} joined {1} team", p->GetName(), teamName); + msg = _Tr("Client", "{0} joined {1} team", p.GetName(), teamName); - auto col = p->GetTeamId() < 2 ? world->GetTeam(p->GetTeamId()).color - : IntVector3::Make(255, 255, 255); + auto col = p.GetTeamId() < 2 ? world->GetTeam(p.GetTeamId()).color + : IntVector3::Make(255, 255, 255); NetLog("%s", msg.c_str()); scriptedUI->RecordChatLog( @@ -290,13 +293,15 @@ namespace spades { } } - void Client::PlayerSpawned(Player *p) { + void Client::PlayerSpawned(Player &p) { if (net->GetGameProperties()->clearCorpseOnRespawn) { - RemoveCorpseForPlayer(p->GetId()); + RemoveCorpseForPlayer(p.GetId()); } } void Client::GrenadeDestroyedBlock(spades::IntVector3 blk) { + SPAssert(map); + for (int x = blk.x - 1; x <= blk.x + 1; x++) for (int y = blk.y - 1; y <= blk.y + 1; y++) for (int z = blk.z - 1; z <= blk.z + 1; z++) { @@ -328,17 +333,15 @@ namespace spades { if (teamId == world->GetLocalPlayer()->GetTeamId()) { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/Win.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } else { Handle chunk = audioDevice->RegisterSound("Sounds/Feedback/Lose.opus"); - audioDevice->PlayLocal(chunk, AudioParam()); + audioDevice->PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } } } - void Client::MarkWorldUpdate() { - upsCounter.MarkFrame(); - } - } -} + void Client::MarkWorldUpdate() { upsCounter.MarkFrame(); } + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_Scene.cpp b/Sources/Client/Client_Scene.cpp index 6966ca0b9..a9397b5af 100644 --- a/Sources/Client/Client_Scene.cpp +++ b/Sources/Client/Client_Scene.cpp @@ -56,7 +56,7 @@ namespace spades { return ClientCameraMode::None; } - Player *p = world->GetLocalPlayer(); + stmp::optional p = world->GetLocalPlayer(); if (!p) { return ClientCameraMode::NotJoined; } @@ -95,7 +95,7 @@ namespace spades { case ClientCameraMode::FirstPersonLocal: case ClientCameraMode::ThirdPersonLocal: SPAssert(world); - return world->GetLocalPlayerIndex(); + return world->GetLocalPlayerIndex().value(); case ClientCameraMode::FirstPersonFollow: case ClientCameraMode::ThirdPersonFollow: return followedPlayerId; } @@ -103,9 +103,7 @@ namespace spades { } Player &Client::GetCameraTargetPlayer() { - Player *p = world->GetPlayer(GetCameraTargetPlayerId()); - SPAssert(p); - return *p; + return world->GetPlayer(GetCameraTargetPlayerId()).value(); } float Client::GetLocalFireVibration() { @@ -123,17 +121,16 @@ namespace spades { return 1.f; } - ClientPlayer* clientPlayer = clientPlayers[player.GetId()]; - SPAssert(clientPlayer); + ClientPlayer &clientPlayer = *clientPlayers[player.GetId()]; float delta = .8f; - switch (player.GetWeapon()->GetWeaponType()) { + switch (player.GetWeapon().GetWeaponType()) { case SMG_WEAPON: delta = .8f; break; case RIFLE_WEAPON: delta = 1.4f; break; case SHOTGUN_WEAPON: delta = .4f; break; } - float aimDownState = clientPlayer->GetAimDownState(); + float aimDownState = clientPlayer.GetAimDownState(); return 1.f + (3.f - 2.f * powf(aimDownState, 1.5f)) * powf(aimDownState, 3.f) * delta; } @@ -180,7 +177,8 @@ namespace spades { def.fovY = (float)cg_fov * static_cast(M_PI) / 180.f; def.fovX = atanf(tanf(def.fovY * .5f) * renderer->ScreenWidth() / - renderer->ScreenHeight()) * 2.f; + renderer->ScreenHeight()) * + 2.f; def.zNear = 0.05f; @@ -206,7 +204,8 @@ namespace spades { localFireVibration *= 0.4f; } - roll += (SampleRandomFloat() - SampleRandomFloat()) * 0.03f * localFireVibration; + roll += (SampleRandomFloat() - SampleRandomFloat()) * 0.03f * + localFireVibration; scale += SampleRandomFloat() * 0.04f * localFireVibration; vibPitch += localFireVibration * (1.f - localFireVibration) * 0.01f; @@ -218,13 +217,13 @@ namespace spades { { float sp = SmoothStep(GetSprintState()); vibYaw += sinf(player.GetWalkAnimationProgress() * - static_cast(M_PI) * 2.f) * - 0.01f * sp; + static_cast(M_PI) * 2.f) * + 0.01f * sp; roll -= sinf(player.GetWalkAnimationProgress() * - static_cast(M_PI) * 2.f) * - 0.005f * (sp); + static_cast(M_PI) * 2.f) * + 0.005f * (sp); float p = cosf(player.GetWalkAnimationProgress() * - static_cast(M_PI) * 2.f); + static_cast(M_PI) * 2.f); p = p * p; p *= p; p *= p; @@ -232,14 +231,14 @@ namespace spades { if (shakeLevel >= 2) { vibYaw += coherentNoiseSamplers[0].Sample( - player.GetWalkAnimationProgress() * 2.5f) * - 0.005f * sp; + player.GetWalkAnimationProgress() * 2.5f) * + 0.005f * sp; vibPitch += coherentNoiseSamplers[1].Sample( - player.GetWalkAnimationProgress() * 2.5f) * - 0.01f * sp; + player.GetWalkAnimationProgress() * 2.5f) * + 0.01f * sp; roll += coherentNoiseSamplers[2].Sample( - player.GetWalkAnimationProgress() * 2.5f) * - 0.008f * sp; + player.GetWalkAnimationProgress() * 2.5f) * + 0.008f * sp; scale += sp * 0.1f; } @@ -248,7 +247,8 @@ namespace spades { def.fovY = (float)cg_fov * static_cast(M_PI) / 180.f; def.fovX = atanf(tanf(def.fovY * .5f) * renderer->ScreenWidth() / - renderer->ScreenHeight()) * 2.f; + renderer->ScreenHeight()) * + 2.f; // for 1st view, camera blur can be used def.denyCameraBlur = false; @@ -289,15 +289,15 @@ namespace spades { Vector3 center = player.GetEye(); if (!player.IsAlive() && lastMyCorpse && - &player == world->GetLocalPlayer()) { + &player == world->GetLocalPlayer()) { center = lastMyCorpse->GetCenter(); } if (map->IsSolidWrapped((int)floorf(center.x), (int)floorf(center.y), - (int)floorf(center.z))) { + (int)floorf(center.z))) { float z = center.z; while (z > center.z - 5.f) { if (!map->IsSolidWrapped((int)floorf(center.x), - (int)floorf(center.y), (int)floorf(z))) { + (int)floorf(center.y), (int)floorf(z))) { center.z = z; break; } else { @@ -308,8 +308,8 @@ namespace spades { float distance = 5.f; if (&player == world->GetLocalPlayer() && - world->GetLocalPlayer()->GetTeamId() < 2 && - !world->GetLocalPlayer()->IsAlive()) { + world->GetLocalPlayer()->GetTeamId() < 2 && + !world->GetLocalPlayer()->IsAlive()) { // deathcam. float elapsedTime = time - lastAliveTime; distance -= 3.f * expf(-elapsedTime * 1.f); @@ -346,7 +346,8 @@ namespace spades { def.fovY = (float)cg_fov * static_cast(M_PI) / 180.f; def.fovX = atanf(tanf(def.fovY * .5f) * renderer->ScreenWidth() / - renderer->ScreenHeight()) * 2.f; + renderer->ScreenHeight()) * + 2.f; // Update initial floating camera pos freeCameraState.position = def.viewOrigin; @@ -371,7 +372,8 @@ namespace spades { def.fovY = (float)cg_fov * static_cast(M_PI) / 180.f; def.fovX = atanf(tanf(def.fovY * .5f) * renderer->ScreenWidth() / - renderer->ScreenHeight()) * 2.f; + renderer->ScreenHeight()) * + 2.f; // for 1st view, camera blur can be used def.denyCameraBlur = false; @@ -388,7 +390,8 @@ namespace spades { if (grenVib > 1.f) grenVib = 1.f; roll += (SampleRandomFloat() - SampleRandomFloat()) * 0.2f * grenVib; - vibPitch += (SampleRandomFloat() - SampleRandomFloat()) * 0.1f * grenVib; + vibPitch += + (SampleRandomFloat() - SampleRandomFloat()) * 0.1f * grenVib; vibYaw += (SampleRandomFloat() - SampleRandomFloat()) * 0.1f * grenVib; scale -= (SampleRandomFloat() - SampleRandomFloat()) * 0.1f * grenVib; @@ -447,7 +450,7 @@ namespace spades { if ((int)cg_manualFocus) { // Depth of field is manually controlled def.depthOfFieldNearBlurStrength = def.depthOfFieldFarBlurStrength = - 0.5f * (float)cg_depthOfFieldAmount; + 0.5f * (float)cg_depthOfFieldAmount; def.depthOfFieldFocalLength = focalLength; } else { def.depthOfFieldNearBlurStrength = cg_depthOfFieldAmount; @@ -487,28 +490,28 @@ namespace spades { return def; } - void Client::AddGrenadeToScene(spades::client::Grenade *g) { + void Client::AddGrenadeToScene(Grenade &g) { SPADES_MARK_FUNCTION(); - IModel *model; + Handle model; model = renderer->RegisterModel("Models/Weapons/Grenade/Grenade.kv6"); - if (g->GetPosition().z > 63.f) { + if (g.GetPosition().z > 63.f) { // work-around for water refraction problem return; } // Move the grenade slightly so that it doesn't look like sinking in // the ground - Vector3 position = g->GetPosition(); + Vector3 position = g.GetPosition(); position.z -= 0.03f * 3.0f; ModelRenderParam param; - Matrix4 mat = g->GetOrientation().ToRotationMatrix() * Matrix4::Scale(0.03f); + Matrix4 mat = g.GetOrientation().ToRotationMatrix() * Matrix4::Scale(0.03f); mat = Matrix4::Translate(position) * mat; param.matrix = mat; - renderer->RenderModel(model, param); + renderer->RenderModel(*model, param); } void Client::AddDebugObjectToScene(const spades::OBB3 &obb, const Vector4 &color) { @@ -541,12 +544,12 @@ namespace spades { void Client::DrawCTFObjects() { SPADES_MARK_FUNCTION(); - CTFGameMode *mode = static_cast(world->GetMode()); + CTFGameMode &mode = dynamic_cast(world->GetMode().value()); int tId; - IModel *base = renderer->RegisterModel("Models/MapObjects/CheckPoint.kv6"); - IModel *intel = renderer->RegisterModel("Models/MapObjects/Intel.kv6"); + Handle base = renderer->RegisterModel("Models/MapObjects/CheckPoint.kv6"); + Handle intel = renderer->RegisterModel("Models/MapObjects/Intel.kv6"); for (tId = 0; tId < 2; tId++) { - CTFGameMode::Team &team = mode->GetTeam(tId); + CTFGameMode::Team &team = mode.GetTeam(tId); IntVector3 col = world->GetTeam(tId).color; Vector3 color = {col.x / 255.f, col.y / 255.f, col.z / 255.f}; @@ -556,30 +559,30 @@ namespace spades { // draw base param.matrix = Matrix4::Translate(team.basePos); param.matrix = param.matrix * Matrix4::Scale(.3f); - renderer->RenderModel(base, param); + renderer->RenderModel(*base, param); // draw flag - if (!mode->GetTeam(1 - tId).hasIntel) { + if (!mode.GetTeam(1 - tId).hasIntel) { param.matrix = Matrix4::Translate(team.flagPos); param.matrix = param.matrix * Matrix4::Scale(.1f); - renderer->RenderModel(intel, param); + renderer->RenderModel(*intel, param); } } } void Client::DrawTCObjects() { SPADES_MARK_FUNCTION(); - TCGameMode *mode = static_cast(world->GetMode()); + TCGameMode &mode = dynamic_cast(world->GetMode().value()); int tId; - IModel *base = renderer->RegisterModel("Models/MapObjects/CheckPoint.kv6"); - int cnt = mode->GetNumTerritories(); + Handle base = renderer->RegisterModel("Models/MapObjects/CheckPoint.kv6"); + int cnt = mode.GetNumTerritories(); for (tId = 0; tId < cnt; tId++) { - TCGameMode::Territory *t = mode->GetTerritory(tId); + TCGameMode::Territory &t = mode.GetTerritory(tId); IntVector3 col; - if (t->ownerTeamId == 2) { + if (t.ownerTeamId == 2) { col = IntVector3::Make(255, 255, 255); } else { - col = world->GetTeam(t->ownerTeamId).color; + col = world->GetTeam(t.ownerTeamId).color; } Vector3 color = {col.x / 255.f, col.y / 255.f, col.z / 255.f}; @@ -587,9 +590,9 @@ namespace spades { param.customColor = color; // draw base - param.matrix = Matrix4::Translate(t->pos); + param.matrix = Matrix4::Translate(t.pos); param.matrix = param.matrix * Matrix4::Scale(.3f); - renderer->RenderModel(base, param); + renderer->RenderModel(*base, param); } } @@ -599,16 +602,16 @@ namespace spades { renderer->StartScene(lastSceneDef); if (world) { - Player *p = world->GetLocalPlayer(); + stmp::optional p = world->GetLocalPlayer(); for (size_t i = 0; i < world->GetNumPlayerSlots(); i++) if (world->GetPlayer(static_cast(i))) { SPAssert(clientPlayers[i]); clientPlayers[i]->AddToScene(); } - std::vector nades = world->GetAllGrenades(); - for (size_t i = 0; i < nades.size(); i++) { - AddGrenadeToScene(nades[i]); + auto &nades = world->GetAllGrenades(); + for (auto &nade : nades) { + AddGrenadeToScene(*nade); } { @@ -639,7 +642,7 @@ namespace spades { std::vector blocks; if (p->IsBlockCursorDragging()) { blocks = world->CubeLine(p->GetBlockCursorDragPos(), - p->GetBlockCursorPos(), 256); + p->GetBlockCursorPos(), 256); } else { blocks.push_back(p->GetBlockCursorPos()); } @@ -652,8 +655,10 @@ namespace spades { if ((int)blocks.size() > p->GetNumBlocks()) color = MakeVector3(1.f, 0.f, 0.f); - IModel *curLine = renderer->RegisterModel("Models/MapObjects/BlockCursorLine.kv6"); - IModel *curSingle = renderer->RegisterModel("Models/MapObjects/BlockCursorSingle.kv6"); + Handle curLine = + renderer->RegisterModel("Models/MapObjects/BlockCursorLine.kv6"); + Handle curSingle = + renderer->RegisterModel("Models/MapObjects/BlockCursorSingle.kv6"); for (size_t i = 0; i < blocks.size(); i++) { IntVector3 &v = blocks[i]; bool solid = blocks.size() > 2 && map->IsSolid(v.x, v.y, v.z); @@ -661,11 +666,16 @@ namespace spades { param.ghost = true; param.opacity = active && !solid ? .7f : .3f; param.customColor = color; - param.matrix = Matrix4::Translate(MakeVector3(v.x + .5f, v.y + .5f, v.z + .5f)); - param.matrix = param.matrix * Matrix4::Scale(1.f / 24.f + (solid ? 0.0005f : 0.f)); // make cursor larger if needed to stop z-fighting - renderer->RenderModel(blocks.size() > 1 ? curLine : curSingle, param); + param.matrix = + Matrix4::Translate(MakeVector3(v.x + .5f, v.y + .5f, v.z + .5f)); + param.matrix = + param.matrix * + Matrix4::Scale( + 1.f / 24.f + + (solid ? 0.0005f + : 0.f)); // make cursor larger if needed to stop z-fighting + renderer->RenderModel(blocks.size() > 1 ? *curLine : *curSingle, param); } - } } } @@ -677,46 +687,37 @@ namespace spades { // draw player hottrack // FIXME: don't use debug line - { - hitTag_t tag = hit_None; - Player *hottracked = HotTrackedPlayer(&tag); - if (hottracked) { - IntVector3 col = world->GetTeam(hottracked->GetTeamId()).color; - Vector4 color = Vector4::Make(col.x / 255.f, col.y / 255.f, col.z / 255.f, 1.f); - Vector4 color2 = Vector4::Make(1, 1, 1, 1); - - Player::HitBoxes hb = hottracked->GetHitBoxes(); - AddDebugObjectToScene(hb.head, (tag & hit_Head) ? color2 : color); - AddDebugObjectToScene(hb.torso, (tag & hit_Torso) ? color2 : color); - AddDebugObjectToScene(hb.limbs[0], (tag & hit_Legs) ? color2 : color); - AddDebugObjectToScene(hb.limbs[1], (tag & hit_Legs) ? color2 : color); - AddDebugObjectToScene(hb.limbs[2], (tag & hit_Arms) ? color2 : color); - } + auto hottracked = HotTrackedPlayer(); + if (hottracked) { + Player &player = std::get<0>(*hottracked); + hitTag_t tag = std::get<1>(*hottracked); + + IntVector3 col = world->GetTeam(player.GetTeamId()).color; + Vector4 color = Vector4::Make(col.x / 255.f, col.y / 255.f, col.z / 255.f, 1.f); + Vector4 color2 = Vector4::Make(1, 1, 1, 1); + + Player::HitBoxes hb = player.GetHitBoxes(); + AddDebugObjectToScene(hb.head, (tag & hit_Head) ? color2 : color); + AddDebugObjectToScene(hb.torso, (tag & hit_Torso) ? color2 : color); + AddDebugObjectToScene(hb.limbs[0], (tag & hit_Legs) ? color2 : color); + AddDebugObjectToScene(hb.limbs[1], (tag & hit_Legs) ? color2 : color); + AddDebugObjectToScene(hb.limbs[2], (tag & hit_Arms) ? color2 : color); } renderer->EndScene(); } - Vector3 Client::Project(spades::Vector3 v) { - v -= lastSceneDef.viewOrigin; - - // transform to NDC - Vector3 v2; - v2.x = Vector3::Dot(v, lastSceneDef.viewAxis[0]); - v2.y = Vector3::Dot(v, lastSceneDef.viewAxis[1]); - v2.z = Vector3::Dot(v, lastSceneDef.viewAxis[2]); - - float tanX = tanf(lastSceneDef.fovX * .5f); - float tanY = tanf(lastSceneDef.fovY * .5f); - - v2.x /= tanX * v2.z; - v2.y /= tanY * v2.z; - - // transform to IRenderer 2D coord - v2.x = (v2.x + 1.f) / 2.f * renderer->ScreenWidth(); - v2.y = (-v2.y + 1.f) / 2.f * renderer->ScreenHeight(); + void Client::UpdateMatrices() { + lastViewProjectionScreenMatrix = + (Matrix4::Scale(renderer->ScreenWidth() * 0.5f, renderer->ScreenHeight() * -0.5f, + 1.0f) * + Matrix4::Translate(1.0f, -1.0f, 0.0f)) * + lastSceneDef.ToOpenGLProjectionMatrix() * lastSceneDef.ToViewMatrix(); + } - return v2; + Vector3 Client::Project(spades::Vector3 v) { + Vector4 screenHomV = lastViewProjectionScreenMatrix * v; + return screenHomV.GetXYZ() / screenHomV.w; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Client_Update.cpp b/Sources/Client/Client_Update.cpp index c174848e4..8c906158c 100644 --- a/Sources/Client/Client_Update.cpp +++ b/Sources/Client/Client_Update.cpp @@ -52,6 +52,7 @@ DEFINE_SPADES_SETTING(cg_ragdoll, "1"); SPADES_SETTING(cg_blood); DEFINE_SPADES_SETTING(cg_ejectBrass, "1"); DEFINE_SPADES_SETTING(cg_hitFeedbackSoundGain, "0.2"); +DEFINE_SPADES_SETTING(cg_tracersFirstPerson, "1"); SPADES_SETTING(cg_alerts); SPADES_SETTING(cg_centerMessage); @@ -68,10 +69,8 @@ namespace spades { float Client::GetSprintState() { if (!world) return 0.f; - if (!world->GetLocalPlayer()) - return 0.f; - ClientPlayer *p = clientPlayers[(int)world->GetLocalPlayerIndex()]; + stmp::optional p = GetLocalClientPlayer(); if (!p) return 0.f; return p->GetSprintState(); @@ -80,10 +79,8 @@ namespace spades { float Client::GetAimDownState() { if (!world) return 0.f; - if (!world->GetLocalPlayer()) - return 0.f; - ClientPlayer *p = clientPlayers[(int)world->GetLocalPlayerIndex()]; + stmp::optional p = GetLocalClientPlayer(); if (!p) return 0.f; return p->GetAimDownState(); @@ -99,10 +96,9 @@ namespace spades { return false; } - auto *clientPlayer = GetLocalClientPlayer(); - SPAssert(clientPlayer); + stmp::optional clientPlayer = GetLocalClientPlayer(); - if (clientPlayer->IsChangingTool()) { + if (clientPlayer.value().IsChangingTool()) { // Player is unable to use a tool while switching to another tool return false; } @@ -110,11 +106,11 @@ namespace spades { return true; } - ClientPlayer *Client::GetLocalClientPlayer() { - if (!world || !world->GetLocalPlayer()) { - return nullptr; + stmp::optional Client::GetLocalClientPlayer() { + if (!world || !world->GetLocalPlayerIndex()) { + return {}; } - return clientPlayers.at(static_cast(world->GetLocalPlayerIndex())); + return clientPlayers.at(static_cast(*world->GetLocalPlayerIndex())); } #pragma mark - World Actions @@ -122,7 +118,7 @@ namespace spades { void Client::CaptureColor() { if (!world) return; - Player *p = world->GetLocalPlayer(); + stmp::optional p = world->GetLocalPlayer(); if (!p) return; if (!p->IsAlive()) @@ -159,7 +155,8 @@ namespace spades { if (!quiet) { Handle c = audioDevice->RegisterSound("Sounds/Weapons/SwitchLocal.opus"); - audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, -.3f, .5f), + AudioParam()); } } @@ -168,10 +165,9 @@ namespace spades { void Client::UpdateWorld(float dt) { SPADES_MARK_FUNCTION(); - Player *player = world->GetLocalPlayer(); + stmp::optional player = world->GetLocalPlayer(); if (player) { - // disable input when UI is open if (scriptedUI->NeedsInput()) { weapInput.primary = false; @@ -206,28 +202,28 @@ namespace spades { #endif // update player view (doesn't affect physics/game logics) - for (size_t i = 0; i < clientPlayers.size(); i++) { - if (clientPlayers[i]) { - clientPlayers[i]->Update(dt); + for (auto &clientPlayer : clientPlayers) { + if (clientPlayer) { + clientPlayer->Update(dt); } } // corpse never accesses audio nor renderer, so // we can do it in the separate thread class CorpseUpdateDispatch : public ConcurrentDispatch { - Client *client; + Client &client; float dt; public: - CorpseUpdateDispatch(Client *c, float dt) : client(c), dt(dt) {} + CorpseUpdateDispatch(Client &c, float dt) : client{c}, dt{dt} {} void Run() override { - for (auto &c : client->corpses) { + for (auto &c : client.corpses) { for (int i = 0; i < 4; i++) c->Update(dt / 4.f); } } }; - CorpseUpdateDispatch corpseDispatch(this, dt); + CorpseUpdateDispatch corpseDispatch{*this, dt}; corpseDispatch.Start(); // local entities should be done in the client thread @@ -264,7 +260,7 @@ namespace spades { } if (time > lastPosSentTime + 1.f && world->GetLocalPlayer()) { - Player *p = world->GetLocalPlayer(); + stmp::optional p = world->GetLocalPlayer(); if (p->IsAlive() && p->GetTeamId() < 2) { net->SendPosition(); lastPosSentTime = time; @@ -314,13 +310,15 @@ namespace spades { for (int sz = -1; sz <= 1; sz++) { GameMap::RayCastResult result; Vector3 shift = {sx * .1f, sy * .1f, sz * .1f}; - result = map->CastRay2(lastPos + shift, freeState.position - lastPos, 256); + result = + map->CastRay2(lastPos + shift, freeState.position - lastPos, 256); if (result.hit && !result.startSolid && Vector3::Dot(result.hitPos - freeState.position - shift, freeState.position - lastPos) < 0.f) { - float dist = Vector3::Dot(result.hitPos - freeState.position - shift, - (freeState.position - lastPos).Normalize()); + float dist = + Vector3::Dot(result.hitPos - freeState.position - shift, + (freeState.position - lastPos).Normalize()); if (dist < minDist) { minResult = result; minDist = dist; @@ -386,13 +384,12 @@ namespace spades { void Client::UpdateLocalPlayer(float dt) { SPADES_MARK_FUNCTION(); - auto *player = world->GetLocalPlayer(); - auto clientPlayer = clientPlayers[world->GetLocalPlayerIndex()]; + Player &player = GetWorld()->GetLocalPlayer().value(); PlayerInput inp = playerInput; WeaponInput winp = weapInput; - Vector3 velocity = player->GetVelocity(); + Vector3 velocity = player.GetVelocity(); Vector3 horizontalVelocity{velocity.x, velocity.y, 0.0f}; if (horizontalVelocity.GetLength() < 0.1f) { @@ -405,36 +402,30 @@ namespace spades { winp.secondary = false; } - // don't allow to stand up when ceilings are too low - if (inp.crouch == false) { - if (player->GetInput().crouch) { - if (!player->TryUncrouch(false)) { - inp.crouch = true; - } - } - } - // don't allow jumping in the air if (inp.jump) { - if (!player->IsOnGroundOrWade()) + if (!player.IsOnGroundOrWade()) inp.jump = false; } - if (player->GetTool() == Player::ToolWeapon) { + if (player.GetTool() == Player::ToolWeapon) { // disable weapon while reloading (except shotgun) - if (player->IsAwaitingReloadCompletion() && !player->GetWeapon()->IsReloadSlow()) { + if (player.IsAwaitingReloadCompletion() && !player.GetWeapon().IsReloadSlow()) { winp.primary = false; winp.secondary = false; } // stop firing if the player is out of ammo - if (player->GetWeapon()->GetAmmo() == 0) { + if (player.GetWeapon().GetAmmo() == 0) { winp.primary = false; } } - player->SetInput(inp); - player->SetWeaponInput(winp); + player.SetInput(inp); + player.SetWeaponInput(winp); + + // Uncrouching may be prevented by an obstacle + inp.crouch = player.GetInput().crouch; // send player input { @@ -452,12 +443,12 @@ namespace spades { hasDelayedReload = false; } - // PlayerInput actualInput = player->GetInput(); - WeaponInput actualWeapInput = player->GetWeaponInput(); + // PlayerInput actualInput = player.GetInput(); + WeaponInput actualWeapInput = player.GetWeaponInput(); - if (!(actualWeapInput.secondary && player->IsToolWeapon() && player->IsAlive()) && - !(cg_holdAimDownSight && weapInput.secondary)) { - if (player->IsToolWeapon()) { + if (!(actualWeapInput.secondary && player.IsToolWeapon() && player.IsAlive()) && + !(cg_holdAimDownSight && weapInput.secondary)) { + if (player.IsToolWeapon()) { // there is a possibility that player has respawned or something. // stop aiming down weapInput.secondary = false; @@ -465,16 +456,16 @@ namespace spades { } // is the selected tool no longer usable (ex. out of ammo)? - if (!player->IsToolSelectable(player->GetTool())) { + if (!player.IsToolSelectable(player.GetTool())) { // release mouse button before auto-switching tools winp.primary = false; winp.secondary = false; weapInput = winp; net->SendWeaponInput(weapInput); - actualWeapInput = winp = player->GetWeaponInput(); + actualWeapInput = winp = player.GetWeaponInput(); // select another tool - Player::ToolType t = player->GetTool(); + Player::ToolType t = player.GetTool(); do { switch (t) { case Player::ToolSpade: t = Player::ToolGrenade; break; @@ -487,23 +478,23 @@ namespace spades { } // send orientation - Vector3 curFront = player->GetFront(); + Vector3 curFront = player.GetFront(); if (curFront.x != lastFront.x || curFront.y != lastFront.y || curFront.z != lastFront.z) { lastFront = curFront; net->SendOrientation(curFront); } - lastKills = world->GetPlayerPersistent(player->GetId()).kills; + lastKills = world->GetPlayerPersistent(player.GetId()).kills; // show block count when building block lines. - if (player->IsAlive() && player->GetTool() == Player::ToolBlock && - player->GetWeaponInput().secondary && player->IsBlockCursorDragging()) { - if (player->IsBlockCursorActive()) { - auto blocks = world->CubeLine(player->GetBlockCursorDragPos(), - player->GetBlockCursorPos(), 256); + if (player.IsAlive() && player.GetTool() == Player::ToolBlock && + player.GetWeaponInput().secondary && player.IsBlockCursorDragging()) { + if (player.IsBlockCursorActive()) { + auto blocks = world->CubeLine(player.GetBlockCursorDragPos(), + player.GetBlockCursorPos(), 256); auto msg = _TrN("Client", "{0} block", "{0} blocks", blocks.size()); - AlertType type = static_cast(blocks.size()) > player->GetNumBlocks() + AlertType type = static_cast(blocks.size()) > player.GetNumBlocks() ? AlertType::Warning : AlertType::Notice; ShowAlert(msg, type, 0.f, true); @@ -515,7 +506,7 @@ namespace spades { } } - if (player->IsAlive()) + if (player.IsAlive()) lastAliveTime = time; else if (nextSpawnConfig) { if (player->GetTeamId() != (*nextSpawnConfig).team) { @@ -527,9 +518,9 @@ namespace spades { nextSpawnConfig.reset(); } - if (player->GetHealth() < lastHealth) { + if (player.GetHealth() < lastHealth) { // ouch! - lastHealth = player->GetHealth(); + lastHealth = player.GetHealth(); lastHurtTime = world->GetTime(); Handle c; @@ -547,10 +538,10 @@ namespace spades { c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal4.opus"); break; } - audioDevice->PlayLocal(c, AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), AudioParam()); - float hpper = player->GetHealth() / 100.f; - int cnt = 18 - (int)(player->GetHealth() / 100.f * 8.f); + float hpper = player.GetHealth() / 100.f; + int cnt = 18 - (int)(player.GetHealth() / 100.f * 8.f); hurtSprites.resize(std::max(cnt, 6)); for (size_t i = 0; i < hurtSprites.size(); i++) { HurtSprite &spr = hurtSprites[i]; @@ -564,7 +555,7 @@ namespace spades { } } else { - lastHealth = player->GetHealth(); + lastHealth = player.GetHealth(); } inp.jump = false; @@ -574,117 +565,123 @@ namespace spades { void Client::PlayerObjectSet(int id) { if (clientPlayers[id]) { - clientPlayers[id]->Invalidate(); clientPlayers[id] = nullptr; } - Player *p = world->GetPlayer(id); - if (p) - clientPlayers[id].Set(new ClientPlayer(p, this), false); + stmp::optional p = world->GetPlayer(id); + if (p) { + clientPlayers[id] = Handle::New(*p, *this); + } } - void Client::PlayerJumped(spades::client::Player *p) { + void Client::PlayerJumped(spades::client::Player &p) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { Handle c = - p->GetWade() ? audioDevice->RegisterSound("Sounds/Player/WaterJump.opus") - : audioDevice->RegisterSound("Sounds/Player/Jump.opus"); - audioDevice->Play(c, p->GetOrigin(), AudioParam()); + p.GetWade() ? audioDevice->RegisterSound("Sounds/Player/WaterJump.opus") + : audioDevice->RegisterSound("Sounds/Player/Jump.opus"); + audioDevice->Play(c.GetPointerOrNull(), p.GetOrigin(), AudioParam()); } } - void Client::PlayerLanded(spades::client::Player *p, bool hurt) { + void Client::PlayerLanded(spades::client::Player &p, bool hurt) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { Handle c; if (hurt) c = audioDevice->RegisterSound("Sounds/Player/FallHurt.opus"); - else if (p->GetWade()) + else if (p.GetWade()) c = audioDevice->RegisterSound("Sounds/Player/WaterLand.opus"); else c = audioDevice->RegisterSound("Sounds/Player/Land.opus"); - audioDevice->Play(c, p->GetOrigin(), AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), p.GetOrigin(), AudioParam()); } } - void Client::PlayerMadeFootstep(spades::client::Player *p) { + void Client::PlayerMadeFootstep(spades::client::Player &p) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { - std::array snds = {"Sounds/Player/Footstep1.opus", "Sounds/Player/Footstep2.opus", - "Sounds/Player/Footstep3.opus", "Sounds/Player/Footstep4.opus", - "Sounds/Player/Footstep5.opus", "Sounds/Player/Footstep6.opus", - "Sounds/Player/Footstep7.opus", "Sounds/Player/Footstep8.opus"}; + std::array snds = { + "Sounds/Player/Footstep1.opus", "Sounds/Player/Footstep2.opus", + "Sounds/Player/Footstep3.opus", "Sounds/Player/Footstep4.opus", + "Sounds/Player/Footstep5.opus", "Sounds/Player/Footstep6.opus", + "Sounds/Player/Footstep7.opus", "Sounds/Player/Footstep8.opus"}; std::array rsnds = { - "Sounds/Player/Run1.opus", "Sounds/Player/Run2.opus", "Sounds/Player/Run3.opus", - "Sounds/Player/Run4.opus", "Sounds/Player/Run5.opus", "Sounds/Player/Run6.opus", - "Sounds/Player/Run7.opus", "Sounds/Player/Run8.opus", "Sounds/Player/Run9.opus", - "Sounds/Player/Run10.opus", "Sounds/Player/Run11.opus", "Sounds/Player/Run12.opus", + "Sounds/Player/Run1.opus", "Sounds/Player/Run2.opus", + "Sounds/Player/Run3.opus", "Sounds/Player/Run4.opus", + "Sounds/Player/Run5.opus", "Sounds/Player/Run6.opus", + "Sounds/Player/Run7.opus", "Sounds/Player/Run8.opus", + "Sounds/Player/Run9.opus", "Sounds/Player/Run10.opus", + "Sounds/Player/Run11.opus", "Sounds/Player/Run12.opus", }; - std::array wsnds = {"Sounds/Player/Wade1.opus", "Sounds/Player/Wade2.opus", - "Sounds/Player/Wade3.opus", "Sounds/Player/Wade4.opus", - "Sounds/Player/Wade5.opus", "Sounds/Player/Wade6.opus", - "Sounds/Player/Wade7.opus", "Sounds/Player/Wade8.opus"}; - bool sprinting = clientPlayers[p->GetId()] - ? clientPlayers[p->GetId()]->GetSprintState() > 0.5f + std::array wsnds = { + "Sounds/Player/Wade1.opus", "Sounds/Player/Wade2.opus", + "Sounds/Player/Wade3.opus", "Sounds/Player/Wade4.opus", + "Sounds/Player/Wade5.opus", "Sounds/Player/Wade6.opus", + "Sounds/Player/Wade7.opus", "Sounds/Player/Wade8.opus"}; + bool sprinting = clientPlayers[p.GetId()] + ? clientPlayers[p.GetId()]->GetSprintState() > 0.5f : false; - Handle c = - p->GetWade() ? audioDevice->RegisterSound(SampleRandomElement(wsnds)) - : audioDevice->RegisterSound(SampleRandomElement(snds)); - audioDevice->Play(c, p->GetOrigin(), AudioParam()); - if (sprinting && !p->GetWade()) { + Handle c = p.GetWade() + ? audioDevice->RegisterSound(SampleRandomElement(wsnds)) + : audioDevice->RegisterSound(SampleRandomElement(snds)); + audioDevice->Play(c.GetPointerOrNull(), p.GetOrigin(), AudioParam()); + if (sprinting && !p.GetWade()) { AudioParam param; - param.volume *= clientPlayers[p->GetId()]->GetSprintState(); + param.volume *= clientPlayers[p.GetId()]->GetSprintState(); c = audioDevice->RegisterSound(SampleRandomElement(rsnds)); - audioDevice->Play(c, p->GetOrigin(), param); + audioDevice->Play(c.GetPointerOrNull(), p.GetOrigin(), param); } } } - void Client::PlayerFiredWeapon(spades::client::Player *p) { + void Client::PlayerFiredWeapon(spades::client::Player &p) { SPADES_MARK_FUNCTION(); - if (p == world->GetLocalPlayer()) { + if (&p == world->GetLocalPlayer()) { localFireVibrationTime = time; } - clientPlayers[p->GetId()]->FiredWeapon(); + clientPlayers.at(p.GetId())->FiredWeapon(); } - void Client::PlayerDryFiredWeapon(spades::client::Player *p) { + void Client::PlayerDryFiredWeapon(spades::client::Player &p) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { - bool isLocal = p == world->GetLocalPlayer(); + bool isLocal = &p == world->GetLocalPlayer(); Handle c = audioDevice->RegisterSound("Sounds/Weapons/DryFire.opus"); if (isLocal) - audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, -.3f, .5f), + AudioParam()); else - audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .3f + - p->GetRight() * .4f, + audioDevice->Play(c.GetPointerOrNull(), + p.GetEye() + p.GetFront() * 0.5f - p.GetUp() * .3f + + p.GetRight() * .4f, AudioParam()); } } - void Client::PlayerReloadingWeapon(spades::client::Player *p) { + void Client::PlayerReloadingWeapon(spades::client::Player &p) { SPADES_MARK_FUNCTION(); - clientPlayers[p->GetId()]->ReloadingWeapon(); + clientPlayers.at(p.GetId())->ReloadingWeapon(); } - void Client::PlayerReloadedWeapon(spades::client::Player *p) { + void Client::PlayerReloadedWeapon(spades::client::Player &p) { SPADES_MARK_FUNCTION(); - clientPlayers[p->GetId()]->ReloadedWeapon(); + clientPlayers.at(p.GetId())->ReloadedWeapon(); } - void Client::PlayerChangedTool(spades::client::Player *p) { + void Client::PlayerChangedTool(spades::client::Player &p) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { - bool isLocal = p == world->GetLocalPlayer(); + bool isLocal = &p == world->GetLocalPlayer(); Handle c; if (isLocal) { // played by ClientPlayer::Update @@ -693,65 +690,75 @@ namespace spades { c = audioDevice->RegisterSound("Sounds/Weapons/Switch.opus"); } if (isLocal) - audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, -.3f, .5f), + AudioParam()); else - audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .3f + - p->GetRight() * .4f, + audioDevice->Play(c.GetPointerOrNull(), + p.GetEye() + p.GetFront() * 0.5f - p.GetUp() * .3f + + p.GetRight() * .4f, AudioParam()); } } - void Client::PlayerRestocked(spades::client::Player *p) { + void Client::PlayerRestocked(spades::client::Player &p) { if (!IsMuted()) { - bool isLocal = p == world->GetLocalPlayer(); + bool isLocal = &p == world->GetLocalPlayer(); Handle c = isLocal ? audioDevice->RegisterSound("Sounds/Weapons/RestockLocal.opus") : audioDevice->RegisterSound("Sounds/Weapons/Restock.opus"); if (isLocal) - audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, -.3f, .5f), + AudioParam()); else - audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .3f + - p->GetRight() * .4f, + audioDevice->Play(c.GetPointerOrNull(), + p.GetEye() + p.GetFront() * 0.5f - p.GetUp() * .3f + + p.GetRight() * .4f, AudioParam()); } } - void Client::PlayerThrownGrenade(spades::client::Player *p, Grenade *g) { + void Client::PlayerThrewGrenade(spades::client::Player &p, + stmp::optional g) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { - bool isLocal = p == world->GetLocalPlayer(); + bool isLocal = &p == world->GetLocalPlayer(); Handle c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Throw.opus"); if (g && isLocal) { - net->SendGrenade(g); + net->SendGrenade(*g); } if (isLocal) - audioDevice->PlayLocal(c, MakeVector3(.4f, 0.1f, .3f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, 0.1f, .3f), + AudioParam()); else - audioDevice->Play(c, p->GetEye() + p->GetFront() * 0.5f - p->GetUp() * .2f + - p->GetRight() * .3f, + audioDevice->Play(c.GetPointerOrNull(), + p.GetEye() + p.GetFront() * 0.5f - p.GetUp() * .2f + + p.GetRight() * .3f, AudioParam()); } } - void Client::PlayerMissedSpade(spades::client::Player *p) { + void Client::PlayerMissedSpade(spades::client::Player &p) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { - bool isLocal = p == world->GetLocalPlayer(); - Handle c = audioDevice->RegisterSound("Sounds/Weapons/Spade/Miss.opus"); + bool isLocal = &p == world->GetLocalPlayer(); + Handle c = + audioDevice->RegisterSound("Sounds/Weapons/Spade/Miss.opus"); if (isLocal) - audioDevice->PlayLocal(c, MakeVector3(.2f, -.1f, 0.7f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.2f, -.1f, 0.7f), + AudioParam()); else - audioDevice->Play(c, p->GetOrigin() + p->GetFront() * 0.8f - p->GetUp() * .2f, + audioDevice->Play(c.GetPointerOrNull(), + p.GetOrigin() + p.GetFront() * 0.8f - p.GetUp() * .2f, AudioParam()); } } - void Client::PlayerHitBlockWithSpade(spades::client::Player *p, Vector3 hitPos, + void Client::PlayerHitBlockWithSpade(spades::client::Player &p, Vector3 hitPos, IntVector3 blockPos, IntVector3 normal) { SPADES_MARK_FUNCTION(); @@ -764,53 +771,58 @@ namespace spades { EmitBlockFragments(shiftedHitPos, colV); - if (p == world->GetLocalPlayer()) { + if (&p == world->GetLocalPlayer()) { localFireVibrationTime = time; } if (!IsMuted()) { - bool isLocal = p == world->GetLocalPlayer(); + bool isLocal = &p == world->GetLocalPlayer(); Handle c = audioDevice->RegisterSound("Sounds/Weapons/Spade/HitBlock.opus"); if (isLocal) - audioDevice->PlayLocal(c, MakeVector3(.1f, -.1f, 1.2f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.1f, -.1f, 1.2f), + AudioParam()); else - audioDevice->Play(c, p->GetOrigin() + p->GetFront() * 0.5f - p->GetUp() * .2f, + audioDevice->Play(c.GetPointerOrNull(), + p.GetOrigin() + p.GetFront() * 0.5f - p.GetUp() * .2f, AudioParam()); } } - void Client::PlayerKilledPlayer(spades::client::Player *killer, - spades::client::Player *victim, KillType kt) { + void Client::PlayerKilledPlayer(spades::client::Player &killer, + spades::client::Player &victim, KillType kt) { // play hit sound if (kt == KillTypeWeapon || kt == KillTypeHeadshot) { // don't play on local: see BullethitPlayer - if (victim != world->GetLocalPlayer()) { + if (&victim != world->GetLocalPlayer()) { if (!IsMuted()) { Handle c; switch (SampleRandomInt(0, 2)) { case 0: - c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh1.opus"); + c = + audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh1.opus"); break; case 1: - c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh2.opus"); + c = + audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh2.opus"); break; case 2: - c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh3.opus"); + c = + audioDevice->RegisterSound("Sounds/Weapons/Impacts/Flesh3.opus"); break; } AudioParam param; param.volume = 4.f; - audioDevice->Play(c, victim->GetEye(), param); + audioDevice->Play(c.GetPointerOrNull(), victim.GetEye(), param); } } } // The local player is dead; initialize the look-you-are-dead cam - if (victim == world->GetLocalPlayer()) { + if (&victim == world->GetLocalPlayer()) { followCameraState.enabled = false; - Vector3 v = -victim->GetFront(); + Vector3 v = -victim.GetFront(); followAndFreeCameraState.yaw = atan2(v.y, v.x); followAndFreeCameraState.pitch = 30.f * M_PI / 180.f; } @@ -822,25 +834,26 @@ namespace spades { case KillTypeGrenade: case KillTypeHeadshot: case KillTypeMelee: - case KillTypeWeapon: Bleed(victim->GetEye()); break; + case KillTypeWeapon: Bleed(victim.GetEye()); break; default: break; } // create ragdoll corpse - if (cg_ragdoll && victim->GetTeamId() < 2) { - Corpse *corp; - corp = new Corpse(renderer, map, victim); - if (victim == world->GetLocalPlayer()) - lastMyCorpse = corp; - if (killer != victim && kt != KillTypeGrenade) { - Vector3 dir = victim->GetPosition() - killer->GetPosition(); + if (cg_ragdoll && victim.GetTeamId() < 2) { + auto corp = stmp::make_unique(*renderer, *map, victim); + + if (&victim == world->GetLocalPlayer()) + lastMyCorpse = corp.get(); + + if (&killer != &victim && kt != KillTypeGrenade) { + Vector3 dir = victim.GetPosition() - killer.GetPosition(); dir = dir.Normalize(); if (kt == KillTypeMelee) { dir *= 6.f; } else { - if (killer->GetWeapon()->GetWeaponType() == SMG_WEAPON) { + if (killer.GetWeapon().GetWeaponType() == SMG_WEAPON) { dir *= 2.8f; - } else if (killer->GetWeapon()->GetWeaponType() == SHOTGUN_WEAPON) { + } else if (killer.GetWeapon().GetWeaponType() == SHOTGUN_WEAPON) { dir *= 4.5f; } else { dir *= 3.5f; @@ -850,8 +863,8 @@ namespace spades { } else if (kt == KillTypeGrenade) { corp->AddImpulse(MakeVector3(0, 0, -4.f - SampleRandomFloat() * 4.f)); } - corp->AddImpulse(victim->GetVelocity() * 32.f); - corpses.emplace_back(corp); + corp->AddImpulse(victim.GetVelocity() * 32.f); + corpses.emplace_back(std::move(corp)); if (corpses.size() > corpseHardLimit) { corpses.pop_front(); @@ -862,21 +875,21 @@ namespace spades { // add chat message std::string s; - s = ChatWindow::TeamColorMessage(killer->GetName(), killer->GetTeamId()); + s = ChatWindow::TeamColorMessage(killer.GetName(), killer.GetTeamId()); std::string cause; - bool isFriendlyFire = killer->GetTeamId() == victim->GetTeamId(); - if (killer == victim) + bool isFriendlyFire = killer.GetTeamId() == victim.GetTeamId(); + if (&killer == &victim) isFriendlyFire = false; - Weapon *w = - killer ? killer->GetWeapon() : nullptr; // only used in case of KillTypeWeapon + Weapon &w = killer.GetWeapon(); // only used in case of KillTypeWeapon switch (kt) { case KillTypeWeapon: - switch (w ? w->GetWeaponType() : RIFLE_WEAPON) { + switch (w.GetWeaponType()) { case RIFLE_WEAPON: cause += _Tr("Client", "Rifle"); break; case SMG_WEAPON: cause += _Tr("Client", "SMG"); break; case SHOTGUN_WEAPON: cause += _Tr("Client", "Shotgun"); break; + default: SPUnreachable(); } break; case KillTypeFall: @@ -887,9 +900,7 @@ namespace spades { //! A cause of death shown in the kill feed. cause += _Tr("Client", "Melee"); break; - case KillTypeGrenade: - cause += _Tr("Client", "Grenade"); - break; + case KillTypeGrenade: cause += _Tr("Client", "Grenade"); break; case KillTypeHeadshot: //! A cause of death shown in the kill feed. cause += _Tr("Client", "Headshot"); @@ -902,75 +913,88 @@ namespace spades { //! A cause of death shown in the kill feed. cause += _Tr("Client", "Weapon Change"); break; - default: - cause += "???"; - break; + default: cause += "???"; break; } s += " ["; if (isFriendlyFire) s += ChatWindow::ColoredMessage(cause, MsgColorFriendlyFire); - else if (killer == world->GetLocalPlayer() || victim == world->GetLocalPlayer()) + else if (&killer == world->GetLocalPlayer() || &victim == world->GetLocalPlayer()) s += ChatWindow::ColoredMessage(cause, MsgColorGray); else s += cause; s += "] "; - if (killer != victim) { - s += ChatWindow::TeamColorMessage(victim->GetName(), victim->GetTeamId()); + if (&killer != &victim) { + s += ChatWindow::TeamColorMessage(victim.GetName(), victim.GetTeamId()); } killfeedWindow->AddMessage(s); // log to netlog - if (killer != victim) { - NetLog("%s (%s) [%s] %s (%s)", killer->GetName().c_str(), - world->GetTeam(killer->GetTeamId()).name.c_str(), cause.c_str(), - victim->GetName().c_str(), world->GetTeam(victim->GetTeamId()).name.c_str()); + if (&killer != &victim) { + NetLog("%s (%s) [%s] %s (%s)", killer.GetName().c_str(), + world->GetTeam(killer.GetTeamId()).name.c_str(), cause.c_str(), + victim.GetName().c_str(), world->GetTeam(victim.GetTeamId()).name.c_str()); } else { - NetLog("%s (%s) [%s]", killer->GetName().c_str(), - world->GetTeam(killer->GetTeamId()).name.c_str(), cause.c_str()); + NetLog("%s (%s) [%s]", killer.GetName().c_str(), + world->GetTeam(killer.GetTeamId()).name.c_str(), cause.c_str()); } // show big message if player is involved - if (victim != killer) { - Player *local = world->GetLocalPlayer(); - if (killer == local || victim == local) { + if (&victim != &killer) { + stmp::optional local = world->GetLocalPlayer(); + if (&killer == local || &victim == local) { std::string msg; - if (killer == local) { + if (&killer == local) { if ((int)cg_centerMessage == 2) - msg = _Tr("Client", "You have killed {0}", victim->GetName()); + msg = _Tr("Client", "You have killed {0}", victim.GetName()); } else { - msg = _Tr("Client", "You were killed by {0}", killer->GetName()); + msg = _Tr("Client", "You were killed by {0}", killer.GetName()); } centerMessageView->AddMessage(msg); } } } - void Client::BulletHitPlayer(spades::client::Player *hurtPlayer, HitType type, - spades::Vector3 hitPos, spades::client::Player *by) { + void Client::BulletHitPlayer(spades::client::Player &hurtPlayer, HitType type, + spades::Vector3 hitPos, spades::client::Player &by, + std::unique_ptr &stateCell) { SPADES_MARK_FUNCTION(); SPAssert(type != HitTypeBlock); // don't bleed local player - if (!IsFirstPerson(GetCameraMode()) || &GetCameraTargetPlayer() != hurtPlayer) { + if (!IsFirstPerson(GetCameraMode()) || &GetCameraTargetPlayer() != &hurtPlayer) { Bleed(hitPos); } - if (hurtPlayer == world->GetLocalPlayer()) { + if (&hurtPlayer == world->GetLocalPlayer()) { // don't player hit sound now; // local bullet impact sound is // played by checking the decrease of HP return; } - if (!IsMuted()) { + // This function gets called for each pellet. We want to play these sounds no more than + // once for each instance of firing. `BulletHitScanState`, stored in `stateCell`, tells + // whether we have played each sound for the current firing session. + struct BulletHitScanState : IBulletHitScanState { + bool hasPlayedNormalHitSound = false; + bool hasPlayedHeadshotSound = false; + }; + + if (!stateCell) { + stateCell = stmp::make_unique(); + } + + auto &hitScanState = dynamic_cast(*stateCell); + + if (!IsMuted() && !hitScanState.hasPlayedNormalHitSound) { if (type == HitTypeMelee) { Handle c = audioDevice->RegisterSound("Sounds/Weapons/Spade/HitPlayer.opus"); - audioDevice->Play(c, hitPos, AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), hitPos, AudioParam()); } else { Handle c; switch (SampleRandomInt(0, 2)) { @@ -986,23 +1010,27 @@ namespace spades { } AudioParam param; param.volume = 4.f; - audioDevice->Play(c, hitPos, param); + audioDevice->Play(c.GetPointerOrNull(), hitPos, param); } + + hitScanState.hasPlayedNormalHitSound = true; } - if (by == world->GetLocalPlayer() && hurtPlayer) { - net->SendHit(hurtPlayer->GetId(), type); + if (&by == world->GetLocalPlayer()) { + net->SendHit(hurtPlayer.GetId(), type); - if (type == HitTypeHead) { + if (type == HitTypeHead && !hitScanState.hasPlayedHeadshotSound) { Handle c = audioDevice->RegisterSound("Sounds/Feedback/HeadshotFeedback.opus"); AudioParam param; param.volume = cg_hitFeedbackSoundGain; - audioDevice->PlayLocal(c, param); + audioDevice->PlayLocal(c.GetPointerOrNull(), param); + + hitScanState.hasPlayedHeadshotSound = true; } hitFeedbackIconState = 1.f; - if (hurtPlayer->GetTeamId() == world->GetLocalPlayer()->GetTeamId()) { + if (hurtPlayer.GetTeamId() == world->GetLocalPlayer()->GetTeamId()) { hitFeedbackFriendly = true; } else { hitFeedbackFriendly = false; @@ -1043,7 +1071,7 @@ namespace spades { c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Water4.opus"); break; } - audioDevice->Play(c, shiftedHitPos, param); + audioDevice->Play(c.GetPointerOrNull(), shiftedHitPos, param); } } else { EmitBlockFragments(shiftedHitPos, colV); @@ -1053,8 +1081,8 @@ namespace spades { param.volume = 2.f; Handle c; - c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Block.opus"); - audioDevice->Play(c, shiftedHitPos, param); + c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Block.opus"); + audioDevice->Play(c.GetPointerOrNull(), shiftedHitPos, param); param.pitch = .9f + SampleRandomFloat() * 0.2f; param.volume = 2.f; @@ -1072,28 +1100,46 @@ namespace spades { c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/Ricochet4.opus"); break; } - audioDevice->Play(c, shiftedHitPos, param); + audioDevice->Play(c.GetPointerOrNull(), shiftedHitPos, param); } } } - void Client::AddBulletTracer(spades::client::Player *player, spades::Vector3 muzzlePos, + void Client::AddBulletTracer(spades::client::Player &player, spades::Vector3 muzzlePos, spades::Vector3 hitPos) { SPADES_MARK_FUNCTION(); - // Do not display tracers for bullets fired by the local player - if (IsFirstPerson(GetCameraMode()) && GetCameraTargetPlayerId() == player->GetId()) { + bool isFirstPerson = + IsFirstPerson(GetCameraMode()) && GetCameraTargetPlayerId() == player.GetId(); + + // If disabled, do not display tracers for bullets fired by the local player + if (!cg_tracersFirstPerson && isFirstPerson) { return; } + // The line segment containing `muzzlePos` and `hitPos` represents the accurate + // trajectory of the fired bullet (as far as the game physics is concerned), but + // displaying it as-is would make it seem fired from a skull gun. Rewrite + // the starting point with the visual muzzle point of the current weapon skin. + Handle clientPlayer = clientPlayers[player.GetId()]; + muzzlePos = clientPlayer->ShouldRenderInThirdPersonView() + ? clientPlayer->GetMuzzlePosition() + : clientPlayer->GetMuzzlePositionInFirstPersonView(); + float vel; - switch (player->GetWeapon()->GetWeaponType()) { + switch (player.GetWeapon().GetWeaponType()) { case RIFLE_WEAPON: vel = 700.f; break; case SMG_WEAPON: vel = 360.f; break; case SHOTGUN_WEAPON: vel = 500.f; break; } - AddLocalEntity(new Tracer(this, muzzlePos, hitPos, vel)); - AddLocalEntity(new MapViewTracer(muzzlePos, hitPos, vel)); + + // Not to give the false illusion that the bullets travel slow + if (isFirstPerson) { + vel *= 2.0f; + } + + AddLocalEntity(stmp::make_unique(*this, muzzlePos, hitPos, vel)); + AddLocalEntity(stmp::make_unique(muzzlePos, hitPos, vel)); } void Client::BlocksFell(std::vector blocks) { @@ -1101,8 +1147,7 @@ namespace spades { if (blocks.empty()) return; - FallingBlock *b = new FallingBlock(this, blocks); - AddLocalEntity(b); + AddLocalEntity(stmp::make_unique(this, blocks)); if (!IsMuted()) { @@ -1114,36 +1159,36 @@ namespace spades { o += .5f; Handle c = audioDevice->RegisterSound("Sounds/Misc/BlockFall.opus"); - audioDevice->Play(c, o, AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), o, AudioParam()); } } - void Client::GrenadeBounced(spades::client::Grenade *g) { + void Client::GrenadeBounced(const Grenade &g) { SPADES_MARK_FUNCTION(); - if (g->GetPosition().z < 63.f) { + if (g.GetPosition().z < 63.f) { if (!IsMuted()) { Handle c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Bounce.opus"); - audioDevice->Play(c, g->GetPosition(), AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), AudioParam()); } } } - void Client::GrenadeDroppedIntoWater(spades::client::Grenade *g) { + void Client::GrenadeDroppedIntoWater(const Grenade &g) { SPADES_MARK_FUNCTION(); if (!IsMuted()) { Handle c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/DropWater.opus"); - audioDevice->Play(c, g->GetPosition(), AudioParam()); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), AudioParam()); } } - void Client::GrenadeExploded(spades::client::Grenade *g) { + void Client::GrenadeExploded(const Grenade &g) { SPADES_MARK_FUNCTION(); - bool inWater = g->GetPosition().z > 63.f; + bool inWater = g.GetPosition().z > 63.f; if (inWater) { if (!IsMuted()) { @@ -1151,22 +1196,23 @@ namespace spades { audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplode.opus"); AudioParam param; param.volume = 10.f; - audioDevice->Play(c, g->GetPosition(), param); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), param); c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplodeFar.opus"); param.volume = 6.f; param.referenceDistance = 10.f; - audioDevice->Play(c, g->GetPosition(), param); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), param); - c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplodeStereo.opus"); + c = + audioDevice->RegisterSound("Sounds/Weapons/Grenade/WaterExplodeStereo.opus"); param.volume = 2.f; - audioDevice->Play(c, g->GetPosition(), param); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), param); } - GrenadeExplosionUnderwater(g->GetPosition()); + GrenadeExplosionUnderwater(g.GetPosition()); } else { - GrenadeExplosion(g->GetPosition()); + GrenadeExplosion(g.GetPosition()); if (!IsMuted()) { Handle c, cs; @@ -1187,30 +1233,30 @@ namespace spades { AudioParam param; param.volume = 30.f; param.referenceDistance = 5.f; - audioDevice->Play(c, g->GetPosition(), param); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), param); param.referenceDistance = 1.f; - audioDevice->Play(cs, g->GetPosition(), param); + audioDevice->Play(cs.GetPointerOrNull(), g.GetPosition(), param); c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/ExplodeFar.opus"); param.volume = 6.f; param.referenceDistance = 40.f; - audioDevice->Play(c, g->GetPosition(), param); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), param); c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/ExplodeFarStereo.opus"); param.referenceDistance = 10.f; - audioDevice->Play(c, g->GetPosition(), param); + audioDevice->Play(c.GetPointerOrNull(), g.GetPosition(), param); // debri sound c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Debris.opus"); param.volume = 5.f; param.referenceDistance = 3.f; IntVector3 outPos; - Vector3 soundPos = g->GetPosition(); + Vector3 soundPos = g.GetPosition(); if (world->GetMap()->CastRay(soundPos, MakeVector3(0, 0, 1), 8.f, outPos)) { soundPos.z = (float)outPos.z - .2f; } - audioDevice->Play(c, soundPos, param); + audioDevice->Play(c.GetPointerOrNull(), soundPos, param); } } } @@ -1221,7 +1267,8 @@ namespace spades { if (!IsMuted()) { Handle c = audioDevice->RegisterSound("Sounds/Weapons/Grenade/Fire.opus"); - audioDevice->PlayLocal(c, MakeVector3(.4f, -.3f, .5f), AudioParam()); + audioDevice->PlayLocal(c.GetPointerOrNull(), MakeVector3(.4f, -.3f, .5f), + AudioParam()); } } @@ -1238,7 +1285,7 @@ namespace spades { SPADES_MARK_FUNCTION(); if (sourceGiven) { - Player *p = world->GetLocalPlayer(); + stmp::optional p = world->GetLocalPlayer(); if (!p) return; Vector3 rel = source - p->GetEye(); @@ -1265,5 +1312,5 @@ namespace spades { break; } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Corpse.cpp b/Sources/Client/Corpse.cpp index d410b04db..ef1c244da 100644 --- a/Sources/Client/Corpse.cpp +++ b/Sources/Client/Corpse.cpp @@ -19,13 +19,13 @@ */ #include "Corpse.h" -#include -#include #include "GameMap.h" #include "IModel.h" #include "IRenderer.h" #include "Player.h" #include "World.h" +#include +#include using namespace std; @@ -33,23 +33,23 @@ DEFINE_SPADES_SETTING(r_corpseLineCollision, "1"); namespace spades { namespace client { - Corpse::Corpse(IRenderer *renderer, GameMap *map, Player *p) - : renderer(renderer), map(map) { + Corpse::Corpse(IRenderer &renderer, GameMap &map, Player &p) + : renderer{renderer}, map{map} { SPADES_MARK_FUNCTION(); - playerId = p->GetId(); + playerId = p.GetId(); - IntVector3 col = p->GetWorld()->GetTeam(p->GetTeamId()).color; + IntVector3 col = p.GetWorld().GetTeam(p.GetTeamId()).color; color = MakeVector3(col.x / 255.f, col.y / 255.f, col.z / 255.f); - bool crouch = p->GetInput().crouch; - Vector3 front = p->GetFront(); + bool crouch = p.GetInput().crouch; + Vector3 front = p.GetFront(); float yaw = atan2(front.y, front.x) + static_cast(M_PI) * .5f; // float pitch = -atan2(front.z, sqrt(front.x * front.x + front.y * front.y)); // lower axis - Matrix4 lower = Matrix4::Translate(p->GetOrigin()); + Matrix4 lower = Matrix4::Translate(p.GetOrigin()); lower = lower * Matrix4::Rotate(MakeVector3(0, 0, 1), yaw); Matrix4 torso; @@ -84,8 +84,7 @@ namespace spades { SetNode(Arm2, torso * MakeVector3(-0.2f, -.4f, .2f)); } - SetNode(Head, - (nodes[Torso1].pos + nodes[Torso2].pos) * .5f + MakeVector3(0, 0, -0.6f)); + SetNode(Head, (nodes[Torso1].pos + nodes[Torso2].pos) * .5f + MakeVector3(0, 0, -0.6f)); } void Corpse::SetNode(NodeType n, spades::Vector3 v) { @@ -99,9 +98,7 @@ namespace spades { nodes[n].lastPos = v; nodes[n].lastForce = MakeVector3(0, 0, 0); } - void Corpse::SetNode(NodeType n, spades::Vector4 v) { - SetNode(n, v.GetXYZ()); - } + void Corpse::SetNode(NodeType n, spades::Vector4 v) { SetNode(n, v.GetXYZ()); } Corpse::~Corpse() {} @@ -293,16 +290,16 @@ namespace spades { static float fractf(float v) { return v - floorf(v); } - static void CheckEscape(GameMap *map, IntVector3 hitBlock, IntVector3 a, IntVector3 b, + static void CheckEscape(GameMap &map, IntVector3 hitBlock, IntVector3 a, IntVector3 b, IntVector3 dir, float &bestDist, IntVector3 &bestDir) { hitBlock += dir; IntVector3 aa = a + dir; IntVector3 bb = b + dir; - if (map->IsSolidWrapped(hitBlock.x, hitBlock.y, hitBlock.z)) + if (map.IsSolidWrapped(hitBlock.x, hitBlock.y, hitBlock.z)) return; - if (map->IsSolidWrapped(aa.x, aa.y, aa.z)) + if (map.IsSolidWrapped(aa.x, aa.y, aa.z)) return; - if (map->IsSolidWrapped(bb.x, bb.y, bb.z)) + if (map.IsSolidWrapped(bb.x, bb.y, bb.z)) return; float dist; if (dir.x == 1) { @@ -342,9 +339,9 @@ namespace spades { IntVector3 hitBlock; - if (map->CastRay(n1.lastPos, n2.lastPos, 16.f, hitBlock)) { - GameMap::RayCastResult res1 = map->CastRay2(n1.lastPos, n2.lastPos - n1.lastPos, 8); - GameMap::RayCastResult res2 = map->CastRay2(n2.lastPos, n1.lastPos - n2.lastPos, 8); + if (map.CastRay(n1.lastPos, n2.lastPos, 16.f, hitBlock)) { + GameMap::RayCastResult res1 = map.CastRay2(n1.lastPos, n2.lastPos - n1.lastPos, 8); + GameMap::RayCastResult res2 = map.CastRay2(n2.lastPos, n1.lastPos - n2.lastPos, 8); if (!res1.hit) return; @@ -532,9 +529,9 @@ namespace spades { // node.vel *= damp; - if (!map->ClipBox(oldPos.x, oldPos.y, oldPos.z)) { + if (!map.ClipBox(oldPos.x, oldPos.y, oldPos.z)) { - if (map->ClipBox(node.pos.x, oldPos.y, oldPos.z)) { + if (map.ClipBox(node.pos.x, oldPos.y, oldPos.z)) { node.vel.x = -node.vel.x * .2f; if (fabsf(node.vel.x) < .3f) node.vel.x = 0.f; @@ -544,7 +541,7 @@ namespace spades { node.vel.z *= .5f; } - if (map->ClipBox(node.pos.x, node.pos.y, oldPos.z)) { + if (map.ClipBox(node.pos.x, node.pos.y, oldPos.z)) { node.vel.y = -node.vel.y * .2f; if (fabsf(node.vel.y) < .3f) node.vel.y = 0.f; @@ -554,7 +551,7 @@ namespace spades { node.vel.z *= .5f; } - if (map->ClipBox(node.pos.x, node.pos.y, node.pos.z)) { + if (map.ClipBox(node.pos.x, node.pos.y, node.pos.z)) { node.vel.z = -node.vel.z * .2f; if (fabsf(node.vel.z) < .3f) node.vel.z = 0.f; @@ -564,7 +561,7 @@ namespace spades { node.vel.y *= .5f; } - if (map->ClipBox(node.pos.x, node.pos.y, node.pos.z)) { + if (map.ClipBox(node.pos.x, node.pos.y, node.pos.z)) { // TODO: getting out block // node.pos = oldPos; // node.vel *= .5f; @@ -572,10 +569,10 @@ namespace spades { } /* - if(map->ClipBox(node.pos.x, + if(map.ClipBox(node.pos.x, node.pos.y, node.pos.z)){ - if(!map->ClipBox(node.pos.x, + if(!map.ClipBox(node.pos.x, node.pos.y, oldPos.z)){ node.vel.z = -node.vel.z * .2f; @@ -583,7 +580,7 @@ namespace spades { node.vel.z = 0.f; node.pos.z = oldPos.z; } - if(!map->ClipBox(node.pos.x, + if(!map.ClipBox(node.pos.x, oldPos.y, node.pos.z)){ node.vel.y = -node.vel.y * .2f; @@ -591,7 +588,7 @@ namespace spades { node.vel.y = 0.f; node.pos.y = oldPos.y; } - if(!map->ClipBox(oldPos.x, + if(!map.ClipBox(oldPos.x, node.pos.y, node.pos.z)){ node.vel.x = -node.vel.x * .2f; @@ -621,7 +618,7 @@ namespace spades { ModelRenderParam param; param.customColor = color; - IModel *model; + Handle model; Matrix4 scaler = Matrix4::Scale(.1f); // draw torso @@ -641,14 +638,14 @@ namespace spades { param.matrix = torso * scaler; - model = renderer->RegisterModel("Models/Player/Torso.kv6"); - renderer->RenderModel(model, param); + model = renderer.RegisterModel("Models/Player/Torso.kv6"); + renderer.RenderModel(*model, param); } // draw Head { Vector3 headBase = (torso * MakeVector3(0.0f, 0.f, 0.f)).GetXYZ(); - model = renderer->RegisterModel("Models/Player/Head.kv6"); + model = renderer.RegisterModel("Models/Player/Head.kv6"); Vector3 aX, aY, aZ; Vector3 center = (nodes[Torso1].pos + nodes[Torso2].pos) * .5f; @@ -661,7 +658,7 @@ namespace spades { aX = Vector3::Cross(aY, aZ).Normalize(); param.matrix = Matrix4::FromAxis(-aX, aY, -aZ, headBase) * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); } // draw Arms @@ -669,7 +666,7 @@ namespace spades { Vector3 arm1Base = (torso * MakeVector3(0.4f, 0.f, 0.2f)).GetXYZ(); Vector3 arm2Base = (torso * MakeVector3(-0.4f, 0.f, 0.2f)).GetXYZ(); - model = renderer->RegisterModel("Models/Player/Arm.kv6"); + model = renderer.RegisterModel("Models/Player/Arm.kv6"); Vector3 aX, aY, aZ; @@ -680,7 +677,7 @@ namespace spades { aX = Vector3::Cross(aY, aZ).Normalize(); param.matrix = Matrix4::FromAxis(aX, aY, aZ, arm1Base) * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); aZ = nodes[Arm2].pos - nodes[Torso2].pos; aZ = aZ.Normalize(); @@ -689,7 +686,7 @@ namespace spades { aX = Vector3::Cross(aY, aZ).Normalize(); param.matrix = Matrix4::FromAxis(aX, aY, aZ, arm2Base) * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); } // draw Leg @@ -697,7 +694,7 @@ namespace spades { Vector3 leg1Base = (torso * MakeVector3(0.25f, 0.f, 0.9f)).GetXYZ(); Vector3 leg2Base = (torso * MakeVector3(-0.25f, 0.f, 0.9f)).GetXYZ(); - model = renderer->RegisterModel("Models/Player/Leg.kv6"); + model = renderer.RegisterModel("Models/Player/Leg.kv6"); Vector3 aX, aY, aZ; @@ -708,7 +705,7 @@ namespace spades { aX = Vector3::Cross(aY, aZ).Normalize(); param.matrix = Matrix4::FromAxis(aX, aY, aZ, leg1Base) * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); aZ = nodes[Leg2].pos - nodes[Torso4].pos; aZ = aZ.Normalize(); @@ -717,7 +714,7 @@ namespace spades { aX = Vector3::Cross(aY, aZ).Normalize(); param.matrix = Matrix4::FromAxis(aX, aY, aZ, leg2Base) * scaler; - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); } } @@ -736,7 +733,7 @@ namespace spades { for (int i = 0; i < NodeCount; i++) { IntVector3 outBlk; - if (map->CastRay(eye, nodes[i].pos, 256.f, outBlk)) + if (map.CastRay(eye, nodes[i].pos, 256.f, outBlk)) return true; } return false; @@ -746,5 +743,5 @@ namespace spades { for (int i = 0; i < NodeCount; i++) nodes[i].vel += v; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Corpse.h b/Sources/Client/Corpse.h index 06b9f3908..104c977d5 100644 --- a/Sources/Client/Corpse.h +++ b/Sources/Client/Corpse.h @@ -61,8 +61,8 @@ namespace spades { Edge() { node1 = node2 = NodeCount; } }; - IRenderer *renderer; - GameMap *map; + IRenderer &renderer; + GameMap ↦ Vector3 color; int playerId; @@ -85,7 +85,15 @@ namespace spades { void LineCollision(NodeType a, NodeType b, float dt); public: - Corpse(IRenderer *renderer, GameMap *map, Player *p); + /** + * Construct a "corpse" client object. + * + * @param renderer The renderer. Must outlive `Corpse`. + * @param map The game map, used for physics. Must outlive `Corpse`. + * @param p The player to create a corpse from. Can be destroyed + * after `Corpse` is constructed. + */ + Corpse(IRenderer &renderer, GameMap &map, Player &p); ~Corpse(); void Update(float dt); @@ -99,5 +107,5 @@ namespace spades { void AddImpulse(Vector3); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/FTFont.cpp b/Sources/Client/FTFont.cpp index 047c60bfa..ee2118e9d 100644 --- a/Sources/Client/FTFont.cpp +++ b/Sources/Client/FTFont.cpp @@ -51,7 +51,8 @@ namespace spades { } return *ft; } - }; + }; // namespace + struct FTFaceWrapper { FT_Face face; std::string buffer; @@ -59,6 +60,7 @@ namespace spades { ~FTFaceWrapper() { FT_Done_Face(face); } operator FT_Face() const { return face; } }; + struct FTBitmapWrapper { FT_Bitmap b; FTBitmapWrapper() { FT_Bitmap_New(&b); } @@ -72,23 +74,25 @@ namespace spades { FTFontSet::~FTFontSet() { SPADES_MARK_FUNCTION(); } void FTFontSet::AddFace(const std::string &fileName) { - FT_Face face; std::string data = FileManager::ReadAllBytes(fileName.c_str()); + auto ret = FT_New_Memory_Face( GetFreeType(), reinterpret_cast(data.data()), data.size(), 0, &face); + if (ret) { SPRaise("Failed to load font %s: FreeType error %d", fileName.c_str(), ret); } - auto *wr = new FTFaceWrapper(face); + auto wr = stmp::make_unique(face); wr->buffer = std::move(data); - faces.emplace_back(wr); + faces.emplace_back(std::move(wr)); } struct BinPlaceResult { - client::IImage ℑ + std::reference_wrapper image; int x, y; + BinPlaceResult(client::IImage &image, int x, int y) : image(image), x(x), y(y) {} }; @@ -99,9 +103,9 @@ namespace spades { std::list> skyline; Bin(int width, int height, client::IRenderer &r) : width(width), height(height) { - Handle tmpbmp(new Bitmap(width, height), false); + auto tmpbmp = Handle::New(width, height); memset(tmpbmp->GetPixels(), 0, tmpbmp->GetWidth() * tmpbmp->GetHeight() * 4); - image.Set(r.CreateImage(tmpbmp), false); + image = r.CreateImage(*tmpbmp); skyline.emplace_back(0, 0); skyline.emplace_back(width, 0); } @@ -113,6 +117,7 @@ namespace spades { "%dx%d on %dx%d bin.", bw, bh, width, height); } + auto it = skyline.begin(); auto it2 = it; ++it2; @@ -129,13 +134,13 @@ namespace spades { break; } - auto maxY = std::max_element(it, it2, [](const std::pair &a, - const std::pair &b) { - return a.second < b.second; - })->second; + auto maxYIter = std::max_element( + it, it2, [](const std::pair &a, const std::pair &b) { + return a.second < b.second; + }); + auto maxY = maxYIter->second; if (maxY + bh < height) { - int right = it->first + bw; int wasted = 0; for (auto it1 = it; it1 != it2;) { @@ -164,6 +169,7 @@ namespace spades { int right = bestIt1->first + bw; BinPlaceResult result(*image, bestIt1->first, bestMaxY); + if (bestIt2->first == right) { it = bestIt1; ++it; @@ -190,13 +196,13 @@ namespace spades { } }; - FTFont::FTFont(client::IRenderer *renderer, FTFontSet *fontSet, float height, - float lineHeight) + FTFont::FTFont(client::IRenderer *renderer, std::shared_ptr _fontSet, + float height, float lineHeight) : client::IFont(renderer), renderer(renderer), lineHeight(lineHeight), height(height), - fontSet(fontSet) { + fontSet(std::move(_fontSet)) { SPADES_MARK_FUNCTION(); SPAssert(renderer); @@ -217,12 +223,13 @@ namespace spades { FTFont::~FTFont() { SPADES_MARK_FUNCTION(); } - FTFont::Glyph *FTFont::GetGlyph(uint32_t code) { + stmp::optional FTFont::GetGlyph(uint32_t code) { auto it = glyphMap.find(code); if (it != glyphMap.end()) { auto ref = it->second; - return &ref.get(); + return ref.get(); } + for (const auto &face : fontSet->faces) { auto cId = FT_Get_Char_Index(*face, code); if (cId != 0) { @@ -241,13 +248,14 @@ namespace spades { auto it3 = glyphs.emplace(std::make_pair(*face, cId), std::move(g)); glyphMap.emplace(code, it3.first->second); - return &it3.first->second; + return it3.first->second; } else { - return &it2->second; + return it2->second; } } } - return nullptr; + + return {}; } template @@ -269,7 +277,7 @@ namespace spades { continue; } - auto *g = GetGlyph(code); + auto g = GetGlyph(code); if (g) { onGlyph(*g); } else { @@ -285,19 +293,20 @@ namespace spades { float x = 0.f; int lines = 1; - SplitTextIntoGlyphs(str, - [&](Glyph &g) { - x += g.advance.x; - maxWidth = std::max(x, maxWidth); - }, - [&](uint32_t codepoint) { - x += MeasureFallback(codepoint, height); - maxWidth = std::max(x, maxWidth); - }, - [&]() { - ++lines; - x = 0.f; - }); + SplitTextIntoGlyphs( + str, + [&](Glyph &g) { + x += g.advance.x; + maxWidth = std::max(x, maxWidth); + }, + [&](uint32_t codepoint) { + x += MeasureFallback(codepoint, height); + maxWidth = std::max(x, maxWidth); + }, + [&]() { + ++lines; + x = 0.f; + }); return Vector2(maxWidth, lines * lineHeight); } @@ -316,7 +325,7 @@ namespace spades { SPAssert(outbmp->pixel_mode == FT_PIXEL_MODE_GRAY); - Handle spbmp(new Bitmap(outbmp->width + 1, outbmp->rows + 1), false); + auto spbmp = Handle::New(outbmp->width + 1, outbmp->rows + 1); memset(spbmp->GetPixels(), 0, 4 * spbmp->GetWidth() * spbmp->GetHeight()); @@ -358,8 +367,8 @@ namespace spades { enum { KernelSize = 6 }; auto &orig = *g.bmp; - Handle newbmp( - new Bitmap(orig.GetWidth() + KernelSize, orig.GetHeight() + KernelSize), false); + auto newbmp = + Handle::New(orig.GetWidth() + KernelSize, orig.GetHeight() + KernelSize); int const origW = orig.GetWidth(); int const origH = orig.GetHeight(); @@ -453,7 +462,6 @@ namespace spades { SplitTextIntoGlyphs( str, [&](Glyph &g) { - RenderGlyph(g); auto &img = *g.image; @@ -499,7 +507,6 @@ namespace spades { SplitTextIntoGlyphs( str, [&](Glyph &g) { - RenderBlurGlyph(g); auto &img = *g.blurImage; @@ -534,5 +541,5 @@ namespace spades { DrawBlurred(text, offset, scale, shadowColor); Draw(text, offset, scale, color); } - } -} + } // namespace ngclient +} // namespace spades diff --git a/Sources/Client/FTFont.h b/Sources/Client/FTFont.h index 4a1463ee7..e2394172a 100644 --- a/Sources/Client/FTFont.h +++ b/Sources/Client/FTFont.h @@ -19,6 +19,7 @@ */ #include +#include #include #include @@ -35,29 +36,29 @@ namespace spades { namespace client { class IImage; } -} +} // namespace spades namespace spades { namespace ngclient { struct FTFaceWrapper; class FTFont; - class FTFontSet : public RefCountedObject { + class FTFontSet { friend class FTFont; std::list> faces; - protected: - ~FTFontSet(); - public: FTFontSet(); + FTFontSet(const FTFontSet &) = delete; + void operator=(const FTFontSet &) = delete; + ~FTFontSet(); + void AddFace(const std::string &fileName); }; /** * FreeType2 based font renderer. * - * Warning: only one thread can access multiple FTFonts sharing the same FTFontSet * at the same time. */ @@ -71,6 +72,7 @@ namespace spades { GlyphImage(client::IImage &img, const AABB2 &bounds, const Vector2 &offset) : img(img), bounds(bounds), offset(offset) {} }; + struct Glyph { FT_Face face; uint32_t charIndex; @@ -79,11 +81,13 @@ namespace spades { stmp::optional blurImage; Handle bmp; }; + struct GlyphHash { std::size_t operator()(const std::pair &p) const { return std::hash()(p.first) ^ std::hash()(p.second); } }; + std::unordered_map, Glyph, GlyphHash> glyphs; std::unordered_map> glyphMap; float lineHeight; @@ -93,13 +97,13 @@ namespace spades { bool rendererIsLowQuality; - Handle fontSet; + std::shared_ptr fontSet; struct Bin; std::list bins; int binSize; - Glyph *GetGlyph(uint32_t code); + stmp::optional GetGlyph(uint32_t code); template void SplitTextIntoGlyphs(const std::string &, T glyphHandler, T3 fallbackHandler, T2 lineBreakHandler); @@ -111,7 +115,7 @@ namespace spades { ~FTFont(); public: - FTFont(client::IRenderer *, FTFontSet *, float height, float lineHeight); + FTFont(client::IRenderer *, std::shared_ptr, float height, float lineHeight); Vector2 Measure(const std::string &) override; @@ -123,5 +127,5 @@ namespace spades { void DrawShadow(const std::string &, const Vector2 &offset, float scale, const Vector4 &color, const Vector4 &shadowColor) override; }; - } -} + } // namespace ngclient +} // namespace spades diff --git a/Sources/Client/FallingBlock.cpp b/Sources/Client/FallingBlock.cpp index 0b74de400..8b05c79ca 100644 --- a/Sources/Client/FallingBlock.cpp +++ b/Sources/Client/FallingBlock.cpp @@ -19,8 +19,6 @@ */ #include "FallingBlock.h" -#include -#include #include "Client.h" #include "GameMap.h" #include "IModel.h" @@ -28,6 +26,8 @@ #include "ParticleSpriteEntity.h" #include "SmokeSpriteEntity.h" #include "World.h" +#include +#include #include namespace spades { @@ -61,7 +61,8 @@ namespace spades { zSum += v.z; } - GameMap *map = client->GetWorld()->GetMap(); + const Handle &map = client->GetWorld()->GetMap(); + SPAssert(map); // build voxel model vmodel = new VoxelModel(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1); @@ -88,7 +89,7 @@ namespace spades { matrix = Matrix4::Translate(matTrans); // build renderer model - model = client->GetRenderer()->CreateModel(vmodel); + model = client->GetRenderer().CreateModel(*vmodel).Unmanage(); time = 0.f; } @@ -101,9 +102,11 @@ namespace spades { bool FallingBlock::Update(float dt) { time += dt; - GameMap *map = client->GetWorld()->GetMap(); + const Handle &map = client->GetWorld()->GetMap(); Vector3 orig = matrix.GetOrigin(); + SPAssert(map); + if (time > 1.f || map->ClipBox(orig.x, orig.y, orig.z)) { // destroy int w = vmodel->GetWidth(); @@ -119,7 +122,7 @@ namespace spades { Vector3 vmAxis2 = vmat.GetAxis(1); Vector3 vmAxis3 = vmat.GetAxis(2); - Handle img = client->GetRenderer()->RegisterImage("Gfx/White.tga"); + Handle img = client->GetRenderer().RegisterImage("Gfx/White.tga"); bool usePrecisePhysics = false; float dist = @@ -139,8 +142,8 @@ namespace spades { client->grenadeVibration += impact / (dist + 5.f); if (client->grenadeVibration > 1.f) client->grenadeVibration = 1.f; - - auto *getRandom = SampleRandomFloat; + + auto *getRandom = SampleRandomFloat; for (int x = 0; x < w; x++) { Vector3 p1 = vmOrigin + vmAxis1 * (float)x; @@ -166,35 +169,36 @@ namespace spades { Vector3 p3 = p2 + vmAxis3 * (float)z; { - ParticleSpriteEntity *ent = - new SmokeSpriteEntity(client, col, 70.f); - ent->SetTrajectory(p3, (MakeVector3(getRandom() - getRandom(), - getRandom() - getRandom(), - getRandom() - getRandom())) * - 0.2f, - 1.f, 0.f); + auto ent = stmp::make_unique(*client, col, 70.f); + ent->SetTrajectory( + p3, + (MakeVector3(getRandom() - getRandom(), getRandom() - getRandom(), + getRandom() - getRandom())) * + 0.2f, + 1.f, 0.f); ent->SetRotation(getRandom() * (float)M_PI * 2.f); ent->SetRadius(1.0f, 0.5f); - ent->SetBlockHitAction(ParticleSpriteEntity::Ignore); + ent->SetBlockHitAction(BlockHitAction::Ignore); ent->SetLifeTime(1.0f + getRandom() * 0.5f, 0.f, 1.0f); - client->AddLocalEntity(ent); + client->AddLocalEntity(std::move(ent)); } col.w = 1.f; for (int i = 0; i < 6; i++) { - ParticleSpriteEntity *ent = - new ParticleSpriteEntity(client, img, col); - ent->SetTrajectory(p3, MakeVector3(getRandom() - getRandom(), - getRandom() - getRandom(), - getRandom() - getRandom()) * - 13.f, + auto ent = stmp::make_unique( + *client, img.GetPointerOrNull(), col); + ent->SetTrajectory(p3, + MakeVector3(getRandom() - getRandom(), + getRandom() - getRandom(), + getRandom() - getRandom()) * + 13.f, 1.f, .6f); ent->SetRotation(getRandom() * (float)M_PI * 2.f); ent->SetRadius(0.35f + getRandom() * getRandom() * 0.1f); ent->SetLifeTime(2.f, 0.f, 1.f); if (usePrecisePhysics) - ent->SetBlockHitAction(ParticleSpriteEntity::BounceWeak); - client->AddLocalEntity(ent); + ent->SetBlockHitAction(BlockHitAction::BounceWeak); + client->AddLocalEntity(std::move(ent)); } } } @@ -218,7 +222,7 @@ namespace spades { void FallingBlock::Render3D() { ModelRenderParam param; param.matrix = matrix; - client->GetRenderer()->RenderModel(model, param); + client->GetRenderer().RenderModel(*model, param); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/FallingBlock.h b/Sources/Client/FallingBlock.h index 7508c61d9..756f52fff 100644 --- a/Sources/Client/FallingBlock.h +++ b/Sources/Client/FallingBlock.h @@ -47,5 +47,5 @@ namespace spades { bool Update(float dt) override; void Render3D() override; }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades \ No newline at end of file diff --git a/Sources/Client/Fonts.cpp b/Sources/Client/Fonts.cpp index cebc780a6..e7de3b747 100644 --- a/Sources/Client/Fonts.cpp +++ b/Sources/Client/Fonts.cpp @@ -31,13 +31,15 @@ namespace spades { namespace client { namespace { + std::regex const g_fontNameRe(".*\\.(?:otf|ttf|ttc)", std::regex::icase); + struct GlobalFontInfo { - Handle guiFontSet; + std::shared_ptr guiFontSet; GlobalFontInfo() { SPLog("Loading built-in fonts"); - guiFontSet.Set(new ngclient::FTFontSet(), false); + guiFontSet = std::make_shared(); if (FileManager::FileExists("Gfx/Fonts/AlteDIN1451.ttf")) { guiFontSet->AddFace("Gfx/Fonts/AlteDIN1451.ttf"); @@ -48,9 +50,8 @@ namespace spades { // Preliminary custom font support auto files = FileManager::EnumFiles("Fonts"); - static std::regex re(".*\\.(?:otf|ttf|ttc)", std::regex::icase); for (const auto &name : files) { - if (!std::regex_match(name, re)) { + if (!std::regex_match(name, g_fontNameRe)) { continue; } SPLog("Loading custom font '%s'", name.c_str()); @@ -65,31 +66,32 @@ namespace spades { return instance; } }; - } + } // namespace FontManager::FontManager(IRenderer *renderer) { { - auto *font = - new Quake3Font(renderer, renderer->RegisterImage("Gfx/Fonts/SquareFontBig.png"), - (const int *)SquareFontBigMap, 48, 8, true); + auto font = Handle::New( + renderer, + renderer->RegisterImage("Gfx/Fonts/SquareFontBig.png").GetPointerOrNull(), + (const int *)SquareFontBigMap, 48, 8.f, true); font->SetGlyphYRange(11.f, 37.f); SPLog("Font 'SquareFont (Large)' Loaded"); - squareDesignFont.Set(font, false); + squareDesignFont = std::move(font).Cast(); } - largeFont.Set( - new ngclient::FTFont(renderer, GlobalFontInfo::GetInstance().guiFontSet, 34.f, 48.f), - false); - mediumFont.Set( - new ngclient::FTFont(renderer, GlobalFontInfo::GetInstance().guiFontSet, 24.f, 32.f), - false); - headingFont.Set( - new ngclient::FTFont(renderer, GlobalFontInfo::GetInstance().guiFontSet, 20.f, 26.f), - false); - guiFont.Set( - new ngclient::FTFont(renderer, GlobalFontInfo::GetInstance().guiFontSet, 16.f, 20.f), - false); + largeFont = Handle::New( + renderer, GlobalFontInfo::GetInstance().guiFontSet, 34.f, 48.f) + .Cast(); + mediumFont = Handle::New( + renderer, GlobalFontInfo::GetInstance().guiFontSet, 24.f, 32.f) + .Cast(); + headingFont = Handle::New( + renderer, GlobalFontInfo::GetInstance().guiFontSet, 20.f, 26.f) + .Cast(); + guiFont = Handle::New( + renderer, GlobalFontInfo::GetInstance().guiFontSet, 16.f, 20.f) + .Cast(); } FontManager::~FontManager() {} - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Fonts.h b/Sources/Client/Fonts.h index 4f7999c7b..1ed6f93f8 100644 --- a/Sources/Client/Fonts.h +++ b/Sources/Client/Fonts.h @@ -29,11 +29,11 @@ namespace spades { public: FontManager(IRenderer *); - IFont *GetSquareDesignFont() { return squareDesignFont; } - IFont *GetLargeFont() { return largeFont; } - IFont *GetMediumFont() { return mediumFont; } - IFont *GetHeadingFont() { return headingFont; } - IFont *GetGuiFont() { return guiFont; } + IFont &GetSquareDesignFont() { return *squareDesignFont; } + IFont &GetLargeFont() { return *largeFont; } + IFont &GetMediumFont() { return *mediumFont; } + IFont &GetHeadingFont() { return *headingFont; } + IFont &GetGuiFont() { return *guiFont; } protected: ~FontManager() override; @@ -45,5 +45,5 @@ namespace spades { Handle headingFont; Handle guiFont; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/GameMap.cpp b/Sources/Client/GameMap.cpp index 636bddb83..e8ca3b8d7 100644 --- a/Sources/Client/GameMap.cpp +++ b/Sources/Client/GameMap.cpp @@ -62,7 +62,7 @@ namespace spades { } } - bool GameMap::IsSurface(int x, int y, int z) { + bool GameMap::IsSurface(int x, int y, int z) const { if (!IsSolid(x, y, z)) return false; if (z == 0) @@ -159,7 +159,7 @@ namespace spades { stream->Write(buffer.data(), buffer.size()); } - bool GameMap::ClipBox(int x, int y, int z) { + bool GameMap::ClipBox(int x, int y, int z) const { int sz; if (x < 0 || x >= 512 || y < 0 || y >= 512) @@ -174,7 +174,7 @@ namespace spades { return IsSolid((int)x, (int)y, sz); } - bool GameMap::ClipWorld(int x, int y, int z) { + bool GameMap::ClipWorld(int x, int y, int z) const { int sz; if (x < 0 || x >= 512 || y < 0 || y >= 512) @@ -191,14 +191,14 @@ namespace spades { return IsSolid((int)x, (int)y, sz); } - bool GameMap::ClipBox(float x, float y, float z) { + bool GameMap::ClipBox(float x, float y, float z) const { SPAssert(!std::isnan(x)); SPAssert(!std::isnan(y)); SPAssert(!std::isnan(z)); return ClipBox((int)floorf(x), (int)floorf(y), (int)floorf(z)); } - bool GameMap::ClipWorld(float x, float y, float z) { + bool GameMap::ClipWorld(float x, float y, float z) const { SPAssert(!std::isnan(x)); SPAssert(!std::isnan(y)); SPAssert(!std::isnan(z)); @@ -206,7 +206,7 @@ namespace spades { } bool GameMap::CastRay(spades::Vector3 v0, spades::Vector3 v1, float length, - spades::IntVector3 &vOut) { + spades::IntVector3 &vOut) const { SPADES_MARK_FUNCTION_DEBUG(); SPAssert(!std::isnan(v0.x)); @@ -359,7 +359,7 @@ namespace spades { } GameMap::RayCastResult GameMap::CastRay2(spades::Vector3 v0, spades::Vector3 dir, - int maxSteps) { + int maxSteps) const { SPADES_MARK_FUNCTION_DEBUG(); GameMap::RayCastResult result; @@ -523,7 +523,7 @@ namespace spades { size_t pos = 0; - Handle map{new GameMap(), false}; + auto map = Handle::New(); if (onProgress) { onProgress(0); @@ -592,7 +592,7 @@ namespace spades { } } - return map.Unmanage(); + return std::move(map).Unmanage(); } } // namespace client } // namespace spades diff --git a/Sources/Client/GameMap.h b/Sources/Client/GameMap.h index c94354f8e..3969c9417 100644 --- a/Sources/Client/GameMap.h +++ b/Sources/Client/GameMap.h @@ -60,10 +60,10 @@ namespace spades { void Save(IStream *); - int Width() { return DefaultWidth; } - int Height() { return DefaultHeight; } - int Depth() { return DefaultDepth; } - inline bool IsSolid(int x, int y, int z) { + int Width() const { return DefaultWidth; } + int Height() const { return DefaultHeight; } + int Depth() const { return DefaultDepth; } + inline bool IsSolid(int x, int y, int z) const { SPAssert(x >= 0); SPAssert(x < Width()); SPAssert(y >= 0); @@ -74,7 +74,7 @@ namespace spades { } /** @return 0xHHBBGGRR where HH is health (up to 100) */ - inline uint32_t GetColor(int x, int y, int z) { + inline uint32_t GetColor(int x, int y, int z) const { SPAssert(x >= 0); SPAssert(x < Width()); SPAssert(y >= 0); @@ -84,11 +84,11 @@ namespace spades { return colorMap[x][y][z]; } - inline uint64_t GetSolidMapWrapped(int x, int y) { + inline uint64_t GetSolidMapWrapped(int x, int y) const { return solidMap[x & (Width() - 1)][y & (Height() - 1)]; } - inline bool IsSolidWrapped(int x, int y, int z) { + inline bool IsSolidWrapped(int x, int y, int z) const { if (z < 0) return false; if (z >= Depth()) @@ -97,7 +97,7 @@ namespace spades { 0; } - inline uint32_t GetColorWrapped(int x, int y, int z) { + inline uint32_t GetColorWrapped(int x, int y, int z) const { return colorMap[x & (Width() - 1)][y & (Height() - 1)][z & (Depth() - 1)]; } @@ -137,14 +137,14 @@ namespace spades { void AddListener(IGameMapListener *); void RemoveListener(IGameMapListener *); - bool ClipBox(int x, int y, int z); - bool ClipWorld(int x, int y, int z); + bool ClipBox(int x, int y, int z) const; + bool ClipWorld(int x, int y, int z) const; - bool ClipBox(float x, float y, float z); - bool ClipWorld(float x, float y, float z); + bool ClipBox(float x, float y, float z) const; + bool ClipWorld(float x, float y, float z) const; // vanila compat - bool CastRay(Vector3 v0, Vector3 v1, float length, IntVector3 &vOut); + bool CastRay(Vector3 v0, Vector3 v1, float length, IntVector3 &vOut) const; // accurate and slow ray casting struct RayCastResult { @@ -154,7 +154,7 @@ namespace spades { IntVector3 hitBlock; IntVector3 normal; }; - RayCastResult CastRay2(Vector3 v0, Vector3 dir, int maxSteps); + RayCastResult CastRay2(Vector3 v0, Vector3 dir, int maxSteps) const; private: uint64_t solidMap[DefaultWidth][DefaultHeight]; @@ -162,7 +162,7 @@ namespace spades { std::list listeners; std::mutex listenersMutex; - bool IsSurface(int x, int y, int z); + bool IsSurface(int x, int y, int z) const; }; } // namespace client } // namespace spades diff --git a/Sources/Client/GameMapLoader.cpp b/Sources/Client/GameMapLoader.cpp index b30323baa..cff4892bb 100644 --- a/Sources/Client/GameMapLoader.cpp +++ b/Sources/Client/GameMapLoader.cpp @@ -39,18 +39,18 @@ namespace spades { struct GameMapLoader::Decoder : public IRunnable { GameMapLoader &parent; - StreamHandle rawDataReader; + std::unique_ptr rawDataReader; - Decoder(GameMapLoader &parent, StreamHandle rawDataReader) - : parent{parent}, rawDataReader{rawDataReader} {} + Decoder(GameMapLoader &parent, std::unique_ptr rawDataReader) + : parent{parent}, rawDataReader{std::move(rawDataReader)} {} void Run() override { SPADES_MARK_FUNCTION(); - std::unique_ptr result{new Result()}; + auto result = stmp::make_unique(); try { - DeflateStream inflate(&*rawDataReader, CompressModeDecompress, false); + DeflateStream inflate(rawDataReader.get(), CompressModeDecompress, false); GameMap *gameMapPtr = GameMap::Load(&inflate, [this](int x) { HandleProgress(x); }); @@ -75,18 +75,12 @@ namespace spades { auto pipe = CreatePipeStream(); - rawDataWriter = StreamHandle{std::get<0>(pipe)}; - auto rawDataReader = StreamHandle{std::get<1>(pipe)}; + rawDataWriter = std::move(std::get<0>(pipe)); + auto rawDataReader = std::move(std::get<1>(pipe)); - decodingThreadRunnable.reset(new Decoder(*this, rawDataReader)); + decodingThreadRunnable = stmp::make_unique(*this, std::move(rawDataReader)); - // Drop `rawDataReader` before the thread starts. `StreamHandle`'s internally - // ref-counted and it's not thread-safe. So, if we don't drop it here, there'll be - // a data race between the constructor of `Decoder` and the deconstruction of the local - // variable `rawDataReader`. - rawDataReader = StreamHandle{}; - - decodingThread.reset(new Thread(&*decodingThreadRunnable)); + decodingThread = stmp::make_unique(&*decodingThreadRunnable); decodingThread->Start(); } @@ -94,7 +88,7 @@ namespace spades { SPADES_MARK_FUNCTION(); // Hang up the writer. This causes the decoder thread to exit gracefully. - rawDataWriter = StreamHandle{}; + rawDataWriter.reset(); decodingThread->Join(); decodingThread.reset(); @@ -116,10 +110,10 @@ namespace spades { if (!rawDataWriter) { SPRaise("The raw data channel is already closed."); } - rawDataWriter = StreamHandle{}; + rawDataWriter.reset(); } - bool GameMapLoader::IsComplete() { return resultCell.operator bool(); } + bool GameMapLoader::IsComplete() const { return resultCell.operator bool(); } void GameMapLoader::WaitComplete() { SPADES_MARK_FUNCTION(); @@ -133,7 +127,7 @@ namespace spades { return static_cast(progressCell.load(std::memory_order_relaxed)) / (512 * 512); } - GameMap *GameMapLoader::TakeGameMap() { + Handle GameMapLoader::TakeGameMap() { SPADES_MARK_FUNCTION(); SPAssert(IsComplete()); @@ -142,7 +136,7 @@ namespace spades { SPAssert(result); if (result->gameMap) { - return result->gameMap.Unmanage(); + return std::move(result->gameMap); } else { std::rethrow_exception(result->exceptionThrown); } diff --git a/Sources/Client/GameMapLoader.h b/Sources/Client/GameMapLoader.h index 287d6ef32..c6396ae1b 100644 --- a/Sources/Client/GameMapLoader.h +++ b/Sources/Client/GameMapLoader.h @@ -56,7 +56,7 @@ namespace spades { /** * Returns `true` if the loading operation is complete, successful or not. */ - bool IsComplete(); + bool IsComplete() const; /** * Blocks the current thread until the decoding is complete. @@ -79,14 +79,14 @@ namespace spades { * If an exception occured while decoding the map, the exception will be rethrown when * this method is called. */ - GameMap *TakeGameMap(); + Handle TakeGameMap(); private: struct Decoder; struct Result; /** A writable stream used to send undecoded data to the decoding thread. */ - StreamHandle rawDataWriter; + std::unique_ptr rawDataWriter; /** A handle for the decoding thread. */ std::unique_ptr decodingThread; diff --git a/Sources/Client/GameMapWrapper.cpp b/Sources/Client/GameMapWrapper.cpp index 9809a45fc..5b13c6900 100644 --- a/Sources/Client/GameMapWrapper.cpp +++ b/Sources/Client/GameMapWrapper.cpp @@ -20,14 +20,13 @@ #include #include +#include #include #include #include "GameMap.h" #include "GameMapWrapper.h" #include -#include -#include #include namespace spades { @@ -39,6 +38,7 @@ namespace spades { width = mp.Width(); height = mp.Height(); depth = mp.Depth(); + // TODO: `stmp::make_unique` doesn't support array initialization yet linkMap.reset(new uint8_t[width * height * depth]); memset(linkMap.get(), 0, width * height * depth); } @@ -57,44 +57,44 @@ namespace spades { for (int y = 0; y < height; y++) SetLink(x, y, depth - 1, Root); - Deque queue(width * height * 2); + std::deque queue(width * height * 2); for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) if (m.IsSolid(x, y, depth - 2)) { SetLink(x, y, depth - 2, PositiveZ); - queue.Push(CellPos(x, y, depth - 2)); + queue.push_back(CellPos(x, y, depth - 2)); } - while (!queue.IsEmpty()) { - CellPos p = queue.Front(); - queue.Shift(); + while (!queue.empty()) { + CellPos p = queue.front(); + queue.pop_front(); int x = p.x, y = p.y, z = p.z; if (p.x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid) { SetLink(x - 1, y, z, PositiveX); - queue.Push(CellPos(x - 1, y, z)); + queue.push_back(CellPos(x - 1, y, z)); } if (p.x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid) { SetLink(x + 1, y, z, NegativeX); - queue.Push(CellPos(x + 1, y, z)); + queue.push_back(CellPos(x + 1, y, z)); } if (p.y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid) { SetLink(x, y - 1, z, PositiveY); - queue.Push(CellPos(x, y - 1, z)); + queue.push_back(CellPos(x, y - 1, z)); } if (p.y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) == Invalid) { SetLink(x, y + 1, z, NegativeY); - queue.Push(CellPos(x, y + 1, z)); + queue.push_back(CellPos(x, y + 1, z)); } if (p.z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid) { SetLink(x, y, z - 1, PositiveZ); - queue.Push(CellPos(x, y, z - 1)); + queue.push_back(CellPos(x, y, z - 1)); } if (p.z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid) { SetLink(x, y, z + 1, NegativeZ); - queue.Push(CellPos(x, y, z + 1)); + queue.push_back(CellPos(x, y, z + 1)); } } @@ -148,11 +148,11 @@ namespace spades { return; // if there's invalid block around this block, // rebuild tree - Deque queue(1024); - queue.Push(CellPos(x, y, z)); - while (!queue.IsEmpty()) { - CellPos p = queue.Front(); - queue.Shift(); + std::deque queue; + queue.push_back(CellPos(x, y, z)); + while (!queue.empty()) { + CellPos p = queue.front(); + queue.pop_front(); int x = p.x, y = p.y, z = p.z; SPAssert(m.IsSolid(x, y, z)); @@ -162,32 +162,32 @@ namespace spades { if (p.x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid && thisLink != NegativeX) { SetLink(x - 1, y, z, PositiveX); - queue.Push(CellPos(x - 1, y, z)); + queue.push_back(CellPos(x - 1, y, z)); } if (p.x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid && thisLink != PositiveX) { SetLink(x + 1, y, z, NegativeX); - queue.Push(CellPos(x + 1, y, z)); + queue.push_back(CellPos(x + 1, y, z)); } if (p.y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid && thisLink != NegativeY) { SetLink(x, y - 1, z, PositiveY); - queue.Push(CellPos(x, y - 1, z)); + queue.push_back(CellPos(x, y - 1, z)); } if (p.y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) == Invalid && thisLink != PositiveY) { SetLink(x, y + 1, z, NegativeY); - queue.Push(CellPos(x, y + 1, z)); + queue.push_back(CellPos(x, y + 1, z)); } if (p.z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid && thisLink != NegativeZ) { SetLink(x, y, z - 1, PositiveZ); - queue.Push(CellPos(x, y, z - 1)); + queue.push_back(CellPos(x, y, z - 1)); } if (p.z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid && thisLink != PositiveZ) { SetLink(x, y, z + 1, NegativeZ); - queue.Push(CellPos(x, y, z + 1)); + queue.push_back(CellPos(x, y, z + 1)); } } } @@ -206,7 +206,7 @@ namespace spades { // solid, but unlinked cells std::vector unlinkedCells; - Deque queue(1024); + std::deque queue; // unlink children for (size_t i = 0; i < cells.size(); i++) { @@ -222,11 +222,11 @@ namespace spades { SPAssert(GetLink(pos.x, pos.y, pos.z) != Root); SetLink(pos.x, pos.y, pos.z, Invalid); - queue.Push(pos); + queue.push_back(pos); - while (!queue.IsEmpty()) { - pos = queue.Front(); - queue.Shift(); + while (!queue.empty()) { + pos = queue.front(); + queue.pop_front(); if (m.IsSolid(pos.x, pos.y, pos.z)) unlinkedCells.push_back(pos); @@ -236,32 +236,32 @@ namespace spades { if (x > 0 && EqualTwoCond(GetLink(x - 1, y, z), PositiveX, Invalid, m.IsSolid(x - 1, y, z))) { SetLink(x - 1, y, z, Marked); - queue.Push(CellPos(x - 1, y, z)); + queue.push_back(CellPos(x - 1, y, z)); } if (x < width - 1 && EqualTwoCond(GetLink(x + 1, y, z), NegativeX, Invalid, m.IsSolid(x + 1, y, z))) { SetLink(x + 1, y, z, Marked); - queue.Push(CellPos(x + 1, y, z)); + queue.push_back(CellPos(x + 1, y, z)); } if (y > 0 && EqualTwoCond(GetLink(x, y - 1, z), PositiveY, Invalid, m.IsSolid(x, y - 1, z))) { SetLink(x, y - 1, z, Marked); - queue.Push(CellPos(x, y - 1, z)); + queue.push_back(CellPos(x, y - 1, z)); } if (y < height - 1 && EqualTwoCond(GetLink(x, y + 1, z), NegativeY, Invalid, m.IsSolid(x, y + 1, z))) { SetLink(x, y + 1, z, Marked); - queue.Push(CellPos(x, y + 1, z)); + queue.push_back(CellPos(x, y + 1, z)); } if (z > 0 && EqualTwoCond(GetLink(x, y, z - 1), PositiveZ, Invalid, m.IsSolid(x, y, z - 1))) { SetLink(x, y, z - 1, Marked); - queue.Push(CellPos(x, y, z - 1)); + queue.push_back(CellPos(x, y, z - 1)); } if (z < depth - 1 && EqualTwoCond(GetLink(x, y, z + 1), NegativeZ, Invalid, m.IsSolid(x, y, z + 1))) { SetLink(x, y, z + 1, Marked); - queue.Push(CellPos(x, y, z + 1)); + queue.push_back(CellPos(x, y, z + 1)); } } } @@ -273,7 +273,7 @@ namespace spades { SetLink(pos.x, pos.y, pos.z, Invalid); } - SPAssert(queue.IsEmpty()); + SPAssert(queue.empty()); // start relinking for (size_t i = 0; i < unlinkedCells.size(); i++) { @@ -302,13 +302,13 @@ namespace spades { if (newLink != Invalid) { SetLink(x, y, z, newLink); - queue.Push(pos); + queue.push_back(pos); } } - while (!queue.IsEmpty()) { - CellPos p = queue.Front(); - queue.Shift(); + while (!queue.empty()) { + CellPos p = queue.front(); + queue.pop_front(); int x = p.x, y = p.y, z = p.z; LinkType thisLink = GetLink(x, y, z); @@ -316,32 +316,32 @@ namespace spades { if (p.x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid && thisLink != NegativeX) { SetLink(x - 1, y, z, PositiveX); - queue.Push(CellPos(x - 1, y, z)); + queue.push_back(CellPos(x - 1, y, z)); } if (p.x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid && thisLink != PositiveX) { SetLink(x + 1, y, z, NegativeX); - queue.Push(CellPos(x + 1, y, z)); + queue.push_back(CellPos(x + 1, y, z)); } if (p.y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid && thisLink != NegativeY) { SetLink(x, y - 1, z, PositiveY); - queue.Push(CellPos(x, y - 1, z)); + queue.push_back(CellPos(x, y - 1, z)); } if (p.y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) == Invalid && thisLink != PositiveY) { SetLink(x, y + 1, z, NegativeY); - queue.Push(CellPos(x, y + 1, z)); + queue.push_back(CellPos(x, y + 1, z)); } if (p.z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid && thisLink != NegativeZ) { SetLink(x, y, z - 1, PositiveZ); - queue.Push(CellPos(x, y, z - 1)); + queue.push_back(CellPos(x, y, z - 1)); } if (p.z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid && thisLink != PositiveZ) { SetLink(x, y, z + 1, NegativeZ); - queue.Push(CellPos(x, y, z + 1)); + queue.push_back(CellPos(x, y, z + 1)); } } @@ -359,5 +359,5 @@ namespace spades { return floatingBlocks; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/GameMapWrapper.h b/Sources/Client/GameMapWrapper.h index 463be5c08..20a39c556 100644 --- a/Sources/Client/GameMapWrapper.h +++ b/Sources/Client/GameMapWrapper.h @@ -21,8 +21,8 @@ #pragma once #include -#include #include +#include namespace spades { namespace client { @@ -113,5 +113,5 @@ namespace spades { void Rebuild(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/GameProperties.cpp b/Sources/Client/GameProperties.cpp index 187cba6b3..432ec42bb 100644 --- a/Sources/Client/GameProperties.cpp +++ b/Sources/Client/GameProperties.cpp @@ -32,5 +32,5 @@ namespace spades { SPLog("Enabled clearCorpseOnRespawn based on a server message heuristics"); } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/GameProperties.h b/Sources/Client/GameProperties.h index 3db80de29..2ddee81f7 100644 --- a/Sources/Client/GameProperties.h +++ b/Sources/Client/GameProperties.h @@ -67,5 +67,5 @@ namespace spades { int GetMaxNumPlayerSlots() const { return manyPlayers ? 128 : 32; } }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Grenade.cpp b/Sources/Client/Grenade.cpp index 84a88a54e..3e9be0a1d 100644 --- a/Sources/Client/Grenade.cpp +++ b/Sources/Client/Grenade.cpp @@ -28,14 +28,13 @@ namespace spades { namespace client { - Grenade::Grenade(World *w, Vector3 pos, Vector3 vel, float fuse) { + Grenade::Grenade(World &w, Vector3 pos, Vector3 vel, float fuse) : world{w} { SPADES_MARK_FUNCTION(); position = pos; velocity = vel; this->fuse = fuse; - world = w; - orientation = Quaternion {0.0f, 0.0f, 0.0f, 1.0f}; + orientation = Quaternion{0.0f, 0.0f, 0.0f, 1.0f}; } Grenade::~Grenade() { SPADES_MARK_FUNCTION(); } @@ -50,8 +49,8 @@ namespace spades { } if (MoveGrenade(dt) == 2) { - if (world->GetListener()) - world->GetListener()->GrenadeBounced(this); + if (world.GetListener()) + world.GetListener()->GrenadeBounced(*this); } return false; @@ -60,8 +59,8 @@ namespace spades { void Grenade::Explode() { SPADES_MARK_FUNCTION(); - if (world->GetListener()) - world->GetListener()->GrenadeExploded(this); + if (world.GetListener()) + world.GetListener()->GrenadeExploded(*this); } int Grenade::MoveGrenade(float fsynctics) { @@ -74,17 +73,19 @@ namespace spades { // Make it roll float radius = 4.0f * 0.03f; - orientation = Quaternion::MakeRotation(Vector3(-velocity.y, velocity.x, 0.0f) * (f / radius)) * orientation; + orientation = + Quaternion::MakeRotation(Vector3(-velocity.y, velocity.x, 0.0f) * (f / radius)) * + orientation; orientation = orientation.Normalize(); // Collision IntVector3 lp = position.Floor(); IntVector3 lp2 = oldPos.Floor(); - GameMap *m = world->GetMap(); + Handle m = world.GetMap(); if (lp.z >= 63 && lp2.z < 63) { - if (world->GetListener()) - world->GetListener()->GrenadeDroppedIntoWater(this); + if (world.GetListener()) + world.GetListener()->GrenadeDroppedIntoWater(*this); } int ret = 0; @@ -110,5 +111,5 @@ namespace spades { } return ret; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Grenade.h b/Sources/Client/Grenade.h index 43182a6d5..ecf626d37 100644 --- a/Sources/Client/Grenade.h +++ b/Sources/Client/Grenade.h @@ -28,7 +28,7 @@ namespace spades { class World; class Grenade { - World *world; + World &world; float fuse; Vector3 position; Vector3 velocity; @@ -43,16 +43,16 @@ namespace spades { int MoveGrenade(float fsynctics); public: - Grenade(World *, Vector3 pos, Vector3 vel, float fuse); + Grenade(World &, Vector3 pos, Vector3 vel, float fuse); ~Grenade(); /** @return true when exploded. */ bool Update(float dt); - Vector3 GetPosition() { return position; } - Vector3 GetVelocity() { return velocity; } - Quaternion GetOrientation() { return orientation; } - float GetFuse() { return fuse; } + Vector3 GetPosition() const { return position; } + Vector3 GetVelocity() const { return velocity; } + Quaternion GetOrientation() const { return orientation; } + float GetFuse() const { return fuse; } }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/GunCasing.cpp b/Sources/Client/GunCasing.cpp index 8095fe76a..6d94a4dba 100644 --- a/Sources/Client/GunCasing.cpp +++ b/Sources/Client/GunCasing.cpp @@ -76,7 +76,7 @@ namespace spades { return false; } - GameMap *map = client->GetWorld()->GetMap(); + const Handle &map = client->GetWorld()->GetMap(); if (!map->ClipWorld(groundPos.x, groundPos.y, groundPos.z)) { return false; } @@ -88,7 +88,7 @@ namespace spades { vel.z += dt * 32.f; IntVector3 lp = matrix.GetOrigin().Floor(); - GameMap *m = client->GetWorld()->GetMap(); + Handle m = client->GetWorld()->GetMap(); if (lp.z >= 63) { // dropped into water @@ -97,12 +97,12 @@ namespace spades { if (waterSound) { if (dist < 40.f * 40.f && !client->IsMuted()) { - IAudioDevice *dev = client->GetAudioDevice(); + IAudioDevice &dev = client->GetAudioDevice(); AudioParam param; param.referenceDistance = .6f; param.pitch = .9f + SampleRandomFloat() * .2f; - dev->Play(waterSound, lastMat.GetOrigin(), param); + dev.Play(waterSound, lastMat.GetOrigin(), param); } waterSound = NULL; } @@ -110,13 +110,13 @@ namespace spades { if (dist < 40.f * 40.f) { int splats = SampleRandomInt(0, 2); - Handle img = client->GetRenderer()->RegisterImage("Gfx/White.tga"); + Handle img = client->GetRenderer().RegisterImage("Gfx/White.tga"); Vector4 col = {1, 1, 1, 0.8f}; Vector3 pt = matrix.GetOrigin(); pt.z = 62.99f; for (int i = 0; i < splats; i++) { - ParticleSpriteEntity *ent = new ParticleSpriteEntity(client, img, col); + auto ent = stmp::make_unique(*client, img, col); ent->SetTrajectory( pt, MakeVector3(SampleRandomFloat() - SampleRandomFloat(), @@ -127,7 +127,7 @@ namespace spades { ent->SetRotation(SampleRandomFloat() * (float)M_PI * 2.f); ent->SetRadius(0.1f + SampleRandomFloat() * SampleRandomFloat() * 0.1f); ent->SetLifeTime(2.f, 0.f, 1.f); - client->AddLocalEntity(ent); + client->AddLocalEntity(std::move(ent)); } } @@ -172,11 +172,11 @@ namespace spades { (client->GetLastSceneDef().viewOrigin - matrix.GetOrigin()) .GetPoweredLength(); if (dist < 40.f * 40.f && !client->IsMuted()) { - IAudioDevice *dev = client->GetAudioDevice(); + IAudioDevice &dev = client->GetAudioDevice(); AudioParam param; param.referenceDistance = .6f; - dev->Play(dropSound, lastMat.GetOrigin(), param); + dev.Play(dropSound, lastMat.GetOrigin(), param); } dropSound = NULL; } @@ -217,7 +217,7 @@ namespace spades { float move = (groundTime - 1.f) * .2f; param.matrix = Matrix4::Translate(0, 0, move) * param.matrix; } - renderer->RenderModel(model, param); + renderer.RenderModel(*model, param); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/GunCasing.h b/Sources/Client/GunCasing.h index 98b59b5de..d232c945a 100644 --- a/Sources/Client/GunCasing.h +++ b/Sources/Client/GunCasing.h @@ -31,7 +31,7 @@ namespace spades { class IAudioChunk; class GunCasing : public ILocalEntity { Client *client; - IRenderer *renderer; + IRenderer &renderer; IModel *model; Matrix4 matrix; Vector3 rotAxis; @@ -46,11 +46,12 @@ namespace spades { float rotSpeed; public: + // TODO: Replace pointers with references GunCasing(Client *client, IModel *model, IAudioChunk *dropSound, IAudioChunk *waterSound, Vector3 pos, Vector3 dir, Vector3 flyDir); ~GunCasing(); bool Update(float dt) override; void Render3D() override; }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades diff --git a/Sources/Client/HitTestDebugger.cpp b/Sources/Client/HitTestDebugger.cpp index 096bbc1d5..29eb8728b 100644 --- a/Sources/Client/HitTestDebugger.cpp +++ b/Sources/Client/HitTestDebugger.cpp @@ -21,8 +21,8 @@ #include //windows needs this. -#include "HitTestDebugger.h" #include "GameMap.h" +#include "HitTestDebugger.h" #include "Player.h" #include "Weapon.h" #include "World.h" @@ -33,8 +33,6 @@ #include #include -SPADES_SETTING(cg_smp); - namespace spades { namespace client { class HitTestDebugger::Port : public draw::SWPort { @@ -43,9 +41,9 @@ namespace spades { public: Port() { SPADES_MARK_FUNCTION(); - bmp.Set(new Bitmap(512, 512), false); + bmp = Handle::New(512, 512); } - Bitmap *GetFramebuffer() override { return bmp; } + Bitmap &GetFramebuffer() override { return *bmp; } void Swap() override { // nothing to do here } @@ -53,8 +51,8 @@ namespace spades { HitTestDebugger::HitTestDebugger(World *world) : world(world) { SPADES_MARK_FUNCTION(); - port.Set(new Port(), false); - renderer.Set(new draw::SWRenderer(port), false); + port = Handle::New(); + renderer = Handle::New(port.Cast()).Cast(); renderer->Init(); } @@ -71,9 +69,9 @@ namespace spades { renderer->SetFogColor(MakeVector3(0.f, 0.f, 0.f)); renderer->SetFogDistance(128.f); - Player *localPlayer = world->GetLocalPlayer(); + stmp::optional localPlayer = world->GetLocalPlayer(); - if (localPlayer == nullptr) { + if (!localPlayer) { SPLog("HitTestDebugger failure: Local player is null"); return; } @@ -100,7 +98,7 @@ namespace spades { // fit FoV to include all possibly hit players float range = 0.2f; for (std::size_t i = 0; i < world->GetNumPlayerSlots(); i++) { - auto *p = world->GetPlayer(static_cast(i)); + auto p = world->GetPlayer(static_cast(i)); if (!p) continue; if (p == localPlayer) @@ -141,16 +139,15 @@ namespace spades { def.fovX = def.fovY = range; - // we cannot change GameMap's listener in the client thread with SMP renderer - def.skipWorld = ((int)cg_smp != 0); + def.skipWorld = false; def.zNear = 0.05f; def.zFar = 200.f; // start rendering - GameMap *map = world->GetMap(); + const Handle &map = world->GetMap(); if (!def.skipWorld) { - renderer->SetGameMap(map); + renderer->SetGameMap(&*map); } renderer->StartScene(def); @@ -204,7 +201,7 @@ namespace spades { }; for (std::size_t i = 0; i < numPlayers; i++) { - auto *p = world->GetPlayer(static_cast(i)); + auto p = world->GetPlayer(static_cast(i)); if (!p) continue; if (p == localPlayer) @@ -233,12 +230,12 @@ namespace spades { renderer->EndScene(); // draw crosshair - IImage *img = renderer->RegisterImage("Gfx/White.tga"); + Handle img = renderer->RegisterImage("Gfx/White.tga"); float size = renderer->ScreenWidth(); renderer->SetColorAlphaPremultiplied(Vector4(1.f, 0.f, 0.f, 0.9f)); - renderer->DrawImage(img, AABB2(size * 0.5f - 1.f, 0.f, 2.f, size)); - renderer->DrawImage(img, AABB2(0.f, size * 0.5f - 1.f, size, 2.f)); + renderer->DrawImage(*img, AABB2(size * 0.5f - 1.f, 0.f, 2.f, size)); + renderer->DrawImage(*img, AABB2(0.f, size * 0.5f - 1.f, size, 2.f)); // draw bullet vectors float fov = tanf(def.fovY * .5f); @@ -250,9 +247,9 @@ namespace spades { x = floorf(x); y = floorf(y); renderer->SetColorAlphaPremultiplied(Vector4(1.f, 0.f, 0.f, 0.9f)); - renderer->DrawImage(img, AABB2(x - 1.f, y - 1.f, 3.f, 3.f)); + renderer->DrawImage(*img, AABB2(x - 1.f, y - 1.f, 3.f, 3.f)); renderer->SetColorAlphaPremultiplied(Vector4(1.f, 1.f, 0.f, 0.9f)); - renderer->DrawImage(img, AABB2(x, y, 1.f, 1.f)); + renderer->DrawImage(*img, AABB2(x, y, 1.f, 1.f)); } renderer->FrameDone(); @@ -271,7 +268,7 @@ namespace spades { fileName = buf; } - switch (localPlayer->GetWeapon()->GetWeaponType()) { + switch (localPlayer->GetWeapon().GetWeaponType()) { case SMG_WEAPON: fileName += "-SMG"; break; case RIFLE_WEAPON: fileName += "-Rifle"; break; case SHOTGUN_WEAPON: fileName += "-Shotgun"; break; @@ -297,7 +294,7 @@ namespace spades { // save image try { - Handle b(renderer->ReadBitmap(), false); + Handle b = renderer->ReadBitmap(); b->Save(fileName); SPLog("HitTestDebugger: saved to '%s'", fileName.c_str()); } catch (const std::exception &ex) { @@ -307,5 +304,5 @@ namespace spades { renderer->Flip(); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/HitTestDebugger.h b/Sources/Client/HitTestDebugger.h index 4e3212f6f..16e286b77 100644 --- a/Sources/Client/HitTestDebugger.h +++ b/Sources/Client/HitTestDebugger.h @@ -58,5 +58,5 @@ namespace spades { void SaveImage(const std::map &hits, const std::vector &bullets); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/HurtRingView.cpp b/Sources/Client/HurtRingView.cpp index 0d8856d3c..80272f226 100644 --- a/Sources/Client/HurtRingView.cpp +++ b/Sources/Client/HurtRingView.cpp @@ -32,7 +32,7 @@ namespace spades { HurtRingView::HurtRingView(Client *cli) : client(cli), renderer(cli->GetRenderer()) { SPADES_MARK_FUNCTION(); - image = renderer->RegisterImage("Gfx/HurtRing2.png"); + image = renderer.RegisterImage("Gfx/HurtRing2.png"); } HurtRingView::~HurtRingView() {} @@ -74,17 +74,17 @@ namespace spades { return; } - Player *p = w->GetLocalPlayer(); - if (p == NULL || !p->IsAlive()) { + auto p = w->GetLocalPlayer(); + if (!p || !p->IsAlive()) { ClearAll(); return; } playerFront = p->GetFront2D(); - float hurtRingSize = renderer->ScreenHeight() * .3f; - float cx = renderer->ScreenWidth() * .5f; - float cy = renderer->ScreenHeight() * .5f; + float hurtRingSize = renderer.ScreenHeight() * .3f; + float cx = renderer.ScreenWidth() * .5f; + float cy = renderer.ScreenHeight() * .5f; static const float coords[][2] = {{-1, 1}, {1, 1}, {-1, 0}}; std::list::iterator it; @@ -95,7 +95,7 @@ namespace spades { if (fade > 1.f) fade = 1.f; Vector4 color = {fade, fade, fade, 0}; - renderer->SetColorAlphaPremultiplied(color); + renderer.SetColorAlphaPremultiplied(color); Vector3 dir = -item.dir; float c = dir.x * playerFront.x + dir.y * playerFront.y; @@ -108,9 +108,9 @@ namespace spades { verts[i] = verts[i] * hurtRingSize + MakeVector2(cx, cy); } - renderer->DrawImage(image, verts[0], verts[1], verts[2], - AABB2(0, 0, image->GetWidth(), image->GetHeight())); + renderer.DrawImage(image, verts[0], verts[1], verts[2], + AABB2(0, 0, image->GetWidth(), image->GetHeight())); } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/HurtRingView.h b/Sources/Client/HurtRingView.h index 4ed4ba4e1..84f60c8ca 100644 --- a/Sources/Client/HurtRingView.h +++ b/Sources/Client/HurtRingView.h @@ -23,6 +23,7 @@ #include #include +#include namespace spades { namespace client { @@ -32,8 +33,8 @@ namespace spades { class HurtRingView { Client *client; - IRenderer *renderer; - IImage *image; + IRenderer &renderer; + Handle image; struct Item { Vector3 dir; @@ -52,5 +53,5 @@ namespace spades { void Update(float dt); void Draw(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IAudioChunk.h b/Sources/Client/IAudioChunk.h index f757fd4d7..3ac397099 100644 --- a/Sources/Client/IAudioChunk.h +++ b/Sources/Client/IAudioChunk.h @@ -23,13 +23,13 @@ #include namespace spades { - namespace client { - class IAudioChunk : public RefCountedObject { - protected: - IAudioChunk() {} - ~IAudioChunk() {} - - public: - }; - } -} + namespace client { + class IAudioChunk : public RefCountedObject { + protected: + IAudioChunk() {} + ~IAudioChunk() {} + + public: + }; + } // namespace client +} // namespace spades diff --git a/Sources/Client/IAudioDevice.h b/Sources/Client/IAudioDevice.h index de88b188b..11d972d7f 100644 --- a/Sources/Client/IAudioDevice.h +++ b/Sources/Client/IAudioDevice.h @@ -62,5 +62,5 @@ namespace spades { virtual void Respatialize(const Vector3 &eye, const Vector3 &front, const Vector3 &up) = 0; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IFont.cpp b/Sources/Client/IFont.cpp index 5830d493a..d64ea4ddb 100644 --- a/Sources/Client/IFont.cpp +++ b/Sources/Client/IFont.cpp @@ -176,10 +176,10 @@ namespace spades { : renderer(renderer), manager(manager) { for (auto font = manager->fonts.begin(); font != manager->fonts.end(); ++font) { auto imgPath = (*font)->imagePath; - auto *img = renderer->RegisterImage(imgPath.c_str()); // addref'd + auto img = renderer->RegisterImage(imgPath.c_str()).Unmanage(); images.push_back(img); } - whiteImage.Set(renderer->RegisterImage("Gfx/White.tga"), false); + whiteImage = renderer->RegisterImage("Gfx/White.tga"); // SW renderer doesn't perform linear interpolation on // rendering images, so size rounding must be done to @@ -226,11 +226,11 @@ namespace spades { auto glyph = FindGlyph(unicode); if (glyph.img == nullptr) { // no glyph found! draw box in the last resort - IImage *img = whiteImage; - renderer->DrawImage(img, AABB2(x, y, size, 1.f)); - renderer->DrawImage(img, AABB2(x, y + size - 1.f, size, 1.f)); - renderer->DrawImage(img, AABB2(x, y + 1.f, 1.f, size - 2.f)); - renderer->DrawImage(img, AABB2(x + size - 1.f, y + 1.f, 1.f, size - 2.f)); + const Handle &img = whiteImage; + renderer->DrawImage(*img, AABB2(x, y, size, 1.f)); + renderer->DrawImage(*img, AABB2(x, y + size - 1.f, size, 1.f)); + renderer->DrawImage(*img, AABB2(x, y + 1.f, 1.f, size - 2.f)); + renderer->DrawImage(*img, AABB2(x + size - 1.f, y + 1.f, 1.f, size - 2.f)); return; } @@ -309,5 +309,5 @@ namespace spades { Draw(message, offset + MakeVector2(1, 1), scale, shadowColor); Draw(message, offset, scale, color); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IFont.h b/Sources/Client/IFont.h index bb3c1b067..d7549d13d 100644 --- a/Sources/Client/IFont.h +++ b/Sources/Client/IFont.h @@ -54,5 +54,5 @@ namespace spades { virtual void DrawShadow(const std::string &message, const Vector2 &offset, float scale, const Vector4 &color, const Vector4 &shadowColor); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IGameMapListener.h b/Sources/Client/IGameMapListener.h index 63e995cd1..46422e319 100644 --- a/Sources/Client/IGameMapListener.h +++ b/Sources/Client/IGameMapListener.h @@ -21,11 +21,11 @@ #pragma once namespace spades { - namespace client { - class GameMap; - class IGameMapListener { - public: - virtual void GameMapChanged(int x, int y, int z, GameMap *) = 0; - }; - } -} + namespace client { + class GameMap; + class IGameMapListener { + public: + virtual void GameMapChanged(int x, int y, int z, GameMap *) = 0; + }; + } // namespace client +} // namespace spades diff --git a/Sources/Client/IGameMode.cpp b/Sources/Client/IGameMode.cpp index 69738ee85..63a41a187 100644 --- a/Sources/Client/IGameMode.cpp +++ b/Sources/Client/IGameMode.cpp @@ -21,5 +21,5 @@ #include "IGameMode.h" namespace spades { - namespace client {} -} + namespace client {} +} // namespace spades diff --git a/Sources/Client/IGameMode.h b/Sources/Client/IGameMode.h index 57c15775c..09ecc1bca 100644 --- a/Sources/Client/IGameMode.h +++ b/Sources/Client/IGameMode.h @@ -34,5 +34,5 @@ namespace spades { virtual ~IGameMode() {} Mode ModeType() const { return mMode; } }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IImage.cpp b/Sources/Client/IImage.cpp index 3ca4cffc5..68bc1e085 100644 --- a/Sources/Client/IImage.cpp +++ b/Sources/Client/IImage.cpp @@ -21,5 +21,5 @@ #include "IImage.h" namespace spades { - namespace client {} -} + namespace client {} +} // namespace spades diff --git a/Sources/Client/IImage.h b/Sources/Client/IImage.h index c6db38af9..ce9e00873 100644 --- a/Sources/Client/IImage.h +++ b/Sources/Client/IImage.h @@ -40,5 +40,5 @@ namespace spades { virtual float GetWidth() = 0; virtual float GetHeight() = 0; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IInputInterface.h b/Sources/Client/IInputInterface.h index 6ee24ada5..dae718b31 100644 --- a/Sources/Client/IInputInterface.h +++ b/Sources/Client/IInputInterface.h @@ -21,12 +21,12 @@ #pragma once namespace spades { - namespace client { - /** input interface - * @obsolete */ - class IInputInterface { - public: - virtual ~IInputInterface() {} - }; - } -} + namespace client { + /** input interface + * @obsolete */ + class IInputInterface { + public: + virtual ~IInputInterface() {} + }; + } // namespace client +} // namespace spades diff --git a/Sources/Client/ILocalEntity.h b/Sources/Client/ILocalEntity.h index da2bfe516..744d40c05 100644 --- a/Sources/Client/ILocalEntity.h +++ b/Sources/Client/ILocalEntity.h @@ -30,5 +30,5 @@ namespace spades { virtual void Render3D() {} virtual void Render2D() {} }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IModel.cpp b/Sources/Client/IModel.cpp index 4adfe16d7..926e5205e 100644 --- a/Sources/Client/IModel.cpp +++ b/Sources/Client/IModel.cpp @@ -52,5 +52,5 @@ namespace spades { }; static RendererModelModelRegistrar registrar; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IModel.h b/Sources/Client/IModel.h index a5b7eba94..2f4f57353 100644 --- a/Sources/Client/IModel.h +++ b/Sources/Client/IModel.h @@ -34,5 +34,5 @@ namespace spades { virtual AABB3 GetBoundingBox() = 0; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IRenderer.cpp b/Sources/Client/IRenderer.cpp index 487660a9c..794854410 100644 --- a/Sources/Client/IRenderer.cpp +++ b/Sources/Client/IRenderer.cpp @@ -21,5 +21,5 @@ #include "IRenderer.h" namespace spades { - namespace client {} -} + namespace client {} +} // namespace spades diff --git a/Sources/Client/IRenderer.h b/Sources/Client/IRenderer.h index 42e02ae0f..345b2f8ae 100644 --- a/Sources/Client/IRenderer.h +++ b/Sources/Client/IRenderer.h @@ -22,10 +22,10 @@ #include -#include #include "IImage.h" #include "IModel.h" #include "SceneDefinition.h" +#include #include namespace spades { @@ -62,7 +62,11 @@ namespace spades { float opacity = 1.0; }; - enum DynamicLightType { DynamicLightTypePoint, DynamicLightTypeSpotlight }; + enum DynamicLightType { + DynamicLightTypePoint, + DynamicLightTypeSpotlight, + DynamicLightTypeLinear + }; struct DynamicLightParam { DynamicLightType type = DynamicLightTypePoint; @@ -72,12 +76,18 @@ namespace spades { * is unaffected by the light. */ float radius; Vector3 color; - + /** + * The second position of the light. + * + * For `DyanmicLightTypeLinear`, this specifies the second endpoint's position. For + * other light types, this value is ignored. + */ + Vector3 point2; /** The basis vectors specifying the orientation of a spotlight. * See the existing code for usage. */ std::array spotAxis; /** The projected image for a spotlight. */ - IImage *image = nullptr; + IImage *image = nullptr; // TODO: Replace this raw pointer with something float spotAngle = 0.0f; /** When set to `true`, the lens flare post-effect is enabled for @@ -95,8 +105,8 @@ namespace spades { virtual void Init() = 0; virtual void Shutdown() = 0; - virtual IImage *RegisterImage(const char *filename) = 0; - virtual IModel *RegisterModel(const char *filename) = 0; + virtual Handle RegisterImage(const char *filename) = 0; + virtual Handle RegisterModel(const char *filename) = 0; /** * Clear the cache of models and images loaded via `RegisterModel` @@ -105,10 +115,10 @@ namespace spades { */ virtual void ClearCache() {} - virtual IImage *CreateImage(Bitmap *) = 0; - virtual IModel *CreateModel(VoxelModel *) = 0; + virtual Handle CreateImage(Bitmap &) = 0; + virtual Handle CreateModel(VoxelModel &) = 0; - virtual void SetGameMap(GameMap *) = 0; + virtual void SetGameMap(stmp::optional) = 0; virtual void SetFogDistance(float) = 0; virtual void SetFogColor(Vector3) = 0; @@ -118,11 +128,11 @@ namespace spades { virtual void AddLight(const client::DynamicLightParam &light) = 0; - virtual void RenderModel(IModel *, const ModelRenderParam &) = 0; + virtual void RenderModel(IModel &, const ModelRenderParam &) = 0; virtual void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) = 0; - virtual void AddSprite(IImage *, Vector3 center, float radius, float rotation) = 0; - virtual void AddLongSprite(IImage *, Vector3 p1, Vector3 p2, float radius) = 0; + virtual void AddSprite(IImage &, Vector3 center, float radius, float rotation) = 0; + virtual void AddLongSprite(IImage &, Vector3 p1, Vector3 p2, float radius) = 0; /** Finalizes a scene. 2D drawing follows. */ virtual void EndScene() = 0; @@ -138,12 +148,15 @@ namespace spades { /** Sets color for image drawing. Always alpha premultiplied. */ virtual void SetColorAlphaPremultiplied(Vector4) = 0; - virtual void DrawImage(IImage *, const Vector2 &outTopLeft) = 0; - virtual void DrawImage(IImage *, const AABB2 &outRect) = 0; - virtual void DrawImage(IImage *, const Vector2 &outTopLeft, const AABB2 &inRect) = 0; - virtual void DrawImage(IImage *, const AABB2 &outRect, const AABB2 &inRect) = 0; - virtual void DrawImage(IImage *, const Vector2 &outTopLeft, const Vector2 &outTopRight, - const Vector2 &outBottomLeft, const AABB2 &inRect) = 0; + virtual void DrawImage(stmp::optional, const Vector2 &outTopLeft) = 0; + virtual void DrawImage(stmp::optional, const AABB2 &outRect) = 0; + virtual void DrawImage(stmp::optional, const Vector2 &outTopLeft, + const AABB2 &inRect) = 0; + virtual void DrawImage(stmp::optional, const AABB2 &outRect, + const AABB2 &inRect) = 0; + virtual void DrawImage(stmp::optional, const Vector2 &outTopLeft, + const Vector2 &outTopRight, const Vector2 &outBottomLeft, + const AABB2 &inRect) = 0; virtual void DrawFlatGameMap(const AABB2 &outRect, const AABB2 &inRect) = 0; @@ -154,10 +167,10 @@ namespace spades { virtual void Flip() = 0; /** get a rendered image. */ - virtual Bitmap *ReadBitmap() = 0; + virtual Handle ReadBitmap() = 0; virtual float ScreenWidth() = 0; virtual float ScreenHeight() = 0; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/IWorldListener.h b/Sources/Client/IWorldListener.h index 30ba9f8ca..e762219f3 100644 --- a/Sources/Client/IWorldListener.h +++ b/Sources/Client/IWorldListener.h @@ -20,8 +20,10 @@ #pragma once -#include #include "PhysicsConstants.h" +#include +#include +#include namespace spades { namespace client { @@ -30,32 +32,57 @@ namespace spades { enum class BuildFailureReason { InsufficientBlocks, InvalidPosition }; + /** The caller of `IWorldListener::BulletHitPlayer` may store a derived class instance of + * this class in a supplied cell. + * + * The instance will be destroyed when the world updater completes the hit scan of a single + * unit of firing (i.e., encompassing all pellets in a single shotgun shell). */ + struct IBulletHitScanState { + virtual ~IBulletHitScanState() {} + }; + class IWorldListener { public: virtual void PlayerObjectSet(int playerId) = 0; - virtual void PlayerMadeFootstep(Player *) = 0; - virtual void PlayerJumped(Player *) = 0; - virtual void PlayerLanded(Player *, bool hurt) = 0; - virtual void PlayerFiredWeapon(Player *) = 0; - virtual void PlayerDryFiredWeapon(Player *) = 0; - virtual void PlayerReloadingWeapon(Player *) = 0; - virtual void PlayerReloadedWeapon(Player *) = 0; - virtual void PlayerChangedTool(Player *) = 0; - virtual void PlayerThrownGrenade(Player *, Grenade *) = 0; - virtual void PlayerMissedSpade(Player *) = 0; - virtual void PlayerHitBlockWithSpade(Player *, Vector3 hitPos, IntVector3 blockPos, + virtual void PlayerMadeFootstep(Player &) = 0; + virtual void PlayerJumped(Player &) = 0; + virtual void PlayerLanded(Player &, bool hurt) = 0; + virtual void PlayerFiredWeapon(Player &) = 0; + virtual void PlayerDryFiredWeapon(Player &) = 0; + virtual void PlayerReloadingWeapon(Player &) = 0; + virtual void PlayerReloadedWeapon(Player &) = 0; + virtual void PlayerChangedTool(Player &) = 0; + virtual void PlayerThrewGrenade(Player &, stmp::optional) = 0; + virtual void PlayerMissedSpade(Player &) = 0; + virtual void PlayerHitBlockWithSpade(Player &, Vector3 hitPos, IntVector3 blockPos, IntVector3 normal) = 0; - virtual void PlayerKilledPlayer(Player *killer, Player *victim, KillType) = 0; - virtual void PlayerRestocked(Player *) = 0; + virtual void PlayerKilledPlayer(Player &killer, Player &victim, KillType) = 0; + virtual void PlayerRestocked(Player &) = 0; - virtual void BulletHitPlayer(Player *hurtPlayer, HitType, Vector3 hitPos, - Player *by) = 0; + /** + * This function gets called when a bullet, pellet, or spade hits a player. + * + * @param hurtPlayer The player upon which harm was inflicted. + * @param hitType Indicates the hit type (which body part was hit for a bullet or + * pellet). Will never be `HitTypeBlock`. + * @param hitPos The world coordinates of the point at which the projectile hit the + * player. + * @param by The player who fired the projectile or is in possession of the spade. + * @param stateCell The caller may store an instance of `IBulletHitScanState`'s derive + * class in this cell. It's empty when this function is called for the first time in + * each unit of firing. The cell will be cleared when the world updater completes the + * hit scan of a single unit of firing (i.e., encompassing all pellets in a single + * shotgun shell). + */ + virtual void BulletHitPlayer(Player &hurtPlayer, HitType hitType, Vector3 hitPos, + Player &by, + std::unique_ptr &stateCell) = 0; virtual void BulletHitBlock(Vector3 hitPos, IntVector3 blockPos, IntVector3 normal) = 0; - virtual void AddBulletTracer(Player *player, Vector3 muzzlePos, Vector3 hitPos) = 0; + virtual void AddBulletTracer(Player &player, Vector3 muzzlePos, Vector3 hitPos) = 0; - virtual void GrenadeExploded(Grenade *) = 0; - virtual void GrenadeBounced(Grenade *) = 0; - virtual void GrenadeDroppedIntoWater(Grenade *) = 0; + virtual void GrenadeExploded(const Grenade &) = 0; + virtual void GrenadeBounced(const Grenade &) = 0; + virtual void GrenadeDroppedIntoWater(const Grenade &) = 0; virtual void BlocksFell(std::vector) = 0; @@ -65,5 +92,5 @@ namespace spades { virtual void LocalPlayerHurt(HurtType type, bool sourceGiven, Vector3 source) = 0; virtual void LocalPlayerBuildError(BuildFailureReason reason) = 0; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/LimboView.cpp b/Sources/Client/LimboView.cpp index dce87479e..8d547c0aa 100644 --- a/Sources/Client/LimboView.cpp +++ b/Sources/Client/LimboView.cpp @@ -45,8 +45,8 @@ namespace spades { float menuHeight = menuWidth / 8.f; float rowHeight = menuHeight + 3.f; - float left = (renderer->ScreenWidth() - contentsWidth) * .5f; - float top = renderer->ScreenHeight() - 150.f; + float left = (renderer.ScreenWidth() - contentsWidth) * .5f; + float top = renderer.ScreenHeight() - 150.f; float teamX = left + 10.f; float firstY = top + 35.f; @@ -83,7 +83,7 @@ namespace spades { AABB2(left + contentsWidth - 266.f, firstY + 52.f, 256.f, 48.f), _Tr("Client", "Set For Next Spawn"))); - cursorPos = MakeVector2(renderer->ScreenWidth() * .5f, renderer->ScreenHeight() * .5f); + cursorPos = MakeVector2(renderer.ScreenWidth() * .5f, renderer.ScreenHeight() * .5f); selectedTeam = 2; selectedWeapon = RIFLE_WEAPON; @@ -95,8 +95,8 @@ namespace spades { cursorPos.y = y; // clip - float w = renderer->ScreenWidth(); - float h = renderer->ScreenHeight(); + float w = renderer.ScreenWidth(); + float h = renderer.ScreenHeight(); cursorPos.x = std::max(cursorPos.x, 0.f); cursorPos.y = std::max(cursorPos.y, 0.f); @@ -109,10 +109,10 @@ namespace spades { for (size_t i = 0; i < items.size(); i++) { MenuItem &item = items[i]; if (item.hover) { - IAudioDevice *dev = client->audioDevice; + IAudioDevice &dev = *client->audioDevice; Handle chunk = - dev->RegisterSound("Sounds/Feedback/Limbo/Select.opus"); - dev->PlayLocal(chunk, AudioParam()); + dev.RegisterSound("Sounds/Feedback/Limbo/Select.opus"); + dev.PlayLocal(chunk.GetPointerOrNull(), AudioParam()); switch (item.type) { case MenuTeam1: selectedTeam = 0; break; case MenuTeam2: selectedTeam = 1; break; @@ -174,37 +174,35 @@ namespace spades { if (!item.visible) newHover = false; if (newHover && !item.hover) { - IAudioDevice *dev = client->audioDevice; + IAudioDevice &dev = *client->audioDevice; Handle chunk = - dev->RegisterSound("Sounds/Feedback/Limbo/Hover.opus"); - dev->PlayLocal(chunk, AudioParam()); + dev.RegisterSound("Sounds/Feedback/Limbo/Hover.opus"); + dev.PlayLocal(chunk.GetPointerOrNull(), AudioParam()); } item.hover = newHover; } } void LimboView::Draw() { - Handle menuItemImage = renderer->RegisterImage("Gfx/Limbo/MenuItem.png"); - Handle menuItemBigImage = renderer->RegisterImage("Gfx/Limbo/BigMenuItem.png"); - IFont *font = client->fontManager->GetGuiFont(); + Handle menuItemImage = renderer.RegisterImage("Gfx/Limbo/MenuItem.png"); + Handle menuItemBigImage = renderer.RegisterImage("Gfx/Limbo/BigMenuItem.png"); + IFont &font = client->fontManager->GetGuiFont(); - float left = (renderer->ScreenWidth() - contentsWidth) * .5f; - float top = renderer->ScreenHeight() - 150.f; + float left = (renderer.ScreenWidth() - contentsWidth) * .5f; + float top = renderer.ScreenHeight() - 150.f; { std::string msg = _Tr("Client", "Select Team:"); Vector2 pos; pos.x = left + 10.f; pos.y = top + 10.f; - font->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.4f)); + font.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.4f)); } if (selectedTeam != 2) { std::string msg = _Tr("Client", "Select Weapon:"); Vector2 pos; pos.x = left + 260.f; pos.y = top + 10.f; - font->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.4f)); + font.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.4f)); } for (size_t i = 0; i < items.size(); i++) { @@ -241,47 +239,47 @@ namespace spades { fillColor = MakeVector4(.7f, .7f, .7f, 1.f) * .9f; } - renderer->SetColorAlphaPremultiplied(fillColor); + renderer.SetColorAlphaPremultiplied(fillColor); if (item.type == MenuSpawn || item.type == MenuNextSpawn) { - renderer->DrawImage(menuItemBigImage, item.rect); + renderer.DrawImage(menuItemBigImage, item.rect); std::string msg = item.text; - IFont *bFont = client->fontManager->GetGuiFont(); - Vector2 size = bFont->Measure(msg); + IFont &bFont = client->fontManager->GetGuiFont(); + Vector2 size = bFont.Measure(msg); Vector2 pos; pos.x = item.rect.GetMinX() + (item.rect.GetWidth() - size.x) / 2.f + 2.f; pos.y = item.rect.GetMinY() + (item.rect.GetHeight() - size.y) / 2.f; - bFont->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.4f)); + bFont.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), + MakeVector4(0, 0, 0, 0.4f)); } else { - renderer->DrawImage(menuItemImage, item.rect); + renderer.DrawImage(menuItemImage, item.rect); std::string msg = item.text; if (item.type == MenuTeam1) msg = client->GetWorld()->GetTeam(0).name; if (item.type == MenuTeam2) msg = client->GetWorld()->GetTeam(1).name; - Vector2 size = font->Measure(msg); + Vector2 size = font.Measure(msg); Vector2 pos; pos.x = item.rect.GetMinX() + 5.f; pos.y = item.rect.GetMinY() + (item.rect.GetHeight() - size.y) / 2.f; - font->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.4f)); + font.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), + MakeVector4(0, 0, 0, 0.4f)); if (index > 0) { std::stringstream ss; ss << index; msg = ss.str(); - pos.x = item.rect.GetMaxX() - 5.f - font->Measure(msg).x; - font->DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), - MakeVector4(0, 0, 0, 0.4f)); + pos.x = item.rect.GetMaxX() - 5.f - font.Measure(msg).x; + font.DrawShadow(msg, pos, 1.f, MakeVector4(1, 1, 1, 1), + MakeVector4(0, 0, 0, 0.4f)); } } } - Handle cursor = renderer->RegisterImage("Gfx/Limbo/Cursor.png"); + Handle cursor = renderer.RegisterImage("Gfx/Limbo/Cursor.png"); - renderer->SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1)); - renderer->DrawImage(cursor, AABB2(cursorPos.x - 8, cursorPos.y - 8, 32, 32)); + renderer.SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1)); + renderer.DrawImage(cursor, AABB2(cursorPos.x - 8, cursorPos.y - 8, 32, 32)); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/LimboView.h b/Sources/Client/LimboView.h index 0c0f8aeca..f0e9d540d 100644 --- a/Sources/Client/LimboView.h +++ b/Sources/Client/LimboView.h @@ -22,8 +22,8 @@ #include -#include #include "PhysicsConstants.h" +#include namespace spades { namespace client { @@ -53,7 +53,7 @@ namespace spades { : type(type), rect(rt), text(txt), hover(false) {} }; Client *client; - IRenderer *renderer; + IRenderer &renderer; std::vector items; @@ -77,5 +77,5 @@ namespace spades { void Draw(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/MapView.cpp b/Sources/Client/MapView.cpp index eab0f56ce..9ebe1da07 100644 --- a/Sources/Client/MapView.cpp +++ b/Sources/Client/MapView.cpp @@ -18,6 +18,7 @@ */ +#include #include #include "CTFGameMode.h" @@ -142,7 +143,7 @@ namespace spades { return scrPos; } - void MapView::DrawIcon(spades::Vector3 pos, spades::client::IImage *img, float rotation) { + void MapView::DrawIcon(spades::Vector3 pos, IImage &img, float rotation) { if (pos.x < inRect.GetMinX() || pos.x > inRect.GetMaxX() || pos.y < inRect.GetMinY() || pos.y > inRect.GetMaxY()) return; @@ -155,8 +156,8 @@ namespace spades { float c = rotation != 0.f ? cosf(rotation) : 1.f; float s = rotation != 0.f ? sinf(rotation) : 0.f; static const float coords[][2] = {{-1, -1}, {1, -1}, {-1, 1}}; - Vector2 u = MakeVector2(img->GetWidth() * .5f, 0.f); - Vector2 v = MakeVector2(0.f, img->GetHeight() * .5f); + Vector2 u = MakeVector2(img.GetWidth() * .5f, 0.f); + Vector2 v = MakeVector2(0.f, img.GetHeight() * .5f); Vector2 vt[3]; for (int i = 0; i < 3; i++) { @@ -165,8 +166,8 @@ namespace spades { vt[i].y = scrPos.y + ss.x * s + ss.y * c; } - renderer->DrawImage(img, vt[0], vt[1], vt[2], - AABB2(0, 0, img->GetWidth(), img->GetHeight())); + renderer.DrawImage(img, vt[0], vt[1], vt[2], + AABB2(0, 0, img.GetWidth(), img.GetHeight())); } void MapView::SwitchScale() { @@ -242,7 +243,7 @@ namespace spades { return; // The player to focus on - Player *focusPlayerPtr = nullptr; + stmp::optional focusPlayerPtr; Vector3 focusPlayerPos; float focusPlayerAngle; @@ -253,7 +254,7 @@ namespace spades { focusPlayerPos = player.GetPosition(); focusPlayerAngle = atan2(front.x, -front.y); - focusPlayerPtr = &player; + focusPlayerPtr = player; } else if (client->GetCameraMode() == ClientCameraMode::Free) { focusPlayerPos = client->freeCameraState.position; focusPlayerAngle = @@ -267,16 +268,16 @@ namespace spades { if (!world->GetLocalPlayer()) { return; } - Player &localPlayer = *world->GetLocalPlayer(); + Player &localPlayer = world->GetLocalPlayer().value(); - SPAssert(focusPlayerPtr); - Player &focusPlayer = *focusPlayerPtr; + Player &focusPlayer = focusPlayerPtr.value(); if (largeMap) if (zoomState < .0001f) return; - GameMap *map = world->GetMap(); + Handle map = world->GetMap(); + SPAssert(map); Vector2 mapSize = MakeVector2(map->Width(), map->Height()); Vector2 center = {focusPlayerPos.x, focusPlayerPos.y}; @@ -291,7 +292,7 @@ namespace spades { center = Mix(center, mapSize * .5f, zoomState); Vector2 zoomedSize = {512, 512}; - if (renderer->ScreenWidth() < 512.f || renderer->ScreenHeight() < 512.f) + if (renderer.ScreenWidth() < 512.f || renderer.ScreenHeight() < 512.f) zoomedSize = MakeVector2(256, 256); if (largeMap) { float per = zoomState; @@ -319,13 +320,13 @@ namespace spades { inRect = inRect.Translated(0, mapSize.y - inRect.GetMaxY()); } - AABB2 outRect(renderer->ScreenWidth() - mapWndSize.x - 16.f, 16.f, mapWndSize.x, + AABB2 outRect(renderer.ScreenWidth() - mapWndSize.x - 16.f, 16.f, mapWndSize.x, mapWndSize.y); if (largeMap) { - outRect.min = MakeVector2((renderer->ScreenWidth() - zoomedSize.x) * .5f, - (renderer->ScreenHeight() - zoomedSize.y) * .5f); - outRect.max = MakeVector2((renderer->ScreenWidth() + zoomedSize.x) * .5f, - (renderer->ScreenHeight() + zoomedSize.y) * .5f); + outRect.min = MakeVector2((renderer.ScreenWidth() - zoomedSize.x) * .5f, + (renderer.ScreenHeight() - zoomedSize.y) * .5f); + outRect.max = MakeVector2((renderer.ScreenWidth() + zoomedSize.x) * .5f, + (renderer.ScreenHeight() + zoomedSize.y) * .5f); } float alpha = 1.f; @@ -335,11 +336,11 @@ namespace spades { // fades bg if (largeMap) { - Handle bg = renderer->RegisterImage("Gfx/MapBg.png"); - Vector2 scrSize = {renderer->ScreenWidth(), renderer->ScreenHeight()}; + Handle bg = renderer.RegisterImage("Gfx/MapBg.png"); + Vector2 scrSize = {renderer.ScreenWidth(), renderer.ScreenHeight()}; float size = std::max(scrSize.x, scrSize.y); - renderer->SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, alpha * .5f)); - renderer->DrawImage( + renderer.SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, alpha * .5f)); + renderer.DrawImage( bg, AABB2((scrSize.x - size) * .5f, (scrSize.y - size) * .5f, size, size)); } @@ -348,60 +349,60 @@ namespace spades { float borderWidth; AABB2 borderRect = outRect; if (largeMap) { - border = renderer->RegisterImage("Gfx/MapBorder.png"); + border = renderer.RegisterImage("Gfx/MapBorder.png"); borderWidth = 3.f * outRect.GetHeight() / zoomedSize.y; } else { - border = renderer->RegisterImage("Gfx/MinimapBorder.png"); + border = renderer.RegisterImage("Gfx/MinimapBorder.png"); borderWidth = 2.f; } borderRect = borderRect.Inflate(borderWidth - 8.f); - renderer->SetColorAlphaPremultiplied(MakeVector4(alpha, alpha, alpha, alpha)); - renderer->DrawImage(border, - AABB2(borderRect.GetMinX() - 16, borderRect.GetMinY() - 16, 16, 16), - AABB2(0, 0, 16, 16)); - renderer->DrawImage(border, - AABB2(borderRect.GetMaxX(), borderRect.GetMinY() - 16, 16, 16), - AABB2(16, 0, 16, 16)); - renderer->DrawImage(border, - AABB2(borderRect.GetMinX() - 16, borderRect.GetMaxY(), 16, 16), - AABB2(0, 16, 16, 16)); - renderer->DrawImage(border, AABB2(borderRect.GetMaxX(), borderRect.GetMaxY(), 16, 16), - AABB2(16, 16, 16, 16)); - renderer->DrawImage( + renderer.SetColorAlphaPremultiplied(MakeVector4(alpha, alpha, alpha, alpha)); + renderer.DrawImage(border, + AABB2(borderRect.GetMinX() - 16, borderRect.GetMinY() - 16, 16, 16), + AABB2(0, 0, 16, 16)); + renderer.DrawImage(border, + AABB2(borderRect.GetMaxX(), borderRect.GetMinY() - 16, 16, 16), + AABB2(16, 0, 16, 16)); + renderer.DrawImage(border, + AABB2(borderRect.GetMinX() - 16, borderRect.GetMaxY(), 16, 16), + AABB2(0, 16, 16, 16)); + renderer.DrawImage(border, AABB2(borderRect.GetMaxX(), borderRect.GetMaxY(), 16, 16), + AABB2(16, 16, 16, 16)); + renderer.DrawImage( border, AABB2(borderRect.GetMinX(), borderRect.GetMinY() - 16, borderRect.GetWidth(), 16), AABB2(16, 0, 0, 16)); - renderer->DrawImage( + renderer.DrawImage( border, AABB2(borderRect.GetMinX(), borderRect.GetMaxY(), borderRect.GetWidth(), 16), AABB2(16, 16, 0, 16)); - renderer->DrawImage( + renderer.DrawImage( border, AABB2(borderRect.GetMinX() - 16, borderRect.GetMinY(), 16, borderRect.GetHeight()), AABB2(0, 16, 16, 0)); - renderer->DrawImage( + renderer.DrawImage( border, AABB2(borderRect.GetMaxX(), borderRect.GetMinY(), 16, borderRect.GetHeight()), AABB2(16, 16, 16, 0)); // draw map - renderer->SetColorAlphaPremultiplied(MakeVector4(alpha, alpha, alpha, alpha)); - renderer->DrawFlatGameMap(outRect, inRect); + renderer.SetColorAlphaPremultiplied(MakeVector4(alpha, alpha, alpha, alpha)); + renderer.DrawFlatGameMap(outRect, inRect); this->inRect = inRect; this->outRect = outRect; // draw grid - renderer->SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 0.8f * alpha)); - Handle dashLine = renderer->RegisterImage("Gfx/DashLine.tga"); + renderer.SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 0.8f * alpha)); + Handle dashLine = renderer.RegisterImage("Gfx/DashLine.tga"); for (float x = 64.f; x < map->Width(); x += 64.f) { float wx = (x - inRect.GetMinX()) / inRect.GetWidth(); if (wx < 0.f || wx >= 1.f) continue; wx = (wx * outRect.GetWidth()) + outRect.GetMinX(); wx = roundf(wx); - renderer->DrawImage(dashLine, MakeVector2(wx, outRect.GetMinY()), - AABB2(0, 0, 1.f, outRect.GetHeight())); + renderer.DrawImage(dashLine, MakeVector2(wx, outRect.GetMinY()), + AABB2(0, 0, 1.f, outRect.GetHeight())); } for (float y = 64.f; y < map->Height(); y += 64.f) { float wy = (y - inRect.GetMinY()) / inRect.GetHeight(); @@ -409,13 +410,13 @@ namespace spades { continue; wy = (wy * outRect.GetHeight()) + outRect.GetMinY(); wy = roundf(wy); - renderer->DrawImage(dashLine, MakeVector2(outRect.GetMinX(), wy), - AABB2(0, 0, outRect.GetWidth(), 1.f)); + renderer.DrawImage(dashLine, MakeVector2(outRect.GetMinX(), wy), + AABB2(0, 0, outRect.GetWidth(), 1.f)); } // draw grid label - renderer->SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1) * (0.8f * alpha)); - Handle mapFont = renderer->RegisterImage("Gfx/Fonts/MapFont.tga"); + renderer.SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1) * (0.8f * alpha)); + Handle mapFont = renderer.RegisterImage("Gfx/Fonts/MapFont.tga"); for (int i = 0; i < 8; i++) { float startX = (float)i * 64.f; float endX = startX + 64.f; @@ -425,8 +426,7 @@ namespace spades { std::min((std::min(endX, inRect.GetMaxX()) - std::max(startX, inRect.GetMinX())) / (endX - startX) * 2.f, 1.f); - renderer->SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1) * - (fade * .8f * alpha)); + renderer.SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1) * (fade * .8f * alpha)); float center = std::max(startX, inRect.GetMinX()); center = .5f * (center + std::min(endX, inRect.GetMaxX())); @@ -437,8 +437,8 @@ namespace spades { float fntX = static_cast((i & 3) * 8); float fntY = static_cast((i >> 2) * 8); - renderer->DrawImage(mapFont, MakeVector2(wx - 4.f, outRect.GetMinY() + 4), - AABB2(fntX, fntY, 8, 8)); + renderer.DrawImage(mapFont, MakeVector2(wx - 4.f, outRect.GetMinY() + 4), + AABB2(fntX, fntY, 8, 8)); } for (int i = 0; i < 8; i++) { float startY = (float)i * 64.f; @@ -449,8 +449,7 @@ namespace spades { std::min((std::min(endY, inRect.GetMaxY()) - std::max(startY, inRect.GetMinY())) / (endY - startY) * 2.f, 1.f); - renderer->SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1) * - (fade * .8f * alpha)); + renderer.SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1) * (fade * .8f * alpha)); float center = std::max(startY, inRect.GetMinY()); center = .5f * (center + std::min(endY, inRect.GetMaxY())); @@ -461,148 +460,153 @@ namespace spades { int fntX = (i & 3) * 8; int fntY = (i >> 2) * 8 + 16; - renderer->DrawImage(mapFont, MakeVector2(outRect.GetMinX() + 4, wy - 4.f), - AABB2(fntX, fntY, 8, 8)); + renderer.DrawImage(mapFont, MakeVector2(outRect.GetMinX() + 4, wy - 4.f), + AABB2(fntX, fntY, 8, 8)); } // draw objects const int iconMode = cg_minimapPlayerIcon; const int colorMode = cg_minimapPlayerColor; - Handle playerSMG = renderer->RegisterImage("Gfx/Map/SMG.png"); - Handle playerRifle = renderer->RegisterImage("Gfx/Map/Rifle.png"); - Handle playerShotgun = renderer->RegisterImage("Gfx/Map/Shotgun.png"); - Handle playerIcon = renderer->RegisterImage("Gfx/Map/Player.png"); - Handle viewIcon = renderer->RegisterImage("Gfx/Map/View.png"); + Handle playerSMG = renderer.RegisterImage("Gfx/Map/SMG.png"); + Handle playerRifle = renderer.RegisterImage("Gfx/Map/Rifle.png"); + Handle playerShotgun = renderer.RegisterImage("Gfx/Map/Shotgun.png"); + Handle playerIcon = renderer.RegisterImage("Gfx/Map/Player.png"); + Handle viewIcon = renderer.RegisterImage("Gfx/Map/View.png"); // draw player's icon for (int i = 0; i < world->GetNumPlayerSlots(); i++) { - Player *p = world->GetPlayer(i); - if (!p || !p->IsAlive()) { + auto maybePlayer = world->GetPlayer(i); + if (!maybePlayer) { + continue; + } + + Player &p = maybePlayer.value(); + if (!p.IsAlive()) { // The player is non-existent or dead continue; } - if (!localPlayer.IsSpectator() && localPlayer.GetTeamId() != p->GetTeamId()) { + if (!localPlayer.IsSpectator() && localPlayer.GetTeamId() != p.GetTeamId()) { // Duh continue; } - if (p->IsSpectator() && p == &localPlayer && + if (p.IsSpectator() && &p == &localPlayer && HasTargetPlayer(client->GetCameraMode())) { // Don't draw white icon when spectating a player continue; } - if (p->IsSpectator() && p != &localPlayer) { + if (p.IsSpectator() && &p != &localPlayer) { // Don't draw other spectators continue; } IntVector3 iconColor = colorMode ? IntVector3::Make(palette[i][0], palette[i][1], palette[i][2]) - : world->GetTeam(p->GetTeamId()).color; - if (p->GetTeamId() >= 2) + : world->GetTeam(p.GetTeamId()).color; + if (p.GetTeamId() >= 2) iconColor = IntVector3::Make(200, 200, 200); // colorMode doesn't matter here, right? Vector4 iconColorF = ModifyColor(iconColor); iconColorF *= alpha; - Vector3 front = p->GetFront2D(); + Vector3 front = p.GetFront2D(); float ang = atan2(front.x, -front.y); - if (p->IsSpectator() && client->GetCameraMode() == ClientCameraMode::Free) { + if (p.IsSpectator() && client->GetCameraMode() == ClientCameraMode::Free) { ang = focusPlayerAngle; } // Draw the focused player's view - if (p == &focusPlayer) { - renderer->SetColorAlphaPremultiplied(iconColorF * 0.9f); - DrawIcon(p->IsSpectator() ? client->freeCameraState.position : p->GetPosition(), - viewIcon, ang); + if (&p == &focusPlayer) { + renderer.SetColorAlphaPremultiplied(iconColorF * 0.9f); + DrawIcon(p.IsSpectator() ? client->freeCameraState.position : p.GetPosition(), + *viewIcon, ang); } - renderer->SetColorAlphaPremultiplied(iconColorF); + renderer.SetColorAlphaPremultiplied(iconColorF); // use a different icon in minimap according to weapon of player if (iconMode) { WeaponType weapon = world->GetPlayer(i)->GetWeaponType(); if (weapon == WeaponType::SMG_WEAPON) { - DrawIcon(p->IsSpectator() ? client->freeCameraState.position - : p->GetPosition(), - playerSMG, ang); + DrawIcon(p.IsSpectator() ? client->freeCameraState.position + : p.GetPosition(), + *playerSMG, ang); } else if (weapon == WeaponType::RIFLE_WEAPON) { - DrawIcon(p->IsSpectator() ? client->freeCameraState.position - : p->GetPosition(), - playerRifle, ang); + DrawIcon(p.IsSpectator() ? client->freeCameraState.position + : p.GetPosition(), + *playerRifle, ang); } else if (weapon == WeaponType::SHOTGUN_WEAPON) { - DrawIcon(p->IsSpectator() ? client->freeCameraState.position - : p->GetPosition(), - playerShotgun, ang); + DrawIcon(p.IsSpectator() ? client->freeCameraState.position + : p.GetPosition(), + *playerShotgun, ang); } } else { // draw normal color - DrawIcon(p == &focusPlayer ? focusPlayerPos : p->GetPosition(), playerIcon, + DrawIcon(&p == &focusPlayer ? focusPlayerPos : p.GetPosition(), *playerIcon, ang); } } - IGameMode *mode = world->GetMode(); + stmp::optional mode = world->GetMode(); if (mode && IGameMode::m_CTF == mode->ModeType()) { - CTFGameMode *ctf = static_cast(mode); - Handle intelIcon = renderer->RegisterImage("Gfx/Map/Intel.png"); - Handle baseIcon = renderer->RegisterImage("Gfx/Map/CommandPost.png"); + CTFGameMode &ctf = dynamic_cast(*mode); + Handle intelIcon = renderer.RegisterImage("Gfx/Map/Intel.png"); + Handle baseIcon = renderer.RegisterImage("Gfx/Map/CommandPost.png"); for (int tId = 0; tId < 2; tId++) { - CTFGameMode::Team &team = ctf->GetTeam(tId); + CTFGameMode::Team &team = ctf.GetTeam(tId); IntVector3 teamColor = world->GetTeam(tId).color; Vector4 teamColorF = ModifyColor(teamColor); teamColorF *= alpha; // draw base - renderer->SetColorAlphaPremultiplied(teamColorF); - DrawIcon(team.basePos, baseIcon, 0.f); + renderer.SetColorAlphaPremultiplied(teamColorF); + DrawIcon(team.basePos, *baseIcon, 0.f); // draw flag - if (!ctf->GetTeam(1 - tId).hasIntel) { - renderer->SetColorAlphaPremultiplied(teamColorF); - DrawIcon(team.flagPos, intelIcon, 0.f); + if (!ctf.GetTeam(1 - tId).hasIntel) { + renderer.SetColorAlphaPremultiplied(teamColorF); + DrawIcon(team.flagPos, *intelIcon, 0.f); } else if (world->GetLocalPlayer()->GetTeamId() == 1 - tId) { // local player's team is carrying - int cId = ctf->GetTeam(1 - tId).carrier; + int cId = ctf.GetTeam(1 - tId).carrier; // in some game modes, carrier becomes invalid if (cId < world->GetNumPlayerSlots()) { - Player *carrier = world->GetPlayer(cId); + auto carrier = world->GetPlayer(cId); if (carrier && carrier->GetTeamId() == world->GetLocalPlayer()->GetTeamId()) { Vector4 col = teamColorF; col *= fabsf(sinf(world->GetTime() * 4.f)); - renderer->SetColorAlphaPremultiplied(col); - DrawIcon(carrier->GetPosition(), intelIcon, 0.f); + renderer.SetColorAlphaPremultiplied(col); + DrawIcon(carrier->GetPosition(), *intelIcon, 0.f); } } } } } else if (mode && IGameMode::m_TC == mode->ModeType()) { - TCGameMode *tc = static_cast(mode); - Handle icon = renderer->RegisterImage("Gfx/Map/CommandPost.png"); - int cnt = tc->GetNumTerritories(); + TCGameMode &tc = dynamic_cast(*mode); + Handle icon = renderer.RegisterImage("Gfx/Map/CommandPost.png"); + int cnt = tc.GetNumTerritories(); for (int i = 0; i < cnt; i++) { - TCGameMode::Territory *t = tc->GetTerritory(i); + TCGameMode::Territory &t = tc.GetTerritory(i); IntVector3 teamColor = {128, 128, 128}; - if (t->ownerTeamId < 2) { - teamColor = world->GetTeam(t->ownerTeamId).color; + if (t.ownerTeamId < 2) { + teamColor = world->GetTeam(t.ownerTeamId).color; } Vector4 teamColorF = ModifyColor(teamColor); teamColorF *= alpha; // draw base - renderer->SetColorAlphaPremultiplied(teamColorF); - DrawIcon(t->pos, icon, 0.f); + renderer.SetColorAlphaPremultiplied(teamColorF); + DrawIcon(t.pos, *icon, 0.f); } } // draw tracers - Handle tracerImage = renderer->RegisterImage("Gfx/Ball.png"); + Handle tracerImage = renderer.RegisterImage("Gfx/Ball.png"); const float tracerWidth = 2.0f; const AABB2 tracerInRect{0.0f, 0.0f, tracerImage->GetWidth(), tracerImage->GetHeight()}; @@ -641,9 +645,9 @@ namespace spades { line3.first + normal * tracerWidth, line3.second - normal * tracerWidth}; - renderer->SetColorAlphaPremultiplied(Vector4{1.0f, 0.8f, 0.6f, 1.0f} * alpha); - renderer->DrawImage(tracerImage, vertices[0], vertices[1], vertices[2], - tracerInRect); + renderer.SetColorAlphaPremultiplied(Vector4{1.0f, 0.8f, 0.6f, 1.0f} * alpha); + renderer.DrawImage(tracerImage, vertices[0], vertices[1], vertices[2], + tracerInRect); } } } @@ -665,7 +669,12 @@ namespace spades { visibleLength = shutterTime * velocity; curDistance = -visibleLength; - curDistance += maxTimeSpread * SampleRandomFloat(); + + // Randomize the starting position within the range of the shutter + // time. However, make sure the tracer is displayed for at least + // one frame. + curDistance += + std::min(length + visibleLength, maxTimeSpread * SampleRandomFloat() * velocity); firstUpdate = true; } diff --git a/Sources/Client/MapView.h b/Sources/Client/MapView.h index 359c93982..b93154e80 100644 --- a/Sources/Client/MapView.h +++ b/Sources/Client/MapView.h @@ -34,7 +34,7 @@ namespace spades { class IImage; class MapView { Client *client; - IRenderer *renderer; + IRenderer &renderer; int scaleMode; float actualScale; @@ -50,7 +50,7 @@ namespace spades { Vector2 Project(const Vector2 &) const; - void DrawIcon(Vector3 pos, IImage *img, float rotation); + void DrawIcon(Vector3 pos, IImage &img, float rotation); public: MapView(Client *, bool largeMap); @@ -79,5 +79,5 @@ namespace spades { stmp::optional> GetLineSegment(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/MumbleLink.cpp b/Sources/Client/MumbleLink.cpp index a0279d5ff..7121ea6ad 100644 --- a/Sources/Client/MumbleLink.cpp +++ b/Sources/Client/MumbleLink.cpp @@ -143,4 +143,4 @@ namespace spades { set_mumble_vector3(mumbleLinkedMemory->fCameraFront, player->GetFront()); set_mumble_vector3(mumbleLinkedMemory->fCameraTop, player->GetUp()); } -} +} // namespace spades diff --git a/Sources/Client/MumbleLink.h b/Sources/Client/MumbleLink.h index fbe6998a7..51efe067d 100644 --- a/Sources/Client/MumbleLink.h +++ b/Sources/Client/MumbleLink.h @@ -5,23 +5,23 @@ #include "Player.h" namespace spades { - struct MumbleLinkedMemory; - struct MumbleLinkPrivate; + struct MumbleLinkedMemory; + struct MumbleLinkPrivate; - class MumbleLink { - const float metre_per_block; - MumbleLinkedMemory *mumbleLinkedMemory; - std::unique_ptr priv; + class MumbleLink { + const float metre_per_block; + MumbleLinkedMemory *mumbleLinkedMemory; + std::unique_ptr priv; - void set_mumble_vector3(float mumble_vec[3], const spades::Vector3 &vec); + void set_mumble_vector3(float mumble_vec[3], const spades::Vector3 &vec); - public: - MumbleLink(); - ~MumbleLink(); + public: + MumbleLink(); + ~MumbleLink(); - bool init(); - void setContext(const std::string &context); - void setIdentity(const std::string &identity); - void update(spades::client::Player *player); - }; -} + bool init(); + void setContext(const std::string &context); + void setIdentity(const std::string &identity); + void update(spades::client::Player *player); + }; +} // namespace spades diff --git a/Sources/Client/NetClient.cpp b/Sources/Client/NetClient.cpp index 81dfa2bc7..e2cc31c46 100644 --- a/Sources/Client/NetClient.cpp +++ b/Sources/Client/NetClient.cpp @@ -29,15 +29,14 @@ #include "Client.h" #include "GameMap.h" #include "GameMapLoader.h" +#include "GameProperties.h" #include "Grenade.h" #include "NetClient.h" #include "Player.h" #include "TCGameMode.h" #include "World.h" -#include "GameProperties.h" #include #include -#include #include #include #include @@ -88,6 +87,7 @@ namespace spades { PacketTypeWeaponReload = 28, // C2S2P PacketTypeChangeTeam = 29, // C2S2P PacketTypeChangeWeapon = 30, // C2S2P + PacketTypeMapCached = 31, // S2C PacketTypeHandShakeInit = 31, // S2C PacketTypeHandShakeReturn = 32, // C2S PacketTypeVersionGet = 33, // S2C @@ -132,7 +132,7 @@ namespace spades { } return CP437::Decode(s); } - } + } // namespace class NetPacketReader { std::vector data; @@ -378,7 +378,6 @@ namespace spades { savedPlayerPos.resize(128); savedPlayerFront.resize(128); savedPlayerTeam.resize(128); - playerPosRecords.resize(128); std::fill(savedPlayerTeam.begin(), savedPlayerTeam.end(), -1); @@ -626,9 +625,9 @@ namespace spades { } } - World *NetClient::GetWorld() { return client->GetWorld(); } + stmp::optional NetClient::GetWorld() { return client->GetWorld(); } - Player *NetClient::GetPlayerOrNull(int pId) { + stmp::optional NetClient::GetPlayerOrNull(int pId) { SPADES_MARK_FUNCTION(); if (!GetWorld()) SPRaise("Invalid Player ID %d: No world", pId); @@ -636,7 +635,7 @@ namespace spades { return NULL; return GetWorld()->GetPlayer(pId); } - Player *NetClient::GetPlayer(int pId) { + Player &NetClient::GetPlayer(int pId) { SPADES_MARK_FUNCTION(); if (!GetWorld()) SPRaise("Invalid Player ID %d: No world", pId); @@ -644,19 +643,19 @@ namespace spades { SPRaise("Invalid Player ID %d: Out of range", pId); if (!GetWorld()->GetPlayer(pId)) SPRaise("Invalid Player ID %d: Doesn't exist", pId); - return GetWorld()->GetPlayer(pId); + return GetWorld()->GetPlayer(pId).value(); } - Player *NetClient::GetLocalPlayer() { + Player &NetClient::GetLocalPlayer() { SPADES_MARK_FUNCTION(); if (!GetWorld()) SPRaise("Failed to get local player: no world"); if (!GetWorld()->GetLocalPlayer()) SPRaise("Failed to get local player: no local player"); - return GetWorld()->GetLocalPlayer(); + return GetWorld()->GetLocalPlayer().value(); } - Player *NetClient::GetLocalPlayerOrNull() { + stmp::optional NetClient::GetLocalPlayerOrNull() { SPADES_MARK_FUNCTION(); if (!GetWorld()) SPRaise("Failed to get local player: no world"); @@ -725,7 +724,7 @@ namespace spades { int ext_count = reader.ReadByte(); for (int i = 0; i < ext_count; i++) { int ext_id = reader.ReadByte(); - int ext_version = reader.ReadByte(); + // int ext_version = reader.ReadByte(); auto got = implementedExtensions.find(ext_id); @@ -744,7 +743,7 @@ namespace spades { switch (reader.GetType()) { case PacketTypePositionData: { - Player *p = GetLocalPlayer(); + Player &p = GetLocalPlayer(); Vector3 pos; if (reader.GetData().size() < 12) { // sometimes 00 00 00 00 packet is sent. @@ -754,15 +753,15 @@ namespace spades { pos.x = reader.ReadFloat(); pos.y = reader.ReadFloat(); pos.z = reader.ReadFloat(); - p->SetPosition(pos); + p.SetPosition(pos); } break; case PacketTypeOrientationData: { - Player *p = GetLocalPlayer(); + Player &p = GetLocalPlayer(); Vector3 pos; pos.x = reader.ReadFloat(); pos.y = reader.ReadFloat(); pos.z = reader.ReadFloat(); - p->SetOrientation(pos); + p.SetOrientation(pos); } break; case PacketTypeWorldUpdate: { // reader.DumpDebug(); @@ -789,11 +788,10 @@ namespace spades { front.y = reader.ReadFloat(); front.z = reader.ReadFloat(); - savedPlayerPos[idx] = pos; - savedPlayerFront[idx] = front; + savedPlayerPos.at(idx) = pos; + savedPlayerFront.at(idx) = front; if (pos.x != 0.f || pos.y != 0.f || pos.z != 0.f || front.x != 0.f || front.y != 0.f || front.z != 0.f) { - Player *p; SPAssert(!std::isnan(pos.x)); SPAssert(!std::isnan(pos.y)); SPAssert(!std::isnan(pos.z)); @@ -802,24 +800,11 @@ namespace spades { SPAssert(!std::isnan(front.z)); SPAssert(front.GetLength() < 40.f); if (GetWorld()) { - p = GetWorld()->GetPlayer(idx); + auto p = GetWorld()->GetPlayer(idx); if (p) { if (p != GetWorld()->GetLocalPlayer()) { p->SetPosition(pos); p->SetOrientation(front); - - PosRecord &rec = playerPosRecords[idx]; - if (rec.valid) { - float timespan = GetWorld()->GetTime() - rec.time; - timespan = std::max(0.16f, timespan); - Vector3 vel = (pos - rec.pos) / timespan; - vel *= 1.f / 32.f; - p->SetVelocity(vel); - } - - rec.valid = true; - rec.pos = pos; - rec.time = GetWorld()->GetTime(); } } } @@ -832,22 +817,19 @@ namespace spades { break; { int pId = reader.ReadByte(); - Player *p = GetPlayer(pId); + Player &p = GetPlayer(pId); PlayerInput inp = ParsePlayerInput(reader.ReadByte()); - if (GetWorld()->GetLocalPlayer() == p) { + if (GetWorld()->GetLocalPlayer() == &p) { // handle "/fly" jump if (inp.jump) { - if (!p) { - SPRaise("Local player is null"); - } - p->ForceJump(); + p.ForceJump(); } break; } - p->SetInput(inp); + p.SetInput(inp); } break; @@ -856,27 +838,27 @@ namespace spades { break; { int pId = reader.ReadByte(); - Player *p = GetPlayer(pId); + Player &p = GetPlayer(pId); WeaponInput inp = ParseWeaponInput(reader.ReadByte()); if (GetWorld()->GetLocalPlayer() == p) break; - p->SetWeaponInput(inp); + p.SetWeaponInput(inp); } break; // Hit Packet is Client-to-Server! case PacketTypeSetHP: { - Player *p = GetLocalPlayer(); + Player &p = GetLocalPlayer(); int hp = reader.ReadByte(); int type = reader.ReadByte(); // 0=fall, 1=weap Vector3 hurtPos; hurtPos.x = reader.ReadFloat(); hurtPos.y = reader.ReadFloat(); hurtPos.z = reader.ReadFloat(); - p->SetHP(hp, type ? HurtTypeWeapon : HurtTypeFall, hurtPos); + p.SetHP(hp, type ? HurtTypeWeapon : HurtTypeFall, hurtPos); } break; case PacketTypeGrenadePacket: @@ -900,24 +882,24 @@ namespace spades { break; }*/ - Grenade *g = new Grenade(GetWorld(), pos, vel, fuseLen); - GetWorld()->AddGrenade(g); + Grenade *g = new Grenade(*GetWorld(), pos, vel, fuseLen); + GetWorld()->AddGrenade(std::unique_ptr{g}); } break; case PacketTypeSetTool: { - Player *p = GetPlayer(reader.ReadByte()); + Player &p = GetPlayer(reader.ReadByte()); int tool = reader.ReadByte(); switch (tool) { - case 0: p->SetTool(Player::ToolSpade); break; - case 1: p->SetTool(Player::ToolBlock); break; - case 2: p->SetTool(Player::ToolWeapon); break; - case 3: p->SetTool(Player::ToolGrenade); break; + case 0: p.SetTool(Player::ToolSpade); break; + case 1: p.SetTool(Player::ToolBlock); break; + case 2: p.SetTool(Player::ToolWeapon); break; + case 3: p.SetTool(Player::ToolGrenade); break; default: SPRaise("Received invalid tool type: %d", tool); } } break; case PacketTypeSetColour: { - Player *p = GetPlayerOrNull(reader.ReadByte()); + stmp::optional p = GetPlayerOrNull(reader.ReadByte()); IntVector3 col = reader.ReadIntColor(); if (p) p->SetHeldBlockColor(col); @@ -945,12 +927,11 @@ namespace spades { default: SPRaise("Received invalid weapon: %d", weapon); } - Player *p = new Player(GetWorld(), pId, wType, team, savedPlayerPos[pId], - GetWorld()->GetTeam(team).color); + auto p = stmp::make_unique(*GetWorld(), pId, wType, team, + savedPlayerPos[pId], + GetWorld()->GetTeam(team).color); p->SetHeldBlockColor(color); // p->SetOrientation(savedPlayerFront[pId]); - GetWorld()->SetPlayer(pId, p); - switch (tool) { case 0: p->SetTool(Player::ToolSpade); break; case 1: p->SetTool(Player::ToolBlock); break; @@ -958,6 +939,7 @@ namespace spades { case 3: p->SetTool(Player::ToolGrenade); break; default: SPRaise("Received invalid tool type: %d", tool); } + GetWorld()->SetPlayer(pId, std::move(p)); World::PlayerPersistent &pers = GetWorld()->GetPlayerPersistent(pId); pers.name = name; @@ -978,20 +960,20 @@ namespace spades { pos.y = reader.ReadFloat(); pos.z = reader.ReadFloat(); - IGameMode *mode = GetWorld()->GetMode(); + stmp::optional mode = GetWorld()->GetMode(); if (mode && IGameMode::m_CTF == mode->ModeType()) { - CTFGameMode *ctf = static_cast(mode); + auto &ctf = dynamic_cast(mode.value()); switch (type) { - case BLUE_BASE: ctf->GetTeam(0).basePos = pos; break; - case BLUE_FLAG: ctf->GetTeam(0).flagPos = pos; break; - case GREEN_BASE: ctf->GetTeam(1).basePos = pos; break; - case GREEN_FLAG: ctf->GetTeam(1).flagPos = pos; break; + case BLUE_BASE: ctf.GetTeam(0).basePos = pos; break; + case BLUE_FLAG: ctf.GetTeam(0).flagPos = pos; break; + case GREEN_BASE: ctf.GetTeam(1).basePos = pos; break; + case GREEN_FLAG: ctf.GetTeam(1).flagPos = pos; break; } } else if (mode && IGameMode::m_TC == mode->ModeType()) { - TCGameMode *tc = static_cast(mode); - if (type >= tc->GetNumTerritories()) { + auto &tc = dynamic_cast(mode.value()); + if (type >= tc.GetNumTerritories()) { SPRaise("Invalid territory id specified: %d (max = %d)", (int)type, - tc->GetNumTerritories() - 1); + tc.GetNumTerritories() - 1); } if (state > 2) { @@ -999,9 +981,9 @@ namespace spades { (int)state); } - TCGameMode::Territory *t = tc->GetTerritory(type); - t->pos = pos; - t->ownerTeamId = state; /* + TCGameMode::Territory &t = tc.GetTerritory(type); + t.pos = pos; + t.ownerTeamId = state; /* t->progressBasePos = 0.f; t->progressRate = 0.f; t->progressStartTime = 0.f; @@ -1035,44 +1017,36 @@ namespace spades { default: SPRaise("Received invalid weapon: %d", weapon); } - Player *p = new Player(GetWorld(), pId, wType, team, savedPlayerPos[pId], - - GetWorld()->GetTeam(team).color); + auto p = + stmp::make_unique(*GetWorld(), pId, wType, team, savedPlayerPos[pId], + GetWorld()->GetTeam(team).color); p->SetPosition(pos); - GetWorld()->SetPlayer(pId, p); + GetWorld()->SetPlayer(pId, std::move(p)); + + Player &pRef = GetWorld()->GetPlayer(pId).value(); World::PlayerPersistent &pers = GetWorld()->GetPlayerPersistent(pId); if (!name.empty()) // sometimes becomes empty pers.name = name; - playerPosRecords[pId].valid = false; - if (pId == GetWorld()->GetLocalPlayerIndex()) { client->LocalPlayerCreated(); lastPlayerInput = 0xffffffff; lastWeaponInput = 0xffffffff; SendHeldBlockColor(); // ensure block color synchronized } else { - if (team < 2 && pId < (int)playerPosRecords.size()) { - PosRecord &rec = playerPosRecords[pId]; - - rec.valid = true; - rec.pos = pos; - rec.time = GetWorld()->GetTime(); - } if (savedPlayerTeam[pId] != team) { - - client->PlayerJoinedTeam(p); + client->PlayerJoinedTeam(pRef); savedPlayerTeam[pId] = team; } } - client->PlayerSpawned(p); + client->PlayerSpawned(pRef); } break; case PacketTypeBlockAction: { - Player *p = GetPlayerOrNull(reader.ReadByte()); + stmp::optional p = GetPlayerOrNull(reader.ReadByte()); int action = reader.ReadByte(); IntVector3 pos; pos.x = reader.ReadInt(); @@ -1086,7 +1060,7 @@ namespace spades { GetWorld()->CreateBlock(pos, temporaryPlayerBlockColor); } else { GetWorld()->CreateBlock(pos, p->GetBlockColor()); - client->PlayerCreatedBlock(p); + client->PlayerCreatedBlock(*p); if (!replace) { p->UsedBlocks(1); } @@ -1117,7 +1091,7 @@ namespace spades { } } break; case PacketTypeBlockLine: { - Player *p = GetPlayerOrNull(reader.ReadByte()); + stmp::optional p = GetPlayerOrNull(reader.ReadByte()); IntVector3 pos1, pos2; pos1.x = reader.ReadInt(); pos1.y = reader.ReadInt(); @@ -1138,7 +1112,7 @@ namespace spades { if (p) { p->UsedBlocks(static_cast(cells.size())); - client->PlayerCreatedBlock(p); + client->PlayerCreatedBlock(*p); } } break; case PacketTypeStateData: @@ -1169,84 +1143,74 @@ namespace spades { int mode = reader.ReadByte(); if (mode == 0) { // CTF - CTFGameMode *mode = new CTFGameMode(); - try { - CTFGameMode::Team &mt1 = mode->GetTeam(0); - CTFGameMode::Team &mt2 = mode->GetTeam(1); - - mt1.score = reader.ReadByte(); - mt2.score = reader.ReadByte(); - mode->SetCaptureLimit(reader.ReadByte()); - - int intelFlags = reader.ReadByte(); - mt1.hasIntel = (intelFlags & 1) != 0; - mt2.hasIntel = (intelFlags & 2) != 0; - - if (mt2.hasIntel) { - mt1.carrier = reader.ReadByte(); - reader.ReadData(11); - } else { - mt1.flagPos.x = reader.ReadFloat(); - mt1.flagPos.y = reader.ReadFloat(); - mt1.flagPos.z = reader.ReadFloat(); - } + auto mode = stmp::make_unique(); - if (mt1.hasIntel) { - mt2.carrier = reader.ReadByte(); - reader.ReadData(11); - } else { - mt2.flagPos.x = reader.ReadFloat(); - mt2.flagPos.y = reader.ReadFloat(); - mt2.flagPos.z = reader.ReadFloat(); - } + CTFGameMode::Team &mt1 = mode->GetTeam(0); + CTFGameMode::Team &mt2 = mode->GetTeam(1); - mt1.basePos.x = reader.ReadFloat(); - mt1.basePos.y = reader.ReadFloat(); - mt1.basePos.z = reader.ReadFloat(); + mt1.score = reader.ReadByte(); + mt2.score = reader.ReadByte(); + mode->SetCaptureLimit(reader.ReadByte()); - mt2.basePos.x = reader.ReadFloat(); - mt2.basePos.y = reader.ReadFloat(); - mt2.basePos.z = reader.ReadFloat(); + int intelFlags = reader.ReadByte(); + mt1.hasIntel = (intelFlags & 1) != 0; + mt2.hasIntel = (intelFlags & 2) != 0; - GetWorld()->SetMode(mode); - } catch (...) { - delete mode; - throw; + if (mt2.hasIntel) { + mt1.carrier = reader.ReadByte(); + reader.ReadData(11); + } else { + mt1.flagPos.x = reader.ReadFloat(); + mt1.flagPos.y = reader.ReadFloat(); + mt1.flagPos.z = reader.ReadFloat(); } + + if (mt1.hasIntel) { + mt2.carrier = reader.ReadByte(); + reader.ReadData(11); + } else { + mt2.flagPos.x = reader.ReadFloat(); + mt2.flagPos.y = reader.ReadFloat(); + mt2.flagPos.z = reader.ReadFloat(); + } + + mt1.basePos.x = reader.ReadFloat(); + mt1.basePos.y = reader.ReadFloat(); + mt1.basePos.z = reader.ReadFloat(); + + mt2.basePos.x = reader.ReadFloat(); + mt2.basePos.y = reader.ReadFloat(); + mt2.basePos.z = reader.ReadFloat(); + + GetWorld()->SetMode(std::move(mode)); } else { // TC - TCGameMode *mode = new TCGameMode(GetWorld()); - try { - int numTer = reader.ReadByte(); - - for (int i = 0; i < numTer; i++) { - TCGameMode::Territory ter; - ter.pos.x = reader.ReadFloat(); - ter.pos.y = reader.ReadFloat(); - ter.pos.z = reader.ReadFloat(); - - int state = reader.ReadByte(); - ter.ownerTeamId = state; - ter.progressBasePos = 0.f; - ter.progressStartTime = 0.f; - ter.progressRate = 0.f; - ter.capturingTeamId = -1; - ter.mode = mode; - mode->AddTerritory(ter); - } - - GetWorld()->SetMode(mode); - } catch (...) { - delete mode; - throw; + auto mode = stmp::make_unique(*GetWorld()); + int numTer = reader.ReadByte(); + + for (int i = 0; i < numTer; i++) { + TCGameMode::Territory ter{*mode}; + ter.pos.x = reader.ReadFloat(); + ter.pos.y = reader.ReadFloat(); + ter.pos.z = reader.ReadFloat(); + + int state = reader.ReadByte(); + ter.ownerTeamId = state; + ter.progressBasePos = 0.f; + ter.progressStartTime = 0.f; + ter.progressRate = 0.f; + ter.capturingTeamId = -1; + mode->AddTerritory(ter); } + + GetWorld()->SetMode(std::move(mode)); } client->JoinedGame(); } break; case PacketTypeKillAction: { - Player *p = GetPlayer(reader.ReadByte()); - Player *killer = GetPlayer(reader.ReadByte()); + Player &p = GetPlayer(reader.ReadByte()); + Player *killer = &GetPlayer(reader.ReadByte()); int kt = reader.ReadByte(); KillType type; switch (kt) { @@ -1264,27 +1228,27 @@ namespace spades { switch (type) { case KillTypeFall: case KillTypeClassChange: - case KillTypeTeamChange: killer = p; break; + case KillTypeTeamChange: killer = &p; break; default: break; } - p->KilledBy(type, killer, respawnTime); - if (p != killer) { + p.KilledBy(type, *killer, respawnTime); + if (&p != killer) { GetWorld()->GetPlayerPersistent(killer->GetId()).kills += 1; } } break; case PacketTypeChatMessage: { // might be wrong player id for server message uint8_t pId = reader.ReadByte(); - Player *p = GetPlayerOrNull(pId); + stmp::optional p = GetPlayerOrNull(pId); int type = reader.ReadByte(); std::string txt = reader.ReadRemainingString(); if (p) { switch (type) { case 0: // all - client->PlayerSentChatMessage(p, true, txt); + client->PlayerSentChatMessage(*p, true, txt); break; case 1: // team - client->PlayerSentChatMessage(p, false, txt); + client->PlayerSentChatMessage(*p, false, txt); break; case 2: // system??? client->ServerSentMessage(txt); @@ -1299,6 +1263,16 @@ namespace spades { } break; case PacketTypeMapStart: { // next map! + if (protocolVersion == 4) { + // The AoS 0.76 protocol allows the client to load a map from a local cache + // if possible. After receiving MapStart, the client should respond with + // MapCached to indicate whether the map with a given checksum exists in the + // cache or not. We don't implement a local cache, so we always ask the + // server to send fresh map data. + NetPacketWriter wri(PacketTypeMapCached); + wri.Write((uint8_t)0); + enet_peer_send(peer, 0, wri.CreatePacket()); + } client->SetWorld(NULL); auto mapSize = reader.ReadInt(); @@ -1312,14 +1286,13 @@ namespace spades { } break; case PacketTypeMapChunk: SPRaise("Unexpected: received Map Chunk while game"); case PacketTypePlayerLeft: { - Player *p = GetPlayer(reader.ReadByte()); + Player &p = GetPlayer(reader.ReadByte()); client->PlayerLeaving(p); - GetWorld()->GetPlayerPersistent(p->GetId()).kills = 0; + GetWorld()->GetPlayerPersistent(p.GetId()).kills = 0; - savedPlayerTeam[p->GetId()] = -1; - playerPosRecords[p->GetId()].valid = false; - GetWorld()->SetPlayer(p->GetId(), NULL); + savedPlayerTeam[p.GetId()] = -1; + GetWorld()->SetPlayer(p.GetId(), NULL); // TODO: message } break; case PacketTypeTerritoryCapture: { @@ -1327,28 +1300,32 @@ namespace spades { bool winning = reader.ReadByte() != 0; int state = reader.ReadByte(); - IGameMode *mode = GetWorld()->GetMode(); - if (mode == NULL) + // TODO: This piece is repeated for at least three times + stmp::optional mode = GetWorld()->GetMode(); + if (!mode) { + SPLog("Ignoring PacketTypeTerritoryCapture because game mode isn't " + "specified yet"); break; + } if (mode->ModeType() != IGameMode::m_TC) { SPRaise("Received PacketTypeTerritoryCapture in non-TC gamemode"); } - TCGameMode *tc = static_cast(mode); + TCGameMode &tc = dynamic_cast(*mode); - if (territoryId >= tc->GetNumTerritories()) { + if (territoryId >= tc.GetNumTerritories()) { SPRaise("Invalid territory id %d specified (max = %d)", territoryId, - tc->GetNumTerritories() - 1); + tc.GetNumTerritories() - 1); } client->TeamCapturedTerritory(state, territoryId); - TCGameMode::Territory *t = tc->GetTerritory(territoryId); + TCGameMode::Territory &t = tc.GetTerritory(territoryId); - t->ownerTeamId = state; - t->progressBasePos = 0.f; - t->progressRate = 0.f; - t->progressStartTime = 0.f; - t->capturingTeamId = -1; + t.ownerTeamId = state; + t.progressBasePos = 0.f; + t.progressRate = 0.f; + t.progressStartTime = 0.f; + t.capturingTeamId = -1; if (winning) client->TeamWon(state); @@ -1359,75 +1336,88 @@ namespace spades { int rate = (int8_t)reader.ReadByte(); float progress = reader.ReadFloat(); - IGameMode *mode = GetWorld()->GetMode(); - if (mode == NULL) + stmp::optional mode = GetWorld()->GetMode(); + if (!mode) { + SPLog( + "Ignoring PacketTypeProgressBar because game mode isn't specified yet"); break; + } if (mode->ModeType() != IGameMode::m_TC) { SPRaise("Received PacketTypeProgressBar in non-TC gamemode"); } - TCGameMode *tc = static_cast(mode); + TCGameMode &tc = dynamic_cast(*mode); - if (territoryId >= tc->GetNumTerritories()) { + if (territoryId >= tc.GetNumTerritories()) { SPRaise("Invalid territory id %d specified (max = %d)", territoryId, - tc->GetNumTerritories() - 1); + tc.GetNumTerritories() - 1); } if (progress < -0.1f || progress > 1.1f) SPRaise("Progress value out of range(%f)", progress); - TCGameMode::Territory *t = tc->GetTerritory(territoryId); + TCGameMode::Territory &t = tc.GetTerritory(territoryId); - t->progressBasePos = progress; - t->progressRate = (float)rate * TC_CAPTURE_RATE; - t->progressStartTime = GetWorld()->GetTime(); - t->capturingTeamId = capturingTeam; + t.progressBasePos = progress; + t.progressRate = (float)rate * TC_CAPTURE_RATE; + t.progressStartTime = GetWorld()->GetTime(); + t.capturingTeamId = capturingTeam; } break; case PacketTypeIntelCapture: { if (!GetWorld()) SPRaise("No world"); - IGameMode *mode = GetWorld()->GetMode(); - if (mode == NULL) + + stmp::optional mode = GetWorld()->GetMode(); + if (!mode) { + SPLog( + "Ignoring PacketTypeIntelCapture because game mode isn't specified yet"); break; + } if (mode->ModeType() != IGameMode::m_CTF) { SPRaise("Received PacketTypeIntelCapture in non-TC gamemode"); } - CTFGameMode *ctf = static_cast(mode); - Player *p = GetPlayer(reader.ReadByte()); + CTFGameMode &ctf = dynamic_cast(mode.value()); + + Player &p = GetPlayer(reader.ReadByte()); client->PlayerCapturedIntel(p); - GetWorld()->GetPlayerPersistent(p->GetId()).kills += 10; - ctf->GetTeam(p->GetTeamId()).hasIntel = false; - ctf->GetTeam(p->GetTeamId()).score++; + GetWorld()->GetPlayerPersistent(p.GetId()).kills += 10; + ctf.GetTeam(p.GetTeamId()).hasIntel = false; + ctf.GetTeam(p.GetTeamId()).score++; bool winning = reader.ReadByte() != 0; if (winning) { - ctf->ResetTeamScoreAndIntelHoldingStatus(); - client->TeamWon(p->GetTeamId()); + ctf.ResetTeamScoreAndIntelHoldingStatus(); + client->TeamWon(p.GetTeamId()); } } break; case PacketTypeIntelPickup: { - Player *p = GetPlayer(reader.ReadByte()); - IGameMode *mode = GetWorld()->GetMode(); - if (mode == NULL) + Player &p = GetPlayer(reader.ReadByte()); + stmp::optional mode = GetWorld()->GetMode(); + if (!mode) { + SPLog( + "Ignoring PacketTypeIntelPickup because game mode isn't specified yet"); break; + } if (mode->ModeType() != IGameMode::m_CTF) { SPRaise("Received PacketTypeIntelPickup in non-TC gamemode"); } - CTFGameMode *ctf = static_cast(mode); - CTFGameMode::Team &team = ctf->GetTeam(p->GetTeamId()); + CTFGameMode &ctf = dynamic_cast(mode.value()); + CTFGameMode::Team &team = ctf.GetTeam(p.GetTeamId()); team.hasIntel = true; - team.carrier = p->GetId(); + team.carrier = p.GetId(); client->PlayerPickedIntel(p); } break; case PacketTypeIntelDrop: { - Player *p = GetPlayer(reader.ReadByte()); - IGameMode *mode = GetWorld()->GetMode(); - if (mode == NULL) + Player &p = GetPlayer(reader.ReadByte()); + stmp::optional mode = GetWorld()->GetMode(); + if (!mode) { + SPLog("Ignoring PacketTypeIntelDrop because game mode isn't specified yet"); break; + } if (mode->ModeType() != IGameMode::m_CTF) { - SPRaise("Received PacketTypeIntelPickup in non-TC gamemode"); + SPRaise("Received PacketTypeIntelDrop in non-TC gamemode"); } - CTFGameMode *ctf = static_cast(mode); - CTFGameMode::Team &team = ctf->GetTeam(p->GetTeamId()); + CTFGameMode &ctf = dynamic_cast(mode.value()); + CTFGameMode::Team &team = ctf.GetTeam(p.GetTeamId()); team.hasIntel = false; Vector3 pos; @@ -1435,13 +1425,13 @@ namespace spades { pos.y = reader.ReadFloat(); pos.z = reader.ReadFloat(); - ctf->GetTeam(1 - p->GetTeamId()).flagPos = pos; + ctf.GetTeam(1 - p.GetTeamId()).flagPos = pos; client->PlayerDropIntel(p); } break; case PacketTypeRestock: { - Player *p = GetLocalPlayer(); // GetPlayer(reader.ReadByte()); - p->Restock(); + Player &p = GetLocalPlayer(); // GetPlayer(reader.ReadByte()); + p.Restock(); } break; case PacketTypeFogColour: { if (GetWorld()) { @@ -1450,24 +1440,24 @@ namespace spades { } } break; case PacketTypeWeaponReload: { - Player *p = GetPlayer(reader.ReadByte()); - if (p != GetLocalPlayerOrNull()) - p->Reload(); + Player &p = GetPlayer(reader.ReadByte()); + if (&p != GetLocalPlayerOrNull()) + p.Reload(); else { int clip = reader.ReadByte(); int reserve = reader.ReadByte(); - if (clip < 255 && reserve < 255 && p) { - p->ReloadDone(clip, reserve); + if (clip < 255 && reserve < 255) { + p.ReloadDone(clip, reserve); } } // FIXME: use of "clip ammo" and "reserve ammo"? } break; case PacketTypeChangeTeam: { - Player *p = GetPlayer(reader.ReadByte()); + Player &p = GetPlayer(reader.ReadByte()); int team = reader.ReadByte(); if (team < 0 || team > 2) SPRaise("Received invalid team: %d", team); - p->SetTeam(team); + p.SetTeam(team); } case PacketTypeChangeWeapon: { reader.ReadByte(); @@ -1525,6 +1515,7 @@ namespace spades { } wri.Update(lengthLabel, (uint8_t)(wri.GetPosition() - beginLabel)); + enet_peer_send(peer, 0, wri.CreatePacket()); } } @@ -1539,7 +1530,7 @@ namespace spades { } NetPacketWriter wri(PacketTypeExistingPlayer); - wri.Write((uint8_t)GetWorld()->GetLocalPlayerIndex()); + wri.Write((uint8_t)0); // Player ID, but shouldn't matter here wri.Write((uint8_t)team); wri.Write((uint8_t)weapId); wri.Write((uint8_t)2); // TODO: change tool @@ -1553,8 +1544,8 @@ namespace spades { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypePositionData); // wri.Write((uint8_t)pId); - Player *p = GetLocalPlayer(); - Vector3 v = p->GetPosition(); + Player &p = GetLocalPlayer(); + Vector3 v = p.GetPosition(); wri.Write(v.x); wri.Write(v.y); wri.Write(v.z); @@ -1599,7 +1590,7 @@ namespace spades { lastPlayerInput = bits; NetPacketWriter wri(PacketTypeInputData); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); wri.Write(bits); enet_peer_send(peer, 0, wri.CreatePacket()); @@ -1618,7 +1609,7 @@ namespace spades { lastWeaponInput = bits; NetPacketWriter wri(PacketTypeWeaponInput); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); wri.Write(bits); enet_peer_send(peer, 0, wri.CreatePacket()); @@ -1627,7 +1618,7 @@ namespace spades { void NetClient::SendBlockAction(spades::IntVector3 v, BlockActionType type) { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeBlockAction); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); switch (type) { case BlockActionCreate: wri.Write((uint8_t)0); break; @@ -1647,7 +1638,7 @@ namespace spades { void NetClient::SendBlockLine(spades::IntVector3 v1, spades::IntVector3 v2) { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeBlockLine); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); wri.Write((uint32_t)v1.x); wri.Write((uint32_t)v1.y); @@ -1662,7 +1653,7 @@ namespace spades { void NetClient::SendReload() { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeWeaponReload); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); // these value should be 255, or // NetClient will think reload was done when @@ -1676,8 +1667,8 @@ namespace spades { void NetClient::SendHeldBlockColor() { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeSetColour); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); - IntVector3 v = GetLocalPlayer()->GetBlockColor(); + wri.Write((uint8_t)GetLocalPlayer().GetId()); + IntVector3 v = GetLocalPlayer().GetBlockColor(); wri.WriteColor(v); enet_peer_send(peer, 0, wri.CreatePacket()); } @@ -1685,31 +1676,31 @@ namespace spades { void NetClient::SendTool() { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeSetTool); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); - switch (GetLocalPlayer()->GetTool()) { + wri.Write((uint8_t)GetLocalPlayer().GetId()); + switch (GetLocalPlayer().GetTool()) { case Player::ToolSpade: wri.Write((uint8_t)0); break; case Player::ToolBlock: wri.Write((uint8_t)1); break; case Player::ToolWeapon: wri.Write((uint8_t)2); break; case Player::ToolGrenade: wri.Write((uint8_t)3); break; - default: SPInvalidEnum("tool", GetLocalPlayer()->GetTool()); + default: SPInvalidEnum("tool", GetLocalPlayer().GetTool()); } enet_peer_send(peer, 0, wri.CreatePacket()); } - void NetClient::SendGrenade(spades::client::Grenade *g) { + void NetClient::SendGrenade(const Grenade &g) { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeGrenadePacket); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); - wri.Write(g->GetFuse()); + wri.Write(g.GetFuse()); - Vector3 v = g->GetPosition(); + Vector3 v = g.GetPosition(); wri.Write(v.x); wri.Write(v.y); wri.Write(v.z); - v = g->GetVelocity(); + v = g.GetVelocity(); wri.Write(v.x); wri.Write(v.y); wri.Write(v.z); @@ -1735,7 +1726,7 @@ namespace spades { void NetClient::SendChat(std::string text, bool global) { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeChatMessage); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); wri.Write((uint8_t)(global ? 0 : 1)); wri.Write(text); wri.Write((uint8_t)0); @@ -1745,7 +1736,7 @@ namespace spades { void NetClient::SendWeaponChange(WeaponType wt) { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeChangeWeapon); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); switch (wt) { case RIFLE_WEAPON: wri.Write((uint8_t)0); break; case SMG_WEAPON: wri.Write((uint8_t)1); break; @@ -1757,7 +1748,7 @@ namespace spades { void NetClient::SendTeamChange(int team) { SPADES_MARK_FUNCTION(); NetPacketWriter wri(PacketTypeChangeTeam); - wri.Write((uint8_t)GetLocalPlayer()->GetId()); + wri.Write((uint8_t)GetLocalPlayer().GetId()); wri.Write((uint8_t)team); enet_peer_send(peer, 0, wri.CreatePacket()); } @@ -1807,7 +1798,7 @@ namespace spades { SPLog("Waiting for the game map decoding to complete..."); mapLoader->MarkEOF(); mapLoader->WaitComplete(); - GameMap *map = mapLoader->TakeGameMap(); + GameMap *map = mapLoader->TakeGameMap().Unmanage(); SPLog("The game map was decoded successfully."); // now initialize world @@ -1822,8 +1813,6 @@ namespace spades { SPLog("World loaded. Processing saved packets (%d)...", (int)savedPackets.size()); - for (size_t i = 0; i < playerPosRecords.size(); i++) - playerPosRecords[i].valid = false; std::fill(savedPlayerTeam.begin(), savedPlayerTeam.end(), -1); // do saved packets @@ -1923,5 +1912,5 @@ namespace spades { return text; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/NetClient.h b/Sources/Client/NetClient.h index 10f356cc9..754cde038 100644 --- a/Sources/Client/NetClient.h +++ b/Sources/Client/NetClient.h @@ -21,12 +21,12 @@ #pragma once +#include #include -#include -#include #include -#include +#include #include +#include #include "PhysicsConstants.h" #include "Player.h" @@ -121,16 +121,6 @@ namespace spades { std::vector savedPlayerFront; std::vector savedPlayerTeam; - struct PosRecord { - float time; - bool valid; - Vector3 pos; - - PosRecord() : valid(false) {} - }; - - std::vector playerPosRecords; - std::vector> savedPackets; int timeToTryMapLoad; @@ -145,11 +135,11 @@ namespace spades { bool HandleHandshakePackets(NetPacketReader &); void HandleExtensionPacket(NetPacketReader &); void HandleGamePacket(NetPacketReader &); - World *GetWorld(); - Player *GetPlayer(int); - Player *GetPlayerOrNull(int); - Player *GetLocalPlayer(); - Player *GetLocalPlayerOrNull(); + stmp::optional GetWorld(); + Player &GetPlayer(int); + stmp::optional GetPlayerOrNull(int); + Player &GetLocalPlayer(); + stmp::optional GetLocalPlayerOrNull(); std::string DisconnectReasonString(uint32_t); @@ -200,7 +190,7 @@ namespace spades { void SendBlockLine(IntVector3 v1, IntVector3 v2); void SendReload(); void SendTool(); - void SendGrenade(Grenade *); + void SendGrenade(const Grenade &); void SendHeldBlockColor(); void SendHit(int targetPlayerId, HitType type); void SendChat(std::string, bool global); @@ -211,5 +201,5 @@ namespace spades { double GetDownlinkBps() { return bandwidthMonitor->GetDownlinkBps(); } double GetUplinkBps() { return bandwidthMonitor->GetUplinkBps(); } }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/NoiseSampler.cpp b/Sources/Client/NoiseSampler.cpp index ac5c1b1e2..567f3df37 100644 --- a/Sources/Client/NoiseSampler.cpp +++ b/Sources/Client/NoiseSampler.cpp @@ -79,5 +79,5 @@ namespace spades { // Create and evaluate a polynomial with given derivatives return (d1 * (1.f - fracCoord) - d2 * fracCoord) * fracCoord * (1.f - fracCoord); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/NoiseSampler.h b/Sources/Client/NoiseSampler.h index 1a82882e7..18e488245 100644 --- a/Sources/Client/NoiseSampler.h +++ b/Sources/Client/NoiseSampler.h @@ -45,5 +45,5 @@ namespace spades { std::vector values; GradientCoherentNoiseSampler1D gcns; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/PaletteView.cpp b/Sources/Client/PaletteView.cpp index 08bb43997..6cd198e79 100644 --- a/Sources/Client/PaletteView.cpp +++ b/Sources/Client/PaletteView.cpp @@ -20,11 +20,11 @@ #include -#include "PaletteView.h" #include "Client.h" #include "IImage.h" #include "IRenderer.h" #include "NetClient.h" +#include "PaletteView.h" #include "Player.h" #include "World.h" @@ -74,7 +74,7 @@ namespace spades { if (!w) return -1; - Player *p = w->GetLocalPlayer(); + stmp::optional p = w->GetLocalPlayer(); if (!p) return -1; @@ -101,7 +101,7 @@ namespace spades { if (!w) return; - Player *p = w->GetLocalPlayer(); + stmp::optional p = w->GetLocalPlayer(); if (!p) return; @@ -151,12 +151,12 @@ namespace spades { void PaletteView::Update() {} void PaletteView::Draw() { - Handle img = renderer->RegisterImage("Gfx/Palette.png"); + Handle img = renderer.RegisterImage("Gfx/Palette.png"); int sel = GetSelectedIndex(); - float scrW = renderer->ScreenWidth(); - float scrH = renderer->ScreenHeight(); + float scrW = renderer.ScreenWidth(); + float scrH = renderer.ScreenHeight(); for (size_t phase = 0; phase < 2; phase++) { for (size_t i = 0; i < colors.size(); i++) { @@ -179,21 +179,21 @@ namespace spades { float x = scrW - 100.f + 10.f * col; float y = scrH - 106.f + 10.f * row - 40.f; - renderer->SetColorAlphaPremultiplied(cl); + renderer.SetColorAlphaPremultiplied(cl); if (selected) { - renderer->DrawImage(img, MakeVector2(x, y), AABB2(0, 16, 16, 16)); + renderer.DrawImage(img, MakeVector2(x, y), AABB2(0, 16, 16, 16)); } else { - renderer->DrawImage(img, MakeVector2(x, y), AABB2(0, 0, 16, 16)); + renderer.DrawImage(img, MakeVector2(x, y), AABB2(0, 0, 16, 16)); } - renderer->SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1)); + renderer.SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1)); if (selected) { - renderer->DrawImage(img, MakeVector2(x, y), AABB2(16, 16, 16, 16)); + renderer.DrawImage(img, MakeVector2(x, y), AABB2(16, 16, 16, 16)); } else { - renderer->DrawImage(img, MakeVector2(x, y), AABB2(16, 0, 16, 16)); + renderer.DrawImage(img, MakeVector2(x, y), AABB2(16, 0, 16, 16)); } } } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/PaletteView.h b/Sources/Client/PaletteView.h index 22183a8fc..c95042d55 100644 --- a/Sources/Client/PaletteView.h +++ b/Sources/Client/PaletteView.h @@ -30,7 +30,7 @@ namespace spades { class IRenderer; class PaletteView { Client *client; - IRenderer *renderer; + IRenderer &renderer; int defaultColor; std::vector colors; @@ -48,5 +48,5 @@ namespace spades { void Update(); void Draw(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ParticleSpriteEntity.cpp b/Sources/Client/ParticleSpriteEntity.cpp index 30201567a..5d4dc04ca 100644 --- a/Sources/Client/ParticleSpriteEntity.cpp +++ b/Sources/Client/ParticleSpriteEntity.cpp @@ -19,14 +19,15 @@ */ #include "ParticleSpriteEntity.h" -#include #include "GameMap.h" #include "World.h" +#include namespace spades { namespace client { - ParticleSpriteEntity::ParticleSpriteEntity(Client *cli, IImage *image, Vector4 color) - : image(image), color(color) { + ParticleSpriteEntity::ParticleSpriteEntity(Client &client, Handle image, + Vector4 color) + : renderer(client.GetRenderer()), image(image), color(color) { position = MakeVector3(0, 0, 0); velocity = MakeVector3(0, 0, 0); radius = 1.f; @@ -41,23 +42,15 @@ namespace spades { fadeInDuration = .1f; fadeOutDuration = .5f; additive = false; - blockHitAction = Delete; - - if (image != NULL) - image->AddRef(); + blockHitAction = BlockHitAction::Delete; - renderer = cli->GetRenderer(); - if (cli->GetWorld()) - map = cli->GetWorld()->GetMap(); + if (client.GetWorld()) + map = client.GetWorld()->GetMap(); else map = NULL; } - ParticleSpriteEntity::~ParticleSpriteEntity() { - if (image != NULL) { - image->Release(); - } - } + ParticleSpriteEntity::~ParticleSpriteEntity() {} void ParticleSpriteEntity::SetLifeTime(float lifeTime, float fadeIn, float fadeOut) { lifetime = lifeTime; @@ -95,9 +88,9 @@ namespace spades { velocity.z += 32.f * dt * gravityScale; // TODO: control clip action - if (blockHitAction != Ignore && map) { + if (blockHitAction != BlockHitAction::Ignore && map) { if (map->ClipWorld(position.x, position.y, position.z)) { - if (blockHitAction == Delete) { + if (blockHitAction == BlockHitAction::Delete) { return false; } else { IntVector3 lp2 = lastPos.Floor(); @@ -155,17 +148,9 @@ namespace spades { if (additive) col.w = 0.f; - renderer->SetColorAlphaPremultiplied(col); - renderer->AddSprite(image, position, radius, angle); - } - void ParticleSpriteEntity::SetImage(IImage *img) { - if (img == image) - return; - if (image != NULL) - image->Release(); - image = img; - if (image != NULL) - image->AddRef(); + renderer.SetColorAlphaPremultiplied(col); + renderer.AddSprite(*image, position, radius, angle); } - } -} + void ParticleSpriteEntity::SetImage(Handle newImage) { image = newImage; } + } // namespace client +} // namespace spades diff --git a/Sources/Client/ParticleSpriteEntity.h b/Sources/Client/ParticleSpriteEntity.h index 7c7af5f82..f152910a3 100644 --- a/Sources/Client/ParticleSpriteEntity.h +++ b/Sources/Client/ParticleSpriteEntity.h @@ -20,23 +20,22 @@ #pragma once -#include #include "Client.h" #include "ILocalEntity.h" +#include namespace spades { namespace client { class IImage; - class ParticleSpriteEntity : public ILocalEntity { - public: - enum BlockHitAction { Delete, Ignore, BounceWeak }; + enum class BlockHitAction { Delete, Ignore, BounceWeak }; + class ParticleSpriteEntity : public ILocalEntity { private: - IRenderer *renderer; - GameMap *map; + IRenderer &renderer; + Handle map; - IImage *image; + Handle image; Vector4 color; bool additive; BlockHitAction blockHitAction; @@ -54,7 +53,7 @@ namespace spades { float fadeOutDuration; public: - ParticleSpriteEntity(Client *cli, IImage *image, Vector4 color); + ParticleSpriteEntity(Client &client, Handle image, Vector4 color); ~ParticleSpriteEntity(); @@ -74,10 +73,10 @@ namespace spades { void SetBlockHitAction(BlockHitAction act) { blockHitAction = act; } - void SetImage(IImage *img); + void SetImage(Handle img); void SetColor(Vector4 col) { color = col; } - IRenderer *GetRenderer() { return renderer; } + IRenderer &GetRenderer() { return renderer; } }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades diff --git a/Sources/Client/Player.cpp b/Sources/Client/Player.cpp index 6d0558b69..65c79b9f2 100644 --- a/Sources/Client/Player.cpp +++ b/Sources/Client/Player.cpp @@ -36,7 +36,7 @@ namespace spades { namespace client { - Player::Player(World *w, int playerId, WeaponType wType, int teamId, Vector3 position, + Player::Player(World &w, int playerId, WeaponType wType, int teamId, Vector3 position, IntVector3 color) : world(w) { SPADES_MARK_FUNCTION(); @@ -57,7 +57,7 @@ namespace spades { moveSteps = 0; this->playerId = playerId; - this->weapon = Weapon::CreateWeapon(wType, this, *w->GetGameProperties()); + this->weapon.reset(Weapon::CreateWeapon(wType, *this, *w.GetGameProperties())); this->weaponType = wType; this->teamId = teamId; this->weapon->Reset(); @@ -86,16 +86,9 @@ namespace spades { canPending = false; } - Player::~Player() { - SPADES_MARK_FUNCTION(); - delete weapon; - } + Player::~Player() { SPADES_MARK_FUNCTION(); } - bool Player::IsLocalPlayer() { - if (!world) - return false; - return world->GetLocalPlayer() == this; - } + bool Player::IsLocalPlayer() { return world.GetLocalPlayer() == this; } void Player::SetInput(PlayerInput newInput) { SPADES_MARK_FUNCTION(); @@ -103,18 +96,29 @@ namespace spades { if (!IsAlive()) return; - if (newInput.crouch != input.crouch && !airborne) { - if (newInput.crouch) - position.z += 0.9f; - else - position.z -= 0.9f; + if (newInput.crouch != input.crouch) { + if (newInput.crouch) { + if (!airborne) { + position.z += 0.9f; + } + } else { + // Refuse the standing-up request if there's no room + if (!TryUncrouch()) { + // ... But if the request is from the server, + // don't ask questions + if (IsLocalPlayer()) { + newInput.crouch = true; + } + } + } } + input = newInput; } void Player::SetWeaponInput(WeaponInput newInput) { SPADES_MARK_FUNCTION(); - auto *listener = GetWorld()->GetListener(); + auto *listener = GetWorld().GetListener(); if (!IsAlive()) return; @@ -129,12 +133,12 @@ namespace spades { newInput.primary = false; if (newInput.secondary != weapInput.secondary) { if (newInput.secondary) { - nextDigTime = world->GetTime() + 1.f; + nextDigTime = world.GetTime() + 1.f; firstDig = true; } } } else if (tool == ToolGrenade) { - if (world->GetTime() < nextGrenadeTime) { + if (world.GetTime() < nextGrenadeTime) { newInput.primary = false; } if (grenades == 0) { @@ -147,13 +151,13 @@ namespace spades { if (newInput.primary != weapInput.primary) { if (!newInput.primary) { if (holdingGrenade) { - nextGrenadeTime = world->GetTime() + .5f; + nextGrenadeTime = world.GetTime() + .5f; ThrowGrenade(); } } else { holdingGrenade = true; - grenadeTime = world->GetTime(); - if (listener && this == world->GetLocalPlayer()) + grenadeTime = world.GetTime(); + if (listener && this == world.GetLocalPlayer()) // playing other's grenade sound // is cheating listener->LocalPlayerPulledGrenadePin(); @@ -163,12 +167,12 @@ namespace spades { // work-around for bug that placing block // occasionally becomes impossible if (nextBlockTime > - world->GetTime() + std::max(GetToolPrimaryDelay(), GetToolSecondaryDelay())) { + world.GetTime() + std::max(GetToolPrimaryDelay(), GetToolSecondaryDelay())) { nextBlockTime = - world->GetTime() + std::max(GetToolPrimaryDelay(), GetToolSecondaryDelay()); + world.GetTime() + std::max(GetToolPrimaryDelay(), GetToolSecondaryDelay()); } - if (world->GetTime() < nextBlockTime) { + if (world.GetTime() < nextBlockTime) { newInput.primary = false; newInput.secondary = false; } @@ -181,7 +185,7 @@ namespace spades { blockCursorDragPos = blockCursorPos; } else { // cannot build; invalid position. - if (listener && this == world->GetLocalPlayer()) { + if (listener && this == world.GetLocalPlayer()) { listener->LocalPlayerBuildError( BuildFailureReason::InvalidPosition); } @@ -190,23 +194,23 @@ namespace spades { if (IsBlockCursorDragging()) { if (IsBlockCursorActive()) { std::vector blocks = - GetWorld()->CubeLine(blockCursorDragPos, blockCursorPos, 256); + GetWorld().CubeLine(blockCursorDragPos, blockCursorPos, 256); if ((int)blocks.size() <= blockStocks) { - if (listener && this == world->GetLocalPlayer()) + if (listener && this == world.GetLocalPlayer()) listener->LocalPlayerCreatedLineBlock(blockCursorDragPos, blockCursorPos); // blockStocks -= blocks.size(); decrease when created } else { // cannot build; insufficient blocks. - if (listener && this == world->GetLocalPlayer()) { + if (listener && this == world.GetLocalPlayer()) { listener->LocalPlayerBuildError( BuildFailureReason::InsufficientBlocks); } } - nextBlockTime = world->GetTime() + GetToolSecondaryDelay(); + nextBlockTime = world.GetTime() + GetToolSecondaryDelay(); } else { // cannot build; invalid position. - if (listener && this == world->GetLocalPlayer()) { + if (listener && this == world.GetLocalPlayer()) { listener->LocalPlayerBuildError( BuildFailureReason::InvalidPosition); } @@ -223,15 +227,15 @@ namespace spades { if (!weapInput.primary) lastSingleBlockBuildSeqDone = false; if (IsBlockCursorActive() && blockStocks > 0) { - if (listener && this == world->GetLocalPlayer()) + if (listener && this == world.GetLocalPlayer()) listener->LocalPlayerBlockAction(blockCursorPos, BlockActionCreate); lastSingleBlockBuildSeqDone = true; // blockStocks--; decrease when created - nextBlockTime = world->GetTime() + GetToolPrimaryDelay(); + nextBlockTime = world.GetTime() + GetToolPrimaryDelay(); } else if (blockStocks > 0 && airborne && canPending && - this == world->GetLocalPlayer()) { + this == world.GetLocalPlayer()) { pendingPlaceBlock = true; pendingPlaceBlockPos = blockCursorPos; } else if (!IsBlockCursorActive()) { @@ -243,7 +247,7 @@ namespace spades { } else { if (!lastSingleBlockBuildSeqDone) { // cannot build; invalid position. - if (listener && this == world->GetLocalPlayer()) { + if (listener && this == world.GetLocalPlayer()) { listener->LocalPlayerBuildError( BuildFailureReason::InvalidPosition); } @@ -274,7 +278,7 @@ namespace spades { return; } weapon->Reload(); - if (this == world->GetLocalPlayer() && weapon->IsReloading()) + if (this == world.GetLocalPlayer() && weapon->IsReloading()) reloadingServerSide = true; } @@ -295,8 +299,8 @@ namespace spades { pendingRestockBlock = true; health = 100; - if (world->GetListener()) - world->GetListener()->PlayerRestocked(this); + if (world.GetListener()) + world.GetListener()->PlayerRestocked(*this); } void Player::GotBlock() { @@ -321,8 +325,8 @@ namespace spades { weapon->AbortReload(); - if (world->GetListener()) - world->GetListener()->PlayerChangedTool(this); + if (world.GetListener()) + world.GetListener()->PlayerChangedTool(*this); } void Player::SetHeldBlockColor(spades::IntVector3 col) { blockColor = col; } @@ -369,16 +373,16 @@ namespace spades { void Player::SetHP(int hp, HurtType type, spades::Vector3 p) { health = hp; - if (this == world->GetLocalPlayer()) { - if (world->GetListener()) - world->GetListener()->LocalPlayerHurt( - type, p.x != 0.f || p.y != 0.f || p.z != 0.f, p); + if (this == world.GetLocalPlayer()) { + if (world.GetListener()) + world.GetListener()->LocalPlayerHurt(type, + p.x != 0.f || p.y != 0.f || p.z != 0.f, p); } } void Player::Update(float dt) { SPADES_MARK_FUNCTION(); - auto *listener = world->GetListener(); + auto *listener = world.GetListener(); MovePlayer(dt); @@ -389,20 +393,22 @@ namespace spades { if (tool == ToolSpade) { if (weapInput.primary) { - if (world->GetTime() > nextSpadeTime) { + if (world.GetTime() > nextSpadeTime) { UseSpade(); - nextSpadeTime = world->GetTime() + GetToolPrimaryDelay(); + nextSpadeTime = world.GetTime() + GetToolPrimaryDelay(); } } else if (weapInput.secondary) { - if (world->GetTime() > nextDigTime) { + if (world.GetTime() > nextDigTime) { DigWithSpade(); - nextDigTime = world->GetTime() + GetToolSecondaryDelay(); + nextDigTime = world.GetTime() + GetToolSecondaryDelay(); firstDig = false; } } } else if (tool == ToolBlock && IsLocalPlayer()) { GameMap::RayCastResult result; - auto *map = GetWorld()->GetMap(); + Handle map = GetWorld().GetMap(); + SPAssert(map); + result = map->CastRay2(GetEye(), GetFront(), 12); canPending = false; @@ -418,7 +424,7 @@ namespace spades { // still okay } else { // cannot build; floating - if (listener && this == world->GetLocalPlayer()) { + if (listener && this == world.GetLocalPlayer()) { listener->LocalPlayerBuildError(BuildFailureReason::InvalidPosition); } blockCursorDragging = false; @@ -428,8 +434,7 @@ namespace spades { if (result.hit && (result.hitBlock + result.normal).z < 62 && (!OverlapsWithOneBlock(result.hitBlock + result.normal)) && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f && - (result.hitBlock + result.normal).z >= 0 && - !pendingPlaceBlock) { + (result.hitBlock + result.normal).z >= 0 && !pendingPlaceBlock) { // Building is possible, and there's no delayed block placement. blockCursorActive = true; @@ -452,17 +457,17 @@ namespace spades { } else if ((!OverlapsWithOneBlock(pendingPlaceBlockPos)) && BoxDistanceToBlock(pendingPlaceBlockPos) < 3.f) { // now building became possible. - SPAssert(this == world->GetLocalPlayer()); + SPAssert(this == world.GetLocalPlayer()); - if (GetWorld()->GetListener()) - GetWorld()->GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, - BlockActionCreate); + if (GetWorld().GetListener()) + GetWorld().GetListener()->LocalPlayerBlockAction(pendingPlaceBlockPos, + BlockActionCreate); pendingPlaceBlock = false; lastSingleBlockBuildSeqDone = true; // blockStocks--; decrease when created - nextBlockTime = world->GetTime() + GetToolPrimaryDelay(); + nextBlockTime = world.GetTime() + GetToolPrimaryDelay(); } } else { @@ -476,11 +481,11 @@ namespace spades { int dist = 11; for (; dist >= 1 && BoxDistanceToBlock(result.hitBlock + result.normal) > 3.f; dist--) { - result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), dist); + result = GetWorld().GetMap()->CastRay2(GetEye(), GetFront(), dist); } for (; dist < 12 && BoxDistanceToBlock(result.hitBlock + result.normal) < 3.f; dist++) { - result = GetWorld()->GetMap()->CastRay2(GetEye(), GetFront(), dist); + result = GetWorld().GetMap()->CastRay2(GetEye(), GetFront(), dist); } blockCursorPos = result.hitBlock + result.normal; @@ -489,7 +494,7 @@ namespace spades { } else if (tool == ToolWeapon) { } else if (tool == ToolGrenade) { if (holdingGrenade) { - if (world->GetTime() - grenadeTime > 2.9f) { + if (world.GetTime() - grenadeTime > 2.9f) { ThrowGrenade(); } } @@ -502,11 +507,11 @@ namespace spades { } if (weapon->IsReloading()) { - lastReloadingTime = world->GetTime(); + lastReloadingTime = world.GetTime(); } else if (reloadingServerSide) { // for some reason a server didn't return // WeaponReload packet. - if (world->GetTime() + lastReloadingTime + .8f) { + if (world.GetTime() + lastReloadingTime + .8f) { reloadingServerSide = false; weapon->ForceReloadDone(); } @@ -554,7 +559,9 @@ namespace spades { int pellets = weapon->GetPelletSize(); float spread = weapon->GetSpread(); - GameMap *map = world->GetMap(); + Handle map = world.GetMap(); + + SPAssert(map); if (!weapInput.secondary) { spread *= 2; @@ -564,6 +571,9 @@ namespace spades { // speed hack (shotgun does this) bool blockDestroyed = false; + // The custom state data, optionally set by `BulletHitPlayer`'s implementation + std::unique_ptr stateCell; + Vector3 dir2 = GetFront(); for (int i = 0; i < pellets; i++) { @@ -579,27 +589,31 @@ namespace spades { GameMap::RayCastResult mapResult; mapResult = map->CastRay2(muzzle, dir, 500); - Player *hitPlayer = NULL; + stmp::optional hitPlayer; float hitPlayerDistance = 0.f; // disregarding Z coordinate float hitPlayerActualDistance = 0.f; HitBodyPart hitPart = HitBodyPart::None; - for (int i = 0; i < world->GetNumPlayerSlots(); i++) { - Player *other = world->GetPlayer(i); - if (other == this || other == NULL) + for (int i = 0; i < world.GetNumPlayerSlots(); i++) { + // TODO: This is a repeated pattern, add something like + // `World::GetExistingPlayerRange()` returning a range + auto maybeOther = world.GetPlayer(i); + if (maybeOther == this || !maybeOther) continue; - if (other == this || !other->IsAlive() || other->GetTeamId() >= 2) + + Player &other = maybeOther.value(); + if (!other.IsAlive() || other.GetTeamId() >= 2) continue; // quickly reject players unlikely to be hit - if (!other->RayCastApprox(muzzle, dir)) + if (!other.RayCastApprox(muzzle, dir)) continue; - HitBoxes hb = other->GetHitBoxes(); + HitBoxes hb = other.GetHitBoxes(); Vector3 hitPos; if (hb.head.RayCast(muzzle, dir, &hitPos)) { float dist = GetHorizontalLength(hitPos - muzzle); - if (hitPlayer == NULL || dist < hitPlayerDistance) { + if (!hitPlayer || dist < hitPlayerDistance) { hitPlayer = other; hitPlayerDistance = dist; hitPlayerActualDistance = (hitPos - muzzle).GetLength(); @@ -608,7 +622,7 @@ namespace spades { } if (hb.torso.RayCast(muzzle, dir, &hitPos)) { float dist = GetHorizontalLength(hitPos - muzzle); - if (hitPlayer == NULL || dist < hitPlayerDistance) { + if (!hitPlayer || dist < hitPlayerDistance) { hitPlayer = other; hitPlayerDistance = dist; hitPlayerActualDistance = (hitPos - muzzle).GetLength(); @@ -618,7 +632,7 @@ namespace spades { for (int j = 0; j < 3; j++) { if (hb.limbs[j].RayCast(muzzle, dir, &hitPos)) { float dist = GetHorizontalLength(hitPos - muzzle); - if (hitPlayer == NULL || dist < hitPlayerDistance) { + if (!hitPlayer || dist < hitPlayerDistance) { hitPlayer = other; hitPlayerDistance = dist; hitPlayerActualDistance = (hitPos - muzzle).GetLength(); @@ -635,13 +649,13 @@ namespace spades { Vector3 finalHitPos; finalHitPos = muzzle + dir * 128.f; - if (hitPlayer == nullptr && !mapResult.hit) { + if (!hitPlayer && !mapResult.hit) { // might hit water surface. } - float hLength = GetHorizontalLength(mapResult.hitPos - muzzle); - if (mapResult.hit && hLength < 128.f && - (hitPlayer == NULL || hLength < hitPlayerDistance)) { + if (mapResult.hit && GetHorizontalLength(mapResult.hitPos - muzzle) < 128.f && + (!hitPlayer || + GetHorizontalLength(mapResult.hitPos - muzzle) < hitPlayerDistance)) { IntVector3 outBlockCoord = mapResult.hitBlock; // TODO: set correct ray distance @@ -651,13 +665,13 @@ namespace spades { outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() && outBlockCoord.z < map->Depth()) { if (outBlockCoord.z == 63) { - if (world->GetListener()) - world->GetListener()->BulletHitBlock( + if (world.GetListener()) + world.GetListener()->BulletHitBlock( mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } else if (outBlockCoord.z == 62) { // blocks at this level cannot be damaged - if (world->GetListener()) - world->GetListener()->BulletHitBlock( + if (world.GetListener()) + world.GetListener()->BulletHitBlock( mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } else { int x = outBlockCoord.x; @@ -675,22 +689,22 @@ namespace spades { health = 0; blockDestroyed = true; // send destroy cmd - if (world->GetListener() && world->GetLocalPlayer() == this) - world->GetListener()->LocalPlayerBlockAction(outBlockCoord, - BlockActionTool); + if (world.GetListener() && world.GetLocalPlayer() == this) + world.GetListener()->LocalPlayerBlockAction(outBlockCoord, + BlockActionTool); } color = (color & 0xffffff) | ((uint32_t)health << 24); if (map->IsSolid(x, y, z)) map->Set(x, y, z, true, color); - world->MarkBlockForRegeneration(outBlockCoord); + world.MarkBlockForRegeneration(outBlockCoord); - if (world->GetListener()) - world->GetListener()->BulletHitBlock( + if (world.GetListener()) + world.GetListener()->BulletHitBlock( mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } } - } else if (hitPlayer != NULL) { + } else if (hitPlayer) { if (hitPlayerDistance < 128.f) { finalHitPos = muzzle + dir * hitPlayerActualDistance; @@ -714,28 +728,24 @@ namespace spades { case HitBodyPart::None: SPAssert(false); break; } - if (world->GetListener()) { + if (world.GetListener()) { switch (hitPart) { case HitBodyPart::Head: - world->GetListener()->BulletHitPlayer( - hitPlayer, HitTypeHead, finalHitPos, - this); + world.GetListener()->BulletHitPlayer( + *hitPlayer, HitTypeHead, finalHitPos, *this, stateCell); break; case HitBodyPart::Torso: - world->GetListener()->BulletHitPlayer( - hitPlayer, HitTypeTorso, finalHitPos, - this); + world.GetListener()->BulletHitPlayer( + *hitPlayer, HitTypeTorso, finalHitPos, *this, stateCell); break; case HitBodyPart::Limb1: case HitBodyPart::Limb2: - world->GetListener()->BulletHitPlayer( - hitPlayer, HitTypeLegs, finalHitPos, - this); + world.GetListener()->BulletHitPlayer( + *hitPlayer, HitTypeLegs, finalHitPos, *this, stateCell); break; case HitBodyPart::Arms: - world->GetListener()->BulletHitPlayer( - hitPlayer, HitTypeArms, finalHitPos, - this); + world.GetListener()->BulletHitPlayer( + *hitPlayer, HitTypeArms, finalHitPos, *this, stateCell); break; case HitBodyPart::None: SPAssert(false); break; } @@ -743,14 +753,14 @@ namespace spades { } } - if (world->GetListener() && this != world->GetLocalPlayer()) - world->GetListener()->AddBulletTracer(this, muzzle, finalHitPos); + if (world.GetListener()) + world.GetListener()->AddBulletTracer(*this, muzzle, finalHitPos); // one pellet done } // do hit test debugging - auto *debugger = world->GetHitTestDebugger(); + auto *debugger = world.GetHitTestDebugger(); if (debugger && IsLocalPlayer()) { debugger->SaveImage(playerHits, bulletVectors); } @@ -762,7 +772,7 @@ namespace spades { upLimit -= 0.03f; // ??? // vanilla's horizontial recoil is driven by a triangular wave generator. - int time = (int) (world->GetTime() * 1000); + int time = (int)(world.GetTime() * 1000); float triWave; if (time % 1024 < 512) { triWave = (time % 512) - 255.5; @@ -789,10 +799,12 @@ namespace spades { horzModifier *= sqrt(1 - pow(o.z, 4)); - o += GetRight() * rec.x * triWave * horzModifier; - o += GetUp() * std::min(rec.y, std::max(0.f, upLimit)) * vertModifier; - o = o.Normalize(); - SetOrientation(o); + if (this->IsLocalPlayer()) { + o += GetRight() * rec.x * triWave * horzModifier; + o += GetUp() * std::min(rec.y, std::max(0.f, upLimit)) * vertModifier; + o = o.Normalize(); + SetOrientation(o); + } reloadingServerSide = false; } @@ -806,7 +818,7 @@ namespace spades { Vector3 muzzle = GetEye() + GetFront() * 0.1f; Vector3 vel = GetFront() * 1.f; - float fuse = world->GetTime() - grenadeTime; + float fuse = world.GetTime() - grenadeTime; fuse = 3.f - fuse; if (health <= 0) { @@ -816,15 +828,15 @@ namespace spades { vel += GetVelocity(); - if (this == world->GetLocalPlayer()) { - Grenade *gren = new Grenade(world, muzzle, vel, fuse); - world->AddGrenade(gren); - if (world->GetListener()) - world->GetListener()->PlayerThrownGrenade(this, gren); + if (this == world.GetLocalPlayer()) { + auto gren = stmp::make_unique(world, muzzle, vel, fuse); + if (world.GetListener()) + world.GetListener()->PlayerThrewGrenade(*this, *gren); + world.AddGrenade(std::move(gren)); } else { // grenade packet will be sent by server - if (world->GetListener()) - world->GetListener()->PlayerThrownGrenade(this, NULL); + if (world.GetListener()) + world.GetListener()->PlayerThrewGrenade(*this, {}); } holdingGrenade = false; @@ -834,9 +846,11 @@ namespace spades { SPADES_MARK_FUNCTION(); IntVector3 outBlockCoord; - GameMap *map = world->GetMap(); + Handle map = world.GetMap(); Vector3 muzzle = GetEye(), dir = GetFront(); + SPAssert(map); + // TODO: set correct ray distance // first do map raycast GameMap::RayCastResult mapResult; @@ -853,20 +867,20 @@ namespace spades { SPAssert(map->IsSolid(outBlockCoord.x, outBlockCoord.y, outBlockCoord.z)); // send destroy command only for local cmd - if (this == world->GetLocalPlayer()) { + if (this == world.GetLocalPlayer()) { - if (world->GetListener()) - world->GetListener()->LocalPlayerBlockAction(outBlockCoord, - BlockActionDig); + if (world.GetListener()) + world.GetListener()->LocalPlayerBlockAction(outBlockCoord, + BlockActionDig); } - if (world->GetListener()) - world->GetListener()->PlayerHitBlockWithSpade( - this, mapResult.hitPos, mapResult.hitBlock, mapResult.normal); + if (world.GetListener()) + world.GetListener()->PlayerHitBlockWithSpade( + *this, mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } } else { - if (world->GetListener()) - world->GetListener()->PlayerMissedSpade(this); + if (world.GetListener()) + world.GetListener()->PlayerMissedSpade(*this); } } @@ -878,27 +892,31 @@ namespace spades { Vector3 muzzle = GetEye(), dir = GetFront(); IntVector3 outBlockCoord; - GameMap *map = world->GetMap(); + Handle map = world.GetMap(); + SPAssert(map); + // TODO: set correct ray distance // first do map raycast GameMap::RayCastResult mapResult; mapResult = map->CastRay2(muzzle, dir, 256); - Player *hitPlayer = NULL; + stmp::optional hitPlayer; int hitFlag = 0; - for (int i = 0; i < world->GetNumPlayerSlots(); i++) { - Player *other = world->GetPlayer(i); - if (other == this || other == NULL) + for (int i = 0; i < world.GetNumPlayerSlots(); i++) { + auto maybeOther = world.GetPlayer(i); + if (maybeOther == this || !maybeOther) continue; - if (other == this || !other->IsAlive() || other->GetTeamId() >= 2) + + Player &other = maybeOther.value(); + if (!other.IsAlive() || other.GetTeamId() >= 2) continue; - if (!other->RayCastApprox(muzzle, dir)) + if (!other.RayCastApprox(muzzle, dir)) continue; - if ((eye - other->GetEye()).GetChebyshevLength() >= MELEE_DISTANCE_F) + if ((eye - other.GetEye()).GetChebyshevLength() >= MELEE_DISTANCE_F) continue; - Vector3 diff = other->GetEye() - eye; + Vector3 diff = other.GetEye() - eye; Vector3 view; view.x = Vector3::Dot(diff, GetRight()); view.y = Vector3::Dot(diff, GetUp()); @@ -920,7 +938,7 @@ namespace spades { outBlockCoord = mapResult.hitBlock; if (mapResult.hit && BoxDistanceToBlock(mapResult.hitBlock + mapResult.normal) < 3.f && - (hitPlayer == NULL) && outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && + !hitPlayer && outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 && outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() && outBlockCoord.z < map->Depth()) { if (outBlockCoord.z < 62) { @@ -936,34 +954,34 @@ namespace spades { if (health <= 0) { health = 0; // send destroy command only for local cmd - if (this == world->GetLocalPlayer()) { - if (world->GetListener()) - world->GetListener()->LocalPlayerBlockAction(outBlockCoord, - BlockActionTool); + if (this == world.GetLocalPlayer()) { + if (world.GetListener()) + world.GetListener()->LocalPlayerBlockAction(outBlockCoord, + BlockActionTool); } } color = (color & 0xffffff) | ((uint32_t)health << 24); if (map->IsSolid(x, y, z)) map->Set(x, y, z, true, color); - world->MarkBlockForRegeneration(outBlockCoord); + world.MarkBlockForRegeneration(outBlockCoord); - if (world->GetListener()) - world->GetListener()->PlayerHitBlockWithSpade( - this, mapResult.hitPos, mapResult.hitBlock, mapResult.normal); + if (world.GetListener()) + world.GetListener()->PlayerHitBlockWithSpade( + *this, mapResult.hitPos, mapResult.hitBlock, mapResult.normal); } - } else if (hitPlayer != NULL) { + } else if (hitPlayer && world.GetListener() && hitFlag) { + // The custom state data, optionally set by `BulletHitPlayer`'s implementation + std::unique_ptr stateCell; - if (world->GetListener()) { - if (hitFlag) - world->GetListener()->BulletHitPlayer(hitPlayer, HitTypeMelee, - hitPlayer->GetEye(), this); - } + if (hitFlag) + world.GetListener()->BulletHitPlayer(*hitPlayer, HitTypeMelee, + hitPlayer->GetEye(), *this, stateCell); } if (missed) { - if (world->GetListener()) - world->GetListener()->PlayerMissedSpade(this); + if (world.GetListener()) + world.GetListener()->PlayerMissedSpade(*this); } } @@ -1024,7 +1042,9 @@ namespace spades { float nz = position.z + offset; float z; - GameMap *map = world->GetMap(); + const Handle &map = world.GetMap(); + + SPAssert(map); if (velocity.x < 0.f) f = -0.45f; @@ -1083,7 +1103,7 @@ namespace spades { if (climb) { velocity.x *= .5f; velocity.y *= .5f; - lastClimbTime = world->GetTime(); + lastClimbTime = world.GetTime(); nz -= 1.f; m = -1.35f; } else { @@ -1116,9 +1136,9 @@ namespace spades { void Player::ForceJump() { velocity.z = -0.36f; lastJump = true; - if (world->GetListener() && world->GetTime() > lastJumpTime + .1f) { - world->GetListener()->PlayerJumped(this); - lastJumpTime = world->GetTime(); + if (world.GetListener() && world.GetTime() > lastJumpTime + .1f) { + world.GetListener()->PlayerJumped(*this); + lastJumpTime = world.GetTime(); } } @@ -1126,9 +1146,9 @@ namespace spades { if (input.jump && (!lastJump) && IsOnGroundOrWade()) { velocity.z = -0.36f; lastJump = true; - if (world->GetListener() && world->GetTime() > lastJumpTime + .1f) { - world->GetListener()->PlayerJumped(this); - lastJumpTime = world->GetTime(); + if (world.GetListener() && world.GetTime() > lastJumpTime + .1f) { + world.GetListener()->PlayerJumped(*this); + lastJumpTime = world.GetTime(); } } else if (!input.jump) { lastJump = false; @@ -1195,12 +1215,12 @@ namespace spades { velocity.y *= .5f; if (f2 > FALL_DAMAGE_VELOCITY) { - if (world->GetListener()) { - world->GetListener()->PlayerLanded(this, true); + if (world.GetListener()) { + world.GetListener()->PlayerLanded(*this, true); } } else { - if (world->GetListener()) { - world->GetListener()->PlayerLanded(this, false); + if (world.GetListener()) { + world.GetListener()->PlayerLanded(*this, false); } } } @@ -1219,15 +1239,15 @@ namespace spades { moveSteps++; moveDistance -= 1.f; - if (world->GetListener() && !madeFootstep) { - world->GetListener()->PlayerMadeFootstep(this); + if (world.GetListener() && !madeFootstep) { + world.GetListener()->PlayerMadeFootstep(*this); madeFootstep = true; } } } } - bool Player::TryUncrouch(bool move) { + bool Player::TryUncrouch() { SPADES_MARK_FUNCTION(); float x1 = position.x + 0.45f; @@ -1237,19 +1257,18 @@ namespace spades { float z1 = position.z + 2.25f; float z2 = position.z - 1.35f; - GameMap *map = world->GetMap(); + const Handle &map = world.GetMap(); + + SPAssert(map); // lower feet - if (airborne && - !(map->ClipBox(x1, y1, z1) || map->ClipBox(x2, y1, z1) || - map->ClipBox(x1, y2, z1) || map->ClipBox(x2, y2, z1))) + if (airborne && !(map->ClipBox(x1, y1, z1) || map->ClipBox(x2, y1, z1) || + map->ClipBox(x1, y2, z1) || map->ClipBox(x2, y2, z1))) { return true; - else if (!(map->ClipBox(x1, y1, z2) || map->ClipBox(x2, y1, z2) || + } else if (!(map->ClipBox(x1, y1, z2) || map->ClipBox(x2, y1, z2) || map->ClipBox(x1, y2, z2) || map->ClipBox(x2, y2, z2))) { - if (move) { - position.z -= 0.9f; - eye.z -= 0.9f; - } + position.z -= 0.9f; + eye.z -= 0.9f; return true; } return false; @@ -1259,7 +1278,7 @@ namespace spades { SPADES_MARK_FUNCTION(); eye = position = pos2; - float f = lastClimbTime - world->GetTime(); + float f = lastClimbTime - world.GetTime(); if (f > -.25f) eye.z += (f + .25f) / .25f; } @@ -1291,7 +1310,7 @@ namespace spades { SPAssert(tool == ToolSpade); SPAssert(weapInput.primary); - return 1.f - (nextSpadeTime - world->GetTime()) / GetToolPrimaryDelay(); + return 1.f - (nextSpadeTime - world.GetTime()) / GetToolPrimaryDelay(); } float Player::GetDigAnimationProgress() { @@ -1299,32 +1318,32 @@ namespace spades { SPAssert(tool == ToolSpade); SPAssert(weapInput.secondary); - return 1.f - (nextDigTime - world->GetTime()) / GetToolSecondaryDelay(); + return 1.f - (nextDigTime - world.GetTime()) / GetToolSecondaryDelay(); } - float Player::GetTimeToNextGrenade() { return nextGrenadeTime - world->GetTime(); } + float Player::GetTimeToNextGrenade() { return nextGrenadeTime - world.GetTime(); } - void Player::KilledBy(KillType type, Player *killer, int respawnTime) { + void Player::KilledBy(KillType type, Player &killer, int respawnTime) { SPADES_MARK_FUNCTION(); health = 0; weapon->SetShooting(false); // if local player is killed while cooking grenade, // drop the live grenade. - if (this == world->GetLocalPlayer() && tool == ToolGrenade && holdingGrenade) { + if (this == world.GetLocalPlayer() && tool == ToolGrenade && holdingGrenade) { ThrowGrenade(); } - if (world->GetListener()) - world->GetListener()->PlayerKilledPlayer(killer, this, type); + if (world.GetListener()) + world.GetListener()->PlayerKilledPlayer(killer, *this, type); input = PlayerInput(); weapInput = WeaponInput(); - this->respawnTime = world->GetTime() + respawnTime; + this->respawnTime = world.GetTime() + respawnTime; } bool Player::IsAlive() { return health > 0; } - std::string Player::GetName() { return world->GetPlayerPersistent(GetId()).name; } + std::string Player::GetName() { return world.GetPlayerPersistent(GetId()).name; } float Player::GetWalkAnimationProgress() { return moveDistance * .5f + (float)(moveSteps)*.5f; @@ -1396,17 +1415,22 @@ namespace spades { return hb; } - IntVector3 Player::GetColor() { return world->GetTeam(teamId).color; } + IntVector3 Player::GetColor() { return world.GetTeam(teamId).color; } bool Player::IsCookingGrenade() { return tool == ToolGrenade && holdingGrenade; } - float Player::GetGrenadeCookTime() { return world->GetTime() - grenadeTime; } + float Player::GetGrenadeCookTime() { return world.GetTime() - grenadeTime; } + + Weapon &Player::GetWeapon() { + SPADES_MARK_FUNCTION(); + SPAssert(weapon); + return *weapon; + } void Player::SetWeaponType(WeaponType weap) { SPADES_MARK_FUNCTION_DEBUG(); if (this->weapon->GetWeaponType() == weap) return; - delete this->weapon; - this->weapon = Weapon::CreateWeapon(weap, this, *world->GetGameProperties()); + this->weapon.reset(Weapon::CreateWeapon(weap, *this, *world.GetGameProperties())); this->weaponType = weap; } @@ -1415,8 +1439,8 @@ namespace spades { bool Player::IsReadyToUseTool() { SPADES_MARK_FUNCTION_DEBUG(); switch (tool) { - case ToolBlock: return world->GetTime() > nextBlockTime && blockStocks > 0; - case ToolGrenade: return world->GetTime() > nextGrenadeTime && grenades > 0; + case ToolBlock: return world.GetTime() > nextBlockTime && blockStocks > 0; + case ToolGrenade: return world.GetTime() > nextGrenadeTime && grenades > 0; case ToolSpade: return true; case ToolWeapon: return weapon->IsReadyToShoot(); } @@ -1462,5 +1486,5 @@ namespace spades { return (e - eye).GetChebyshevLength(); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Player.h b/Sources/Client/Player.h index d452f3dd6..631464b7f 100644 --- a/Sources/Client/Player.h +++ b/Sources/Client/Player.h @@ -21,8 +21,10 @@ #pragma once -#include +#include + #include "PhysicsConstants.h" +#include namespace spades { namespace client { @@ -66,7 +68,7 @@ namespace spades { }; private: - World *world; + World &world; Vector3 position; Vector3 velocity; @@ -79,7 +81,7 @@ namespace spades { ToolType tool; WeaponType weaponType; - Weapon *weapon; + std::unique_ptr weapon; int playerId; int teamId; IntVector3 color; // obsolete @@ -127,6 +129,7 @@ namespace spades { void RepositionPlayer(const Vector3 &); void MovePlayer(float fsynctics); void BoxClipMove(float fsynctics); + bool TryUncrouch(); void UseSpade(); void DigWithSpade(); @@ -134,13 +137,16 @@ namespace spades { void ThrowGrenade(); public: - Player(World *, int playerId, WeaponType weapon, int teamId, Vector3 position, + Player(World &, int playerId, WeaponType weapon, int teamId, Vector3 position, IntVector3 color); + Player(const Player &) = delete; + void operator=(const Player &) = delete; + ~Player(); int GetId() { return playerId; } - Weapon *GetWeapon() { return weapon; } + Weapon &GetWeapon(); WeaponType GetWeaponType() { return weaponType; } int GetTeamId() { return teamId; } bool IsSpectator() { return teamId >= 2; } @@ -188,7 +194,7 @@ namespace spades { void UsedBlocks(int c) { blockStocks = std::max(blockStocks - c, 0); } /** makes player's health 0. */ - void KilledBy(KillType, Player *killer, int respawnTime); + void KilledBy(KillType, Player &killer, int respawnTime); bool IsAlive(); /** @return world time to respawn */ @@ -207,13 +213,12 @@ namespace spades { Vector3 GetVelocity() { return velocity; } int GetMoveSteps() { return moveSteps; } - World *GetWorld() { return world; } + World &GetWorld() { return world; } bool GetWade(); bool IsOnGroundOrWade(); void Update(float dt); - bool TryUncrouch(bool move); // ?? float GetToolPrimaryDelay(); float GetToolSecondaryDelay(); @@ -241,5 +246,5 @@ namespace spades { float BoxDistanceToBlock(IntVector3); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Quake3Font.cpp b/Sources/Client/Quake3Font.cpp index ec42fef93..eb1f7eb62 100644 --- a/Sources/Client/Quake3Font.cpp +++ b/Sources/Client/Quake3Font.cpp @@ -175,5 +175,5 @@ namespace spades { x += MeasureFallback(ch, (yMax - yMin) * scale) * invScale; } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Quake3Font.h b/Sources/Client/Quake3Font.h index 5881c8248..4351a24e6 100644 --- a/Sources/Client/Quake3Font.h +++ b/Sources/Client/Quake3Font.h @@ -56,5 +56,5 @@ namespace spades { void Draw(const std::string &, Vector2 offset, float scale, Vector4 color) override; void SetGlyphYRange(float yMin, float yMax); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/SceneDefinition.cpp b/Sources/Client/SceneDefinition.cpp index c29c215e7..f1745f8ed 100644 --- a/Sources/Client/SceneDefinition.cpp +++ b/Sources/Client/SceneDefinition.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2013 yvt + Copyright (c) 2021 yvt This file is part of OpenSpades. @@ -17,4 +17,58 @@ along with OpenSpades. If not, see . */ +#include + #include "SceneDefinition.h" + +namespace spades { + namespace client { + Matrix4 SceneDefinition::ToOpenGLProjectionMatrix() const { + float near = this->zNear; + float far = this->zFar; + float t = near * std::tan(this->fovY * .5f); + float r = near * std::tan(this->fovX * .5f); + float a = r * 2.f, b = t * 2.f, c = far - near; + + Matrix4 mat; + mat.m[0] = near * 2.f / a; + mat.m[1] = 0.f; + mat.m[2] = 0.f; + mat.m[3] = 0.f; + mat.m[4] = 0.f; + mat.m[5] = near * 2.f / b; + mat.m[6] = 0.f; + mat.m[7] = 0.f; + mat.m[8] = 0.f; + mat.m[9] = 0.f; + mat.m[10] = -(far + near) / c; + mat.m[11] = -1.f; + mat.m[12] = 0.f; + mat.m[13] = 0.f; + mat.m[14] = -(far * near * 2.f) / c; + mat.m[15] = 0.f; + + return mat; + } + + Matrix4 SceneDefinition::ToViewMatrix() const { + Matrix4 mat = Matrix4::Identity(); + mat.m[0] = this->viewAxis[0].x; + mat.m[4] = this->viewAxis[0].y; + mat.m[8] = this->viewAxis[0].z; + mat.m[1] = this->viewAxis[1].x; + mat.m[5] = this->viewAxis[1].y; + mat.m[9] = this->viewAxis[1].z; + mat.m[2] = -this->viewAxis[2].x; + mat.m[6] = -this->viewAxis[2].y; + mat.m[10] = -this->viewAxis[2].z; + + Vector4 v = mat * this->viewOrigin; + mat.m[12] = -v.x; + mat.m[13] = -v.y; + mat.m[14] = -v.z; + + return mat; + } + } // namespace client +} // namespace spades diff --git a/Sources/Client/SceneDefinition.h b/Sources/Client/SceneDefinition.h index 241074761..02e668c21 100644 --- a/Sources/Client/SceneDefinition.h +++ b/Sources/Client/SceneDefinition.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2013 yvt + Copyright (c) 2021 yvt This file is part of OpenSpades. @@ -56,6 +56,10 @@ namespace spades { saturation = 1.f; radialBlur = 0.f; } + + Matrix4 ToOpenGLProjectionMatrix() const; + + Matrix4 ToViewMatrix() const; }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ScoreboardView.cpp b/Sources/Client/ScoreboardView.cpp index 07653dce3..c686e1eb8 100644 --- a/Sources/Client/ScoreboardView.cpp +++ b/Sources/Client/ScoreboardView.cpp @@ -50,7 +50,6 @@ namespace spades { 1}; // Goldish yellow static const auto spectatorTeamId = 255; // Spectators have a team id of 255 - ScoreboardView::ScoreboardView(Client *client) : client(client), renderer(client->GetRenderer()) { SPADES_MARK_FUNCTION(); @@ -62,14 +61,12 @@ namespace spades { // Use GUI font if spectator string has special chars auto spectatorString = _TrN("Client", "Spectator{1}", "Spectators{1}", "", ""); auto has_special_char = - std::find_if(spectatorString.begin(), spectatorString.end(), - [](char ch) { - return !(isalnum(static_cast(ch)) || ch == '_'); - }) != spectatorString.end(); - - spectatorFont = has_special_char ? - client->fontManager->GetMediumFont() : - client->fontManager->GetSquareDesignFont(); + std::find_if(spectatorString.begin(), spectatorString.end(), [](char ch) { + return !(isalnum(static_cast(ch)) || ch == '_'); + }) != spectatorString.end(); + + spectatorFont = has_special_char ? client->fontManager->GetMediumFont() + : client->fontManager->GetSquareDesignFont(); } ScoreboardView::~ScoreboardView() {} @@ -81,7 +78,7 @@ namespace spades { int cnt = tc->GetNumTerritories(); int num = 0; for (int i = 0; i < cnt; i++) - if (tc->GetTerritory(i)->ownerTeamId == team) + if (tc->GetTerritory(i).ownerTeamId == team) num++; return num; } else { @@ -94,7 +91,8 @@ namespace spades { return MakeVector4(c.x / 255.f, c.y / 255.f, c.z / 255.f, 1.f); } - Vector4 ScoreboardView::AdjustColor(spades::Vector4 col, float bright, float saturation) const { + Vector4 ScoreboardView::AdjustColor(spades::Vector4 col, float bright, + float saturation) const { col.x *= bright; col.y *= bright; col.z *= bright; @@ -129,18 +127,24 @@ namespace spades { return; } - IGameMode *mode = world->GetMode(); - ctf = IGameMode::m_CTF == mode->ModeType() ? static_cast(mode) : NULL; - tc = IGameMode::m_TC == mode->ModeType() ? static_cast(mode) : NULL; + // TODO: `ctf` and `tc` are only valid throughout the method call's + // duration. Move them to a new context type + auto mode = world->GetMode(); + ctf = IGameMode::m_CTF == mode->ModeType() + ? dynamic_cast(mode.get_pointer()) + : NULL; + tc = IGameMode::m_TC == mode->ModeType() + ? dynamic_cast(mode.get_pointer()) + : NULL; Handle image; - IFont *font; + IFont &font = client->fontManager->GetSquareDesignFont(); Vector2 pos, size; std::string str; - float scrWidth = renderer->ScreenWidth(); - // float scrHeight = renderer->ScreenHeight(); + float scrWidth = renderer.ScreenWidth(); + // float scrHeight = renderer.ScreenHeight(); const Vector4 whiteColor = {1, 1, 1, 1}; - Handle whiteImage = renderer->RegisterImage("Gfx/White.tga"); + Handle whiteImage = renderer.RegisterImage("Gfx/White.tga"); float teamBarTop = 120.f; float teamBarHeight = 60.f; @@ -152,42 +156,41 @@ namespace spades { float playersBottom = playersTop + playersHeight; // draw shadow - image = renderer->RegisterImage("Gfx/Scoreboard/TopShadow.tga"); + image = renderer.RegisterImage("Gfx/Scoreboard/TopShadow.tga"); size.y = 32.f; - renderer->SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 0.2f)); - renderer->DrawImage(image, AABB2(0, teamBarTop - size.y, scrWidth, size.y)); - renderer->SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 0.2f)); - renderer->DrawImage(image, AABB2(0, playersBottom + size.y, scrWidth, -size.y)); + renderer.SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 0.2f)); + renderer.DrawImage(image, AABB2(0, teamBarTop - size.y, scrWidth, size.y)); + renderer.SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 0.2f)); + renderer.DrawImage(image, AABB2(0, playersBottom + size.y, scrWidth, -size.y)); // draw team bar image = whiteImage; - renderer->SetColorAlphaPremultiplied(AdjustColor(GetTeamColor(0), 0.8f, 0.3f)); - renderer->DrawImage(image, AABB2(0, teamBarTop, scrWidth * .5f, teamBarHeight)); - renderer->SetColorAlphaPremultiplied(AdjustColor(GetTeamColor(1), 0.8f, 0.3f)); - renderer->DrawImage(image, - AABB2(scrWidth * .5f, teamBarTop, scrWidth * .5f, teamBarHeight)); + renderer.SetColorAlphaPremultiplied(AdjustColor(GetTeamColor(0), 0.8f, 0.3f)); + renderer.DrawImage(image, AABB2(0, teamBarTop, scrWidth * .5f, teamBarHeight)); + renderer.SetColorAlphaPremultiplied(AdjustColor(GetTeamColor(1), 0.8f, 0.3f)); + renderer.DrawImage(image, + AABB2(scrWidth * .5f, teamBarTop, scrWidth * .5f, teamBarHeight)); - image = renderer->RegisterImage("Gfx/Scoreboard/Grunt.png"); + image = renderer.RegisterImage("Gfx/Scoreboard/Grunt.png"); size.x = 120.f; size.y = 60.f; - renderer->DrawImage( + renderer.DrawImage( image, AABB2(contentsLeft, teamBarTop + teamBarHeight - size.y, size.x, size.y)); - renderer->DrawImage( + renderer.DrawImage( image, AABB2(contentsRight, teamBarTop + teamBarHeight - size.y, -size.x, size.y)); - font = client->fontManager->GetSquareDesignFont(); str = world->GetTeam(0).name; pos.x = contentsLeft + 110.f; pos.y = teamBarTop + 5.f; - font->Draw(str, pos + MakeVector2(0, 2), 1.f, MakeVector4(0, 0, 0, 0.5)); - font->Draw(str, pos, 1.f, whiteColor); + font.Draw(str, pos + MakeVector2(0, 2), 1.f, MakeVector4(0, 0, 0, 0.5)); + font.Draw(str, pos, 1.f, whiteColor); str = world->GetTeam(1).name; - size = font->Measure(str); + size = font.Measure(str); pos.x = contentsRight - 110.f - size.x; pos.y = teamBarTop + 5.f; - font->Draw(str, pos + MakeVector2(0, 2), 1.f, MakeVector4(0, 0, 0, 0.5)); - font->Draw(str, pos, 1.f, whiteColor); + font.Draw(str, pos + MakeVector2(0, 2), 1.f, MakeVector4(0, 0, 0, 0.5)); + font.Draw(str, pos, 1.f, whiteColor); // draw scores int capLimit; @@ -200,23 +203,23 @@ namespace spades { } if (capLimit != -1) { str = Format("{0}-{1}", GetTeamScore(0), capLimit); - pos.x = scrWidth * .5f - font->Measure(str).x - 15.f; + pos.x = scrWidth * .5f - font.Measure(str).x - 15.f; pos.y = teamBarTop + 5.f; - font->Draw(str, pos, 1.f, Vector4(1.f, 1.f, 1.f, 0.5f)); + font.Draw(str, pos, 1.f, Vector4(1.f, 1.f, 1.f, 0.5f)); str = Format("{0}-{1}", GetTeamScore(1), capLimit); pos.x = scrWidth * .5f + 15.f; pos.y = teamBarTop + 5.f; - font->Draw(str, pos, 1.f, Vector4(1.f, 1.f, 1.f, 0.5f)); + font.Draw(str, pos, 1.f, Vector4(1.f, 1.f, 1.f, 0.5f)); } // players background auto areSpectatorsPr = areSpectatorsPresent(); - image = renderer->RegisterImage("Gfx/Scoreboard/PlayersBg.png"); - renderer->SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 1.f)); - renderer->DrawImage(image, - AABB2(0, playersTop, scrWidth, - playersHeight + (areSpectatorsPr ? spectatorsHeight : 0))); + image = renderer.RegisterImage("Gfx/Scoreboard/PlayersBg.png"); + renderer.SetColorAlphaPremultiplied(MakeVector4(0, 0, 0, 1.f)); + renderer.DrawImage(image, + AABB2(0, playersTop, scrWidth, + playersHeight + (areSpectatorsPr ? spectatorsHeight : 0))); // draw players DrawPlayers(0, contentsLeft, playersTop, (contentsRight - contentsLeft) * .5f, @@ -237,7 +240,7 @@ namespace spades { void ScoreboardView::DrawPlayers(int team, float left, float top, float width, float height) { - IFont *font = client->fontManager->GetGuiFont(); + IFont &font = client->fontManager->GetGuiFont(); float rowHeight = 24.f; char buf[256]; Vector2 size; @@ -249,16 +252,17 @@ namespace spades { std::vector entries; for (int i = 0; i < world->GetNumPlayerSlots(); i++) { - Player *p = world->GetPlayer(i); - if (!p) + auto maybePlayer = world->GetPlayer(i); + if (!maybePlayer) continue; - if (p->GetTeamId() != team) + Player &player = maybePlayer.value(); + if (player.GetTeamId() != team) continue; ScoreboardEntry ent; - ent.name = p->GetName(); + ent.name = player.GetName(); ent.score = world->GetPlayerPersistent(i).kills; - ent.alive = p->IsAlive(); + ent.alive = player.IsAlive(); ent.id = i; entries.push_back(ent); @@ -284,29 +288,29 @@ namespace spades { Vector4 color = white; sprintf(buf, "#%d", ent.id); // FIXME: 1-base? - size = font->Measure(buf); + size = font.Measure(buf); if (colormode == "1") { IntVector3 Colorplayer = IntVector3::Make(palette[ent.id][0], palette[ent.id][1], palette[ent.id][2]); Vector4 ColorplayerF = ModifyColor(Colorplayer); ColorplayerF *= 1.0f; - font->Draw(buf, MakeVector2(colX + 35.f - size.x, rowY), 1.f, ColorplayerF); + font.Draw(buf, MakeVector2(colX + 35.f - size.x, rowY), 1.f, ColorplayerF); } else { - font->Draw(buf, MakeVector2(colX + 35.f - size.x, rowY), 1.f, white); + font.Draw(buf, MakeVector2(colX + 35.f - size.x, rowY), 1.f, white); } color = ent.alive ? white : gray; - if (ent.id == world->GetLocalPlayerIndex()) + if (stmp::make_optional(ent.id) == world->GetLocalPlayerIndex()) color = GetTeamColor(team); - font->Draw(ent.name, MakeVector2(colX + 45.f, rowY), 1.f, color); + font.Draw(ent.name, MakeVector2(colX + 45.f, rowY), 1.f, color); color = white; sprintf(buf, "%d", ent.score); - size = font->Measure(buf); - font->Draw(buf, MakeVector2(colX + colWidth - 10.f - size.x, rowY), 1.f, color); + size = font.Measure(buf); + font.Draw(buf, MakeVector2(colX + colWidth - 10.f - size.x, rowY), 1.f, color); row++; if (row >= maxRows) { @@ -317,7 +321,7 @@ namespace spades { } void ScoreboardView::DrawSpectators(float top, float centerX) const { - IFont *font = client->fontManager->GetGuiFont(); + IFont &font = client->fontManager->GetGuiFont(); char buf[256]; std::vector entries; @@ -326,14 +330,16 @@ namespace spades { int numSpectators = 0; float totalPixelWidth = 0; for (int i = 0; i < world->GetNumPlayerSlots(); i++) { - Player *p = world->GetPlayer(i); - if (!p) + auto maybePlayer = world->GetPlayer(i); + if (!maybePlayer) continue; - if (p->GetTeamId() != spectatorTeamId) + Player &player = maybePlayer.value(); + + if (player.GetTeamId() != spectatorTeamId) continue; ScoreboardEntry ent; - ent.name = p->GetName(); + ent.name = player.GetName(); ent.id = i; entries.push_back(ent); @@ -342,7 +348,7 @@ namespace spades { // Measure total width in pixels so that we can center align all the spectators sprintf(buf, "#%d", ent.id); totalPixelWidth += - font->Measure(buf).x + font->Measure(ent.name).x + xPixelSpectatorOffset; + font.Measure(buf).x + font.Measure(ent.name).x + xPixelSpectatorOffset; } if (numSpectators == 0) { return; @@ -351,12 +357,11 @@ namespace spades { strcpy(buf, _TrN("Client", "Spectator{1}", "Spectators{1}", numSpectators, ":").c_str()); - auto isSquareFont = spectatorFont == client->fontManager->GetSquareDesignFont(); + auto isSquareFont = spectatorFont == &client->fontManager->GetSquareDesignFont(); auto sizeSpecString = spectatorFont->Measure(buf); - spectatorFont->Draw(buf, - MakeVector2(centerX - sizeSpecString.x / 2, top + (isSquareFont ? 0 : 10)), - 1.f, - spectatorTextColor); + spectatorFont->Draw( + buf, MakeVector2(centerX - sizeSpecString.x / 2, top + (isSquareFont ? 0 : 10)), 1.f, + spectatorTextColor); auto yOffset = top + sizeSpecString.y; auto halfTotalX = totalPixelWidth / 2; @@ -366,12 +371,12 @@ namespace spades { ScoreboardEntry &ent = entries[i]; sprintf(buf, "#%d", ent.id); - font->Draw(buf, MakeVector2(currentXoffset, yOffset), 1.f, spectatorIdColor); + font.Draw(buf, MakeVector2(currentXoffset, yOffset), 1.f, spectatorIdColor); - auto sizeName = font->Measure(ent.name); - auto sizeID = font->Measure(buf); - font->Draw(ent.name, MakeVector2(currentXoffset + sizeID.x + 5.f, yOffset), 1.f, - white); + auto sizeName = font.Measure(ent.name); + auto sizeID = font.Measure(buf); + font.Draw(ent.name, MakeVector2(currentXoffset + sizeID.x + 5.f, yOffset), 1.f, + white); currentXoffset += sizeID.x + sizeName.x + xPixelSpectatorOffset; } @@ -379,11 +384,11 @@ namespace spades { bool ScoreboardView::areSpectatorsPresent() const { for (auto i = 0; i < client->GetWorld()->GetNumPlayerSlots(); i++) { - auto *p = world->GetPlayer(i); - if (p && p->GetTeamId() == spectatorTeamId) + auto p = world->GetPlayer(i); + if (p && p.value().GetTeamId() == spectatorTeamId) return true; } return false; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/ScoreboardView.h b/Sources/Client/ScoreboardView.h index 9629d15ba..fdbf2c617 100644 --- a/Sources/Client/ScoreboardView.h +++ b/Sources/Client/ScoreboardView.h @@ -33,29 +33,26 @@ namespace spades { class IFont; class ScoreboardView { Client *client; - IRenderer *renderer; + IRenderer &renderer; IImage *image; World *world; CTFGameMode *ctf; TCGameMode *tc; - IFont *spectatorFont; + Handle spectatorFont; int GetTeamScore(int) const; Vector4 GetTeamColor(int); - Vector4 AdjustColor(Vector4 col, - float bright, - float saturation) const; - void DrawPlayers(int team, - float left, float top, - float width, float height); + Vector4 AdjustColor(Vector4 col, float bright, float saturation) const; + void DrawPlayers(int team, float left, float top, float width, float height); void DrawSpectators(float top, float width) const; bool areSpectatorsPresent() const; + public: ScoreboardView(Client *); ~ScoreboardView(); void Draw(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/SmokeSpriteEntity.cpp b/Sources/Client/SmokeSpriteEntity.cpp index f8738afce..8eda7251f 100644 --- a/Sources/Client/SmokeSpriteEntity.cpp +++ b/Sources/Client/SmokeSpriteEntity.cpp @@ -28,11 +28,12 @@ namespace spades { namespace client { static IRenderer *lastRenderer = NULL; - static IImage *lastSeq[180]; - static IImage *lastSeq2[48]; + static Handle lastSeq[180]; + static Handle lastSeq2[48]; // FIXME: add "image manager"? static void Load(IRenderer *r) { + // FIXME: Pointers are not unique identifiers since the same value could be reused if (r == lastRenderer) return; @@ -50,19 +51,19 @@ namespace spades { lastRenderer = r; } - IImage *SmokeSpriteEntity::GetSequence(int i, IRenderer *r, Type type) { + IImage &SmokeSpriteEntity::GetSequence(int i, IRenderer *r, Type type) { Load(r); if (type == Type::Steady) { SPAssert(i >= 0 && i < 180); - return lastSeq[i]; + return *lastSeq[i]; } else { SPAssert(i >= 0 && i < 48); - return lastSeq2[i]; + return *lastSeq2[i]; } } - SmokeSpriteEntity::SmokeSpriteEntity(Client *c, Vector4 color, float fps, Type type) - : ParticleSpriteEntity(c, GetSequence(0, c->GetRenderer(), type), color), + SmokeSpriteEntity::SmokeSpriteEntity(Client &client, Vector4 color, float fps, Type type) + : ParticleSpriteEntity(client, GetSequence(0, &client.GetRenderer(), type), color), fps(fps), type(type) { frame = 0.f; @@ -82,9 +83,9 @@ namespace spades { } int fId = (int)floorf(frame); - SetImage(GetSequence(fId, GetRenderer(), type)); + SetImage(GetSequence(fId, &GetRenderer(), type)); return ParticleSpriteEntity::Update(dt); } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/SmokeSpriteEntity.h b/Sources/Client/SmokeSpriteEntity.h index 3f1585cb2..7e5e77d9a 100644 --- a/Sources/Client/SmokeSpriteEntity.h +++ b/Sources/Client/SmokeSpriteEntity.h @@ -34,14 +34,14 @@ namespace spades { float frame; float fps; Type type; - static IImage *GetSequence(int i, IRenderer *r, Type); + static IImage &GetSequence(int i, IRenderer *r, Type); public: - SmokeSpriteEntity(Client *cli, Vector4 color, float fps, Type type = Type::Steady); + SmokeSpriteEntity(Client &cli, Vector4 color, float fps, Type type = Type::Steady); static void Preload(IRenderer *); bool Update(float dt) override; }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades diff --git a/Sources/Client/TCGameMode.cpp b/Sources/Client/TCGameMode.cpp index 642e3cb6e..6f36e5f0b 100644 --- a/Sources/Client/TCGameMode.cpp +++ b/Sources/Client/TCGameMode.cpp @@ -20,19 +20,17 @@ */ #include "TCGameMode.h" -#include #include "World.h" +#include namespace spades { namespace client { - TCGameMode::TCGameMode(World *w) : IGameMode(m_TC), world(w) { SPADES_MARK_FUNCTION(); } + TCGameMode::TCGameMode(World &w) : IGameMode(m_TC), world(w) { SPADES_MARK_FUNCTION(); } TCGameMode::~TCGameMode() { SPADES_MARK_FUNCTION(); } TCGameMode::Team &TCGameMode::GetTeam(int t) { SPADES_MARK_FUNCTION(); - SPAssert(t >= 0); - SPAssert(t < 2); - return teams[t]; + return teams.at(t); } void TCGameMode::AddTerritory(const spades::client::TCGameMode::Territory &t) { @@ -40,7 +38,7 @@ namespace spades { } float TCGameMode::Territory::GetProgress() { - float dt = mode->world->GetTime() - progressStartTime; + float dt = mode.world.GetTime() - progressStartTime; float prog = progressBasePos; prog += progressRate * dt; if (prog < 0.f) @@ -49,5 +47,5 @@ namespace spades { prog = 1.f; return prog; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/TCGameMode.h b/Sources/Client/TCGameMode.h index 6d353f2f3..9eac7ca80 100644 --- a/Sources/Client/TCGameMode.h +++ b/Sources/Client/TCGameMode.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include "IGameMode.h" @@ -32,7 +33,7 @@ namespace spades { class TCGameMode : public IGameMode { public: struct Territory { - TCGameMode *mode; + TCGameMode &mode; Vector3 pos; /** team that owns this territory, or 2 if this territory is currently neutral.*/ @@ -45,6 +46,8 @@ namespace spades { float progressRate; float progressStartTime; + Territory(TCGameMode &mode) : mode{mode} {} + /** gets capture progress of this territory. * 0 = ownerTeamId is capturing, 1 = 1-ownerTeamId has captured this. */ float GetProgress(); @@ -53,25 +56,26 @@ namespace spades { int captureLimit; private: - World *world; - Team teams[2]; + World &world; + std::array teams; std::vector territories; public: - TCGameMode(World *); + TCGameMode(World &); ~TCGameMode(); + TCGameMode(const TCGameMode &) = delete; + void operator=(const TCGameMode &) = delete; + Team &GetTeam(int t); int GetNumTerritories() const { return (int)territories.size(); } - Territory *GetTerritory(int index) { + Territory &GetTerritory(int index) { SPADES_MARK_FUNCTION(); - SPAssert(index >= 0); - SPAssert(index < GetNumTerritories()); - return &(territories[index]); + return territories.at(index); } void AddTerritory(const Territory &); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/TCProgressView.cpp b/Sources/Client/TCProgressView.cpp index 938c1f553..b68c1a689 100644 --- a/Sources/Client/TCProgressView.cpp +++ b/Sources/Client/TCProgressView.cpp @@ -34,22 +34,23 @@ namespace spades { float progress; // 0 = team1 owns }; - TCProgressView::TCProgressView(Client *c) : client(c), renderer(c->GetRenderer()) { + TCProgressView::TCProgressView(Client &client) + : client(client), renderer(client.GetRenderer()) { lastTerritoryId = -1; } TCProgressView::~TCProgressView() {} - static TCProgressState StateForTerritory(TCGameMode::Territory *t, int myTeam) { + static TCProgressState StateForTerritory(TCGameMode::Territory &t, int myTeam) { TCProgressState state; - if (t->capturingTeamId == -1) { - state.team1 = t->ownerTeamId; + if (t.capturingTeamId == -1) { + state.team1 = t.ownerTeamId; state.team2 = 2; state.progress = 0.f; } else { - float prg = t->GetProgress(); - state.team1 = t->ownerTeamId; - state.team2 = t->capturingTeamId; + float prg = t.GetProgress(); + state.team1 = t.ownerTeamId; + state.team2 = t.capturingTeamId; state.progress = prg; if (state.team2 == myTeam) { @@ -61,39 +62,42 @@ namespace spades { } void TCProgressView::Draw() { - World *w = client->GetWorld(); + World *w = client.GetWorld(); if (!w) { lastTerritoryId = -1; return; } - IGameMode *mode = w->GetMode(); + stmp::optional mode = w->GetMode(); if (!mode || IGameMode::m_TC != mode->ModeType()) { return; } - TCGameMode *tc = static_cast(mode); + TCGameMode &tc = dynamic_cast(mode.value()); - float scrW = renderer->ScreenWidth(); - float scrH = renderer->ScreenHeight(); + float scrW = renderer.ScreenWidth(); + float scrH = renderer.ScreenHeight(); - Handle prgBg = renderer->RegisterImage("Gfx/TC/ProgressBg.png"); - Handle prgBar = renderer->RegisterImage("Gfx/TC/ProgressBar.png"); + Handle prgBg = renderer.RegisterImage("Gfx/TC/ProgressBg.png"); + Handle prgBar = renderer.RegisterImage("Gfx/TC/ProgressBar.png"); + + stmp::optional maybePlayer = w->GetLocalPlayer(); + if (maybePlayer && maybePlayer.value().GetTeamId() < 2 && + maybePlayer.value().IsAlive()) { + Player &p = maybePlayer.value(); - Player *p = w->GetLocalPlayer(); - if (p && p->GetTeamId() < 2 && p->IsAlive()) { // show approaching territory - TCGameMode::Territory *nearTerritory = NULL; + stmp::optional nearTerritory; int nearTerId = 0; float distance = 0.f; - int myTeam = p->GetTeamId(); + int myTeam = p.GetTeamId(); - int cnt = tc->GetNumTerritories(); + int cnt = tc.GetNumTerritories(); for (int i = 0; i < cnt; i++) { - TCGameMode::Territory *t = tc->GetTerritory(i); - Vector3 diff = t->pos - p->GetEye(); + TCGameMode::Territory &t = tc.GetTerritory(i); + Vector3 diff = t.pos - p.GetEye(); if (fabsf(diff.x) < 18.f && fabsf(diff.y) < 18.f && fabsf(diff.z) < 18.f) { float dist = diff.GetPoweredLength(); - if (nearTerritory == NULL || dist < distance) { - nearTerritory = t; + if (!nearTerritory || dist < distance) { + nearTerritory = &t; nearTerId = i; distance = dist; } @@ -106,45 +110,45 @@ namespace spades { lastTerritoryTime = w->GetTime(); } else if (lastTerritoryId != -1 && w->GetTime() < lastTerritoryTime + 2.f) { fade = 1.f - (w->GetTime() - lastTerritoryTime) / 2.f; - nearTerritory = tc->GetTerritory(lastTerritoryId); + nearTerritory = &tc.GetTerritory(lastTerritoryId); } if (nearTerritory) { - TCProgressState state = StateForTerritory(nearTerritory, myTeam); + TCProgressState state = StateForTerritory(*nearTerritory, myTeam); float x = (scrW - 256.f) * .5f; float y = scrH * 0.7f; if (nearTerritory->ownerTeamId == 2) { - renderer->SetColorAlphaPremultiplied(MakeVector4(fade, fade, fade, fade)); + renderer.SetColorAlphaPremultiplied(MakeVector4(fade, fade, fade, fade)); } else { IntVector3 c = w->GetTeam(nearTerritory->ownerTeamId).color; - renderer->SetColorAlphaPremultiplied( + renderer.SetColorAlphaPremultiplied( MakeVector4(c.x / 255.f, c.y / 255.f, c.z / 255.f, 1) * fade); } - renderer->DrawImage(prgBg, MakeVector2(x, y)); + renderer.DrawImage(prgBg, MakeVector2(x, y)); // get away from border state.progress += (.5f - state.progress) * 12.f / 256.f; if (state.team1 != 2) { IntVector3 c = w->GetTeam(state.team1).color; - renderer->SetColorAlphaPremultiplied( + renderer.SetColorAlphaPremultiplied( MakeVector4(c.x / 255.f, c.y / 255.f, c.z / 255.f, 1) * (fade * 0.8f)); - renderer->DrawImage(prgBar, MakeVector2(x, y), - AABB2(0, 0, (1.f - state.progress) * 256.f, 32)); + renderer.DrawImage(prgBar, MakeVector2(x, y), + AABB2(0, 0, (1.f - state.progress) * 256.f, 32)); } if (state.team2 != 2) { IntVector3 c = w->GetTeam(state.team2).color; - renderer->SetColorAlphaPremultiplied( + renderer.SetColorAlphaPremultiplied( MakeVector4(c.x / 255.f, c.y / 255.f, c.z / 255.f, 1) * (fade * 0.8f)); - renderer->DrawImage( + renderer.DrawImage( prgBar, MakeVector2(x + (1.f - state.progress) * 256.f, y), AABB2((1.f - state.progress) * 256.f, 0, state.progress * 256.f, 32)); } - IFont *font = client->fontManager->GetGuiFont(); + IFont &font = client.fontManager->GetGuiFont(); std::string str; if (nearTerritory->ownerTeamId == 2) { @@ -154,17 +158,17 @@ namespace spades { str = _Tr("Client", "{0}'s Territory", str); } - Vector2 size = font->Measure(str); + Vector2 size = font.Measure(str); x = (scrW - size.x) * .5f; y += 35.f; - font->DrawShadow(str, MakeVector2(x, y), 1.f, MakeVector4(1.f, 1.f, 1.f, fade), - MakeVector4(0, 0, 0, 0.5f * fade)); + font.DrawShadow(str, MakeVector2(x, y), 1.f, MakeVector4(1.f, 1.f, 1.f, fade), + MakeVector4(0, 0, 0, 0.5f * fade)); } } else { // unable to show nearby territory lastTerritoryId = -1; } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/TCProgressView.h b/Sources/Client/TCProgressView.h index 8d91f641e..13d35fb98 100644 --- a/Sources/Client/TCProgressView.h +++ b/Sources/Client/TCProgressView.h @@ -25,17 +25,17 @@ namespace spades { class Client; class IRenderer; class TCProgressView { - Client *client; - IRenderer *renderer; + Client &client; + IRenderer &renderer; int lastTerritoryId; float lastTerritoryTime; public: - TCProgressView(Client *); + TCProgressView(Client &); ~TCProgressView(); void Draw(); }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades diff --git a/Sources/Client/Tracer.cpp b/Sources/Client/Tracer.cpp index e56563376..3fe202beb 100644 --- a/Sources/Client/Tracer.cpp +++ b/Sources/Client/Tracer.cpp @@ -6,6 +6,8 @@ // Copyright (c) 2013 yvt.jp. All rights reserved. // +#include + #include "Tracer.h" #include "Client.h" #include "IRenderer.h" @@ -13,23 +15,26 @@ namespace spades { namespace client { - Tracer::Tracer(Client *cli, Vector3 p1, Vector3 p2, float bulletVel) - : client(cli), startPos(p1), velocity(bulletVel) { + Tracer::Tracer(Client &_client, Vector3 p1, Vector3 p2, float bulletVel) + : client(_client), startPos(p1), velocity(bulletVel) { dir = (p2 - p1).Normalize(); length = (p2 - p1).GetLength(); - velocity *= 0.5f; // make it slower for visual effect - - const float maxTimeSpread = 1.0f / 30.f; - const float shutterTime = 1.0f / 30.f; + const float maxTimeSpread = 1.0f / 60.f; + const float shutterTime = 1.0f / 100.f; visibleLength = shutterTime * velocity; curDistance = -visibleLength; - curDistance += maxTimeSpread * SampleRandomFloat(); + + // Randomize the starting position within the range of the shutter + // time. However, make sure the tracer is displayed for at least + // one frame. + curDistance += + std::min(length + visibleLength, maxTimeSpread * SampleRandomFloat() * velocity); firstUpdate = true; - image = cli->GetRenderer()->RegisterImage("Gfx/Ball.png"); + image = client.GetRenderer().RegisterImage("Gfx/Ball.png"); } bool Tracer::Update(float dt) { @@ -44,8 +49,8 @@ namespace spades { } void Tracer::Render3D() { - IRenderer *r = client->GetRenderer(); - if (dynamic_cast(r)) { + IRenderer &r = client.GetRenderer(); + if (dynamic_cast(&r)) { // SWRenderer doesn't support long sprites (yet) float startDist = curDistance; float endDist = curDistance + visibleLength; @@ -59,8 +64,10 @@ namespace spades { Vector3 pos1 = startPos + dir * startDist; Vector3 pos2 = startPos + dir * endDist; Vector4 col = {1.f, .6f, .2f, 0.f}; - r->AddDebugLine(pos1, pos2, Vector4{1.0f, 0.6f, 0.2f, 1.0f}); + r.AddDebugLine(pos1, pos2, Vector4{1.0f, 0.6f, 0.2f, 1.0f}); } else { + SceneDefinition sceneDef = client.GetLastSceneDef(); + for (float step = 0.0f; step <= 1.0f; step += 0.1f) { float startDist = curDistance; float endDist = curDistance + visibleLength; @@ -75,15 +82,20 @@ namespace spades { continue; } + Vector3 pos1 = startPos + dir * startDist; Vector3 pos2 = startPos + dir * endDist; Vector4 col = {1.f, .6f, .2f, 0.f}; - r->SetColorAlphaPremultiplied(col * 0.4f); - r->AddLongSprite(image, pos1, pos2, .05f); + + float distanceToCamera = (pos2 - sceneDef.viewOrigin).GetLength(); + float radius = 0.002f * distanceToCamera; + + r.SetColorAlphaPremultiplied(col * 0.4f); + r.AddLongSprite(*image, pos1, pos2, radius); } } } Tracer::~Tracer() {} - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Tracer.h b/Sources/Client/Tracer.h index 918a5c50c..caaed4820 100644 --- a/Sources/Client/Tracer.h +++ b/Sources/Client/Tracer.h @@ -8,16 +8,17 @@ #pragma once -#include #include "ILocalEntity.h" +#include +#include namespace spades { namespace client { class Client; class IImage; class Tracer : public ILocalEntity { - Client *client; - IImage *image; + Client &client; + Handle image; Vector3 startPos, dir; float length; float curDistance; @@ -26,11 +27,11 @@ namespace spades { bool firstUpdate; public: - Tracer(Client *, Vector3 p1, Vector3 p2, float bulletVel); + Tracer(Client &, Vector3 p1, Vector3 p2, float bulletVel); ~Tracer(); bool Update(float dt) override; void Render3D() override; }; - } -} \ No newline at end of file + } // namespace client +} // namespace spades diff --git a/Sources/Client/Weapon.cpp b/Sources/Client/Weapon.cpp index a5a14e70a..6c14582b7 100644 --- a/Sources/Client/Weapon.cpp +++ b/Sources/Client/Weapon.cpp @@ -28,12 +28,12 @@ namespace spades { namespace client { - Weapon::Weapon(World *w, Player *p) + Weapon::Weapon(World &w, Player &p) : world(w), owner(p), time(0), shooting(false), - shootingPreviously(false), + shootingPreviously(false), reloading(false), nextShotTime(0.f), reloadStartTime(-101.f), @@ -59,7 +59,7 @@ namespace spades { void Weapon::SetShooting(bool b) { shooting = b; } bool Weapon::IsReadyToShoot() { - return (ammo > 0 || !owner->IsLocalPlayer()) && time >= nextShotTime && + return (ammo > 0 || !owner.IsLocalPlayer()) && time >= nextShotTime && (!reloading || IsReloadSlow()); } @@ -72,7 +72,7 @@ namespace spades { bool Weapon::FrameNext(float dt) { SPADES_MARK_FUNCTION(); - bool ownerIsLocalPlayer = owner->IsLocalPlayer(); + bool ownerIsLocalPlayer = owner.IsLocalPlayer(); bool fired = false; bool dryFire = false; @@ -93,8 +93,8 @@ namespace spades { ammo--; } - if (world->GetListener()) { - world->GetListener()->PlayerFiredWeapon(owner); + if (world.GetListener()) { + world.GetListener()->PlayerFiredWeapon(owner); } nextShotTime += GetDelay(); } else if (time >= nextShotTime) { @@ -128,22 +128,22 @@ namespace spades { slowReloadLeftCount--; if (slowReloadLeftCount > 0) Reload(false); - else if (world->GetListener()) - world->GetListener()->PlayerReloadedWeapon(owner); + else if (world.GetListener()) + world.GetListener()->PlayerReloadedWeapon(owner); } else { if (!ownerIsLocalPlayer) { ammo = GetClipSize(); } - if (world->GetListener()) - world->GetListener()->PlayerReloadedWeapon(owner); + if (world.GetListener()) + world.GetListener()->PlayerReloadedWeapon(owner); } } } time += dt; if (dryFire && !lastDryFire) { - if (world->GetListener()) - world->GetListener()->PlayerDryFiredWeapon(owner); + if (world.GetListener()) + world.GetListener()->PlayerDryFiredWeapon(owner); } lastDryFire = dryFire; return fired; @@ -163,7 +163,7 @@ namespace spades { void Weapon::Reload(bool initial) { SPADES_MARK_FUNCTION(); - bool ownerIsLocalPlayer = owner->IsLocalPlayer(); + bool ownerIsLocalPlayer = owner.IsLocalPlayer(); if (reloading) return; @@ -171,7 +171,7 @@ namespace spades { // Is the clip already full? if (ammo >= GetClipSize()) return; - + if (ownerIsLocalPlayer) { if (stock == 0) return; @@ -186,8 +186,8 @@ namespace spades { reloadStartTime = time; reloadEndTime = time + GetReloadTime(); - if (world->GetListener()) - world->GetListener()->PlayerReloadingWeapon(owner); + if (world.GetListener()) + world.GetListener()->PlayerReloadingWeapon(owner); } void Weapon::ForceReloadDone() { @@ -199,7 +199,7 @@ namespace spades { class RifleWeapon3 : public Weapon { public: - RifleWeapon3(World *w, Player *p) : Weapon(w, p) {} + RifleWeapon3(World &w, Player &p) : Weapon(w, p) {} std::string GetName() override { return "Rifle"; } float GetDelay() override { return 0.5f; } int GetClipSize() override { return 10; } @@ -226,7 +226,7 @@ namespace spades { class SMGWeapon3 : public Weapon { public: - SMGWeapon3(World *w, Player *p) : Weapon(w, p) {} + SMGWeapon3(World &w, Player &p) : Weapon(w, p) {} std::string GetName() override { return "SMG"; } float GetDelay() override { return 0.1f; } int GetClipSize() override { return 30; } @@ -253,7 +253,7 @@ namespace spades { class ShotgunWeapon3 : public Weapon { public: - ShotgunWeapon3(World *w, Player *p) : Weapon(w, p) {} + ShotgunWeapon3(World &w, Player &p) : Weapon(w, p) {} std::string GetName() override { return "Shotgun"; } float GetDelay() override { return 1.f; } int GetClipSize() override { return 6; } @@ -283,7 +283,7 @@ namespace spades { class RifleWeapon4 : public Weapon { public: - RifleWeapon4(World *w, Player *p) : Weapon(w, p) {} + RifleWeapon4(World &w, Player &p) : Weapon(w, p) {} std::string GetName() override { return "Rifle"; } float GetDelay() override { return 0.6f; } int GetClipSize() override { return 8; } @@ -315,7 +315,7 @@ namespace spades { class SMGWeapon4 : public Weapon { public: - SMGWeapon4(World *w, Player *p) : Weapon(w, p) {} + SMGWeapon4(World &w, Player &p) : Weapon(w, p) {} std::string GetName() override { return "SMG"; } float GetDelay() override { return 0.1f; } int GetClipSize() override { return 30; } @@ -342,7 +342,7 @@ namespace spades { class ShotgunWeapon4 : public Weapon { public: - ShotgunWeapon4(World *w, Player *p) : Weapon(w, p) {} + ShotgunWeapon4(World &w, Player &p) : Weapon(w, p) {} std::string GetName() override { return "Shotgun"; } float GetDelay() override { return 0.8f; } int GetClipSize() override { return 8; } @@ -367,27 +367,26 @@ namespace spades { int GetPelletSize() override { return 8; } }; - Weapon *Weapon::CreateWeapon(WeaponType type, Player *p, const GameProperties &gp) { + Weapon *Weapon::CreateWeapon(WeaponType type, Player &p, const GameProperties &gp) { SPADES_MARK_FUNCTION(); switch (gp.protocolVersion) { case ProtocolVersion::v075: switch (type) { - case RIFLE_WEAPON: return new RifleWeapon3(p->GetWorld(), p); - case SMG_WEAPON: return new SMGWeapon3(p->GetWorld(), p); - case SHOTGUN_WEAPON: return new ShotgunWeapon3(p->GetWorld(), p); + case RIFLE_WEAPON: return new RifleWeapon3(p.GetWorld(), p); + case SMG_WEAPON: return new SMGWeapon3(p.GetWorld(), p); + case SHOTGUN_WEAPON: return new ShotgunWeapon3(p.GetWorld(), p); default: SPInvalidEnum("type", type); } case ProtocolVersion::v076: switch (type) { - case RIFLE_WEAPON: return new RifleWeapon4(p->GetWorld(), p); - case SMG_WEAPON: return new SMGWeapon4(p->GetWorld(), p); - case SHOTGUN_WEAPON: return new ShotgunWeapon4(p->GetWorld(), p); + case RIFLE_WEAPON: return new RifleWeapon4(p.GetWorld(), p); + case SMG_WEAPON: return new SMGWeapon4(p.GetWorld(), p); + case SHOTGUN_WEAPON: return new ShotgunWeapon4(p.GetWorld(), p); default: SPInvalidEnum("type", type); } - default: - SPInvalidEnum("protocolVersion", gp.protocolVersion); + default: SPInvalidEnum("protocolVersion", gp.protocolVersion); } } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/Weapon.h b/Sources/Client/Weapon.h index 973dc212a..ec8eb9091 100644 --- a/Sources/Client/Weapon.h +++ b/Sources/Client/Weapon.h @@ -31,8 +31,8 @@ namespace spades { struct GameProperties; class Weapon { - World *world; - Player *owner; + World &world; + Player &owner; float time; bool shooting; bool shootingPreviously; @@ -49,7 +49,7 @@ namespace spades { int stock; public: - Weapon(World *, Player *); + Weapon(World &, Player &); virtual ~Weapon(); virtual std::string GetName() = 0; virtual float GetDelay() = 0; @@ -65,7 +65,7 @@ namespace spades { virtual int GetPelletSize() = 0; - static Weapon *CreateWeapon(WeaponType index, Player *, const GameProperties &); + static Weapon *CreateWeapon(WeaponType index, Player &owner, const GameProperties &); void Restock(); void Reset(); @@ -95,5 +95,5 @@ namespace spades { bool IsReadyToShoot(); }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/World.cpp b/Sources/Client/World.cpp index 56c220dd8..6e93b408e 100644 --- a/Sources/Client/World.cpp +++ b/Sources/Client/World.cpp @@ -23,10 +23,6 @@ #include #include -#include -#include -#include -#include #include "GameMap.h" #include "GameMapWrapper.h" #include "GameProperties.h" @@ -37,6 +33,9 @@ #include "Player.h" #include "Weapon.h" #include "World.h" +#include +#include +#include #include DEFINE_SPADES_SETTING(cg_debugHitTest, "0"); @@ -47,43 +46,12 @@ namespace spades { World::World(const std::shared_ptr &gameProperties) : gameProperties{gameProperties} { SPADES_MARK_FUNCTION(); - - listener = NULL; - - map = NULL; - mapWrapper = NULL; - - localPlayerIndex = -1; - for (int i = 0; i < 128; i++) { - players.push_back((Player *)NULL); - playerPersistents.push_back(PlayerPersistent()); - } - - localPlayerIndex = 0; - - time = 0.f; - mode = NULL; - } - World::~World() { - SPADES_MARK_FUNCTION(); - - for (std::list::iterator it = grenades.begin(); it != grenades.end(); it++) - delete *it; - for (size_t i = 0; i < players.size(); i++) - if (players[i]) - delete players[i]; - if (mode) { - delete mode; - } - if (map) { - delete mapWrapper; - map->Release(); - } } + World::~World() { SPADES_MARK_FUNCTION(); } size_t World::GetNumPlayers() { size_t numPlayers = 0; - for (auto *p : players) { + for (const auto &p : players) { if (p) ++numPlayers; } @@ -95,9 +63,9 @@ namespace spades { ApplyBlockActions(); - for (size_t i = 0; i < players.size(); i++) - if (players[i]) - players[i]->Update(dt); + for (const auto &player : players) + if (player) + player->Update(dt); while (!blockRegenerationQueue.empty()) { auto it = blockRegenerationQueue.begin(); @@ -118,74 +86,52 @@ namespace spades { blockRegenerationQueue.erase(it); } - std::vector::iterator> removedGrenades; - for (std::list::iterator it = grenades.begin(); it != grenades.end(); it++) { - Grenade *g = *it; - if (g->Update(dt)) { + std::vector removedGrenades; + for (auto it = grenades.begin(); it != grenades.end(); it++) { + Grenade &g = **it; + if (g.Update(dt)) { removedGrenades.push_back(it); } } - for (size_t i = 0; i < removedGrenades.size(); i++) - grenades.erase(removedGrenades[i]); + for (auto it : removedGrenades) + grenades.erase(it); time += dt; } - void World::SetMap(spades::client::GameMap *newMap) { + void World::SetMap(Handle newMap) { if (map == newMap) return; hitTestDebugger.reset(); if (map) { - map->Release(); - delete mapWrapper; + mapWrapper.reset(); } map = newMap; if (map) { - map->AddRef(); - mapWrapper = new GameMapWrapper(*map); + mapWrapper = stmp::make_unique(*map); mapWrapper->Rebuild(); } } - void World::AddGrenade(spades::client::Grenade *g) { - SPADES_MARK_FUNCTION_DEBUG(); - - grenades.push_back(g); - } - - std::vector World::GetAllGrenades() { + void World::AddGrenade(std::unique_ptr g) { SPADES_MARK_FUNCTION_DEBUG(); - std::vector g; - for (std::list::iterator it = grenades.begin(); it != grenades.end(); it++) { - g.push_back(*it); - } - return g; + grenades.push_back(std::move(g)); } - void World::SetPlayer(int i, spades::client::Player *p) { + void World::SetPlayer(int i, std::unique_ptr p) { SPADES_MARK_FUNCTION(); - SPAssert(i >= 0); - SPAssert(i < (int)players.size()); - if (players[i] == p) - return; - if (players[i]) - delete players[i]; - players[i] = p; - if (listener) + + players.at(i) = std::move(p); + if (listener) { listener->PlayerObjectSet(i); + } } - void World::SetMode(spades::client::IGameMode *m) { - if (mode == m) - return; - if (mode) - delete mode; - mode = m; - } + void World::SetMode(std::unique_ptr m) { mode = std::move(m); } void World::MarkBlockForRegeneration(const IntVector3 &blockLocation) { UnmarkBlockForRegeneration(blockLocation); @@ -345,7 +291,7 @@ namespace spades { World::PlayerPersistent &World::GetPlayerPersistent(int index) { SPAssert(index >= 0); SPAssert(index < players.size()); - return playerPersistents[index]; + return playerPersistents.at(index); } std::vector World::CubeLine(spades::IntVector3 v1, spades::IntVector3 v2, @@ -437,15 +383,16 @@ namespace spades { } World::WeaponRayCastResult World::WeaponRayCast(spades::Vector3 startPos, - spades::Vector3 dir, Player *exclude) { + spades::Vector3 dir, + stmp::optional excludePlayerId) { WeaponRayCastResult result; - Player *hitPlayer = NULL; + stmp::optional hitPlayer; float hitPlayerDistance = 0.f; hitTag_t hitFlag = hit_None; for (int i = 0; i < (int)players.size(); i++) { - Player *p = players[i]; - if (p == NULL || p == exclude) + const auto &p = players[i]; + if (!p || (excludePlayerId && *excludePlayerId == i)) continue; if (p->GetTeamId() >= 2 || !p->IsAlive()) continue; @@ -457,9 +404,9 @@ namespace spades { if (hb.head.RayCast(startPos, dir, &hitPos)) { float dist = (hitPos - startPos).GetLength(); - if (hitPlayer == NULL || dist < hitPlayerDistance) { - if (hitPlayer != p) { - hitPlayer = p; + if (!hitPlayer || dist < hitPlayerDistance) { + if (hitPlayer != i) { + hitPlayer = i; hitFlag = hit_None; } hitPlayerDistance = dist; @@ -468,9 +415,9 @@ namespace spades { } if (hb.torso.RayCast(startPos, dir, &hitPos)) { float dist = (hitPos - startPos).GetLength(); - if (hitPlayer == NULL || dist < hitPlayerDistance) { - if (hitPlayer != p) { - hitPlayer = p; + if (!hitPlayer || dist < hitPlayerDistance) { + if (hitPlayer != i) { + hitPlayer = i; hitFlag = hit_None; } hitPlayerDistance = dist; @@ -480,9 +427,9 @@ namespace spades { for (int j = 0; j < 3; j++) { if (hb.limbs[j].RayCast(startPos, dir, &hitPos)) { float dist = (hitPos - startPos).GetLength(); - if (hitPlayer == NULL || dist < hitPlayerDistance) { - if (hitPlayer != p) { - hitPlayer = p; + if (!hitPlayer || dist < hitPlayerDistance) { + if (hitPlayer != i) { + hitPlayer = i; hitFlag = hit_None; } hitPlayerDistance = dist; @@ -501,17 +448,16 @@ namespace spades { res2 = map->CastRay2(startPos, dir, 256); if (res2.hit && - (hitPlayer == NULL || (res2.hitPos - startPos).GetLength() < hitPlayerDistance)) { + (!hitPlayer || (res2.hitPos - startPos).GetLength() < hitPlayerDistance)) { result.hit = true; result.startSolid = res2.startSolid; - result.player = NULL; result.hitFlag = hit_None; result.blockPos = res2.hitBlock; result.hitPos = res2.hitPos; } else if (hitPlayer) { result.hit = true; result.startSolid = false; // FIXME: startSolid for player - result.player = hitPlayer; + result.playerId = hitPlayer; result.hitPos = startPos + dir * hitPlayerDistance; result.hitFlag = hitFlag; } else { @@ -524,11 +470,11 @@ namespace spades { HitTestDebugger *World::GetHitTestDebugger() { if (cg_debugHitTest) { if (hitTestDebugger == nullptr) { - hitTestDebugger.reset(new HitTestDebugger(this)); + hitTestDebugger = stmp::make_unique(this); } return hitTestDebugger.get(); } return nullptr; } - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Client/World.h b/Sources/Client/World.h index 78b521f0b..869f0f7a2 100644 --- a/Sources/Client/World.h +++ b/Sources/Client/World.h @@ -21,17 +21,20 @@ #pragma once +#include #include +#include #include #include #include #include -#include #include "GameMapWrapper.h" #include "PhysicsConstants.h" #include #include +#include +#include namespace spades { namespace client { @@ -44,6 +47,9 @@ namespace spades { class Client; // FIXME: for debug class HitTestDebugger; struct GameProperties; + + constexpr std::size_t NumPlayerSlots = 128; + class World { friend class Client; // FIXME: for debug public: @@ -58,23 +64,23 @@ namespace spades { }; private: - IWorldListener *listener; + IWorldListener *listener = nullptr; - IGameMode *mode; + std::unique_ptr mode; - GameMap *map; - GameMapWrapper *mapWrapper; - float time; + Handle map; + std::unique_ptr mapWrapper; + float time = 0.0f; IntVector3 fogColor; Team teams[3]; std::shared_ptr gameProperties; - std::vector players; - std::vector playerPersistents; - int localPlayerIndex; + std::array, NumPlayerSlots> players; + std::array playerPersistents; + stmp::optional localPlayerIndex; - std::list grenades; + std::list> grenades; std::unique_ptr hitTestDebugger; std::unordered_map createdBlocks; @@ -87,40 +93,43 @@ namespace spades { void ApplyBlockActions(); public: - World(const std::shared_ptr&); + World(const std::shared_ptr &); ~World(); - GameMap *GetMap() { return map; } - GameMapWrapper *GetMapWrapper() { return mapWrapper; } + const Handle &GetMap() { return map; } + GameMapWrapper &GetMapWrapper() { return *mapWrapper; } float GetTime() { return time; } /** Returns a non-null reference to `GameProperties`. */ const std::shared_ptr &GetGameProperties() { return gameProperties; } - void SetMap(GameMap *); + void SetMap(Handle); IntVector3 GetFogColor() { return fogColor; } void SetFogColor(IntVector3 v) { fogColor = v; } void Advance(float dt); - void AddGrenade(Grenade *); - std::vector GetAllGrenades(); + void AddGrenade(std::unique_ptr); + const std::list> &GetAllGrenades() { return grenades; } void MarkBlockForRegeneration(const IntVector3 &blockLocation); void UnmarkBlockForRegeneration(const IntVector3 &blockLocation); std::vector CubeLine(IntVector3 v1, IntVector3 v2, int maxLength); - Player *GetPlayer(unsigned int i) { - // SPAssert(i >= 0); lm: unsigned cannot be smaller than 0 :) + stmp::optional GetPlayer(unsigned int i) { SPAssert(i < players.size()); - return players[i]; + return players[i].get(); } - void SetPlayer(int i, Player *p); + void SetPlayer(int i, std::unique_ptr p); - IGameMode *GetMode() { return mode; } - void SetMode(IGameMode *); + /** + * Get the object containing data specific to the current game mode. + * Can be `{}` if the game mode is not specified yet. + */ + stmp::optional GetMode() { return mode.get(); } + void SetMode(std::unique_ptr); Team &GetTeam(int t) { if (t >= 2 || t < 0) // spectator @@ -135,32 +144,33 @@ namespace spades { struct WeaponRayCastResult { bool hit, startSolid; - Player *player; + stmp::optional playerId; IntVector3 blockPos; Vector3 hitPos; hitTag_t hitFlag; }; - WeaponRayCastResult WeaponRayCast(Vector3 startPos, Vector3 dir, Player *exclude); + WeaponRayCastResult WeaponRayCast(Vector3 startPos, Vector3 dir, + stmp::optional excludePlayerId); size_t GetNumPlayerSlots() { return players.size(); } - size_t GetNumPlayers(); - int GetLocalPlayerIndex() { return localPlayerIndex; } - - void SetLocalPlayerIndex(int p) { localPlayerIndex = p; } + stmp::optional GetLocalPlayerIndex() { return localPlayerIndex; } + void SetLocalPlayerIndex(stmp::optional p) { localPlayerIndex = p; } - Player *GetLocalPlayer() { - if (GetLocalPlayerIndex() == -1) - return NULL; - return GetPlayer(GetLocalPlayerIndex()); + /** Get the local player. Can be `nullptr`. */ + stmp::optional GetLocalPlayer() { + if (!GetLocalPlayerIndex()) + return {}; + return GetPlayer(*GetLocalPlayerIndex()); } + /** Can be `nullptr`. */ HitTestDebugger *GetHitTestDebugger(); - void SetListener(IWorldListener *l) { listener = l; } + void SetListener(IWorldListener *newListener) { listener = newListener; } IWorldListener *GetListener() { return listener; } }; - } -} + } // namespace client +} // namespace spades diff --git a/Sources/Core/AudioStream.cpp b/Sources/Core/AudioStream.cpp index 1c4d67852..0ae1fb69e 100644 --- a/Sources/Core/AudioStream.cpp +++ b/Sources/Core/AudioStream.cpp @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with OpenSpades. If not, see . - + */ #include @@ -30,10 +30,10 @@ namespace spades { namespace { - std::regex wavRegex {".*\\.wav", std::regex::icase}; - std::regex opusRegex {".*\\.(?:opus|ogg)", std::regex::icase}; + std::regex const wavRegex{".*\\.wav", std::regex::icase}; + std::regex const opusRegex{".*\\.(?:opus|ogg)", std::regex::icase}; - using CodecInfo = std::tuple; + using CodecInfo = std::tuple; CodecInfo g_codecs[] = { CodecInfo {"WAV Decoder", [] (IStream *stream, bool autoClose) -> IAudioStream * { return new WavAudioStream(stream, autoClose); @@ -53,15 +53,20 @@ namespace spades { // give it a try. // open error shouldn't be handled here - IStream *str = FileManager::OpenForReading(fileName.c_str()); + auto stream = FileManager::OpenForReading(fileName.c_str()); try { - return std::get<1>(codec)(str, true); + auto parsedStream = std::get<1>(codec)(stream.get(), true); + + // The ownership of `stream` moves to `parsedStream` if the load + // succeeds + stream.release(); + + return parsedStream; } catch (const std::exception &ex) { errMsg += std::get<0>(codec); errMsg += ":\n"; errMsg += ex.what(); errMsg += "\n\n"; - delete str; } } diff --git a/Sources/Core/Bitmap.cpp b/Sources/Core/Bitmap.cpp index 3f369f799..40201ab61 100644 --- a/Sources/Core/Bitmap.cpp +++ b/Sources/Core/Bitmap.cpp @@ -21,55 +21,72 @@ #include #include -#include #include "Bitmap.h" #include "Debug.h" #include "Exception.h" #include "FileManager.h" #include "IBitmapCodec.h" #include "IStream.h" +#include #include namespace spades { - Bitmap::Bitmap(int ww, int hh) : w(ww), h(hh), pixels(nullptr), autoDelete(true) { - SPADES_MARK_FUNCTION(); + namespace { + void ValidateDimensions(int width, int height) { + SPADES_MARK_FUNCTION(); + + // Do not allow creating a huge image so that we can catch misuses + // and memory corruption + if (width < 1 || height < 1 || width > 8192 || height > 8192) { + SPRaise("Invalid dimensions: %dx%d", width, height); + } + } - if (w < 1 || h < 1 || w > 8192 || h > 8192) { - SPRaise("Invalid dimension: %dx%d", w, h); + inline void ValidatePoint(const Bitmap &bitmap, int x, int y) { + if (static_cast(x) >= static_cast(bitmap.GetWidth()) || + static_cast(y) >= static_cast(bitmap.GetHeight())) { + SPRaise("The point (%d, %d) is out of bounds of bitmap of size %dx%d", x, y, + bitmap.GetWidth(), bitmap.GetHeight()); + } } + } // namespace - pixels = new uint32_t[w * h]; - SPAssert(pixels != NULL); + Bitmap::Bitmap(int width, int height) + : width{width}, height{height}, pixels{nullptr}, autoDelete{true} { + SPADES_MARK_FUNCTION(); + + ValidateDimensions(width, height); + + pixels = new uint32_t[width * height]; + SPAssert(pixels != nullptr); } - Bitmap::Bitmap(uint32_t *pixels, int w, int h) : w(w), h(h), pixels(pixels), autoDelete(false) { + Bitmap::Bitmap(uint32_t *pixels, int width, int height) + : width{width}, height{height}, pixels{pixels}, autoDelete{false} { SPADES_MARK_FUNCTION(); - if (w < 1 || h < 1 || w > 8192 || h > 8192) { - SPRaise("Invalid dimension: %dx%d", w, h); - } - - SPAssert(pixels != NULL); + ValidateDimensions(width, height); + SPAssert(pixels != nullptr); } Bitmap::~Bitmap() { SPADES_MARK_FUNCTION(); - if (autoDelete) + if (autoDelete) { delete[] pixels; + } } - Bitmap *Bitmap::Load(const std::string &filename) { + Handle Bitmap::Load(const std::string &filename) { std::vector codecs = IBitmapCodec::GetAllCodecs(); std::string errMsg; - for (size_t i = 0; i < codecs.size(); i++) { - IBitmapCodec *codec = codecs[i]; + for (IBitmapCodec *codec : codecs) { if (codec->CanLoad() && codec->CheckExtension(filename)) { // give it a try. // open error shouldn't be handled here - StreamHandle str = FileManager::OpenForReading(filename.c_str()); + std::unique_ptr str{FileManager::OpenForReading(filename.c_str())}; try { - return codec->Load(str); + return {codec->Load(str.get()), false}; } catch (const std::exception &ex) { errMsg += codec->GetName(); errMsg += ":\n"; @@ -87,18 +104,17 @@ namespace spades { } } - Bitmap *Bitmap::Load(IStream *stream) { + Handle Bitmap::Load(IStream &stream) { std::vector codecs = IBitmapCodec::GetAllCodecs(); - auto pos = stream->GetPosition(); + auto pos = stream.GetPosition(); std::string errMsg; - for (size_t i = 0; i < codecs.size(); i++) { - IBitmapCodec *codec = codecs[i]; + for (IBitmapCodec *codec : codecs) { if (codec->CanLoad()) { // give it a try. // open error shouldn't be handled here try { - stream->SetPosition(pos); - return codec->Load(stream); + stream.SetPosition(pos); + return {codec->Load(&stream), false}; } catch (const std::exception &ex) { errMsg += codec->GetName(); errMsg += ":\n"; @@ -117,12 +133,11 @@ namespace spades { void Bitmap::Save(const std::string &filename) { std::vector codecs = IBitmapCodec::GetAllCodecs(); - for (size_t i = 0; i < codecs.size(); i++) { - IBitmapCodec *codec = codecs[i]; + for (IBitmapCodec *codec : codecs) { if (codec->CanSave() && codec->CheckExtension(filename)) { - StreamHandle str = FileManager::OpenForWriting(filename.c_str()); + std::unique_ptr str{FileManager::OpenForWriting(filename.c_str())}; - codec->Save(str, this); + codec->Save(str.get(), this); return; } } @@ -130,25 +145,19 @@ namespace spades { SPRaise("Bitmap codec not found for filename: %s", filename.c_str()); } - uint32_t Bitmap::GetPixel(int x, int y) { - SPAssert(x >= 0); - SPAssert(y >= 0); - SPAssert(x < w); - SPAssert(y < h); - return pixels[x + y * w]; + uint32_t Bitmap::GetPixel(int x, int y) const { + ValidatePoint(*this, x, y); + return pixels[x + y * width]; } void Bitmap::SetPixel(int x, int y, uint32_t p) { - SPAssert(x >= 0); - SPAssert(y >= 0); - SPAssert(x < w); - SPAssert(y < h); - pixels[x + y * w] = p; + ValidatePoint(*this, x, y); + pixels[x + y * width] = p; } Handle Bitmap::Clone() { - Bitmap *b = new Bitmap(w, h); - std::memcpy(b->GetPixels(), pixels, static_cast(w * h * 4)); - return Handle(b, false); + Handle b = Handle::New(width, height); + std::memcpy(b->GetPixels(), pixels, static_cast(width * height * 4)); + return b; } -} +} // namespace spades diff --git a/Sources/Core/Bitmap.h b/Sources/Core/Bitmap.h index fa190600c..a2a573232 100644 --- a/Sources/Core/Bitmap.h +++ b/Sources/Core/Bitmap.h @@ -29,7 +29,7 @@ namespace spades { class IStream; class Bitmap : public RefCountedObject { - int w, h; + int width, height; uint32_t *pixels; bool autoDelete; @@ -37,20 +37,83 @@ namespace spades { ~Bitmap(); public: - Bitmap(int w, int h); - Bitmap(uint32_t *pixels, int w, int h); + /** + * Construct an owned bitmap image of the specified size. + * + * The initial content is undefined. Throws an exception if the size is + * invalid or outside the predetermined safe limit. + */ + Bitmap(int width, int height); - static Bitmap *Load(const std::string &); - static Bitmap *Load(IStream *); // must be seekable + /** + * Construct a borrowed bitmap image. + * + * "Borrowed" means the constructed `Bitmap` just points an existing + * memory location where the content is stored and does not own it by + * itself. Thus, the content is not released when `Bitmap` is released. + */ + Bitmap(uint32_t *pixels, int width, int height); + + /** + * Load a bitmap image from the specified OpenSpades filesystem path. + * + * Throws an exception if something goes wrong, e.g., a non-existent + * file or a corrupted image. + */ + static Handle Load(const std::string &); + + /** + * Load a bitmap image from the specified stream. The stream must be + * readable and seekable. + * + * Throws an exception if something goes wrong, e.g., a corrupted image. + */ + static Handle Load(IStream &); + + /** + * Save the bitmap image to the specified OpenSpades filesystem path. + * The image format is determined from the file extension. + * + * Throws an exception if something goes wrong, e.g., an unrecognized + * file extension or an I/O error. + */ void Save(const std::string &); + /** + * Get a pointer to the undering image data. + * + * - The image is stored in a row-major format, meaning when scanning + * through the image data, the X coordinate changes fastest. + * - There are no padding between rows. Thus, the stride is calculated + * as `GetWidth() * 4` bytes. + * - Each pixel is encoded in the 32-bit RGBA format. + */ uint32_t *GetPixels() { return pixels; } - int GetWidth() { return w; } - int GetHeight() { return h; } - uint32_t GetPixel(int x, int y); + /** Get the width of the image, measured in pixels. */ + int GetWidth() const { return width; } + + /** Get the height of the image, measured in pixels. */ + int GetHeight() const { return height; } + + /** + * Get the color value at the specified point. + * + * Throws an exception if the point is out of bounds. + */ + uint32_t GetPixel(int x, int y) const; + + /** + * Replace the color value at the specified point. + * + * Throws an exception if the point is out of bounds. + */ void SetPixel(int x, int y, uint32_t); + /** + * Construct a brand new owned bitmap image based on the content of + * an existing `Bitmap`. + */ Handle Clone(); }; -} +} // namespace spades diff --git a/Sources/Core/CP437.cpp b/Sources/Core/CP437.cpp index 6d8469bca..02f1b7d54 100644 --- a/Sources/Core/CP437.cpp +++ b/Sources/Core/CP437.cpp @@ -3,57 +3,63 @@ * WTFPL */ -#include #include +#include #include "CP437.h" #include static const uint16_t cp437map[256] = { - /* - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,*/ + /* + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, + 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,*/ - // graphic symbols - 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, - 0x25d8, 0x25cb, 0x000a, 0x2642, 0x2640, 0x000d, 0x266b, 0x263c, - 0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8, - 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc, + // graphic symbols + 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 0x25d8, 0x25cb, 0x000a, 0x2642, + 0x2640, 0x000d, 0x266b, 0x263c, 0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8, + 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, - 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, - 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, - 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, - 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229, - 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, + 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, + 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, + 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, + 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, + 0x00ee, 0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, + 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa, + 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, + 0x255d, 0x255c, 0x255b, 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, + 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, + 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, + 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, + 0x221e, 0x03c6, 0x03b5, 0x2229, 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, + 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0, }; namespace spades { - class CP437::ReverseMap { - public: - std::map mp; - ReverseMap() { - for (int i = 0; i < 256; i++) { - mp[cp437map[i]] = static_cast(i); + namespace { + struct ReverseMap { + std::unordered_map mp; + ReverseMap() { + for (int i = 0; i < 256; i++) { + mp[cp437map[i]] = static_cast(i); + } } - } - }; + }; - CP437::ReverseMap CP437::reverse; + ReverseMap const g_reverse; + } // namespace char CP437::EncodeChar(uint32_t unicode, char fb) { - auto it = reverse.mp.find(unicode); - if (it == reverse.mp.end()) { + auto it = g_reverse.mp.find(unicode); + if (it == g_reverse.mp.end()) { return fb; } else { SPAssert(cp437map[static_cast(it->second)] == unicode); @@ -63,7 +69,7 @@ namespace spades { std::uint32_t CP437::DecodeChar(char c) { auto r = cp437map[static_cast(c)]; - SPAssert(reverse.mp.find(r)->second == c); + SPAssert(g_reverse.mp.find(r)->second == c); return r; } @@ -90,4 +96,4 @@ namespace spades { } return outp; } -} +} // namespace spades diff --git a/Sources/Core/CP437.h b/Sources/Core/CP437.h index 6c8036119..8f0a5f7f9 100644 --- a/Sources/Core/CP437.h +++ b/Sources/Core/CP437.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2013 yvt * WTFPL -*/ + */ #include #include @@ -10,10 +10,8 @@ namespace spades { class CP437 { - class ReverseMap; - static ReverseMap reverse; - CP437() {} - ~CP437() {} + CP437() = delete; + ~CP437() = delete; public: static char EncodeChar(std::uint32_t unicode, char fallback = 0xff); @@ -21,4 +19,4 @@ namespace spades { static std::string Encode(const std::string &, char fallback = 0xff); static std::string Decode(const std::string &); }; -} +} // namespace spades diff --git a/Sources/Core/ConcurrentDispatch.cpp b/Sources/Core/ConcurrentDispatch.cpp index a0e6292b3..95e13ad72 100644 --- a/Sources/Core/ConcurrentDispatch.cpp +++ b/Sources/Core/ConcurrentDispatch.cpp @@ -217,7 +217,7 @@ namespace spades { Thread::CleanupExitedThreads(); } - void DispatchQueue::EnterEventLoop() throw() { + void DispatchQueue::EnterEventLoop() noexcept { while (true) { SyncQueueEntry *ent = internal->Wait(); ent->dispatch->ExecuteProtected(); @@ -317,7 +317,7 @@ namespace spades { ent->Done(); } - void ConcurrentDispatch::ExecuteProtected() throw() { + void ConcurrentDispatch::ExecuteProtected() noexcept { try { Execute(); } catch (const std::exception &ex) { diff --git a/Sources/Core/ConcurrentDispatch.h b/Sources/Core/ConcurrentDispatch.h index 47df43445..25daf20a6 100644 --- a/Sources/Core/ConcurrentDispatch.h +++ b/Sources/Core/ConcurrentDispatch.h @@ -40,7 +40,7 @@ namespace spades { ~DispatchQueue(); static DispatchQueue *GetThreadQueue(); void ProcessQueue(); - void EnterEventLoop() throw(); + void EnterEventLoop() noexcept; void MarkSDLVideoThread(); }; @@ -56,7 +56,7 @@ namespace spades { IRunnable *runnable; void Execute(); - void ExecuteProtected() throw(); + void ExecuteProtected() noexcept; // disable ConcurrentDispatch(const ConcurrentDispatch &) {} diff --git a/Sources/Core/CpuID.cpp b/Sources/Core/CpuID.cpp index a4b92ab1c..b3fa61a8a 100644 --- a/Sources/Core/CpuID.cpp +++ b/Sources/Core/CpuID.cpp @@ -16,6 +16,10 @@ namespace spades { std::array regs; #ifdef WIN32 __cpuid(reinterpret_cast(regs.data()), a); +#elif defined(__i386__) && (defined(__pic__) || defined(__PIC__)) + asm volatile("mov %%ebx, %%edi\ncpuid\nxchg %%edi, %%ebx\n" + : "=a"(regs[0]), "=D"(regs[1]), "=c"(regs[2]), "=d"(regs[2]) + : "a"(a), "c"(0)); #else asm volatile("cpuid" : "=a"(regs[0]), "=b"(regs[1]), "=c"(regs[2]), "=d"(regs[3]) @@ -24,20 +28,39 @@ namespace spades { return regs; } + static uint32_t xcr0() { +#ifdef WIN32 + return static_cast(_xgetbv(0)); +#else + uint32_t a; + asm volatile("xgetbv" : "=a"(a) : "c"(0) : "%edx"); + return a; +#endif + } + CpuID::CpuID() { uint32_t maxStdLevel; { auto ar = cpuid(0); char buf[13]; - buf[12] = 0; maxStdLevel = ar[0]; - memcpy(buf, ar.data() + 1, 12); + memcpy(&buf[0], &ar[1], 4); + memcpy(&buf[4], &ar[3], 4); + memcpy(&buf[8], &ar[2], 4); + buf[12] = 0; vendor = buf; } { auto ar = cpuid(1); featureEcx = ar[2]; featureEdx = ar[3]; + + // xsave/osxsave + if ((featureEcx & (1U << 28)) && (featureEcx & 26) && (featureEcx & 27)) { + auto x = xcr0(); + featureXcr0Avx = ((x & 6) == 6); + featureXcr0Avx512 = ((x & 224) == 224); + } } { @@ -68,12 +91,12 @@ namespace spades { case CpuFeature::SSE3: return featureEcx & (1U << 0); case CpuFeature::SSSE3: return featureEcx & (1U << 9); case CpuFeature::FMA: return featureEcx & (1U << 12); - case CpuFeature::AVX: return featureEcx & (1U << 28); - case CpuFeature::AVX2: return subfeature & (1U << 5); - case CpuFeature::AVX512CD: return subfeature & (1U << 28); - case CpuFeature::AVX512ER: return subfeature & (1U << 27); - case CpuFeature::AVX512PF: return subfeature & (1U << 26); - case CpuFeature::AVX512F: return subfeature & (1U << 16); + case CpuFeature::AVX: return featureXcr0Avx; + case CpuFeature::AVX2: return (featureXcr0Avx && subfeature & (1U << 5)); + case CpuFeature::AVX512CD: return (featureXcr0Avx512 && subfeature & (1U << 28)); + case CpuFeature::AVX512ER: return (featureXcr0Avx512 && subfeature & (1U << 27)); + case CpuFeature::AVX512PF: return (featureXcr0Avx512 && subfeature & (1U << 26)); + case CpuFeature::AVX512F: return (featureXcr0Avx512 && subfeature & (1U << 16)); case CpuFeature::SimultaneousMT: return featureEdx & (1U << 28); } } diff --git a/Sources/Core/CpuID.h b/Sources/Core/CpuID.h index 9a2648c75..22b185751 100644 --- a/Sources/Core/CpuID.h +++ b/Sources/Core/CpuID.h @@ -36,6 +36,8 @@ namespace spades { uint32_t featureEdx; uint32_t subfeature; std::string info; + bool featureXcr0Avx; + bool featureXcr0Avx512; public: CpuID(); diff --git a/Sources/Core/Debug.cpp b/Sources/Core/Debug.cpp index 079f255d7..664141695 100644 --- a/Sources/Core/Debug.cpp +++ b/Sources/Core/Debug.cpp @@ -40,8 +40,6 @@ namespace spades { namespace reflection { - Function::Function(const char *n, const char *f, int l) : name(n), file(f), line(l) {} - BacktraceEntryAdder::BacktraceEntryAdder(const BacktraceEntry &entry) { bt = Backtrace::GetGlobalBacktrace(); if (bt) @@ -194,7 +192,7 @@ namespace spades { BoundedLogBuffer g_consoleLogBuffer; } // namespace - static IStream *logStream = NULL; + static std::unique_ptr logStream; static bool attemptedToInitializeLog = false; static std::string accumlatedLog; diff --git a/Sources/Core/Debug.h b/Sources/Core/Debug.h index 1d561c89f..16af52473 100644 --- a/Sources/Core/Debug.h +++ b/Sources/Core/Debug.h @@ -33,7 +33,8 @@ namespace spades { int line; public: - Function(const char *name, const char *File, int line); + constexpr Function(const char *name, const char *file, int line) + : name{name}, file{file}, line{line} {} const char *GetName() const { return name; } const char *GetFileName() const { return file; } @@ -43,11 +44,11 @@ namespace spades { class Backtrace; class BacktraceEntry { - Function *function; + Function const *function; public: BacktraceEntry() {} - BacktraceEntry(Function *f) : function(f) {} + BacktraceEntry(Function const *f) : function(f) {} const Function &GetFunction() const { return *function; } }; @@ -102,7 +103,8 @@ namespace spades { #endif #define SPADES_MARK_FUNCTION() \ - static ::spades::reflection::Function thisFunction(__PRETTY_FUNCTION__, __FILE__, __LINE__); \ + static constexpr ::spades::reflection::Function thisFunction{__PRETTY_FUNCTION__, __FILE__, \ + __LINE__}; \ ::spades::reflection::BacktraceEntryAdder backtraceEntryAdder( \ (::spades::reflection::BacktraceEntry(&thisFunction))) @@ -130,9 +132,19 @@ namespace spades { #ifdef __GNUC__ #define DEPRECATED(func) func __attribute__((deprecated)) +#define PURE __attribute__((pure)) +#define LIKELY(cond) __builtin_expect(!!(cond), true) +#define UNLIKELY(cond) __builtin_expect(!!(cond), false) #elif defined(_MSC_VER) #define DEPRECATED(func) __declspec(deprecated) func +#define LIKELY(cond) (cond) +#define UNLIKELY(cond) (cond) +#define PURE #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED(func) func +#define PURE +#pragma message("WARNING: You need to implement LIKELY/UNLIKELY for this compiler") +#define LIKELY(cond) (cond) +#define UNLIKELY(cond) (cond) #endif diff --git a/Sources/Core/Deque.h b/Sources/Core/Deque.h deleted file mode 100644 index 0b0f7111c..000000000 --- a/Sources/Core/Deque.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright (c) 2013 yvt - - This file is part of OpenSpades. - - OpenSpades is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenSpades is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenSpades. If not, see . - - */ - -#pragma once - -#include -#include - -#include - -namespace spades { - /** Deque implementation. NPOT is not fully supported. */ - template class Deque { - T *ptr; - size_t length; - size_t startPos; - size_t capacity; - - public: - Deque(size_t cap) { - ptr = (T *)malloc(sizeof(T) * cap); - startPos = 0; - length = 0; - capacity = cap; - } - - ~Deque() { free(ptr); } - - void Reserve(size_t newCap) { - if (newCap <= capacity) - return; - T *newPtr = (T *)malloc(sizeof(T) * newCap); - size_t pos = startPos; - for (size_t i = 0; i < length; i++) { - newPtr[i] = ptr[pos++]; - if (pos == capacity) - pos = 0; - } - free(ptr); - ptr = newPtr; - startPos = 0; - capacity = newCap; - } - - void Push(const T &e) { - if (length + 1 > capacity) { - size_t newCap = capacity; - while (newCap < length + 1) - newCap <<= 1; - Reserve(newCap); - } - size_t pos = startPos + length; - if (pos >= capacity) - pos -= capacity; - ptr[pos] = e; - length++; - } - - T &Front() { return ptr[startPos]; } - - void Shift() { - SPAssert(length > 0); - startPos++; - if (startPos == capacity) - startPos = 0; - length--; - } - - size_t GetLength() const { return length; } - - bool IsEmpty() const { return length == 0; } - }; -} diff --git a/Sources/Core/DirectoryFileSystem.cpp b/Sources/Core/DirectoryFileSystem.cpp index badd36c0a..8fbb93231 100644 --- a/Sources/Core/DirectoryFileSystem.cpp +++ b/Sources/Core/DirectoryFileSystem.cpp @@ -48,7 +48,7 @@ namespace spades { DirectoryFileSystem::~DirectoryFileSystem() { SPADES_MARK_FUNCTION(); } - std::string DirectoryFileSystem::physicalPath(const std::string &lg) { + std::string DirectoryFileSystem::PathToPhysical(const std::string &lg) { // TODO: check ".."? return rootPath + '/' + lg; } @@ -82,7 +82,7 @@ namespace spades { std::vector ret; std::wstring filePath; - std::wstring path = Utf8ToWString(physicalPath(p).c_str()); + std::wstring path = Utf8ToWString(PathToPhysical(p).c_str()); // open the Win32 find handle. h = FindFirstFileExW((path + L"\\*").c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, NULL, 0); @@ -116,7 +116,7 @@ namespace spades { #else // open the directory. - std::string path = physicalPath(p); + std::string path = PathToPhysical(p); DIR *dir = opendir(path.c_str()); struct dirent *ent; @@ -146,24 +146,24 @@ namespace spades { #endif } - IStream *DirectoryFileSystem::OpenForReading(const char *fn) { + std::unique_ptr DirectoryFileSystem::OpenForReading(const char *fn) { SPADES_MARK_FUNCTION(); - std::string path = physicalPath(fn); + std::string path = PathToPhysical(fn); SDL_RWops *f = SDL_RWFromFile(path.c_str(), "rb"); if (f == NULL) { SPRaise("I/O error while opening %s for reading: %s", fn, SDL_GetError()); } - return new SdlFileStream(f, true); + return stmp::make_unique(f, true); } - IStream *DirectoryFileSystem::OpenForWriting(const char *fn) { + std::unique_ptr DirectoryFileSystem::OpenForWriting(const char *fn) { SPADES_MARK_FUNCTION(); if (!canWrite) { SPRaise("Writing prohibited for root path '%s'", rootPath.c_str()); } - std::string path = physicalPath(fn); + std::string path = PathToPhysical(fn); // create required directory if (path.find_first_of("/\\") != std::string::npos) { @@ -187,14 +187,14 @@ namespace spades { if (f == NULL) { SPRaise("I/O error while opening %s for writing", fn); } - return new SdlFileStream(f, true); + return stmp::make_unique(f, true); } // TODO: open for appending? bool DirectoryFileSystem::FileExists(const char *fn) { SPADES_MARK_FUNCTION(); - std::string path = physicalPath(fn); + std::string path = PathToPhysical(fn); SDL_RWops *f = SDL_RWFromFile(path.c_str(), "rb"); if (f) { SDL_RWclose(f); @@ -202,4 +202,4 @@ namespace spades { } return false; } -} +} // namespace spades diff --git a/Sources/Core/DirectoryFileSystem.h b/Sources/Core/DirectoryFileSystem.h index d307bb638..a274cd550 100644 --- a/Sources/Core/DirectoryFileSystem.h +++ b/Sources/Core/DirectoryFileSystem.h @@ -29,7 +29,7 @@ namespace spades { std::string rootPath; bool canWrite; - std::string physicalPath(const std::string &); + std::string PathToPhysical(const std::string &); public: DirectoryFileSystem(const std::string &root, bool canWrite = true); @@ -37,8 +37,8 @@ namespace spades { std::vector EnumFiles(const char *) override; - IStream *OpenForReading(const char *) override; - IStream *OpenForWriting(const char *) override; + std::unique_ptr OpenForReading(const char *) override; + std::unique_ptr OpenForWriting(const char *) override; bool FileExists(const char *) override; }; } diff --git a/Sources/Core/Exception.cpp b/Sources/Core/Exception.cpp index 539eeab71..bc4b84c60 100644 --- a/Sources/Core/Exception.cpp +++ b/Sources/Core/Exception.cpp @@ -55,6 +55,6 @@ namespace spades { message = Format("{0}\nat {1}:{2}\n{3}", message, file, line, trace.ToString()); } - Exception::~Exception() throw() {} - const char *Exception::what() const throw() { return message.c_str(); } + Exception::~Exception() noexcept {} + const char *Exception::what() const noexcept { return message.c_str(); } } diff --git a/Sources/Core/FileManager.cpp b/Sources/Core/FileManager.cpp index e06aabada..98585f819 100644 --- a/Sources/Core/FileManager.cpp +++ b/Sources/Core/FileManager.cpp @@ -29,7 +29,7 @@ namespace spades { static std::list g_fileSystems; - IStream *FileManager::OpenForReading(const char *fn) { + std::unique_ptr FileManager::OpenForReading(const char *fn) { SPADES_MARK_FUNCTION(); if (!fn) SPInvalidArgument("fn"); @@ -51,7 +51,7 @@ namespace spades { SPFileNotFound(fn); } - IStream *FileManager::OpenForWriting(const char *fn) { + std::unique_ptr FileManager::OpenForWriting(const char *fn) { SPADES_MARK_FUNCTION(); if (!fn) SPInvalidArgument("fn"); @@ -117,15 +117,11 @@ namespace spades { std::string FileManager::ReadAllBytes(const char *fn) { SPADES_MARK_FUNCTION(); - IStream *stream = OpenForReading(fn); - try { - std::string ret = stream->ReadAllBytes(); - delete stream; - return ret; - } catch (...) { - delete stream; - throw; - } + auto stream = OpenForReading(fn); + SPAssert(stream); + + std::string ret = stream->ReadAllBytes(); + return ret; } std::vector FileManager::EnumFiles(const char *path) { @@ -147,8 +143,8 @@ namespace spades { } void FileManager::Close() { - for (auto *fs: g_fileSystems) { + for (auto *fs : g_fileSystems) { delete fs; } - } -} + } +} // namespace spades diff --git a/Sources/Core/FileManager.h b/Sources/Core/FileManager.h index c3e9c66b6..df20e0e58 100644 --- a/Sources/Core/FileManager.h +++ b/Sources/Core/FileManager.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include @@ -30,8 +31,8 @@ namespace spades { FileManager() {} public: - static IStream *OpenForReading(const char *); - static IStream *OpenForWriting(const char *); + static std::unique_ptr OpenForReading(const char *); + static std::unique_ptr OpenForWriting(const char *); static bool FileExists(const char *); static void AddFileSystem(IFileSystem *); static void AppendFileSystem(IFileSystem *); @@ -40,4 +41,4 @@ namespace spades { static std::string ReadAllBytes(const char *); static void Close(); }; -}; +}; // namespace spades diff --git a/Sources/Core/IFileSystem.h b/Sources/Core/IFileSystem.h index 035a050e3..86db08d7d 100644 --- a/Sources/Core/IFileSystem.h +++ b/Sources/Core/IFileSystem.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include @@ -29,8 +30,8 @@ namespace spades { public: virtual ~IFileSystem() {} virtual std::vector EnumFiles(const char *) = 0; - virtual IStream *OpenForReading(const char *) = 0; - virtual IStream *OpenForWriting(const char *) = 0; + virtual std::unique_ptr OpenForReading(const char *) = 0; + virtual std::unique_ptr OpenForWriting(const char *) = 0; virtual bool FileExists(const char *) = 0; }; -} +} // namespace spades diff --git a/Sources/Core/IStream.cpp b/Sources/Core/IStream.cpp index fafcd9918..fd5ce8fcf 100644 --- a/Sources/Core/IStream.cpp +++ b/Sources/Core/IStream.cpp @@ -20,13 +20,13 @@ #include -#include #include "Debug.h" #include "Exception.h" #include "IStream.h" +#include namespace spades { - IStream::~IStream() throw(Exception) {} + IStream::~IStream() {} int IStream::ReadByte() { SPUnsupported(); } size_t IStream::Read(void *out, size_t bytes) { @@ -111,70 +111,4 @@ namespace spades { SPRaise("Failed to read 4 bytes"); return data; } - - StreamHandle::StreamHandle() : o(NULL) {} - - StreamHandle::StreamHandle(IStream *stream) { - SPADES_MARK_FUNCTION(); - if (!stream) - SPInvalidArgument("stream"); - o = new SharedStream(stream); - } - - StreamHandle::StreamHandle(const StreamHandle &handle) : o(handle.o) { - SPADES_MARK_FUNCTION_DEBUG(); - o->Retain(); - } - - StreamHandle::~StreamHandle() { - SPADES_MARK_FUNCTION(); - Reset(); - } - - spades::StreamHandle &StreamHandle::operator=(const spades::StreamHandle &h) { - SPADES_MARK_FUNCTION(); - if (o != h.o) { - SharedStream *old = o; - o = h.o; - if (o) { - o->Retain(); - } - if (old) { - old->Release(); - } - } - return *this; - } - - IStream *StreamHandle::operator->() const { - SPAssert(o); - return o->stream; - } - - StreamHandle::operator class spades::IStream *() const { - SPAssert(o); - return o->stream; - } - - StreamHandle::operator bool() const { return o->stream; } - - void StreamHandle::Reset() { - if (o) { - o->Release(); - o = NULL; - } - } - - StreamHandle::SharedStream::SharedStream(IStream *s) : stream(s), refCount(1) {} - - StreamHandle::SharedStream::~SharedStream() { delete stream; } - - void StreamHandle::SharedStream::Retain() { refCount++; } - - void StreamHandle::SharedStream::Release() { - SPAssert(refCount > 0); - refCount--; - if (refCount == 0) - delete this; - } -} +} // namespace spades diff --git a/Sources/Core/IStream.h b/Sources/Core/IStream.h index b5257ae5d..fa288b77c 100644 --- a/Sources/Core/IStream.h +++ b/Sources/Core/IStream.h @@ -41,7 +41,7 @@ namespace spades { IStream() {} public: - virtual ~IStream() throw(Exception); + virtual ~IStream(); /** reads one byte and return in range [0, 255]. * -1 if EOF reached. */ virtual int ReadByte(); @@ -66,29 +66,4 @@ namespace spades { // utilities virtual std::string ReadAllBytes(); }; - - /** makes management of stream lifetime easier. - * don't create multiple StreamHandles with the same IStream. */ - class StreamHandle { - struct SharedStream { - IStream *stream; - int refCount; - SharedStream(IStream *); - ~SharedStream(); - void Retain(); - void Release(); - }; - SharedStream *o; - - public: - StreamHandle(); - StreamHandle(IStream *); - StreamHandle(const StreamHandle &); - ~StreamHandle(); - spades::StreamHandle &operator=(const StreamHandle &); - void Reset(); - IStream *operator->() const; - operator IStream *() const; - operator bool() const; - }; } diff --git a/Sources/Core/Math.cpp b/Sources/Core/Math.cpp index c7f45cfa1..9ca761f7d 100644 --- a/Sources/Core/Math.cpp +++ b/Sources/Core/Math.cpp @@ -26,18 +26,6 @@ #include namespace spades { - /* - Vector3 Line3::Project(spades::Vector3 v, - bool supposeUnbounded) { - - } - - float Line3::GetDistanceTo(spades::Vector3 v, - bool supposeUnbounded){ - - } - */ - namespace { std::random_device r_device; std::mt19937_64 global_rng{r_device()}; @@ -330,6 +318,12 @@ namespace spades { } bool OBB3::RayCast(spades::Vector3 start, spades::Vector3 dir, spades::Vector3 *hitPos) { + // inside? + if (*this && start) { + *hitPos = start; + return true; + } + Vector3 normX = {m.m[0], m.m[1], m.m[2]}; Vector3 normY = {m.m[4], m.m[5], m.m[6]}; Vector3 normZ = {m.m[8], m.m[9], m.m[10]}; @@ -344,12 +338,6 @@ namespace spades { float dotY = Vector3::Dot(dir, normY); float dotZ = Vector3::Dot(dir, normZ); - // inside? - if (*this && start) { - *hitPos = start; - return true; - } - // x-plane hit test if (dotX != 0.f) { float startp = Vector3::Dot(start, normX); @@ -479,6 +467,24 @@ namespace spades { return ab; } + Vector3 Line3::Project(Vector3 v, bool supposeUnbounded) { + Vector3 delta = v2 - v1; + Vector3 direction = delta.Normalize(); + float length = delta.GetLength(); + float positionOnLine = Vector3::Dot(v - v1, direction); + if ((end1 & !supposeUnbounded) && positionOnLine < 0.0f) { + positionOnLine = 0.0f; + }; + if ((end2 & !supposeUnbounded) && positionOnLine > length) { + positionOnLine = length; + }; + return v1 + direction * positionOnLine; + } + + float Line3::GetDistanceTo(Vector3 v, bool supposeUnbounded) { + return (v - Project(v, supposeUnbounded)).GetLength(); + } + std::string Replace(const std::string &text, const std::string &before, const std::string &after) { std::string out; diff --git a/Sources/Core/OpusAudioStream.cpp b/Sources/Core/OpusAudioStream.cpp index d656e414f..751d1fc37 100644 --- a/Sources/Core/OpusAudioStream.cpp +++ b/Sources/Core/OpusAudioStream.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include "OpusAudioStream.h" diff --git a/Sources/Core/PipeStream.cpp b/Sources/Core/PipeStream.cpp index 2095cf100..0072a0dc0 100644 --- a/Sources/Core/PipeStream.cpp +++ b/Sources/Core/PipeStream.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include "PipeStream.h" namespace spades { @@ -150,9 +152,10 @@ namespace spades { } // namespace - std::tuple CreatePipeStream() { + std::tuple, std::unique_ptr> CreatePipeStream() { auto state = std::make_shared(); - return std::make_tuple(new PipeWriter(state), new PipeReader(state)); + return std::make_tuple(stmp::make_unique(state), + stmp::make_unique(state)); } } // namespace spades diff --git a/Sources/Core/PipeStream.h b/Sources/Core/PipeStream.h index 07e4f5a5c..0e2f6a9ae 100644 --- a/Sources/Core/PipeStream.h +++ b/Sources/Core/PipeStream.h @@ -17,6 +17,7 @@ along with OpenSpades. If not, see . */ +#include #include #include @@ -30,5 +31,5 @@ namespace spades { * - If the writer hangs up, the reader will get an EOF for further reads. * - If the reader hangs up, the writer silently discards the written data. */ - std::tuple CreatePipeStream(); + std::tuple, std::unique_ptr> CreatePipeStream(); } // namespace spades diff --git a/Sources/Core/RefCountedObject.h b/Sources/Core/RefCountedObject.h index 3f5efdf18..269abdd97 100644 --- a/Sources/Core/RefCountedObject.h +++ b/Sources/Core/RefCountedObject.h @@ -34,6 +34,28 @@ namespace spades { + /** + * A ref-counted object that internally holds a reference count. + * + * This type is used mainly for compatibility with AngelScript's GC + * behavior as it's impossible to implement with `std::shared_ptr`. In + * general cases, `std::unique_ptr` or `std::shared_ptr` is more suitable. + * + * # Conventions + * + * - When storing a strong reference, use `Handle`. Do not attempt to + * manually update the reference count unless absolutely necessary. + * - Under any circumstances, do not manually call its destructor. + * - Use `Handle::New(...)` to consturct an object. + * - Methods receive `T` via a parameter of type `T&` or + * `stmp::optional`. They may create and hold a strong reference + * using `Handle::Handle(T&)`. Alternatively, they can use `Handle` + * if it is apparent that they store the object as `Handle`. + * - Methods return `T` via a return type `Handle`. + * + * Note that `stmp::optional` nor `Handle` can be passed to/from AngelScript + * safely. + */ class RefCountedObject { std::atomic refCount; #if DEBUG_REFCOUNTED_OBJECT_LAST_RELEASE @@ -46,11 +68,16 @@ namespace spades { public: RefCountedObject(); + RefCountedObject(const RefCountedObject &) = delete; + void operator=(const RefCountedObject &) = delete; void AddRef(); void Release(); }; + /** + * A nullable smart pointer for `T <: RefCountedObject`. + */ template class Handle { T *ptr; @@ -67,7 +94,11 @@ namespace spades { if (ptr) ptr->AddRef(); } - Handle(Handle &&h) : ptr(h.MaybeUnmanage()) {} + Handle(Handle &&h) : ptr(std::move(h).MaybeUnmanage()) {} + Handle(T &ref) : ptr{&ref} { ptr->AddRef(); } + Handle(stmp::optional ref) : ptr{ref.get_pointer()} { if (ptr) + ptr->AddRef(); + } template Handle(Handle &&h) : ptr(h.MaybeUnmanage()) {} @@ -79,23 +110,17 @@ namespace spades { } template static Handle New(Args &&... args) { - T *ptr = new T{std::forward(args)...}; + T *ptr = new T(std::forward(args)...); return {ptr, false}; } - T *operator->() { - SPAssert(ptr != NULL); - return ptr; - } - const T *operator->() const { + T *operator->() const { + // TODO: Do not skip null check in release builds SPAssert(ptr != NULL); return ptr; } - T &operator*() { - SPAssert(ptr != NULL); - return *ptr; - } - const T &operator*() const { + T &operator*() const { + // TODO: Do not skip null check in release builds SPAssert(ptr != NULL); return *ptr; } @@ -114,19 +139,42 @@ namespace spades { } void operator=(T *p) { Set(p); } void operator=(const Handle &h) { Set(h.ptr, true); } - operator T *() { return ptr; } - T *Unmanage() { + + operator stmp::optional() const { return ptr; } + + /** + * Get a nullable raw pointer. After the operation, the original `Handle` + * still owns a reference to the referent (if any). + * + * This conversion have a danger of causing a pointer use-after-free if + * used incorrectly. For example, `IImage *image = CreateImage().GetPointer();` + * creates a dangling pointer because the temporary value `CreateImage()` + * is destroyed right after initializing the variable, invalidating the + * pointer returned by `GetPointer()`. This is why this conversion is + * no longer supported as implicit casting. + */ + T *GetPointerOrNull() const { return ptr; } + /** + * Convert a `Handle` to a raw pointer, transfering the ownership. + * Throws an exception if the `Handle` is null. + */ + T *Unmanage() && { SPAssert(ptr != NULL); T *p = ptr; ptr = NULL; return p; } - T *MaybeUnmanage() { + /** + * Convert a `Handle` to a raw pointer, transfering the ownership. + */ + T *MaybeUnmanage() && { T *p = ptr; ptr = NULL; return p; } - operator bool() { return ptr != NULL; } + operator bool() const { return ptr != NULL; } + + bool operator==(const Handle &rhs) const { return ptr == rhs.ptr; } /** * Attempts to cast this `Handle` to `Handle` using `dynamic_cast`, consuming this @@ -155,4 +203,4 @@ namespace spades { */ template Handle Cast() const & { return Handle{*this}.Cast(); } }; -} +} // namespace spades diff --git a/Sources/Core/SdlImageReader.cpp b/Sources/Core/SdlImageReader.cpp index e229c7bea..2ee809591 100644 --- a/Sources/Core/SdlImageReader.cpp +++ b/Sources/Core/SdlImageReader.cpp @@ -62,27 +62,22 @@ namespace spades { int height = img->h; int pitch = img->pitch; - Handle bmp; - bmp.Set(new Bitmap(width, height), false); - try { - unsigned char *outPixels = (unsigned char *)bmp->GetPixels(); - - if (pitch == width * 4) { - // if the pitch matches the requirement of Bitmap, - // just use it - memcpy(outPixels, inPixels, pitch * height); - } else { - // convert - for (int y = 0; y < height; y++) { - memcpy(outPixels, inPixels, width * 4); - outPixels += width * 4; - inPixels += pitch; - } + auto bmp = Handle::New(width, height); + unsigned char *outPixels = (unsigned char *)bmp->GetPixels(); + + if (pitch == width * 4) { + // if the pitch matches the requirement of Bitmap, + // just use it + memcpy(outPixels, inPixels, pitch * height); + } else { + // convert + for (int y = 0; y < height; y++) { + memcpy(outPixels, inPixels, width * 4); + outPixels += width * 4; + inPixels += pitch; } - return bmp.Unmanage(); - } catch (...) { - throw; } + return std::move(bmp).Unmanage(); } void Save(IStream *, Bitmap *) override { diff --git a/Sources/Core/Semaphore.h b/Sources/Core/Semaphore.h index 2aa3bef55..fbd968671 100644 --- a/Sources/Core/Semaphore.h +++ b/Sources/Core/Semaphore.h @@ -28,6 +28,8 @@ namespace spades { public: Semaphore(int initial = 1); ~Semaphore(); + Semaphore(const Semaphore &) = delete; + void operator=(const Semaphore &) = delete; void Post(); void Wait(); @@ -35,4 +37,4 @@ namespace spades { void Lock() override { Wait(); } void Unlock() override { Post(); } }; -} +} // namespace spades diff --git a/Sources/Core/ServerAddress.cpp b/Sources/Core/ServerAddress.cpp index a252ebe07..a42216b59 100644 --- a/Sources/Core/ServerAddress.cpp +++ b/Sources/Core/ServerAddress.cpp @@ -41,11 +41,13 @@ namespace spades { return vl; } - ServerAddress::ServerAddress(std::string address, ProtocolVersion version) - : mAddress(address), mVersion(version) { - static std::regex v075regex {"(.*):0?\\.?75"}; - static std::regex v076regex {"(.*):0?\\.?76"}; + namespace { + std::regex const v075regex{"(.*):0?\\.?75"}; + std::regex const v076regex{"(.*):0?\\.?76"}; + } // namespace + ServerAddress::ServerAddress(std::string address, ProtocolVersion version) + : mAddress(address), mVersion(version) { std::smatch matchResult; if (std::regex_match(address, matchResult, v075regex)) { diff --git a/Sources/Core/Settings.cpp b/Sources/Core/Settings.cpp index 7c679c3c5..27dbfc4d9 100644 --- a/Sources/Core/Settings.cpp +++ b/Sources/Core/Settings.cpp @@ -382,6 +382,14 @@ namespace spades { void Settings::ItemHandle::operator=(const std::string &value) { item->Set(value); } void Settings::ItemHandle::operator=(int value) { item->Set(value); } void Settings::ItemHandle::operator=(float value) { item->Set(value); } + bool Settings::ItemHandle::operator==(int value) { + item->Load(); + return item->intValue == value; + } + bool Settings::ItemHandle::operator!=(int value) { + item->Load(); + return item->intValue != value; + } Settings::ItemHandle::operator std::string() { item->Load(); return item->string; diff --git a/Sources/Core/Settings.h b/Sources/Core/Settings.h index a06b8b829..9564140c5 100644 --- a/Sources/Core/Settings.h +++ b/Sources/Core/Settings.h @@ -102,6 +102,8 @@ namespace spades { void operator=(const std::string &); void operator=(int); void operator=(float); + bool operator==(int); + bool operator!=(int); operator std::string(); operator float(); operator int(); diff --git a/Sources/Core/ShellApi.cpp b/Sources/Core/ShellApi.cpp index 24d76bdc2..17438d11e 100644 --- a/Sources/Core/ShellApi.cpp +++ b/Sources/Core/ShellApi.cpp @@ -89,7 +89,7 @@ namespace spades { return false; } } -#elif __unix || __unix__ +#elif (__unix || __unix__) || defined(__HAIKU__) bool ShowDirectoryInShell(const std::string &directoryPath) { // FIXME: escape single quotes if (directoryPath.find("'") != std::string::npos) { diff --git a/Sources/Core/TMPUtils.h b/Sources/Core/TMPUtils.h index e2cbd9642..520ca4378 100644 --- a/Sources/Core/TMPUtils.h +++ b/Sources/Core/TMPUtils.h @@ -68,13 +68,37 @@ namespace stmp { Allocator().construct(reinterpret_cast(&storage), std::forward(args)...); has_some = true; } - void operator=(const T &o) { reset(o); } - void operator=(T &&o) { reset(std::move(o)); } + void operator=(const T &o) { + if (has_some) { + **this = o; + } else { + reset(o); + } + } + void operator=(T &&o) { + if (has_some) { + **this = std::move(o); + } else { + reset(std::move(o)); + } + } void operator=(const optional &o) { - if (o) + if (has_some && o.has_some) { + **this = *o; + } else if (o.has_some) { reset(*o); - else + } else { reset(); + } + } + void operator=(optional &&o) { + if (has_some && o.has_some) { + **this = *std::move(o); + } else if (o.has_some) { + reset(*std::move(o)); + } else { + reset(); + } } T *get_pointer() { return has_some ? reinterpret_cast(&storage) : nullptr; } @@ -115,13 +139,13 @@ namespace stmp { if (!has_some) { throw bad_optional_access{}; } - return *get_pointer(); + return std::move(*get_pointer()); } const T &&value() const && { if (!has_some) { throw bad_optional_access{}; } - return *get_pointer(); + return std::move(*get_pointer()); } template T value_or(U &&default_value) const & { @@ -131,14 +155,8 @@ namespace stmp { return *this ? std::move(get()) : static_cast(std::forward(default_value)); } - T &operator->() { - assert(has_some); - return get(); - } - const T &operator->() const { - assert(has_some); - return get(); - } + T *operator->() { return &get(); } + const T *operator->() const { return &get(); } T &operator*() { assert(has_some); @@ -150,8 +168,152 @@ namespace stmp { } explicit operator bool() const { return has_some; } + + bool operator==(const optional &rhs) const { + return has_some == rhs.has_some && (!has_some || **this == *rhs); + } + bool operator!=(const optional &rhs) const { + return has_some != rhs.has_some || (has_some && **this != *rhs); + } + + template bool operator==(const U &rhs) const { return has_some && **this == rhs; } + template bool operator!=(const U &rhs) const { return !has_some || **this != rhs; } + }; + + template + typename std::enable_if::value, bool>::type + operator==(const U &lhs, const optional rhs) { + return rhs && lhs == *rhs; + } + template + typename std::enable_if::value, bool>::type + operator!=(const U &lhs, const optional rhs) { + return !rhs || lhs != *rhs; + } + + /** + * Specialization of `optional` for references. Works very similarly to + * pointers, but it's better at communicating the nullability. + * + * Boost's `optional` has this, while C++17's `optional` doesn't. + */ + template class optional { + T *ptr; + + public: + optional() : ptr(nullptr) {} + optional(T *v) : ptr(v) {} + optional(T &v) : ptr(&v) {} + optional(const optional &o) : ptr(o.ptr) {} + void reset() { ptr = nullptr; } + void operator=(const optional &o) { ptr = o.ptr; } + + T *get_pointer() { return ptr; } + const T *get_pointer() const { return ptr; } + + T &get() { + assert(ptr); + return *get_pointer(); + } + const T &get() const { + assert(ptr); + return *get_pointer(); + } + + T &value() { + if (!ptr) { + throw bad_optional_access{}; + } + return *get_pointer(); + } + const T &value() const { + if (!ptr) { + throw bad_optional_access{}; + } + return *get_pointer(); + } + + template T &value_or(U &&default_value) const & { + return *this ? get() : static_cast(std::forward(default_value)); + } + template T &value_or(U &&default_value) && { + return *this ? std::move(get()) : static_cast(std::forward(default_value)); + } + + T *operator->() { return &get(); } + const T *operator->() const { return &get(); } + + T &operator*() { return get(); } + const T &operator*() const { return get(); } + + explicit operator bool() const { return !!ptr; } + + bool operator==(const optional &rhs) const { return ptr == rhs.ptr; } + bool operator!=(const optional &rhs) const { return ptr != rhs.ptr; } + + bool operator==(const T *rhs) const { return ptr == rhs; } + bool operator!=(const T *rhs) const { return ptr != rhs; } }; + template bool operator==(const T *lhs, const optional rhs) { + return lhs == rhs.get_pointer(); + } + template bool operator!=(const T *lhs, const optional rhs) { + return lhs != rhs.get_pointer(); + } + + template class optional { + const T *ptr; + + public: + optional() : ptr(nullptr) {} + optional(const T *v) : ptr(v) {} + optional(const T &v) : ptr(&v) {} + optional(const optional &o) : ptr(o.ptr) {} + void reset() { ptr = nullptr; } + void operator=(const optional &o) { ptr = o.ptr; } + + const T *get_pointer() const { return ptr; } + + const T &get() const { + assert(ptr); + return *get_pointer(); + } + + const T &value() const { + if (!ptr) { + throw bad_optional_access{}; + } + return *get_pointer(); + } + + template T &value_or(U &&default_value) const & { + return *this ? get() : static_cast(std::forward(default_value)); + } + + const T *operator->() const { return &get(); } + const T &operator*() const { return get(); } + + explicit operator bool() const { return !!ptr; } + + bool operator==(const optional &rhs) const { return ptr == rhs.ptr; } + bool operator!=(const optional &rhs) const { return ptr != rhs.ptr; } + + bool operator==(const T *rhs) const { return ptr == rhs; } + bool operator!=(const T *rhs) const { return ptr != rhs; } + }; + + template bool operator==(const T *lhs, const optional rhs) { + return lhs == rhs.get_pointer(); + } + template bool operator!=(const T *lhs, const optional rhs) { + return lhs != rhs.get_pointer(); + } + + template optional::type> make_optional(T &&value) { + return {std::forward(value)}; + } + /** Safe atomic smart pointer. */ template class atomic_unique_ptr { std::atomic inner; @@ -221,4 +383,9 @@ namespace stmp { template function make_fn(T &&inner) { return function(std::move(inner)); } + + /** Polyfill of `std::make_unique` for compilers which don't support it. */ + template std::unique_ptr make_unique(Args &&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } } // namespace stmp diff --git a/Sources/Core/VersionInfo.cpp b/Sources/Core/VersionInfo.cpp index b35f43f5b..07a8aa825 100644 --- a/Sources/Core/VersionInfo.cpp +++ b/Sources/Core/VersionInfo.cpp @@ -44,10 +44,16 @@ std::string VersionInfo::GetVersionInfo() { return windowsVersion; #elif defined(__FreeBSD__) return std::string("FreeBSD"); +#elif defined(__DragonFly__) + return std::string("DragonFly BSD"); #elif defined(__OpenBSD__) return std::string("OpenBSD"); #elif defined(__NetBSD__) return std::string("NetBSD"); +#elif defined(__sun) + return std::string("Solaris / Illumos"); +#elif defined(__HAIKU__) + return std::string("Haiku"); #else return std::string("Unknown OS"); #endif diff --git a/Sources/Core/VoxelModel.cpp b/Sources/Core/VoxelModel.cpp index 9c1e37865..c0215f274 100644 --- a/Sources/Core/VoxelModel.cpp +++ b/Sources/Core/VoxelModel.cpp @@ -38,20 +38,27 @@ namespace spades { width = w; height = h; depth = d; + if (d > 64) { SPRaise("Voxel model with depth > 64 is not supported."); } - solidBits = new uint64_t[w * h]; - colors = new uint32_t[w * h * d]; + // TODO: `stmp::make_unique` doesn't support `T[]` yet + solidBits.reset(new uint64_t[w * h]); + colors.reset(new uint32_t[w * h * d]); - std::fill(solidBits, solidBits + w * h, 0); + std::fill(solidBits.get(), solidBits.get() + w * h, 0); + } + VoxelModel::~VoxelModel() { SPADES_MARK_FUNCTION(); } + + void VoxelModel::ThrowInvalidSpan [[noreturn]] (int x, int y) const { + SPRaise("Span (%d, %d, :) is out of bounds of voxel model of size %dx%dx%d", x, y, width, + height, depth); } - VoxelModel::~VoxelModel() { - SPADES_MARK_FUNCTION(); - delete[] solidBits; - delete[] colors; + void VoxelModel::ThrowInvalidPoint [[noreturn]] (int x, int y, int z) const { + SPRaise("Point (%d, %d, %d) is out of bounds of voxel model of size %dx%dx%d", x, y, z, + width, height, depth); } void VoxelModel::ForceMaterial(MaterialType newMaterialId) { @@ -61,27 +68,30 @@ namespace spades { } } - struct KV6Block { - uint32_t color; - uint16_t zPos; - uint8_t visFaces; - uint8_t lighting; - }; - - struct KV6Header { - uint32_t xsiz, ysiz, zsiz; - float xpivot, ypivot, zpivot; - uint32_t blklen; - }; - static uint32_t swapColor(uint32_t col) { - union { - uint8_t bytes[4]; - uint32_t c; - } u; - u.c = col; - std::swap(u.bytes[0], u.bytes[2]); - return (u.c & 0xffffff); - } + namespace { + struct KV6Block { + uint32_t color; + uint16_t zPos; + uint8_t visFaces; + uint8_t lighting; + }; + + struct KV6Header { + uint32_t xsiz, ysiz, zsiz; + float xpivot, ypivot, zpivot; + uint32_t blklen; + }; + + uint32_t swapColor(uint32_t col) { + union { + uint8_t bytes[4]; + uint32_t c; + } u; + u.c = col; + std::swap(u.bytes[0], u.bytes[2]); + return (u.c & 0xffffff); + } + } // namespace void VoxelModel::HollowFill() { std::vector stack; @@ -191,22 +201,22 @@ namespace spades { } } - VoxelModel *VoxelModel::LoadKV6(spades::IStream *stream) { + Handle VoxelModel::LoadKV6(IStream &stream) { SPADES_MARK_FUNCTION(); - if (stream->Read(4) != "Kvxl") { + if (stream.Read(4) != "Kvxl") { SPRaise("Invalid magic"); } KV6Header header; - if (stream->Read(&header, sizeof(header)) < sizeof(header)) { + if (stream.Read(&header, sizeof(header)) < sizeof(header)) { SPRaise("File truncated: failed to read header"); } std::vector blkdata; blkdata.resize(header.blklen); - if (stream->Read(blkdata.data(), sizeof(KV6Block) * header.blklen) < + if (stream.Read(blkdata.data(), sizeof(KV6Block) * header.blklen) < sizeof(KV6Block) * header.blklen) { SPRaise("File truncated: failed to read blocks"); } @@ -214,7 +224,7 @@ namespace spades { std::vector xoffset; xoffset.resize(header.xsiz); - if (stream->Read(xoffset.data(), sizeof(uint32_t) * header.xsiz) < + if (stream.Read(xoffset.data(), sizeof(uint32_t) * header.xsiz) < sizeof(uint32_t) * header.xsiz) { SPRaise("File truncated: failed to read xoffset"); } @@ -222,7 +232,7 @@ namespace spades { std::vector xyoffset; xyoffset.resize(header.xsiz * header.ysiz); - if (stream->Read(xyoffset.data(), sizeof(uint16_t) * header.xsiz * header.ysiz) < + if (stream.Read(xyoffset.data(), sizeof(uint16_t) * header.xsiz * header.ysiz) < sizeof(uint16_t) * header.xsiz * header.ysiz) { SPRaise("File truncated: failed to read xyoffset"); } @@ -242,38 +252,30 @@ namespace spades { SPRaise("File corrupted: sum(xyoffset) != blkdata.size()"); } - VoxelModel *model = new VoxelModel(header.xsiz, header.ysiz, header.zsiz); + auto model = Handle::New(header.xsiz, header.ysiz, header.zsiz); model->SetOrigin(MakeVector3(-header.xpivot, -header.ypivot, -header.zpivot)); - try { - int pos = 0; - for (int x = 0; x < (int)header.xsiz; x++) - for (int y = 0; y < (int)header.ysiz; y++) { - int spanBlocks = (int)xyoffset[x * header.ysiz + y]; - int lastZ = -1; - // printf("pos: %d, (%d, %d): %d\n", - // pos, x, y, spanBlocks); - while (spanBlocks--) { - const KV6Block &b = blkdata[pos]; - // printf("%d, %d, %d: %d, %d\n", x, y, b.zPos, - // b.visFaces, b.lighting); - if (model->IsSolid(x, y, b.zPos)) { - SPRaise("Duplicate voxel (%d, %d, %d)", x, y, b.zPos); - } - if (b.zPos <= lastZ) { - SPRaise("Not Z-sorted"); - } - lastZ = b.zPos; - model->SetSolid(x, y, b.zPos, swapColor(b.color)); - pos++; + + int pos = 0; + for (int x = 0; x < (int)header.xsiz; x++) + for (int y = 0; y < (int)header.ysiz; y++) { + int spanBlocks = (int)xyoffset[x * header.ysiz + y]; + int lastZ = -1; + while (spanBlocks--) { + const KV6Block &b = blkdata[pos]; + if (model->IsSolid(x, y, b.zPos)) { + SPRaise("Duplicate voxel (%d, %d, %d)", x, y, b.zPos); } + if (b.zPos <= lastZ) { + SPRaise("Not Z-sorted"); + } + lastZ = b.zPos; + model->SetSolid(x, y, b.zPos, swapColor(b.color)); + pos++; } + } - SPAssert(pos == blkdata.size()); - model->HollowFill(); - return model; - } catch (...) { - delete model; - throw; - } + SPAssert(pos == blkdata.size()); + model->HollowFill(); + return model; } -} +} // namespace spades diff --git a/Sources/Core/VoxelModel.h b/Sources/Core/VoxelModel.h index 95ef73177..7d5f1cce8 100644 --- a/Sources/Core/VoxelModel.h +++ b/Sources/Core/VoxelModel.h @@ -21,6 +21,7 @@ #pragma once #include +#include #include "IStream.h" #include "Math.h" @@ -37,17 +38,18 @@ namespace spades { }; class VoxelModel : public RefCountedObject { - Vector3 origin; - int width, height, depth; - uint64_t *solidBits; - uint32_t *colors; - - protected: - ~VoxelModel(); - public: + /** + * Construct an empty voxel model of the specified size. + */ VoxelModel(int width, int height, int depth); + VoxelModel(const VoxelModel &) = delete; + void operator=(const VoxelModel &) = delete; + + /** + * Fill hollow spaces (if any) in the model. + */ void HollowFill(); /** @@ -56,83 +58,146 @@ namespace spades { * The KV6 format does not include material information, so the material * IDs of the loaded voxels are set to `0`. */ - static VoxelModel *LoadKV6(IStream *); + static Handle LoadKV6(IStream &); /** * Replace the material ID with the specified value. */ void ForceMaterial(MaterialType newMaterialId); - const uint64_t &GetSolidBitsAt(int x, int y) const { - SPAssert(x >= 0); - SPAssert(x < width); - SPAssert(y >= 0); - SPAssert(y < height); + /** `GetSolidBits` without bounds checking. */ + const uint64_t &GetSolidBitsAtUnchecked(int x, int y) const { return solidBits[x + y * width]; } + + /** `GetSolidBits` without bounds checking. */ + uint64_t &GetSolidBitsAtUnchecked(int x, int y) { return solidBits[x + y * width]; } + + /** + * Get a reference to a bitfield each of whose bit `z` indicates + * whether the voxel `(x, y, z)` is solid (occupied) or not. + */ + const uint64_t &GetSolidBitsAt(int x, int y) const { + ValidateSpan(x, y); + return GetSolidBitsAtUnchecked(x, y); + } + + /** See `GetSolidBitsAt(int, int) const`. */ uint64_t &GetSolidBitsAt(int x, int y) { - SPAssert(x >= 0); - SPAssert(x < width); - SPAssert(y >= 0); - SPAssert(y < height); - return solidBits[x + y * width]; + ValidateSpan(x, y); + return GetSolidBitsAtUnchecked(x, y); + } + + /** `GetColor` without bounds checking. */ + const uint32_t &GetColorUnchecked(int x, int y, int z) const { + return colors[(x + y * width) * depth + z]; + } + + /** `GetColor` without bounds checking. */ + uint32_t &GetColorUnchecked(int x, int y, int z) { + return colors[(x + y * width) * depth + z]; } /** - * Get the color value of a voxel. + * Get a reference to the color value of a voxel. * * The color value is a 32-bit value where the lower 24 bits represent * a color. The remaining 8 bits represent a material ID. See * `MaterialType` for the predefined material IDs. */ const uint32_t &GetColor(int x, int y, int z) const { - SPAssert(x >= 0); - SPAssert(x < width); - SPAssert(y >= 0); - SPAssert(y < height); - SPAssert(z >= 0); - SPAssert(z < depth); - return colors[(x + y * width) * depth + z]; + ValidatePoint(x, y, z); + return GetColorUnchecked(x, y, z); } + /** + * See `GetColor(int, int int) const`. + */ uint32_t &GetColor(int x, int y, int z) { - SPAssert(x >= 0); - SPAssert(x < width); - SPAssert(y >= 0); - SPAssert(y < height); - SPAssert(z >= 0); - SPAssert(z < depth); - return colors[(x + y * width) * depth + z]; + ValidatePoint(x, y, z); + return GetColorUnchecked(x, y, z); } + /** + * Return a flag whether indicating the specified voxel. + * + * This method returns `false` for out-of-bound voxels. + */ bool IsSolid(int x, int y, int z) const { - if (z < 0 || z >= depth) - return false; - if (x < 0 || y < 0 || x >= width || y >= height) + if (x < 0 || y < 0 || x >= width || y >= height || z < 0 || z >= depth) { return false; - uint64_t bits = GetSolidBitsAt(x, y); + } + uint64_t bits = GetSolidBitsAtUnchecked(x, y); return (bits >> z) & 1; } + /** + * Remove the specified solid voxel (if any). + */ void SetAir(int x, int y, int z) { - SPAssert(z >= 0); - SPAssert(z < depth); + ValidatePoint(x, y, z); + uint64_t mask = 1ULL << z; GetSolidBitsAt(x, y) &= ~mask; } + /** + * Replace the specified voxel with a solid voxel with the specified + * color value. + */ void SetSolid(int x, int y, int z, uint32_t color) { - uint64_t mask = 1ULL << z; - GetSolidBitsAt(x, y) |= mask; GetColor(x, y, z) = color; + + // Let `GetColor` validate `z` so that the following shift operator + // doesn't cause UB + uint64_t mask = 1ULL << z; + GetSolidBitsAtUnchecked(x, y) |= mask; } - Vector3 GetOrigin() { return origin; } + /** + * Get the origin point. + * + * The model is translated by this vector. In contrary to what the name implies, this + * does not represent an origin point (i.e., it does not translate the model by the + * negation of this vector). + */ + Vector3 GetOrigin() const { return origin; } + /** Set the origin point. */ void SetOrigin(Vector3 v) { origin = v; } + /** Get the width (the dimention along the X axis). */ int GetWidth() const { return width; } + /** Get the height (the dimention along the Y axis). */ int GetHeight() const { return height; } + /** Get the depth (the dimention along the Z axis). */ int GetDepth() const { return depth; } + + protected: + ~VoxelModel(); + + private: + Vector3 origin; + int width, height, depth; + std::unique_ptr solidBits; + std::unique_ptr colors; + + void ValidateSpan(int x, int y) const { + if (static_cast(x) >= static_cast(width) || + static_cast(y) >= static_cast(height)) { + ThrowInvalidSpan(x, y); + } + } + + void ValidatePoint(int x, int y, int z) const { + if (static_cast(x) >= static_cast(width) || + static_cast(y) >= static_cast(height) || + static_cast(z) >= static_cast(depth)) { + ThrowInvalidPoint(x, y, z); + } + } + + void ThrowInvalidSpan [[noreturn]] (int x, int y) const; + void ThrowInvalidPoint [[noreturn]] (int x, int y, int z) const; }; -} +} // namespace spades diff --git a/Sources/Core/VoxelModelLoader.cpp b/Sources/Core/VoxelModelLoader.cpp index ca9d7244c..8aa267a69 100644 --- a/Sources/Core/VoxelModelLoader.cpp +++ b/Sources/Core/VoxelModelLoader.cpp @@ -77,7 +77,7 @@ namespace spades { }; } // namespace - VoxelModel *VoxelModelLoader::Load(const char *path) { + Handle VoxelModelLoader::Load(const char *path) { // Load the metadata file std::string metadataPath = path; { @@ -112,7 +112,7 @@ namespace spades { { SPLog("Loading '%s' as a KV6 voxel model.", path); std::unique_ptr stream{FileManager::OpenForReading(path)}; - voxelModel = Handle{VoxelModel::LoadKV6(stream.get()), false}; + voxelModel = VoxelModel::LoadKV6(*stream); } // Apply transformation requested by the metadata @@ -124,6 +124,6 @@ namespace spades { voxelModel->ForceMaterial(*meta.forceMaterial); } - return voxelModel.Unmanage(); + return voxelModel; } } // namespace spades diff --git a/Sources/Core/VoxelModelLoader.h b/Sources/Core/VoxelModelLoader.h index b260cbbdc..b03c9c57b 100644 --- a/Sources/Core/VoxelModelLoader.h +++ b/Sources/Core/VoxelModelLoader.h @@ -22,6 +22,8 @@ #include +#include + namespace spades { class VoxelModel; @@ -52,6 +54,6 @@ namespace spades { * // (All fields are optional) * } */ - static VoxelModel *Load(const char *path); + static Handle Load(const char *path); }; -} // namespace spades \ No newline at end of file +} // namespace spades diff --git a/Sources/Core/ZipFileSystem.cpp b/Sources/Core/ZipFileSystem.cpp index b7b8b8ddb..b144e9e9e 100644 --- a/Sources/Core/ZipFileSystem.cpp +++ b/Sources/Core/ZipFileSystem.cpp @@ -330,7 +330,7 @@ namespace spades { unzClose(zip); } - IStream *ZipFileSystem::OpenForReading(const char *fn) { + std::unique_ptr ZipFileSystem::OpenForReading(const char *fn) { SPADES_MARK_FUNCTION(); if (currentStream) { @@ -345,8 +345,7 @@ namespace spades { try { currentStream = new ZipFileInputStream(this, zip); // load all data to allow seeking - DynamicMemoryStream *stream; - stream = new DynamicMemoryStream(); + auto stream = stmp::make_unique(); try { char buf[4096]; size_t rd; @@ -358,7 +357,6 @@ namespace spades { delete currentStream; return stream; } catch (...) { - delete stream; delete currentStream; throw; } @@ -368,7 +366,7 @@ namespace spades { } } - IStream *ZipFileSystem::OpenForWriting(const char *fn) { + std::unique_ptr ZipFileSystem::OpenForWriting(const char *fn) { SPADES_MARK_FUNCTION(); SPRaise("ZIP file system doesn't support writing"); } diff --git a/Sources/Core/ZipFileSystem.h b/Sources/Core/ZipFileSystem.h index 85e728be7..d29c1a943 100644 --- a/Sources/Core/ZipFileSystem.h +++ b/Sources/Core/ZipFileSystem.h @@ -67,8 +67,8 @@ namespace spades { std::vector EnumFiles(const char *) override; - IStream *OpenForReading(const char *) override; - IStream *OpenForWriting(const char *) override; + std::unique_ptr OpenForReading(const char *) override; + std::unique_ptr OpenForWriting(const char *) override; bool FileExists(const char *) override; }; } diff --git a/Sources/Draw/CellToTriangle.h b/Sources/Draw/CellToTriangle.h index 463e3f4e3..89c861d52 100644 --- a/Sources/Draw/CellToTriangle.h +++ b/Sources/Draw/CellToTriangle.h @@ -301,4 +301,4 @@ namespace c2t { return std::move(polys); } }; -} +} // namespace c2t diff --git a/Sources/Draw/GLAmbientShadowRenderer.cpp b/Sources/Draw/GLAmbientShadowRenderer.cpp index a0e1bf7d1..3cc7e0eff 100644 --- a/Sources/Draw/GLAmbientShadowRenderer.cpp +++ b/Sources/Draw/GLAmbientShadowRenderer.cpp @@ -21,39 +21,40 @@ #include #include -#include #include "GLAmbientShadowRenderer.h" #include "GLProfiler.h" #include "GLRenderer.h" +#include #include namespace spades { namespace draw { class GLAmbientShadowRenderer::UpdateDispatch : public ConcurrentDispatch { - GLAmbientShadowRenderer *renderer; + GLAmbientShadowRenderer &renderer; public: - std::atomic done {false}; - UpdateDispatch(GLAmbientShadowRenderer *r) : renderer(r) { } + std::atomic done{false}; + UpdateDispatch(GLAmbientShadowRenderer &r) : renderer(r) {} void Run() override { SPADES_MARK_FUNCTION(); - renderer->UpdateDirtyChunks(); + renderer.UpdateDirtyChunks(); done = true; } }; - GLAmbientShadowRenderer::GLAmbientShadowRenderer(GLRenderer *r, client::GameMap *m) - : renderer(r), device(r->GetGLDevice()), map(m) { + GLAmbientShadowRenderer::GLAmbientShadowRenderer(GLRenderer &r, client::GameMap &m) + : renderer(r), device(r.GetGLDevice()), map(m) { SPADES_MARK_FUNCTION(); - for (int i = 0; i < NumRays; i++) { - Vector3 dir = MakeVector3(SampleRandomFloat(), SampleRandomFloat(), SampleRandomFloat()); + for (auto &rayDir : rays) { + Vector3 dir = + MakeVector3(SampleRandomFloat(), SampleRandomFloat(), SampleRandomFloat()); dir = dir.Normalize(); dir += 0.01f; - rays[i] = dir; + rayDir = dir; } w = map->Width(); @@ -66,45 +67,47 @@ namespace spades { chunks = std::vector{static_cast(chunkW * chunkH * chunkD)}; - for (size_t i = 0; i < chunks.size(); i++) { - Chunk &c = chunks[i]; + for (Chunk &c : chunks) { float *data = (float *)c.data; - std::fill(data, data + ChunkSize * ChunkSize * ChunkSize, 1.f); + std::fill(data, data + ChunkSize * ChunkSize * ChunkSize * 2, 1.f); } - for (int x = 0; x < chunkW; x++) - for (int y = 0; y < chunkH; y++) + for (int x = 0; x < chunkW; x++) { + for (int y = 0; y < chunkH; y++) { for (int z = 0; z < chunkD; z++) { Chunk &c = GetChunk(x, y, z); c.cx = x; c.cy = y; c.cz = z; } + } + } - SPLog("Chunk buffer allocated (%d bytes)", (int) sizeof(Chunk) * chunkW * chunkH * chunkD); + SPLog("Chunk buffer allocated (%d bytes)", + (int)sizeof(Chunk) * chunkW * chunkH * chunkD); // make texture - texture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture3D, texture); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapS, IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapT, IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapR, - IGLDevice::ClampToEdge); - device->TexImage3D(IGLDevice::Texture3D, 0, IGLDevice::Red, w, h, d + 1, 0, - IGLDevice::Red, IGLDevice::FloatType, NULL); + texture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture3D, texture); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapS, IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapT, IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapR, + IGLDevice::ClampToEdge); + device.TexImage3D(IGLDevice::Texture3D, 0, IGLDevice::RG, w, h, d + 1, 0, IGLDevice::RG, + IGLDevice::FloatType, NULL); SPLog("Chunk texture allocated"); std::vector v; - v.resize(w * h); + v.resize(w * h * 2); std::fill(v.begin(), v.end(), 1.f); for (int i = 0; i < d + 1; i++) { - device->TexSubImage3D(IGLDevice::Texture3D, 0, 0, 0, i, w, h, 1, IGLDevice::Red, - IGLDevice::FloatType, v.data()); + device.TexSubImage3D(IGLDevice::Texture3D, 0, 0, 0, i, w, h, 1, IGLDevice::RG, + IGLDevice::FloatType, v.data()); } SPLog("Chunk texture initialized"); @@ -118,43 +121,25 @@ namespace spades { dispatch->Join(); delete dispatch; } - device->DeleteTexture(texture); + device.DeleteTexture(texture); } + /** + * Evaluate the AO term at the point specified by given world coordinates. + */ float GLAmbientShadowRenderer::Evaluate(IntVector3 ipos) { SPADES_MARK_FUNCTION_DEBUG(); - float sum = 0; + float sum = 0.0f; Vector3 pos = MakeVector3((float)ipos.x, (float)ipos.y, (float)ipos.z); - - float muzzleDiff = 0.02f; - - // check allowed ray direction - uint8_t directions[8] = {0, 1, 2, 3, 4, 5, 6, 7}; - int numDirections = 0; - for (int x = -1; x <= 0; x++) - for (int y = -1; y <= 0; y++) - for (int z = -1; z <= 0; z++) { - if (!map->IsSolidWrapped(ipos.x + x, ipos.y + y, ipos.z + z)) { - unsigned int bits = 0; - if (x) - bits |= 1; - if (y) - bits |= 2; - if (z) - bits |= 4; - directions[numDirections++] = bits; - } - } - if (numDirections == 0) - numDirections = 8; - - int dirId = 0; + pos.x += 0.5f; + pos.y += 0.5f; + pos.z += 0.5f; for (int i = 0; i < NumRays; i++) { Vector3 dir = rays[i]; - unsigned int bits = directions[dirId]; + unsigned int bits = i & 7; if (bits & 1) dir.x = -dir.x; if (bits & 2) @@ -162,25 +147,15 @@ namespace spades { if (bits & 4) dir.z = -dir.z; - dirId++; - if (dirId >= numDirections) - dirId = 0; - - Vector3 muzzle = pos + dir * muzzleDiff; + Vector3 muzzle = pos; IntVector3 hitBlock; float brightness = 1.f; - if (map->IsSolidWrapped((int)floorf(muzzle.x), (int)floorf(muzzle.y), - (int)floorf(muzzle.z))) { - if (numDirections < 8) - SPAssert(false); - continue; - } - if (map->CastRay(muzzle, dir, 18.f, hitBlock)) { + if (map->CastRay(muzzle, dir, (float)RayLength, hitBlock)) { Vector3 centerPos = MakeVector3(hitBlock.x + .5f, hitBlock.y + .5f, hitBlock.z + .5f); float dist = (centerPos - muzzle).GetPoweredLength(); - brightness = dist * 0.02f; // 1/7/7 + brightness = dist * (1.0 / float((RayLength - 1) * (RayLength - 1))); if (brightness > 1.f) brightness = 1.f; } @@ -188,29 +163,33 @@ namespace spades { sum += brightness; } - sum *= 1.f / (float)NumRays; - sum *= (float)numDirections / 4.f; + sum = std::min(sum * (2.f / (float)NumRays), 1.0f); return sum; } void GLAmbientShadowRenderer::GameMapChanged(int x, int y, int z, client::GameMap *map) { SPADES_MARK_FUNCTION_DEBUG(); - if (map != this->map) + if (map != this->map.GetPointerOrNull()) { return; + } - Invalidate(x - 8, y - 8, z - 8, x + 8, y + 8, z + 8); + Invalidate(x - RayLength, y - RayLength, z - RayLength, x + RayLength, y + RayLength, + z + RayLength); } void GLAmbientShadowRenderer::Invalidate(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { SPADES_MARK_FUNCTION_DEBUG(); - if (minZ < 0) + if (minZ < 0) { minZ = 0; - if (maxZ > d - 1) + } + if (maxZ > d - 1) { maxZ = d - 1; - if (minX > maxX || minY > maxY || minZ > maxZ) + } + if (minX > maxX || minY > maxY || minZ > maxZ) { return; + } // these should be floor div int cx1 = minX >> ChunkSizeBits; @@ -220,8 +199,8 @@ namespace spades { int cy2 = maxY >> ChunkSizeBits; int cz2 = maxZ >> ChunkSizeBits; - for (int cx = cx1; cx <= cx2; cx++) - for (int cy = cy1; cy <= cy2; cy++) + for (int cx = cx1; cx <= cx2; cx++) { + for (int cy = cy1; cy <= cy2; cy++) { for (int cz = cz1; cz <= cz2; cz++) { Chunk &c = GetChunkWrapped(cx, cy, cz); int originX = cx * ChunkSize; @@ -252,16 +231,13 @@ namespace spades { c.dirtyMaxZ = std::max(inMaxZ, c.dirtyMaxZ); } } + } + } } int GLAmbientShadowRenderer::GetNumDirtyChunks() { - int cnt = 0; - for (size_t i = 0; i < chunks.size(); i++) { - Chunk &c = chunks[i]; - if (c.dirty) - cnt++; - } - return cnt; + return (int)std::count_if(chunks.begin(), chunks.end(), + [](const Chunk &c) { return c.dirty; }); } void GLAmbientShadowRenderer::Update() { @@ -270,38 +246,36 @@ namespace spades { dispatch->Join(); delete dispatch; } - dispatch = new UpdateDispatch(this); + dispatch = new UpdateDispatch(*this); dispatch->Start(); } // Count the number of chunks that need to be uploaded to GPU. // This value is approximate but it should be okay for profiling use - int cnt = 0; - for (size_t i = 0; i < chunks.size(); i++) { - if (!chunks[i].transferDone.load()) - cnt++; - } - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Large Ambient Occlusion [>= %d chunk(s)]", cnt); - - device->BindTexture(IGLDevice::Texture3D, texture); - for (size_t i = 0; i < chunks.size(); i++) { - Chunk &c = chunks[i]; + std::size_t numChunksToLoad = std::count_if( + chunks.begin(), chunks.end(), [](const Chunk &c) { return !c.transferDone.load(); }); + GLProfiler::Context profiler{renderer.GetGLProfiler(), + "Large Ambient Occlusion [>= %d chunk(s)]", + numChunksToLoad}; + + device.BindTexture(IGLDevice::Texture3D, texture); + for (Chunk &c : chunks) { if (!c.transferDone.exchange(true)) { - device->TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, - c.cy * ChunkSize, c.cz * ChunkSize + 1, ChunkSize, - ChunkSize, ChunkSize, IGLDevice::Red, - IGLDevice::FloatType, c.data); + device.TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, + c.cy * ChunkSize, c.cz * ChunkSize + 1, ChunkSize, + ChunkSize, ChunkSize, IGLDevice::RG, IGLDevice::FloatType, + c.data); } } } void GLAmbientShadowRenderer::UpdateDirtyChunks() { - int dirtyChunkIds[256]; - int numDirtyChunks = 0; + std::array dirtyChunkIds; + std::size_t numDirtyChunks = 0; int nearDirtyChunks = 0; // first, check only chunks in near range - Vector3 eyePos = renderer->GetSceneDef().viewOrigin; + Vector3 eyePos = renderer.GetSceneDef().viewOrigin; int eyeX = (int)(eyePos.x) >> ChunkSizeBits; int eyeY = (int)(eyePos.y) >> ChunkSizeBits; int eyeZ = (int)(eyePos.z) >> ChunkSizeBits; @@ -320,7 +294,7 @@ namespace spades { if (c.dirty) { dirtyChunkIds[numDirtyChunks++] = static_cast(i); nearDirtyChunks++; - if (numDirtyChunks >= 256) + if (numDirtyChunks >= dirtyChunkIds.size()) break; } } @@ -331,7 +305,7 @@ namespace spades { Chunk &c = chunks[i]; if (c.dirty) { dirtyChunkIds[numDirtyChunks++] = static_cast(i); - if (numDirtyChunks >= 256) + if (numDirtyChunks >= dirtyChunkIds.size()) break; } } @@ -341,7 +315,7 @@ namespace spades { for (int i = 0; i < 8; i++) { if (numDirtyChunks <= 0) break; - int idx = SampleRandomInt(0, numDirtyChunks - 1); + std::size_t idx = SampleRandomInt(std::size_t{0}, numDirtyChunks - 1); Chunk &c = chunks[dirtyChunkIds[idx]]; // remove from list (fast) @@ -366,19 +340,170 @@ namespace spades { int originY = cy * ChunkSize; int originZ = cz * ChunkSize; + // Compute the slightly larger volume for blurring + constexpr int padding = 2; + float wData[ChunkSize + padding * 2][ChunkSize + padding * 2][ChunkSize + padding * 2] + [2]; + std::uint8_t wFlags[ChunkSize + padding * 2][ChunkSize + padding * 2] + [ChunkSize + padding * 2]; + int wOriginX = originX - padding; + int wOriginY = originY - padding; + int wOriginZ = originZ - padding; + int wDirtyMinX = c.dirtyMinX; + int wDirtyMinY = c.dirtyMinY; + int wDirtyMinZ = c.dirtyMinZ; + int wDirtyMaxX = c.dirtyMaxX + padding * 2; + int wDirtyMaxY = c.dirtyMaxY + padding * 2; + int wDirtyMaxZ = c.dirtyMaxZ + padding * 2; + + auto b = [](int i) -> std::uint8_t { return (std::uint8_t)1 << i; }; + auto to_b = [](bool b, int i) -> std::uint8_t { return (std::uint8_t)b << i; }; + + for (int z = wDirtyMinZ; z <= wDirtyMaxZ; z++) + for (int y = wDirtyMinY; y <= wDirtyMaxY; y++) + for (int x = wDirtyMinX; x <= wDirtyMaxX; x++) { + IntVector3 pos{ + x + wOriginX, + y + wOriginY, + z + wOriginZ, + }; + + if (map->IsSolidWrapped(pos.x, pos.y, pos.z)) { + wData[z][y][x][0] = 0.0; + wData[z][y][x][1] = 0.0; + } else { + wData[z][y][x][0] = Evaluate(pos); + wData[z][y][x][1] = 1.0; + } + // bit 0: solids + // bit 1: contact (by-surface voxel) + wFlags[z][y][x] = + to_b(map->IsSolidWrapped(pos.x, pos.y, pos.z), 0) | + to_b(map->IsSolidWrapped(pos.x - 1, pos.y - 1, pos.z - 1) | + map->IsSolidWrapped(pos.x - 1, pos.y - 1, pos.z) | + map->IsSolidWrapped(pos.x - 1, pos.y - 1, pos.z + 1) | + map->IsSolidWrapped(pos.x - 1, pos.y, pos.z - 1) | + map->IsSolidWrapped(pos.x - 1, pos.y, pos.z) | + map->IsSolidWrapped(pos.x - 1, pos.y, pos.z + 1) | + map->IsSolidWrapped(pos.x - 1, pos.y + 1, pos.z - 1) | + map->IsSolidWrapped(pos.x - 1, pos.y + 1, pos.z) | + map->IsSolidWrapped(pos.x - 1, pos.y + 1, pos.z + 1) | + map->IsSolidWrapped(pos.x - 1, pos.y - 1, pos.z - 1) | + map->IsSolidWrapped(pos.x, pos.y - 1, pos.z) | + map->IsSolidWrapped(pos.x, pos.y - 1, pos.z + 1) | + map->IsSolidWrapped(pos.x, pos.y, pos.z - 1) | + map->IsSolidWrapped(pos.x, pos.y, pos.z + 1) | + map->IsSolidWrapped(pos.x, pos.y + 1, pos.z - 1) | + map->IsSolidWrapped(pos.x, pos.y + 1, pos.z) | + map->IsSolidWrapped(pos.x, pos.y + 1, pos.z + 1) | + map->IsSolidWrapped(pos.x + 1, pos.y - 1, pos.z - 1) | + map->IsSolidWrapped(pos.x + 1, pos.y - 1, pos.z) | + map->IsSolidWrapped(pos.x + 1, pos.y - 1, pos.z + 1) | + map->IsSolidWrapped(pos.x + 1, pos.y, pos.z - 1) | + map->IsSolidWrapped(pos.x + 1, pos.y, pos.z) | + map->IsSolidWrapped(pos.x + 1, pos.y, pos.z + 1) | + map->IsSolidWrapped(pos.x + 1, pos.y + 1, pos.z - 1) | + map->IsSolidWrapped(pos.x + 1, pos.y + 1, pos.z) | + map->IsSolidWrapped(pos.x + 1, pos.y + 1, pos.z + 1), + 1); + } + + // The AO terms are sampled 0.5 blocks away from the terrain surface, + // which leads to under-shadowing. Compensate for this effect. + for (int z = wDirtyMinZ; z <= wDirtyMaxZ; z++) + for (int y = wDirtyMinY; y <= wDirtyMaxY; y++) + for (int x = wDirtyMinX; x <= wDirtyMaxX; x++) { + float &d = wData[z][y][x][0]; + d *= d * d + 1.0f - d; + } + + // Blur the result to remove noise + // + // | this | neighbor | + // | solid | contact | solid | contact | blur + // | 0 0 | 0 x | 1 + // | 0 1 | 0 0 | 0 (prevent under-shadowing) + // | 0 1 | 0 1 | 1 + // | 0 x | 1 x | 0 (solid voxel's value is zero) + // | 1 x | 0 x | 0 (solid voxel's value must remain zero) + // | 1 x | 1 x | x + // + // + // this voxel + // + // solid + // /-------\ . + // +---+---+---+---+ + // | 1 | 0 | 0 | 0 | + // +---+---+---+---+\ . + // | 1 | 1 | 0 | 0 | | + // /+---+---+---+---+ | contact neighbor + // | | 0 | 0 | | | | + // solid | +---+---+---+---+/ + // | | 0 | 0 | | | + // \+---+---+---+---+ + // \-------/ + // contact + // + static const float divider[] = {1.0f, 1.0f / 2.0f, 1.0f / 3.0f}; + auto mask = [](bool b, float x) { return b ? x : 0.0f; }; + auto shouldBlur = [=](std::uint8_t thisFlags, std::uint8_t neighborFlags) { + return ((neighborFlags & b(0)) | ((~thisFlags | neighborFlags) & b(1))) == 0b10; + }; + for (int blurPass = 0; blurPass < 2; ++blurPass) { + for (int z = wDirtyMinZ; z <= wDirtyMaxZ; z++) + for (int y = wDirtyMinY; y <= wDirtyMaxY; y++) + for (int x = wDirtyMinX + 1; x < wDirtyMaxX; x++) { + if (wFlags[z][y][x] & b(0)) { + continue; + } + // Do not blur between by-surface voxels and + // in-the-air voxels + bool m1 = shouldBlur(wFlags[z][y][x], wFlags[z][y][x - 1]); + bool m2 = shouldBlur(wFlags[z][y][x], wFlags[z][y][x + 1]); + wData[z][y][x][0] = + (wData[z][y][x][0] + mask(m1, wData[z][y][x - 1][0]) + + mask(m2, wData[z][y][x + 1][0])) * + divider[(int)m1 + (int)m2]; + } + for (int z = wDirtyMinZ; z <= wDirtyMaxZ; z++) + for (int y = wDirtyMinY + 1; y < wDirtyMaxY; y++) + for (int x = wDirtyMinX; x <= wDirtyMaxX; x++) { + if (wFlags[z][y][x] & b(0)) { + continue; + } + bool m1 = shouldBlur(wFlags[z][y][x], wFlags[z][y - 1][x]); + bool m2 = shouldBlur(wFlags[z][y][x], wFlags[z][y + 1][x]); + wData[z][y][x][0] = + (wData[z][y][x][0] + mask(m1, wData[z][y - 1][x][0]) + + mask(m2, wData[z][y + 1][x][0])) * + divider[(int)m1 + (int)m2]; + } + for (int z = wDirtyMinZ + 1; z < wDirtyMaxZ; z++) + for (int y = wDirtyMinY; y <= wDirtyMaxY; y++) + for (int x = wDirtyMinX; x <= wDirtyMaxX; x++) { + if (wFlags[z][y][x] & b(0)) { + continue; + } + bool m1 = shouldBlur(wFlags[z][y][x], wFlags[z - 1][y][x]); + bool m2 = shouldBlur(wFlags[z][y][x], wFlags[z + 1][y][x]); + wData[z][y][x][0] = + (wData[z][y][x][0] + mask(m1, wData[z - 1][y][x][0]) + + mask(m2, wData[z + 1][y][x][0])) * + divider[(int)m1 + (int)m2]; + } + } + + // Copy the result to `c.data` for (int z = c.dirtyMinZ; z <= c.dirtyMaxZ; z++) for (int y = c.dirtyMinY; y <= c.dirtyMaxY; y++) for (int x = c.dirtyMinX; x <= c.dirtyMaxX; x++) { - IntVector3 pos; - pos.x = (x + originX); - pos.y = (y + originY); - pos.z = (z + originZ); - - c.data[z][y][x] = Evaluate(pos); + c.data[z][y][x][0] = wData[z + padding][y + padding][x + padding][0]; + c.data[z][y][x][1] = wData[z + padding][y + padding][x + padding][1]; } c.dirty = false; c.transferDone = false; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLAmbientShadowRenderer.h b/Sources/Draw/GLAmbientShadowRenderer.h index 45b57e985..9261eb25b 100644 --- a/Sources/Draw/GLAmbientShadowRenderer.h +++ b/Sources/Draw/GLAmbientShadowRenderer.h @@ -20,12 +20,14 @@ #pragma once -#include +#include #include +#include +#include "IGLDevice.h" #include #include -#include "IGLDevice.h" +#include namespace spades { namespace client { @@ -35,23 +37,27 @@ namespace spades { class GLRenderer; class IGLDevice; class GLAmbientShadowRenderer { - class UpdateDispatch; - enum { NumRays = 16, ChunkSize = 16, ChunkSizeBits = 4 }; - GLRenderer *renderer; - IGLDevice *device; - client::GameMap *map; - Vector3 rays[NumRays]; + + static constexpr int NumRays = 16; + static constexpr int ChunkSizeBits = 4; + static constexpr int ChunkSize = 1 << ChunkSizeBits; + static constexpr int RayLength = 16; + + GLRenderer &renderer; + IGLDevice &device; + Handle map; + std::array rays; struct Chunk { int cx, cy, cz; - float data[ChunkSize][ChunkSize][ChunkSize]; + float data[ChunkSize][ChunkSize][ChunkSize][2]; bool dirty = true; int dirtyMinX = 0, dirtyMaxX = ChunkSize - 1; int dirtyMinY = 0, dirtyMaxY = ChunkSize - 1; int dirtyMinZ = 0, dirtyMaxZ = ChunkSize - 1; - std::atomic transferDone {true}; + std::atomic transferDone{true}; }; IGLDevice::UInteger texture; @@ -85,7 +91,7 @@ namespace spades { UpdateDispatch *dispatch; public: - GLAmbientShadowRenderer(GLRenderer *renderer, client::GameMap *map); + GLAmbientShadowRenderer(GLRenderer &renderer, client::GameMap &map); ~GLAmbientShadowRenderer(); float Evaluate(IntVector3); @@ -96,5 +102,5 @@ namespace spades { IGLDevice::UInteger GetTexture() { return texture; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLAutoExposureFilter.cpp b/Sources/Draw/GLAutoExposureFilter.cpp index aff6e481d..a8084be5d 100644 --- a/Sources/Draw/GLAutoExposureFilter.cpp +++ b/Sources/Draw/GLAutoExposureFilter.cpp @@ -20,62 +20,58 @@ #include -#include -#include #include "GLAutoExposureFilter.h" #include "GLProgram.h" #include "GLProgramAttribute.h" #include "GLProgramUniform.h" #include "GLQuadRenderer.h" #include "GLRenderer.h" -#include "IGLDevice.h" #include "GLSettings.h" +#include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLAutoExposureFilter::GLAutoExposureFilter(GLRenderer *renderer) : renderer(renderer) { - thru = renderer->RegisterProgram("Shaders/PostFilters/PassThrough.program"); + GLAutoExposureFilter::GLAutoExposureFilter(GLRenderer &renderer) : renderer{renderer} { + thru = renderer.RegisterProgram("Shaders/PostFilters/PassThrough.program"); preprocess = - renderer->RegisterProgram("Shaders/PostFilters/AutoExposurePreprocess.program"); - computeGain = renderer->RegisterProgram("Shaders/PostFilters/AutoExposure.program"); + renderer.RegisterProgram("Shaders/PostFilters/AutoExposurePreprocess.program"); + computeGain = renderer.RegisterProgram("Shaders/PostFilters/AutoExposure.program"); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); - exposureTexture = dev->GenTexture(); + exposureTexture = dev.GenTexture(); - dev->BindTexture(IGLDevice::Texture2D, exposureTexture); + dev.BindTexture(IGLDevice::Texture2D, exposureTexture); - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA16F, 1, 1, 0, IGLDevice::RGBA, - IGLDevice::UnsignedByte, NULL); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA16F, 1, 1, 0, IGLDevice::RGBA, + IGLDevice::UnsignedByte, NULL); SPLog("Brightness Texture Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - exposureFramebuffer = dev->GenFramebuffer(); - dev->BindFramebuffer(IGLDevice::Framebuffer, exposureFramebuffer); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, exposureTexture, 0); - dev->Viewport(0, 0, 1, 1); - dev->ClearColor(1.f, 1.f, 1.f, 1.f); - dev->Clear(IGLDevice::ColorBufferBit); - - dev->BindFramebuffer(IGLDevice::Framebuffer, 0); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::ClampToEdge); + + exposureFramebuffer = dev.GenFramebuffer(); + dev.BindFramebuffer(IGLDevice::Framebuffer, exposureFramebuffer); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, exposureTexture, 0); + dev.Viewport(0, 0, 1, 1); + dev.ClearColor(1.f, 1.f, 1.f, 1.f); + dev.Clear(IGLDevice::ColorBufferBit); + + dev.BindFramebuffer(IGLDevice::Framebuffer, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); SPLog("Brightness Framebuffer Allocated"); } GLAutoExposureFilter::~GLAutoExposureFilter() { - IGLDevice *dev = renderer->GetGLDevice(); - dev->DeleteTexture(exposureTexture); - dev->DeleteFramebuffer(exposureFramebuffer); + IGLDevice &dev = renderer.GetGLDevice(); + dev.DeleteTexture(exposureTexture); + dev.DeleteFramebuffer(exposureFramebuffer); } namespace { @@ -83,17 +79,17 @@ namespace spades { int w, h; GLColorBuffer buffer; }; - } + } // namespace GLColorBuffer GLAutoExposureFilter::Filter(GLColorBuffer input, float dt) { SPADES_MARK_FUNCTION(); std::vector levels; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); - GLSettings &settings = renderer->GetSettings(); + GLSettings &settings = renderer.GetSettings(); static GLProgramAttribute thruPosition("positionAttribute"); static GLProgramUniform thruColor("colorUniform"); @@ -139,8 +135,8 @@ namespace spades { thruTexture.SetValue(0); thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); - dev->Enable(IGLDevice::Blend, false); - dev->ActiveTexture(0); + dev.Enable(IGLDevice::Blend, false); + dev.ActiveTexture(0); // downsample until it becomes 1x1x GLColorBuffer buffer = input; @@ -153,8 +149,8 @@ namespace spades { int newH = (prevH + 1) / 2; GLColorBuffer newLevel = input.GetManager()->CreateBufferHandle(newW, newH); - dev->BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, newLevel.GetFramebuffer()); + dev.BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, newLevel.GetFramebuffer()); if (firstLevel) { preprocess->Use(); qr.SetCoordAttributeIndex(preprocessPosition()); @@ -163,18 +159,18 @@ namespace spades { thru->Use(); qr.SetCoordAttributeIndex(thruPosition()); } - dev->Viewport(0, 0, newLevel.GetWidth(), newLevel.GetHeight()); - dev->ClearColor(1.f, 1.f, 1.f, 1.f); - dev->Clear(IGLDevice::ColorBufferBit); + dev.Viewport(0, 0, newLevel.GetWidth(), newLevel.GetHeight()); + dev.ClearColor(1.f, 1.f, 1.f, 1.f); + dev.Clear(IGLDevice::ColorBufferBit); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); buffer = newLevel; } // compute estimated brightness on GPU - dev->Enable(IGLDevice::Blend, true); - dev->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); + dev.Enable(IGLDevice::Blend, true); + dev.BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); float minExposure = settings.r_hdrAutoExposureMin; float maxExposure = settings.r_hdrAutoExposureMax; @@ -196,30 +192,30 @@ namespace spades { computeGainMinGain.SetValue(std::pow(2.0f, minExposure)); computeGainMaxGain.SetValue(std::pow(2.0f, maxExposure)); qr.SetCoordAttributeIndex(computeGainPosition()); - dev->BindFramebuffer(IGLDevice::Framebuffer, exposureFramebuffer); - dev->BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); - dev->Viewport(0, 0, 1, 1); + dev.BindFramebuffer(IGLDevice::Framebuffer, exposureFramebuffer); + dev.BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); + dev.Viewport(0, 0, 1, 1); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); // apply exposure adjustment thru->Use(); thruColor.SetValue(1.f, 1.f, 1.f, 1.f); thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); thruTexture.SetValue(0); - dev->Enable(IGLDevice::Blend, true); - dev->BlendFunc(IGLDevice::DestColor, IGLDevice::Zero); // multiply + dev.Enable(IGLDevice::Blend, true); + dev.BlendFunc(IGLDevice::DestColor, IGLDevice::Zero); // multiply qr.SetCoordAttributeIndex(thruPosition()); - dev->BindTexture(IGLDevice::Texture2D, exposureTexture); - dev->BindFramebuffer(IGLDevice::Framebuffer, input.GetFramebuffer()); - dev->Viewport(0, 0, input.GetWidth(), input.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, exposureTexture); + dev.BindFramebuffer(IGLDevice::Framebuffer, input.GetFramebuffer()); + dev.Viewport(0, 0, input.GetWidth(), input.GetHeight()); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); - dev->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); + dev.BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); return input; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLAutoExposureFilter.h b/Sources/Draw/GLAutoExposureFilter.h index 19339c490..2b935119f 100644 --- a/Sources/Draw/GLAutoExposureFilter.h +++ b/Sources/Draw/GLAutoExposureFilter.h @@ -30,16 +30,16 @@ namespace spades { GLProgram *thru; GLProgram *computeGain; GLProgram *preprocess; - GLRenderer *renderer; + GLRenderer &renderer; // 1x1 of framebuffer that holds the scene brightness IGLDevice::UInteger exposureFramebuffer; IGLDevice::UInteger exposureTexture; public: - GLAutoExposureFilter(GLRenderer *); + GLAutoExposureFilter(GLRenderer &); ~GLAutoExposureFilter(); GLColorBuffer Filter(GLColorBuffer, float dt); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLBasicShadowMapRenderer.cpp b/Sources/Draw/GLBasicShadowMapRenderer.cpp index 7ae4f453f..9add82945 100644 --- a/Sources/Draw/GLBasicShadowMapRenderer.cpp +++ b/Sources/Draw/GLBasicShadowMapRenderer.cpp @@ -19,64 +19,62 @@ */ #include "GLBasicShadowMapRenderer.h" -#include -#include -#include #include "GLProfiler.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include +#include namespace spades { namespace draw { - GLBasicShadowMapRenderer::GLBasicShadowMapRenderer(GLRenderer *r) - : IGLShadowMapRenderer(r) { + GLBasicShadowMapRenderer::GLBasicShadowMapRenderer(GLRenderer &r) + : IGLShadowMapRenderer(r), device(r.GetGLDevice()) { SPADES_MARK_FUNCTION(); - device = r->GetGLDevice(); - - textureSize = r->GetSettings().r_shadowMapSize; + textureSize = r.GetSettings().r_shadowMapSize; if ((int)textureSize > 4096) { SPLog("r_shadowMapSize is too large; changed to 4096"); - r->GetSettings().r_shadowMapSize = textureSize = 4096; + r.GetSettings().r_shadowMapSize = textureSize = 4096; } - colorTexture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, colorTexture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGB, textureSize, textureSize, 0, - IGLDevice::RGB, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); + colorTexture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, colorTexture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGB, textureSize, textureSize, 0, + IGLDevice::RGB, IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); for (int i = 0; i < NumSlices; i++) { - texture[i] = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, texture[i]); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, - textureSize, textureSize, 0, IGLDevice::DepthComponent, - IGLDevice::UnsignedInt, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - framebuffer[i] = device->GenFramebuffer(); - device->BindFramebuffer(IGLDevice::Framebuffer, framebuffer[i]); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, colorTexture, 0); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, - IGLDevice::Texture2D, texture[i], 0); - - device->BindFramebuffer(IGLDevice::Framebuffer, 0); + texture[i] = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, texture[i]); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, textureSize, + textureSize, 0, IGLDevice::DepthComponent, IGLDevice::UnsignedInt, + NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + framebuffer[i] = device.GenFramebuffer(); + device.BindFramebuffer(IGLDevice::Framebuffer, framebuffer[i]); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, colorTexture, 0); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, + IGLDevice::Texture2D, texture[i], 0); + + device.BindFramebuffer(IGLDevice::Framebuffer, 0); } } @@ -84,10 +82,10 @@ namespace spades { SPADES_MARK_FUNCTION(); for (int i = 0; i < NumSlices; i++) { - device->DeleteTexture(texture[i]); - device->DeleteFramebuffer(framebuffer[i]); + device.DeleteTexture(texture[i]); + device.DeleteFramebuffer(framebuffer[i]); } - device->DeleteTexture(colorTexture); + device.DeleteTexture(colorTexture); } #define Segment GLBSMRSegment @@ -142,7 +140,7 @@ namespace spades { up = Vector3::Cross(lightDir, side).Normalize(); // build frustrum - client::SceneDefinition def = GetRenderer()->GetSceneDef(); + client::SceneDefinition def = GetRenderer().GetSceneDef(); Vector3 frustrum[8]; float tanX = tanf(def.fovX * .5f); float tanY = tanf(def.fovY * .5f); @@ -224,15 +222,12 @@ namespace spades { void GLBasicShadowMapRenderer::Render() { SPADES_MARK_FUNCTION(); - IGLDevice::Integer lastFb = device->GetInteger(IGLDevice::FramebufferBinding); - - // client::SceneDefinition def = GetRenderer()->GetSceneDef(); - float nearDist = 0.f; for (int i = 0; i < NumSlices; i++) { - GLProfiler::Context profiler(GetRenderer()->GetGLProfiler(), "Slice %d / %d", i + 1, (int)NumSlices); + GLProfiler::Context profiler(GetRenderer().GetGLProfiler(), "Slice %d / %d", i + 1, + (int)NumSlices); float farDist = 0.0; // TODO: variable far distance according to the scene definition @@ -245,32 +240,16 @@ namespace spades { BuildMatrix(nearDist, farDist); matrices[i] = matrix; - /* - printf("m[%d]=\n[%f,%f,%f,%f]\n[%f,%f,%f,%f]\n[%f,%f,%f,%f]\n[%f,%f,%f,%f]\n", - i, matrix.m[0], matrix.m[4], matrix.m[8], matrix.m[12], - matrix.m[1], matrix.m[5], matrix.m[9], matrix.m[13], - matrix.m[2], matrix.m[6], matrix.m[10], matrix.m[14], - matrix.m[3], matrix.m[7], matrix.m[11], matrix.m[15]);*/ - /* - matrix = Matrix4::Identity(); - matrix = Matrix4::Scale(1.f / 16.f); - matrix = matrix * Matrix4::Rotate(MakeVector3(1, 0, 0), M_PI / 4.f); - matrix = matrix * Matrix4::Translate(-def.viewOrigin); - matrix = Matrix4::Scale(1,1,16.f / 70.f) * matrix;*/ - - device->BindFramebuffer(IGLDevice::Framebuffer, framebuffer[i]); - device->Viewport(0, 0, textureSize, textureSize); - device->ClearDepth(1.f); - device->Clear(IGLDevice::DepthBufferBit); + + device.BindFramebuffer(IGLDevice::Framebuffer, framebuffer[i]); + device.Viewport(0, 0, textureSize, textureSize); + device.ClearDepth(1.f); + device.Clear(IGLDevice::DepthBufferBit); RenderShadowMapPass(); nearDist = farDist; } - - device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); - - device->Viewport(0, 0, device->ScreenWidth(), device->ScreenHeight()); } bool GLBasicShadowMapRenderer::Cull(const spades::AABB3 &) { @@ -292,5 +271,5 @@ namespace spades { // return true; // return obb.GetDistanceTo(center) < rad; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLBasicShadowMapRenderer.h b/Sources/Draw/GLBasicShadowMapRenderer.h index 0df7f8c3b..739cbe2cb 100644 --- a/Sources/Draw/GLBasicShadowMapRenderer.h +++ b/Sources/Draw/GLBasicShadowMapRenderer.h @@ -31,7 +31,7 @@ namespace spades { enum { NumSlices = 3 }; - IGLDevice *device; + IGLDevice &device; int textureSize; @@ -49,12 +49,12 @@ namespace spades { void BuildMatrix(float near, float far); public: - GLBasicShadowMapRenderer(GLRenderer *); + GLBasicShadowMapRenderer(GLRenderer &); ~GLBasicShadowMapRenderer(); void Render() override; bool Cull(const AABB3 &) override; bool SphereCull(const Vector3 ¢er, float rad) override; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLBloomFilter.cpp b/Sources/Draw/GLBloomFilter.cpp index 0887284d9..c17106856 100644 --- a/Sources/Draw/GLBloomFilter.cpp +++ b/Sources/Draw/GLBloomFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLBloomFilter.h" #include "GLProgram.h" #include "GLProgramAttribute.h" @@ -29,11 +27,13 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLBloomFilter::GLBloomFilter(GLRenderer *renderer) : renderer(renderer) { - thru = renderer->RegisterProgram("Shaders/PostFilters/PassThrough.program"); + GLBloomFilter::GLBloomFilter(GLRenderer &renderer) : renderer(renderer) { + thru = renderer.RegisterProgram("Shaders/PostFilters/PassThrough.program"); } #define Level BloomLevel @@ -48,7 +48,7 @@ namespace spades { std::vector levels; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); static GLProgramAttribute thruPosition("positionAttribute"); @@ -61,7 +61,7 @@ namespace spades { thruTexture(thru); thruTexCoordRange(thru); - GLProgram *gammaMix = renderer->RegisterProgram("Shaders/PostFilters/GammaMix.program"); + GLProgram *gammaMix = renderer.RegisterProgram("Shaders/PostFilters/GammaMix.program"); static GLProgramAttribute gammaMixPosition("positionAttribute"); static GLProgramUniform gammaMixTexture1("texture1"); static GLProgramUniform gammaMixTexture2("texture2"); @@ -77,7 +77,7 @@ namespace spades { thru->Use(); thruColor.SetValue(1.f, 1.f, 1.f, 1.f); thruTexture.SetValue(0); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); // create downsample levels for (int i = 0; i < 6; i++) { @@ -96,14 +96,14 @@ namespace spades { thru->Use(); qr.SetCoordAttributeIndex(thruPosition()); - dev->BindTexture(IGLDevice::Texture2D, prevLevel.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, newLevel.GetFramebuffer()); - dev->Viewport(0, 0, newLevel.GetWidth(), newLevel.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, prevLevel.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, newLevel.GetFramebuffer()); + dev.Viewport(0, 0, newLevel.GetWidth(), newLevel.GetHeight()); thruTexCoordRange.SetValue(0.f, 0.f, (float)newLevel.GetWidth() * 2.f / (float)prevW, (float)newLevel.GetHeight() * 2.f / (float)prevH); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); Level lv; lv.w = newW; @@ -112,8 +112,8 @@ namespace spades { levels.push_back(lv); } - dev->Enable(IGLDevice::Blend, true); - dev->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); + dev.Enable(IGLDevice::Blend, true); + dev.BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); // composite levels in the opposite direction thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); @@ -126,12 +126,12 @@ namespace spades { thru->Use(); qr.SetCoordAttributeIndex(thruPosition()); - dev->BindTexture(IGLDevice::Texture2D, curLevel.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, targLevel.GetFramebuffer()); - dev->Viewport(0, 0, targLevel.GetWidth(), targLevel.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, curLevel.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, targLevel.GetFramebuffer()); + dev.Viewport(0, 0, targLevel.GetWidth(), targLevel.GetHeight()); thruColor.SetValue(1.f, 1.f, 1.f, alpha); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); } // composite to the final image @@ -140,22 +140,22 @@ namespace spades { gammaMix->Use(); qr.SetCoordAttributeIndex(gammaMixPosition()); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, topLevel.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, topLevel.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); gammaMixTexture1.SetValue(0); gammaMixTexture2.SetValue(1); gammaMixMix1.SetValue(.8f, .8f, .8f); gammaMixMix2.SetValue(.2f, .2f, .2f); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); - dev->ActiveTexture(0); + dev.ActiveTexture(0); return output; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLBloomFilter.h b/Sources/Draw/GLBloomFilter.h index 4b6112738..865f71858 100644 --- a/Sources/Draw/GLBloomFilter.h +++ b/Sources/Draw/GLBloomFilter.h @@ -29,11 +29,11 @@ namespace spades { class GLBloomFilter { GLProgram *thru; - GLRenderer *renderer; + GLRenderer &renderer; public: - GLBloomFilter(GLRenderer *); + GLBloomFilter(GLRenderer &); GLColorBuffer Filter(GLColorBuffer); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLCameraBlurFilter.cpp b/Sources/Draw/GLCameraBlurFilter.cpp index 649766544..dbf3bf91b 100644 --- a/Sources/Draw/GLCameraBlurFilter.cpp +++ b/Sources/Draw/GLCameraBlurFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLCameraBlurFilter.h" #include "GLProfiler.h" #include "GLProgram.h" @@ -30,12 +28,14 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLCameraBlurFilter::GLCameraBlurFilter(GLRenderer *renderer) : renderer(renderer) { + GLCameraBlurFilter::GLCameraBlurFilter(GLRenderer &renderer) : renderer(renderer) { prevMatrix = Matrix4::Identity(); - program = renderer->RegisterProgram("Shaders/PostFilters/CameraBlur.program"); + program = renderer.RegisterProgram("Shaders/PostFilters/CameraBlur.program"); } #define M(r, c) (d.m[(r) + (c)*4]) @@ -56,7 +56,8 @@ namespace spades { return acosf(v); } - GLColorBuffer GLCameraBlurFilter::Filter(GLColorBuffer input, float radialBlur) { + GLColorBuffer GLCameraBlurFilter::Filter(GLColorBuffer input, float intensity, + float radialBlur) { SPADES_MARK_FUNCTION(); if (radialBlur > 0.f) @@ -66,10 +67,10 @@ namespace spades { bool hasRadialBlur = radialBlur < .9999f; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); static GLProgramAttribute programPosition("positionAttribute"); static GLProgramUniform programTexture("mainTexture"); @@ -83,7 +84,7 @@ namespace spades { programReverseMatrix(program); programShutterTimeScale(program); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); Matrix4 newMatrix = Matrix4::Identity(); Vector3 axes[] = {def.viewAxis[0], def.viewAxis[1], def.viewAxis[2]}; axes[0] /= std::tan(def.fovX * 0.5f); @@ -114,14 +115,14 @@ namespace spades { } float movePixels = MyACos(diffMatrix.m[0]); - float shutterTimeScale = .3f; + float shutterTimeScale = intensity; movePixels = std::max(movePixels, MyACos(diffMatrix.m[5])); movePixels = std::max(movePixels, MyACos(diffMatrix.m[10])); movePixels = tanf(movePixels) / tanf(def.fovX * .5f); - movePixels *= (float)dev->ScreenWidth() * .5f; + movePixels *= (float)renderer.GetRenderWidth() * .5f; movePixels *= shutterTimeScale; - movePixels = std::max(movePixels, (1.f - radialBlur) * dev->ScreenWidth() * 0.5f); + movePixels = std::max(movePixels, (1.f - radialBlur) * renderer.GetRenderWidth() * 0.5f); if (movePixels < 1.f) { // too less change, skip camera blur @@ -146,28 +147,28 @@ namespace spades { GLColorBuffer buf = input; qr.SetCoordAttributeIndex(programPosition()); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); - dev->ActiveTexture(0); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); + dev.ActiveTexture(0); for (int i = 0; i < levels; i++) { GLColorBuffer output = input.GetManager()->CreateBufferHandle(); programShutterTimeScale.SetValue(shutterTimeScale); - dev->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, buf.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); shutterTimeScale /= 5.f; buf = output; } - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, 0); - dev->ActiveTexture(0); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, 0); + dev.ActiveTexture(0); return buf; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLCameraBlurFilter.h b/Sources/Draw/GLCameraBlurFilter.h index d3ceda17e..4d4d3144c 100644 --- a/Sources/Draw/GLCameraBlurFilter.h +++ b/Sources/Draw/GLCameraBlurFilter.h @@ -20,8 +20,8 @@ #pragma once -#include #include "GLFramebufferManager.h" +#include namespace spades { namespace draw { @@ -29,12 +29,12 @@ namespace spades { class GLProgram; class GLCameraBlurFilter { GLProgram *program; - GLRenderer *renderer; + GLRenderer &renderer; Matrix4 prevMatrix; public: - GLCameraBlurFilter(GLRenderer *); - GLColorBuffer Filter(GLColorBuffer, float radialBlur = 0.f); + GLCameraBlurFilter(GLRenderer &); + GLColorBuffer Filter(GLColorBuffer, float intensity, float radialBlur = 0.f); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLColorCorrectionFilter.cpp b/Sources/Draw/GLColorCorrectionFilter.cpp index 8999c1a09..bcd10e0d9 100644 --- a/Sources/Draw/GLColorCorrectionFilter.cpp +++ b/Sources/Draw/GLColorCorrectionFilter.cpp @@ -19,9 +19,8 @@ */ #include +#include -#include -#include #include "GLColorCorrectionFilter.h" #include "GLProgram.h" #include "GLProgramAttribute.h" @@ -29,41 +28,90 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include #include namespace spades { namespace draw { - GLColorCorrectionFilter::GLColorCorrectionFilter(GLRenderer *renderer) - : renderer(renderer), settings(renderer->GetSettings()) { - lens = renderer->RegisterProgram("Shaders/PostFilters/ColorCorrection.program"); + GLColorCorrectionFilter::GLColorCorrectionFilter(GLRenderer &renderer) + : renderer(renderer), settings(renderer.GetSettings()) { + lens = renderer.RegisterProgram("Shaders/PostFilters/ColorCorrection.program"); + gaussProgram = renderer.RegisterProgram("Shaders/PostFilters/Gauss1D.program"); } - GLColorBuffer GLColorCorrectionFilter::Filter(GLColorBuffer input, Vector3 tintVal) { + GLColorBuffer GLColorCorrectionFilter::Filter(GLColorBuffer input, Vector3 tintVal, + float fogLuminance) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); + GLColorBuffer output = input.GetManager()->CreateBufferHandle(); + + float sharpeningFinalGainValue = + std::max(std::min(settings.r_sharpen.operator float(), 1.0f), 0.0f); + GLColorBuffer blurredInput = input; + + if (sharpeningFinalGainValue > 0.0f) { + // Apply a 1D gaussian blur on the horizontal direction. + // (The vertical direction blur is done by the final program) + static GLProgramAttribute blur_positionAttribute("positionAttribute"); + static GLProgramUniform blur_textureUniform("mainTexture"); + static GLProgramUniform blur_unitShift("unitShift"); + gaussProgram->Use(); + blur_positionAttribute(gaussProgram); + blur_textureUniform(gaussProgram); + blur_unitShift(gaussProgram); + blur_textureUniform.SetValue(0); + + dev.ActiveTexture(0); + qr.SetCoordAttributeIndex(blur_positionAttribute()); + dev.Enable(IGLDevice::Blend, false); + + blurredInput = renderer.GetFramebufferManager()->CreateBufferHandle(); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, blurredInput.GetFramebuffer()); + blur_unitShift.SetValue(1.0f / (float)input.GetWidth(), 0.f); + qr.Draw(); + } + + float sharpeningFloor = 0.0f; + + // If temporal AA is enabled, enable the sharpening effect regardless of + // the current fog color to offset the blurring caused by the temporal AA. + if (settings.r_temporalAA) { + sharpeningFloor = 1.5f; + } + static GLProgramAttribute lensPosition("positionAttribute"); static GLProgramUniform lensTexture("mainTexture"); + static GLProgramUniform blurredTexture("blurredTexture"); static GLProgramUniform saturation("saturation"); static GLProgramUniform enhancement("enhancement"); static GLProgramUniform tint("tint"); + static GLProgramUniform sharpening("sharpening"); + static GLProgramUniform sharpeningFinalGain("sharpeningFinalGain"); + static GLProgramUniform blurPixelShift("blurPixelShift"); saturation(lens); enhancement(lens); tint(lens); + sharpening(lens); + sharpeningFinalGain(lens); + blurPixelShift(lens); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); lensPosition(lens); lensTexture(lens); + blurredTexture(lens); lens->Use(); tint.SetValue(tintVal.x, tintVal.y, tintVal.z); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); if (settings.r_hdr) { // when HDR is enabled ACES tone mapping is applied first, so @@ -87,18 +135,82 @@ namespace spades { } lensTexture.SetValue(0); + blurredTexture.SetValue(1); + + // Calculate the sharpening factor + // + // One reason to do this is for aesthetic reasons. Another reason is to offset + // OpenSpades' denser fog compared to the vanilla client. Technically, the fog density + // function is mostly identical between these two clients. However, OpenSpades applies + // the fog color in the linear color space, which is physically accurate but has an + // unexpected consequence of somewhat strengthening the effect. + // + // (`r_volumetricFog` completely changes the density function, which we leave out from + // this discussion.) + // + // Given an object color o (only one color channel is discussed here), fog color f, and + // fog density d, the output color c_voxlap and c_os for the vanilla client and + // OpenSpades, respectively, is calculated by: + // + // c_voxlap = o^(1/2)(1-d) + f^(1/2)d + // c_os = (o(1-d) + fd)^(1/2) + // + // Here the sRGB transfer function is approximated by an exact gamma = 2 power law. + // o and f are in the linear color space, whereas c_voxlap and c_os are in the sRGB + // color space (because that's how `ColorCorrection.fs` is implemented). + // + // The contrast reduction by the fog can be calculated by differentiating each of them + // by o: + // + // c_voxlap' = (1-d) / sqrt(o) / 2 + // c_os' = (1-d) / sqrt(o(1-d) + fd) / 2 + // + // Now we find out the amount of color contrast we must recover by dividing c_voxlap' by + // c_os'. Since it's objects around the fog end distance that concern the users, let + // d = 1: + // + // c_voxlap' / c_os' = sqrt(o(1-d) + fd) / sqrt(o) + // = sqrt(f) / sqrt(o) + // + // (Turns out, the result so far does not change whichever color space c_voxlap and c_os + // are represented in.) + // + // This is a function over an object color o and fog color f. Let us calculate the + // average of this function assuming a uniform distribution of o over the interval + // [o_min, o_max]: + // + // ∫[c_voxlap' / c_os', {o, o_min, o_max}] + // = 2sqrt(f)(sqrt(o_max) - sqrt(o_min)) / (o_max - o_min) + // + // Since the pixels aren't usually fully lit nor completely dark, let us arbitrarily + // assume o_min = 0.001 and o_max = 0.5 (I think this is reasonable for a deuce hiding + // in a shady corridor) (and let it be `r_offset`): + // + // r_offset + // = 2sqrt(f)(sqrt(o_max) - sqrt(o_min)) / (o_max - o_min) + // ≈ 2.70 sqrt(f) + // + // So if this value is higher than 1, we need enhance the rendered image. Otherwise, + // we will maintain the status quo for now. (In most servers I have encountered, the fog + // color was a bright color, so this status quo won't be a problem, I think. No one has + // complained about it so far.) + sharpening.SetValue(std::max(std::sqrt(fogLuminance) * 2.7f, sharpeningFloor)); + sharpeningFinalGain.SetValue(sharpeningFinalGainValue); + blurPixelShift.SetValue(1.0f / (float)input.GetHeight()); // composite to the final image - GLColorBuffer output = input.GetManager()->CreateBufferHandle(); qr.SetCoordAttributeIndex(lensPosition()); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, blurredInput.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); return output; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLColorCorrectionFilter.h b/Sources/Draw/GLColorCorrectionFilter.h index 2a7aaad41..10b4c69d1 100644 --- a/Sources/Draw/GLColorCorrectionFilter.h +++ b/Sources/Draw/GLColorCorrectionFilter.h @@ -28,13 +28,17 @@ namespace spades { class GLProgram; class GLSettings; class GLColorCorrectionFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLSettings &settings; + GLProgram *gaussProgram; GLProgram *lens; public: - GLColorCorrectionFilter(GLRenderer *); - GLColorBuffer Filter(GLColorBuffer, Vector3 tint); + GLColorCorrectionFilter(GLRenderer &); + /** + * @param fogLuminance The luminance of the fog color. Must be in the sRGB color space. + */ + GLColorBuffer Filter(GLColorBuffer, Vector3 tint, float fogLuminance); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLDepthOfFieldFilter.cpp b/Sources/Draw/GLDepthOfFieldFilter.cpp index 52445e293..54161cb75 100644 --- a/Sources/Draw/GLDepthOfFieldFilter.cpp +++ b/Sources/Draw/GLDepthOfFieldFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLDepthOfFieldFilter.h" #include "GLProfiler.h" #include "GLProgram.h" @@ -30,6 +28,8 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { @@ -37,25 +37,25 @@ namespace spades { return (int)settings.r_depthOfField >= 2; } - GLDepthOfFieldFilter::GLDepthOfFieldFilter(GLRenderer *renderer) - : renderer(renderer), settings(renderer->GetSettings()) { - gaussProgram = renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program"); + GLDepthOfFieldFilter::GLDepthOfFieldFilter(GLRenderer &renderer) + : renderer(renderer), settings(renderer.GetSettings()) { + gaussProgram = renderer.RegisterProgram("Shaders/PostFilters/Gauss1D.program"); if (HighQualityDoFEnabled()) - blurProgram = renderer->RegisterProgram("Shaders/PostFilters/DoFBlur2.program"); + blurProgram = renderer.RegisterProgram("Shaders/PostFilters/DoFBlur2.program"); else - blurProgram = renderer->RegisterProgram("Shaders/PostFilters/DoFBlur.program"); - cocGen = renderer->RegisterProgram("Shaders/PostFilters/DoFCoCGen.program"); - cocMix = renderer->RegisterProgram("Shaders/PostFilters/DoFCoCMix.program"); - gammaMix = renderer->RegisterProgram("Shaders/PostFilters/GammaMix.program"); - finalMix = renderer->RegisterProgram("Shaders/PostFilters/DoFMix.program"); - passthrough = renderer->RegisterProgram("Shaders/PostFilters/PassThrough.program"); + blurProgram = renderer.RegisterProgram("Shaders/PostFilters/DoFBlur.program"); + cocGen = renderer.RegisterProgram("Shaders/PostFilters/DoFCoCGen.program"); + cocMix = renderer.RegisterProgram("Shaders/PostFilters/DoFCoCMix.program"); + gammaMix = renderer.RegisterProgram("Shaders/PostFilters/GammaMix.program"); + finalMix = renderer.RegisterProgram("Shaders/PostFilters/DoFMix.program"); + passthrough = renderer.RegisterProgram("Shaders/PostFilters/PassThrough.program"); } GLColorBuffer GLDepthOfFieldFilter::BlurCoC(GLColorBuffer buffer, float spread) { SPADES_MARK_FUNCTION(); // do gaussian blur GLProgram *program = gaussProgram; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = buffer.GetWidth(); int h = buffer.GetHeight(); @@ -69,22 +69,22 @@ namespace spades { blur_unitShift(program); blur_textureUniform.SetValue(0); - dev->ActiveTexture(0); + dev.ActiveTexture(0); qr.SetCoordAttributeIndex(blur_positionAttribute()); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); // x-direction - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, 1); - dev->BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, 1); + dev.BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); blur_unitShift.SetValue(spread / (float)w, 0.f); qr.Draw(); buffer.Release(); // y-direction - GLColorBuffer buf3 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, 1); - dev->BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); + GLColorBuffer buf3 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, 1); + dev.BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); blur_unitShift.SetValue(0.f, spread / (float)h); qr.Draw(); buf2.Release(); @@ -96,15 +96,15 @@ namespace spades { float globalBlur, float nearBlur, float farBlur) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); - int w = dev->ScreenWidth(); - int h = dev->ScreenHeight(); + int w = dev.ScreenWidth(); + int h = dev.ScreenHeight(); int w2 = HighQualityDoFEnabled() ? w : (w + 3) / 4; int h2 = HighQualityDoFEnabled() ? h : (h + 3) / 4; - GLColorBuffer coc = renderer->GetFramebufferManager()->CreateBufferHandle(w2, h2, 1); + GLColorBuffer coc = renderer.GetFramebufferManager()->CreateBufferHandle(w2, h2, 1); { static GLProgramAttribute positionAttribute("positionAttribute"); @@ -133,7 +133,7 @@ namespace spades { depthTexture.SetValue(0); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); zNearFar.SetValue(def.zNear, def.zFar); pixelShift.SetValue(1.f / (float)w, 1.f / (float)h); @@ -151,12 +151,12 @@ namespace spades { farBlurUniform.SetValue(-farBlur); qr.SetCoordAttributeIndex(positionAttribute()); - dev->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, coc.GetFramebuffer()); - dev->Viewport(0, 0, w2, h2); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, coc.GetFramebuffer()); + dev.Viewport(0, 0, w2, h2); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); } if (HighQualityDoFEnabled()) { @@ -168,8 +168,7 @@ namespace spades { GLColorBuffer cocBlur = BlurCoC(coc, 1.f); // mix - - GLColorBuffer coc2 = renderer->GetFramebufferManager()->CreateBufferHandle(w2, h2, 1); + GLColorBuffer coc2 = renderer.GetFramebufferManager()->CreateBufferHandle(w2, h2, 1); { static GLProgramAttribute positionAttribute("positionAttribute"); @@ -183,18 +182,18 @@ namespace spades { cocMix->Use(); cocBlurTexture.SetValue(1); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, cocBlur.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, cocBlur.GetTexture()); cocTexture.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, coc.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, coc.GetTexture()); qr.SetCoordAttributeIndex(positionAttribute()); - dev->BindFramebuffer(IGLDevice::Framebuffer, coc2.GetFramebuffer()); - dev->Viewport(0, 0, w2, h2); + dev.BindFramebuffer(IGLDevice::Framebuffer, coc2.GetFramebuffer()); + dev.Viewport(0, 0, w2, h2); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); } coc2 = BlurCoC(coc2, .5f); @@ -208,7 +207,7 @@ namespace spades { SPADES_MARK_FUNCTION(); // do gaussian blur GLProgram *program = blurProgram; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = buffer.GetWidth(); int h = buffer.GetHeight(); @@ -226,11 +225,11 @@ namespace spades { blur_offset(program); blur_cocUniform.SetValue(1); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, coc.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, coc.GetTexture()); blur_textureUniform.SetValue(0); - dev->ActiveTexture(0); + dev.ActiveTexture(0); qr.SetCoordAttributeIndex(blur_positionAttribute()); @@ -239,9 +238,9 @@ namespace spades { float sX = 1.f / (float)w, sY = 1.f / (float)h; while (len > .5f) { GLColorBuffer buf2 = - renderer->GetFramebufferManager()->CreateBufferHandle(w2, h2, false); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); - dev->BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); + renderer.GetFramebufferManager()->CreateBufferHandle(w2, h2, false); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); blur_offset.SetValue(offset.x * sX, offset.y * sY); qr.Draw(); buffer = buf2; @@ -257,11 +256,13 @@ namespace spades { SPADES_MARK_FUNCTION(); // do gaussian blur GLProgram *program = gammaMix; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = buffer1.GetWidth(); int h = buffer1.GetHeight(); + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, false); + static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform1("texture1"); static GLProgramUniform blur_textureUniform2("texture2"); @@ -273,13 +274,13 @@ namespace spades { blur_textureUniform1(program); blur_textureUniform1.SetValue(1); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, buffer1.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, buffer1.GetTexture()); blur_textureUniform2(program); blur_textureUniform2.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, buffer2.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, buffer2.GetTexture()); blur_mix1(program); blur_mix2(program); @@ -288,11 +289,10 @@ namespace spades { blur_mix2.SetValue(.5f, .5f, .5f); qr.SetCoordAttributeIndex(blur_positionAttribute()); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); // x-direction - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, false); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); qr.Draw(); return buf2; } @@ -302,11 +302,13 @@ namespace spades { SPADES_MARK_FUNCTION(); // do gaussian blur GLProgram *program = finalMix; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = tex.GetWidth(); int h = tex.GetHeight(); + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, false); + static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform1("mainTexture"); static GLProgramUniform blur_textureUniform2("blurTexture1"); @@ -318,33 +320,32 @@ namespace spades { blur_textureUniform1(program); blur_textureUniform1.SetValue(3); - dev->ActiveTexture(3); - dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture()); + dev.ActiveTexture(3); + dev.BindTexture(IGLDevice::Texture2D, tex.GetTexture()); blur_textureUniform2(program); blur_textureUniform2.SetValue(2); - dev->ActiveTexture(2); - dev->BindTexture(IGLDevice::Texture2D, blur1.GetTexture()); + dev.ActiveTexture(2); + dev.BindTexture(IGLDevice::Texture2D, blur1.GetTexture()); blur_textureUniform3(program); blur_textureUniform3.SetValue(1); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, blur2.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, blur2.GetTexture()); blur_textureUniform4(program); blur_textureUniform4.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, coc.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, coc.GetTexture()); blur_blurredOnlyUniform(program); blur_blurredOnlyUniform.SetValue(HighQualityDoFEnabled() ? 1 : 0); qr.SetCoordAttributeIndex(blur_positionAttribute()); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); // x-direction - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, false); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); qr.Draw(); return buf2; } @@ -353,11 +354,14 @@ namespace spades { SPADES_MARK_FUNCTION(); // do gaussian blur GLProgram *program = passthrough; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = tex.GetWidth(); int h = tex.GetHeight(); + GLColorBuffer buf2 = + renderer.GetFramebufferManager()->CreateBufferHandle(w / 2, h / 2, false); + static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform("mainTexture"); static GLProgramUniform blur_colorUniform("colorUniform"); @@ -367,8 +371,8 @@ namespace spades { blur_textureUniform(program); blur_textureUniform.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, tex.GetTexture()); blur_colorUniform(program); blur_colorUniform.SetValue(1.f, 1.f, 1.f, 1.f); @@ -377,12 +381,10 @@ namespace spades { blur_texCoordRangeUniform.SetValue(0.f, 0.f, 1.f, 1.f); qr.SetCoordAttributeIndex(blur_positionAttribute()); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); - GLColorBuffer buf2 = - renderer->GetFramebufferManager()->CreateBufferHandle(w / 2, h / 2, false); - dev->Viewport(0, 0, w / 2, h / 2); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.Viewport(0, 0, w / 2, h / 2); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); qr.Draw(); return buf2; } @@ -392,19 +394,19 @@ namespace spades { float nearBlur, float farBlur) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); - int w = dev->ScreenWidth(); - int h = dev->ScreenHeight(); + int w = input.GetWidth(); + int h = input.GetHeight(); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); GLColorBuffer coc; globalBlur = std::min(globalBlur * 3.f, 1.f); { - GLProfiler::Context p(renderer->GetGLProfiler(), "CoC Computation"); + GLProfiler::Context p(renderer.GetGLProfiler(), "CoC Computation"); coc = GenerateCoC(blurDepthRange, vignetteBlur, globalBlur, nearBlur, farBlur); } @@ -429,38 +431,38 @@ namespace spades { maxCoc /= (float)divide; } - dev->Viewport(0, 0, w / divide, h / divide); + dev.Viewport(0, 0, w / divide, h / divide); GLColorBuffer buf1, buf2; { - GLProfiler::Context p(renderer->GetGLProfiler(), "Blur 1"); + GLProfiler::Context p(renderer.GetGLProfiler(), "Blur 1"); buf1 = Blur(lowbuf, coc, MakeVector2(0.f, -1.f) * maxCoc); } { - GLProfiler::Context p(renderer->GetGLProfiler(), "Blur 2"); + GLProfiler::Context p(renderer.GetGLProfiler(), "Blur 2"); buf2 = Blur(lowbuf, coc, MakeVector2(-sin60, cos60) * maxCoc); lowbuf.Release(); } { - GLProfiler::Context p(renderer->GetGLProfiler(), "Mix 1"); + GLProfiler::Context p(renderer.GetGLProfiler(), "Mix 1"); buf2 = AddMix(buf1, buf2); } // return buf2; { - GLProfiler::Context p(renderer->GetGLProfiler(), "Blur 3"); + GLProfiler::Context p(renderer.GetGLProfiler(), "Blur 3"); buf1 = Blur(buf1, coc, MakeVector2(-sin60, cos60) * maxCoc); } { - GLProfiler::Context p(renderer->GetGLProfiler(), "Blur 4"); + GLProfiler::Context p(renderer.GetGLProfiler(), "Blur 4"); buf2 = Blur(buf2, coc, MakeVector2(sin60, cos60) * maxCoc); } - dev->Viewport(0, 0, w, h); + dev.Viewport(0, 0, w, h); { - GLProfiler::Context p(renderer->GetGLProfiler(), "Mix 2"); + GLProfiler::Context p(renderer.GetGLProfiler(), "Mix 2"); GLColorBuffer output = FinalMix(input, buf1, buf2, coc); return output; } } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLDepthOfFieldFilter.h b/Sources/Draw/GLDepthOfFieldFilter.h index 257fc35cf..79a153ca6 100644 --- a/Sources/Draw/GLDepthOfFieldFilter.h +++ b/Sources/Draw/GLDepthOfFieldFilter.h @@ -28,7 +28,7 @@ namespace spades { class GLProgram; class GLSettings; class GLDepthOfFieldFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLSettings &settings; GLProgram *cocGen; // program to generate CoC radius GLProgram *cocMix; // program to mix CoC radius @@ -49,9 +49,9 @@ namespace spades { bool HighQualityDoFEnabled(); public: - GLDepthOfFieldFilter(GLRenderer *); + GLDepthOfFieldFilter(GLRenderer &); GLColorBuffer Filter(GLColorBuffer, float blurDepthRange, float vignetteBlur, float globalBlur, float nearBlur, float farBlur); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLDynamicLight.cpp b/Sources/Draw/GLDynamicLight.cpp index 74ad82e0c..590a3705e 100644 --- a/Sources/Draw/GLDynamicLight.cpp +++ b/Sources/Draw/GLDynamicLight.cpp @@ -61,9 +61,15 @@ namespace spades { clipPlanes[i] = Plane3::PlaneWithPointOnPlane(param.origin, planeN[i]); } } + + if (param.type == client::DynamicLightTypeLinear) { + poweredLength = (param.point2 - param.origin).GetPoweredLength(); + } } bool GLDynamicLight::Cull(const spades::AABB3 &box) const { + const client::DynamicLightParam ¶m = GetParam(); + if (param.type == client::DynamicLightTypeSpotlight) { for (const Plane3 &plane : clipPlanes) { if (!PlaneCullTest(plane, box)) { @@ -72,8 +78,19 @@ namespace spades { } } - const client::DynamicLightParam ¶m = GetParam(); - return box.Inflate(param.radius) && param.origin; + AABB3 inflatedBox = box.Inflate(param.radius); + + if (param.type == client::DynamicLightTypeLinear) { + Vector3 intersection; + // TODO: using `OBB3` here is overkill, but `AABB3` doesn't have `RayCast` + if (!OBB3(inflatedBox) + .RayCast(param.origin, param.point2 - param.origin, &intersection)) { + return false; + } + return (intersection - param.origin).GetPoweredLength() <= poweredLength; + } + + return inflatedBox && param.origin; } bool GLDynamicLight::SphereCull(const spades::Vector3 ¢er, float radius) const { @@ -85,10 +102,13 @@ namespace spades { return false; } } + } else if (param.type == client::DynamicLightTypeLinear) { + return Line3::MakeLineSegment(param.origin, param.point2).GetDistanceTo(center) < + radius + param.radius; } float maxDistance = radius + param.radius; return (center - param.origin).GetPoweredLength() < maxDistance * maxDistance; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLDynamicLight.h b/Sources/Draw/GLDynamicLight.h index 40ccb16c7..e63183c49 100644 --- a/Sources/Draw/GLDynamicLight.h +++ b/Sources/Draw/GLDynamicLight.h @@ -33,6 +33,9 @@ namespace spades { /** World-space clip planes (spotlight only) */ std::array clipPlanes; + /** `(point2 - origin).GetPoweredLength()` (linear light only) */ + float poweredLength; + public: GLDynamicLight(const client::DynamicLightParam ¶m); const client::DynamicLightParam &GetParam() const { return param; } @@ -43,5 +46,5 @@ namespace spades { bool SphereCull(const Vector3 ¢er, float radius) const; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLDynamicLightShader.cpp b/Sources/Draw/GLDynamicLightShader.cpp index 7c014d288..9fedfbc7a 100644 --- a/Sources/Draw/GLDynamicLightShader.cpp +++ b/Sources/Draw/GLDynamicLightShader.cpp @@ -19,10 +19,10 @@ */ #include "GLDynamicLightShader.h" -#include #include "GLImage.h" #include "GLProgramManager.h" #include "GLRenderer.h" +#include namespace spades { namespace draw { @@ -32,12 +32,17 @@ namespace spades { dynamicLightRadius("dynamicLightRadius"), dynamicLightRadiusInversed("dynamicLightRadiusInversed"), dynamicLightSpotMatrix("dynamicLightSpotMatrix"), - dynamicLightProjectionTexture("dynamicLightProjectionTexture") + dynamicLightProjectionTexture("dynamicLightProjectionTexture"), + dynamicLightIsLinear("dynamicLightIsLinear"), + dynamicLightLinearDirection("dynamicLightLinearDirection"), + dynamicLightLinearLength("dynamicLightLinearLength") { lastRenderer = NULL; } + GLDynamicLightShader::~GLDynamicLightShader() {} + std::vector GLDynamicLightShader::RegisterShader(spades::draw::GLProgramManager *r) { std::vector shaders; @@ -53,20 +58,24 @@ namespace spades { int GLDynamicLightShader::operator()(GLRenderer *renderer, spades::draw::GLProgram *program, const GLDynamicLight &light, int texStage) { + // TODO: Raw pointers are not unique! if (lastRenderer != renderer) { - whiteImage = static_cast(renderer->RegisterImage("Gfx/White.tga")); + whiteImage = renderer->RegisterImage("Gfx/White.tga").Cast(); lastRenderer = renderer; } const client::DynamicLightParam ¶m = light.GetParam(); - IGLDevice *device = renderer->GetGLDevice(); + IGLDevice &device = renderer->GetGLDevice(); dynamicLightOrigin(program); dynamicLightColor(program); dynamicLightRadius(program); dynamicLightRadiusInversed(program); dynamicLightSpotMatrix(program); dynamicLightProjectionTexture(program); + dynamicLightIsLinear(program); + dynamicLightLinearDirection(program); + dynamicLightLinearLength(program); dynamicLightOrigin.SetValue(param.origin.x, param.origin.y, param.origin.z); dynamicLightColor.SetValue(param.color.x, param.color.y, param.color.z); @@ -74,7 +83,7 @@ namespace spades { dynamicLightRadiusInversed.SetValue(1.f / param.radius); if (param.type == client::DynamicLightTypeSpotlight) { - device->ActiveTexture(texStage); + device.ActiveTexture(texStage); static_cast(param.image)->Bind(IGLDevice::Texture2D); dynamicLightProjectionTexture.SetValue(texStage); texStage++; @@ -82,13 +91,15 @@ namespace spades { dynamicLightSpotMatrix.SetValue(light.GetProjectionMatrix()); // bad hack to make texture clamped to edge - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - } else { - device->ActiveTexture(texStage); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dynamicLightIsLinear.SetValue(0); + } else if (param.type == client::DynamicLightTypePoint || + param.type == client::DynamicLightTypeLinear) { + device.ActiveTexture(texStage); whiteImage->Bind(IGLDevice::Texture2D); dynamicLightProjectionTexture.SetValue(texStage); texStage++; @@ -97,11 +108,29 @@ namespace spades { // UV is in a valid range so the fragments are not discarded. dynamicLightSpotMatrix.SetValue(Matrix4::Translate(0.5, 0.5, 0.0) * Matrix4::Scale(0.0)); + + if (param.type == client::DynamicLightTypeLinear) { + // Convert two endpoints to one endpoint + direction + length. + // `Vector3::Normalize` is no-op when the length is zero, + // therefore the zero-length case is handled. + Vector3 direction = param.point2 - param.origin; + float length = direction.GetLength(); + direction = direction.Normalize(); + + dynamicLightLinearDirection.SetValue(direction.x, direction.y, direction.z); + dynamicLightLinearLength.SetValue(length); + + dynamicLightIsLinear.SetValue(1); + } else { + dynamicLightIsLinear.SetValue(0); + } + } else { + SPUnreachable(); } - device->ActiveTexture(texStage); + device.ActiveTexture(texStage); return texStage; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLDynamicLightShader.h b/Sources/Draw/GLDynamicLightShader.h index 61c9c3638..9c80216f2 100644 --- a/Sources/Draw/GLDynamicLightShader.h +++ b/Sources/Draw/GLDynamicLightShader.h @@ -22,10 +22,10 @@ #include -#include -#include #include "GLDynamicLight.h" #include "GLProgramUniform.h" +#include +#include namespace spades { namespace draw { @@ -34,7 +34,7 @@ namespace spades { class GLProgramManager; class GLDynamicLightShader { GLRenderer *lastRenderer; - GLImage *whiteImage; + Handle whiteImage; GLProgramUniform dynamicLightOrigin; GLProgramUniform dynamicLightColor; @@ -42,10 +42,13 @@ namespace spades { GLProgramUniform dynamicLightRadiusInversed; GLProgramUniform dynamicLightSpotMatrix; GLProgramUniform dynamicLightProjectionTexture; + GLProgramUniform dynamicLightIsLinear; + GLProgramUniform dynamicLightLinearDirection; + GLProgramUniform dynamicLightLinearLength; public: GLDynamicLightShader(); - ~GLDynamicLightShader() {} + ~GLDynamicLightShader(); static std::vector RegisterShader(GLProgramManager *); @@ -57,5 +60,5 @@ namespace spades { int operator()(GLRenderer *renderer, GLProgram *, const GLDynamicLight &light, int firstTexStage); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFXAAFilter.cpp b/Sources/Draw/GLFXAAFilter.cpp index 036ddf09c..cd2fe5622 100644 --- a/Sources/Draw/GLFXAAFilter.cpp +++ b/Sources/Draw/GLFXAAFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLFXAAFilter.h" #include "GLProgram.h" #include "GLProgramAttribute.h" @@ -29,23 +27,27 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLFXAAFilter::GLFXAAFilter(GLRenderer *renderer) : renderer(renderer) { - lens = renderer->RegisterProgram("Shaders/PostFilters/FXAA.program"); + GLFXAAFilter::GLFXAAFilter(GLRenderer &renderer) : renderer(renderer) { + lens = renderer.RegisterProgram("Shaders/PostFilters/FXAA.program"); } GLColorBuffer GLFXAAFilter::Filter(GLColorBuffer input) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); + GLColorBuffer output = input.GetManager()->CreateBufferHandle(); + static GLProgramAttribute lensPosition("positionAttribute"); static GLProgramUniform lensTexture("mainTexture"); static GLProgramUniform inverseVP("inverseVP"); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); lensPosition(lens); lensTexture(lens); @@ -53,20 +55,19 @@ namespace spades { lens->Use(); - inverseVP.SetValue(1.f / dev->ScreenWidth(), 1.f / dev->ScreenHeight()); + inverseVP.SetValue(1.f / input.GetWidth(), 1.f / input.GetHeight()); lensTexture.SetValue(0); // composite to the final image - GLColorBuffer output = input.GetManager()->CreateBufferHandle(); qr.SetCoordAttributeIndex(lensPosition()); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); return output; } - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFXAAFilter.h b/Sources/Draw/GLFXAAFilter.h index 8b5a8c337..5be267f8e 100644 --- a/Sources/Draw/GLFXAAFilter.h +++ b/Sources/Draw/GLFXAAFilter.h @@ -27,12 +27,12 @@ namespace spades { class GLRenderer; class GLProgram; class GLFXAAFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLProgram *lens; public: - GLFXAAFilter(GLRenderer *); + GLFXAAFilter(GLRenderer &); GLColorBuffer Filter(GLColorBuffer); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFlatMapRenderer.cpp b/Sources/Draw/GLFlatMapRenderer.cpp index 88761d9b8..1cabc6651 100644 --- a/Sources/Draw/GLFlatMapRenderer.cpp +++ b/Sources/Draw/GLFlatMapRenderer.cpp @@ -19,43 +19,37 @@ */ #include "GLFlatMapRenderer.h" +#include "GLImage.h" +#include "GLRenderer.h" #include #include #include -#include "GLImage.h" -#include "GLRenderer.h" namespace spades { namespace draw { - GLFlatMapRenderer::GLFlatMapRenderer(GLRenderer *r, client::GameMap *m) + GLFlatMapRenderer::GLFlatMapRenderer(GLRenderer &r, client::GameMap &m) : renderer(r), map(m) { SPADES_MARK_FUNCTION(); - chunkRows = m->Height() >> ChunkBits; - chunkCols = m->Width() >> ChunkBits; + chunkRows = m.Height() >> ChunkBits; + chunkCols = m.Width() >> ChunkBits; for (int i = 0; i < chunkRows * chunkCols; i++) chunkInvalid.push_back(false); - Handle bmp(GenerateBitmap(0, 0, m->Width(), m->Height()), false); - try { - image = static_cast(renderer->CreateImage(bmp)); - } catch (...) { - throw; - } + Handle bmp(GenerateBitmap(0, 0, m.Width(), m.Height()), false); + image = renderer.CreateImage(*bmp).Cast(); image->Bind(IGLDevice::Texture2D); - IGLDevice *dev = renderer->GetGLDevice(); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); + IGLDevice &dev = renderer.GetGLDevice(); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); } - GLFlatMapRenderer::~GLFlatMapRenderer() { image->Release(); } + GLFlatMapRenderer::~GLFlatMapRenderer() {} Bitmap *GLFlatMapRenderer::GenerateBitmap(int mx, int my, int w, int h) { SPADES_MARK_FUNCTION(); - Handle bmp(new Bitmap(w, h), false); + auto bmp = Handle::New(w, h); try { uint32_t *pixels = bmp->GetPixels(); @@ -76,19 +70,19 @@ namespace spades { } catch (...) { throw; } - return bmp.Unmanage(); + return std::move(bmp).Unmanage(); } - void GLFlatMapRenderer::GameMapChanged(int x, int y, int z, client::GameMap *map) { - if (map != this->map) + void GLFlatMapRenderer::GameMapChanged(int x, int y, int z, client::GameMap &map) { + if (this->map.GetPointerOrNull() != &map) return; SPAssert(x >= 0); - SPAssert(x < map->Width()); + SPAssert(x < map.Width()); SPAssert(y >= 0); - SPAssert(y < map->Height()); + SPAssert(y < map.Height()); SPAssert(z >= 0); - SPAssert(z < map->Depth()); + SPAssert(z < map.Depth()); int chunkX = x >> ChunkBits; int chunkY = y >> ChunkBits; @@ -112,14 +106,14 @@ namespace spades { GenerateBitmap(chunkX * ChunkSize, chunkY * ChunkSize, ChunkSize, ChunkSize), false); try { - image->SubImage(bmp, chunkX * ChunkSize, chunkY * ChunkSize); + image->SubImage(bmp.GetPointerOrNull(), chunkX * ChunkSize, chunkY * ChunkSize); } catch (...) { throw; } chunkInvalid[i] = false; } - renderer->DrawImage(image, dest, src); + renderer.DrawImage(*image, dest, src); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFlatMapRenderer.h b/Sources/Draw/GLFlatMapRenderer.h index ecf8efe79..81a490ed5 100644 --- a/Sources/Draw/GLFlatMapRenderer.h +++ b/Sources/Draw/GLFlatMapRenderer.h @@ -23,6 +23,7 @@ #include #include +#include namespace spades { class Bitmap; @@ -35,22 +36,22 @@ namespace spades { class GLFlatMapRenderer { enum { ChunkSize = 16, ChunkBits = 4 }; - GLRenderer *renderer; - client::GameMap *map; + GLRenderer &renderer; + Handle map; std::vector chunkInvalid; - GLImage *image; + Handle image; int chunkCols, chunkRows; Bitmap *GenerateBitmap(int x, int y, int w, int h); public: - GLFlatMapRenderer(GLRenderer *renderer, client::GameMap *map); + GLFlatMapRenderer(GLRenderer &renderer, client::GameMap &map); ~GLFlatMapRenderer(); void Draw(const AABB2 &dest, const AABB2 &src); - void GameMapChanged(int x, int y, int z, client::GameMap *); + void GameMapChanged(int x, int y, int z, client::GameMap &); }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFogFilter.cpp b/Sources/Draw/GLFogFilter.cpp index 8258c21cb..1b7875fa9 100644 --- a/Sources/Draw/GLFogFilter.cpp +++ b/Sources/Draw/GLFogFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLFogFilter.h" #include "GLMapShadowRenderer.h" #include "GLProgram.h" @@ -30,16 +28,18 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLFogFilter::GLFogFilter(GLRenderer *renderer) : renderer(renderer) { - lens = renderer->RegisterProgram("Shaders/PostFilters/Fog.program"); + GLFogFilter::GLFogFilter(GLRenderer &renderer) : renderer(renderer) { + lens = renderer.RegisterProgram("Shaders/PostFilters/Fog.program"); } GLColorBuffer GLFogFilter::Filter(GLColorBuffer input) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); static GLProgramAttribute lensPosition("positionAttribute"); @@ -57,7 +57,7 @@ namespace spades { static GLProgramUniform fogColor("fogColor"); static GLProgramUniform fogDistance("fogDistance"); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); lensPosition(lens); lensShadowMapTexture(lens); @@ -75,9 +75,9 @@ namespace spades { lens->Use(); - client::SceneDefinition def = renderer->GetSceneDef(); + client::SceneDefinition def = renderer.GetSceneDef(); lensFov.SetValue(tanf(def.fovX * .5f), tanf(def.fovY * .5f)); - if (renderer->IsRenderingMirror()) { + if (renderer.IsRenderingMirror()) { def.viewOrigin.z = 63.f * 2.f - def.viewOrigin.z; def.viewAxis[0].z = -def.viewAxis[0].z; def.viewAxis[1].z = -def.viewAxis[1].z; @@ -89,7 +89,7 @@ namespace spades { lensViewAxisFront.SetValue(def.viewAxis[2].x, def.viewAxis[2].y, def.viewAxis[2].z); zNearFar.SetValue(def.zNear, def.zFar); - Vector3 fogCol = renderer->GetFogColor(); + Vector3 fogCol = renderer.GetFogColor(); fogCol *= fogCol; // linearize fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); @@ -103,24 +103,24 @@ namespace spades { // composite to the final image GLColorBuffer output = input.GetManager()->CreateBufferHandle(); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); qr.SetCoordAttributeIndex(lensPosition()); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, input.GetManager()->GetDepthTexture()); - dev->ActiveTexture(2); - dev->BindTexture(IGLDevice::Texture2D, renderer->GetMapShadowRenderer()->GetTexture()); - dev->ActiveTexture(3); - dev->BindTexture(IGLDevice::Texture2D, - renderer->GetMapShadowRenderer()->GetCoarseTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, input.GetManager()->GetDepthTexture()); + dev.ActiveTexture(2); + dev.BindTexture(IGLDevice::Texture2D, renderer.GetMapShadowRenderer()->GetTexture()); + dev.ActiveTexture(3); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetMapShadowRenderer()->GetCoarseTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); qr.Draw(); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, 0); return output; } - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFogFilter.h b/Sources/Draw/GLFogFilter.h index 437f48d56..5ef78b2c6 100644 --- a/Sources/Draw/GLFogFilter.h +++ b/Sources/Draw/GLFogFilter.h @@ -27,12 +27,12 @@ namespace spades { class GLRenderer; class GLProgram; class GLFogFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLProgram *lens; public: - GLFogFilter(GLRenderer *); + GLFogFilter(GLRenderer &); GLColorBuffer Filter(GLColorBuffer); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFogFilter2.cpp b/Sources/Draw/GLFogFilter2.cpp new file mode 100644 index 000000000..d61ba8373 --- /dev/null +++ b/Sources/Draw/GLFogFilter2.cpp @@ -0,0 +1,280 @@ +/* + Copyright (c) 2021 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +#include +#include + +#include "GLAmbientShadowRenderer.h" +#include "GLFogFilter2.h" +#include "GLImage.h" +#include "GLMapShadowRenderer.h" +#include "GLProgram.h" +#include "GLProgramAttribute.h" +#include "GLProgramUniform.h" +#include "GLQuadRenderer.h" +#include "GLRadiosityRenderer.h" +#include "GLRenderer.h" +#include "IGLDevice.h" +#include +#include + +namespace { + constexpr int NoiseTexSize = 128; +} + +namespace spades { + namespace draw { + GLFogFilter2::GLFogFilter2(GLRenderer &renderer) : renderer(renderer) { + lens = renderer.RegisterProgram("Shaders/PostFilters/Fog2.program"); + ditherPattern = renderer.RegisterImage("Gfx/DitherPattern4x4.png").Cast(); + + IGLDevice &dev = renderer.GetGLDevice(); + noiseTex = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, noiseTex); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, NoiseTexSize, NoiseTexSize, 0, + IGLDevice::BGRA, IGLDevice::UnsignedByte, NULL); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); + } + + GLFogFilter2::~GLFogFilter2() { renderer.GetGLDevice().DeleteTexture(noiseTex); } + + GLColorBuffer GLFogFilter2::Filter(GLColorBuffer input) { + SPADES_MARK_FUNCTION(); + + IGLDevice &dev = renderer.GetGLDevice(); + GLAmbientShadowRenderer *ambientShadowRenderer = renderer.GetAmbientShadowRenderer(); + GLRadiosityRenderer *radiosityRenderer = renderer.GetRadiosityRenderer(); + GLQuadRenderer qr(dev); + + SPAssert(ambientShadowRenderer); + SPAssert(radiosityRenderer); + + // Update `noiseTex` if the time has moved forward since the last time + if (renderer.GetFrameNumber() != lastNoiseTexFrameNumber) { + std::array noise; + + for (uint32_t &x : noise) { + x = static_cast(SampleRandom()); + } + + dev.BindTexture(IGLDevice::Texture2D, noiseTex); + dev.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, NoiseTexSize, NoiseTexSize, + IGLDevice::BGRA, IGLDevice::UnsignedByte, noise.data()); + + lastNoiseTexFrameNumber = renderer.GetFrameNumber(); + } + + // Calculate the current view-projection matrix. Exclude `def.viewOrigin` from this + // matrix. + // TODO: This was copied from `GLTemporalAAFilter.cpp`. + // De-duplicate! + client::SceneDefinition def = renderer.GetSceneDef(); + if (renderer.IsRenderingMirror()) { + def.viewOrigin.z = 63.f * 2.f - def.viewOrigin.z; + def.viewAxis[0].z = -def.viewAxis[0].z; + def.viewAxis[1].z = -def.viewAxis[1].z; + def.viewAxis[2].z = -def.viewAxis[2].z; + } + + Matrix4 viewMatrix = Matrix4::Identity(); + Vector3 axes[] = {def.viewAxis[0], def.viewAxis[1], def.viewAxis[2]}; + viewMatrix.m[0] = axes[0].x; + viewMatrix.m[1] = axes[1].x; + viewMatrix.m[2] = -axes[2].x; + viewMatrix.m[4] = axes[0].y; + viewMatrix.m[5] = axes[1].y; + viewMatrix.m[6] = -axes[2].y; + viewMatrix.m[8] = axes[0].z; + viewMatrix.m[9] = axes[1].z; + viewMatrix.m[10] = -axes[2].z; + + Matrix4 projectionMatrix; + { + // From `GLRenderer::BuildProjectionMatrix` + float near = def.zNear; + float far = def.zFar; + float t = near * std::tan(def.fovY * .5f); + float r = near * std::tan(def.fovX * .5f); + float a = r * 2.f, b = t * 2.f, c = far - near; + Matrix4 &mat = projectionMatrix; + mat.m[0] = near * 2.f / a; + mat.m[1] = 0.f; + mat.m[2] = 0.f; + mat.m[3] = 0.f; + mat.m[4] = 0.f; + mat.m[5] = near * 2.f / b; + mat.m[6] = 0.f; + mat.m[7] = 0.f; + mat.m[8] = 0.f; + mat.m[9] = 0.f; + mat.m[10] = -(far + near) / c; + mat.m[11] = -1.f; + mat.m[12] = 0.f; + mat.m[13] = 0.f; + mat.m[14] = -(far * near * 2.f) / c; + mat.m[15] = 0.f; + } + + Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix; + + // In `y = viewProjectionMatrix * x`, the coordinate space `y` belongs to must + // cover the clip region by range `[0, 1]` (like texture coordinates) + // instead of `[-1, 1]` (like OpenGL clip coordinates) + viewProjectionMatrix = Matrix4::Translate(1.0f, 1.0f, 1.0f) * viewProjectionMatrix; + viewProjectionMatrix = Matrix4::Scale(0.5f, 0.5f, 0.5f) * viewProjectionMatrix; + + // TODO: These were clearly copied from `GLLensFilter.cpp`. Remove the + // `lens` prefix! + static GLProgramAttribute lensPosition("positionAttribute"); + static GLProgramUniform lensShadowMapTexture("shadowMapTexture"); + static GLProgramUniform ambientShadowTexture("ambientShadowTexture"); + static GLProgramUniform radiosityTexture("radiosityTexture"); + static GLProgramUniform lensColorTexture("colorTexture"); + static GLProgramUniform lensDepthTexture("depthTexture"); + static GLProgramUniform lensViewOrigin("viewOrigin"); + static GLProgramUniform viewProjectionMatrixInv("viewProjectionMatrixInv"); + static GLProgramUniform sunlightScale("sunlightScale"); + static GLProgramUniform ambientScale("ambientScale"); + static GLProgramUniform radiosityScale("radiosityScale"); + static GLProgramUniform fogDistance("fogDistance"); + static GLProgramUniform ditherTexture("ditherTexture"); + static GLProgramUniform ditherOffset("ditherOffset"); + static GLProgramUniform noiseTexture("noiseTexture"); + + dev.Enable(IGLDevice::Blend, false); + + lensPosition(lens); + lensShadowMapTexture(lens); + lensColorTexture(lens); + lensDepthTexture(lens); + lensViewOrigin(lens); + sunlightScale(lens); + ambientScale(lens); + radiosityScale(lens); + fogDistance(lens); + ditherTexture(lens); + ditherOffset(lens); + viewProjectionMatrixInv(lens); + ambientShadowTexture(lens); + radiosityTexture(lens); + noiseTexture(lens); + + lens->Use(); + + lensViewOrigin.SetValue(def.viewOrigin.x, def.viewOrigin.y, def.viewOrigin.z); + viewProjectionMatrixInv.SetValue(viewProjectionMatrix.Inversed()); + + Vector3 fogCol = renderer.GetFogColor(); + fogCol *= fogCol; // linearize + + float sunlightBrightness = 0.6f; // Sun -> Fog -> Eye + float ambientBrightness = 1.0f; // Sun -> Fog -> Fog -> Eye + float radiosityBrightness = 1.0f; + float radiosityOffset = 0.2f; + // Let's say the fog modulates the incoming light with some factor + // we call `fogTransmission`. When there are no occluding objects, + // we see this color: + // + // fogTransmission * sunlightBrightness + + // ambientBrightness * fogTransmission * fogColor + // + // This expresion's value must be equal to a given `fogColor`: + // + // fogTransmission * sunlightBrightness + + // ambientBrightness * fogTransmission * fogColor = fogColor + // + // Solving this for `fogTransmission`: + // + // fogTransmission = fogColor / + // (sunlightBrightness + ambientBrightness * fogColor) + // + // We add some value (`radiosityOffset`) to `radiosityScale` for + // artistic reasons. We want the fog to reflect some light. + auto fogTransmission1 = [=](float fogColor) { + return fogColor / (sunlightBrightness + ambientBrightness * fogColor); + }; + Vector3 fogTransmission{ + fogTransmission1(fogCol.x), + fogTransmission1(fogCol.y), + fogTransmission1(fogCol.z), + }; + sunlightScale.SetValue(fogTransmission.x * sunlightBrightness, + fogTransmission.y * sunlightBrightness, + fogTransmission.z * sunlightBrightness); + ambientScale.SetValue(fogTransmission.x * fogCol.x * ambientBrightness, + fogTransmission.y * fogCol.y * ambientBrightness, + fogTransmission.z * fogCol.z * ambientBrightness); + radiosityScale.SetValue(fogTransmission.x * radiosityBrightness + radiosityOffset, + fogTransmission.y * radiosityBrightness + radiosityOffset, + fogTransmission.z * radiosityBrightness + radiosityOffset); + + fogDistance.SetValue(128.f); + + lensColorTexture.SetValue(0); + lensDepthTexture.SetValue(1); + lensShadowMapTexture.SetValue(2); + ditherTexture.SetValue(3); + ambientShadowTexture.SetValue(4); + radiosityTexture.SetValue(5); + noiseTexture.SetValue(6); + + std::uint32_t frame = renderer.GetFrameNumber() % 4; + ditherOffset.SetValue((float)(frame & 1) * 0.5f, (float)((frame >> 1) & 1) * 0.5f); + + // composite to the final image + GLColorBuffer output = input.GetManager()->CreateBufferHandle(); + + dev.Enable(IGLDevice::Blend, false); + qr.SetCoordAttributeIndex(lensPosition()); + + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, input.GetManager()->GetDepthTexture()); + + dev.ActiveTexture(2); + dev.BindTexture(IGLDevice::Texture2D, renderer.GetMapShadowRenderer()->GetTexture()); + + dev.ActiveTexture(3); + ditherPattern->Bind(IGLDevice::Texture2D); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + + dev.ActiveTexture(4); + dev.BindTexture(IGLDevice::Texture3D, ambientShadowRenderer->GetTexture()); + dev.ActiveTexture(5); + dev.BindTexture(IGLDevice::Texture3D, radiosityRenderer->GetTextureFlat()); + dev.ActiveTexture(6); + dev.BindTexture(IGLDevice::Texture2D, noiseTex); + + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); + qr.Draw(); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, 0); + + return output; + } + } // namespace draw +} // namespace spades \ No newline at end of file diff --git a/Sources/Draw/GLFogFilter2.h b/Sources/Draw/GLFogFilter2.h new file mode 100644 index 000000000..cfae79a7a --- /dev/null +++ b/Sources/Draw/GLFogFilter2.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2021 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +#pragma once + +#include + +#include "GLFramebufferManager.h" + +namespace spades { + namespace draw { + class GLRenderer; + class GLProgram; + class GLImage; + class GLFogFilter2 { + GLRenderer &renderer; + GLProgram *lens; + Handle ditherPattern; + IGLDevice::UInteger noiseTex; + /** + * The recorded value of `GLRenderer::GetFrameNumber()` of when `noiseTex` was updated + * last time. + */ + std::uint32_t lastNoiseTexFrameNumber = 0xffffffff; + + public: + GLFogFilter2(GLRenderer &); + ~GLFogFilter2(); + GLColorBuffer Filter(GLColorBuffer); + }; + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFramebufferManager.cpp b/Sources/Draw/GLFramebufferManager.cpp index 5952fbfbd..a1f7c2612 100644 --- a/Sources/Draw/GLFramebufferManager.cpp +++ b/Sources/Draw/GLFramebufferManager.cpp @@ -19,23 +19,18 @@ */ #include "GLFramebufferManager.h" -#include -#include -#include #include "GLSettings.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { static void RaiseFBStatusError(IGLDevice::Enum status) { std::string type; switch (status) { - case IGLDevice::FramebufferComplete: - type = "GL_FRAMEBUFFER_COMPLETE"; - break; - case IGLDevice::FramebufferUndefined: - type = "GL_FRAMEBUFFER_UNDEFINED"; - break; + case IGLDevice::FramebufferComplete: type = "GL_FRAMEBUFFER_COMPLETE"; break; + case IGLDevice::FramebufferUndefined: type = "GL_FRAMEBUFFER_UNDEFINED"; break; case IGLDevice::FramebufferIncompleteAttachment: type = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break; @@ -61,8 +56,13 @@ namespace spades { SPRaise("OpenGL Framebuffer completeness check failed: %s", type.c_str()); } - GLFramebufferManager::GLFramebufferManager(IGLDevice *dev, GLSettings &settings) - : device(dev), settings(settings), doingPostProcessing(false) { + GLFramebufferManager::GLFramebufferManager(IGLDevice &dev, GLSettings &settings, + int renderWidth, int renderHeight) + : device(dev), + settings(settings), + doingPostProcessing(false), + renderWidth(renderWidth), + renderHeight(renderHeight) { SPADES_MARK_FUNCTION(); SPLog("Initializing framebuffer manager"); @@ -83,35 +83,32 @@ namespace spades { // multisample renderbuffer for scene // rendering. - multisampledFramebuffer = dev->GenFramebuffer(); - dev->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + multisampledFramebuffer = dev.GenFramebuffer(); + dev.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); - multisampledDepthRenderbuffer = dev->GenRenderbuffer(); - dev->BindRenderbuffer(IGLDevice::Renderbuffer, multisampledDepthRenderbuffer); - dev->RenderbufferStorage(IGLDevice::Renderbuffer, (int)settings.r_multisamples, - IGLDevice::DepthComponent24, dev->ScreenWidth(), - dev->ScreenHeight()); + multisampledDepthRenderbuffer = dev.GenRenderbuffer(); + dev.BindRenderbuffer(IGLDevice::Renderbuffer, multisampledDepthRenderbuffer); + dev.RenderbufferStorage(IGLDevice::Renderbuffer, (int)settings.r_multisamples, + IGLDevice::DepthComponent24, renderWidth, renderHeight); SPLog("MSAA Depth Buffer Allocated"); - dev->FramebufferRenderbuffer(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, - IGLDevice::Renderbuffer, - multisampledDepthRenderbuffer); + dev.FramebufferRenderbuffer(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, + IGLDevice::Renderbuffer, multisampledDepthRenderbuffer); - multisampledColorRenderbuffer = dev->GenRenderbuffer(); - dev->BindRenderbuffer(IGLDevice::Renderbuffer, multisampledColorRenderbuffer); + multisampledColorRenderbuffer = dev.GenRenderbuffer(); + dev.BindRenderbuffer(IGLDevice::Renderbuffer, multisampledColorRenderbuffer); if (settings.r_srgb) { SPLog("Creating MSAA Color Buffer with SRGB8_ALPHA"); useHighPrec = false; - dev->RenderbufferStorage(IGLDevice::Renderbuffer, (int)settings.r_multisamples, - IGLDevice::SRGB8Alpha, dev->ScreenWidth(), - dev->ScreenHeight()); + dev.RenderbufferStorage(IGLDevice::Renderbuffer, (int)settings.r_multisamples, + IGLDevice::SRGB8Alpha, renderWidth, renderHeight); SPLog("MSAA Color Buffer Allocated"); - dev->FramebufferRenderbuffer( - IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, IGLDevice::Renderbuffer, - multisampledColorRenderbuffer); - IGLDevice::Enum status = dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + dev.FramebufferRenderbuffer(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Renderbuffer, + multisampledColorRenderbuffer); + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } @@ -123,17 +120,16 @@ namespace spades { SPLog("RGB10A2/HDR disabled"); SPRaise("jump to catch(...)"); } - dev->RenderbufferStorage(IGLDevice::Renderbuffer, - (int)settings.r_multisamples, - useHdr ? IGLDevice::RGBA16F : IGLDevice::RGB10A2, - dev->ScreenWidth(), dev->ScreenHeight()); + dev.RenderbufferStorage(IGLDevice::Renderbuffer, + (int)settings.r_multisamples, + useHdr ? IGLDevice::RGBA16F : IGLDevice::RGB10A2, + renderWidth, renderHeight); SPLog("MSAA Color Buffer Allocated"); - dev->FramebufferRenderbuffer( + dev.FramebufferRenderbuffer( IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, IGLDevice::Renderbuffer, multisampledColorRenderbuffer); - IGLDevice::Enum status = - dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } @@ -145,17 +141,16 @@ namespace spades { useHighPrec = false; useHdr = false; settings.r_hdr = 0; - dev->RenderbufferStorage(IGLDevice::Renderbuffer, - (int)settings.r_multisamples, IGLDevice::RGBA8, - dev->ScreenWidth(), dev->ScreenHeight()); + dev.RenderbufferStorage(IGLDevice::Renderbuffer, + (int)settings.r_multisamples, IGLDevice::RGBA8, + renderWidth, renderHeight); SPLog("MSAA Color Buffer Allocated"); - dev->FramebufferRenderbuffer( + dev.FramebufferRenderbuffer( IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, IGLDevice::Renderbuffer, multisampledColorRenderbuffer); - IGLDevice::Enum status = - dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } @@ -174,49 +169,44 @@ namespace spades { // we must first copy to non-multismapled // framebuffer to use it in shader as a texture. - renderFramebuffer = dev->GenFramebuffer(); - dev->BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); + renderFramebuffer = dev.GenFramebuffer(); + dev.BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); - renderDepthTexture = dev->GenTexture(); - dev->BindTexture(IGLDevice::Texture2D, renderDepthTexture); - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, - dev->ScreenWidth(), dev->ScreenHeight(), 0, IGLDevice::DepthComponent, - IGLDevice::UnsignedInt, NULL); + renderDepthTexture = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, renderDepthTexture); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, renderWidth, + renderHeight, 0, IGLDevice::DepthComponent, IGLDevice::UnsignedInt, + NULL); SPLog("Depth Buffer Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, - IGLDevice::Texture2D, renderDepthTexture, 0); - - renderColorTexture = dev->GenTexture(); - dev->BindTexture(IGLDevice::Texture2D, renderColorTexture); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, + IGLDevice::Texture2D, renderDepthTexture, 0); + + renderColorTexture = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, renderColorTexture); if (settings.r_srgb) { SPLog("Creating Non-MSAA SRGB buffer"); useHighPrec = false; - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::SRGB8Alpha, dev->ScreenWidth(), - dev->ScreenHeight(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, - NULL); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::SRGB8Alpha, renderWidth, + renderHeight, 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); SPLog("Color Buffer Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, renderColorTexture, 0); - - IGLDevice::Enum status = dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, renderColorTexture, 0); + + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } @@ -228,24 +218,23 @@ namespace spades { SPLog("RGB10A2/HDR disabled"); SPRaise("jump to catch(...)"); } - dev->TexImage2D(IGLDevice::Texture2D, 0, - useHdr ? IGLDevice::RGBA16F : IGLDevice::RGB10A2, - dev->ScreenWidth(), dev->ScreenHeight(), 0, IGLDevice::RGBA, - IGLDevice::UnsignedByte, NULL); + dev.TexImage2D( + IGLDevice::Texture2D, 0, useHdr ? IGLDevice::RGBA16F : IGLDevice::RGB10A2, + renderWidth, renderHeight, 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); SPLog("Color Buffer Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, renderColorTexture, 0); - - IGLDevice::Enum status = dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, renderColorTexture, 0); + + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } @@ -256,23 +245,23 @@ namespace spades { useHighPrec = false; useHdr = false; settings.r_hdr = 0; - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, dev->ScreenWidth(), - dev->ScreenHeight(), 0, IGLDevice::RGBA, - IGLDevice::UnsignedByte, NULL); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, renderWidth, + renderHeight, 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, + NULL); SPLog("Color Buffer Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, renderColorTexture, 0); - - IGLDevice::Enum status = dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, renderColorTexture, 0); + + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } @@ -283,89 +272,118 @@ namespace spades { if ((int)settings.r_water >= 2) { SPLog("Creating Mirror framebuffer"); - mirrorFramebuffer = dev->GenFramebuffer(); - dev->BindFramebuffer(IGLDevice::Framebuffer, mirrorFramebuffer); + mirrorFramebuffer = dev.GenFramebuffer(); + dev.BindFramebuffer(IGLDevice::Framebuffer, mirrorFramebuffer); - mirrorColorTexture = dev->GenTexture(); - dev->BindTexture(IGLDevice::Texture2D, mirrorColorTexture); + mirrorColorTexture = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, mirrorColorTexture); SPLog("Creating Mirror texture"); - dev->TexImage2D(IGLDevice::Texture2D, 0, fbInternalFormat, dev->ScreenWidth(), - dev->ScreenHeight(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, - NULL); + dev.TexImage2D(IGLDevice::Texture2D, 0, fbInternalFormat, renderWidth, + renderHeight, 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); SPLog("Color Buffer Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, mirrorColorTexture, 0); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, mirrorColorTexture, 0); SPLog("Creating Mirror depth texture"); - mirrorDepthTexture = dev->GenTexture(); - dev->BindTexture(IGLDevice::Texture2D, mirrorDepthTexture); - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, - dev->ScreenWidth(), dev->ScreenHeight(), 0, - IGLDevice::DepthComponent, IGLDevice::UnsignedInt, NULL); + mirrorDepthTexture = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, mirrorDepthTexture); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, renderWidth, + renderHeight, 0, IGLDevice::DepthComponent, IGLDevice::UnsignedInt, + NULL); SPLog("Depth Buffer Allocated"); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, - IGLDevice::Texture2D, mirrorDepthTexture, 0); - - IGLDevice::Enum status = dev->CheckFramebufferStatus(IGLDevice::Framebuffer); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, + IGLDevice::Texture2D, mirrorDepthTexture, 0); + + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); if (status != IGLDevice::FramebufferComplete) { RaiseFBStatusError(status); } SPLog("Mirror Framebuffer Created"); } // (int)r_water >= 2 - renderFramebufferWithoutDepth = dev->GenFramebuffer(); - dev->BindFramebuffer(IGLDevice::Framebuffer, renderFramebufferWithoutDepth); - dev->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, renderColorTexture, 0); + renderFramebufferWithoutDepth = dev.GenFramebuffer(); + dev.BindFramebuffer(IGLDevice::Framebuffer, renderFramebufferWithoutDepth); + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, renderColorTexture, 0); // add render buffer as a registered buffer Buffer buf; buf.framebuffer = renderFramebufferWithoutDepth; buf.texture = renderColorTexture; buf.refCount = 0; - buf.w = device->ScreenWidth(); - buf.h = device->ScreenHeight(); + buf.w = renderWidth; + buf.h = renderHeight; buf.internalFormat = fbInternalFormat; buffers.push_back(buf); - dev->BindFramebuffer(IGLDevice::Framebuffer, 0); - dev->BindRenderbuffer(IGLDevice::Renderbuffer, 0); + dev.BindFramebuffer(IGLDevice::Framebuffer, 0); + dev.BindRenderbuffer(IGLDevice::Renderbuffer, 0); } GLFramebufferManager::~GLFramebufferManager() { - // maybe framebuffers are released automatically when - // application quits... + if (multisampledFramebuffer) { + device.DeleteFramebuffer(multisampledFramebuffer); + } + if (multisampledColorRenderbuffer) { + device.DeleteRenderbuffer(multisampledColorRenderbuffer); + } + if (multisampledDepthRenderbuffer) { + device.DeleteRenderbuffer(multisampledDepthRenderbuffer); + } + if (renderFramebuffer) { + device.DeleteFramebuffer(renderFramebuffer); + } + if (renderColorTexture) { + device.DeleteTexture(renderColorTexture); + } + if (renderDepthTexture) { + device.DeleteTexture(renderDepthTexture); + } + if (mirrorFramebuffer) { + device.DeleteFramebuffer(mirrorFramebuffer); + } + if (mirrorColorTexture) { + device.DeleteTexture(mirrorColorTexture); + } + if (mirrorDepthTexture) { + device.DeleteTexture(mirrorDepthTexture); + } + for (const Buffer &buffer : buffers) { + device.DeleteFramebuffer(buffer.framebuffer); + device.DeleteTexture(buffer.texture); + } + buffers.clear(); } void GLFramebufferManager::PrepareSceneRendering() { SPADES_MARK_FUNCTION(); if (useMultisample) { // ---- multisampled - device->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); - device->Enable(IGLDevice::Multisample, useMultisample); + device.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + device.Enable(IGLDevice::Multisample, useMultisample); } else { // ---- single sampled - device->BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); // calling glDisable(GL_MULTISAMPLE) on non-MSAA FB // causes GL_INVALID_FRAMEBUFFER_OPERATION on @@ -374,9 +392,9 @@ namespace spades { doingPostProcessing = false; - device->Enable(IGLDevice::DepthTest, true); - device->DepthMask(true); - device->Viewport(0, 0, device->ScreenWidth(), device->ScreenHeight()); + device.Enable(IGLDevice::DepthTest, true); + device.DepthMask(true); + device.Viewport(0, 0, renderWidth, renderHeight); } GLColorBuffer @@ -394,71 +412,71 @@ namespace spades { captured.Release(); } - device->BindFramebuffer(IGLDevice::Framebuffer, tempFb); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, handle.GetTexture(), 0); + device.BindFramebuffer(IGLDevice::Framebuffer, tempFb); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, handle.GetTexture(), 0); // downsample - int w = device->ScreenWidth(); - int h = device->ScreenHeight(); + int w = renderWidth; + int h = renderHeight; if (settings.r_blitFramebuffer) { if (useMultisample) { - device->BindFramebuffer(IGLDevice::ReadFramebuffer, multisampledFramebuffer); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, multisampledFramebuffer); } else { - device->BindFramebuffer(IGLDevice::ReadFramebuffer, renderFramebuffer); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, renderFramebuffer); } - device->BindFramebuffer(IGLDevice::DrawFramebuffer, tempFb); - device->BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::ColorBufferBit, - IGLDevice::Nearest); - device->BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::DepthBufferBit, - IGLDevice::Nearest); - device->BindFramebuffer(IGLDevice::ReadFramebuffer, 0); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, 0); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, tempFb); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::ColorBufferBit, + IGLDevice::Nearest); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::DepthBufferBit, + IGLDevice::Nearest); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, 0); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, 0); } else { if (useMultisample) { - device->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); } else { - device->BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); } - device->BindTexture(IGLDevice::Texture2D, handle.GetTexture()); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); - device->BindTexture(IGLDevice::Texture2D, tempDepthTex); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindTexture(IGLDevice::Texture2D, handle.GetTexture()); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindTexture(IGLDevice::Texture2D, tempDepthTex); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); } // restore render framebuffer if (useMultisample) { // ---- multisampled - device->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); } else { // ---- single sampled - device->BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); } return handle; } void GLFramebufferManager::ClearMirrorTexture(spades::Vector3 bgCol) { - device->BindFramebuffer(IGLDevice::Framebuffer, mirrorFramebuffer); - device->Viewport(0, 0, device->ScreenWidth(), device->ScreenHeight()); - device->ClearColor(bgCol.x, bgCol.y, bgCol.z, 1.f); - device->Clear((IGLDevice::Enum)(IGLDevice::ColorBufferBit | IGLDevice::DepthBufferBit)); + device.BindFramebuffer(IGLDevice::Framebuffer, mirrorFramebuffer); + device.Viewport(0, 0, renderWidth, renderHeight); + device.ClearColor(bgCol.x, bgCol.y, bgCol.z, 1.f); + device.Clear((IGLDevice::Enum)(IGLDevice::ColorBufferBit | IGLDevice::DepthBufferBit)); // restore framebuffer if (useMultisample) { // ---- multisampled - device->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); } else { // ---- single sampled - device->BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); } } void GLFramebufferManager::CopyToMirrorTexture(IGLDevice::UInteger fb) { SPADES_MARK_FUNCTION(); - int w = device->ScreenWidth(); - int h = device->ScreenHeight(); + int w = renderWidth; + int h = renderHeight; if (fb == 0) { fb = useMultisample ? multisampledFramebuffer : renderFramebuffer; } @@ -468,59 +486,65 @@ namespace spades { if (useMultisample) { // downsample if (settings.r_blitFramebuffer) { - device->BindFramebuffer(IGLDevice::ReadFramebuffer, fb); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, mirrorFramebuffer); - device->BlitFramebuffer(0, 0, w, h, 0, 0, w, h, - IGLDevice::ColorBufferBit | - (needsDepth ? IGLDevice::DepthBufferBit : 0), - IGLDevice::Nearest); - device->BindFramebuffer(IGLDevice::ReadFramebuffer, 0); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, 0); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, fb); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, mirrorFramebuffer); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::ColorBufferBit, + IGLDevice::Nearest); + if (needsDepth) { + device.BindFramebuffer(IGLDevice::ReadFramebuffer, renderFramebuffer); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::DepthBufferBit, + IGLDevice::Nearest); + } + device.BindFramebuffer(IGLDevice::ReadFramebuffer, 0); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, 0); } else { - device->BindFramebuffer(IGLDevice::Framebuffer, fb); - device->BindTexture(IGLDevice::Texture2D, mirrorColorTexture); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindFramebuffer(IGLDevice::Framebuffer, fb); + device.BindTexture(IGLDevice::Texture2D, mirrorColorTexture); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); if (needsDepth) { - device->BindTexture(IGLDevice::Texture2D, mirrorDepthTexture); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindTexture(IGLDevice::Texture2D, mirrorDepthTexture); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); } } } else { // copy if (settings.r_blitFramebuffer) { - device->BindFramebuffer(IGLDevice::ReadFramebuffer, fb); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, mirrorFramebuffer); - device->BlitFramebuffer(0, 0, w, h, 0, 0, w, h, - IGLDevice::ColorBufferBit | - (needsDepth ? IGLDevice::DepthBufferBit : 0), - IGLDevice::Nearest); - device->BindFramebuffer(IGLDevice::ReadFramebuffer, 0); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, 0); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, fb); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, mirrorFramebuffer); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::ColorBufferBit, + IGLDevice::Nearest); + if (needsDepth) { + device.BindFramebuffer(IGLDevice::ReadFramebuffer, renderFramebuffer); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::DepthBufferBit, + IGLDevice::Nearest); + } + device.BindFramebuffer(IGLDevice::ReadFramebuffer, 0); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, 0); } else { - device->BindFramebuffer(IGLDevice::Framebuffer, fb); - device->BindTexture(IGLDevice::Texture2D, mirrorColorTexture); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindFramebuffer(IGLDevice::Framebuffer, fb); + device.BindTexture(IGLDevice::Texture2D, mirrorColorTexture); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); if (needsDepth) { - device->BindTexture(IGLDevice::Texture2D, mirrorDepthTexture); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindTexture(IGLDevice::Texture2D, mirrorDepthTexture); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); } } } - device->BindTexture(IGLDevice::Texture2D, mirrorColorTexture); - // device->GenerateMipmap(IGLDevice::Texture2D); + device.BindTexture(IGLDevice::Texture2D, mirrorColorTexture); + // device.GenerateMipmap(IGLDevice::Texture2D); // restore framebuffer if (useMultisample) { // ---- multisampled - device->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); } else { // ---- single sampled - device->BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); + device.BindFramebuffer(IGLDevice::Framebuffer, renderFramebuffer); } - device->Enable(IGLDevice::DepthTest, true); - device->DepthMask(true); + device.Enable(IGLDevice::DepthTest, true); + device.DepthMask(true); } GLFramebufferManager::BufferHandle GLFramebufferManager::StartPostProcessing() { @@ -530,28 +554,28 @@ namespace spades { if (useMultisample) { // downsample - int w = device->ScreenWidth(); - int h = device->ScreenHeight(); + int w = renderWidth; + int h = renderHeight; if (settings.r_blitFramebuffer) { - device->BindFramebuffer(IGLDevice::ReadFramebuffer, multisampledFramebuffer); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, renderFramebuffer); - device->BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::ColorBufferBit, - IGLDevice::Nearest); - device->BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::DepthBufferBit, - IGLDevice::Nearest); - device->BindFramebuffer(IGLDevice::ReadFramebuffer, 0); - device->BindFramebuffer(IGLDevice::DrawFramebuffer, 0); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, multisampledFramebuffer); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, renderFramebuffer); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::ColorBufferBit, + IGLDevice::Nearest); + device.BlitFramebuffer(0, 0, w, h, 0, 0, w, h, IGLDevice::DepthBufferBit, + IGLDevice::Nearest); + device.BindFramebuffer(IGLDevice::ReadFramebuffer, 0); + device.BindFramebuffer(IGLDevice::DrawFramebuffer, 0); } else { - device->BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); - device->BindTexture(IGLDevice::Texture2D, renderColorTexture); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); - device->BindTexture(IGLDevice::Texture2D, renderDepthTexture); - device->CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindFramebuffer(IGLDevice::Framebuffer, multisampledFramebuffer); + device.BindTexture(IGLDevice::Texture2D, renderColorTexture); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); + device.BindTexture(IGLDevice::Texture2D, renderDepthTexture); + device.CopyTexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 0, 0, w, h); } } - device->Enable(IGLDevice::DepthTest, false); - device->DepthMask(false); + device.Enable(IGLDevice::DepthTest, false); + device.DepthMask(false); // zero is always renderFramebuffer return BufferHandle(this, 0); @@ -583,9 +607,9 @@ namespace spades { SPADES_MARK_FUNCTION(); if (w < 0) - w = device->ScreenWidth(); + w = renderWidth; if (h < 0) - h = device->ScreenHeight(); + h = renderHeight; // During the main rendering pass the first buffer is allocated to the render target // and cannot be allocated for pre/postprocessing pass @@ -610,27 +634,27 @@ namespace spades { // no buffer is free! IGLDevice::Enum ifmt = iFormat; - IGLDevice::UInteger tex = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, tex); - device->TexImage2D(IGLDevice::Texture2D, 0, ifmt, w, h, 0, IGLDevice::Red, - IGLDevice::UnsignedByte, NULL); + IGLDevice::UInteger tex = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, tex); + device.TexImage2D(IGLDevice::Texture2D, 0, ifmt, w, h, 0, IGLDevice::Red, + IGLDevice::UnsignedByte, NULL); SPLog("Texture allocated."); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - IGLDevice::UInteger fb = device->GenFramebuffer(); - device->BindFramebuffer(IGLDevice::Framebuffer, fb); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, tex, 0); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + IGLDevice::UInteger fb = device.GenFramebuffer(); + device.BindFramebuffer(IGLDevice::Framebuffer, fb); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, tex, 0); SPLog("Framebuffer created."); - device->BindFramebuffer(IGLDevice::Framebuffer, 0); + device.BindFramebuffer(IGLDevice::Framebuffer, 0); Buffer buf; buf.framebuffer = fb; @@ -710,5 +734,5 @@ namespace spades { Buffer &b = manager->buffers[bufferIndex]; return b.internalFormat; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLFramebufferManager.h b/Sources/Draw/GLFramebufferManager.h index 6134b4f99..c779e751a 100644 --- a/Sources/Draw/GLFramebufferManager.h +++ b/Sources/Draw/GLFramebufferManager.h @@ -54,7 +54,7 @@ namespace spades { }; private: - IGLDevice *device; + IGLDevice &device; GLSettings &settings; struct Buffer { @@ -71,29 +71,32 @@ namespace spades { bool doingPostProcessing; - IGLDevice::UInteger multisampledFramebuffer; + int renderWidth; + int renderHeight; + + IGLDevice::UInteger multisampledFramebuffer = 0; // for multisample - IGLDevice::UInteger multisampledColorRenderbuffer; - IGLDevice::UInteger multisampledDepthRenderbuffer; + IGLDevice::UInteger multisampledColorRenderbuffer = 0; + IGLDevice::UInteger multisampledDepthRenderbuffer = 0; // common - IGLDevice::UInteger renderFramebuffer; - IGLDevice::UInteger renderColorTexture; - IGLDevice::UInteger renderDepthTexture; + IGLDevice::UInteger renderFramebuffer = 0; + IGLDevice::UInteger renderColorTexture = 0; + IGLDevice::UInteger renderDepthTexture = 0; - IGLDevice::UInteger renderFramebufferWithoutDepth; + IGLDevice::UInteger renderFramebufferWithoutDepth = 0; IGLDevice::Enum fbInternalFormat; - IGLDevice::UInteger mirrorFramebuffer; - IGLDevice::UInteger mirrorColorTexture; - IGLDevice::UInteger mirrorDepthTexture; + IGLDevice::UInteger mirrorFramebuffer = 0; + IGLDevice::UInteger mirrorColorTexture = 0; + IGLDevice::UInteger mirrorDepthTexture = 0; std::vector buffers; public: - GLFramebufferManager(IGLDevice *, GLSettings &); + GLFramebufferManager(IGLDevice &, GLSettings &, int renderWidth, int renderHeight); ~GLFramebufferManager(); /** setups device for scene rendering. */ @@ -106,7 +109,19 @@ namespace spades { void MakeSureAllBuffersReleased(); IGLDevice::UInteger GetDepthTexture() { return renderDepthTexture; } + IGLDevice::Enum GetMainInternalFormat() { return fbInternalFormat; } + + + /** + * Creates BufferHandle with a given size and format. + * Might clobber the current framebuffer and texture bindings. + */ BufferHandle CreateBufferHandle(int w = -1, int h = -1, bool alpha = false); + + /** + * Creates BufferHandle with a given size and format. + * Might clobber the current framebuffer and texture bindings. + */ BufferHandle CreateBufferHandle(int w, int h, IGLDevice::Enum internalFormat); void CopyToMirrorTexture(IGLDevice::UInteger fb = 0); @@ -117,5 +132,5 @@ namespace spades { // name is too long, so shorten it! typedef GLFramebufferManager::BufferHandle GLColorBuffer; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLImage.cpp b/Sources/Draw/GLImage.cpp index 269d97537..e234df948 100644 --- a/Sources/Draw/GLImage.cpp +++ b/Sources/Draw/GLImage.cpp @@ -53,22 +53,22 @@ namespace spades { device->BindTexture(target, tex); } - GLImage *GLImage::FromBitmap(spades::Bitmap *bmp, spades::draw::IGLDevice *dev) { + Handle GLImage::FromBitmap(spades::Bitmap &bmp, spades::draw::IGLDevice *dev) { SPADES_MARK_FUNCTION(); IGLDevice::UInteger tex; tex = dev->GenTexture(); dev->BindTexture(IGLDevice::Texture2D, tex); - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA, bmp->GetWidth(), - bmp->GetHeight(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, - bmp->GetPixels()); + dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA, bmp.GetWidth(), + bmp.GetHeight(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, + bmp.GetPixels()); dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Linear); dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::LinearMipmapNearest); dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); dev->GenerateMipmap(IGLDevice::Texture2D); - return new GLImage(tex, dev, bmp->GetWidth(), bmp->GetHeight()); + return Handle::New(tex, dev, (float)bmp.GetWidth(), (float)bmp.GetHeight()); } void GLImage::SubImage(spades::Bitmap *bmp, int x, int y) { @@ -78,6 +78,10 @@ namespace spades { IGLDevice::RGBA, IGLDevice::UnsignedByte, bmp->GetPixels()); } + // TODO: Make sure this method is called even for `GLImage`s created via + // `GLRenderer::CreateImage`. Otherwise, `GLImage` outliving the + // originating `GLRenderer` will cause a use-after-free in its + // destructor. void GLImage::Invalidate() { SPADES_MARK_FUNCTION(); MakeSureValid(); @@ -86,5 +90,5 @@ namespace spades { if (autoDelete) device->DeleteTexture(tex); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLImage.h b/Sources/Draw/GLImage.h index 8b4cec95c..fa418a66a 100644 --- a/Sources/Draw/GLImage.h +++ b/Sources/Draw/GLImage.h @@ -20,8 +20,8 @@ #pragma once -#include #include "IGLDevice.h" +#include namespace spades { class Bitmap; @@ -42,7 +42,7 @@ namespace spades { public: GLImage(IGLDevice::UInteger textureObject, IGLDevice *device, float w, float h, bool autoDelete = true); - static GLImage *FromBitmap(Bitmap *, IGLDevice *); + static Handle FromBitmap(Bitmap &, IGLDevice *); void Bind(IGLDevice::Enum target); float GetWidth() override { return width; } @@ -56,5 +56,5 @@ namespace spades { void Update(Bitmap &bmp, int x, int y) override { SubImage(&bmp, x, y); } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLImageManager.cpp b/Sources/Draw/GLImageManager.cpp index 0ae69d613..2ce08c7ea 100644 --- a/Sources/Draw/GLImageManager.cpp +++ b/Sources/Draw/GLImageManager.cpp @@ -29,7 +29,7 @@ namespace spades { namespace draw { - GLImageManager::GLImageManager(IGLDevice *dev) : device(dev), whiteImage(nullptr) { + GLImageManager::GLImageManager(IGLDevice &dev) : device(dev), whiteImage(nullptr) { SPADES_MARK_FUNCTION(); } @@ -71,9 +71,9 @@ namespace spades { GLImage *GLImageManager::CreateImage(const std::string &name) { SPADES_MARK_FUNCTION(); - Handle bmp(Bitmap::Load(name), false); + Handle bmp = Bitmap::Load(name); - return GLImage::FromBitmap(bmp, device); + return GLImage::FromBitmap(*bmp, &device).Unmanage(); } // draw all imaegs so that all textures are resident diff --git a/Sources/Draw/GLImageManager.h b/Sources/Draw/GLImageManager.h index 4156e0367..9f0f1e346 100644 --- a/Sources/Draw/GLImageManager.h +++ b/Sources/Draw/GLImageManager.h @@ -31,14 +31,14 @@ namespace spades { class GLRenderer; class GLImageManager { - IGLDevice *device; + IGLDevice &device; std::map images; GLImage *whiteImage; GLImage *CreateImage(const std::string &); public: - GLImageManager(IGLDevice *); + GLImageManager(IGLDevice &); ~GLImageManager(); GLImage *RegisterImage(const std::string &); diff --git a/Sources/Draw/GLImageRenderer.cpp b/Sources/Draw/GLImageRenderer.cpp index 6f32d6601..20f074285 100644 --- a/Sources/Draw/GLImageRenderer.cpp +++ b/Sources/Draw/GLImageRenderer.cpp @@ -19,25 +19,24 @@ */ #include "GLImageRenderer.h" -#include -#include -#include #include "GLImage.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLImageRenderer::GLImageRenderer(GLRenderer *r) + GLImageRenderer::GLImageRenderer(GLRenderer &r) : renderer(r), - device(r->GetGLDevice()), - invScreenWidthFactored(2.f / device->ScreenWidth()), - invScreenHeightFactored(-2.f / device->ScreenHeight()) { + device(r.GetGLDevice()), + invScreenWidthFactored(2.f / device.ScreenWidth()), + invScreenHeightFactored(-2.f / device.ScreenHeight()) { SPADES_MARK_FUNCTION(); image = NULL; - program = renderer->RegisterProgram("Shaders/BasicImage.program"); + program = renderer.RegisterProgram("Shaders/BasicImage.program"); program->Use(); @@ -79,33 +78,32 @@ namespace spades { program->Use(); - device->ActiveTexture(0); + device.ActiveTexture(0); image->Bind(IGLDevice::Texture2D); - device->VertexAttribPointer((*positionAttribute)(), 2, IGLDevice::FloatType, false, - sizeof(ImageVertex), vertices.data()); - device->VertexAttribPointer((*colorAttribute)(), 4, IGLDevice::FloatType, false, - sizeof(ImageVertex), - (const char *)vertices.data() + sizeof(float) * 4); - device->VertexAttribPointer((*textureCoordAttribute)(), 2, IGLDevice::FloatType, false, - sizeof(ImageVertex), - (const char *)vertices.data() + sizeof(float) * 2); + device.VertexAttribPointer((*positionAttribute)(), 2, IGLDevice::FloatType, false, + sizeof(ImageVertex), vertices.data()); + device.VertexAttribPointer((*colorAttribute)(), 4, IGLDevice::FloatType, false, + sizeof(ImageVertex), + (const char *)vertices.data() + sizeof(float) * 4); + device.VertexAttribPointer((*textureCoordAttribute)(), 2, IGLDevice::FloatType, false, + sizeof(ImageVertex), + (const char *)vertices.data() + sizeof(float) * 2); - device->EnableVertexAttribArray((*positionAttribute)(), true); - device->EnableVertexAttribArray((*colorAttribute)(), true); - device->EnableVertexAttribArray((*textureCoordAttribute)(), true); + device.EnableVertexAttribArray((*positionAttribute)(), true); + device.EnableVertexAttribArray((*colorAttribute)(), true); + device.EnableVertexAttribArray((*textureCoordAttribute)(), true); screenSize->SetValue(invScreenWidthFactored, invScreenHeightFactored); textureSize->SetValue(image->GetInvWidth(), image->GetInvHeight()); texture->SetValue(0); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedInt, indices.data()); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedInt, indices.data()); - device->EnableVertexAttribArray((*positionAttribute)(), false); - device->EnableVertexAttribArray((*colorAttribute)(), false); - device->EnableVertexAttribArray((*textureCoordAttribute)(), false); + device.EnableVertexAttribArray((*positionAttribute)(), false); + device.EnableVertexAttribArray((*colorAttribute)(), false); + device.EnableVertexAttribArray((*textureCoordAttribute)(), false); vertices.clear(); indices.clear(); @@ -164,5 +162,5 @@ namespace spades { indices.push_back(idx + 2); indices.push_back(idx + 3); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLImageRenderer.h b/Sources/Draw/GLImageRenderer.h index 1702ff96f..18c88187d 100644 --- a/Sources/Draw/GLImageRenderer.h +++ b/Sources/Draw/GLImageRenderer.h @@ -32,8 +32,8 @@ namespace spades { class IGLDevice; class GLRenderer; class GLImageRenderer { - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLImage *image; float invScreenWidthFactored; @@ -58,7 +58,7 @@ namespace spades { std::vector indices; public: - GLImageRenderer(GLRenderer *renderer); + GLImageRenderer(GLRenderer &renderer); ~GLImageRenderer(); void Flush(); @@ -69,5 +69,5 @@ namespace spades { float dy4, float sx1, float sy1, float sx2, float sy2, float sx3, float sy3, float sx4, float sy4, float r, float g, float b, float a); }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLensDustFilter.cpp b/Sources/Draw/GLLensDustFilter.cpp index fd5568179..2b066bc0c 100644 --- a/Sources/Draw/GLLensDustFilter.cpp +++ b/Sources/Draw/GLLensDustFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLImage.h" #include "GLLensDustFilter.h" #include "GLProgram.h" @@ -30,41 +28,44 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include #include namespace spades { namespace draw { - GLLensDustFilter::GLLensDustFilter(GLRenderer *renderer) : renderer(renderer) { - thru = renderer->RegisterProgram("Shaders/PostFilters/PassThroughConstAlpha.program"); - gauss1d = renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program"); - dust = renderer->RegisterProgram("Shaders/PostFilters/LensDust.program"); - dustImg = (GLImage *)renderer->RegisterImage("Textures/LensDustTexture.jpg"); - - IGLDevice *dev = renderer->GetGLDevice(); - noiseTex = dev->GenTexture(); - dev->BindTexture(IGLDevice::Texture2D, noiseTex); - dev->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, 128, 128, 0, IGLDevice::BGRA, - IGLDevice::UnsignedByte, NULL); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); + GLLensDustFilter::GLLensDustFilter(GLRenderer &renderer) : renderer(renderer) { + thru = renderer.RegisterProgram("Shaders/PostFilters/PassThroughConstAlpha.program"); + gauss1d = renderer.RegisterProgram("Shaders/PostFilters/Gauss1D.program"); + dust = renderer.RegisterProgram("Shaders/PostFilters/LensDust.program"); + dustImg = renderer.RegisterImage("Textures/LensDustTexture.jpg").Cast(); + + IGLDevice &dev = renderer.GetGLDevice(); + noiseTex = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, noiseTex); + dev.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, 128, 128, 0, IGLDevice::BGRA, + IGLDevice::UnsignedByte, NULL); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); } - GLLensDustFilter::~GLLensDustFilter() { renderer->GetGLDevice()->DeleteTexture(noiseTex); } + GLLensDustFilter::~GLLensDustFilter() { renderer.GetGLDevice().DeleteTexture(noiseTex); } #define Level GLLensDustFilterLevel GLColorBuffer GLLensDustFilter::DownSample(GLColorBuffer tex, bool linearize) { SPADES_MARK_FUNCTION(); GLProgram *program = thru; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = tex.GetWidth(); int h = tex.GetHeight(); + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle( + (w + 1) / 2, (h + 1) / 2, false); + static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform("mainTexture"); static GLProgramUniform blur_colorUniform("colorUniform"); @@ -75,8 +76,8 @@ namespace spades { blur_textureUniform(program); blur_textureUniform.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, tex.GetTexture()); blur_texCoordOffsetUniform(program); blur_texCoordOffsetUniform.SetValue(1.f / w, 1.f / h, -1.f / w, -1.f / h); @@ -90,16 +91,14 @@ namespace spades { qr.SetCoordAttributeIndex(blur_positionAttribute()); if (linearize) { - dev->Enable(IGLDevice::Blend, true); - dev->BlendFunc(IGLDevice::SrcColor, IGLDevice::Zero); + dev.Enable(IGLDevice::Blend, true); + dev.BlendFunc(IGLDevice::SrcColor, IGLDevice::Zero); } else { - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); } - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle( - (w + 1) / 2, (h + 1) / 2, false); - dev->Viewport(0, 0, buf2.GetWidth(), buf2.GetHeight()); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.Viewport(0, 0, buf2.GetWidth(), buf2.GetHeight()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); qr.Draw(); return buf2; } @@ -107,11 +106,13 @@ namespace spades { GLColorBuffer GLLensDustFilter::GaussianBlur(GLColorBuffer tex, bool vertical) { SPADES_MARK_FUNCTION(); GLProgram *program = gauss1d; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = tex.GetWidth(); int h = tex.GetHeight(); + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, false); + static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform("mainTexture"); static GLProgramUniform blur_unitShift("unitShift"); @@ -120,18 +121,17 @@ namespace spades { blur_textureUniform(program); blur_textureUniform.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, tex.GetTexture()); blur_unitShift(program); blur_unitShift.SetValue(vertical ? 0.f : 1.f / w, vertical ? 1.f / h : 0.f); qr.SetCoordAttributeIndex(blur_positionAttribute()); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, false); - dev->Viewport(0, 0, buf2.GetWidth(), buf2.GetHeight()); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.Viewport(0, 0, buf2.GetWidth(), buf2.GetHeight()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); qr.Draw(); return buf2; } @@ -144,10 +144,10 @@ namespace spades { noise[i] = static_cast(SampleRandom()); } - IGLDevice *dev = renderer->GetGLDevice(); - dev->BindTexture(IGLDevice::Texture2D, noiseTex); - dev->TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 128, 128, IGLDevice::BGRA, - IGLDevice::UnsignedByte, noise.data()); + IGLDevice &dev = renderer.GetGLDevice(); + dev.BindTexture(IGLDevice::Texture2D, noiseTex); + dev.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, 128, 128, IGLDevice::BGRA, + IGLDevice::UnsignedByte, noise.data()); } struct Level { @@ -163,10 +163,10 @@ namespace spades { std::vector levels; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); - GLSettings &settings = renderer->GetSettings(); + GLSettings &settings = renderer.GetSettings(); static GLProgramAttribute thruPosition("positionAttribute"); static GLProgramUniform thruColor("colorUniform"); @@ -185,7 +185,7 @@ namespace spades { thru->Use(); thruColor.SetValue(1.f, 1.f, 1.f, 1.f); thruTexture.SetValue(0); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); levels.reserve(10); @@ -215,8 +215,8 @@ namespace spades { levels.push_back(lv); } - dev->Enable(IGLDevice::Blend, true); - dev->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); + dev.Enable(IGLDevice::Blend, true); + dev.BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); // composite levels in the opposite direction thru->Use(); @@ -237,24 +237,24 @@ namespace spades { targLevel.GetWidth(), targLevel.GetHeight(), false); levels[i - 1].retBuf[j] = targRet; - dev->BindFramebuffer(IGLDevice::Framebuffer, targRet.GetFramebuffer()); - dev->Viewport(0, 0, targRet.GetWidth(), targRet.GetHeight()); + dev.BindFramebuffer(IGLDevice::Framebuffer, targRet.GetFramebuffer()); + dev.Viewport(0, 0, targRet.GetWidth(), targRet.GetHeight()); - dev->BindTexture(IGLDevice::Texture2D, targLevel.GetTexture()); + dev.BindTexture(IGLDevice::Texture2D, targLevel.GetTexture()); thruColor.SetValue(1.f, 1.f, 1.f, 1.f); thruTexCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); qr.Draw(); float cx = 0.f, cy = 0.f; - dev->BindTexture(IGLDevice::Texture2D, curLevel.GetTexture()); + dev.BindTexture(IGLDevice::Texture2D, curLevel.GetTexture()); thruColor.SetValue(1.f, 1.f, 1.f, alpha); thruTexCoordRange.SetValue(cx, cy, 1.f, 1.f); - dev->Enable(IGLDevice::Blend, true); + dev.Enable(IGLDevice::Blend, true); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); } } @@ -274,8 +274,8 @@ namespace spades { dust->Use(); - float facX = renderer->ScreenWidth() / 128.f; - float facY = renderer->ScreenHeight() / 128.f; + float facX = renderer.GetRenderWidth() / 128.f; + float facY = renderer.GetRenderHeight() / 128.f; dustNoiseTexCoordFactor.SetValue(facX, facY, facX / 128.f, facY / 128.f); // composite to the final image @@ -283,26 +283,26 @@ namespace spades { GLColorBuffer topLevel1 = levels[0].retBuf[0]; qr.SetCoordAttributeIndex(dustPosition()); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, topLevel1.GetTexture()); - dev->ActiveTexture(5); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, topLevel1.GetTexture()); + dev.ActiveTexture(5); dustImg->Bind(IGLDevice::Texture2D); - dev->ActiveTexture(6); - dev->BindTexture(IGLDevice::Texture2D, noiseTex); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.ActiveTexture(6); + dev.BindTexture(IGLDevice::Texture2D, noiseTex); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); dustBlurTexture1.SetValue(1); dustDustTexture.SetValue(5); dustNoiseTexture.SetValue(6); dustInputTexture.SetValue(0); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); - dev->ActiveTexture(0); + dev.ActiveTexture(0); return output; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLensDustFilter.h b/Sources/Draw/GLLensDustFilter.h index 53ad089ae..77fe40d2a 100644 --- a/Sources/Draw/GLLensDustFilter.h +++ b/Sources/Draw/GLLensDustFilter.h @@ -20,7 +20,6 @@ #pragma once -#include #include #include @@ -36,8 +35,8 @@ namespace spades { GLProgram *thru; GLProgram *dust; GLProgram *gauss1d; - GLImage *dustImg; - GLRenderer *renderer; + Handle dustImg; + GLRenderer &renderer; IGLDevice::UInteger noiseTex; std::vector noise; GLColorBuffer DownSample(GLColorBuffer, bool linearize = false); @@ -45,9 +44,9 @@ namespace spades { void UpdateNoise(); public: - GLLensDustFilter(GLRenderer *); + GLLensDustFilter(GLRenderer &); ~GLLensDustFilter(); GLColorBuffer Filter(GLColorBuffer); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLensFilter.cpp b/Sources/Draw/GLLensFilter.cpp index ae33be4bb..12ae970c7 100644 --- a/Sources/Draw/GLLensFilter.cpp +++ b/Sources/Draw/GLLensFilter.cpp @@ -21,31 +21,33 @@ #include #include "GLLensFilter.h" -#include -#include #include "GLProgram.h" #include "GLProgramAttribute.h" #include "GLProgramUniform.h" #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLLensFilter::GLLensFilter(GLRenderer *renderer) : renderer(renderer) { - lens = renderer->RegisterProgram("Shaders/PostFilters/Lens.program"); + GLLensFilter::GLLensFilter(GLRenderer &renderer) : renderer(renderer) { + lens = renderer.RegisterProgram("Shaders/PostFilters/Lens.program"); } GLColorBuffer GLLensFilter::Filter(GLColorBuffer input) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); + GLColorBuffer output = input.GetManager()->CreateBufferHandle(); + static GLProgramAttribute lensPosition("positionAttribute"); static GLProgramUniform lensTexture("mainTexture"); static GLProgramUniform lensFov("fov"); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); lensPosition(lens); lensTexture(lens); @@ -53,21 +55,20 @@ namespace spades { lens->Use(); - client::SceneDefinition def = renderer->GetSceneDef(); + client::SceneDefinition def = renderer.GetSceneDef(); lensFov.SetValue(tanf(def.fovX * .5f), tanf(def.fovY * .5f)); lensTexture.SetValue(0); // composite to the final image - GLColorBuffer output = input.GetManager()->CreateBufferHandle(); qr.SetCoordAttributeIndex(lensPosition()); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); return output; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLensFilter.h b/Sources/Draw/GLLensFilter.h index 286ed9309..2b1afc441 100644 --- a/Sources/Draw/GLLensFilter.h +++ b/Sources/Draw/GLLensFilter.h @@ -27,12 +27,12 @@ namespace spades { class GLRenderer; class GLProgram; class GLLensFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLProgram *lens; public: - GLLensFilter(GLRenderer *); + GLLensFilter(GLRenderer &); GLColorBuffer Filter(GLColorBuffer); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLensFlareFilter.cpp b/Sources/Draw/GLLensFlareFilter.cpp index d5a6b9130..1b69c879a 100644 --- a/Sources/Draw/GLLensFlareFilter.cpp +++ b/Sources/Draw/GLLensFlareFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLImage.h" #include "GLLensFlareFilter.h" #include "GLMapShadowRenderer.h" @@ -32,27 +30,29 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLLensFlareFilter::GLLensFlareFilter(GLRenderer *renderer) : renderer(renderer) { - blurProgram = renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program"); - scannerProgram = renderer->RegisterProgram("Shaders/LensFlare/Scanner.program"); - drawProgram = renderer->RegisterProgram("Shaders/LensFlare/Draw.program"); - flare1 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/1.png"); - flare2 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/2.png"); - flare3 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/3.png"); - flare4 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/4.jpg"); - mask1 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/mask1.png"); - mask2 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/mask2.png"); - mask3 = (GLImage *)renderer->RegisterImage("Gfx/LensFlare/mask3.png"); - white = (GLImage *)renderer->RegisterImage("Gfx/White.tga"); + GLLensFlareFilter::GLLensFlareFilter(GLRenderer &renderer) : renderer(renderer) { + blurProgram = renderer.RegisterProgram("Shaders/PostFilters/Gauss1D.program"); + scannerProgram = renderer.RegisterProgram("Shaders/LensFlare/Scanner.program"); + drawProgram = renderer.RegisterProgram("Shaders/LensFlare/Draw.program"); + flare1 = renderer.RegisterImage("Gfx/LensFlare/1.png").Cast(); + flare2 = renderer.RegisterImage("Gfx/LensFlare/2.png").Cast(); + flare3 = renderer.RegisterImage("Gfx/LensFlare/3.png").Cast(); + flare4 = renderer.RegisterImage("Gfx/LensFlare/4.jpg").Cast(); + mask1 = renderer.RegisterImage("Gfx/LensFlare/mask1.png").Cast(); + mask2 = renderer.RegisterImage("Gfx/LensFlare/mask2.png").Cast(); + mask3 = renderer.RegisterImage("Gfx/LensFlare/mask3.png").Cast(); + white = renderer.RegisterImage("Gfx/White.tga").Cast(); } GLColorBuffer GLLensFlareFilter::Blur(GLColorBuffer buffer, float spread) { // do gaussian blur GLProgram *program = blurProgram; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = buffer.GetWidth(); int h = buffer.GetHeight(); @@ -66,22 +66,22 @@ namespace spades { blur_unitShift(program); blur_textureUniform.SetValue(0); - dev->ActiveTexture(0); + dev.ActiveTexture(0); qr.SetCoordAttributeIndex(blur_positionAttribute()); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); // x-direction - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, false); - dev->BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, false); + dev.BindTexture(IGLDevice::Texture2D, buffer.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); blur_unitShift.SetValue(spread / (float)w, 0.f); qr.Draw(); buffer.Release(); // y-direction - GLColorBuffer buf3 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, false); - dev->BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); + GLColorBuffer buf3 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, false); + dev.BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); blur_unitShift.SetValue(0.f, spread / (float)h); qr.Draw(); buf2.Release(); @@ -97,9 +97,9 @@ namespace spades { bool infinityDistance) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); - client::SceneDefinition def = renderer->GetSceneDef(); + client::SceneDefinition def = renderer.GetSceneDef(); // transform sun into NDC Vector3 sunWorld = direction; @@ -110,7 +110,7 @@ namespace spades { return; } - IGLDevice::UInteger lastFramebuffer = dev->GetInteger(IGLDevice::FramebufferBinding); + IGLDevice::UInteger lastFramebuffer = dev.GetInteger(IGLDevice::FramebufferBinding); Vector2 fov = {tanf(def.fovX * .5f), tanf(def.fovY * .5f)}; Vector2 sunScreen; @@ -121,12 +121,12 @@ namespace spades { Vector2 sunSize = {sunRadiusTan / fov.x, sunRadiusTan / fov.y}; GLColorBuffer visiblityBuffer = - renderer->GetFramebufferManager()->CreateBufferHandle(64, 64, false); + renderer.GetFramebufferManager()->CreateBufferHandle(64, 64, false); GLQuadRenderer qr(dev); { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Occlusion Test"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Occlusion Test"); GLProgram *scanner = scannerProgram; static GLProgramAttribute positionAttribute("positionAttribute"); @@ -153,20 +153,20 @@ namespace spades { scanZ.SetValue(far * (near - depth) / (depth * (near - far))); } - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); depthTexture.SetValue(0); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureCompareMode, - IGLDevice::CompareRefToTexture); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureCompareFunc, - IGLDevice::Less); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureCompareMode, + IGLDevice::CompareRefToTexture); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureCompareFunc, + IGLDevice::Less); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); Vector2 sunTexPos = sunScreen * .5f + .5f; Vector2 sunTexSize = sunSize * .5f; @@ -177,20 +177,20 @@ namespace spades { radius.SetValue(32.f); qr.SetCoordAttributeIndex(positionAttribute()); - dev->BindFramebuffer(IGLDevice::Framebuffer, visiblityBuffer.GetFramebuffer()); - dev->Viewport(0, 0, 64, 64); - dev->ClearColor(0, 0, 0, 1); - dev->Clear(IGLDevice::ColorBufferBit); + dev.BindFramebuffer(IGLDevice::Framebuffer, visiblityBuffer.GetFramebuffer()); + dev.Viewport(0, 0, 64, 64); + dev.ClearColor(0, 0, 0, 1); + dev.Clear(IGLDevice::ColorBufferBit); qr.Draw(); // restore depth texture's compare mode - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureCompareMode, - IGLDevice::None); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureCompareMode, + IGLDevice::None); } visiblityBuffer = Blur(visiblityBuffer, 1.f); @@ -199,15 +199,15 @@ namespace spades { // lens flare size doesn't follow sun size sunSize = MakeVector2(.01f, .01f); - sunSize.x *= renderer->ScreenHeight() / renderer->ScreenWidth(); + sunSize.x *= renderer.ScreenHeight() / renderer.ScreenWidth(); float aroundness = sunScreen.GetPoweredLength() * 0.6f; float aroundness2 = std::min(sunScreen.GetPoweredLength() * 3.2f, 1.f); - dev->BindFramebuffer(IGLDevice::Framebuffer, lastFramebuffer); + dev.BindFramebuffer(IGLDevice::Framebuffer, lastFramebuffer); { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Draw"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Draw"); GLProgram *draw = drawProgram; static GLProgramAttribute positionAttribute("positionAttribute"); @@ -226,27 +226,27 @@ namespace spades { flareTexture(draw); color(draw); - dev->Enable(IGLDevice::Blend, true); - dev->BlendFunc(IGLDevice::One, IGLDevice::One); + dev.Enable(IGLDevice::Blend, true); + dev.BlendFunc(IGLDevice::One, IGLDevice::One); - dev->ActiveTexture(2); + dev.ActiveTexture(2); white->Bind(IGLDevice::Texture2D); flareTexture.SetValue(2); - dev->ActiveTexture(1); + dev.ActiveTexture(1); white->Bind(IGLDevice::Texture2D); modulationTexture.SetValue(1); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, visiblityBuffer.GetTexture()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, visiblityBuffer.GetTexture()); visibilityTexture.SetValue(0); qr.SetCoordAttributeIndex(positionAttribute()); - dev->Viewport(0, 0, dev->ScreenWidth(), dev->ScreenHeight()); + dev.Viewport(0, 0, renderer.GetRenderWidth(), renderer.GetRenderHeight()); /* render flare */ - dev->ActiveTexture(2); + dev.ActiveTexture(2); flare4->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * .04f, sunColor.y * .03f, sunColor.z * .04f); @@ -255,7 +255,7 @@ namespace spades { sunScreen.y + sunSize.y * 256.f); qr.Draw(); - dev->ActiveTexture(2); + dev.ActiveTexture(2); white->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * .3f, sunColor.y * .3f, sunColor.z * .3f); @@ -287,7 +287,7 @@ namespace spades { /* render dusts */ - dev->ActiveTexture(1); + dev.ActiveTexture(1); mask3->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * .4f * aroundness, sunColor.y * .4f * aroundness, @@ -299,9 +299,9 @@ namespace spades { if (renderReflections) { - dev->ActiveTexture(1); + dev.ActiveTexture(1); white->Bind(IGLDevice::Texture2D); - dev->ActiveTexture(2); + dev.ActiveTexture(2); flare2->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * 1.f, sunColor.y * 1.f, sunColor.z * 1.f); @@ -336,9 +336,9 @@ namespace spades { qr.Draw(); - dev->ActiveTexture(1); + dev.ActiveTexture(1); mask2->Bind(IGLDevice::Texture2D); - dev->ActiveTexture(2); + dev.ActiveTexture(2); flare1->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * .5f, sunColor.y * .4f, sunColor.z * .3f); @@ -357,7 +357,7 @@ namespace spades { qr.Draw(); - dev->ActiveTexture(2); + dev.ActiveTexture(2); flare3->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * .3f, sunColor.y * .3f, sunColor.z * .3f); @@ -368,9 +368,9 @@ namespace spades { qr.Draw(); - dev->ActiveTexture(1); + dev.ActiveTexture(1); mask1->Bind(IGLDevice::Texture2D); - dev->ActiveTexture(2); + dev.ActiveTexture(2); flare3->Bind(IGLDevice::Texture2D); color.SetValue(sunColor.x * .8f * aroundness2, sunColor.y * .5f * aroundness2, @@ -385,10 +385,10 @@ namespace spades { } } - dev->ActiveTexture(0); + dev.ActiveTexture(0); // restore blend mode - dev->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); + dev.BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLensFlareFilter.h b/Sources/Draw/GLLensFlareFilter.h index 502c129b1..2d92a315a 100644 --- a/Sources/Draw/GLLensFlareFilter.h +++ b/Sources/Draw/GLLensFlareFilter.h @@ -1,21 +1,21 @@ /* Copyright (c) 2013 yvt - + This file is part of OpenSpades. - + OpenSpades is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + OpenSpades is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with OpenSpades. If not, see . - + */ #pragma once @@ -24,21 +24,20 @@ namespace spades { namespace draw { - class GLImage; + class GLImage; class GLRenderer; class GLProgram; class GLLensFlareFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLProgram *blurProgram, *scannerProgram, *drawProgram; - GLImage *flare1, *flare2, *flare3, *flare4, *white; - GLImage *mask1, *mask2, *mask3; + Handle flare1, flare2, flare3, flare4, white; + Handle mask1, mask2, mask3; GLColorBuffer Blur(GLColorBuffer, float spread = 1.f); + public: - GLLensFlareFilter(GLRenderer *); + GLLensFlareFilter(GLRenderer &); void Draw(); - void Draw(Vector3 direction, bool reflections, - Vector3 color, bool infinityDistance); + void Draw(Vector3 direction, bool reflections, Vector3 color, bool infinityDistance); }; - } -} - + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLongSpriteRenderer.cpp b/Sources/Draw/GLLongSpriteRenderer.cpp index ece733c8f..322805cfc 100644 --- a/Sources/Draw/GLLongSpriteRenderer.cpp +++ b/Sources/Draw/GLLongSpriteRenderer.cpp @@ -19,21 +19,21 @@ */ #include "GLLongSpriteRenderer.h" -#include #include "GLImage.h" #include "GLProgram.h" #include "GLRenderer.h" #include "IGLDevice.h" #include "SWFeatureLevel.h" +#include #include namespace spades { namespace draw { - GLLongSpriteRenderer::GLLongSpriteRenderer(GLRenderer *renderer) + GLLongSpriteRenderer::GLLongSpriteRenderer(GLRenderer &renderer) : renderer(renderer), - device(renderer->GetGLDevice()), - settings(renderer->GetSettings()), + device(renderer.GetGLDevice()), + settings(renderer.GetSettings()), projectionViewMatrix("projectionViewMatrix"), rightVector("rightVector"), upVector("upVector"), @@ -47,7 +47,7 @@ namespace spades { colorAttribute("colorAttribute") { SPADES_MARK_FUNCTION(); - program = renderer->RegisterProgram("Shaders/LongSprite.program"); + program = renderer.RegisterProgram("Shaders/LongSprite.program"); } GLLongSpriteRenderer::~GLLongSpriteRenderer() { SPADES_MARK_FUNCTION(); } @@ -102,27 +102,27 @@ namespace spades { texCoordAttribute(program); colorAttribute(program); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); - viewMatrix.SetValue(renderer->GetViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); + viewMatrix.SetValue(renderer.GetViewMatrix()); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); - Vector3 fogCol = renderer->GetFogColor(); + Vector3 fogCol = renderer.GetFogColor(); fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); rightVector.SetValue(def.viewAxis[0].x, def.viewAxis[0].y, def.viewAxis[0].z); upVector.SetValue(def.viewAxis[1].x, def.viewAxis[1].y, def.viewAxis[1].z); texture.SetValue(0); - device->ActiveTexture(0); + device.ActiveTexture(0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(texCoordAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(texCoordAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; @@ -332,9 +332,9 @@ namespace spades { Flush(); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(texCoordAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(texCoordAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); } void GLLongSpriteRenderer::Flush() { @@ -343,22 +343,21 @@ namespace spades { if (vertices.empty()) return; - device->VertexAttribPointer(positionAttribute(), 3, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].x)); - device->VertexAttribPointer(texCoordAttribute(), 2, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].u)); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].r)); + device.VertexAttribPointer(positionAttribute(), 3, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].x)); + device.VertexAttribPointer(texCoordAttribute(), 2, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].u)); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].r)); SPAssert(lastImage); lastImage->Bind(IGLDevice::Texture2D); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedInt, indices.data()); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedInt, indices.data()); vertices.clear(); indices.clear(); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLLongSpriteRenderer.h b/Sources/Draw/GLLongSpriteRenderer.h index 1a0209152..d6c27aa16 100644 --- a/Sources/Draw/GLLongSpriteRenderer.h +++ b/Sources/Draw/GLLongSpriteRenderer.h @@ -23,9 +23,9 @@ #include #include -#include #include "GLProgramAttribute.h" #include "GLProgramUniform.h" +#include namespace spades { namespace draw { @@ -56,8 +56,8 @@ namespace spades { } }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLSettings &settings; std::vector sprites; @@ -83,12 +83,12 @@ namespace spades { void Flush(); public: - GLLongSpriteRenderer(GLRenderer *); + GLLongSpriteRenderer(GLRenderer &); ~GLLongSpriteRenderer(); void Add(GLImage *img, Vector3 p1, Vector3 p2, float rad, Vector4 color); void Clear(); void Render(); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLMapChunk.cpp b/Sources/Draw/GLMapChunk.cpp index a7bef7f14..03eb31724 100644 --- a/Sources/Draw/GLMapChunk.cpp +++ b/Sources/Draw/GLMapChunk.cpp @@ -21,9 +21,6 @@ #include #include -#include -#include -#include #include "GLDynamicLightShader.h" #include "GLMapChunk.h" #include "GLMapRenderer.h" @@ -32,15 +29,16 @@ #include "GLRenderer.h" #include "IGLDevice.h" #include // for asOFFSET. somehow `offsetof` fails on gcc-4.8 +#include +#include +#include namespace spades { namespace draw { - GLMapChunk::GLMapChunk(spades::draw::GLMapRenderer *r, client::GameMap *mp, int cx, int cy, - int cz) { + GLMapChunk::GLMapChunk(GLMapRenderer &r, client::GameMap *mp, int cx, int cy, int cz) + : renderer(r), device(r.device) { SPADES_MARK_FUNCTION(); - renderer = r; - device = r->device; map = mp; chunkX = cx; chunkY = cy; @@ -67,11 +65,11 @@ namespace spades { if (!b) { if (buffer) { - device->DeleteBuffer(buffer); + device.DeleteBuffer(buffer); buffer = 0; } if (iBuffer) { - device->DeleteBuffer(iBuffer); + device.DeleteBuffer(iBuffer); iBuffer = 0; } std::vector i; @@ -202,7 +200,7 @@ namespace spades { y &= 511; if (z == 63) { - if (renderer->renderer->GetSettings().r_water) { + if (renderer.renderer.GetSettings().r_water) { return map->IsSolid(x, y, 62); } else { return map->IsSolid(x, y, 63); @@ -218,11 +216,11 @@ namespace spades { vertices.clear(); indices.clear(); if (buffer) { - device->DeleteBuffer(buffer); + device.DeleteBuffer(buffer); buffer = 0; } if (iBuffer) { - device->DeleteBuffer(iBuffer); + device.DeleteBuffer(iBuffer); iBuffer = 0; } @@ -277,27 +275,27 @@ namespace spades { if (vertices.size() == 0) return; - buffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); + buffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(vertices.size() * sizeof(Vertex)), - vertices.data(), IGLDevice::DynamicDraw); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(vertices.size() * sizeof(Vertex)), + vertices.data(), IGLDevice::DynamicDraw); if (!indices.empty()) { - iBuffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, iBuffer); + iBuffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, iBuffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(indices.size() * sizeof(uint16_t)), - indices.data(), IGLDevice::DynamicDraw); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(indices.size() * sizeof(uint16_t)), + indices.data(), IGLDevice::DynamicDraw); } - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); } void GLMapChunk::RenderDepthPass() { SPADES_MARK_FUNCTION(); - Vector3 eye = renderer->renderer->GetSceneDef().viewOrigin; + Vector3 eye = renderer.renderer.GetSceneDef().viewOrigin; if (!realized) return; @@ -328,10 +326,10 @@ namespace spades { bx.max.x += sx; bx.max.y += sy; - if (!renderer->renderer->BoxFrustrumCull(bx)) + if (!renderer.renderer.BoxFrustrumCull(bx)) return; - GLProgram *depthonlyProgram = renderer->depthonlyProgram; + GLProgram *depthonlyProgram = renderer.depthonlyProgram; static GLProgramUniform chunkPosition("chunkPosition"); @@ -343,20 +341,19 @@ namespace spades { positionAttribute(depthonlyProgram); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 3, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)asOFFSET(Vertex, x)); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 3, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)asOFFSET(Vertex, x)); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); - device->BindBuffer(IGLDevice::ElementArrayBuffer, iBuffer); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedShort, NULL); - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, iBuffer); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedShort, NULL); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); } void GLMapChunk::RenderSunlightPass() { SPADES_MARK_FUNCTION(); - Vector3 eye = renderer->renderer->GetSceneDef().viewOrigin; + Vector3 eye = renderer.renderer.GetSceneDef().viewOrigin; if (!realized) return; @@ -387,10 +384,10 @@ namespace spades { bx.max.x += sx; bx.max.y += sy; - if (!renderer->renderer->BoxFrustrumCull(bx)) + if (!renderer.renderer.BoxFrustrumCull(bx)) return; - GLProgram *basicProgram = renderer->basicProgram; + GLProgram *basicProgram = renderer.basicProgram; static GLProgramUniform chunkPosition("chunkPosition"); @@ -411,33 +408,32 @@ namespace spades { normalAttribute(basicProgram); fixedPositionAttribute(basicProgram); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 3, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)asOFFSET(Vertex, x)); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 3, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)asOFFSET(Vertex, x)); if (ambientOcclusionCoordAttribute() != -1) - device->VertexAttribPointer(ambientOcclusionCoordAttribute(), 2, - IGLDevice::UnsignedShort, false, sizeof(Vertex), - (void *)asOFFSET(Vertex, aoX)); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, - sizeof(Vertex), (void *)asOFFSET(Vertex, colorRed)); + device.VertexAttribPointer(ambientOcclusionCoordAttribute(), 2, + IGLDevice::UnsignedShort, false, sizeof(Vertex), + (void *)asOFFSET(Vertex, aoX)); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, + sizeof(Vertex), (void *)asOFFSET(Vertex, colorRed)); if (normalAttribute() != -1) - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)asOFFSET(Vertex, nx)); - - device->VertexAttribPointer(fixedPositionAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)asOFFSET(Vertex, sx)); - - device->BindBuffer(IGLDevice::ArrayBuffer, 0); - device->BindBuffer(IGLDevice::ElementArrayBuffer, iBuffer); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedShort, NULL); - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, + sizeof(Vertex), (void *)asOFFSET(Vertex, nx)); + + device.VertexAttribPointer(fixedPositionAttribute(), 3, IGLDevice::Byte, false, + sizeof(Vertex), (void *)asOFFSET(Vertex, sx)); + + device.BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, iBuffer); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedShort, NULL); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); } void GLMapChunk::RenderDLightPass(std::vector lights) { SPADES_MARK_FUNCTION(); - Vector3 eye = renderer->renderer->GetSceneDef().viewOrigin; + Vector3 eye = renderer.renderer.GetSceneDef().viewOrigin; if (!realized) return; @@ -468,10 +464,10 @@ namespace spades { bx.max.x += sx; bx.max.y += sy; - if (!renderer->renderer->BoxFrustrumCull(bx)) + if (!renderer.renderer.BoxFrustrumCull(bx)) return; - GLProgram *program = renderer->dlightProgram; + GLProgram *program = renderer.dlightProgram; static GLProgramUniform chunkPosition("chunkPosition"); @@ -487,30 +483,30 @@ namespace spades { colorAttribute(program); normalAttribute(program); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 3, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)asOFFSET(Vertex, x)); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, - sizeof(Vertex), (void *)asOFFSET(Vertex, colorRed)); - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)asOFFSET(Vertex, nx)); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 3, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)asOFFSET(Vertex, x)); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, + sizeof(Vertex), (void *)asOFFSET(Vertex, colorRed)); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, sizeof(Vertex), + (void *)asOFFSET(Vertex, nx)); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); - device->BindBuffer(IGLDevice::ElementArrayBuffer, iBuffer); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, iBuffer); for (size_t i = 0; i < lights.size(); i++) { static GLDynamicLightShader lightShader; - lightShader(renderer->renderer, program, lights[i], 1); + lightShader(&renderer.renderer, program, lights[i], 1); if (!lights[i].Cull(bx)) continue; - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedShort, NULL); + device.DrawElements(IGLDevice::Triangles, + static_cast(indices.size()), + IGLDevice::UnsignedShort, NULL); } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); } float GLMapChunk::DistanceFromEye(const Vector3 &eye) { @@ -534,5 +530,5 @@ namespace spades { // return std::max(diff.GetLength() - radius, 0.f); return std::max(dist - ((float)Size * .5f), 0.f); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLMapChunk.h b/Sources/Draw/GLMapChunk.h index 5f6545174..6c13c146c 100644 --- a/Sources/Draw/GLMapChunk.h +++ b/Sources/Draw/GLMapChunk.h @@ -22,11 +22,11 @@ #include +#include "GLDynamicLight.h" +#include "IGLDevice.h" #include #include #include -#include "GLDynamicLight.h" -#include "IGLDevice.h" namespace spades { namespace draw { @@ -51,8 +51,8 @@ namespace spades { uint8_t pad3; }; - GLMapRenderer *renderer; - IGLDevice *device; + GLMapRenderer &renderer; + IGLDevice &device; client::GameMap *map; int chunkX, chunkY, chunkZ; AABB3 aabb; @@ -79,7 +79,7 @@ namespace spades { public: enum { Size = 16, SizeBits = 4 }; - GLMapChunk(GLMapRenderer *, client::GameMap *mp, int cx, int cy, int cz); + GLMapChunk(GLMapRenderer &, client::GameMap *mp, int cx, int cy, int cz); ~GLMapChunk(); void SetNeedsUpdate() { needsUpdate = true; } @@ -92,5 +92,5 @@ namespace spades { void RenderDepthPass(); void RenderDLightPass(std::vector lights); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLMapRenderer.cpp b/Sources/Draw/GLMapRenderer.cpp index cb1d61f29..281ba169e 100644 --- a/Sources/Draw/GLMapRenderer.cpp +++ b/Sources/Draw/GLMapRenderer.cpp @@ -19,40 +19,38 @@ */ #include "GLMapRenderer.h" -#include -#include -#include #include "GLDynamicLightShader.h" #include "GLImage.h" #include "GLMapChunk.h" #include "GLMapShadowRenderer.h" #include "GLProfiler.h" #include "GLProgram.h" -#include "GLProgram.h" #include "GLProgramAttribute.h" #include "GLProgramUniform.h" #include "GLRenderer.h" #include "GLShadowShader.h" #include "IGLDevice.h" +#include +#include +#include namespace spades { namespace draw { - void GLMapRenderer::PreloadShaders(spades::draw::GLRenderer *renderer) { - if (renderer->GetSettings().r_physicalLighting) - renderer->RegisterProgram("Shaders/BasicBlockPhys.program"); + void GLMapRenderer::PreloadShaders(GLRenderer &renderer) { + if (renderer.GetSettings().r_physicalLighting) + renderer.RegisterProgram("Shaders/BasicBlockPhys.program"); else - renderer->RegisterProgram("Shaders/BasicBlock.program"); - renderer->RegisterProgram("Shaders/BasicBlockDepthOnly.program"); - renderer->RegisterProgram("Shaders/BasicBlockDynamicLit.program"); - renderer->RegisterProgram("Shaders/BackFaceBlock.program"); - renderer->RegisterImage("Gfx/AmbientOcclusion.png"); + renderer.RegisterProgram("Shaders/BasicBlock.program"); + renderer.RegisterProgram("Shaders/BasicBlockDepthOnly.program"); + renderer.RegisterProgram("Shaders/BasicBlockDynamicLit.program"); + renderer.RegisterProgram("Shaders/BackFaceBlock.program"); + renderer.RegisterImage("Gfx/AmbientOcclusion.png"); } - GLMapRenderer::GLMapRenderer(client::GameMap *m, GLRenderer *r) : renderer(r), gameMap(m) { + GLMapRenderer::GLMapRenderer(client::GameMap *m, GLRenderer &r) + : renderer(r), device(r.GetGLDevice()), gameMap(m) { SPADES_MARK_FUNCTION(); - device = renderer->GetGLDevice(); - numChunkWidth = gameMap->Width() / GLMapChunk::Size; numChunkHeight = gameMap->Height() / GLMapChunk::Size; numChunkDepth = gameMap->Depth() / GLMapChunk::Size; @@ -63,30 +61,30 @@ namespace spades { chunkInfos = new ChunkRenderInfo[numChunks]; for (int i = 0; i < numChunks; i++) - chunks[i] = new GLMapChunk(this, gameMap, i / numChunkDepth / numChunkHeight, + chunks[i] = new GLMapChunk(*this, gameMap, i / numChunkDepth / numChunkHeight, (i / numChunkDepth) % numChunkHeight, i % numChunkDepth); - if (r->GetSettings().r_physicalLighting) - basicProgram = renderer->RegisterProgram("Shaders/BasicBlockPhys.program"); + if (r.GetSettings().r_physicalLighting) + basicProgram = renderer.RegisterProgram("Shaders/BasicBlockPhys.program"); else - basicProgram = renderer->RegisterProgram("Shaders/BasicBlock.program"); - depthonlyProgram = renderer->RegisterProgram("Shaders/BasicBlockDepthOnly.program"); - dlightProgram = renderer->RegisterProgram("Shaders/BasicBlockDynamicLit.program"); - backfaceProgram = renderer->RegisterProgram("Shaders/BackFaceBlock.program"); - aoImage = (GLImage *)renderer->RegisterImage("Gfx/AmbientOcclusion.png"); + basicProgram = renderer.RegisterProgram("Shaders/BasicBlock.program"); + depthonlyProgram = renderer.RegisterProgram("Shaders/BasicBlockDepthOnly.program"); + dlightProgram = renderer.RegisterProgram("Shaders/BasicBlockDynamicLit.program"); + backfaceProgram = renderer.RegisterProgram("Shaders/BackFaceBlock.program"); + aoImage = renderer.RegisterImage("Gfx/AmbientOcclusion.png").Cast(); static const uint8_t squareVertices[] = {0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1}; - squareVertexBuffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, squareVertexBuffer); - device->BufferData(IGLDevice::ArrayBuffer, sizeof(squareVertices), squareVertices, - IGLDevice::StaticDraw); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + squareVertexBuffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, squareVertexBuffer); + device.BufferData(IGLDevice::ArrayBuffer, sizeof(squareVertices), squareVertices, + IGLDevice::StaticDraw); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); } GLMapRenderer::~GLMapRenderer() { SPADES_MARK_FUNCTION(); - device->DeleteBuffer(squareVertexBuffer); + device.DeleteBuffer(squareVertexBuffer); for (int i = 0; i < numChunks; i++) delete chunks[i]; delete[] chunks; @@ -139,30 +137,30 @@ namespace spades { } void GLMapRenderer::Realize() { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Map Chunks"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Map Chunks"); - Vector3 eye = renderer->GetSceneDef().viewOrigin; + Vector3 eye = renderer.GetSceneDef().viewOrigin; RealizeChunks(eye); } void GLMapRenderer::Prerender() { SPADES_MARK_FUNCTION(); - //depth-only pass + // depth-only pass - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Map"); - Vector3 eye = renderer->GetSceneDef().viewOrigin; + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Map"); + Vector3 eye = renderer.GetSceneDef().viewOrigin; - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); - device->ColorMask(false, false, false, false); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); + device.ColorMask(false, false, false, false); depthonlyProgram->Use(); static GLProgramAttribute positionAttribute("positionAttribute"); positionAttribute(depthonlyProgram); - device->EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); static GLProgramUniform projectionViewMatrix("projectionViewMatrix"); projectionViewMatrix(depthonlyProgram); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); // draw from nearest to farthest int cx = (int)floorf(eye.x) / GLMapChunk::Size; @@ -180,52 +178,50 @@ namespace spades { } } - - device->EnableVertexAttribArray(positionAttribute(), false); - device->ColorMask(true, true, true, true); - + device.EnableVertexAttribArray(positionAttribute(), false); + device.ColorMask(true, true, true, true); } void GLMapRenderer::RenderSunlightPass() { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Map"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Map"); - Vector3 eye = renderer->GetSceneDef().viewOrigin; + Vector3 eye = renderer.GetSceneDef().viewOrigin; // draw back face to avoid cheating. // without this, players can see through blocks by // covering themselves by ones. RenderBackface(); - device->ActiveTexture(0); + device.ActiveTexture(0); aoImage->Bind(IGLDevice::Texture2D); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, 0); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); basicProgram->Use(); static GLShadowShader shadowShader; - shadowShader(renderer, basicProgram, 2); + shadowShader(&renderer, basicProgram, 2); static GLProgramUniform fogDistance("fogDistance"); fogDistance(basicProgram); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); static GLProgramUniform viewSpaceLight("viewSpaceLight"); viewSpaceLight(basicProgram); - Vector3 vspLight = (renderer->GetViewMatrix() * MakeVector4(0, -1, -1, 0)).GetXYZ(); + Vector3 vspLight = (renderer.GetViewMatrix() * MakeVector4(0, -1, -1, 0)).GetXYZ(); viewSpaceLight.SetValue(vspLight.x, vspLight.y, vspLight.z); static GLProgramUniform fogColor("fogColor"); fogColor(basicProgram); - Vector3 fogCol = renderer->GetFogColorForSolidPass(); + Vector3 fogCol = renderer.GetFogColorForSolidPass(); fogCol *= fogCol; // linearize fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); @@ -237,7 +233,7 @@ namespace spades { detailTextureUnif(basicProgram); detailTextureUnif.SetValue(1); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); static GLProgramAttribute positionAttribute("positionAttribute"); static GLProgramAttribute ambientOcclusionCoordAttribute( @@ -252,29 +248,30 @@ namespace spades { normalAttribute(basicProgram); fixedPositionAttribute(basicProgram); - device->EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); if (ambientOcclusionCoordAttribute() != -1) - device->EnableVertexAttribArray(ambientOcclusionCoordAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(ambientOcclusionCoordAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); if (normalAttribute() != -1) - device->EnableVertexAttribArray(normalAttribute(), true); - device->EnableVertexAttribArray(fixedPositionAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(fixedPositionAttribute(), true); static GLProgramUniform projectionViewMatrix("projectionViewMatrix"); projectionViewMatrix(basicProgram); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); static GLProgramUniform viewMatrix("viewMatrix"); viewMatrix(basicProgram); - viewMatrix.SetValue(renderer->GetViewMatrix()); + viewMatrix.SetValue(renderer.GetViewMatrix()); static GLProgramUniform viewOriginVector("viewOriginVector"); viewOriginVector(basicProgram); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); - //RealizeChunks(eye); // should already be realized from the prepass - //TODO maybe add some way of checking if the chunks have been realized for the current eye? Probably just a bool called "alreadyrealized" that gets checked in RealizeChunks + // RealizeChunks(eye); // should already be realized from the prepass + // TODO maybe add some way of checking if the chunks have been realized for the current + // eye? Probably just a bool called "alreadyrealized" that gets checked in RealizeChunks // draw from nearest to farthest int cx = (int)floorf(eye.x) / GLMapChunk::Size; @@ -292,47 +289,47 @@ namespace spades { } } - device->EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); if (ambientOcclusionCoordAttribute() != -1) - device->EnableVertexAttribArray(ambientOcclusionCoordAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(ambientOcclusionCoordAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); if (normalAttribute() != -1) - device->EnableVertexAttribArray(normalAttribute(), false); - device->EnableVertexAttribArray(fixedPositionAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(fixedPositionAttribute(), false); - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, 0); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); } void GLMapRenderer::RenderDynamicLightPass(std::vector lights) { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Map"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Map"); if (lights.empty()) return; - Vector3 eye = renderer->GetSceneDef().viewOrigin; + Vector3 eye = renderer.GetSceneDef().viewOrigin; - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); dlightProgram->Use(); static GLProgramUniform fogDistance("fogDistance"); fogDistance(dlightProgram); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); static GLProgramUniform detailTextureUnif("detailTexture"); detailTextureUnif(dlightProgram); detailTextureUnif.SetValue(0); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); static GLProgramAttribute positionAttribute("positionAttribute"); static GLProgramAttribute colorAttribute("colorAttribute"); @@ -342,24 +339,24 @@ namespace spades { colorAttribute(dlightProgram); normalAttribute(dlightProgram); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); static GLProgramUniform projectionViewMatrix("projectionViewMatrix"); projectionViewMatrix(dlightProgram); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); static GLProgramUniform viewMatrix("viewMatrix"); viewMatrix(dlightProgram); - viewMatrix.SetValue(renderer->GetViewMatrix()); + viewMatrix.SetValue(renderer.GetViewMatrix()); static GLProgramUniform viewOriginVector("viewOriginVector"); viewOriginVector(dlightProgram); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); - //RealizeChunks(eye); // should already be realized from the prepass + // RealizeChunks(eye); // should already be realized from the prepass // draw from nearest to farthest int cx = (int)floorf(eye.x) / GLMapChunk::Size; @@ -380,12 +377,12 @@ namespace spades { } } - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); } void GLMapRenderer::DrawColumnDepth(int cx, int cy, int cz, spades::Vector3 eye) { @@ -446,9 +443,9 @@ namespace spades { } void GLMapRenderer::RenderBackface() { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Back-face"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Back-face"); - IntVector3 eye = renderer->GetSceneDef().viewOrigin.Floor(); + IntVector3 eye = renderer.GetSceneDef().viewOrigin.Floor(); std::vector vertices; std::vector indices; client::GameMap *m = gameMap; @@ -491,7 +488,7 @@ namespace spades { if (vertices.empty()) return; - device->Enable(IGLDevice::CullFace, false); + device.Enable(IGLDevice::CullFace, false); backfaceProgram->Use(); @@ -501,22 +498,21 @@ namespace spades { positionAttribute(backfaceProgram); projectionViewMatrix(backfaceProgram); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); - device->VertexAttribPointer(positionAttribute(), 3, IGLDevice::Short, false, - sizeof(BFVertex), vertices.data()); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); + device.VertexAttribPointer(positionAttribute(), 3, IGLDevice::Short, false, + sizeof(BFVertex), vertices.data()); - device->EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedShort, indices.data()); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedShort, indices.data()); - device->EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); - device->Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::CullFace, true); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLMapRenderer.h b/Sources/Draw/GLMapRenderer.h index 3f0537bea..df7b547f9 100644 --- a/Sources/Draw/GLMapRenderer.h +++ b/Sources/Draw/GLMapRenderer.h @@ -20,11 +20,11 @@ #pragma once +#include "GLDynamicLight.h" +#include "IGLDevice.h" #include #include #include -#include "GLDynamicLight.h" -#include "IGLDevice.h" namespace spades { namespace draw { @@ -37,14 +37,14 @@ namespace spades { friend class GLMapChunk; protected: - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLProgram *depthonlyProgram; GLProgram *basicProgram; GLProgram *dlightProgram; GLProgram *backfaceProgram; - GLImage *aoImage; + Handle aoImage; IGLDevice::UInteger squareVertexBuffer; @@ -78,10 +78,10 @@ namespace spades { void RenderBackface(); public: - GLMapRenderer(client::GameMap *, GLRenderer *); + GLMapRenderer(client::GameMap *, GLRenderer &); virtual ~GLMapRenderer(); - static void PreloadShaders(GLRenderer *); + static void PreloadShaders(GLRenderer &); void GameMapChanged(int x, int y, int z, client::GameMap *); @@ -92,5 +92,5 @@ namespace spades { void RenderSunlightPass(); void RenderDynamicLightPass(std::vector lights); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLMapShadowRenderer.cpp b/Sources/Draw/GLMapShadowRenderer.cpp index d6071f689..66718c0ab 100644 --- a/Sources/Draw/GLMapShadowRenderer.cpp +++ b/Sources/Draw/GLMapShadowRenderer.cpp @@ -19,40 +19,40 @@ */ #include "GLMapShadowRenderer.h" -#include -#include #include "GLProfiler.h" #include "GLRadiosityRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { - GLMapShadowRenderer::GLMapShadowRenderer(GLRenderer *renderer, client::GameMap *map) - : renderer(renderer), device(renderer->GetGLDevice()), map(map) { + GLMapShadowRenderer::GLMapShadowRenderer(GLRenderer &renderer, client::GameMap *map) + : renderer(renderer), device(renderer.GetGLDevice()), map(map) { SPADES_MARK_FUNCTION(); - texture = device->GenTexture(); - coarseTexture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, texture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA, map->Width(), - map->Height(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); - - device->BindTexture(IGLDevice::Texture2D, coarseTexture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, map->Width() / CoarseSize, - map->Height() / CoarseSize, 0, IGLDevice::BGRA, - IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); + texture = device.GenTexture(); + coarseTexture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, texture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA, map->Width(), map->Height(), + 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); + + device.BindTexture(IGLDevice::Texture2D, coarseTexture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, map->Width() / CoarseSize, + map->Height() / CoarseSize, 0, IGLDevice::BGRA, + IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); w = map->Width(); h = map->Height(); @@ -71,21 +71,21 @@ namespace spades { GLMapShadowRenderer::~GLMapShadowRenderer() { SPADES_MARK_FUNCTION(); - device->DeleteTexture(texture); - device->DeleteTexture(coarseTexture); + device.DeleteTexture(texture); + device.DeleteTexture(coarseTexture); } void GLMapShadowRenderer::Update() { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Terrain Shadow Map"); - GLRadiosityRenderer *radiosity = renderer->GetRadiosityRenderer(); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Terrain Shadow Map"); + GLRadiosityRenderer *radiosity = renderer.GetRadiosityRenderer(); std::vector coarseUpdateBitmap; coarseUpdateBitmap.resize(coarseBitmap.size()); std::fill(coarseUpdateBitmap.begin(), coarseUpdateBitmap.end(), 0); - device->BindTexture(IGLDevice::Texture2D, texture); + device.BindTexture(IGLDevice::Texture2D, texture); for (size_t i = 0; i < updateBitmap.size(); i++) { int y = static_cast(i / updateBitmapPitch); int x = static_cast((i - y * updateBitmapPitch) * 32); @@ -118,8 +118,8 @@ namespace spades { coarseUpdateBitmap[((x + j) >> CoarseBits) + (y >> CoarseBits) * (w >> CoarseBits)] = 1; - device->TexSubImage2D(IGLDevice::Texture2D, 0, x, y, 32, 1, IGLDevice::RGBA, - IGLDevice::UnsignedByte, pixels); + device.TexSubImage2D(IGLDevice::Texture2D, 0, x, y, 32, 1, IGLDevice::RGBA, + IGLDevice::UnsignedByte, pixels); } updateBitmap[i] = 0; @@ -163,12 +163,13 @@ namespace spades { } } if (coarseUpdated) { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Coarse Shadow Map Upload"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Coarse Shadow Map Upload"); - device->BindTexture(IGLDevice::Texture2D, coarseTexture); - device->TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, w >> CoarseBits, - h >> CoarseBits, IGLDevice::BGRA, IGLDevice::UnsignedByte, - coarseBitmap.data()); + device.BindTexture(IGLDevice::Texture2D, coarseTexture); + device.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, w >> CoarseBits, + h >> CoarseBits, IGLDevice::BGRA, IGLDevice::UnsignedByte, + coarseBitmap.data()); } } } @@ -226,5 +227,5 @@ namespace spades { MarkUpdate(x, y - z); MarkUpdate(x, y - z - 1); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLMapShadowRenderer.h b/Sources/Draw/GLMapShadowRenderer.h index fa2e6e6b3..3d8d0ee83 100644 --- a/Sources/Draw/GLMapShadowRenderer.h +++ b/Sources/Draw/GLMapShadowRenderer.h @@ -38,8 +38,8 @@ namespace spades { enum { CoarseSize = 8, CoarseBits = 3 }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; client::GameMap *map; IGLDevice::UInteger texture; IGLDevice::UInteger coarseTexture; @@ -56,7 +56,7 @@ namespace spades { void MarkUpdate(int x, int y); public: - GLMapShadowRenderer(GLRenderer *renderer, client::GameMap *map); + GLMapShadowRenderer(GLRenderer &renderer, client::GameMap *map); ~GLMapShadowRenderer(); void GameMapChanged(int x, int y, int z, client::GameMap *); @@ -66,5 +66,5 @@ namespace spades { IGLDevice::UInteger GetTexture() { return texture; } IGLDevice::UInteger GetCoarseTexture() { return coarseTexture; } }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLModel.cpp b/Sources/Draw/GLModel.cpp index 360849741..f90d8defb 100644 --- a/Sources/Draw/GLModel.cpp +++ b/Sources/Draw/GLModel.cpp @@ -23,5 +23,5 @@ namespace spades { namespace draw { GLModel::GLModel() { renderId = -1; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLModel.h b/Sources/Draw/GLModel.h index 9906d13b6..64f58ed6b 100644 --- a/Sources/Draw/GLModel.h +++ b/Sources/Draw/GLModel.h @@ -22,9 +22,9 @@ #include +#include "GLDynamicLight.h" #include #include -#include "GLDynamicLight.h" namespace spades { namespace draw { @@ -55,5 +55,5 @@ namespace spades { // members used when rendering by GLModelRenderer int renderId; }; - } -}; + } // namespace draw +}; // namespace spades diff --git a/Sources/Draw/GLModelManager.cpp b/Sources/Draw/GLModelManager.cpp index dc6891128..68a000890 100644 --- a/Sources/Draw/GLModelManager.cpp +++ b/Sources/Draw/GLModelManager.cpp @@ -30,41 +30,27 @@ namespace spades { namespace draw { - GLModelManager::GLModelManager(GLRenderer *r) { - SPADES_MARK_FUNCTION(); - - renderer = r; - } - GLModelManager::~GLModelManager() { - SPADES_MARK_FUNCTION(); - - for (std::map::iterator it = models.begin(); it != models.end(); - it++) { - it->second->Release(); - } - } + GLModelManager::GLModelManager(GLRenderer &r) : renderer{r} { SPADES_MARK_FUNCTION(); } + GLModelManager::~GLModelManager() { SPADES_MARK_FUNCTION(); } - GLModel *GLModelManager::RegisterModel(const char *name) { + Handle GLModelManager::RegisterModel(const char *name) { SPADES_MARK_FUNCTION(); - std::map::iterator it; - it = models.find(std::string(name)); + auto it = models.find(std::string(name)); if (it == models.end()) { - GLModel *m = CreateModel(name); + Handle m = CreateModel(name); models[name] = m; - m->AddRef(); return m; } - it->second->AddRef(); // model manager owns this reference return it->second; } - GLModel *GLModelManager::CreateModel(const char *name) { + Handle GLModelManager::CreateModel(const char *name) { SPADES_MARK_FUNCTION(); - Handle voxelModel{VoxelModelLoader::Load(name), false}; + auto voxelModel = VoxelModelLoader::Load(name); - return static_cast(renderer->CreateModelOptimized(voxelModel)); + return renderer.CreateModelOptimized(*voxelModel).Cast(); } void GLModelManager::ClearCache() { models.clear(); } diff --git a/Sources/Draw/GLModelManager.h b/Sources/Draw/GLModelManager.h index 6eec81461..fddbf64f8 100644 --- a/Sources/Draw/GLModelManager.h +++ b/Sources/Draw/GLModelManager.h @@ -24,20 +24,21 @@ #include #include +#include namespace spades { namespace draw { class GLModel; class GLRenderer; class GLModelManager { - GLRenderer *renderer; - std::map models; - GLModel *CreateModel(const char *); + GLRenderer &renderer; + std::map> models; + Handle CreateModel(const char *); public: - GLModelManager(GLRenderer *); + GLModelManager(GLRenderer &); ~GLModelManager(); - GLModel *RegisterModel(const char *); + Handle RegisterModel(const char *); void ClearCache(); }; diff --git a/Sources/Draw/GLModelRenderer.cpp b/Sources/Draw/GLModelRenderer.cpp index 3fbbd332e..078fefa98 100644 --- a/Sources/Draw/GLModelRenderer.cpp +++ b/Sources/Draw/GLModelRenderer.cpp @@ -19,14 +19,14 @@ */ #include "GLModelRenderer.h" -#include #include "GLModel.h" #include "GLProfiler.h" #include "GLRenderer.h" +#include namespace spades { namespace draw { - GLModelRenderer::GLModelRenderer(GLRenderer *r) : renderer(r), device(r->GetGLDevice()) { + GLModelRenderer::GLModelRenderer(GLRenderer &r) : renderer(r), device(r.GetGLDevice()) { SPADES_MARK_FUNCTION(); modelCount = 0; } @@ -52,8 +52,9 @@ namespace spades { void GLModelRenderer::RenderShadowMapPass() { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Model [%d model(s), %d unique model type(s)]", modelCount, - (int)models.size()); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Model [%d model(s), %d unique model type(s)]", modelCount, + (int)models.size()); int numModels = 0; for (size_t i = 0; i < models.size(); i++) { @@ -69,10 +70,11 @@ namespace spades { } void GLModelRenderer::Prerender(bool ghostPass) { - device->ColorMask(false, false, false, false); + device.ColorMask(false, false, false, false); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Model [%d model(s), %d unique model type(s)]", modelCount, - (int)models.size()); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Model [%d model(s), %d unique model type(s)]", modelCount, + (int)models.size()); int numModels = 0; for (size_t i = 0; i < models.size(); i++) { @@ -81,14 +83,15 @@ namespace spades { model->Prerender(m.params, ghostPass); numModels += (int)m.params.size(); } - device->ColorMask(true, true, true, true); + device.ColorMask(true, true, true, true); } void GLModelRenderer::RenderSunlightPass(bool ghostPass) { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Model [%d model(s), %d unique model type(s)]", modelCount, - (int)models.size()); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Model [%d model(s), %d unique model type(s)]", modelCount, + (int)models.size()); for (size_t i = 0; i < models.size(); i++) { RenderModel &m = models[i]; @@ -101,8 +104,9 @@ namespace spades { void GLModelRenderer::RenderDynamicLightPass(std::vector lights) { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Model [%d model(s), %d unique model type(s)]", modelCount, - (int)models.size()); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Model [%d model(s), %d unique model type(s)]", modelCount, + (int)models.size()); if (!lights.empty()) { @@ -125,5 +129,5 @@ namespace spades { modelCount = 0; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLModelRenderer.h b/Sources/Draw/GLModelRenderer.h index 578cc442a..6100c3f3e 100644 --- a/Sources/Draw/GLModelRenderer.h +++ b/Sources/Draw/GLModelRenderer.h @@ -22,10 +22,10 @@ #include -#include -#include #include "GLDynamicLight.h" #include "IGLDevice.h" +#include +#include namespace spades { namespace draw { @@ -35,8 +35,8 @@ namespace spades { class GLModelRenderer { friend class GLSparseShadowMapRenderer; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; struct RenderModel { GLModel *model; @@ -47,7 +47,7 @@ namespace spades { int modelCount; public: - GLModelRenderer(GLRenderer *); + GLModelRenderer(GLRenderer &); ~GLModelRenderer(); void AddModel(GLModel *model, const client::ModelRenderParam ¶m); @@ -60,5 +60,5 @@ namespace spades { void Clear(); }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLNonlinearizeFilter.cpp b/Sources/Draw/GLNonlinearizeFilter.cpp index ca00f5a85..0cf9499b0 100644 --- a/Sources/Draw/GLNonlinearizeFilter.cpp +++ b/Sources/Draw/GLNonlinearizeFilter.cpp @@ -20,8 +20,6 @@ #include -#include -#include #include "GLNonlinearizeFilter.h" #include "GLProgram.h" #include "GLProgramAttribute.h" @@ -29,24 +27,28 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "IGLDevice.h" +#include +#include #include namespace spades { namespace draw { - GLNonlinearlizeFilter::GLNonlinearlizeFilter(GLRenderer *renderer) : renderer(renderer) { - lens = renderer->RegisterProgram("Shaders/PostFilters/Nonlinearize.program"); + GLNonlinearlizeFilter::GLNonlinearlizeFilter(GLRenderer &renderer) : renderer(renderer) { + lens = renderer.RegisterProgram("Shaders/PostFilters/Nonlinearize.program"); } GLColorBuffer GLNonlinearlizeFilter::Filter(GLColorBuffer input) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); + + GLColorBuffer output = input.GetManager()->CreateBufferHandle(); static GLProgramAttribute lensPosition("positionAttribute"); static GLProgramUniform lensTexture("mainTexture"); static GLProgramUniform lensGamma("gamma"); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); lensPosition(lens); lensTexture(lens); @@ -55,19 +57,18 @@ namespace spades { lens->Use(); lensTexture.SetValue(0); - lensGamma.SetValue(1.f / (float)renderer->GetSettings().r_hdrGamma); + lensGamma.SetValue(1.f / (float)renderer.GetSettings().r_hdrGamma); // composite to the final image - GLColorBuffer output = input.GetManager()->CreateBufferHandle(); qr.SetCoordAttributeIndex(lensPosition()); - dev->BindTexture(IGLDevice::Texture2D, input.GetTexture()); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, output.GetWidth(), output.GetHeight()); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); qr.Draw(); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.BindTexture(IGLDevice::Texture2D, 0); return output; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLNonlinearizeFilter.h b/Sources/Draw/GLNonlinearizeFilter.h index 159b922c6..9581d6f7f 100644 --- a/Sources/Draw/GLNonlinearizeFilter.h +++ b/Sources/Draw/GLNonlinearizeFilter.h @@ -27,12 +27,12 @@ namespace spades { class GLRenderer; class GLProgram; class GLNonlinearlizeFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLProgram *lens; public: - GLNonlinearlizeFilter(GLRenderer *); + GLNonlinearlizeFilter(GLRenderer &); GLColorBuffer Filter(GLColorBuffer); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLOptimizedVoxelModel.cpp b/Sources/Draw/GLOptimizedVoxelModel.cpp index d36160ee1..0fce1cdeb 100644 --- a/Sources/Draw/GLOptimizedVoxelModel.cpp +++ b/Sources/Draw/GLOptimizedVoxelModel.cpp @@ -20,10 +20,6 @@ #include -#include -#include -#include -#include #include "CellToTriangle.h" #include "GLDynamicLightShader.h" #include "GLImage.h" @@ -35,43 +31,45 @@ #include "GLShadowMapShader.h" #include "GLShadowShader.h" #include "IGLShadowMapRenderer.h" +#include +#include +#include +#include namespace spades { namespace draw { - void GLOptimizedVoxelModel::PreloadShaders(spades::draw::GLRenderer *renderer) { - renderer->RegisterProgram("Shaders/OptimizedVoxelModel.program"); - renderer->RegisterProgram("Shaders/OptimizedVoxelModelDynamicLit.program"); - renderer->RegisterProgram("Shaders/OptimizedVoxelModelShadowMap.program"); - renderer->RegisterImage("Gfx/AmbientOcclusion.png"); + void GLOptimizedVoxelModel::PreloadShaders(GLRenderer &renderer) { + renderer.RegisterProgram("Shaders/OptimizedVoxelModel.program"); + renderer.RegisterProgram("Shaders/OptimizedVoxelModelDynamicLit.program"); + renderer.RegisterProgram("Shaders/OptimizedVoxelModelShadowMap.program"); + renderer.RegisterImage("Gfx/AmbientOcclusion.png"); } - GLOptimizedVoxelModel::GLOptimizedVoxelModel(VoxelModel *m, GLRenderer *r) { + GLOptimizedVoxelModel::GLOptimizedVoxelModel(VoxelModel *m, GLRenderer &r) + : renderer{r}, device{r.GetGLDevice()} { SPADES_MARK_FUNCTION(); - renderer = r; - device = r->GetGLDevice(); - BuildVertices(m); GenerateTexture(); - program = renderer->RegisterProgram("Shaders/OptimizedVoxelModel.program"); + program = renderer.RegisterProgram("Shaders/OptimizedVoxelModel.program"); dlightProgram = - renderer->RegisterProgram("Shaders/OptimizedVoxelModelDynamicLit.program"); + renderer.RegisterProgram("Shaders/OptimizedVoxelModelDynamicLit.program"); shadowMapProgram = - renderer->RegisterProgram("Shaders/OptimizedVoxelModelShadowMap.program"); - aoImage = (GLImage *)renderer->RegisterImage("Gfx/AmbientOcclusion.png"); - - buffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(vertices.size() * sizeof(Vertex)), - vertices.data(), IGLDevice::StaticDraw); - - idxBuffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, idxBuffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(indices.size() * sizeof(uint32_t)), - indices.data(), IGLDevice::StaticDraw); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + renderer.RegisterProgram("Shaders/OptimizedVoxelModelShadowMap.program"); + aoImage = renderer.RegisterImage("Gfx/AmbientOcclusion.png").Cast(); + + buffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(vertices.size() * sizeof(Vertex)), + vertices.data(), IGLDevice::StaticDraw); + + idxBuffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, idxBuffer); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(indices.size() * sizeof(uint32_t)), + indices.data(), IGLDevice::StaticDraw); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); origin = m->GetOrigin(); origin -= .5f; // (0,0,0) is center of voxel (0,0,0) @@ -96,9 +94,8 @@ namespace spades { GLOptimizedVoxelModel::~GLOptimizedVoxelModel() { SPADES_MARK_FUNCTION(); - image->Release(); - device->DeleteBuffer(idxBuffer); - device->DeleteBuffer(buffer); + device.DeleteBuffer(idxBuffer); + device.DeleteBuffer(buffer); } void GLOptimizedVoxelModel::GenerateTexture() { @@ -137,7 +134,7 @@ namespace spades { std::vector().swap(bmpIndex); - image = static_cast(renderer->CreateImage(bmp)); + image = renderer.CreateImage(*bmp).Cast(); } uint8_t GLOptimizedVoxelModel::calcAOID(VoxelModel *m, int x, int y, int z, int ux, int uy, @@ -355,7 +352,8 @@ namespace spades { p3 += nn; SPAssert(!model->IsSolid(p3.x, p3.y, p3.z)); - uint8_t aoId = calcAOID(model, p3.x, p3.y, p3.z, ux, uy, uz, vx, vy, vz); + uint8_t aoId = + calcAOID(model, p3.x, p3.y, p3.z, ux, uy, uz, vx, vy, vz); if (aoId % 16 == 15) { // These AOIDs are allocated for non-default materials. @@ -535,13 +533,13 @@ namespace spades { GLOptimizedVoxelModel::RenderShadowMapPass(std::vector params) { SPADES_MARK_FUNCTION(); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); shadowMapProgram->Use(); static GLShadowMapShader shadowMapShader; - shadowMapShader(renderer, shadowMapProgram, 0); + shadowMapShader(&renderer, shadowMapProgram, 0); static GLProgramUniform modelOrigin("modelOrigin"); modelOrigin(shadowMapProgram); @@ -554,20 +552,20 @@ namespace spades { positionAttribute(shadowMapProgram); normalAttribute(shadowMapProgram); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)0); if (normalAttribute() != -1) { - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)8); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, + sizeof(Vertex), (void *)8); } - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); if (normalAttribute() != -1) - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); for (size_t i = 0; i < params.size(); i++) { const client::ModelRenderParam ¶m = params[i]; @@ -583,7 +581,7 @@ namespace spades { if (param.depthHack) continue; - if (!renderer->GetShadowMapRenderer()->SphereCull(param.matrix.GetOrigin(), rad)) { + if (!renderer.GetShadowMapRenderer()->SphereCull(param.matrix.GetOrigin(), rad)) { continue; } @@ -600,53 +598,53 @@ namespace spades { modelNormalMatrix(shadowMapProgram); modelNormalMatrix.SetValue(modelMatrix); - device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, - (void *)0); + device.DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, + (void *)0); } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); if (normalAttribute() != -1) - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); } void GLOptimizedVoxelModel::RenderSunlightPass(std::vector params, bool ghostPass) { SPADES_MARK_FUNCTION(); - bool mirror = renderer->IsRenderingMirror(); + bool mirror = renderer.IsRenderingMirror(); - device->ActiveTexture(0); + device.ActiveTexture(0); aoImage->Bind(IGLDevice::Texture2D); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); - device->ActiveTexture(1); + device.ActiveTexture(1); image->Bind(IGLDevice::Texture2D); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); program->Use(); static GLShadowShader shadowShader; - shadowShader(renderer, program, 2); + shadowShader(&renderer, program, 2); static GLProgramUniform fogDistance("fogDistance"); fogDistance(program); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); static GLProgramUniform fogColor("fogColor"); fogColor(program); - Vector3 fogCol = renderer->GetFogColorForSolidPass(); + Vector3 fogCol = renderer.GetFogColorForSolidPass(); fogCol *= fogCol; // linearize fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); @@ -674,7 +672,7 @@ namespace spades { static GLProgramUniform viewOriginVector("viewOriginVector"); viewOriginVector(program); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); // setup attributes @@ -686,20 +684,20 @@ namespace spades { textureCoordAttribute(program); normalAttribute(program); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)0); - device->VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false, - sizeof(Vertex), (void *)4); - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)8); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)0); + device.VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false, + sizeof(Vertex), (void *)4); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, sizeof(Vertex), + (void *)8); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(textureCoordAttribute(), true); - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(textureCoordAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); for (size_t i = 0; i < params.size(); i++) { const client::ModelRenderParam ¶m = params[i]; @@ -714,7 +712,7 @@ namespace spades { // frustrum cull float rad = radius; rad *= param.matrix.GetAxis(0).GetLength(); - if (!renderer->SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { + if (!renderer.SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { continue; } @@ -725,12 +723,12 @@ namespace spades { Matrix4 modelMatrix = param.matrix; static GLProgramUniform projectionViewModelMatrix("projectionViewModelMatrix"); projectionViewModelMatrix(program); - projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() * + projectionViewModelMatrix.SetValue(renderer.GetProjectionViewMatrix() * modelMatrix); static GLProgramUniform viewModelMatrix("viewModelMatrix"); viewModelMatrix(program); - viewModelMatrix.SetValue(renderer->GetViewMatrix() * modelMatrix); + viewModelMatrix.SetValue(renderer.GetViewMatrix() * modelMatrix); static GLProgramUniform modelMatrixU("modelMatrix"); modelMatrixU(program); @@ -748,26 +746,26 @@ namespace spades { modelOpacity.SetValue(param.opacity); if (param.depthHack) { - device->DepthRange(0.f, 0.1f); + device.DepthRange(0.f, 0.1f); } - device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, - (void *)0); + device.DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, + (void *)0); if (param.depthHack) { - device->DepthRange(0.f, 1.f); + device.DepthRange(0.f, 1.f); } } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(textureCoordAttribute(), false); - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(textureCoordAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, 0); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); } void @@ -775,22 +773,22 @@ namespace spades { std::vector lights) { SPADES_MARK_FUNCTION(); - bool mirror = renderer->IsRenderingMirror(); + bool mirror = renderer.IsRenderingMirror(); - device->ActiveTexture(0); + device.ActiveTexture(0); aoImage->Bind(IGLDevice::Texture2D); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); - device->ActiveTexture(1); + device.ActiveTexture(1); image->Bind(IGLDevice::Texture2D); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); dlightProgram->Use(); @@ -798,7 +796,7 @@ namespace spades { static GLProgramUniform fogDistance("fogDistance"); fogDistance(dlightProgram); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); static GLProgramUniform modelOrigin("modelOrigin"); modelOrigin(dlightProgram); @@ -814,7 +812,7 @@ namespace spades { static GLProgramUniform viewOriginVector("viewOriginVector"); viewOriginVector(dlightProgram); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); // setup attributes @@ -826,20 +824,20 @@ namespace spades { textureCoordAttribute(dlightProgram); normalAttribute(dlightProgram); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)0); - device->VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false, - sizeof(Vertex), (void *)4); - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)8); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)0); + device.VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false, + sizeof(Vertex), (void *)4); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, sizeof(Vertex), + (void *)8); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(textureCoordAttribute(), true); - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(textureCoordAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); for (size_t i = 0; i < params.size(); i++) { const client::ModelRenderParam ¶m = params[i]; @@ -853,7 +851,7 @@ namespace spades { // frustrum cull float rad = radius; rad *= param.matrix.GetAxis(0).GetLength(); - if (!renderer->SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { + if (!renderer.SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { continue; } @@ -864,12 +862,12 @@ namespace spades { Matrix4 modelMatrix = param.matrix; static GLProgramUniform projectionViewModelMatrix("projectionViewModelMatrix"); projectionViewModelMatrix(dlightProgram); - projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() * + projectionViewModelMatrix.SetValue(renderer.GetProjectionViewMatrix() * modelMatrix); static GLProgramUniform viewModelMatrix("viewModelMatrix"); viewModelMatrix(dlightProgram); - viewModelMatrix.SetValue(renderer->GetViewMatrix() * modelMatrix); + viewModelMatrix.SetValue(renderer.GetViewMatrix() * modelMatrix); static GLProgramUniform modelMatrixU("modelMatrix"); modelMatrixU(dlightProgram); @@ -883,29 +881,29 @@ namespace spades { modelNormalMatrix.SetValue(modelMatrix); if (param.depthHack) { - device->DepthRange(0.f, 0.1f); + device.DepthRange(0.f, 0.1f); } for (size_t i = 0; i < lights.size(); i++) { if (!lights[i].SphereCull(param.matrix.GetOrigin(), rad)) continue; - dlightShader(renderer, dlightProgram, lights[i], 2); + dlightShader(&renderer, dlightProgram, lights[i], 2); - device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, - (void *)0); + device.DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, + (void *)0); } if (param.depthHack) { - device->DepthRange(0.f, 1.f); + device.DepthRange(0.f, 1.f); } } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(textureCoordAttribute(), false); - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(textureCoordAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(0); + device.ActiveTexture(0); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLOptimizedVoxelModel.h b/Sources/Draw/GLOptimizedVoxelModel.h index 0820f2e56..f670daadb 100644 --- a/Sources/Draw/GLOptimizedVoxelModel.h +++ b/Sources/Draw/GLOptimizedVoxelModel.h @@ -46,13 +46,14 @@ namespace spades { uint8_t padding2; }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + // TODO: `*this` might outlive `GLRenderer`. Needs a safeguard! + IGLDevice &device; GLProgram *program; GLProgram *dlightProgram; GLProgram *shadowMapProgram; - GLImage *image; - GLImage *aoImage; + Handle image; + Handle aoImage; IGLDevice::UInteger buffer; IGLDevice::UInteger idxBuffer; @@ -82,9 +83,9 @@ namespace spades { ~GLOptimizedVoxelModel(); public: - GLOptimizedVoxelModel(VoxelModel *, GLRenderer *r); + GLOptimizedVoxelModel(VoxelModel *, GLRenderer &r); - static void PreloadShaders(GLRenderer *); + static void PreloadShaders(GLRenderer &); void Prerender(std::vector params, bool ghostPass) override; @@ -98,5 +99,5 @@ namespace spades { AABB3 GetBoundingBox() override { return boundingBox; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProfiler.cpp b/Sources/Draw/GLProfiler.cpp index 0003c3756..55a157b16 100644 --- a/Sources/Draw/GLProfiler.cpp +++ b/Sources/Draw/GLProfiler.cpp @@ -23,11 +23,11 @@ #include #include #include +#include #include #include #include #include -#include #include "GLProfiler.h" @@ -54,7 +54,7 @@ namespace spades { .count() / 1000000.0; } - } + } // namespace struct GLProfiler::Measurement { double totalWallClockTime = 0.0; @@ -86,7 +86,7 @@ namespace spades { GLProfiler::GLProfiler(GLRenderer &renderer) : m_settings{renderer.GetSettings()}, m_renderer{renderer}, - m_device{*renderer.GetGLDevice()}, + m_device{renderer.GetGLDevice()}, m_active{false}, m_lastSaveTime{0.0}, m_shouldSaveThisFrame{false}, @@ -197,27 +197,29 @@ namespace spades { struct Traverser { GLProfiler &self; Traverser(GLProfiler &self) : self{self} {} - void Traverse(Phase &phase, stmp::optional> base) { + void Traverse(Phase &phase, stmp::optional> base) { if (!phase.queryObjectIndices) { return; } if (base) { auto baseIndices = *(*base).first.queryObjectIndices; - (*phase.queryObjectIndices).second = (*base).second ? baseIndices.second : baseIndices.first; + (*phase.queryObjectIndices).second = + (*base).second ? baseIndices.second : baseIndices.first; } auto it = phase.subphases.begin(); while (it != phase.subphases.end() && !it->queryObjectIndices) { ++it; } while (it != phase.subphases.end()) { - auto it2 = it; ++it2; + auto it2 = it; + ++it2; while (it2 != phase.subphases.end() && !it2->queryObjectIndices) { ++it2; } if (it2 == phase.subphases.end()) { - Traverse(*it, std::pair{phase, true}); + Traverse(*it, std::pair{phase, true}); } else { - Traverse(*it, std::pair{*it2, false}); + Traverse(*it, std::pair{*it2, false}); } it = it2; } @@ -486,7 +488,7 @@ namespace spades { factor{factor} {} void DrawText(const char *str) { - client::IImage *font = self.m_font; + client::IImage &font = *self.m_font; while (*str) { char c = *str; @@ -547,7 +549,7 @@ namespace spades { float barScale = 4000.0 * self.m_settings.r_debugTimingOutputBarScale; float boxWidth = static_cast(time * barScale); float childBoxWidth = static_cast(subphaseTime * barScale); - client::IImage *white = self.m_white; + client::IImage &white = *self.m_white; renderer.SetColorAlphaPremultiplied(Vector4{0.0f, 0.0f, 0.0f, 0.5f}); renderer.DrawImage(white, AABB2{cursor.x, cursor.y + 1.0f, boxWidth, 8.0f}); @@ -613,5 +615,5 @@ namespace spades { m_profiler.EndPhase(); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProfiler.h b/Sources/Draw/GLProfiler.h index 2f0756eb4..3517b31c9 100644 --- a/Sources/Draw/GLProfiler.h +++ b/Sources/Draw/GLProfiler.h @@ -49,8 +49,8 @@ namespace spades { bool m_shouldSaveThisFrame; bool m_waitingTimerQueryResult; - client::IImage *m_font; - client::IImage *m_white; + Handle m_font; + Handle m_white; Stopwatch m_stopwatch; @@ -96,5 +96,5 @@ namespace spades { ~Context(); }; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgram.cpp b/Sources/Draw/GLProgram.cpp index 1cff5fe4f..7ff8d51f1 100644 --- a/Sources/Draw/GLProgram.cpp +++ b/Sources/Draw/GLProgram.cpp @@ -21,10 +21,10 @@ #include #include -#include -#include #include "GLProgram.h" #include "GLShader.h" +#include +#include namespace spades { namespace draw { @@ -37,9 +37,9 @@ namespace spades { device->DeleteProgram(handle); } - void GLProgram::Attach(spades::draw::GLShader *shader) { + void GLProgram::Attach(GLShader &shader) { SPADES_MARK_FUNCTION(); - device->AttachShader(handle, shader->GetHandle()); + this->Attach(shader.GetHandle()); } void GLProgram::Attach(IGLDevice::UInteger shader) { @@ -98,5 +98,5 @@ namespace spades { SPADES_MARK_FUNCTION(); device->UseProgram(handle); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgram.h b/Sources/Draw/GLProgram.h index 6e4f0f756..ae666064e 100644 --- a/Sources/Draw/GLProgram.h +++ b/Sources/Draw/GLProgram.h @@ -36,7 +36,7 @@ namespace spades { GLProgram(IGLDevice *, std::string name = "(unnamed)"); ~GLProgram(); - void Attach(GLShader *); + void Attach(GLShader &); void Attach(IGLDevice::UInteger shader); void Link(); @@ -49,5 +49,5 @@ namespace spades { IGLDevice *GetDevice() const { return device; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgramAttribute.cpp b/Sources/Draw/GLProgramAttribute.cpp index aab7c7c22..fcbe352be 100644 --- a/Sources/Draw/GLProgramAttribute.cpp +++ b/Sources/Draw/GLProgramAttribute.cpp @@ -43,5 +43,5 @@ namespace spades { } return loc; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgramAttribute.h b/Sources/Draw/GLProgramAttribute.h index f589fc2a1..c7959b6f4 100644 --- a/Sources/Draw/GLProgramAttribute.h +++ b/Sources/Draw/GLProgramAttribute.h @@ -36,5 +36,5 @@ namespace spades { int operator()() { return loc; } int operator()(GLProgram *); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgramManager.cpp b/Sources/Draw/GLProgramManager.cpp index 692397e5f..8e1428c1e 100644 --- a/Sources/Draw/GLProgramManager.cpp +++ b/Sources/Draw/GLProgramManager.cpp @@ -19,11 +19,6 @@ */ #include "GLProgramManager.h" -#include -#include -#include -#include -#include #include "GLDynamicLightShader.h" #include "GLProgram.h" #include "GLSettings.h" @@ -31,133 +26,132 @@ #include "GLShadowMapShader.h" #include "GLShadowShader.h" #include "IGLShadowMapRenderer.h" +#include +#include +#include +#include +#include +#include namespace spades { namespace draw { - GLProgramManager::GLProgramManager(IGLDevice *d, IGLShadowMapRenderer *smr, + GLProgramManager::GLProgramManager(IGLDevice &d, IGLShadowMapRenderer *smr, GLSettings &settings) : device(d), shadowMapRenderer(smr), settings(settings) { SPADES_MARK_FUNCTION(); } - GLProgramManager::~GLProgramManager() { - SPADES_MARK_FUNCTION(); - - for (std::map::iterator it = programs.begin(); - it != programs.end(); it++) { - delete it->second; - } - for (std::map::iterator it = shaders.begin(); - it != shaders.end(); it++) { - delete it->second; - } - } + GLProgramManager::~GLProgramManager() { SPADES_MARK_FUNCTION(); } GLProgram *GLProgramManager::RegisterProgram(const std::string &name) { SPADES_MARK_FUNCTION(); - std::map::iterator it; - it = programs.find(name); + auto it = programs.find(name); if (it == programs.end()) { - GLProgram *prog = CreateProgram(name); - programs[name] = prog; - return prog; + auto program = CreateProgram(name); + GLProgram *programPtr = program.get(); + + programs[name] = std::move(program); + + return programPtr; } else { - return it->second; + return it->second.get(); } } GLShader *GLProgramManager::RegisterShader(const std::string &name) { SPADES_MARK_FUNCTION(); - std::map::iterator it; - it = shaders.find(name); + auto it = shaders.find(name); if (it == shaders.end()) { - GLShader *prog = CreateShader(name); - shaders[name] = prog; - return prog; + auto shader = CreateShader(name); + GLShader *shaderPtr = shader.get(); + + shaders[name] = std::move(shader); + + return shaderPtr; } else { - return it->second; + return it->second.get(); } } - GLProgram *GLProgramManager::CreateProgram(const std::string &name) { + std::unique_ptr GLProgramManager::CreateProgram(const std::string &name) { SPADES_MARK_FUNCTION(); SPLog("Loading GLSL program '%s'", name.c_str()); std::string text = FileManager::ReadAllBytes(name.c_str()); std::vector lines = SplitIntoLines(text); - GLProgram *p = new GLProgram(device, name); + auto p = stmp::make_unique(&device, name); for (size_t i = 0; i < lines.size(); i++) { std::string text = TrimSpaces(lines[i]); if (text.empty()) - break; + break; // TODO: Probably wrong, but unconfirmed if (text == "*shadow*") { std::vector shaders = GLShadowShader::RegisterShader(this, settings, false); - for (size_t i = 0; i < shaders.size(); i++) - p->Attach(shaders[i]); - continue; + for (GLShader *shader : shaders) { + p->Attach(*shader); + } } else if (text == "*shadow-lite*") { std::vector shaders = GLShadowShader::RegisterShader(this, settings, false, true); - for (size_t i = 0; i < shaders.size(); i++) - p->Attach(shaders[i]); - continue; + for (GLShader *shader : shaders) { + p->Attach(*shader); + } } else if (text == "*shadow-variance*") { std::vector shaders = GLShadowShader::RegisterShader(this, settings, true); - for (size_t i = 0; i < shaders.size(); i++) - p->Attach(shaders[i]); - continue; + for (GLShader *shader : shaders) { + p->Attach(*shader); + } } else if (text == "*dlight*") { std::vector shaders = GLDynamicLightShader::RegisterShader(this); - for (size_t i = 0; i < shaders.size(); i++) - p->Attach(shaders[i]); - continue; + for (GLShader *shader : shaders) { + p->Attach(*shader); + } } else if (text == "*shadowmap*") { std::vector shaders = GLShadowMapShader::RegisterShader(this); - for (size_t i = 0; i < shaders.size(); i++) - p->Attach(shaders[i]); - continue; + for (GLShader *shader : shaders) { + p->Attach(*shader); + } } else if (text[0] == '*') { SPRaise("Unknown special shader: %s", text.c_str()); } else if (text[0] == '#') { - continue; + // Comment line + } else { + auto shader = CreateShader(text); + p->Attach(*shader); } - GLShader *s = CreateShader(text); - - p->Attach(s); } Stopwatch sw; p->Link(); SPLog("Successfully linked GLSL program '%s' in %.3fms", name.c_str(), sw.GetTime() * 1000.); - // p->Validate(); return p; } - GLShader *GLProgramManager::CreateShader(const std::string &name) { + std::unique_ptr GLProgramManager::CreateShader(const std::string &name) { SPADES_MARK_FUNCTION(); SPLog("Loading GLSL shader '%s'", name.c_str()); std::string text = FileManager::ReadAllBytes(name.c_str()); GLShader::Type type; - if (name.find(".fs") != std::string::npos) + if (name.find(".fs") != std::string::npos) { type = GLShader::FragmentShader; - else if (name.find(".vs") != std::string::npos) + } else if (name.find(".vs") != std::string::npos) { type = GLShader::VertexShader; - else if (name.find(".gs") != std::string::npos) + } else if (name.find(".gs") != std::string::npos) { type = GLShader::GeometryShader; - else + } else { SPRaise("Failed to determine the type of a shader: %s", name.c_str()); + } - GLShader *s = new GLShader(device, type); + auto s = stmp::make_unique(device, type); std::string finalSource; @@ -179,6 +173,13 @@ namespace spades { } else { finalSource += "#define USE_SSAO 0\n"; } + if (settings.r_radiosity.operator int() >= 2) { + finalSource += "#define USE_RADIOSITY 2\n"; + } else if (settings.r_radiosity.operator int() >= 1) { + finalSource += "#define USE_RADIOSITY 1\n"; + } else { + finalSource += "#define USE_RADIOSITY 0\n"; + } finalSource += text; @@ -186,9 +187,9 @@ namespace spades { Stopwatch sw; s->Compile(); - SPLog("Successfully compiled GLSL program '%s' in %.3fms", name.c_str(), // should this be "program" or "shader"? + SPLog("Successfully compiled GLSL shader '%s' in %.3fms", name.c_str(), sw.GetTime() * 1000.); return s; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgramManager.h b/Sources/Draw/GLProgramManager.h index 3c1ab40e6..4d5448a86 100644 --- a/Sources/Draw/GLProgramManager.h +++ b/Sources/Draw/GLProgramManager.h @@ -19,7 +19,8 @@ */ #pragma once -#include +#include +#include #include namespace spades { @@ -30,23 +31,23 @@ namespace spades { class IGLShadowMapRenderer; class GLSettings; class GLProgramManager { - IGLDevice *device; + IGLDevice &device; GLSettings &settings; IGLShadowMapRenderer *shadowMapRenderer; - std::map programs; - std::map shaders; + std::unordered_map> programs; + std::unordered_map> shaders; - GLProgram *CreateProgram(const std::string &name); - GLShader *CreateShader(const std::string &name); + std::unique_ptr CreateProgram(const std::string &name); + std::unique_ptr CreateShader(const std::string &name); public: - GLProgramManager(IGLDevice *, IGLShadowMapRenderer *shadowMapRenderer, + GLProgramManager(IGLDevice &, IGLShadowMapRenderer *shadowMapRenderer, GLSettings &settings); ~GLProgramManager(); GLProgram *RegisterProgram(const std::string &name); GLShader *RegisterShader(const std::string &name); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgramUniform.cpp b/Sources/Draw/GLProgramUniform.cpp index ce939509f..a53b5c4e0 100644 --- a/Sources/Draw/GLProgramUniform.cpp +++ b/Sources/Draw/GLProgramUniform.cpp @@ -21,84 +21,69 @@ #include #include "GLProgramUniform.h" -#include #include +#include namespace spades { namespace draw { - GLProgramUniform::GLProgramUniform(const std::string& n): - name(n){ - last = NULL; - } + GLProgramUniform::GLProgramUniform(const std::string &n) : name(n) { last = NULL; } - void GLProgramUniform::SetProgram(spades::draw::GLProgram *p){ + void GLProgramUniform::SetProgram(spades::draw::GLProgram *p) { SPADES_MARK_FUNCTION_DEBUG(); - if(p == NULL) { + if (p == NULL) { SPInvalidArgument("prog"); } - if(last != p){ + if (last != p) { last = p; last->Use(); - loc = p->GetDevice()->GetUniformLocation - (p->GetHandle(), name.c_str()) - ; - if(loc == -1){ - fprintf(stderr,"WARNING: uniform '%s' not found\n", - name.c_str()); + loc = p->GetDevice()->GetUniformLocation(p->GetHandle(), name.c_str()); + if (loc == -1) { + fprintf(stderr, "WARNING: uniform '%s' not found\n", name.c_str()); } } } - void GLProgramUniform::SetValue(IGLDevice::Float v){ + void GLProgramUniform::SetValue(IGLDevice::Float v) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, v); } - void GLProgramUniform::SetValue(IGLDevice::Float x, - IGLDevice::Float y){ + void GLProgramUniform::SetValue(IGLDevice::Float x, IGLDevice::Float y) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x, y); } - void GLProgramUniform::SetValue(IGLDevice::Float x, - IGLDevice::Float y, - IGLDevice::Float z){ + void GLProgramUniform::SetValue(IGLDevice::Float x, IGLDevice::Float y, + IGLDevice::Float z) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x, y, z); } - void GLProgramUniform::SetValue(IGLDevice::Float x, - IGLDevice::Float y, - IGLDevice::Float z, - IGLDevice::Float w){ + void GLProgramUniform::SetValue(IGLDevice::Float x, IGLDevice::Float y, IGLDevice::Float z, + IGLDevice::Float w) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x, y, z, w); } - void GLProgramUniform::SetValue(IGLDevice::Integer x){ + void GLProgramUniform::SetValue(IGLDevice::Integer x) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x); } - void GLProgramUniform::SetValue(IGLDevice::Integer x, - IGLDevice::Integer y){ + void GLProgramUniform::SetValue(IGLDevice::Integer x, IGLDevice::Integer y) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x, y); } - void GLProgramUniform::SetValue(IGLDevice::Integer x, - IGLDevice::Integer y, - IGLDevice::Integer z){ + void GLProgramUniform::SetValue(IGLDevice::Integer x, IGLDevice::Integer y, + IGLDevice::Integer z) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x, y, z); } - void GLProgramUniform::SetValue(IGLDevice::Integer x, - IGLDevice::Integer y, - IGLDevice::Integer z, - IGLDevice::Integer w){ + void GLProgramUniform::SetValue(IGLDevice::Integer x, IGLDevice::Integer y, + IGLDevice::Integer z, IGLDevice::Integer w) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, x, y, z, w); } - void GLProgramUniform::SetValue(const spades::Matrix4 &m, - bool transpose) { + void GLProgramUniform::SetValue(const spades::Matrix4 &m, bool transpose) { SPADES_MARK_FUNCTION_DEBUG(); last->GetDevice()->Uniform(loc, transpose, m); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLProgramUniform.h b/Sources/Draw/GLProgramUniform.h index 1f7466f61..fffcb37cf 100644 --- a/Sources/Draw/GLProgramUniform.h +++ b/Sources/Draw/GLProgramUniform.h @@ -47,5 +47,5 @@ namespace spades { void SetValue(const Matrix4 &, bool transpose = false); bool IsActive() const { return loc != -1; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLQuadRenderer.cpp b/Sources/Draw/GLQuadRenderer.cpp index 57b89d5f8..0ee23225c 100644 --- a/Sources/Draw/GLQuadRenderer.cpp +++ b/Sources/Draw/GLQuadRenderer.cpp @@ -25,7 +25,7 @@ namespace spades { namespace draw { - GLQuadRenderer::GLQuadRenderer(IGLDevice *device) : device(device) {} + GLQuadRenderer::GLQuadRenderer(IGLDevice &device) : device(device) {} GLQuadRenderer::~GLQuadRenderer() {} @@ -34,10 +34,10 @@ namespace spades { void GLQuadRenderer::Draw() { static const uint8_t vertices[][4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; - device->EnableVertexAttribArray(attrIndex, true); - device->VertexAttribPointer(attrIndex, 2, IGLDevice::UnsignedByte, false, 4, vertices); - device->DrawArrays(IGLDevice::TriangleFan, 0, 4); - device->EnableVertexAttribArray(attrIndex, false); + device.EnableVertexAttribArray(attrIndex, true); + device.VertexAttribPointer(attrIndex, 2, IGLDevice::UnsignedByte, false, 4, vertices); + device.DrawArrays(IGLDevice::TriangleFan, 0, 4); + device.EnableVertexAttribArray(attrIndex, false); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLQuadRenderer.h b/Sources/Draw/GLQuadRenderer.h index bf77d7bfa..9330591cb 100644 --- a/Sources/Draw/GLQuadRenderer.h +++ b/Sources/Draw/GLQuadRenderer.h @@ -29,12 +29,12 @@ namespace spades { * load program by yourself, and GLQuadRenderer does * setting vertex attributes and drawing. */ class GLQuadRenderer { - IGLDevice *device; + IGLDevice &device; IGLDevice::UInteger attrIndex; public: - GLQuadRenderer(IGLDevice *); + GLQuadRenderer(IGLDevice &); ~GLQuadRenderer(); /** specifies the index of an attribute that @@ -43,5 +43,5 @@ namespace spades { void Draw(); }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLRadiosityRenderer.cpp b/Sources/Draw/GLRadiosityRenderer.cpp index 5cf5d512d..6343eb450 100644 --- a/Sources/Draw/GLRadiosityRenderer.cpp +++ b/Sources/Draw/GLRadiosityRenderer.cpp @@ -21,15 +21,19 @@ #include #include -#include #include "GLMapShadowRenderer.h" #include "GLRadiosityRenderer.h" #include "GLRenderer.h" +#include #include #include -#ifdef __APPLE__ +#if defined(__APPLE__) +#if defined(__x86_64__) #include +#else +#include +#endif #endif #include "GLProfiler.h" @@ -37,22 +41,22 @@ namespace spades { namespace draw { class GLRadiosityRenderer::UpdateDispatch : public ConcurrentDispatch { - GLRadiosityRenderer *renderer; + GLRadiosityRenderer &renderer; public: - std::atomic done {false}; - UpdateDispatch(GLRadiosityRenderer *r) : renderer(r) { } + std::atomic done{false}; + UpdateDispatch(GLRadiosityRenderer &r) : renderer(r) {} void Run() override { SPADES_MARK_FUNCTION(); - renderer->UpdateDirtyChunks(); + renderer.UpdateDirtyChunks(); done = true; } }; - GLRadiosityRenderer::GLRadiosityRenderer(GLRenderer *r, client::GameMap *m) - : renderer(r), device(r->GetGLDevice()), settings(r->GetSettings()), map(m) { + GLRadiosityRenderer::GLRadiosityRenderer(GLRenderer &r, client::GameMap *m) + : renderer(r), device(r.GetGLDevice()), settings(r.GetSettings()), map(m) { SPADES_MARK_FUNCTION(); w = map->Width(); @@ -92,30 +96,31 @@ namespace spades { c.cz = z; } - SPLog("Chunk buffer allocated (%d bytes)", (int) sizeof(Chunk) * chunkW * chunkH * chunkD); + SPLog("Chunk buffer allocated (%d bytes)", + (int)sizeof(Chunk) * chunkW * chunkH * chunkD); // make texture - textureFlat = device->GenTexture(); - textureX = device->GenTexture(); - textureY = device->GenTexture(); - textureZ = device->GenTexture(); + textureFlat = device.GenTexture(); + textureX = device.GenTexture(); + textureY = device.GenTexture(); + textureZ = device.GenTexture(); IGLDevice::UInteger texs[] = {textureFlat, textureX, textureY, textureZ}; for (int i = 0; i < 4; i++) { - device->BindTexture(IGLDevice::Texture3D, texs[i]); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapS, - IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapT, - IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapR, - IGLDevice::ClampToEdge); - device->TexImage3D( + device.BindTexture(IGLDevice::Texture3D, texs[i]); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapS, + IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapT, + IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture3D, IGLDevice::TextureWrapR, + IGLDevice::ClampToEdge); + device.TexImage3D( IGLDevice::Texture3D, 0, ((int)settings.r_radiosity >= 2) ? IGLDevice::RGB10A2 : IGLDevice::RGB5A1, w, h, d, 0, IGLDevice::BGRA, IGLDevice::UnsignedInt2101010Rev, NULL); @@ -129,11 +134,10 @@ namespace spades { for (int j = 0; j < 4; j++) { - device->BindTexture(IGLDevice::Texture3D, texs[j]); + device.BindTexture(IGLDevice::Texture3D, texs[j]); for (int i = 0; i < d; i++) { - device->TexSubImage3D(IGLDevice::Texture3D, 0, 0, 0, i, w, h, 1, - IGLDevice::BGRA, IGLDevice::UnsignedInt2101010Rev, - v.data()); + device.TexSubImage3D(IGLDevice::Texture3D, 0, 0, 0, i, w, h, 1, IGLDevice::BGRA, + IGLDevice::UnsignedInt2101010Rev, v.data()); } } dispatch = NULL; @@ -149,10 +153,10 @@ namespace spades { } SPLog("Releasing textures"); - device->DeleteTexture(textureFlat); - device->DeleteTexture(textureX); - device->DeleteTexture(textureY); - device->DeleteTexture(textureZ); + device.DeleteTexture(textureFlat); + device.DeleteTexture(textureX); + device.DeleteTexture(textureY); + device.DeleteTexture(textureZ); } GLRadiosityRenderer::Result GLRadiosityRenderer::Evaluate(IntVector3 ipos) { @@ -166,7 +170,7 @@ namespace spades { Vector3 pos = {ipos.x + .5f, ipos.y + .5f, ipos.z + .5f}; - GLMapShadowRenderer *shadowmap = renderer->mapShadowRenderer; + GLMapShadowRenderer *shadowmap = renderer.mapShadowRenderer; uint32_t *bitmap = shadowmap->bitmap.data(); int centerX = ipos.x; int centerY = ipos.y - ipos.z; @@ -347,7 +351,7 @@ namespace spades { dispatch->Join(); delete dispatch; } - dispatch = new UpdateDispatch(this); + dispatch = new UpdateDispatch(*this); dispatch->Start(); } int cnt = 0; @@ -355,33 +359,34 @@ namespace spades { if (!chunks[i].transferDone.load()) cnt++; } - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Radiosity [>= %d chunk(s)]", cnt); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Radiosity [>= %d chunk(s)]", + cnt); for (size_t i = 0; i < chunks.size(); i++) { Chunk &c = chunks[i]; if (!c.transferDone.exchange(true)) { - device->BindTexture(IGLDevice::Texture3D, textureFlat); - device->TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, - c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, - ChunkSize, IGLDevice::BGRA, - IGLDevice::UnsignedInt2101010Rev, c.dataFlat); - - device->BindTexture(IGLDevice::Texture3D, textureX); - device->TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, - c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, - ChunkSize, IGLDevice::BGRA, - IGLDevice::UnsignedInt2101010Rev, c.dataX); - - device->BindTexture(IGLDevice::Texture3D, textureY); - device->TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, - c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, - ChunkSize, IGLDevice::BGRA, - IGLDevice::UnsignedInt2101010Rev, c.dataY); - - device->BindTexture(IGLDevice::Texture3D, textureZ); - device->TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, - c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, - ChunkSize, IGLDevice::BGRA, - IGLDevice::UnsignedInt2101010Rev, c.dataZ); + device.BindTexture(IGLDevice::Texture3D, textureFlat); + device.TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, + c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, + ChunkSize, IGLDevice::BGRA, + IGLDevice::UnsignedInt2101010Rev, c.dataFlat); + + device.BindTexture(IGLDevice::Texture3D, textureX); + device.TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, + c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, + ChunkSize, IGLDevice::BGRA, + IGLDevice::UnsignedInt2101010Rev, c.dataX); + + device.BindTexture(IGLDevice::Texture3D, textureY); + device.TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, + c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, + ChunkSize, IGLDevice::BGRA, + IGLDevice::UnsignedInt2101010Rev, c.dataY); + + device.BindTexture(IGLDevice::Texture3D, textureZ); + device.TexSubImage3D(IGLDevice::Texture3D, 0, c.cx * ChunkSize, + c.cy * ChunkSize, c.cz * ChunkSize, ChunkSize, ChunkSize, + ChunkSize, IGLDevice::BGRA, + IGLDevice::UnsignedInt2101010Rev, c.dataZ); } } } @@ -392,7 +397,7 @@ namespace spades { int nearDirtyChunks = 0; // first, check only chunks in near range - Vector3 eyePos = renderer->GetSceneDef().viewOrigin; + Vector3 eyePos = renderer.GetSceneDef().viewOrigin; int eyeX = (int)(eyePos.x) >> ChunkSizeBits; int eyeY = (int)(eyePos.y) >> ChunkSizeBits; int eyeZ = (int)(eyePos.z) >> ChunkSizeBits; @@ -536,5 +541,5 @@ namespace spades { c.dirty = false; c.transferDone = false; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLRadiosityRenderer.h b/Sources/Draw/GLRadiosityRenderer.h index a2327d8c4..228bc15b3 100644 --- a/Sources/Draw/GLRadiosityRenderer.h +++ b/Sources/Draw/GLRadiosityRenderer.h @@ -20,13 +20,13 @@ #pragma once +#include #include #include -#include +#include "IGLDevice.h" #include #include -#include "IGLDevice.h" namespace spades { namespace client { @@ -42,8 +42,8 @@ namespace spades { class UpdateDispatch; enum { ChunkSize = 16, ChunkSizeBits = 4, Envelope = 6 }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLSettings &settings; client::GameMap *map; @@ -58,7 +58,7 @@ namespace spades { int dirtyMinY = 0, dirtyMaxY = ChunkSize - 1; int dirtyMinZ = 0, dirtyMaxZ = ChunkSize - 1; - std::atomic transferDone { true }; + std::atomic transferDone{true}; }; IGLDevice::UInteger textureFlat; @@ -102,7 +102,7 @@ namespace spades { Vector3 base, x, y, z; }; - GLRadiosityRenderer(GLRenderer *renderer, client::GameMap *map); + GLRadiosityRenderer(GLRenderer &renderer, client::GameMap *map); ~GLRadiosityRenderer(); Result Evaluate(IntVector3); @@ -116,5 +116,5 @@ namespace spades { IGLDevice::UInteger GetTextureY() { return textureY; } IGLDevice::UInteger GetTextureZ() { return textureZ; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLRenderer.cpp b/Sources/Draw/GLRenderer.cpp index 7e38adeb4..b2cb61817 100644 --- a/Sources/Draw/GLRenderer.cpp +++ b/Sources/Draw/GLRenderer.cpp @@ -21,12 +21,6 @@ #include #include -#include -#include -#include -#include -#include -#include #include "GLAmbientShadowRenderer.h" #include "GLAutoExposureFilter.h" #include "GLBloomFilter.h" @@ -35,6 +29,7 @@ #include "GLFXAAFilter.h" #include "GLFlatMapRenderer.h" #include "GLFogFilter.h" +#include "GLFogFilter2.h" #include "GLFramebufferManager.h" #include "GLImage.h" #include "GLImageManager.h" @@ -56,31 +51,37 @@ #include "GLProgramUniform.h" #include "GLRadiosityRenderer.h" #include "GLRenderer.h" +#include "GLResampleBicubicFilter.h" +#include "GLSSAOFilter.h" #include "GLSettings.h" #include "GLShadowMapShader.h" #include "GLSoftLitSpriteRenderer.h" #include "GLSoftSpriteRenderer.h" #include "GLSpriteRenderer.h" +#include "GLTemporalAAFilter.h" #include "GLVoxelModel.h" #include "GLWaterRenderer.h" -#include "GLSSAOFilter.h" #include "IGLDevice.h" #include "IGLShadowMapRenderer.h" +#include +#include +#include +#include +#include +#include namespace spades { namespace draw { // TODO: raise error for any calls after Shutdown(). - GLRenderer::GLRenderer(IGLDevice *_device) - : device(_device), - fbManager(NULL), + GLRenderer::GLRenderer(Handle _device) + : device(std::move(_device)), map(NULL), inited(false), sceneUsedInThisFrame(false), programManager(NULL), imageManager(NULL), modelManager(NULL), - shadowMapRenderer(NULL), mapShadowRenderer(NULL), mapRenderer(NULL), imageRenderer(NULL), @@ -88,7 +89,6 @@ namespace spades { modelRenderer(NULL), spriteRenderer(NULL), longSpriteRenderer(NULL), - waterRenderer(NULL), ambientShadowRenderer(NULL), radiosityRenderer(NULL), cameraBlur(NULL), @@ -101,20 +101,27 @@ namespace spades { duringSceneRendering(false) { SPADES_MARK_FUNCTION(); + SPAssert(device); + SPLog("GLRenderer bootstrap"); - fbManager = new GLFramebufferManager(_device, settings); + // Report invalid settings via `SPLog`, which might be useful for diagnosis. + settings.ValidateSettings(); + + renderWidth = renderHeight = -1; - programManager = new GLProgramManager(_device, shadowMapRenderer, settings); - imageManager = new GLImageManager(_device); - imageRenderer = new GLImageRenderer(this); + UpdateRenderSize(); + + programManager = new GLProgramManager(*device, shadowMapRenderer.get(), settings); + imageManager = new GLImageManager(*device); + imageRenderer = new GLImageRenderer(*this); profiler.reset(new GLProfiler(*this)); smoothedFogColor = MakeVector3(-1.f, -1.f, -1.f); // ready for 2d draw - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); device->Enable(IGLDevice::Blend, true); SPLog("GLRenderer started"); @@ -126,6 +133,33 @@ namespace spades { Shutdown(); } + void GLRenderer::UpdateRenderSize() { + float renderScale = settings.r_scale; + renderScale = std::max(0.2f, renderScale); + if (!(renderScale < 1.0f)) { // eliminates NaN + renderScale = 1.0f; + } + + int screenWidth = device->ScreenWidth(); + int screenHeight = device->ScreenHeight(); + + int newRenderWidth = static_cast(screenWidth * renderScale); + int newRenderHeight = static_cast(screenHeight * renderScale); + + if (newRenderWidth != renderWidth || newRenderHeight != renderHeight) { + SPLog("Render size has changed"); + renderWidth = newRenderWidth; + renderHeight = newRenderHeight; + + fbManager.reset( + new GLFramebufferManager(*device, settings, renderWidth, renderHeight)); + if (waterRenderer) { + SPLog("Creating Water Renderer"); + waterRenderer.reset(new GLWaterRenderer(*this, map)); + } + } + } + void GLRenderer::Init() { if (modelManager != NULL) { // already initialized @@ -133,59 +167,68 @@ namespace spades { } SPLog("GLRenderer initializing for 3D rendering"); - shadowMapRenderer = GLShadowMapShader::CreateShadowMapRenderer(this); - modelManager = new GLModelManager(this); + shadowMapRenderer = GLShadowMapShader::CreateShadowMapRenderer(*this); + modelManager = new GLModelManager(*this); if ((int)settings.r_softParticles >= 2) - spriteRenderer = new GLSoftLitSpriteRenderer(this); + spriteRenderer = new GLSoftLitSpriteRenderer(*this); else if (settings.r_softParticles) - spriteRenderer = new GLSoftSpriteRenderer(this); + spriteRenderer = new GLSoftSpriteRenderer(*this); else - spriteRenderer = new GLSpriteRenderer(this); - longSpriteRenderer = new GLLongSpriteRenderer(this); - modelRenderer = new GLModelRenderer(this); + spriteRenderer = new GLSpriteRenderer(*this); + longSpriteRenderer = new GLLongSpriteRenderer(*this); + modelRenderer = new GLModelRenderer(*this); // preload SPLog("Preloading Assets"); - GLMapRenderer::PreloadShaders(this); - GLVoxelModel::PreloadShaders(this); - GLOptimizedVoxelModel::PreloadShaders(this); + GLMapRenderer::PreloadShaders(*this); + GLVoxelModel::PreloadShaders(*this); + GLOptimizedVoxelModel::PreloadShaders(*this); if (settings.r_water) - GLWaterRenderer::PreloadShaders(this); + GLWaterRenderer::PreloadShaders(*this); if (settings.r_cameraBlur) { - cameraBlur = new GLCameraBlurFilter(this); + cameraBlur = new GLCameraBlurFilter(*this); + } + if (settings.r_temporalAA) { + temporalAAFilter.reset(new GLTemporalAAFilter(*this)); } - if (settings.r_fogShadow) { - GLFogFilter(this); + if (settings.ShouldUseFogFilter2()) { + fogFilter2.reset(new GLFogFilter2(*this)); + } else if (settings.r_fogShadow) { + GLFogFilter(*this); } if (settings.r_bloom) { - lensDustFilter = new GLLensDustFilter(this); + lensDustFilter = new GLLensDustFilter(*this); } if (settings.r_hdr) { - autoExposureFilter = new GLAutoExposureFilter(this); + autoExposureFilter = new GLAutoExposureFilter(*this); } if (settings.r_lens) { - GLLensFilter(this); + GLLensFilter(*this); } if (settings.r_lensFlare) { - GLLensFlareFilter(this); + GLLensFlareFilter(*this); } if (settings.r_colorCorrection) { - GLColorCorrectionFilter(this); + GLColorCorrectionFilter(*this); } if (settings.r_fxaa) { - GLFXAAFilter(this); + GLFXAAFilter(*this); + } + + if (settings.r_scaleFilter.operator int() == 2) { + GLResampleBicubicFilter(*this); } if (settings.r_depthOfField) { - GLDepthOfFieldFilter(this); + GLDepthOfFieldFilter(*this); } device->Finish(); @@ -197,6 +240,8 @@ namespace spades { SPLog("GLRender finalizing"); SetGameMap(nullptr); + temporalAAFilter.reset(); + fogFilter2.reset(); delete autoExposureFilter; autoExposureFilter = NULL; delete lensDustFilter; @@ -211,18 +256,14 @@ namespace spades { mapShadowRenderer = NULL; delete mapRenderer; mapRenderer = NULL; - delete waterRenderer; - waterRenderer = NULL; + waterRenderer.reset(); delete ambientShadowRenderer; ambientShadowRenderer = NULL; - delete shadowMapRenderer; - shadowMapRenderer = NULL; + shadowMapRenderer.reset(); delete cameraBlur; cameraBlur = NULL; delete longSpriteRenderer; longSpriteRenderer = NULL; - delete waterRenderer; - waterRenderer = NULL; delete modelRenderer; modelRenderer = NULL; delete spriteRenderer; @@ -235,20 +276,19 @@ namespace spades { programManager = NULL; delete imageManager; imageManager = NULL; - delete fbManager; - fbManager = NULL; + fbManager.reset(); profiler.reset(); SPLog("GLRenderer finalized"); } - client::IImage *GLRenderer::RegisterImage(const char *filename) { + Handle GLRenderer::RegisterImage(const char *filename) { SPADES_MARK_FUNCTION(); return imageManager->RegisterImage(filename); } - client::IModel *GLRenderer::RegisterModel(const char *filename) { + Handle GLRenderer::RegisterModel(const char *filename) { SPADES_MARK_FUNCTION(); - return modelManager->RegisterModel(filename); + return modelManager->RegisterModel(filename).Cast(); } void GLRenderer::ClearCache() { @@ -257,22 +297,22 @@ namespace spades { imageManager->ClearCache(); } - client::IImage *GLRenderer::CreateImage(spades::Bitmap *bmp) { + Handle GLRenderer::CreateImage(spades::Bitmap &bmp) { SPADES_MARK_FUNCTION(); - return GLImage::FromBitmap(bmp, device); + return GLImage::FromBitmap(bmp, device.GetPointerOrNull()).Cast(); } - client::IModel *GLRenderer::CreateModel(spades::VoxelModel *model) { + Handle GLRenderer::CreateModel(spades::VoxelModel &model) { SPADES_MARK_FUNCTION(); - return new GLVoxelModel(model, this); + return Handle::New(&model, *this).Cast(); } - client::IModel *GLRenderer::CreateModelOptimized(spades::VoxelModel *model) { + Handle GLRenderer::CreateModelOptimized(spades::VoxelModel &model) { SPADES_MARK_FUNCTION(); if (settings.r_optimizedVoxelModel) { - return new GLOptimizedVoxelModel(model, this); + return Handle::New(&model, *this).Cast(); } else { - return new GLVoxelModel(model, this); + return Handle::New(&model, *this).Cast(); } } @@ -283,11 +323,12 @@ namespace spades { } } - void GLRenderer::SetGameMap(client::GameMap *mp) { + void GLRenderer::SetGameMap(stmp::optional newMap) { SPADES_MARK_FUNCTION(); - if (mp) + if (newMap) { EnsureInitialized(); + } client::GameMap *oldMap = map; @@ -300,39 +341,38 @@ namespace spades { flatMapRenderer = NULL; delete mapShadowRenderer; mapShadowRenderer = NULL; - delete waterRenderer; - waterRenderer = NULL; + waterRenderer.reset(); delete ambientShadowRenderer; ambientShadowRenderer = NULL; - if (mp) { + if (newMap) { SPLog("Creating new renderers..."); SPLog("Creating Terrain Shadow Map Renderer"); - mapShadowRenderer = new GLMapShadowRenderer(this, mp); + mapShadowRenderer = new GLMapShadowRenderer(*this, newMap.get_pointer()); SPLog("Creating TerrainRenderer"); - mapRenderer = new GLMapRenderer(mp, this); + mapRenderer = new GLMapRenderer(newMap.get_pointer(), *this); SPLog("Creating Minimap Renderer"); - flatMapRenderer = new GLFlatMapRenderer(this, mp); + flatMapRenderer = new GLFlatMapRenderer(*this, *newMap); SPLog("Creating Water Renderer"); - waterRenderer = new GLWaterRenderer(this, mp); + waterRenderer.reset(new GLWaterRenderer(*this, newMap.get_pointer())); if (settings.r_radiosity) { SPLog("Creating Ray-traced Ambient Occlusion Renderer"); - ambientShadowRenderer = new GLAmbientShadowRenderer(this, mp); + ambientShadowRenderer = new GLAmbientShadowRenderer(*this, *newMap); SPLog("Creating Relective Shadow Maps Renderer"); - radiosityRenderer = new GLRadiosityRenderer(this, mp); + radiosityRenderer = new GLRadiosityRenderer(*this, newMap.get_pointer()); } else { SPLog("Radiosity is disabled"); } - mp->AddListener(this); - mp->AddRef(); + newMap->AddListener(this); + newMap->AddRef(); SPLog("Created"); } else { SPLog("No map loaded"); } - this->map = mp; + this->map = newMap.get_pointer(); if (oldMap) { oldMap->RemoveListener(this); oldMap->Release(); @@ -372,51 +412,24 @@ namespace spades { void GLRenderer::BuildProjectionMatrix() { SPADES_MARK_FUNCTION(); - float near = sceneDef.zNear; - float far = sceneDef.zFar; - float t = near * tanf(sceneDef.fovY * .5f); - float r = near * tanf(sceneDef.fovX * .5f); - float a = r * 2.f, b = t * 2.f, c = far - near; - Matrix4 mat; - mat.m[0] = near * 2.f / a; - mat.m[1] = 0.f; - mat.m[2] = 0.f; - mat.m[3] = 0.f; - mat.m[4] = 0.f; - mat.m[5] = near * 2.f / b; - mat.m[6] = 0.f; - mat.m[7] = 0.f; - mat.m[8] = 0.f; - mat.m[9] = 0.f; - mat.m[10] = -(far + near) / c; - mat.m[11] = -1.f; - mat.m[12] = 0.f; - mat.m[13] = 0.f; - mat.m[14] = -(far * near * 2.f) / c; - mat.m[15] = 0.f; + Matrix4 mat = sceneDef.ToOpenGLProjectionMatrix(); + + if (settings.r_temporalAA && temporalAAFilter) { + float jitterX = 1.0f / GetRenderWidth(); + float jitterY = 1.0f / GetRenderHeight(); + Vector2 jitter = temporalAAFilter->GetProjectionMatrixJitter(); + jitterX *= jitter.x * 1.3f; + jitterY *= jitter.y * 1.3f; + mat = Matrix4::Translate(jitterX, jitterY, 0.0f) * mat; + } + projectionMatrix = mat; } void GLRenderer::BuildView() { SPADES_MARK_FUNCTION(); - Matrix4 mat = Matrix4::Identity(); - mat.m[0] = sceneDef.viewAxis[0].x; - mat.m[4] = sceneDef.viewAxis[0].y; - mat.m[8] = sceneDef.viewAxis[0].z; - mat.m[1] = sceneDef.viewAxis[1].x; - mat.m[5] = sceneDef.viewAxis[1].y; - mat.m[9] = sceneDef.viewAxis[1].z; - mat.m[2] = -sceneDef.viewAxis[2].x; - mat.m[6] = -sceneDef.viewAxis[2].y; - mat.m[10] = -sceneDef.viewAxis[2].z; - - Vector4 v = mat * sceneDef.viewOrigin; - mat.m[12] = -v.x; - mat.m[13] = -v.y; - mat.m[14] = -v.z; - - viewMatrix = mat; + viewMatrix = sceneDef.ToViewMatrix(); } void GLRenderer::BuildFrustrum() { @@ -490,20 +503,17 @@ namespace spades { #pragma mark - Add Scene Objects - void GLRenderer::RenderModel(client::IModel *model, const client::ModelRenderParam ¶m) { + void GLRenderer::RenderModel(client::IModel &model, const client::ModelRenderParam ¶m) { SPADES_MARK_FUNCTION(); - GLModel *m = dynamic_cast(model); - if (!m) { - SPInvalidArgument("model"); - } + GLModel &glModel = dynamic_cast(model); EnsureInitialized(); EnsureSceneStarted(); // TODO: early frustrum cull? - modelRenderer->AddModel(m, param); + modelRenderer->AddModel(&glModel, param); } void GLRenderer::AddLight(const client::DynamicLightParam &light) { @@ -523,12 +533,10 @@ namespace spades { debugLines.push_back(line); } - void GLRenderer::AddSprite(client::IImage *img, spades::Vector3 center, float radius, + void GLRenderer::AddSprite(client::IImage &img, spades::Vector3 center, float radius, float rotation) { SPADES_MARK_FUNCTION_DEBUG(); - GLImage *im = dynamic_cast(img); - if (!im) - SPInvalidArgument("im"); + GLImage &glImage = dynamic_cast(img); if (!SphereFrustrumCull(center, radius * 1.5f)) return; @@ -536,20 +544,18 @@ namespace spades { EnsureInitialized(); EnsureSceneStarted(); - spriteRenderer->Add(im, center, radius, rotation, drawColorAlphaPremultiplied); + spriteRenderer->Add(&glImage, center, radius, rotation, drawColorAlphaPremultiplied); } - void GLRenderer::AddLongSprite(client::IImage *img, spades::Vector3 p1, spades::Vector3 p2, + void GLRenderer::AddLongSprite(client::IImage &img, spades::Vector3 p1, spades::Vector3 p2, float radius) { SPADES_MARK_FUNCTION_DEBUG(); - GLImage *im = dynamic_cast(img); - if (!im) - SPInvalidArgument("im"); + GLImage &glImage = dynamic_cast(img); EnsureInitialized(); EnsureSceneStarted(); - longSpriteRenderer->Add(im, p1, p2, radius, drawColorAlphaPremultiplied); + longSpriteRenderer->Add(&glImage, p1, p2, radius, drawColorAlphaPremultiplied); } #pragma mark - Scene Finalizer @@ -637,12 +643,14 @@ namespace spades { device->Enable(IGLDevice::DepthTest, false); device->Enable(IGLDevice::CullFace, false); - ssaoBuffer = GLSSAOFilter(this).Filter(); + ssaoBuffer = GLSSAOFilter(*this).Filter(); ssaoBufferTexture = ssaoBuffer.GetTexture(); device->BindTexture(IGLDevice::Texture2D, ssaoBufferTexture); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); device->Enable(IGLDevice::CullFace, true); } @@ -660,19 +668,22 @@ namespace spades { } if (settings.r_ssao) { device->BindTexture(IGLDevice::Texture2D, ssaoBufferTexture); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Linear); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); ssaoBuffer.Release(); } { - GLProfiler::Context p(*profiler, "Dynamic Light Pass [%d light(s)]", (int)lights.size()); + GLProfiler::Context p(*profiler, "Dynamic Light Pass [%d light(s)]", + (int)lights.size()); device->Enable(IGLDevice::Blend, true); device->Enable(IGLDevice::DepthTest, true); device->DepthFunc(IGLDevice::Equal); - device->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::One, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::One, IGLDevice::Zero, + IGLDevice::One); if (!sceneDef.skipWorld && mapRenderer) { mapRenderer->RenderDynamicLightPass(lights); @@ -814,15 +825,20 @@ namespace spades { std::swap(view, viewMatrix); projectionViewMatrix = projectionMatrix * viewMatrix; - if (settings.r_fogShadow && mapShadowRenderer && - fogColor.GetPoweredLength() > .000001f) { + if (settings.r_fogShadow && mapShadowRenderer) { GLProfiler::Context p(*profiler, "Volumetric Fog"); GLFramebufferManager::BufferHandle handle; - GLFogFilter fogfilter(this); handle = fbManager->StartPostProcessing(); - handle = fogfilter.Filter(handle); + if (settings.ShouldUseFogFilter2()) { + if (!fogFilter2) { + fogFilter2.reset(new GLFogFilter2(*this)); + } + handle = fogFilter2->Filter(handle); + } else { + handle = GLFogFilter(*this).Filter(handle); + } fbManager->CopyToMirrorTexture(handle.GetFramebuffer()); } else { fbManager->CopyToMirrorTexture(); @@ -846,7 +862,8 @@ namespace spades { { GLProfiler::Context p(*profiler, "Clear"); device->ClearColor(bgCol.x, bgCol.y, bgCol.z, 1.f); - device->Clear((IGLDevice::Enum)(IGLDevice::ColorBufferBit | IGLDevice::DepthBufferBit)); + device->Clear( + (IGLDevice::Enum)(IGLDevice::ColorBufferBit | IGLDevice::DepthBufferBit)); } device->FrontFace(IGLDevice::CW); @@ -873,15 +890,15 @@ namespace spades { device->DepthMask(false); if (!settings.r_softParticles) { // softparticle is a part of postprocess GLProfiler::Context p(*profiler, "Particles"); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); spriteRenderer->Render(); } { GLProfiler::Context p(*profiler, "Long Particles"); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); longSpriteRenderer->Render(); } @@ -897,37 +914,55 @@ namespace spades { GLProfiler::Context p(*profiler, "Preparation"); handle = fbManager->StartPostProcessing(); } - if (settings.r_fogShadow && mapShadowRenderer && - fogColor.GetPoweredLength() > .000001f) { + if (settings.r_fogShadow && mapShadowRenderer) { GLProfiler::Context p(*profiler, "Volumetric Fog"); - GLFogFilter fogfilter(this); - handle = fogfilter.Filter(handle); + if (settings.ShouldUseFogFilter2()) { + if (!fogFilter2) { + fogFilter2.reset(new GLFogFilter2(*this)); + } + handle = fogFilter2->Filter(handle); + } else { + handle = GLFogFilter(*this).Filter(handle); + } } device->BindFramebuffer(IGLDevice::Framebuffer, handle.GetFramebuffer()); if (settings.r_softParticles) { // softparticle is a part of postprocess GLProfiler::Context p(*profiler, "Soft Particle"); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); spriteRenderer->Render(); } - device->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::SrcAlpha, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); if (settings.r_depthOfField && (sceneDef.depthOfFieldFocalLength > 0.f || sceneDef.blurVignette > 0.f)) { GLProfiler::Context p(*profiler, "Depth of Field"); - handle = GLDepthOfFieldFilter(this).Filter( + handle = GLDepthOfFieldFilter(*this).Filter( handle, sceneDef.depthOfFieldFocalLength, sceneDef.blurVignette, sceneDef.globalBlur, sceneDef.depthOfFieldNearBlurStrength, sceneDef.depthOfFieldFarBlurStrength); } if (settings.r_cameraBlur && !sceneDef.denyCameraBlur) { + if (!cameraBlur) { + cameraBlur = new GLCameraBlurFilter(*this); + } + GLProfiler::Context p(*profiler, "Camera Blur"); // FIXME: better (correctly constructed) radial blur algorithm - handle = cameraBlur->Filter(handle, sceneDef.radialBlur); + handle = cameraBlur->Filter( + handle, std::min(settings.r_cameraBlur * 0.2f, 1.0f), sceneDef.radialBlur); + } + + if (settings.r_temporalAA) { + if (!temporalAAFilter) { + temporalAAFilter.reset(new GLTemporalAAFilter(*this)); + } + GLProfiler::Context p(*profiler, "Temporal AA"); + handle = temporalAAFilter->Filter(handle, settings.r_fxaa); } if (settings.r_bloom) { @@ -935,26 +970,26 @@ namespace spades { handle = lensDustFilter->Filter(handle); } - // do r_fxaa before lens filter so that color aberration looks nice + // Do r_fxaa before lens filter so that color aberration looks nice. if (settings.r_fxaa) { GLProfiler::Context p(*profiler, "FXAA"); - handle = GLFXAAFilter(this).Filter(handle); + handle = GLFXAAFilter(*this).Filter(handle); } if (settings.r_lens) { GLProfiler::Context p(*profiler, "Lens Filter"); - handle = GLLensFilter(this).Filter(handle); + handle = GLLensFilter(*this).Filter(handle); } if (settings.r_lensFlare) { GLProfiler::Context p(*profiler, "Lens Flare"); device->BindFramebuffer(IGLDevice::Framebuffer, handle.GetFramebuffer()); - GLLensFlareFilter(this).Draw(); + GLLensFlareFilter(*this).Draw(); } if (settings.r_lensFlare && settings.r_lensFlareDynamic) { GLProfiler::Context p(*profiler, "Dynamic Light Lens Flare"); - GLLensFlareFilter lensFlareRenderer(this); + GLLensFlareFilter lensFlareRenderer(*this); device->BindFramebuffer(IGLDevice::Framebuffer, handle.GetFramebuffer()); for (size_t i = 0; i < lights.size(); i++) { const GLDynamicLight &dl = lights[i]; @@ -1005,7 +1040,7 @@ namespace spades { if (settings.r_hdr) { GLProfiler::Context p(*profiler, "Gamma Correction"); - handle = GLNonlinearlizeFilter(this).Filter(handle); + handle = GLNonlinearlizeFilter(*this).Filter(handle); } if (settings.r_colorCorrection) { @@ -1015,18 +1050,47 @@ namespace spades { tint = Mix(tint, MakeVector3(1.f, 1.f, 1.f), 0.2f); tint *= 1.f / std::min(std::min(tint.x, tint.y), tint.z); + float fogLuminance = (fogColor.x + fogColor.y + fogColor.z) * (1.0f / 3.0f); + + if (settings.ShouldUseFogFilter2()) { + // `GLFogFilter2` adds a GI factor, so the fog receives some light + // even if the fog color is set to dark. + fogLuminance = fogLuminance * 0.9 + 0.2; + } + float exposure = powf(2.f, (float)settings.r_exposureValue * 0.5f); - handle = GLColorCorrectionFilter(this).Filter(handle, tint * exposure); + handle = + GLColorCorrectionFilter(*this).Filter(handle, tint * exposure, fogLuminance); // update smoothed fog color smoothedFogColor = Mix(smoothedFogColor, fogColor, 0.002f); } } + // Resample the rendered image using a non-trivial filter if such + // a filter is selected. + int scaleFilter = settings.r_scaleFilter; + bool scalingMayBeNeeded = GetRenderWidth() != device->ScreenWidth() || + GetRenderHeight() != device->ScreenHeight(); + if (scaleFilter == 0) { + // Nearest neighbor - trivial + } else if (scaleFilter == 1) { + // Bi-linear - trivial + } else if (scaleFilter == 2) { + // Bi-cubic - non-trivial + handle = GLResampleBicubicFilter{*this}.Filter(handle, device->ScreenWidth(), + device->ScreenHeight()); + scaleFilter = 0; + } else { + // I don't know this filter. + scaleFilter = 1; + } + if (settings.r_srgb && settings.r_srgb2D) { // in gamma corrected mode, // 2d drawings are done on gamma-corrected FB // see also: FrameDone + // TODO: Handle the case where `scaleFilter == 0` lastColorBufferTexture = handle.GetTexture(); device->BindFramebuffer(IGLDevice::Framebuffer, handle.GetFramebuffer()); device->Enable(IGLDevice::FramebufferSRGB, true); @@ -1038,16 +1102,34 @@ namespace spades { GLProfiler::Context p(*profiler, "Copying to WM-given Framebuffer"); + if (scaleFilter == 0) { + // Temporarily change the textute filter to NN + device->BindTexture(IGLDevice::Texture2D, handle.GetTexture()); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + } + device->BindFramebuffer(IGLDevice::Framebuffer, 0); device->Enable(IGLDevice::Blend, false); - device->Viewport(0, 0, handle.GetWidth(), handle.GetHeight()); - Handle image(new GLImage(handle.GetTexture(), device, handle.GetWidth(), - handle.GetHeight(), false), + device->Viewport(0, 0, device->ScreenWidth(), device->ScreenHeight()); + Handle image(new GLImage(handle.GetTexture(), device.GetPointerOrNull(), + handle.GetWidth(), handle.GetHeight(), false), false); SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1)); - DrawImage(image, - AABB2(0, handle.GetHeight(), handle.GetWidth(), -handle.GetHeight())); + DrawImage(*image, AABB2(0, device->ScreenHeight(), device->ScreenWidth(), + -device->ScreenHeight())); imageRenderer->Flush(); + + if (scaleFilter == 0) { + // Reset the texture filter + device->BindTexture(IGLDevice::Texture2D, handle.GetTexture()); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + } } handle.Release(); @@ -1059,9 +1141,7 @@ namespace spades { modelRenderer->Clear(); // prepare for 2d drawing - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); - device->Enable(IGLDevice::Blend, true); + Prepare2DRendering(true); } //#pragma mark - 2D Drawings @@ -1071,8 +1151,8 @@ namespace spades { void EnsureSceneNotStarted(); imageRenderer->Flush(); - device->BlendFunc(IGLDevice::Zero, IGLDevice::SrcColor, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::Zero, IGLDevice::SrcColor, IGLDevice::Zero, + IGLDevice::One); Vector4 col = {color.x, color.y, color.z, 1}; @@ -1111,11 +1191,12 @@ namespace spades { device->EnableVertexAttribArray(positionAttribute(), false); device->EnableVertexAttribArray(colorAttribute(), false); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); + device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); } - void GLRenderer::DrawImage(client::IImage *image, const spades::Vector2 &outTopLeft) { + void GLRenderer::DrawImage(stmp::optional image, + const spades::Vector2 &outTopLeft) { SPADES_MARK_FUNCTION(); if (image == nullptr) { @@ -1127,15 +1208,16 @@ namespace spades { AABB2(0, 0, image->GetWidth(), image->GetHeight())); } - void GLRenderer::DrawImage(client::IImage *image, const spades::AABB2 &outRect) { + void GLRenderer::DrawImage(stmp::optional image, + const spades::AABB2 &outRect) { SPADES_MARK_FUNCTION(); DrawImage(image, outRect, AABB2(0, 0, image ? image->GetWidth() : 0, image ? image->GetHeight() : 0)); } - void GLRenderer::DrawImage(client::IImage *image, const spades::Vector2 &outTopLeft, - const spades::AABB2 &inRect) { + void GLRenderer::DrawImage(stmp::optional image, + const spades::Vector2 &outTopLeft, const spades::AABB2 &inRect) { SPADES_MARK_FUNCTION(); DrawImage(image, @@ -1143,8 +1225,8 @@ namespace spades { inRect); } - void GLRenderer::DrawImage(client::IImage *image, const spades::AABB2 &outRect, - const spades::AABB2 &inRect) { + void GLRenderer::DrawImage(stmp::optional image, + const spades::AABB2 &outRect, const spades::AABB2 &inRect) { SPADES_MARK_FUNCTION(); DrawImage(image, Vector2::Make(outRect.GetMinX(), outRect.GetMinY()), @@ -1152,7 +1234,8 @@ namespace spades { Vector2::Make(outRect.GetMinX(), outRect.GetMaxY()), inRect); } - void GLRenderer::DrawImage(client::IImage *image, const spades::Vector2 &outTopLeft, + void GLRenderer::DrawImage(stmp::optional image, + const spades::Vector2 &outTopLeft, const spades::Vector2 &outTopRight, const spades::Vector2 &outBottomLeft, const spades::AABB2 &inRect) { @@ -1163,7 +1246,7 @@ namespace spades { // d = a + (b - a) + (c - a) // = b + c - a Vector2 outBottomRight = outTopRight + outBottomLeft - outTopLeft; - GLImage *img = dynamic_cast(image); + GLImage *img = dynamic_cast(image.get_pointer()); if (!img) { if (!image) { img = imageManager->GetWhiteImage(); @@ -1215,8 +1298,7 @@ namespace spades { imageRenderer->Flush(); - if (settings.r_debugTimingOutputScreen && - settings.r_debugTiming) { + if (settings.r_debugTimingOutputScreen && settings.r_debugTiming) { GLProfiler::Context p(*profiler, "Draw GLProfiler Results"); profiler->DrawResult(); imageRenderer->Flush(); @@ -1234,21 +1316,22 @@ namespace spades { device->BindFramebuffer(IGLDevice::Framebuffer, 0); device->Enable(IGLDevice::Blend, false); device->Viewport(0, 0, w, h); - Handle image(new GLImage(lastColorBufferTexture, device, w, h, false), - false); + + auto image = Handle::New(lastColorBufferTexture, device.GetPointerOrNull(), + w, h, false); SetColorAlphaPremultiplied(MakeVector4(1, 1, 1, 1)); - DrawImage(image, AABB2(0, h, w, -h)); + DrawImage(*image, AABB2(0, h, w, -h)); imageRenderer->Flush(); // must flush now because handle is released soon } lastTime = sceneDef.time; // ready for 2d draw of next frame - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, - IGLDevice::Zero, IGLDevice::One); - device->Enable(IGLDevice::Blend, true); + Prepare2DRendering(true); profiler->EndFrame(); + + ++frameNumber; } void GLRenderer::Flip() { @@ -1257,13 +1340,22 @@ namespace spades { EnsureSceneNotStarted(); device->Swap(); + + UpdateRenderSize(); + } + + void GLRenderer::Prepare2DRendering(bool reset) { + device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha, IGLDevice::Zero, + IGLDevice::One); + device->Enable(IGLDevice::Blend, true); + device->BindFramebuffer(IGLDevice::Framebuffer, 0); + device->Viewport(0, 0, device->ScreenWidth(), device->ScreenHeight()); } - Bitmap *GLRenderer::ReadBitmap() { + Handle GLRenderer::ReadBitmap() { SPADES_MARK_FUNCTION(); - Bitmap *bmp; EnsureSceneNotStarted(); - bmp = new Bitmap(device->ScreenWidth(), device->ScreenHeight()); + auto bmp = Handle::New(device->ScreenWidth(), device->ScreenHeight()); device->ReadPixels(0, 0, device->ScreenWidth(), device->ScreenHeight(), IGLDevice::RGBA, IGLDevice::UnsignedByte, bmp->GetPixels()); return bmp; @@ -1273,7 +1365,7 @@ namespace spades { if (mapRenderer) mapRenderer->GameMapChanged(x, y, z, map); if (flatMapRenderer) - flatMapRenderer->GameMapChanged(x, y, z, map); + flatMapRenderer->GameMapChanged(x, y, z, *map); if (mapShadowRenderer) mapShadowRenderer->GameMapChanged(x, y, z, map); if (waterRenderer) @@ -1314,5 +1406,5 @@ namespace spades { } return true; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLRenderer.h b/Sources/Draw/GLRenderer.h index 656724173..05ca44a9c 100644 --- a/Sources/Draw/GLRenderer.h +++ b/Sources/Draw/GLRenderer.h @@ -55,6 +55,8 @@ namespace spades { class GLLensDustFilter; class GLSoftLitSpriteRenderer; class GLAutoExposureFilter; + class GLTemporalAAFilter; + class GLFogFilter2; class GLProfiler; class GLRenderer : public client::IRenderer, public client::IGameMapListener { @@ -69,10 +71,13 @@ namespace spades { }; Handle device; - GLFramebufferManager *fbManager; - client::GameMap *map; + std::unique_ptr fbManager; + client::GameMap *map; // TODO: get rid of raw pointers GLSettings settings; + int renderWidth; + int renderHeight; + std::unique_ptr profiler; bool inited; @@ -88,7 +93,8 @@ namespace spades { GLImageManager *imageManager; GLModelManager *modelManager; - IGLShadowMapRenderer *shadowMapRenderer; + // TODO: get rid of these abominations called raw pointers + std::unique_ptr shadowMapRenderer; GLMapShadowRenderer *mapShadowRenderer; GLMapRenderer *mapRenderer; GLImageRenderer *imageRenderer; @@ -96,13 +102,15 @@ namespace spades { GLModelRenderer *modelRenderer; IGLSpriteRenderer *spriteRenderer; GLLongSpriteRenderer *longSpriteRenderer; - GLWaterRenderer *waterRenderer; + std::unique_ptr waterRenderer; GLAmbientShadowRenderer *ambientShadowRenderer; GLRadiosityRenderer *radiosityRenderer; GLCameraBlurFilter *cameraBlur; GLLensDustFilter *lensDustFilter; GLAutoExposureFilter *autoExposureFilter; + std::unique_ptr temporalAAFilter; + std::unique_ptr fogFilter2; // used when r_ssao = 1. only valid while rendering objects IGLDevice::UInteger ssaoBufferTexture; @@ -125,6 +133,7 @@ namespace spades { bool legacyColorPremultiply; unsigned int lastTime; + std::uint32_t frameNumber = 0; bool duringSceneRendering; @@ -141,28 +150,32 @@ namespace spades { void EnsureSceneStarted(); void EnsureSceneNotStarted(); + void UpdateRenderSize(); + + void Prepare2DRendering(bool reset = false); + protected: ~GLRenderer(); public: - GLRenderer(IGLDevice *glDevice); + GLRenderer(Handle glDevice); void Init() override; void Shutdown() override; - client::IImage *RegisterImage(const char *filename) override; - client::IModel *RegisterModel(const char *filename) override; + Handle RegisterImage(const char *filename) override; + Handle RegisterModel(const char *filename) override; void ClearCache() override; - client::IImage *CreateImage(Bitmap *) override; - client::IModel *CreateModel(VoxelModel *) override; - client::IModel *CreateModelOptimized(VoxelModel *); + Handle CreateImage(Bitmap &) override; + Handle CreateModel(VoxelModel &) override; + Handle CreateModelOptimized(VoxelModel &); GLProgram *RegisterProgram(const std::string &name); GLShader *RegisterShader(const std::string &name); - void SetGameMap(client::GameMap *) override; + void SetGameMap(stmp::optional) override; void SetFogColor(Vector3 v) override; void SetFogDistance(float f) override { fogDistance = f; } @@ -172,14 +185,14 @@ namespace spades { void StartScene(const client::SceneDefinition &) override; - void RenderModel(client::IModel *, const client::ModelRenderParam &) override; + void RenderModel(client::IModel &, const client::ModelRenderParam &) override; void AddLight(const client::DynamicLightParam &light) override; void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) override; - void AddSprite(client::IImage *, Vector3 center, float radius, float rotation) override; - void AddLongSprite(client::IImage *, Vector3 p1, Vector3 p2, float radius) override; + void AddSprite(client::IImage &, Vector3 center, float radius, float rotation) override; + void AddLongSprite(client::IImage &, Vector3 p1, Vector3 p2, float radius) override; void EndScene() override; @@ -188,28 +201,33 @@ namespace spades { void SetColor(Vector4) override; void SetColorAlphaPremultiplied(Vector4) override; - void DrawImage(client::IImage *, const Vector2 &outTopLeft) override; - void DrawImage(client::IImage *, const AABB2 &outRect) override; - void DrawImage(client::IImage *, const Vector2 &outTopLeft, + void DrawImage(stmp::optional, const Vector2 &outTopLeft) override; + void DrawImage(stmp::optional, const AABB2 &outRect) override; + void DrawImage(stmp::optional, const Vector2 &outTopLeft, + const AABB2 &inRect) override; + void DrawImage(stmp::optional, const AABB2 &outRect, + const AABB2 &inRect) override; + void DrawImage(stmp::optional, const Vector2 &outTopLeft, + const Vector2 &outTopRight, const Vector2 &outBottomLeft, const AABB2 &inRect) override; - void DrawImage(client::IImage *, const AABB2 &outRect, const AABB2 &inRect) override; - void DrawImage(client::IImage *, const Vector2 &outTopLeft, const Vector2 &outTopRight, - const Vector2 &outBottomLeft, const AABB2 &inRect) override; void DrawFlatGameMap(const AABB2 &outRect, const AABB2 &inRect) override; void FrameDone() override; void Flip() override; - Bitmap *ReadBitmap() override; + Handle ReadBitmap() override; float ScreenWidth() override; float ScreenHeight() override; + int GetRenderWidth() const { return renderWidth; } + int GetRenderHeight() const { return renderHeight; } + GLSettings &GetSettings() { return settings; } - IGLDevice *GetGLDevice() { return device; } + IGLDevice &GetGLDevice() { return *device; } GLProfiler &GetGLProfiler() { return *profiler; } - GLFramebufferManager *GetFramebufferManager() { return fbManager; } - IGLShadowMapRenderer *GetShadowMapRenderer() { return shadowMapRenderer; } + GLFramebufferManager *GetFramebufferManager() { return fbManager.get(); } + IGLShadowMapRenderer *GetShadowMapRenderer() { return shadowMapRenderer.get(); } GLAmbientShadowRenderer *GetAmbientShadowRenderer() { return ambientShadowRenderer; } GLMapShadowRenderer *GetMapShadowRenderer() { return mapShadowRenderer; } GLRadiosityRenderer *GetRadiosityRenderer() { return radiosityRenderer; } @@ -219,6 +237,8 @@ namespace spades { const Matrix4 &GetProjectionViewMatrix() const { return projectionViewMatrix; } const Matrix4 &GetViewMatrix() const { return viewMatrix; } + std::uint32_t GetFrameNumber() const { return frameNumber; } + bool IsRenderingMirror() const { return renderingMirror; } void GameMapChanged(int x, int y, int z, client::GameMap *) override; @@ -228,5 +248,5 @@ namespace spades { bool BoxFrustrumCull(const AABB3 &); bool SphereFrustrumCull(const Vector3 ¢er, float radius); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLResampleBicubicFilter.cpp b/Sources/Draw/GLResampleBicubicFilter.cpp new file mode 100644 index 000000000..1b1b78777 --- /dev/null +++ b/Sources/Draw/GLResampleBicubicFilter.cpp @@ -0,0 +1,74 @@ +/* + Copyright (c) 2021 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +#include + +#include "GLProgram.h" +#include "GLProgramAttribute.h" +#include "GLProgramUniform.h" +#include "GLQuadRenderer.h" +#include "GLRenderer.h" +#include "GLResampleBicubicFilter.h" +#include "IGLDevice.h" +#include +#include + +namespace spades { + namespace draw { + GLResampleBicubicFilter::GLResampleBicubicFilter(GLRenderer &renderer) + : renderer(renderer) { + lens = renderer.RegisterProgram("Shaders/PostFilters/ResampleBicubic.program"); + } + GLColorBuffer GLResampleBicubicFilter::Filter(GLColorBuffer input, int outputWidth, + int outputHeight) { + SPADES_MARK_FUNCTION(); + + IGLDevice &dev = renderer.GetGLDevice(); + GLQuadRenderer qr(dev); + + GLColorBuffer output = + input.GetManager()->CreateBufferHandle(outputWidth, outputHeight); + + static GLProgramAttribute lensPosition("positionAttribute"); + static GLProgramUniform lensTexture("mainTexture"); + static GLProgramUniform inverseVP("inverseVP"); + + dev.Enable(IGLDevice::Blend, false); + + lensPosition(lens); + lensTexture(lens); + inverseVP(lens); + + lens->Use(); + + inverseVP.SetValue(1.f / input.GetWidth(), 1.f / input.GetHeight()); + lensTexture.SetValue(0); + + qr.SetCoordAttributeIndex(lensPosition()); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); + qr.Draw(); + dev.BindTexture(IGLDevice::Texture2D, 0); + + return output; + } + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLResampleBicubicFilter.h b/Sources/Draw/GLResampleBicubicFilter.h new file mode 100644 index 000000000..df4fe35fb --- /dev/null +++ b/Sources/Draw/GLResampleBicubicFilter.h @@ -0,0 +1,38 @@ +/* + Copyright (c) 2013 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +#pragma once + +#include "GLFramebufferManager.h" + +namespace spades { + namespace draw { + class GLRenderer; + class GLProgram; + class GLResampleBicubicFilter { + GLRenderer &renderer; + GLProgram *lens; + + public: + GLResampleBicubicFilter(GLRenderer &); + GLColorBuffer Filter(GLColorBuffer, int outputWidth, int outputHeight); + }; + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSSAOFilter.cpp b/Sources/Draw/GLSSAOFilter.cpp index 4cfab5fd8..f5727aa46 100644 --- a/Sources/Draw/GLSSAOFilter.cpp +++ b/Sources/Draw/GLSSAOFilter.cpp @@ -21,6 +21,7 @@ #include #include +#include "GLImage.h" #include "GLProfiler.h" #include "GLProgram.h" #include "GLProgramAttribute.h" @@ -28,7 +29,6 @@ #include "GLQuadRenderer.h" #include "GLRenderer.h" #include "GLSSAOFilter.h" -#include "GLImage.h" #include "IGLDevice.h" #include #include @@ -36,22 +36,22 @@ namespace spades { namespace draw { - GLSSAOFilter::GLSSAOFilter(GLRenderer *renderer) - : renderer(renderer), settings(renderer->GetSettings()) { - ssaoProgram = renderer->RegisterProgram("Shaders/PostFilters/SSAO.program"); + GLSSAOFilter::GLSSAOFilter(GLRenderer &renderer) + : renderer(renderer), settings(renderer.GetSettings()) { + ssaoProgram = renderer.RegisterProgram("Shaders/PostFilters/SSAO.program"); bilateralProgram = - renderer->RegisterProgram("Shaders/PostFilters/BilateralFilter.program"); + renderer.RegisterProgram("Shaders/PostFilters/BilateralFilter.program"); - ditherPattern = static_cast(renderer->RegisterImage("Gfx/DitherPattern4x4.png")); + ditherPattern = renderer.RegisterImage("Gfx/DitherPattern4x4.png").Cast(); } GLColorBuffer GLSSAOFilter::GenerateRawSSAOImage(int width, int height) { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); GLColorBuffer output = - renderer->GetFramebufferManager()->CreateBufferHandle(width, height, 1); + renderer.GetFramebufferManager()->CreateBufferHandle(width, height, 1); { GLProgram *program = ssaoProgram; @@ -75,7 +75,7 @@ namespace spades { program->Use(); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); zNearFar.SetValue(def.zNear, def.zFar); fieldOfView.SetValue(std::tan(def.fovX * 0.5f), std::tan(def.fovY * 0.5f)); @@ -85,30 +85,32 @@ namespace spades { float kernelSize = std::max(1.0f, std::min(width, height) * 0.0018f); sampleOffsetScale.SetValue(kernelSize / (float)width, kernelSize / (float)height); - if (width < dev->ScreenWidth()) { + if (width < renderer.GetRenderWidth()) { // 2x downsampling texCoordRange.SetValue(0.25f / width, 0.25f / height, 1.f, 1.f); } else { texCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); } - dev->ActiveTexture(0); + dev.ActiveTexture(0); depthTexture.SetValue(0); - dev->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); - dev->ActiveTexture(1); + dev.ActiveTexture(1); ditherTexture.SetValue(1); ditherPattern->Bind(IGLDevice::Texture2D); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); - dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); - dev->Viewport(0, 0, width, height); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, width, height); qr.SetCoordAttributeIndex(positionAttribute()); qr.Draw(); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, 0); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, 0); } return output; @@ -119,12 +121,14 @@ namespace spades { SPADES_MARK_FUNCTION(); // do gaussian blur GLProgram *program = bilateralProgram; - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); GLQuadRenderer qr(dev); int w = width == -1 ? tex.GetWidth() : width; int h = height == -1 ? tex.GetHeight() : height; + GLColorBuffer buf2 = renderer.GetFramebufferManager()->CreateBufferHandle(w, h, 1); + static GLProgramAttribute positionAttribute("positionAttribute"); static GLProgramUniform inputTexture("inputTexture"); static GLProgramUniform depthTexture("depthTexture"); @@ -145,38 +149,37 @@ namespace spades { pixelShift(program); inputTexture.SetValue(0); - dev->ActiveTexture(0); - dev->BindTexture(IGLDevice::Texture2D, tex.GetTexture()); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, tex.GetTexture()); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Nearest); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Nearest); depthTexture.SetValue(1); - dev->ActiveTexture(1); - dev->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); texCoordRange.SetValue(0.f, 0.f, 1.f, 1.f); unitShift.SetValue(direction ? 1.f / (float)width : 0.0f, direction ? 0.0f : 1.f / (float)height); - pixelShift.SetValue(1.f / (float)width, 1.f / (float)height, (float)width, (float)height); + pixelShift.SetValue(1.f / (float)width, 1.f / (float)height, (float)width, + (float)height); isUpsampling.SetValue(width > tex.GetWidth() ? 1 : 0); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); zNearFar.SetValue(def.zNear, def.zFar); qr.SetCoordAttributeIndex(positionAttribute()); - - GLColorBuffer buf2 = renderer->GetFramebufferManager()->CreateBufferHandle(w, h, 1); - dev->Viewport(0, 0, w, h); - dev->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + dev.Viewport(0, 0, w, h); + dev.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); qr.Draw(); - dev->ActiveTexture(0); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Linear); - dev->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Linear); + dev.ActiveTexture(0); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Linear); return buf2; } @@ -184,25 +187,26 @@ namespace spades { GLColorBuffer GLSSAOFilter::Filter() { SPADES_MARK_FUNCTION(); - IGLDevice *dev = renderer->GetGLDevice(); + IGLDevice &dev = renderer.GetGLDevice(); - int width = dev->ScreenWidth(); - int height = dev->ScreenHeight(); + int width = renderer.GetRenderWidth(); + int height = renderer.GetRenderHeight(); - dev->Enable(IGLDevice::Blend, false); + dev.Enable(IGLDevice::Blend, false); - bool useLowQualitySSAO = renderer->IsRenderingMirror() || renderer->GetSettings().r_ssao >= 2; - GLColorBuffer ssao = useLowQualitySSAO ? - GenerateRawSSAOImage((width + 1) / 2, (height + 1) / 2) : - GenerateRawSSAOImage(width, height); + bool useLowQualitySSAO = + renderer.IsRenderingMirror() || renderer.GetSettings().r_ssao >= 2; + GLColorBuffer ssao = useLowQualitySSAO + ? GenerateRawSSAOImage((width + 1) / 2, (height + 1) / 2) + : GenerateRawSSAOImage(width, height); ssao = ApplyBilateralFilter(ssao, false, width, height); ssao = ApplyBilateralFilter(ssao, true, width, height); - if (!renderer->IsRenderingMirror()) { + if (!renderer.IsRenderingMirror()) { ssao = ApplyBilateralFilter(ssao, false, width, height); ssao = ApplyBilateralFilter(ssao, true, width, height); } return ssao; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSSAOFilter.h b/Sources/Draw/GLSSAOFilter.h index ced6b0100..9723e3ad5 100644 --- a/Sources/Draw/GLSSAOFilter.h +++ b/Sources/Draw/GLSSAOFilter.h @@ -29,20 +29,20 @@ namespace spades { class GLImage; class GLSettings; class GLSSAOFilter { - GLRenderer *renderer; + GLRenderer &renderer; GLSettings &settings; GLProgram *ssaoProgram; GLProgram *bilateralProgram; - GLImage *ditherPattern; + Handle ditherPattern; GLColorBuffer GenerateRawSSAOImage(int width, int height); GLColorBuffer ApplyBilateralFilter(GLColorBuffer, bool direction, int width = -1, int height = -1); public: - GLSSAOFilter(GLRenderer *); + GLSSAOFilter(GLRenderer &); GLColorBuffer Filter(); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSettings.cpp b/Sources/Draw/GLSettings.cpp index c5197b0b0..db92dbd15 100644 --- a/Sources/Draw/GLSettings.cpp +++ b/Sources/Draw/GLSettings.cpp @@ -18,6 +18,8 @@ */ +#include + #include "GLSettings.h" DEFINE_SPADES_SETTING(r_blitFramebuffer, "1"); @@ -57,16 +59,30 @@ DEFINE_SPADES_SETTING(r_optimizedVoxelModel, "1"); DEFINE_SPADES_SETTING(r_physicalLighting, "0"); DEFINE_SPADES_SETTING(r_radiosity, "0"); DEFINE_SPADES_SETTING(r_saturation, "1"); +DEFINE_SPADES_SETTING(r_scale, "1"); +DEFINE_SPADES_SETTING(r_scaleFilter, "1"); DEFINE_SPADES_SETTING(r_shadowMapSize, "2048"); +DEFINE_SPADES_SETTING(r_sharpen, "1"); DEFINE_SPADES_SETTING(r_softParticles, "1"); DEFINE_SPADES_SETTING(r_sparseShadowMaps, "1"); DEFINE_SPADES_SETTING(r_srgb, "0"); DEFINE_SPADES_SETTING(r_srgb2D, "1"); DEFINE_SPADES_SETTING(r_ssao, "0"); +DEFINE_SPADES_SETTING(r_temporalAA, "0"); DEFINE_SPADES_SETTING(r_water, "2"); namespace spades { namespace draw { GLSettings::GLSettings() {} - } -} + + void GLSettings::ValidateSettings() { + if (this->r_fogShadow.operator int() == 2 && !this->ShouldUseFogFilter2()) { + SPLog("`r_fogShadow 2` is ignored because `r_radiosity` is disabled"); + } + } + + bool GLSettings::ShouldUseFogFilter2() { + return this->r_fogShadow.operator int() == 2 && !!this->r_radiosity.operator int(); + } + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSettings.h b/Sources/Draw/GLSettings.h index 204dfad35..1b559f97a 100644 --- a/Sources/Draw/GLSettings.h +++ b/Sources/Draw/GLSettings.h @@ -27,9 +27,10 @@ namespace spades { public: GLSettings(); + // clang-format off TypedItemHandle r_blitFramebuffer { *this, "r_blitFramebuffer" }; TypedItemHandle r_bloom { *this, "r_bloom" }; - TypedItemHandle r_cameraBlur { *this, "r_cameraBlur", ItemFlags::Latch }; + TypedItemHandle r_cameraBlur { *this, "r_cameraBlur" }; TypedItemHandle r_colorCorrection { *this, "r_colorCorrection" }; TypedItemHandle r_debugTiming { *this, "r_debugTiming" }; TypedItemHandle r_debugTimingOutputScreen { *this, "r_debugTimingOutputScreen" }; @@ -44,7 +45,7 @@ namespace spades { TypedItemHandle r_depthPrepass { *this, "r_depthPrepass" }; TypedItemHandle r_dlights { *this, "r_dlights" }; TypedItemHandle r_exposureValue { *this, "r_exposureValue" }; - TypedItemHandle r_fogShadow { *this, "r_fogShadow", ItemFlags::Latch }; + TypedItemHandle r_fogShadow { *this, "r_fogShadow", ItemFlags::Latch }; TypedItemHandle r_fxaa { *this, "r_fxaa" }; TypedItemHandle r_hdr { *this, "r_hdr", ItemFlags::Latch }; TypedItemHandle r_hdrAutoExposureMin { *this, "r_hdrAutoExposureMin" }; @@ -64,13 +65,22 @@ namespace spades { TypedItemHandle r_physicalLighting { *this, "r_physicalLighting", ItemFlags::Latch }; TypedItemHandle r_radiosity { *this, "r_radiosity", ItemFlags::Latch }; TypedItemHandle r_saturation { *this, "r_saturation" }; + TypedItemHandle r_scale { *this, "r_scale" }; + TypedItemHandle r_scaleFilter { *this, "r_scaleFilter" }; TypedItemHandle r_shadowMapSize { *this, "r_shadowMapSize", ItemFlags::Latch }; + TypedItemHandle r_sharpen { *this, "r_sharpen" }; TypedItemHandle r_softParticles { *this, "r_softParticles", ItemFlags::Latch }; TypedItemHandle r_sparseShadowMaps { *this, "r_sparseShadowMaps", ItemFlags::Latch }; TypedItemHandle r_srgb { *this, "r_srgb", ItemFlags::Latch }; TypedItemHandle r_srgb2D { *this, "r_srgb2D", ItemFlags::Latch }; TypedItemHandle r_ssao { *this, "r_ssao", ItemFlags::Latch }; + TypedItemHandle r_temporalAA { *this, "r_temporalAA" }; TypedItemHandle r_water { *this, "r_water", ItemFlags::Latch }; + // clang-format on + + /** Check illegal settings and report via `SPLog`. */ + void ValidateSettings(); + bool ShouldUseFogFilter2(); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLShader.cpp b/Sources/Draw/GLShader.cpp index c9ca72583..bf2cc53c9 100644 --- a/Sources/Draw/GLShader.cpp +++ b/Sources/Draw/GLShader.cpp @@ -26,22 +26,20 @@ namespace spades { namespace draw { - GLShader::GLShader(IGLDevice *dev, Type type) : device(dev), compiled(false) { + GLShader::GLShader(IGLDevice &dev, Type type) : device(dev), compiled(false) { SPADES_MARK_FUNCTION(); switch (type) { - case VertexShader: handle = device->CreateShader(IGLDevice::VertexShader); break; - case GeometryShader: handle = device->CreateShader(IGLDevice::GeometryShader); break; - case FragmentShader: - handle = device->CreateShader(IGLDevice::FragmentShader); - break; + case VertexShader: handle = device.CreateShader(IGLDevice::VertexShader); break; + case GeometryShader: handle = device.CreateShader(IGLDevice::GeometryShader); break; + case FragmentShader: handle = device.CreateShader(IGLDevice::FragmentShader); break; default: SPInvalidEnum("type", type); } } GLShader::~GLShader() { SPADES_MARK_FUNCTION(); - device->DeleteShader(handle); + device.DeleteShader(handle); } void GLShader::AddSource(const std::string &src) { @@ -61,19 +59,19 @@ namespace spades { lens.push_back(static_cast(sources[i].size())); } - device->ShaderSource(handle, static_cast(srcs.size()), srcs.data(), - lens.data()); + device.ShaderSource(handle, static_cast(srcs.size()), srcs.data(), + lens.data()); - device->CompileShader(handle); + device.CompileShader(handle); - if (device->GetShaderInteger(handle, IGLDevice::CompileStatus) == 0) { + if (device.GetShaderInteger(handle, IGLDevice::CompileStatus) == 0) { // error std::vector errMsg; - errMsg.resize(device->GetShaderInteger(handle, IGLDevice::InfoLogLength) + 1); + errMsg.resize(device.GetShaderInteger(handle, IGLDevice::InfoLogLength) + 1); IGLDevice::Sizei outLen; - device->GetShaderInfoLog(handle, static_cast(errMsg.size()), - &outLen, errMsg.data()); + device.GetShaderInfoLog(handle, static_cast(errMsg.size()), + &outLen, errMsg.data()); errMsg[outLen] = 0; std::string src; @@ -89,5 +87,5 @@ namespace spades { compiled = true; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLShader.h b/Sources/Draw/GLShader.h index 9bec44c3f..52a65e768 100644 --- a/Sources/Draw/GLShader.h +++ b/Sources/Draw/GLShader.h @@ -27,7 +27,7 @@ namespace spades { namespace draw { class GLShader { - IGLDevice *device; + IGLDevice &device; IGLDevice::UInteger handle; std::vector sources; bool compiled; @@ -35,7 +35,7 @@ namespace spades { public: enum Type { VertexShader, FragmentShader, GeometryShader }; - GLShader(IGLDevice *, Type); + GLShader(IGLDevice &, Type); ~GLShader(); void AddSource(const std::string &); @@ -45,7 +45,7 @@ namespace spades { bool IsCompiled() const { return compiled; } - IGLDevice *GetDevice() const { return device; } + IGLDevice &GetDevice() const { return device; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLShadowMapShader.cpp b/Sources/Draw/GLShadowMapShader.cpp index e42e301ec..32859a2b7 100644 --- a/Sources/Draw/GLShadowMapShader.cpp +++ b/Sources/Draw/GLShadowMapShader.cpp @@ -19,13 +19,14 @@ */ #include "GLShadowMapShader.h" -#include -#include #include "GLBasicShadowMapRenderer.h" #include "GLMapShadowRenderer.h" #include "GLProgramManager.h" #include "GLRenderer.h" #include "GLSparseShadowMapRenderer.h" +#include +#include +#include namespace spades { namespace draw { @@ -48,15 +49,18 @@ namespace spades { return shaders; } - IGLShadowMapRenderer * - GLShadowMapShader::CreateShadowMapRenderer(spades::draw::GLRenderer *r) { + std::unique_ptr + GLShadowMapShader::CreateShadowMapRenderer(GLRenderer &r) { SPADES_MARK_FUNCTION(); - auto &settings = r->GetSettings(); - if (!settings.r_modelShadows) - return NULL; - if (settings.r_sparseShadowMaps) - return new GLSparseShadowMapRenderer(r); - return new GLBasicShadowMapRenderer(r); + auto &settings = r.GetSettings(); + if (!settings.r_modelShadows) { + return {}; + } + if (settings.r_sparseShadowMaps) { + return stmp::make_unique(r); + } else { + return stmp::make_unique(r); + } } int GLShadowMapShader::operator()(GLRenderer *renderer, spades::draw::GLProgram *program, @@ -83,5 +87,5 @@ namespace spades { return texStage; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLShadowMapShader.h b/Sources/Draw/GLShadowMapShader.h index f94fb29af..08fd1b5a0 100644 --- a/Sources/Draw/GLShadowMapShader.h +++ b/Sources/Draw/GLShadowMapShader.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include "GLProgramUniform.h" @@ -39,7 +40,7 @@ namespace spades { static std::vector RegisterShader(GLProgramManager *); - static IGLShadowMapRenderer *CreateShadowMapRenderer(GLRenderer *); + static std::unique_ptr CreateShadowMapRenderer(GLRenderer &); /** setups shadow map shader. * note that this function sets the current active texture @@ -48,5 +49,5 @@ namespace spades { * @return next available texture stage */ int operator()(GLRenderer *renderer, GLProgram *, int firstTexStage); }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades \ No newline at end of file diff --git a/Sources/Draw/GLShadowShader.cpp b/Sources/Draw/GLShadowShader.cpp index 8038a8ef8..0763d0d7f 100644 --- a/Sources/Draw/GLShadowShader.cpp +++ b/Sources/Draw/GLShadowShader.cpp @@ -95,11 +95,7 @@ namespace spades { } if (settings.r_radiosity) { - if ((int)settings.r_radiosity >= 2) { - shaders.push_back(r->RegisterShader("Shaders/Shadow/MapRadiosity.fs")); - } else { - shaders.push_back(r->RegisterShader("Shaders/Shadow/MapRadiosityLow.fs")); - } + shaders.push_back(r->RegisterShader("Shaders/Shadow/MapRadiosity.fs")); shaders.push_back(r->RegisterShader("Shaders/Shadow/MapRadiosity.vs")); } else { shaders.push_back(r->RegisterShader("Shaders/Shadow/MapRadiosityNull.fs")); @@ -131,7 +127,7 @@ namespace spades { dev->BindTexture(IGLDevice::Texture2D, renderer->mapShadowRenderer->GetTexture()); } else { // TODO: do this case properly - GLImage *img = (GLImage *)renderer->RegisterImage("Gfx/White.tga"); + auto img = renderer->RegisterImage("Gfx/White.tga").Cast(); img->Bind(IGLDevice::Texture2D); } mapShadowTexture.SetValue(texStage); @@ -289,8 +285,8 @@ namespace spades { ssaoTexture.SetValue(texStage); texStage++; - ssaoTextureUVScale.SetValue(1.0f / renderer->ScreenWidth(), - 1.0f / renderer->ScreenHeight()); + ssaoTextureUVScale.SetValue(1.0f / renderer->GetRenderWidth(), + 1.0f / renderer->GetRenderHeight()); } } @@ -298,5 +294,5 @@ namespace spades { return texStage; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLShadowShader.h b/Sources/Draw/GLShadowShader.h index ed337139d..b8f83bfdf 100644 --- a/Sources/Draw/GLShadowShader.h +++ b/Sources/Draw/GLShadowShader.h @@ -70,5 +70,5 @@ namespace spades { * @return next available texture stage */ int operator()(GLRenderer *renderer, GLProgram *, int firstTexStage); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSoftLitSpriteRenderer.cpp b/Sources/Draw/GLSoftLitSpriteRenderer.cpp index cb748c037..5749f96d4 100644 --- a/Sources/Draw/GLSoftLitSpriteRenderer.cpp +++ b/Sources/Draw/GLSoftLitSpriteRenderer.cpp @@ -19,7 +19,6 @@ */ #include "GLSoftLitSpriteRenderer.h" -#include #include "GLDynamicLight.h" #include "GLFramebufferManager.h" #include "GLImage.h" @@ -30,15 +29,16 @@ #include "GLShadowShader.h" #include "IGLDevice.h" #include "SWFeatureLevel.h" +#include #include namespace spades { namespace draw { - GLSoftLitSpriteRenderer::GLSoftLitSpriteRenderer(GLRenderer *renderer) + GLSoftLitSpriteRenderer::GLSoftLitSpriteRenderer(GLRenderer &renderer) : renderer(renderer), - settings(renderer->GetSettings()), - device(renderer->GetGLDevice()), + settings(renderer.GetSettings()), + device(renderer.GetGLDevice()), projectionViewMatrix("projectionViewMatrix"), rightVector("rightVector"), upVector("upVector"), @@ -60,7 +60,7 @@ namespace spades { dlBAttribute("dlBAttribute") { SPADES_MARK_FUNCTION(); - program = renderer->RegisterProgram("Shaders/SoftLitSprite.program"); + program = renderer.RegisterProgram("Shaders/SoftLitSprite.program"); } GLSoftLitSpriteRenderer::~GLSoftLitSpriteRenderer() { SPADES_MARK_FUNCTION(); } @@ -68,7 +68,7 @@ namespace spades { void GLSoftLitSpriteRenderer::Add(spades::draw::GLImage *img, spades::Vector3 center, float rad, float ang, Vector4 color) { SPADES_MARK_FUNCTION_DEBUG(); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); Sprite spr; spr.image = img; spr.center = center; @@ -116,7 +116,7 @@ namespace spades { return; // light every sprite - const std::vector &lights = renderer->lights; + const std::vector &lights = renderer.lights; for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; if (spr.color.w < .0001f && @@ -203,8 +203,8 @@ namespace spades { lastImage = NULL; program->Use(); - device->Enable(IGLDevice::Blend, true); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); + device.Enable(IGLDevice::Blend, true); + device.BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); projectionViewMatrix(program); rightVector(program); @@ -226,16 +226,16 @@ namespace spades { dlGAttribute(program); dlBAttribute(program); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); - viewMatrix.SetValue(renderer->GetViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); + viewMatrix.SetValue(renderer.GetViewMatrix()); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); - Vector3 fogCol = renderer->GetFogColor(); + Vector3 fogCol = renderer.GetFogColor(); fogCol *= fogCol; // linearize fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); rightVector.SetValue(def.viewAxis[0].x, def.viewAxis[0].y, def.viewAxis[0].z); upVector.SetValue(def.viewAxis[1].x, def.viewAxis[1].y, def.viewAxis[1].z); frontVector.SetValue(def.viewAxis[2].x, def.viewAxis[2].y, def.viewAxis[2].z); @@ -246,27 +246,27 @@ namespace spades { zNearFar.SetValue(def.zNear, def.zFar); static GLShadowShader shadowShader; - shadowShader(renderer, program, 2); + shadowShader(&renderer, program, 2); - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); - device->ActiveTexture(0); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); + device.ActiveTexture(0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(spritePosAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); - device->EnableVertexAttribArray(emissionAttribute(), true); - device->EnableVertexAttribArray(dlRAttribute(), true); - device->EnableVertexAttribArray(dlGAttribute(), true); - device->EnableVertexAttribArray(dlBAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(spritePosAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(emissionAttribute(), true); + device.EnableVertexAttribArray(dlRAttribute(), true); + device.EnableVertexAttribArray(dlGAttribute(), true); + device.EnableVertexAttribArray(dlBAttribute(), true); thresLow = tanf(def.fovX * .5f) * tanf(def.fovY * .5f) * 1.8f; thresRange = thresLow * .5f; // full-resolution sprites { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Full Resolution"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Full Resolution"); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; float layer = LayerForSprite(spr); @@ -320,18 +320,18 @@ namespace spades { } // low-res sprites - IGLDevice::UInteger lastFb = device->GetInteger(IGLDevice::FramebufferBinding); - int sW = device->ScreenWidth(), sH = device->ScreenHeight(); + IGLDevice::UInteger lastFb = device.GetInteger(IGLDevice::FramebufferBinding); + int sW = renderer.GetRenderWidth(), sH = renderer.GetRenderHeight(); int lW = (sW + 3) / 4, lH = (sH + 3) / 4; int numLowResSprites = 0; - GLColorBuffer buf = renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); - device->BindFramebuffer(IGLDevice::Framebuffer, buf.GetFramebuffer()); - device->ClearColor(0.f, 0.f, 0.f, 0.f); - device->Clear(IGLDevice::ColorBufferBit); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); - device->Viewport(0, 0, lW, lH); + GLColorBuffer buf = renderer.GetFramebufferManager()->CreateBufferHandle(lW, lH, true); + device.BindFramebuffer(IGLDevice::Framebuffer, buf.GetFramebuffer()); + device.ClearColor(0.f, 0.f, 0.f, 0.f); + device.Clear(IGLDevice::ColorBufferBit); + device.BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); + device.Viewport(0, 0, lW, lH); { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Low Resolution"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Low Resolution"); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; float layer = LayerForSprite(spr); @@ -387,27 +387,27 @@ namespace spades { // finalize - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, 0); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(spritePosAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); - device->EnableVertexAttribArray(emissionAttribute(), false); - device->EnableVertexAttribArray(dlRAttribute(), false); - device->EnableVertexAttribArray(dlGAttribute(), false); - device->EnableVertexAttribArray(dlBAttribute(), false); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(spritePosAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(emissionAttribute(), false); + device.EnableVertexAttribArray(dlRAttribute(), false); + device.EnableVertexAttribArray(dlGAttribute(), false); + device.EnableVertexAttribArray(dlBAttribute(), false); // composite downsampled sprite - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); + device.BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); if (numLowResSprites > 0) { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Finalize"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Finalize"); GLQuadRenderer qr(device); // do gaussian blur GLProgram *program = - renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program"); + renderer.RegisterProgram("Shaders/PostFilters/Gauss1D.program"); static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform("mainTexture"); static GLProgramUniform blur_unitShift("unitShift"); @@ -416,34 +416,34 @@ namespace spades { blur_textureUniform(program); blur_unitShift(program); blur_textureUniform.SetValue(0); - device->ActiveTexture(0); + device.ActiveTexture(0); qr.SetCoordAttributeIndex(blur_positionAttribute()); - device->Enable(IGLDevice::Blend, false); + device.Enable(IGLDevice::Blend, false); // x-direction GLColorBuffer buf2 = - renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); - device->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); - device->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + renderer.GetFramebufferManager()->CreateBufferHandle(lW, lH, true); + device.BindTexture(IGLDevice::Texture2D, buf.GetTexture()); + device.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); blur_unitShift.SetValue(1.f / lW, 0.f); qr.Draw(); buf.Release(); // x-direction GLColorBuffer buf3 = - renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); - device->BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); - device->BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); + renderer.GetFramebufferManager()->CreateBufferHandle(lW, lH, true); + device.BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); + device.BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); blur_unitShift.SetValue(0.f, 1.f / lH); qr.Draw(); buf2.Release(); buf = buf3; - device->Enable(IGLDevice::Blend, true); + device.Enable(IGLDevice::Blend, true); // composite - program = renderer->RegisterProgram("Shaders/PostFilters/PassThrough.program"); + program = renderer.RegisterProgram("Shaders/PostFilters/PassThrough.program"); static GLProgramAttribute positionAttribute("positionAttribute"); static GLProgramUniform colorUniform("colorUniform"); static GLProgramUniform textureUniform("mainTexture"); @@ -461,16 +461,16 @@ namespace spades { colorUniform.SetValue(1.f, 1.f, 1.f, 1.f); qr.SetCoordAttributeIndex(positionAttribute()); - device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); - device->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); - device->Viewport(0, 0, sW, sH); + device.BindFramebuffer(IGLDevice::Framebuffer, lastFb); + device.BindTexture(IGLDevice::Texture2D, buf.GetTexture()); + device.Viewport(0, 0, sW, sH); qr.Draw(); - device->BindTexture(IGLDevice::Texture2D, 0); + device.BindTexture(IGLDevice::Texture2D, 0); } else { - device->Viewport(0, 0, sW, sH); + device.Viewport(0, 0, sW, sH); - device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); + device.BindFramebuffer(IGLDevice::Framebuffer, lastFb); } buf.Release(); @@ -482,30 +482,29 @@ namespace spades { if (vertices.empty()) return; - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].x)); - device->VertexAttribPointer(spritePosAttribute(), 3, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].sx)); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].color)); - device->VertexAttribPointer(emissionAttribute(), 3, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].emission)); - device->VertexAttribPointer(dlRAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].dlR)); - device->VertexAttribPointer(dlGAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].dlG)); - device->VertexAttribPointer(dlBAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].dlB)); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].x)); + device.VertexAttribPointer(spritePosAttribute(), 3, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].sx)); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].color)); + device.VertexAttribPointer(emissionAttribute(), 3, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].emission)); + device.VertexAttribPointer(dlRAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].dlR)); + device.VertexAttribPointer(dlGAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].dlG)); + device.VertexAttribPointer(dlBAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].dlB)); SPAssert(lastImage); lastImage->Bind(IGLDevice::Texture2D); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedInt, indices.data()); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedInt, indices.data()); vertices.clear(); indices.clear(); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSoftLitSpriteRenderer.h b/Sources/Draw/GLSoftLitSpriteRenderer.h index 26f09a4eb..78183e164 100644 --- a/Sources/Draw/GLSoftLitSpriteRenderer.h +++ b/Sources/Draw/GLSoftLitSpriteRenderer.h @@ -23,10 +23,10 @@ #include #include -#include #include "GLProgramAttribute.h" #include "GLProgramUniform.h" #include "IGLSpriteRenderer.h" +#include namespace spades { namespace draw { @@ -63,9 +63,9 @@ namespace spades { Vector4 dlR, dlG, dlB; }; - GLRenderer *renderer; + GLRenderer &renderer; GLSettings &settings; - IGLDevice *device; + IGLDevice &device; std::vector sprites; GLImage *lastImage; @@ -101,12 +101,12 @@ namespace spades { float LayerForSprite(const Sprite &); public: - GLSoftLitSpriteRenderer(GLRenderer *); + GLSoftLitSpriteRenderer(GLRenderer &); ~GLSoftLitSpriteRenderer(); void Add(GLImage *img, Vector3 center, float rad, float ang, Vector4 color) override; void Clear() override; void Render() override; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSoftSpriteRenderer.cpp b/Sources/Draw/GLSoftSpriteRenderer.cpp index 5ea71934f..2da25c2a4 100644 --- a/Sources/Draw/GLSoftSpriteRenderer.cpp +++ b/Sources/Draw/GLSoftSpriteRenderer.cpp @@ -19,7 +19,6 @@ */ #include "GLSoftSpriteRenderer.h" -#include #include "GLFramebufferManager.h" #include "GLImage.h" #include "GLProfiler.h" @@ -28,14 +27,15 @@ #include "GLRenderer.h" #include "IGLDevice.h" #include "SWFeatureLevel.h" // for fastRcp +#include namespace spades { namespace draw { - GLSoftSpriteRenderer::GLSoftSpriteRenderer(GLRenderer *renderer) + GLSoftSpriteRenderer::GLSoftSpriteRenderer(GLRenderer &renderer) : renderer(renderer), - device(renderer->GetGLDevice()), - settings(renderer->GetSettings()), + device(renderer.GetGLDevice()), + settings(renderer.GetSettings()), projectionViewMatrix("projectionViewMatrix"), rightVector("rightVector"), upVector("upVector"), @@ -52,7 +52,7 @@ namespace spades { colorAttribute("colorAttribute") { SPADES_MARK_FUNCTION(); - program = renderer->RegisterProgram("Shaders/SoftSprite.program"); + program = renderer.RegisterProgram("Shaders/SoftSprite.program"); } GLSoftSpriteRenderer::~GLSoftSpriteRenderer() { SPADES_MARK_FUNCTION(); } @@ -60,7 +60,7 @@ namespace spades { void GLSoftSpriteRenderer::Add(spades::draw::GLImage *img, spades::Vector3 center, float rad, float ang, Vector4 color) { SPADES_MARK_FUNCTION_DEBUG(); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); Sprite spr; spr.image = img; spr.center = center; @@ -106,8 +106,8 @@ namespace spades { lastImage = NULL; program->Use(); - device->Enable(IGLDevice::Blend, true); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); + device.Enable(IGLDevice::Blend, true); + device.BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); projectionViewMatrix(program); rightVector(program); @@ -125,16 +125,16 @@ namespace spades { spritePosAttribute(program); colorAttribute(program); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); - viewMatrix.SetValue(renderer->GetViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); + viewMatrix.SetValue(renderer.GetViewMatrix()); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); - Vector3 fogCol = renderer->GetFogColor(); + Vector3 fogCol = renderer.GetFogColor(); fogCol *= fogCol; // linearize fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); rightVector.SetValue(def.viewAxis[0].x, def.viewAxis[0].y, def.viewAxis[0].z); upVector.SetValue(def.viewAxis[1].x, def.viewAxis[1].y, def.viewAxis[1].z); frontVector.SetValue(def.viewAxis[2].x, def.viewAxis[2].y, def.viewAxis[2].z); @@ -144,21 +144,21 @@ namespace spades { depthTexture.SetValue(1); zNearFar.SetValue(def.zNear, def.zFar); - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetDepthTexture()); - device->ActiveTexture(0); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); + device.ActiveTexture(0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(spritePosAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(spritePosAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); thresLow = tanf(def.fovX * .5f) * tanf(def.fovY * .5f) * 1.8f; thresRange = thresLow * .5f; // full-resolution sprites { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Full Resolution"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Full Resolution"); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; float layer = LayerForSprite(spr); @@ -213,18 +213,18 @@ namespace spades { } // low-res sprites - IGLDevice::UInteger lastFb = device->GetInteger(IGLDevice::FramebufferBinding); - int sW = device->ScreenWidth(), sH = device->ScreenHeight(); + IGLDevice::UInteger lastFb = device.GetInteger(IGLDevice::FramebufferBinding); + int sW = renderer.GetRenderWidth(), sH = renderer.GetRenderHeight(); int lW = (sW + 3) / 4, lH = (sH + 3) / 4; int numLowResSprites = 0; - GLColorBuffer buf = renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); - device->BindFramebuffer(IGLDevice::Framebuffer, buf.GetFramebuffer()); - device->ClearColor(0.f, 0.f, 0.f, 0.f); - device->Clear(IGLDevice::ColorBufferBit); - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); - device->Viewport(0, 0, lW, lH); + GLColorBuffer buf = renderer.GetFramebufferManager()->CreateBufferHandle(lW, lH, true); + device.BindFramebuffer(IGLDevice::Framebuffer, buf.GetFramebuffer()); + device.ClearColor(0.f, 0.f, 0.f, 0.f); + device.Clear(IGLDevice::ColorBufferBit); + device.BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); + device.Viewport(0, 0, lW, lH); { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Low Resolution"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Low Resolution"); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; float layer = LayerForSprite(spr); @@ -281,23 +281,23 @@ namespace spades { // finalize - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, 0); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(spritePosAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(spritePosAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); // composite downsampled sprite - device->BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); + device.BlendFunc(IGLDevice::One, IGLDevice::OneMinusSrcAlpha); if (numLowResSprites > 0) { - GLProfiler::Context measure(renderer->GetGLProfiler(), "Finalize"); + GLProfiler::Context measure(renderer.GetGLProfiler(), "Finalize"); GLQuadRenderer qr(device); // do gaussian blur GLProgram *program = - renderer->RegisterProgram("Shaders/PostFilters/Gauss1D.program"); + renderer.RegisterProgram("Shaders/PostFilters/Gauss1D.program"); static GLProgramAttribute blur_positionAttribute("positionAttribute"); static GLProgramUniform blur_textureUniform("mainTexture"); static GLProgramUniform blur_unitShift("unitShift"); @@ -306,34 +306,34 @@ namespace spades { blur_textureUniform(program); blur_unitShift(program); blur_textureUniform.SetValue(0); - device->ActiveTexture(0); + device.ActiveTexture(0); qr.SetCoordAttributeIndex(blur_positionAttribute()); - device->Enable(IGLDevice::Blend, false); + device.Enable(IGLDevice::Blend, false); // x-direction GLColorBuffer buf2 = - renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); - device->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); - device->BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); + renderer.GetFramebufferManager()->CreateBufferHandle(lW, lH, true); + device.BindTexture(IGLDevice::Texture2D, buf.GetTexture()); + device.BindFramebuffer(IGLDevice::Framebuffer, buf2.GetFramebuffer()); blur_unitShift.SetValue(1.f / lW, 0.f); qr.Draw(); buf.Release(); // x-direction GLColorBuffer buf3 = - renderer->GetFramebufferManager()->CreateBufferHandle(lW, lH, true); - device->BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); - device->BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); + renderer.GetFramebufferManager()->CreateBufferHandle(lW, lH, true); + device.BindTexture(IGLDevice::Texture2D, buf2.GetTexture()); + device.BindFramebuffer(IGLDevice::Framebuffer, buf3.GetFramebuffer()); blur_unitShift.SetValue(0.f, 1.f / lH); qr.Draw(); buf2.Release(); buf = buf3; - device->Enable(IGLDevice::Blend, true); + device.Enable(IGLDevice::Blend, true); // composite - program = renderer->RegisterProgram("Shaders/PostFilters/PassThrough.program"); + program = renderer.RegisterProgram("Shaders/PostFilters/PassThrough.program"); static GLProgramAttribute positionAttribute("positionAttribute"); static GLProgramUniform colorUniform("colorUniform"); static GLProgramUniform textureUniform("mainTexture"); @@ -351,16 +351,16 @@ namespace spades { colorUniform.SetValue(1.f, 1.f, 1.f, 1.f); qr.SetCoordAttributeIndex(positionAttribute()); - device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); - device->BindTexture(IGLDevice::Texture2D, buf.GetTexture()); - device->Viewport(0, 0, sW, sH); + device.BindFramebuffer(IGLDevice::Framebuffer, lastFb); + device.BindTexture(IGLDevice::Texture2D, buf.GetTexture()); + device.Viewport(0, 0, sW, sH); qr.Draw(); - device->BindTexture(IGLDevice::Texture2D, 0); + device.BindTexture(IGLDevice::Texture2D, 0); } else { - device->Viewport(0, 0, sW, sH); + device.Viewport(0, 0, sW, sH); - device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); + device.BindFramebuffer(IGLDevice::Framebuffer, lastFb); } buf.Release(); @@ -372,22 +372,21 @@ namespace spades { if (vertices.empty()) return; - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].x)); - device->VertexAttribPointer(spritePosAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].sx)); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].r)); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].x)); + device.VertexAttribPointer(spritePosAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].sx)); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].r)); SPAssert(lastImage); lastImage->Bind(IGLDevice::Texture2D); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedInt, indices.data()); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedInt, indices.data()); vertices.clear(); indices.clear(); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSoftSpriteRenderer.h b/Sources/Draw/GLSoftSpriteRenderer.h index 87af277ef..faac93207 100644 --- a/Sources/Draw/GLSoftSpriteRenderer.h +++ b/Sources/Draw/GLSoftSpriteRenderer.h @@ -23,10 +23,10 @@ #include #include -#include #include "GLProgramAttribute.h" #include "GLProgramUniform.h" #include "IGLSpriteRenderer.h" +#include namespace spades { namespace draw { @@ -57,8 +57,8 @@ namespace spades { float r, g, b, a; }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLSettings &settings; std::vector sprites; @@ -90,12 +90,12 @@ namespace spades { float LayerForSprite(const Sprite &); public: - GLSoftSpriteRenderer(GLRenderer *); + GLSoftSpriteRenderer(GLRenderer &); ~GLSoftSpriteRenderer(); void Add(GLImage *img, Vector3 center, float rad, float ang, Vector4 color) override; void Clear() override; void Render() override; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSparseShadowMapRenderer.cpp b/Sources/Draw/GLSparseShadowMapRenderer.cpp index 21a0ee09d..011cb1ebf 100644 --- a/Sources/Draw/GLSparseShadowMapRenderer.cpp +++ b/Sources/Draw/GLSparseShadowMapRenderer.cpp @@ -19,21 +19,20 @@ */ #include "GLSparseShadowMapRenderer.h" -#include -#include -#include #include "GLModel.h" #include "GLModelRenderer.h" #include "GLProfiler.h" #include "GLRenderer.h" -#include "GLRenderer.h" #include "IGLDevice.h" +#include +#include +#include namespace spades { namespace draw { - GLSparseShadowMapRenderer::GLSparseShadowMapRenderer(GLRenderer *r) - : IGLShadowMapRenderer(r), device(r->GetGLDevice()), settings(r->GetSettings()) { + GLSparseShadowMapRenderer::GLSparseShadowMapRenderer(GLRenderer &r) + : IGLShadowMapRenderer(r), device(r.GetGLDevice()), settings(r.GetSettings()) { SPADES_MARK_FUNCTION(); textureSize = settings.r_shadowMapSize; @@ -48,63 +47,63 @@ namespace spades { minLod = 0; maxLod = 15; - colorTexture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, colorTexture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGB, textureSize, textureSize, 0, - IGLDevice::RGB, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - texture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, texture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, textureSize, - textureSize, 0, IGLDevice::DepthComponent, IGLDevice::UnsignedInt, - NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - pagetableTexture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, pagetableTexture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, Tiles, Tiles, 0, - IGLDevice::BGRA, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - framebuffer = device->GenFramebuffer(); - device->BindFramebuffer(IGLDevice::Framebuffer, framebuffer); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, - IGLDevice::Texture2D, colorTexture, 0); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, - IGLDevice::Texture2D, texture, 0); - - device->BindFramebuffer(IGLDevice::Framebuffer, 0); + colorTexture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, colorTexture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGB, textureSize, textureSize, 0, + IGLDevice::RGB, IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + texture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, texture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, textureSize, + textureSize, 0, IGLDevice::DepthComponent, IGLDevice::UnsignedInt, + NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + pagetableTexture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, pagetableTexture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, Tiles, Tiles, 0, + IGLDevice::BGRA, IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + framebuffer = device.GenFramebuffer(); + device.BindFramebuffer(IGLDevice::Framebuffer, framebuffer); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, colorTexture, 0); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, + IGLDevice::Texture2D, texture, 0); + + device.BindFramebuffer(IGLDevice::Framebuffer, 0); } GLSparseShadowMapRenderer::~GLSparseShadowMapRenderer() { SPADES_MARK_FUNCTION(); - device->DeleteTexture(texture); - device->DeleteTexture(pagetableTexture); - device->DeleteFramebuffer(framebuffer); - device->DeleteTexture(colorTexture); + device.DeleteTexture(texture); + device.DeleteTexture(pagetableTexture); + device.DeleteFramebuffer(framebuffer); + device.DeleteTexture(colorTexture); } #define Segment GLSSMRSegment @@ -159,7 +158,7 @@ namespace spades { up = Vector3::Cross(lightDir, side).Normalize(); // build frustrum - client::SceneDefinition def = GetRenderer()->GetSceneDef(); + client::SceneDefinition def = GetRenderer().GetSceneDef(); Vector3 frustrum[8]; float tanX = tanf(def.fovX * .5f); float tanY = tanf(def.fovY * .5f); @@ -241,25 +240,17 @@ namespace spades { void GLSparseShadowMapRenderer::Render() { SPADES_MARK_FUNCTION(); - IGLDevice::Integer lastFb = device->GetInteger(IGLDevice::FramebufferBinding); - - // client::SceneDefinition def = GetRenderer()->GetSceneDef(); - float nearDist = 0.f; float farDist = 150.f; BuildMatrix(nearDist, farDist); - device->BindFramebuffer(IGLDevice::Framebuffer, framebuffer); - device->Viewport(0, 0, textureSize, textureSize); - device->ClearDepth(1.f); - device->Clear(IGLDevice::DepthBufferBit); + device.BindFramebuffer(IGLDevice::Framebuffer, framebuffer); + device.Viewport(0, 0, textureSize, textureSize); + device.ClearDepth(1.f); + device.Clear(IGLDevice::DepthBufferBit); RenderShadowMapPass(); - - device->BindFramebuffer(IGLDevice::Framebuffer, lastFb); - - device->Viewport(0, 0, device->ScreenWidth(), device->ScreenHeight()); } #pragma mark - Sparse Processor @@ -270,7 +261,7 @@ namespace spades { static const size_t GroupNodeFlag = NoNode ^ (NoNode >> 1); struct GLSparseShadowMapRenderer::Internal { - GLSparseShadowMapRenderer *renderer; + GLSparseShadowMapRenderer &renderer; Vector3 cameraShadowCoord; typedef int LodUnit; @@ -476,12 +467,13 @@ namespace spades { } } - Internal(GLSparseShadowMapRenderer *r) : renderer(r) { + Internal(GLSparseShadowMapRenderer &r) : renderer(r) { - GLProfiler::Context profiler(r->GetRenderer()->GetGLProfiler(), "Sparse Page Table Generation"); + GLProfiler::Context profiler(r.GetRenderer().GetGLProfiler(), + "Sparse Page Table Generation"); - cameraShadowCoord = r->GetRenderer()->GetSceneDef().viewOrigin; - cameraShadowCoord = (r->matrix * cameraShadowCoord).GetXYZ(); + cameraShadowCoord = r.GetRenderer().GetSceneDef().viewOrigin; + cameraShadowCoord = (r.matrix * cameraShadowCoord).GetXYZ(); // clear group maps for (size_t x = 0; x < Tiles; x++) @@ -489,7 +481,7 @@ namespace spades { groupMap[x][y] = NoGroup; const std::vector &rmodels = - renderer->GetRenderer()->GetModelRenderer()->models; + renderer.GetRenderer().GetModelRenderer()->models; allInstances.reserve(256); groups.reserve(64); nodes.reserve(256); @@ -509,7 +501,7 @@ namespace spades { OBB3 instWorldBoundsOBB = inst.param->matrix * modelBounds; // w should be 1, so this should wor - OBB3 instBoundsOBB = r->matrix * instWorldBoundsOBB; + OBB3 instBoundsOBB = r.matrix * instWorldBoundsOBB; AABB3 instBounds = instBoundsOBB.GetBoundingAABB(); // frustrum(?) cull @@ -562,7 +554,7 @@ namespace spades { } } - mapSize = r->settings.r_shadowMapSize; + mapSize = r.settings.r_shadowMapSize; } bool AddGroupToNode(size_t &nodeRef, int nx, int ny, int nw, int nh, size_t gId) { @@ -572,8 +564,8 @@ namespace spades { int w = g.tile2.x - g.tile1.x; int h = g.tile2.y - g.tile1.y; int lod = g.lod; - int minLod = renderer->minLod; - int maxLod = renderer->maxLod; + int minLod = renderer.minLod; + int maxLod = renderer.maxLod; lod += lodBias; if (lod < minLod) lod = minLod; @@ -663,7 +655,8 @@ namespace spades { if (groups.empty()) return; - GLProfiler::Context profiler(renderer->GetRenderer()->GetGLProfiler(), "Pack [%d group(s)]", (int)groups.size()); + GLProfiler::Context profiler(renderer.GetRenderer().GetGLProfiler(), + "Pack [%d group(s)]", (int)groups.size()); lodBias = 100; if (TryPack()) { @@ -708,11 +701,12 @@ namespace spades { }; void GLSparseShadowMapRenderer::RenderShadowMapPass() { - Internal itnl(this); + Internal itnl(*this); itnl.Pack(); { - GLProfiler::Context profiler(GetRenderer()->GetGLProfiler(), "Page Table Generation"); + GLProfiler::Context profiler(GetRenderer().GetGLProfiler(), + "Page Table Generation"); for (int x = 0; x < Tiles; x++) { for (int y = 0; y < Tiles; y++) { size_t val = itnl.groupMap[x][y]; @@ -749,19 +743,20 @@ namespace spades { } { - GLProfiler::Context profiler(GetRenderer()->GetGLProfiler(), "Page Table Upload"); - device->BindTexture(IGLDevice::Texture2D, pagetableTexture); - device->TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, Tiles, Tiles, IGLDevice::BGRA, - IGLDevice::UnsignedByte, pagetable); + GLProfiler::Context profiler(GetRenderer().GetGLProfiler(), "Page Table Upload"); + device.BindTexture(IGLDevice::Texture2D, pagetableTexture); + device.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, Tiles, Tiles, IGLDevice::BGRA, + IGLDevice::UnsignedByte, pagetable); } Matrix4 baseMatrix = matrix; { - GLProfiler::Context profiler(GetRenderer()->GetGLProfiler(), "Shadow Maps [%d group(s)]", (int)itnl.groups.size()); + GLProfiler::Context profiler(GetRenderer().GetGLProfiler(), + "Shadow Maps [%d group(s)]", (int)itnl.groups.size()); ModelRenderer mrend; for (size_t i = 0; i < itnl.groups.size(); i++) { Internal::Group &g = itnl.groups[i]; - device->Viewport(g.rawX, g.rawY, g.rawW, g.rawH); + device.Viewport(g.rawX, g.rawY, g.rawW, g.rawH); Vector3 dest1 = Internal::TileToShadowMapCoord(g.tile1); Vector3 dest2 = Internal::TileToShadowMapCoord(g.tile2); @@ -815,8 +810,8 @@ namespace spades { float yy = fabsf(vw.y); float rx = rad * vpWidth; float ry = rad * vpHeight; - + return xx < (1.f + rx) && yy < (1.f + ry);*/ } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSparseShadowMapRenderer.h b/Sources/Draw/GLSparseShadowMapRenderer.h index 5dc0c748f..7c7187fe2 100644 --- a/Sources/Draw/GLSparseShadowMapRenderer.h +++ b/Sources/Draw/GLSparseShadowMapRenderer.h @@ -37,7 +37,7 @@ namespace spades { enum { Tiles = 64 }; - IGLDevice *device; + IGLDevice &device; GLSettings &settings; int textureSize; @@ -63,12 +63,12 @@ namespace spades { void RenderShadowMapPass() override; public: - GLSparseShadowMapRenderer(GLRenderer *); + GLSparseShadowMapRenderer(GLRenderer &); ~GLSparseShadowMapRenderer(); void Render() override; bool Cull(const AABB3 &) override; bool SphereCull(const Vector3 ¢er, float rad) override; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSpriteRenderer.cpp b/Sources/Draw/GLSpriteRenderer.cpp index 44bdea646..3bd66a6fe 100644 --- a/Sources/Draw/GLSpriteRenderer.cpp +++ b/Sources/Draw/GLSpriteRenderer.cpp @@ -19,20 +19,20 @@ */ #include "GLSpriteRenderer.h" -#include #include "GLImage.h" #include "GLProgram.h" #include "GLRenderer.h" #include "IGLDevice.h" #include "SWFeatureLevel.h" +#include namespace spades { namespace draw { - GLSpriteRenderer::GLSpriteRenderer(GLRenderer *renderer) + GLSpriteRenderer::GLSpriteRenderer(GLRenderer &renderer) : renderer(renderer), - device(renderer->GetGLDevice()), - settings(renderer->GetSettings()), + device(renderer.GetGLDevice()), + settings(renderer.GetSettings()), projectionViewMatrix("projectionViewMatrix"), rightVector("rightVector"), upVector("upVector"), @@ -46,7 +46,7 @@ namespace spades { colorAttribute("colorAttribute") { SPADES_MARK_FUNCTION(); - program = renderer->RegisterProgram("Shaders/Sprite.program"); + program = renderer.RegisterProgram("Shaders/Sprite.program"); } GLSpriteRenderer::~GLSpriteRenderer() { SPADES_MARK_FUNCTION(); } @@ -101,28 +101,28 @@ namespace spades { spritePosAttribute(program); colorAttribute(program); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); - viewMatrix.SetValue(renderer->GetViewMatrix()); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); + viewMatrix.SetValue(renderer.GetViewMatrix()); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); - Vector3 fogCol = renderer->GetFogColor(); + Vector3 fogCol = renderer.GetFogColor(); fogCol *= fogCol; fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); rightVector.SetValue(def.viewAxis[0].x, def.viewAxis[0].y, def.viewAxis[0].z); upVector.SetValue(def.viewAxis[1].x, def.viewAxis[1].y, def.viewAxis[1].z); texture.SetValue(0); - device->ActiveTexture(0); + device.ActiveTexture(0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(spritePosAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(spritePosAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); for (size_t i = 0; i < sprites.size(); i++) { Sprite &spr = sprites[i]; @@ -167,9 +167,9 @@ namespace spades { Flush(); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(spritePosAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(spritePosAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); } void GLSpriteRenderer::Flush() { @@ -178,22 +178,21 @@ namespace spades { if (vertices.empty()) return; - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].x)); - device->VertexAttribPointer(spritePosAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].sx)); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, - sizeof(Vertex), &(vertices[0].r)); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].x)); + device.VertexAttribPointer(spritePosAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].sx)); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::FloatType, false, + sizeof(Vertex), &(vertices[0].r)); SPAssert(lastImage); lastImage->Bind(IGLDevice::Texture2D); - device->DrawElements(IGLDevice::Triangles, - static_cast(indices.size()), - IGLDevice::UnsignedInt, indices.data()); + device.DrawElements(IGLDevice::Triangles, static_cast(indices.size()), + IGLDevice::UnsignedInt, indices.data()); vertices.clear(); indices.clear(); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLSpriteRenderer.h b/Sources/Draw/GLSpriteRenderer.h index 94c40c465..68e20c74f 100644 --- a/Sources/Draw/GLSpriteRenderer.h +++ b/Sources/Draw/GLSpriteRenderer.h @@ -23,10 +23,10 @@ #include #include -#include #include "GLProgramAttribute.h" #include "GLProgramUniform.h" #include "IGLSpriteRenderer.h" +#include namespace spades { namespace draw { @@ -56,8 +56,8 @@ namespace spades { float r, g, b, a; }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLSettings &settings; std::vector sprites; @@ -83,12 +83,12 @@ namespace spades { void Flush(); public: - GLSpriteRenderer(GLRenderer *); + GLSpriteRenderer(GLRenderer &); ~GLSpriteRenderer(); void Add(GLImage *img, Vector3 center, float rad, float ang, Vector4 color) override; void Clear() override; void Render() override; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLTemporalAAFilter.cpp b/Sources/Draw/GLTemporalAAFilter.cpp new file mode 100644 index 000000000..f46ea0085 --- /dev/null +++ b/Sources/Draw/GLTemporalAAFilter.cpp @@ -0,0 +1,387 @@ +/* + Copyright (c) 2017 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +#include + +#include "GLFXAAFilter.h" +#include "GLProfiler.h" +#include "GLProgram.h" +#include "GLProgramAttribute.h" +#include "GLProgramUniform.h" +#include "GLQuadRenderer.h" +#include "GLRenderer.h" +#include "GLTemporalAAFilter.h" +#include "IGLDevice.h" +#include +#include + +namespace spades { + namespace draw { + GLTemporalAAFilter::GLTemporalAAFilter(GLRenderer &renderer) : renderer(renderer) { + prevMatrix = Matrix4::Identity(); + prevViewOrigin = Vector3(0.0f, 0.0f, 0.0f); + program = renderer.RegisterProgram("Shaders/PostFilters/TemporalAA.program"); + + // Preload + GLFXAAFilter{renderer}; + } + + GLTemporalAAFilter::~GLTemporalAAFilter() { DeleteHistoryBuffer(); } + + void GLTemporalAAFilter::DeleteHistoryBuffer() { + if (!historyBuffer.valid) { + return; + } + + IGLDevice &dev = renderer.GetGLDevice(); + dev.DeleteFramebuffer(historyBuffer.framebuffer); + dev.DeleteTexture(historyBuffer.texture); + + historyBuffer.valid = false; + } + + GLColorBuffer GLTemporalAAFilter::Filter(GLColorBuffer input, bool useFxaa) { + SPADES_MARK_FUNCTION(); + + IGLDevice &dev = renderer.GetGLDevice(); + GLQuadRenderer qr(dev); + + // Calculate the current view-projection matrix. + const client::SceneDefinition &def = renderer.GetSceneDef(); + Matrix4 newMatrix = Matrix4::Identity(); + Vector3 axes[] = {def.viewAxis[0], def.viewAxis[1], def.viewAxis[2]}; + newMatrix.m[0] = axes[0].x; + newMatrix.m[1] = axes[1].x; + newMatrix.m[2] = -axes[2].x; + newMatrix.m[4] = axes[0].y; + newMatrix.m[5] = axes[1].y; + newMatrix.m[6] = -axes[2].y; + newMatrix.m[8] = axes[0].z; + newMatrix.m[9] = axes[1].z; + newMatrix.m[10] = -axes[2].z; + + Matrix4 projectionMatrix; + { + // From `GLRenderer::BuildProjectionMatrix` + float near = def.zNear; + float far = def.zFar; + float t = near * std::tan(def.fovY * .5f); + float r = near * std::tan(def.fovX * .5f); + float a = r * 2.f, b = t * 2.f, c = far - near; + Matrix4 &mat = projectionMatrix; + mat.m[0] = near * 2.f / a; + mat.m[1] = 0.f; + mat.m[2] = 0.f; + mat.m[3] = 0.f; + mat.m[4] = 0.f; + mat.m[5] = near * 2.f / b; + mat.m[6] = 0.f; + mat.m[7] = 0.f; + mat.m[8] = 0.f; + mat.m[9] = 0.f; + mat.m[10] = -(far + near) / c; + mat.m[11] = -1.f; + mat.m[12] = 0.f; + mat.m[13] = 0.f; + mat.m[14] = -(far * near * 2.f) / c; + mat.m[15] = 0.f; + } + + newMatrix = projectionMatrix * newMatrix; + + // In `y = newMatrix * x`, the coordinate space `y` belongs to must + // cover the clip region by range `[0, 1]` (like texture coordinates) + // instead of `[-1, 1]` (like OpenGL clip coordinates) + newMatrix = Matrix4::Translate(1.0f, 1.0f, 1.0f) * newMatrix; + newMatrix = Matrix4::Scale(0.5f, 0.5f, 0.5f) * newMatrix; + + // Camera translation must be incorporated into the calculation + // separately to avoid numerical errors. (You'd be suprised to see + // how visible the visual artifacts can be.) + Matrix4 translationMatrix = Matrix4::Translate(def.viewOrigin - prevViewOrigin); + + // Compute the reprojection matrix + Matrix4 inverseNewMatrix = newMatrix.Inversed(); + Matrix4 diffMatrix = prevMatrix * translationMatrix * inverseNewMatrix; + prevMatrix = newMatrix; + prevViewOrigin = def.viewOrigin; + + if (!historyBuffer.valid || historyBuffer.width != input.GetWidth() || + historyBuffer.height != input.GetHeight()) { + DeleteHistoryBuffer(); + + historyBuffer.width = input.GetWidth(); + historyBuffer.height = input.GetHeight(); + + auto internalFormat = renderer.GetFramebufferManager()->GetMainInternalFormat(); + + historyBuffer.framebuffer = dev.GenFramebuffer(); + dev.BindFramebuffer(IGLDevice::Framebuffer, historyBuffer.framebuffer); + + historyBuffer.texture = dev.GenTexture(); + dev.BindTexture(IGLDevice::Texture2D, historyBuffer.texture); + + historyBuffer.valid = true; + + SPLog("Creating a history buffer"); + dev.TexImage2D(IGLDevice::Texture2D, 0, internalFormat, historyBuffer.width, + historyBuffer.height, 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, + NULL); + SPLog("History buffer allocated"); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + dev.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + dev.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, + IGLDevice::Texture2D, historyBuffer.texture, 0); + + IGLDevice::Enum status = dev.CheckFramebufferStatus(IGLDevice::Framebuffer); + if (status != IGLDevice::FramebufferComplete) { + SPRaise("Failed to create a history buffer."); + } + SPLog("Created a history framebuffer"); + + // Initialize the history buffer with the latest input + dev.BindFramebuffer(IGLDevice::DrawFramebuffer, historyBuffer.framebuffer); + dev.BindFramebuffer(IGLDevice::ReadFramebuffer, input.GetFramebuffer()); + dev.BlitFramebuffer(0, 0, input.GetWidth(), input.GetHeight(), 0, 0, + input.GetWidth(), input.GetHeight(), IGLDevice::ColorBufferBit, + IGLDevice::Nearest); + dev.BindFramebuffer(IGLDevice::ReadFramebuffer, 0); + dev.BindFramebuffer(IGLDevice::DrawFramebuffer, 0); + + // Reset the blending factor + dev.BindFramebuffer(IGLDevice::Framebuffer, historyBuffer.framebuffer); + dev.ColorMask(false, false, false, true); + dev.ClearColor(0.0f, 0.0f, 0.0f, 0.5f); + dev.Clear(IGLDevice::ColorBufferBit); + dev.ColorMask(true, true, true, true); + + if (useFxaa) { + return GLFXAAFilter{renderer}.Filter(input); + } + + return input; + } + + GLColorBuffer output = input.GetManager()->CreateBufferHandle(); + + GLColorBuffer processedInput = input; + /* // this didn't work well: + GLColorBuffer processedInput = + useFxaa ? [&] { + GLProfiler::Context p(renderer.GetGLProfiler(), "FXAA"); + return GLFXAAFilter{renderer}.Filter(input); + }() : input; */ + + static GLProgramAttribute positionAttribute("positionAttribute"); + static GLProgramUniform inputTexture("inputTexture"); + static GLProgramUniform depthTexture("depthTexture"); + static GLProgramUniform previousTexture("previousTexture"); + static GLProgramUniform processedInputTexture("processedInputTexture"); + static GLProgramUniform reprojectionMatrix("reprojectionMatrix"); + static GLProgramUniform inverseVP("inverseVP"); + static GLProgramUniform viewProjectionMatrixInv("viewProjectionMatrixInv"); + static GLProgramUniform fogDistance("fogDistance"); + + dev.Enable(IGLDevice::Blend, false); + + positionAttribute(program); + inputTexture(program); + depthTexture(program); + previousTexture(program); + processedInputTexture(program); + reprojectionMatrix(program); + inverseVP(program); + viewProjectionMatrixInv(program); + fogDistance(program); + + program->Use(); + + inputTexture.SetValue(0); + previousTexture.SetValue(1); + processedInputTexture.SetValue(2); + depthTexture.SetValue(3); + reprojectionMatrix.SetValue(diffMatrix); + inverseVP.SetValue(1.f / input.GetWidth(), 1.f / input.GetHeight()); + viewProjectionMatrixInv.SetValue(inverseNewMatrix); + fogDistance.SetValue(128.f); + + // Perform temporal AA + // TODO: pre/post tone mapping to prevent aliasing near overbright area + qr.SetCoordAttributeIndex(positionAttribute()); + dev.ActiveTexture(0); + dev.BindTexture(IGLDevice::Texture2D, input.GetTexture()); + dev.ActiveTexture(1); + dev.BindTexture(IGLDevice::Texture2D, historyBuffer.texture); + dev.ActiveTexture(2); + dev.BindTexture(IGLDevice::Texture2D, processedInput.GetTexture()); + dev.ActiveTexture(3); + dev.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetDepthTexture()); + dev.ActiveTexture(0); + dev.BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer()); + dev.Viewport(0, 0, output.GetWidth(), output.GetHeight()); + qr.Draw(); + dev.BindTexture(IGLDevice::Texture2D, 0); + + // Copy the result to the history buffer + dev.BindFramebuffer(IGLDevice::DrawFramebuffer, historyBuffer.framebuffer); + dev.BindFramebuffer(IGLDevice::ReadFramebuffer, output.GetFramebuffer()); + dev.BlitFramebuffer(0, 0, input.GetWidth(), input.GetHeight(), 0, 0, input.GetWidth(), + input.GetHeight(), IGLDevice::ColorBufferBit, IGLDevice::Nearest); + dev.BindFramebuffer(IGLDevice::ReadFramebuffer, 0); + dev.BindFramebuffer(IGLDevice::DrawFramebuffer, 0); + return output; + } + + Vector2 GLTemporalAAFilter::GetProjectionMatrixJitter() { + // Obtained from Hyper3D (MIT licensed) + static const std::vector jitterTable = { + 0.281064, 0.645281, -0.167313, 0.685935, -0.160711, -0.113289, + 1.08453, -0.0970135, -0.3655, -0.51894, 0.275308, -0.000830889, + -0.0431051, 0.574405, -0.163071, -0.30989, 0.372959, -0.0161521, + 0.131741, 0.456781, 0.0165477, -0.0975113, -0.273682, -0.509164, + 0.573244, -0.714618, -0.479023, 0.0525875, 0.316595, -0.148211, + -0.423713, -0.22462, -0.528986, 0.390866, 0.0439115, -0.274567, + 0.106133, -0.377686, 0.481055, 0.398664, 0.314325, 0.839894, + -0.625382, 0.0543475, -0.201899, 0.198677, 0.0182834, 0.621111, + 0.128773, -0.265686, 0.602337, 0.296946, 0.773769, 0.0479956, + -0.132997, -0.0410526, -0.254838, 0.326185, 0.347585, -0.580061, + 0.405482, 0.101755, -0.201249, 0.306534, 0.469578, -0.111657, + -0.796765, -0.0773768, -0.538891, 0.206104, -0.0794146, 0.098465, + 0.413728, 0.0259771, -0.823897, 0.0925169, 0.88273, -0.184931, + -0.134422, -0.247737, -0.682095, 0.177566, 0.299386, -0.329205, + 0.0488276, 0.504052, 0.268825, 0.395508, -1.10225, 0.101069, + -0.0408943, -0.580797, -0.00804806, -0.402047, -0.418787, 0.697977, + -0.308492, -0.122199, 0.628944, 0.54588, 0.0622768, -0.488552, + 0.0474367, 0.215963, -0.679212, 0.311237, -0.000920773, -0.721814, + 0.579613, -0.0458724, -0.467233, 0.268248, 0.246741, -0.15576, + 0.0473638, 0.0246596, -0.572414, -0.419131, -0.357526, 0.452787, + -0.112269, 0.710673, -0.41551, 0.429337, 0.0882859, -0.433878, + -0.0818105, -0.180361, 0.36754, -0.49486, 0.449489, -0.837214, + -1.09047, 0.168766, -0.163687, 0.256186, 0.633943, -0.012522, + 0.631576, -0.27161, -0.15392, -0.471082, -0.071748, -0.275351, + -0.134404, 0.126987, -0.478438, -0.144772, -0.38336, 0.37449, + -0.458729, -0.318997, -0.313852, 0.081244, -0.287645, 0.200266, + -0.45997, 0.108317, -0.216842, -0.165177, -0.296687, 0.771041, + 0.933613, 0.617833, -0.263007, -0.236543, -0.406302, 0.241173, + -0.225985, -0.108225, 0.087069, -0.0444767, 0.645569, -0.112983, + -0.689477, 0.498425, 0.0738087, 0.447277, 0.0972104, -0.314627, + 0.393365, -0.0919185, -0.32199, -0.193414, -0.126091, 0.185217, + 0.318475, 0.140509, -0.115877, -0.911059, 0.336104, -0.645395, + 0.00686884, -0.172296, -0.513633, -0.302956, -1.20699, 0.148284, + 0.357629, 0.58123, 0.106886, -0.872183, -0.49183, -0.202535, + -0.869357, 0.0371933, -0.0869231, 0.22624, 0.198995, 0.191016, + 0.151591, 0.347114, 0.056674, -0.213039, -0.228541, -0.473257, + -0.574876, -0.0826995, -0.730448, 0.343791, 0.795006, 0.366191, + 0.419235, -1.11688, 0.227321, -0.0937171, 0.156708, -0.3307, + 0.328026, -0.454046, 0.432153, -0.189323, 0.31821, 0.312532, + 0.0963759, 0.126471, -0.396326, 0.0353236, -0.366891, -0.279321, + 0.106791, 0.0697961, 0.383726, 0.260039, 0.00297499, 0.45812, + -0.544967, -0.230453, -0.150821, -0.374241, -0.739835, 0.462278, + -0.76681, -0.455701, 0.261229, 0.274824, 0.161605, -0.402379, + 0.571192, 0.0844102, -0.47416, 0.683535, 0.144919, -0.134556, + -0.0414159, 0.357005, -0.643226, -0.00324917, -0.173286, 0.770447, + 0.261563, 0.707628, 0.131681, 0.539707, -0.367105, 0.150912, + -0.310055, -0.270554, 0.686523, 0.195065, 0.282361, 0.569649, + 0.106642, 0.296521, 0.185682, 0.124763, 0.182832, 0.42824, + -0.489455, 0.55954, 0.383582, 0.52804, -0.236162, -0.356153, + 0.70445, -0.300133, 1.06101, 0.0289559, 0.4671, -0.0455821, + -1.18106, 0.26797, 0.223324, 0.793996, -0.833809, -0.412982, + -0.443497, -0.634181, -0.000902414, -0.319155, 0.629076, -0.378669, + -0.230422, 0.489184, 0.122302, 0.397895, 0.421496, -0.41475, + 0.192182, -0.477254, -0.32989, 0.285264, -0.0248513, -0.224073, + 0.520192, 0.138148, 0.783388, 0.540348, -0.468401, 0.189778, + 0.327808, 0.387399, 0.0163817, 0.340137, -0.174623, -0.560019, + -0.32246, 0.353305, 0.513422, -0.472848, -0.0151656, 0.0802364, + -0.0833406, 0.000303745, -0.359159, -0.666926, 0.446711, -0.254889, + -0.263977, 0.534997, 0.555322, -0.315034, -0.62762, -0.14342, + -0.78082, 0.29739, 0.0783401, -0.665565, -0.177726, 0.62018, + -0.723053, 0.108446, 0.550657, 0.00324011, 0.387362, -0.251661, + -0.616413, -0.260163, -0.798613, 0.0174665, -0.208833, -0.0398486, + -0.506167, 0.00121689, -0.75707, -0.0326216, 0.30282, 0.085227, + -0.27267, 0.25662, 0.182456, -0.184061, -0.577699, -0.685311, + 0.587003, 0.35393, -0.276868, -0.0617566, -0.365888, 0.673723, + -0.0476918, -0.0914235, 0.560627, -0.387913, -0.194537, 0.135256, + -0.0808623, 0.315394, -0.0383463, 0.267406, 0.545766, -0.659403, + -0.410556, 0.305285, 0.0364261, 0.396365, -0.284096, 0.137003, + 0.611792, 0.191185, 0.440866, 0.87738, 0.470405, -0.372227, + -0.84977, 0.676291, -0.0709138, -0.456707, 0.222892, -0.728947, + 0.2414, 0.109269, 0.707531, 0.027894, -0.381266, -0.1872, + -0.674006, -0.441284, -0.151681, -0.695721, 0.360165, -0.397063, + 0.02772, 0.271526, -0.170258, -0.198509, 0.524165, 0.29589, + -0.895699, -0.266005, 0.0971003, 0.640709, -0.169635, 0.0263381, + -0.779951, -0.37692, -0.703577, 0.00526047, -0.822414, -0.152364, + 0.10004, 0.194787, 0.453202, -0.495236, 1.01192, -0.682168, + -0.453866, 0.387515, -0.355192, 0.214262, 0.2677, -0.263514, + 0.334733, 0.683574, 0.181592, 0.599759, -0.182972, 0.402297, + -0.319075, 0.553958, -0.990873, -0.143754, 0.506054, 0.0535431, + -0.647583, 0.53928, -0.510285, 0.452258, -0.796479, 0.186279, + -0.0960782, -0.124537, 0.509105, -0.1712, 0.219554, -0.528307, + -0.377211, -0.447177, -0.0283537, 0.856948, -0.128052, 0.482509, + 0.528981, -0.785958, 0.816482, 0.213728, -0.433917, -0.0413878, + -0.997625, 0.228201, -0.113198, 0.425206, 0.0261474, 0.68678, + 0.224967, 0.48489, 0.53184, 0.572936, -0.419627, -0.70428, + -0.216836, 0.57302, 0.640487, -0.172722, 0.237492, -0.390903, + 0.0717416, 0.852097, -0.0422118, 0.151465, -0.638427, 0.132246, + -0.0552788, 0.436714, -0.281931, 0.411517, -0.340499, -0.725834, + -0.478547, 0.332275, -0.0243354, -0.499295, 0.238681, -0.324647, + -0.182754, 0.520306, -0.0762625, 0.631812, -0.652095, -0.504378, + -0.534564, 0.118165, -0.384134, 0.611485, 0.635868, 0.100705, + 0.25619, 0.197184, 0.328731, -0.0750947, -0.763023, 0.516191, + 0.375317, -0.17778, 0.880709, 0.668956, 0.376694, 0.425053, + -0.930982, 0.0534644, -0.0423658, 0.695356, 0.352989, 0.0400925, + 0.383482, 0.188746, 0.0193305, 0.128885, -0.23603, -0.288163, + -0.311799, -0.425027, -0.297739, -0.349681, -0.278894, 0.00934887, + -0.38221, 0.542819, 0.234533, -0.213422, 0.198418, 0.694582, + -0.43395, -0.417672, 0.553686, -0.10748, -0.352711, -0.0115025, + 0.0581546, 0.962054, 0.210576, 0.339536, -0.0818458, -0.358587, + -0.342001, -0.0689676, 0.0470595, -0.3791, 0.212149, -0.00608754, + 0.318279, 0.246769, 0.514428, 0.457749, 0.759536, 0.236433, + 0.422228, 0.571146, -0.247402, 0.667306, -0.558038, -0.158556, + -0.369374, -0.341798, 0.30697, -0.535024, -0.487844, -0.0888073, + 0.404439, -0.580029, 0.457389, 0.297961, -0.0356712, 0.508803, + 0.325652, -0.239089, -0.743984, 0.21902, 0.455838, 0.149938, + -0.150058, 0.342239, 0.147549, -0.044282, -0.634129, 0.266822, + -0.764306, -0.13691, -0.59542, -0.503302, -0.581097, 0.455914, + 0.193022, -0.255091, 0.0782733, 0.354385, 0.181455, -0.579845, + -0.597151, -0.747541, -0.471478, -0.257622, 0.80429, 0.908564, + 0.11331, -0.210526, 0.893246, -0.354708, -0.581153, 0.366957, + 0.000682831, 1.05443, 0.310998, 0.455284, -0.251732, -0.567471, + -0.660306, -0.202108, 0.836359, -0.467352, -0.20453, 0.0710459, + 0.0628843, -0.132979, -0.755594, 0.0600963, 0.725805, -0.221625, + 0.133578, -0.802764, 0.00850201, 0.748137, -0.411616, -0.136451, + 0.0531707, -0.977616, 0.162951, 0.0394506, -0.0480862, 0.797194, + 0.52012, 0.238174, 0.169073, 0.249234, 0.00133944, -0.01138, + 0.107195, 0.0101681, -0.247766, -0.415877, -0.450288, 0.800731}; + jitterTableIndex += 2; + if (jitterTableIndex == jitterTable.size()) { + jitterTableIndex = 0; + } + return Vector2{jitterTable[jitterTableIndex], jitterTable[jitterTableIndex + 1]}; + } + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLTemporalAAFilter.h b/Sources/Draw/GLTemporalAAFilter.h new file mode 100644 index 000000000..69a223a30 --- /dev/null +++ b/Sources/Draw/GLTemporalAAFilter.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2017 yvt + + This file is part of OpenSpades. + + OpenSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenSpades. If not, see . + + */ + +#pragma once + +#include "GLFramebufferManager.h" + +namespace spades { + namespace draw { + class GLRenderer; + class GLProgram; + + /** + * Implementation of the temporal anti-aliasing filter. + * + * The current implementation requires `BlitFramebuffer` for simplicity. + */ + class GLTemporalAAFilter { + GLRenderer &renderer; + GLProgram *program; + + struct HistoryBuffer { + bool valid = false; + int width, height; + + IGLDevice::UInteger framebuffer; + IGLDevice::UInteger texture; + } historyBuffer; + + Matrix4 prevMatrix; + Vector3 prevViewOrigin; + std::size_t jitterTableIndex = 0; + + void DeleteHistoryBuffer(); + + public: + GLTemporalAAFilter(GLRenderer &); + ~GLTemporalAAFilter(); + + Vector2 GetProjectionMatrixJitter(); + + GLColorBuffer Filter(GLColorBuffer, bool useFxaa); + }; + } +} diff --git a/Sources/Draw/GLVoxelModel.cpp b/Sources/Draw/GLVoxelModel.cpp index 5c721b2a4..78cbaf31e 100644 --- a/Sources/Draw/GLVoxelModel.cpp +++ b/Sources/Draw/GLVoxelModel.cpp @@ -19,7 +19,6 @@ */ #include "GLVoxelModel.h" -#include #include "GLDynamicLightShader.h" #include "GLImage.h" #include "GLProgram.h" @@ -29,40 +28,39 @@ #include "GLShadowMapShader.h" #include "GLShadowShader.h" #include "IGLShadowMapRenderer.h" +#include namespace spades { namespace draw { - void GLVoxelModel::PreloadShaders(spades::draw::GLRenderer *renderer) { - renderer->RegisterProgram("Shaders/VoxelModel.program"); - renderer->RegisterProgram("Shaders/VoxelModelDynamicLit.program"); - renderer->RegisterProgram("Shaders/VoxelModelShadowMap.program"); - renderer->RegisterImage("Gfx/AmbientOcclusion.png"); + void GLVoxelModel::PreloadShaders(GLRenderer &renderer) { + renderer.RegisterProgram("Shaders/VoxelModel.program"); + renderer.RegisterProgram("Shaders/VoxelModelDynamicLit.program"); + renderer.RegisterProgram("Shaders/VoxelModelShadowMap.program"); + renderer.RegisterImage("Gfx/AmbientOcclusion.png"); } - GLVoxelModel::GLVoxelModel(VoxelModel *m, GLRenderer *r) { + GLVoxelModel::GLVoxelModel(VoxelModel *m, GLRenderer &r) + : renderer{r}, device(r.GetGLDevice()) { SPADES_MARK_FUNCTION(); - renderer = r; - device = r->GetGLDevice(); - - program = renderer->RegisterProgram("Shaders/VoxelModel.program"); - dlightProgram = renderer->RegisterProgram("Shaders/VoxelModelDynamicLit.program"); - shadowMapProgram = renderer->RegisterProgram("Shaders/VoxelModelShadowMap.program"); - aoImage = (GLImage *)renderer->RegisterImage("Gfx/AmbientOcclusion.png"); + program = renderer.RegisterProgram("Shaders/VoxelModel.program"); + dlightProgram = renderer.RegisterProgram("Shaders/VoxelModelDynamicLit.program"); + shadowMapProgram = renderer.RegisterProgram("Shaders/VoxelModelShadowMap.program"); + aoImage = renderer.RegisterImage("Gfx/AmbientOcclusion.png").Cast(); BuildVertices(m); - buffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(vertices.size() * sizeof(Vertex)), - vertices.data(), IGLDevice::StaticDraw); + buffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(vertices.size() * sizeof(Vertex)), + vertices.data(), IGLDevice::StaticDraw); - idxBuffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, idxBuffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(indices.size() * sizeof(uint32_t)), - indices.data(), IGLDevice::StaticDraw); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + idxBuffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, idxBuffer); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(indices.size() * sizeof(uint32_t)), + indices.data(), IGLDevice::StaticDraw); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); origin = m->GetOrigin(); origin -= .5f; // (0,0,0) is center of voxel (0,0,0) @@ -87,8 +85,8 @@ namespace spades { GLVoxelModel::~GLVoxelModel() { SPADES_MARK_FUNCTION(); - device->DeleteBuffer(idxBuffer); - device->DeleteBuffer(buffer); + device.DeleteBuffer(idxBuffer); + device.DeleteBuffer(buffer); } uint8_t GLVoxelModel::calcAOID(VoxelModel *m, int x, int y, int z, int ux, int uy, int uz, @@ -157,7 +155,7 @@ namespace spades { v.red = (uint8_t)(color); v.green = (uint8_t)(color >> 8); v.blue = (uint8_t)(color >> 16); - v.diffuse = 255; + v.material = (uint8_t)(color >> 24); v.nx = nx; v.ny = ny; v.nz = nz; @@ -238,7 +236,6 @@ namespace spades { continue; uint32_t color = model->GetColor(x, y, z); - color |= 0xff000000UL; if (!model->IsSolid(x - 1, y, z)) EmitFace(model, x, y, z, -1, 0, 0, color); @@ -266,13 +263,13 @@ namespace spades { void GLVoxelModel::RenderShadowMapPass(std::vector params) { SPADES_MARK_FUNCTION(); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); shadowMapProgram->Use(); static GLShadowMapShader shadowMapShader; - shadowMapShader(renderer, shadowMapProgram, 0); + shadowMapShader(&renderer, shadowMapProgram, 0); static GLProgramUniform modelOrigin("modelOrigin"); modelOrigin(shadowMapProgram); @@ -285,20 +282,20 @@ namespace spades { positionAttribute(shadowMapProgram); normalAttribute(shadowMapProgram); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)0); if (normalAttribute() != -1) { - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)12); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, + sizeof(Vertex), (void *)12); } - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); if (normalAttribute() != -1) - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); for (size_t i = 0; i < params.size(); i++) { const client::ModelRenderParam ¶m = params[i]; @@ -314,7 +311,7 @@ namespace spades { if (param.depthHack) continue; - if (!renderer->GetShadowMapRenderer()->SphereCull(param.matrix.GetOrigin(), rad)) { + if (!renderer.GetShadowMapRenderer()->SphereCull(param.matrix.GetOrigin(), rad)) { continue; } @@ -331,43 +328,44 @@ namespace spades { modelNormalMatrix(shadowMapProgram); modelNormalMatrix.SetValue(modelMatrix); - device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, - (void *)0); + device.DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, + (void *)0); } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); if (normalAttribute() != -1) - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); } - void GLVoxelModel::RenderSunlightPass(std::vector params, bool ghostPass) { + void GLVoxelModel::RenderSunlightPass(std::vector params, + bool ghostPass) { SPADES_MARK_FUNCTION(); - device->ActiveTexture(0); + device.ActiveTexture(0); aoImage->Bind(IGLDevice::Texture2D); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); program->Use(); static GLShadowShader shadowShader; - shadowShader(renderer, program, 1); + shadowShader(&renderer, program, 1); static GLProgramUniform fogDistance("fogDistance"); fogDistance(program); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); static GLProgramUniform fogColor("fogColor"); fogColor(program); - Vector3 fogCol = renderer->GetFogColorForSolidPass(); + Vector3 fogCol = renderer.GetFogColorForSolidPass(); fogCol *= fogCol; fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); @@ -387,7 +385,7 @@ namespace spades { static GLProgramUniform viewOriginVector("viewOriginVector"); viewOriginVector(program); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); // setup attributes @@ -401,23 +399,23 @@ namespace spades { colorAttribute(program); normalAttribute(program); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)0); - device->VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false, - sizeof(Vertex), (void *)4); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, - sizeof(Vertex), (void *)8); - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)12); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)0); + device.VertexAttribPointer(textureCoordAttribute(), 2, IGLDevice::UnsignedShort, false, + sizeof(Vertex), (void *)4); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, + sizeof(Vertex), (void *)8); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, sizeof(Vertex), + (void *)12); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(textureCoordAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(textureCoordAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); for (size_t i = 0; i < params.size(); i++) { const client::ModelRenderParam ¶m = params[i]; @@ -429,7 +427,7 @@ namespace spades { // frustrum cull float rad = radius; rad *= param.matrix.GetAxis(0).GetLength(); - if (!renderer->SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { + if (!renderer.SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { continue; } @@ -440,12 +438,12 @@ namespace spades { Matrix4 modelMatrix = param.matrix; static GLProgramUniform projectionViewModelMatrix("projectionViewModelMatrix"); projectionViewModelMatrix(program); - projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() * + projectionViewModelMatrix.SetValue(renderer.GetProjectionViewMatrix() * modelMatrix); static GLProgramUniform viewModelMatrix("viewModelMatrix"); viewModelMatrix(program); - viewModelMatrix.SetValue(renderer->GetViewMatrix() * modelMatrix); + viewModelMatrix.SetValue(renderer.GetViewMatrix() * modelMatrix); static GLProgramUniform modelMatrixU("modelMatrix"); modelMatrixU(program); @@ -463,35 +461,35 @@ namespace spades { modelOpacity.SetValue(param.opacity); if (param.depthHack) { - device->DepthRange(0.f, 0.1f); + device.DepthRange(0.f, 0.1f); } - device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, - (void *)0); + device.DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, + (void *)0); if (param.depthHack) { - device->DepthRange(0.f, 1.f); + device.DepthRange(0.f, 1.f); } } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(textureCoordAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(textureCoordAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, 0); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, 0); } void GLVoxelModel::RenderDynamicLightPass(std::vector params, std::vector lights) { SPADES_MARK_FUNCTION(); - device->ActiveTexture(0); + device.ActiveTexture(0); - device->Enable(IGLDevice::CullFace, true); - device->Enable(IGLDevice::DepthTest, true); + device.Enable(IGLDevice::CullFace, true); + device.Enable(IGLDevice::DepthTest, true); dlightProgram->Use(); @@ -499,7 +497,7 @@ namespace spades { static GLProgramUniform fogDistance("fogDistance"); fogDistance(dlightProgram); - fogDistance.SetValue(renderer->GetFogDistance()); + fogDistance.SetValue(renderer.GetFogDistance()); static GLProgramUniform modelOrigin("modelOrigin"); modelOrigin(dlightProgram); @@ -513,7 +511,7 @@ namespace spades { static GLProgramUniform viewOriginVector("viewOriginVector"); viewOriginVector(dlightProgram); - const auto &viewOrigin = renderer->GetSceneDef().viewOrigin; + const auto &viewOrigin = renderer.GetSceneDef().viewOrigin; viewOriginVector.SetValue(viewOrigin.x, viewOrigin.y, viewOrigin.z); // setup attributes @@ -525,20 +523,20 @@ namespace spades { colorAttribute(dlightProgram); normalAttribute(dlightProgram); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, - sizeof(Vertex), (void *)0); - device->VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, - sizeof(Vertex), (void *)8); - device->VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, - sizeof(Vertex), (void *)12); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 4, IGLDevice::UnsignedByte, false, + sizeof(Vertex), (void *)0); + device.VertexAttribPointer(colorAttribute(), 4, IGLDevice::UnsignedByte, true, + sizeof(Vertex), (void *)8); + device.VertexAttribPointer(normalAttribute(), 3, IGLDevice::Byte, false, sizeof(Vertex), + (void *)12); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), true); - device->EnableVertexAttribArray(colorAttribute(), true); - device->EnableVertexAttribArray(normalAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(colorAttribute(), true); + device.EnableVertexAttribArray(normalAttribute(), true); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); for (size_t i = 0; i < params.size(); i++) { const client::ModelRenderParam ¶m = params[i]; @@ -549,7 +547,7 @@ namespace spades { // frustrum cull float rad = radius; rad *= param.matrix.GetAxis(0).GetLength(); - if (!renderer->SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { + if (!renderer.SphereFrustrumCull(param.matrix.GetOrigin(), rad)) { continue; } @@ -560,12 +558,12 @@ namespace spades { Matrix4 modelMatrix = param.matrix; static GLProgramUniform projectionViewModelMatrix("projectionViewModelMatrix"); projectionViewModelMatrix(dlightProgram); - projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() * + projectionViewModelMatrix.SetValue(renderer.GetProjectionViewMatrix() * modelMatrix); static GLProgramUniform viewModelMatrix("viewModelMatrix"); viewModelMatrix(dlightProgram); - viewModelMatrix.SetValue(renderer->GetViewMatrix() * modelMatrix); + viewModelMatrix.SetValue(renderer.GetViewMatrix() * modelMatrix); static GLProgramUniform modelMatrixU("modelMatrix"); modelMatrixU(dlightProgram); @@ -579,29 +577,29 @@ namespace spades { modelNormalMatrix.SetValue(modelMatrix); if (param.depthHack) { - device->DepthRange(0.f, 0.1f); + device.DepthRange(0.f, 0.1f); } for (size_t i = 0; i < lights.size(); i++) { if (!lights[i].SphereCull(param.matrix.GetOrigin(), rad)) continue; - dlightShader(renderer, dlightProgram, lights[i], 0); + dlightShader(&renderer, dlightProgram, lights[i], 0); - device->DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, - (void *)0); + device.DrawElements(IGLDevice::Triangles, numIndices, IGLDevice::UnsignedInt, + (void *)0); } if (param.depthHack) { - device->DepthRange(0.f, 1.f); + device.DepthRange(0.f, 1.f); } } - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); - device->EnableVertexAttribArray(colorAttribute(), false); - device->EnableVertexAttribArray(normalAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(colorAttribute(), false); + device.EnableVertexAttribArray(normalAttribute(), false); - device->ActiveTexture(0); + device.ActiveTexture(0); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLVoxelModel.h b/Sources/Draw/GLVoxelModel.h index 820c7f6e4..057558c91 100644 --- a/Sources/Draw/GLVoxelModel.h +++ b/Sources/Draw/GLVoxelModel.h @@ -41,18 +41,18 @@ namespace spades { // color uint8_t red, green, blue; - uint8_t diffuse; + uint8_t material; // normal uint8_t nx, ny, nz; }; - GLRenderer *renderer; - IGLDevice *device; + GLRenderer &renderer; + IGLDevice &device; GLProgram *program; GLProgram *dlightProgram; GLProgram *shadowMapProgram; - GLImage *aoImage; + Handle aoImage; IGLDevice::UInteger buffer; IGLDevice::UInteger idxBuffer; @@ -75,9 +75,9 @@ namespace spades { ~GLVoxelModel(); public: - GLVoxelModel(VoxelModel *, GLRenderer *r); + GLVoxelModel(VoxelModel *, GLRenderer &r); - static void PreloadShaders(GLRenderer *); + static void PreloadShaders(GLRenderer &); void Prerender(std::vector params, bool ghostPass) override; @@ -91,5 +91,5 @@ namespace spades { AABB3 GetBoundingBox() override { return boundingBox; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLWaterRenderer.cpp b/Sources/Draw/GLWaterRenderer.cpp index 7241bc2c5..12424de36 100644 --- a/Sources/Draw/GLWaterRenderer.cpp +++ b/Sources/Draw/GLWaterRenderer.cpp @@ -23,10 +23,6 @@ #include -#include -#include -#include -#include #include "GLFramebufferManager.h" #include "GLImage.h" #include "GLProfiler.h" @@ -37,6 +33,10 @@ #include "GLShadowShader.h" #include "GLWaterRenderer.h" #include "IGLDevice.h" +#include +#include +#include +#include namespace spades { namespace draw { @@ -422,7 +422,7 @@ namespace spades { int count = (int)floorf(dt * 600.f); if (count > 400) count = 400; - + for (int i = 0; i < count; i++) { int ox = SampleRandomInt(0, size - 3); int oy = SampleRandomInt(0, size - 3); @@ -445,60 +445,60 @@ namespace spades { #pragma mark - Water Renderer - void GLWaterRenderer::PreloadShaders(spades::draw::GLRenderer *renderer) { - auto &settings = renderer->GetSettings(); + void GLWaterRenderer::PreloadShaders(GLRenderer &renderer) { + auto &settings = renderer.GetSettings(); if ((int)settings.r_water >= 3) - renderer->RegisterProgram("Shaders/Water3.program"); + renderer.RegisterProgram("Shaders/Water3.program"); else if ((int)settings.r_water >= 2) - renderer->RegisterProgram("Shaders/Water2.program"); + renderer.RegisterProgram("Shaders/Water2.program"); else - renderer->RegisterProgram("Shaders/Water.program"); + renderer.RegisterProgram("Shaders/Water.program"); } - GLWaterRenderer::GLWaterRenderer(GLRenderer *renderer, client::GameMap *map) + GLWaterRenderer::GLWaterRenderer(GLRenderer &renderer, client::GameMap *map) : renderer(renderer), - device(renderer->GetGLDevice()), - settings(renderer->GetSettings()), + device(renderer.GetGLDevice()), + settings(renderer.GetSettings()), map(map) { SPADES_MARK_FUNCTION(); if ((int)settings.r_water >= 3) - program = renderer->RegisterProgram("Shaders/Water3.program"); + program = renderer.RegisterProgram("Shaders/Water3.program"); else if ((int)settings.r_water >= 2) - program = renderer->RegisterProgram("Shaders/Water2.program"); + program = renderer.RegisterProgram("Shaders/Water2.program"); else - program = renderer->RegisterProgram("Shaders/Water.program"); + program = renderer.RegisterProgram("Shaders/Water.program"); BuildVertices(); - tempDepthTexture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, tempDepthTexture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, - device->ScreenWidth(), device->ScreenHeight(), 0, - IGLDevice::DepthComponent, IGLDevice::UnsignedInt, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::ClampToEdge); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::ClampToEdge); - - tempFramebuffer = device->GenFramebuffer(); - device->BindFramebuffer(IGLDevice::Framebuffer, tempFramebuffer); - device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, - IGLDevice::Texture2D, tempDepthTexture, 0); + tempDepthTexture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, tempDepthTexture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, + renderer.GetRenderWidth(), renderer.GetRenderHeight(), 0, + IGLDevice::DepthComponent, IGLDevice::UnsignedInt, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::ClampToEdge); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::ClampToEdge); + + tempFramebuffer = device.GenFramebuffer(); + device.BindFramebuffer(IGLDevice::Framebuffer, tempFramebuffer); + device.FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, + IGLDevice::Texture2D, tempDepthTexture, 0); // create water color texture - texture = device->GenTexture(); - device->BindTexture(IGLDevice::Texture2D, texture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, map->Width(), - map->Height(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); + texture = device.GenTexture(); + device.BindTexture(IGLDevice::Texture2D, texture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, map->Width(), + map->Height(), 0, IGLDevice::RGBA, IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::Repeat); w = map->Width(); h = map->Height(); @@ -510,13 +510,11 @@ namespace spades { std::fill(updateBitmap.begin(), updateBitmap.end(), 0xffffffffUL); std::fill(bitmap.begin(), bitmap.end(), 0xffffffffUL); - device->TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, w, h, IGLDevice::BGRA, - IGLDevice::UnsignedByte, bitmap.data()); - + device.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, w, h, IGLDevice::BGRA, + IGLDevice::UnsignedByte, bitmap.data()); size_t numLayers = ((int)settings.r_water >= 2) ? 3 : 1; - // create wave tank simlation for (size_t i = 0; i < numLayers; i++) { if ((int)settings.r_water >= 3) { @@ -525,42 +523,43 @@ namespace spades { waveTanks.push_back(new FFTWaveTank<7>()); } } - + // create heightmap texture - waveTexture = device->GenTexture(); + waveTexture = device.GenTexture(); if (numLayers == 1) { - device->BindTexture(IGLDevice::Texture2D, waveTexture); - device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, - waveTanks[0]->GetSize(), waveTanks[0]->GetSize(), 0, - IGLDevice::BGRA, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::LinearMipmapLinear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, - IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, - IGLDevice::Repeat); + device.BindTexture(IGLDevice::Texture2D, waveTexture); + device.TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGBA8, + waveTanks[0]->GetSize(), waveTanks[0]->GetSize(), 0, + IGLDevice::BGRA, IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::LinearMipmapLinear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, + IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, + IGLDevice::Repeat); if (settings.r_maxAnisotropy > 1.0f) { - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMaxAnisotropy, - (float)settings.r_maxAnisotropy); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMaxAnisotropy, + (float)settings.r_maxAnisotropy); } } else { - device->BindTexture(IGLDevice::Texture2DArray, waveTexture); - device->TexImage3D(IGLDevice::Texture2DArray, 0, IGLDevice::RGBA8, - waveTanks[0]->GetSize(), waveTanks[0]->GetSize(), static_cast(numLayers), 0, - IGLDevice::BGRA, IGLDevice::UnsignedByte, NULL); - device->TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureMinFilter, - IGLDevice::LinearMipmapLinear); - device->TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureWrapS, - IGLDevice::Repeat); - device->TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureWrapT, - IGLDevice::Repeat); + device.BindTexture(IGLDevice::Texture2DArray, waveTexture); + device.TexImage3D(IGLDevice::Texture2DArray, 0, IGLDevice::RGBA8, + waveTanks[0]->GetSize(), waveTanks[0]->GetSize(), + static_cast(numLayers), 0, IGLDevice::BGRA, + IGLDevice::UnsignedByte, NULL); + device.TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureMinFilter, + IGLDevice::LinearMipmapLinear); + device.TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureWrapS, + IGLDevice::Repeat); + device.TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureWrapT, + IGLDevice::Repeat); if (settings.r_maxAnisotropy > 1.0f) { - device->TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureMaxAnisotropy, - (float)settings.r_maxAnisotropy); + device.TexParamater(IGLDevice::Texture2DArray, IGLDevice::TextureMaxAnisotropy, + (float)settings.r_maxAnisotropy); } } @@ -606,74 +605,74 @@ namespace spades { } } - buffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(sizeof(Vertex) * vertices.size()), - vertices.data(), IGLDevice::StaticDraw); - idxBuffer = device->GenBuffer(); - device->BindBuffer(IGLDevice::ArrayBuffer, idxBuffer); - device->BufferData(IGLDevice::ArrayBuffer, - static_cast(sizeof(uint32_t) * indices.size()), - indices.data(), IGLDevice::StaticDraw); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + buffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(sizeof(Vertex) * vertices.size()), + vertices.data(), IGLDevice::StaticDraw); + idxBuffer = device.GenBuffer(); + device.BindBuffer(IGLDevice::ArrayBuffer, idxBuffer); + device.BufferData(IGLDevice::ArrayBuffer, + static_cast(sizeof(uint32_t) * indices.size()), + indices.data(), IGLDevice::StaticDraw); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); numIndices = indices.size(); } GLWaterRenderer::~GLWaterRenderer() { SPADES_MARK_FUNCTION(); - device->DeleteBuffer(buffer); - device->DeleteBuffer(idxBuffer); - device->DeleteFramebuffer(tempFramebuffer); - device->DeleteTexture(tempDepthTexture); - device->DeleteTexture(texture); + device.DeleteBuffer(buffer); + device.DeleteBuffer(idxBuffer); + device.DeleteFramebuffer(tempFramebuffer); + device.DeleteTexture(tempDepthTexture); + device.DeleteTexture(texture); if (occlusionQuery) - device->DeleteQuery(occlusionQuery); + device.DeleteQuery(occlusionQuery); for (size_t i = 0; i < waveTanks.size(); i++) { waveTanks[i]->Join(); delete waveTanks[i]; } - device->DeleteTexture(waveTexture); + device.DeleteTexture(waveTexture); } void GLWaterRenderer::Render() { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Render"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Render"); if (occlusionQuery == 0 && settings.r_occlusionQuery) - occlusionQuery = device->GenQuery(); + occlusionQuery = device.GenQuery(); GLColorBuffer colorBuffer; { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Preparation"); - colorBuffer = renderer->GetFramebufferManager()->PrepareForWaterRendering( + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Preparation"); + colorBuffer = renderer.GetFramebufferManager()->PrepareForWaterRendering( tempFramebuffer, tempDepthTexture); } - float fogDist = renderer->GetFogDistance(); - Vector3 fogCol = renderer->GetFogColorForSolidPass(); + float fogDist = renderer.GetFogDistance(); + Vector3 fogCol = renderer.GetFogColorForSolidPass(); fogCol *= fogCol; // linearize - Vector3 skyCol = renderer->GetFogColor(); + Vector3 skyCol = renderer.GetFogColor(); skyCol *= skyCol; // linearize - const client::SceneDefinition &def = renderer->GetSceneDef(); + const client::SceneDefinition &def = renderer.GetSceneDef(); float waterLevel = 63.f; float waterRange = 128.f; Matrix4 mat = Matrix4::Translate(def.viewOrigin.x, def.viewOrigin.y, waterLevel); mat = mat * Matrix4::Scale(waterRange, waterRange, 1.f); - GLProfiler::Context profiler2(renderer->GetGLProfiler(), "Draw Plane"); + GLProfiler::Context profiler2(renderer.GetGLProfiler(), "Draw Plane"); // do color - device->DepthFunc(IGLDevice::Less); - device->ColorMask(true, true, true, true); + device.DepthFunc(IGLDevice::Less); + device.ColorMask(true, true, true, true); { GLProgram *prg = program; prg->Use(); @@ -706,24 +705,24 @@ namespace spades { fovTan(prg); waterPlane(prg); - projectionViewModelMatrix.SetValue(renderer->GetProjectionViewMatrix() * mat); - projectionViewMatrix.SetValue(renderer->GetProjectionViewMatrix()); + projectionViewModelMatrix.SetValue(renderer.GetProjectionViewMatrix() * mat); + projectionViewMatrix.SetValue(renderer.GetProjectionViewMatrix()); modelMatrix.SetValue(mat); - viewModelMatrix.SetValue(renderer->GetViewMatrix() * mat); - viewMatrix.SetValue(renderer->GetViewMatrix()); + viewModelMatrix.SetValue(renderer.GetViewMatrix() * mat); + viewMatrix.SetValue(renderer.GetViewMatrix()); fogDistance.SetValue(fogDist); fogColor.SetValue(fogCol.x, fogCol.y, fogCol.z); skyColor.SetValue(skyCol.x, skyCol.y, skyCol.z); zNearFar.SetValue(def.zNear, def.zFar); viewOrigin.SetValue(def.viewOrigin.x, def.viewOrigin.y, def.viewOrigin.z); - /*displaceScale.SetValue(1.f / renderer->ScreenWidth() / tanf(def.fovX * .5f), - 1.f / renderer->ScreenHeight() / tanf(def.fovY) * .5f);*/ + /*displaceScale.SetValue(1.f / renderer.ScreenWidth() / tanf(def.fovX * .5f), + 1.f / renderer.ScreenHeight() / tanf(def.fovY) * .5f);*/ displaceScale.SetValue(1.f / tanf(def.fovX * .5f), 1.f / tanf(def.fovY * .5f)); fovTan.SetValue(tanf(def.fovX * .5f), -tanf(def.fovY * .5f), -tanf(def.fovX * .5f), tanf(def.fovY * .5f)); // make water plane in view coord - Matrix4 wmat = renderer->GetViewMatrix() * mat; + Matrix4 wmat = renderer.GetViewMatrix() * mat; Vector3 dir = wmat.GetAxis(2); waterPlane.SetValue(dir.x, dir.y, dir.z, -Vector3::Dot(dir, wmat.GetOrigin())); @@ -743,56 +742,56 @@ namespace spades { mirrorTexture(prg); mirrorDepthTexture(prg); - device->ActiveTexture(0); - device->BindTexture(IGLDevice::Texture2D, colorBuffer.GetTexture()); + device.ActiveTexture(0); + device.BindTexture(IGLDevice::Texture2D, colorBuffer.GetTexture()); screenTexture.SetValue(0); // depth is not interpolated, so color shouldn't be - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Nearest); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Nearest); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Nearest); - device->ActiveTexture(1); - device->BindTexture(IGLDevice::Texture2D, tempDepthTexture); + device.ActiveTexture(1); + device.BindTexture(IGLDevice::Texture2D, tempDepthTexture); depthTexture.SetValue(1); - device->ActiveTexture(2); - device->BindTexture(IGLDevice::Texture2D, texture); + device.ActiveTexture(2); + device.BindTexture(IGLDevice::Texture2D, texture); textureUnif.SetValue(2); static GLShadowShader shadowShader; if (waveTanks.size() == 1) { - device->ActiveTexture(3); - device->BindTexture(IGLDevice::Texture2D, waveTexture); + device.ActiveTexture(3); + device.BindTexture(IGLDevice::Texture2D, waveTexture); waveTextureUnif.SetValue(3); - shadowShader(renderer, prg, 4); + shadowShader(&renderer, prg, 4); } else if (waveTanks.size() == 3) { - device->ActiveTexture(3); - device->BindTexture(IGLDevice::Texture2DArray, waveTexture); + device.ActiveTexture(3); + device.BindTexture(IGLDevice::Texture2DArray, waveTexture); waveTextureArrayUnif.SetValue(3); // mirror - device->ActiveTexture(4); - device->BindTexture(IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetMirrorTexture()); + device.ActiveTexture(4); + device.BindTexture(IGLDevice::Texture2D, + renderer.GetFramebufferManager()->GetMirrorTexture()); if ((float)settings.r_maxAnisotropy > 1.1f) { - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMaxAnisotropy, - (float)settings.r_maxAnisotropy); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMaxAnisotropy, + (float)settings.r_maxAnisotropy); } mirrorTexture.SetValue(4); if ((int)settings.r_water >= 3) { - device->ActiveTexture(5); - device->BindTexture( + device.ActiveTexture(5); + device.BindTexture( IGLDevice::Texture2D, - renderer->GetFramebufferManager()->GetMirrorDepthTexture()); + renderer.GetFramebufferManager()->GetMirrorDepthTexture()); mirrorDepthTexture.SetValue(5); - shadowShader(renderer, prg, 6); + shadowShader(&renderer, prg, 6); } else { - shadowShader(renderer, prg, 5); + shadowShader(&renderer, prg, 5); } } else { SPAssert(false); @@ -802,35 +801,34 @@ namespace spades { positionAttribute(prg); - device->EnableVertexAttribArray(positionAttribute(), true); + device.EnableVertexAttribArray(positionAttribute(), true); - device->BindBuffer(IGLDevice::ArrayBuffer, buffer); - device->VertexAttribPointer(positionAttribute(), 2, IGLDevice::FloatType, false, - sizeof(Vertex), NULL); - device->BindBuffer(IGLDevice::ArrayBuffer, 0); + device.BindBuffer(IGLDevice::ArrayBuffer, buffer); + device.VertexAttribPointer(positionAttribute(), 2, IGLDevice::FloatType, false, + sizeof(Vertex), NULL); + device.BindBuffer(IGLDevice::ArrayBuffer, 0); - device->BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); + device.BindBuffer(IGLDevice::ElementArrayBuffer, idxBuffer); if (occlusionQuery) - device->BeginQuery(IGLDevice::SamplesPassed, occlusionQuery); + device.BeginQuery(IGLDevice::SamplesPassed, occlusionQuery); - device->DrawElements(IGLDevice::Triangles, - static_cast(numIndices), - IGLDevice::UnsignedInt, NULL); + device.DrawElements(IGLDevice::Triangles, static_cast(numIndices), + IGLDevice::UnsignedInt, NULL); if (occlusionQuery) - device->EndQuery(IGLDevice::SamplesPassed); + device.EndQuery(IGLDevice::SamplesPassed); - device->BindBuffer(IGLDevice::ElementArrayBuffer, 0); + device.BindBuffer(IGLDevice::ElementArrayBuffer, 0); - device->EnableVertexAttribArray(positionAttribute(), false); + device.EnableVertexAttribArray(positionAttribute(), false); - device->ActiveTexture(0); + device.ActiveTexture(0); // restore filter mode for color buffer - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, - IGLDevice::Linear); - device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, - IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, + IGLDevice::Linear); + device.TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, + IGLDevice::Linear); } } @@ -846,42 +844,42 @@ namespace spades { void GLWaterRenderer::Update(float dt) { SPADES_MARK_FUNCTION(); - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Update"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Update"); // update wavetank simulation { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Waiting for Simulation To Done"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Waiting for Simulation To Done"); for (size_t i = 0; i < waveTanks.size(); i++) { waveTanks[i]->Join(); } } { { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Upload"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Upload"); if (waveTanks.size() == 1) { - device->BindTexture(IGLDevice::Texture2D, waveTexture); - device->TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, - waveTanks[0]->GetSize(), waveTanks[0]->GetSize(), - IGLDevice::BGRA, IGLDevice::UnsignedByte, - waveTanks[0]->GetBitmap()); + device.BindTexture(IGLDevice::Texture2D, waveTexture); + device.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, waveTanks[0]->GetSize(), + waveTanks[0]->GetSize(), IGLDevice::BGRA, + IGLDevice::UnsignedByte, waveTanks[0]->GetBitmap()); } else { - device->BindTexture(IGLDevice::Texture2DArray, waveTexture); + device.BindTexture(IGLDevice::Texture2DArray, waveTexture); for (size_t i = 0; i < waveTanks.size(); i++) { - device->TexSubImage3D(IGLDevice::Texture2DArray, 0, 0, 0, static_cast(i), - waveTanks[i]->GetSize(), waveTanks[i]->GetSize(), 1, - IGLDevice::BGRA, IGLDevice::UnsignedByte, - waveTanks[i]->GetBitmap()); + device.TexSubImage3D( + IGLDevice::Texture2DArray, 0, 0, 0, static_cast(i), + waveTanks[i]->GetSize(), waveTanks[i]->GetSize(), 1, IGLDevice::BGRA, + IGLDevice::UnsignedByte, waveTanks[i]->GetBitmap()); } } } { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Generate Mipmap"); + GLProfiler::Context profiler(renderer.GetGLProfiler(), "Generate Mipmap"); if (waveTanks.size() == 1) { - device->BindTexture(IGLDevice::Texture2D, waveTexture); - device->GenerateMipmap(IGLDevice::Texture2D); + device.BindTexture(IGLDevice::Texture2D, waveTexture); + device.GenerateMipmap(IGLDevice::Texture2D); } else { - device->BindTexture(IGLDevice::Texture2DArray, waveTexture); - device->GenerateMipmap(IGLDevice::Texture2DArray); + device.BindTexture(IGLDevice::Texture2DArray, waveTexture); + device.GenerateMipmap(IGLDevice::Texture2DArray); } } } @@ -895,8 +893,9 @@ namespace spades { } { - GLProfiler::Context profiler(renderer->GetGLProfiler(), "Upload Water Color Texture"); - device->BindTexture(IGLDevice::Texture2D, texture); + GLProfiler::Context profiler(renderer.GetGLProfiler(), + "Upload Water Color Texture"); + device.BindTexture(IGLDevice::Texture2D, texture); bool fullUpdate = true; for (size_t i = 0; i < updateBitmap.size(); i++) { if (updateBitmap[i] == 0) { @@ -930,8 +929,8 @@ namespace spades { } if (modified) { - device->TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, w, h, IGLDevice::BGRA, - IGLDevice::UnsignedByte, bitmap.data()); + device.TexSubImage2D(IGLDevice::Texture2D, 0, 0, 0, w, h, IGLDevice::BGRA, + IGLDevice::UnsignedByte, bitmap.data()); } for (size_t i = 0; i < updateBitmap.size(); i++) { @@ -961,8 +960,8 @@ namespace spades { } if (modified) { - device->TexSubImage2D(IGLDevice::Texture2D, 0, x, y, 32, 1, - IGLDevice::BGRA, IGLDevice::UnsignedByte, pixels); + device.TexSubImage2D(IGLDevice::Texture2D, 0, x, y, 32, 1, + IGLDevice::BGRA, IGLDevice::UnsignedByte, pixels); } updateBitmap[i] = 0; @@ -985,5 +984,5 @@ namespace spades { return; MarkUpdate(x, y); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/GLWaterRenderer.h b/Sources/Draw/GLWaterRenderer.h index 2d5e810e9..be2b0b8e3 100644 --- a/Sources/Draw/GLWaterRenderer.h +++ b/Sources/Draw/GLWaterRenderer.h @@ -20,8 +20,8 @@ #pragma once -#include #include +#include #include "IGLDevice.h" @@ -33,16 +33,15 @@ namespace spades { class GLRenderer; class IGLDevice; class GLProgram; - class GLSettings; - class GLWaterRenderer{ + class GLSettings; + class GLWaterRenderer { class IWaveTank; class StandardWaveTank; - template - class FFTWaveTank; + template class FFTWaveTank; - GLRenderer *renderer; - IGLDevice *device; - GLSettings &settings; + GLRenderer &renderer; + IGLDevice &device; + GLSettings &settings; client::GameMap *map; std::vector waveTanks; @@ -54,7 +53,7 @@ namespace spades { std::vector bitmap; - IGLDevice::UInteger texture; // water color + IGLDevice::UInteger texture; // water color IGLDevice::UInteger waveTexture; // bumpmap struct Vertex; @@ -72,11 +71,12 @@ namespace spades { void BuildVertices(); void MarkUpdate(int x, int y); + public: - GLWaterRenderer(GLRenderer *, client::GameMap *map); + GLWaterRenderer(GLRenderer &, client::GameMap *map); ~GLWaterRenderer(); - static void PreloadShaders(GLRenderer *); + static void PreloadShaders(GLRenderer &); void Render(); @@ -84,9 +84,7 @@ namespace spades { void GameMapChanged(int x, int y, int z, client::GameMap *); - IGLDevice::UInteger GetOcclusionQuery() { - return occlusionQuery; - } + IGLDevice::UInteger GetOcclusionQuery() { return occlusionQuery; } }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/IGLDevice.h b/Sources/Draw/IGLDevice.h index db6c5fc62..7f00cbb76 100644 --- a/Sources/Draw/IGLDevice.h +++ b/Sources/Draw/IGLDevice.h @@ -413,5 +413,5 @@ namespace spades { virtual void Swap() = 0; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/IGLShadowMapRenderer.cpp b/Sources/Draw/IGLShadowMapRenderer.cpp index be10f0437..3ad191965 100644 --- a/Sources/Draw/IGLShadowMapRenderer.cpp +++ b/Sources/Draw/IGLShadowMapRenderer.cpp @@ -19,16 +19,16 @@ */ #include "IGLShadowMapRenderer.h" -#include #include "GLModelRenderer.h" #include "GLRenderer.h" +#include namespace spades { namespace draw { - IGLShadowMapRenderer::IGLShadowMapRenderer(GLRenderer *renderer) : renderer(renderer) {} + IGLShadowMapRenderer::IGLShadowMapRenderer(GLRenderer &renderer) : renderer(renderer) {} void IGLShadowMapRenderer::RenderShadowMapPass() { SPADES_MARK_FUNCTION(); - renderer->modelRenderer->RenderShadowMapPass(); + renderer.modelRenderer->RenderShadowMapPass(); } - } -} \ No newline at end of file + } // namespace draw +} // namespace spades \ No newline at end of file diff --git a/Sources/Draw/IGLShadowMapRenderer.h b/Sources/Draw/IGLShadowMapRenderer.h index 4f0001974..3f5404e2b 100644 --- a/Sources/Draw/IGLShadowMapRenderer.h +++ b/Sources/Draw/IGLShadowMapRenderer.h @@ -34,21 +34,24 @@ namespace spades { }; class IGLShadowMapRenderer { - GLRenderer *renderer; + GLRenderer &renderer; protected: virtual void RenderShadowMapPass(); public: - IGLShadowMapRenderer(GLRenderer *); + IGLShadowMapRenderer(GLRenderer &); virtual ~IGLShadowMapRenderer() {} - GLRenderer *GetRenderer() { return renderer; } + GLRenderer &GetRenderer() { return renderer; } + /** + * Clobbers the current framebuffer binding and viewport rectangle. + */ virtual void Render() = 0; virtual bool Cull(const AABB3 &) = 0; virtual bool SphereCull(const Vector3 ¢er, float rad) = 0; }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/IGLSpriteRenderer.h b/Sources/Draw/IGLSpriteRenderer.h index 7ea661ffe..485309490 100644 --- a/Sources/Draw/IGLSpriteRenderer.h +++ b/Sources/Draw/IGLSpriteRenderer.h @@ -32,5 +32,5 @@ namespace spades { virtual void Clear() = 0; virtual void Render() = 0; }; - } -} \ No newline at end of file + } // namespace draw +} // namespace spades \ No newline at end of file diff --git a/Sources/Draw/SWFeatureLevel.cpp b/Sources/Draw/SWFeatureLevel.cpp index ff653444f..fcc2257a2 100644 --- a/Sources/Draw/SWFeatureLevel.cpp +++ b/Sources/Draw/SWFeatureLevel.cpp @@ -40,5 +40,5 @@ namespace spades { #else SWFeatureLevel DetectFeatureLevel() { return SWFeatureLevel::None; } #endif - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWFeatureLevel.h b/Sources/Draw/SWFeatureLevel.h index 9f8b54239..54b92bddb 100644 --- a/Sources/Draw/SWFeatureLevel.h +++ b/Sources/Draw/SWFeatureLevel.h @@ -115,14 +115,14 @@ namespace spades { return tmp; } #else - static inline float fastDiv(float a, float b) { return a / b; } - static inline float fastRcp(float b) { return 1.f / b; } - static inline float fastRSqrt(float b) { return 1.f / sqrtf(b); } + static inline PURE float fastDiv(float a, float b) { return a / b; } + static inline PURE float fastRcp(float b) { return 1.f / b; } + static inline PURE float fastRSqrt(float b) { return 1.f / sqrtf(b); } #endif static inline float fastSqrt(float s) { if (s == 0.f) return 0.f; return s * fastRSqrt(s); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWFlatMapRenderer.cpp b/Sources/Draw/SWFlatMapRenderer.cpp index af43f66f0..45817fc25 100644 --- a/Sources/Draw/SWFlatMapRenderer.cpp +++ b/Sources/Draw/SWFlatMapRenderer.cpp @@ -30,15 +30,15 @@ namespace spades { namespace draw { - SWFlatMapRenderer::SWFlatMapRenderer(SWRenderer *r, client::GameMap *map) - : r(r), map(map), w(map->Width()), h(map->Height()), needsUpdate(true) { + SWFlatMapRenderer::SWFlatMapRenderer(SWRenderer &r, Handle inMap) + : r(r), map(std::move(inMap)), w(map->Width()), h(map->Height()), needsUpdate(true) { SPADES_MARK_FUNCTION(); if (w & 31) { SPRaise("Map width must be a multiple of 32."); } - img.Set(new SWImage(map->Width(), map->Height()), false); + img = Handle::New(map->Width(), map->Height()); updateMap.resize(w * h / 32); std::fill(updateMap.begin(), updateMap.end(), 0xffffffff); updateMap2.resize(w * h / 32); @@ -62,7 +62,7 @@ namespace spades { } auto *outPixels = img->GetRawBitmap(); - auto *mapRenderer = r->mapRenderer.get(); + auto *mapRenderer = r.mapRenderer.get(); int idx = 0; for (int y = 0; y < h; y++) { @@ -109,5 +109,5 @@ namespace spades { needsUpdate = true; updateMap[(x + y * w) >> 5] |= 1 << (x & 31); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWFlatMapRenderer.h b/Sources/Draw/SWFlatMapRenderer.h index 1eb2b0b13..a740e8009 100644 --- a/Sources/Draw/SWFlatMapRenderer.h +++ b/Sources/Draw/SWFlatMapRenderer.h @@ -34,7 +34,7 @@ namespace spades { class SWImage; class SWFlatMapRenderer { - SWRenderer *r; + SWRenderer &r; Handle img; Handle map; int w, h; @@ -46,16 +46,16 @@ namespace spades { uint32_t GeneratePixel(int x, int y); public: - SWFlatMapRenderer(SWRenderer *r, client::GameMap *); + SWFlatMapRenderer(SWRenderer &r, Handle); ~SWFlatMapRenderer(); - SWImage *GetImage() { + SWImage &GetImage() { Update(); - return img; + return *img; } void Update(bool firstTime = false); void SetNeedsUpdate(int x, int y); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWImage.cpp b/Sources/Draw/SWImage.cpp index e67091d6d..fbf474c18 100644 --- a/Sources/Draw/SWImage.cpp +++ b/Sources/Draw/SWImage.cpp @@ -40,21 +40,21 @@ namespace spades { col |= b | (g << 8) | (r << 16); // swap RGB/BGR return col; } - } + } // namespace - SWImage::SWImage(Bitmap *m) - : ew(m->GetWidth()), - eh(m->GetHeight()), + SWImage::SWImage(Bitmap &m) + : ew(m.GetWidth()), + eh(m.GetHeight()), isWhite(false), - w(static_cast(m->GetWidth())), - h(static_cast(m->GetHeight())), + w(static_cast(m.GetWidth())), + h(static_cast(m.GetHeight())), iw(1.f / w), ih(1.f / h) { bmp.resize(ew * eh); // premultiplied alpha { - uint32_t *inpix = m->GetPixels(); + uint32_t *inpix = m.GetPixels(); uint32_t *outpix = bmp.data(); bool foundNonWhite = false; for (std::size_t i = ew * eh; i; i--) { @@ -105,31 +105,24 @@ namespace spades { isWhite = false; } - SWImageManager::~SWImageManager() { - for (auto it = images.begin(); it != images.end(); it++) - it->second->Release(); - } + SWImageManager::~SWImageManager() {} - SWImage *SWImageManager::RegisterImage(const std::string &name) { + Handle SWImageManager::RegisterImage(const std::string &name) { auto it = images.find(name); if (it == images.end()) { - Handle vm; - vm.Set(Bitmap::Load(name), false); - auto *m = CreateImage(vm); - images.insert(std::make_pair(name, m)); - m->AddRef(); - return m; - } else { - auto *image = it->second; - image->AddRef(); + Handle bitmap = Bitmap::Load(name); + Handle image = CreateImage(*bitmap); + images.insert(std::make_pair(name, image)); return image; + } else { + return it->second; } } - SWImage *SWImageManager::CreateImage(Bitmap *vm) { return new SWImage(vm); } - - void SWImageManager::ClearCache() { - images.clear(); + Handle SWImageManager::CreateImage(Bitmap &bitmap) { + return Handle::New(bitmap); } - } -} + + void SWImageManager::ClearCache() { images.clear(); } + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWImage.h b/Sources/Draw/SWImage.h index 41e4fa9ae..41f1a160a 100644 --- a/Sources/Draw/SWImage.h +++ b/Sources/Draw/SWImage.h @@ -42,7 +42,7 @@ namespace spades { ~SWImage(); public: - SWImage(Bitmap *bmp); + SWImage(Bitmap &bmp); SWImage(int w, int h); uint32_t *GetRawBitmap() { return bmp.data(); } @@ -60,16 +60,16 @@ namespace spades { }; class SWImageManager { - std::unordered_map images; + std::unordered_map> images; public: SWImageManager() {} ~SWImageManager(); - SWImage *RegisterImage(const std::string &); - SWImage *CreateImage(Bitmap *); + Handle RegisterImage(const std::string &); + Handle CreateImage(Bitmap &); void ClearCache(); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWImageRenderer.cpp b/Sources/Draw/SWImageRenderer.cpp index d21368a09..d46e45d0d 100644 --- a/Sources/Draw/SWImageRenderer.cpp +++ b/Sources/Draw/SWImageRenderer.cpp @@ -280,17 +280,16 @@ namespace spades { const Vertex &v3, SWImageRenderer &r) { // TODO: support null image - Bitmap *const fb = r.frame; - SPAssert(fb != nullptr); + Bitmap &fb = *r.frame; if (v3.position.y <= 0.f) { // viewport cull return; } - const int fbW = fb->GetWidth(); - const int fbH = fb->GetHeight(); - uint32_t *const bmp = fb->GetPixels(); + const int fbW = fb.GetWidth(); + const int fbH = fb.GetHeight(); + uint32_t *const bmp = fb.GetPixels(); if (v1.position.y >= static_cast(fbH)) { // viewport cull @@ -533,7 +532,7 @@ namespace spades { } }; -// TODO: Non-SSE2 renderer for solid polygons + // TODO: Non-SSE2 renderer for solid polygons #pragma mark - SSE2 #if ENABLE_SSE2 @@ -546,17 +545,16 @@ namespace spades { static void DrawPolygonInternalInner(SWImage *img, const Vertex &v1, const Vertex &v2, const Vertex &v3, SWImageRenderer &r) { - Bitmap *const fb = r.frame; - SPAssert(fb != nullptr); + Bitmap &fb = *r.frame; if (v3.position.y <= 0.f) { // viewport cull return; } - const int fbW = fb->GetWidth(); - const int fbH = fb->GetHeight(); - uint32_t *const bmp = fb->GetPixels(); + const int fbW = fb.GetWidth(); + const int fbH = fb.GetHeight(); + uint32_t *const bmp = fb.GetPixels(); if (v1.position.y >= static_cast(fbH)) { // viewport cull @@ -980,17 +978,16 @@ namespace spades { static void DrawPolygonInternalInner(SWImage *img, const Vertex &v1, const Vertex &v2, const Vertex &v3, SWImageRenderer &r) { - Bitmap *const fb = r.frame; - SPAssert(fb != nullptr); + Bitmap &fb = *r.frame; if (v3.position.y <= 0.f) { // viewport cull return; } - const int fbW = fb->GetWidth(); - const int fbH = fb->GetHeight(); - uint32_t *const bmp = fb->GetPixels(); + const int fbW = fb.GetWidth(); + const int fbH = fb.GetHeight(); + uint32_t *const bmp = fb.GetPixels(); if (v1.position.y >= static_cast(fbH)) { // viewport cull @@ -1400,8 +1397,8 @@ namespace spades { [img, &r](Vertex &v1, Vertex &v2, Vertex &v3) { PolygonRenderer::DrawPolygonInternal(img, v1, v2, v3, r); - }); - }); + }); + }); } }; @@ -1442,7 +1439,7 @@ namespace spades { void SWImageRenderer::DrawPolygon(SWImage *img, const Vertex &v1, const Vertex &v2, const Vertex &v3) { - SPAssert(frame != nullptr); + SPAssert(frame); switch (shader) { case ShaderType::Sprite: PolygonRenderer2Width()), h(m->Height()), renderer(r), @@ -226,11 +226,11 @@ namespace spades { const auto *rle = this->rle.data(); auto &rleHeap = this->rleHeap; - client::GameMap *map = this->map; + client::GameMap &map = *this->map; // pitch culling { - const auto &frustrum = renderer->frustrum; + const auto &frustrum = renderer.frustrum; static const float pi = M_PI; const auto &horz = line.horizonDir; minPitch = -pi * 0.4999f; @@ -529,13 +529,13 @@ namespace spades { // check for new spans - auto BuildLinePixel = [map](int x, int y, int z, Face face, float dist) { + auto BuildLinePixel = [&map](int x, int y, int z, Face face, float dist) { LinePixel px; px.depth = dist; #if ENABLE_SSE - if (flevel == SWFeatureLevel::SSE2) { + if constexpr (flevel == SWFeatureLevel::SSE2) { __m128i m; - uint32_t col = map->GetColorWrapped(x, y, z); + uint32_t col = map.GetColorWrapped(x, y, z); m = _mm_setr_epi32(col, 0, 0, 0); m = _mm_unpacklo_epi8(m, _mm_setzero_si128()); m = _mm_shufflelo_epi16(m, 0xc6); @@ -560,7 +560,7 @@ namespace spades { // non-optimized { uint32_t col; - col = map->GetColorWrapped(x, y, z); + col = map.GetColorWrapped(x, y, z); col = (col & 0xff00) | ((col & 0xff) << 16) | ((col & 0xff0000) >> 16); switch (face) { case Face::PosZ: col = (col & 0xfcfcfc) >> 2; break; @@ -887,7 +887,7 @@ namespace spades { // though this isn't a problem as long as the color comes // in the LSB's #if ENABLE_SSE - if (flevel == SWFeatureLevel::SSE2) { + if constexpr (flevel == SWFeatureLevel::SSE2) { __m128i m; if (under == 1) { @@ -985,7 +985,7 @@ namespace spades { // though this isn't a problem as long as the color comes // in the LSB's #if ENABLE_SSE - if (flevel == SWFeatureLevel::SSE2) { + if constexpr (flevel == SWFeatureLevel::SSE2) { __m128i m; if (under == 1) { @@ -1157,7 +1157,6 @@ namespace spades { int under = r_swUndersampling; InvokeParallel2([&](unsigned int th, unsigned int numThreads) { - if (under <= 1) { RenderFinal(yawMin, yawMax, static_cast(numLines), th, numThreads); @@ -1174,10 +1173,8 @@ namespace spades { depthBuf = nullptr; } - void SWMapRenderer::Render(const client::SceneDefinition &def, Bitmap *frame, + void SWMapRenderer::Render(const client::SceneDefinition &def, Bitmap &frame, float *depthBuffer) { - if (!frame) - SPInvalidArgument("frame"); if (!depthBuffer) SPInvalidArgument("depthBuffer"); @@ -1188,12 +1185,12 @@ namespace spades { #if ENABLE_SSE2 if (static_cast(level) >= static_cast(SWFeatureLevel::SSE2)) { - RenderInner(def, frame, depthBuffer); + RenderInner(def, &frame, depthBuffer); return; } #endif - RenderInner(def, frame, depthBuffer); + RenderInner(def, &frame, depthBuffer); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWMapRenderer.h b/Sources/Draw/SWMapRenderer.h index 268ac9781..b4a233cb4 100644 --- a/Sources/Draw/SWMapRenderer.h +++ b/Sources/Draw/SWMapRenderer.h @@ -23,7 +23,6 @@ #include #include -#include "SWFeatureLevel.h" #include "SWFeatureLevel.h" #include #include @@ -44,11 +43,13 @@ namespace spades { struct LinePixel; int w, h; - SWRenderer *renderer; + SWRenderer &renderer; SWFeatureLevel level; client::SceneDefinition sceneDef; Handle map; + // TODO: The following fields are only used during a function call + // to `Render`. Move them to a context struct? Bitmap *frameBuf; float *depthBuf; std::vector lines; @@ -74,12 +75,12 @@ namespace spades { void RenderInner(const client::SceneDefinition &, Bitmap *fb, float *depthBuffer); public: - SWMapRenderer(SWRenderer *r, client::GameMap *, SWFeatureLevel level); + SWMapRenderer(SWRenderer &r, client::GameMap *, SWFeatureLevel level); ~SWMapRenderer(); - void Render(const client::SceneDefinition &, Bitmap *fb, float *depthBuffer); + void Render(const client::SceneDefinition &, Bitmap &fb, float *depthBuffer); void UpdateRle(int x, int y); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWModel.cpp b/Sources/Draw/SWModel.cpp index 16ff451a5..7e9c0cdfe 100644 --- a/Sources/Draw/SWModel.cpp +++ b/Sources/Draw/SWModel.cpp @@ -20,32 +20,32 @@ #include #include "SWModel.h" -#include #include +#include namespace spades { namespace draw { - SWModel::SWModel(VoxelModel *m) : rawModel(m) { - center.x = m->GetWidth(); - center.y = m->GetHeight(); - center.z = m->GetDepth(); + SWModel::SWModel(VoxelModel &m) : rawModel(m) { + center.x = m.GetWidth(); + center.y = m.GetHeight(); + center.z = m.GetDepth(); center *= 0.5f; radius = center.GetLength(); - int w = m->GetWidth(); - int h = m->GetHeight(); - int d = m->GetDepth(); + int w = m.GetWidth(); + int h = m.GetHeight(); + int d = m.GetDepth(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { renderDataAddr.push_back(static_cast(renderData.size())); - uint64_t map = m->GetSolidBitsAt(x, y); - uint64_t map1 = x > 0 ? m->GetSolidBitsAt(x - 1, y) : 0; - uint64_t map2 = x < (w - 1) ? m->GetSolidBitsAt(x + 1, y) : 0; - uint64_t map3 = y > 0 ? m->GetSolidBitsAt(x, y - 1) : 0; - uint64_t map4 = y < (h - 1) ? m->GetSolidBitsAt(x, y + 1) : 0; + uint64_t map = m.GetSolidBitsAt(x, y); + uint64_t map1 = x > 0 ? m.GetSolidBitsAt(x - 1, y) : 0; + uint64_t map2 = x < (w - 1) ? m.GetSolidBitsAt(x + 1, y) : 0; + uint64_t map3 = y > 0 ? m.GetSolidBitsAt(x, y - 1) : 0; + uint64_t map4 = y < (h - 1) ? m.GetSolidBitsAt(x, y + 1) : 0; map1 &= map2; map1 &= map3; map1 &= map4; @@ -55,7 +55,7 @@ namespace spades { continue; if (z == 0 || z == (d - 1) || ((map >> (z - 1)) & 7ULL) != 7ULL || (map1 & (1ULL << z)) == 0) { - uint32_t col = m->GetColor(x, y, z); + uint32_t col = m.GetColor(x, y, z); uint32_t encodedColor; encodedColor = @@ -75,7 +75,7 @@ namespace spades { for (int cx = -1; cx <= 1; cx++) for (int cy = -1; cy <= 1; cy++) for (int cz = -1; cz <= 1; cz++) { - if (m->IsSolid(x + cx, y + cy, z + cz)) { + if (m.IsSolid(x + cx, y + cy, z + cz)) { nx -= cx; ny -= cy; nz -= cz; @@ -106,9 +106,9 @@ namespace spades { SWModel::~SWModel() {} AABB3 SWModel::GetBoundingBox() { - VoxelModel *m = rawModel; + VoxelModel &m = *rawModel; Vector3 minPos = {0, 0, 0}; - Vector3 maxPos = {(float)m->GetWidth(), (float)m->GetHeight(), (float)m->GetDepth()}; + Vector3 maxPos = {(float)m.GetWidth(), (float)m.GetHeight(), (float)m.GetDepth()}; auto origin = rawModel->GetOrigin() - .5f; minPos += origin; maxPos += origin; @@ -123,33 +123,27 @@ namespace spades { return boundingBox; } - SWModelManager::~SWModelManager() { - for (auto it = models.begin(); it != models.end(); it++) - it->second->Release(); - } + SWModelManager::~SWModelManager() {} - SWModel *SWModelManager::RegisterModel(const std::string &name) { + Handle SWModelManager::RegisterModel(const std::string &name) { auto it = models.find(name); if (it == models.end()) { - Handle vm; - vm.Set(VoxelModelLoader::Load(name.c_str()), false); + auto vm = VoxelModelLoader::Load(name.c_str()); - SWModel *model = CreateModel(vm); + Handle model = CreateModel(*vm); models.insert(std::make_pair(name, model)); model->AddRef(); return model; } else { - SWModel *model = it->second; - model->AddRef(); - return model; + return it->second; } } - SWModel *SWModelManager::CreateModel(spades::VoxelModel *vm) { return new SWModel(vm); } - - void SWModelManager::ClearCache() { - models.clear(); + Handle SWModelManager::CreateModel(spades::VoxelModel &vm) { + return Handle::New(vm); } - } -} + + void SWModelManager::ClearCache() { models.clear(); } + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWModel.h b/Sources/Draw/SWModel.h index 2789da305..eb11c4026 100644 --- a/Sources/Draw/SWModel.h +++ b/Sources/Draw/SWModel.h @@ -44,26 +44,26 @@ namespace spades { ~SWModel(); public: - SWModel(VoxelModel *model); + SWModel(VoxelModel &model); float GetRadius() { return radius; } Vector3 GetCenter() { return center; } - VoxelModel *GetRawModel() { return rawModel; } + VoxelModel &GetRawModel() { return *rawModel; } AABB3 GetBoundingBox(); }; class SWModelManager { - std::unordered_map models; + std::unordered_map> models; public: SWModelManager() {} ~SWModelManager(); - SWModel *RegisterModel(const std::string &); - SWModel *CreateModel(VoxelModel *); + Handle RegisterModel(const std::string &); + Handle CreateModel(VoxelModel &); void ClearCache(); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWModelRenderer.cpp b/Sources/Draw/SWModelRenderer.cpp index 9f686ea91..c7703b360 100644 --- a/Sources/Draw/SWModelRenderer.cpp +++ b/Sources/Draw/SWModelRenderer.cpp @@ -44,23 +44,23 @@ namespace spades { static ZVals zvals; template - void SWModelRenderer::RenderInner(spades::draw::SWModel *model, + void SWModelRenderer::RenderInner(spades::draw::SWModel &model, const client::ModelRenderParam ¶m) { auto &mat = param.matrix; auto origin = mat.GetOrigin(); auto axis1 = mat.GetAxis(0); auto axis2 = mat.GetAxis(1); auto axis3 = mat.GetAxis(2); - auto *rawModel = model->GetRawModel(); - auto rawModelOrigin = rawModel->GetOrigin(); + auto &rawModel = model.GetRawModel(); + auto rawModelOrigin = rawModel.GetOrigin(); rawModelOrigin += 0.25f; origin += axis1 * rawModelOrigin.x; origin += axis2 * rawModelOrigin.y; origin += axis3 * rawModelOrigin.z; - int w = rawModel->GetWidth(); - int h = rawModel->GetHeight(); - // int d = rawModel->GetDepth(); + int w = rawModel.GetWidth(); + int h = rawModel.GetHeight(); + // int d = rawModel.GetDepth(); // evaluate brightness for each normals uint8_t brights[3 * 3 * 3 + 1]; @@ -131,7 +131,7 @@ namespace spades { // compute center coord. for culling { auto center = origin; - auto localCenter = model->GetCenter(); + auto localCenter = model.GetCenter(); center += axis1 * localCenter.x; center += axis2 * localCenter.y; center += axis3 * localCenter.z; @@ -140,14 +140,14 @@ namespace spades { largestAxis = std::max(largestAxis, axis2.GetPoweredLength()); largestAxis = std::max(largestAxis, axis3.GetPoweredLength()); - if (!r->SphereFrustrumCull(center, model->GetRadius() * sqrtf(largestAxis))) + if (!r->SphereFrustrumCull(center, model.GetRadius() * sqrtf(largestAxis))) return; } - Bitmap *fbmp = r->fb; - auto *fb = fbmp->GetPixels(); - int fw = fbmp->GetWidth(); - int fh = fbmp->GetHeight(); + Bitmap &fbmp = *r->fb; + auto *fb = fbmp.GetPixels(); + int fw = fbmp.GetWidth(); + int fh = fbmp.GetHeight(); auto *db = r->depthBuffer.data(); Matrix4 viewproj = r->GetProjectionViewMatrix(); @@ -183,7 +183,7 @@ namespace spades { for (int x = 0; x < w; x++) { auto v2 = v1; for (int y = 0; y < h; y++) { - auto *mp = &model->renderData[model->renderDataAddr[x + y * w]]; + auto *mp = &model.renderData[model.renderDataAddr[x + y * w]]; while (*mp != -1) { uint32_t data = *(mp++); uint32_t normal = *(mp++); @@ -234,7 +234,7 @@ namespace spades { SPAssert(normal < 28); int bright = brights[normal]; #if ENABLE_SSE2 - if (lvl == SWFeatureLevel::SSE2) { + if constexpr (lvl == SWFeatureLevel::SSE2) { auto m = _mm_setr_epi32(color, 0, 0, 0); auto f = _mm_set1_epi16(bright << 8); @@ -276,7 +276,7 @@ namespace spades { } } - void SWModelRenderer::Render(spades::draw::SWModel *model, + void SWModelRenderer::Render(spades::draw::SWModel &model, const client::ModelRenderParam ¶m) { #if ENABLE_SSE2 if (static_cast(level) >= static_cast(SWFeatureLevel::SSE2)) { @@ -285,5 +285,5 @@ namespace spades { #endif RenderInner(model, param); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWModelRenderer.h b/Sources/Draw/SWModelRenderer.h index 0355f5cbd..01dda50d9 100644 --- a/Sources/Draw/SWModelRenderer.h +++ b/Sources/Draw/SWModelRenderer.h @@ -33,13 +33,13 @@ namespace spades { SWFeatureLevel level; template - void RenderInner(SWModel *model, const client::ModelRenderParam ¶m); + void RenderInner(SWModel &model, const client::ModelRenderParam ¶m); public: SWModelRenderer(SWRenderer *, SWFeatureLevel level); ~SWModelRenderer(); - void Render(SWModel *model, const client::ModelRenderParam ¶m); + void Render(SWModel &model, const client::ModelRenderParam ¶m); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWPort.h b/Sources/Draw/SWPort.h index 7bedac97a..4d93dd3fa 100644 --- a/Sources/Draw/SWPort.h +++ b/Sources/Draw/SWPort.h @@ -33,7 +33,7 @@ namespace spades { /** * Returns a `Bitmap` on which the scene is rendered. */ - virtual Bitmap *GetFramebuffer() = 0; + virtual Bitmap &GetFramebuffer() = 0; /** * Presents the contents of the framebuffer (returned by @@ -41,5 +41,5 @@ namespace spades { */ virtual void Swap() = 0; }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWRenderer.cpp b/Sources/Draw/SWRenderer.cpp index b14f931e4..19968db00 100644 --- a/Sources/Draw/SWRenderer.cpp +++ b/Sources/Draw/SWRenderer.cpp @@ -42,9 +42,9 @@ DEFINE_SPADES_SETTING(r_swNumThreads, "4"); namespace spades { namespace draw { - SWRenderer::SWRenderer(SWPort *port, SWFeatureLevel level) + SWRenderer::SWRenderer(Handle _port, SWFeatureLevel level) : featureLevel(level), - port(port), + port(std::move(_port)), map(nullptr), fb(nullptr), inited(false), @@ -58,9 +58,7 @@ namespace spades { SPADES_MARK_FUNCTION(); - if (port == nullptr) { - SPRaise("Port is null."); - } + SPAssert(port); SPLog("---- SWRenderer early initialization started ---"); @@ -78,7 +76,7 @@ namespace spades { renderStopwatch.Reset(); SPLog("setting framebuffer."); - SetFramebuffer(port->GetFramebuffer()); + SetFramebuffer(&port->GetFramebuffer()); // alloc depth buffer SPLog("initializing depth buffer."); @@ -140,16 +138,16 @@ namespace spades { inited = false; } - client::IImage *SWRenderer::RegisterImage(const char *filename) { + Handle SWRenderer::RegisterImage(const char *filename) { SPADES_MARK_FUNCTION(); EnsureValid(); - return imageManager->RegisterImage(filename); + return imageManager->RegisterImage(filename).Cast(); } - client::IModel *SWRenderer::RegisterModel(const char *filename) { + Handle SWRenderer::RegisterModel(const char *filename) { SPADES_MARK_FUNCTION(); EnsureInitialized(); - return modelManager->RegisterModel(filename); + return modelManager->RegisterModel(filename).Cast(); } void SWRenderer::ClearCache() { @@ -159,23 +157,23 @@ namespace spades { modelManager->ClearCache(); } - client::IImage *SWRenderer::CreateImage(spades::Bitmap *bmp) { + Handle SWRenderer::CreateImage(spades::Bitmap &bmp) { SPADES_MARK_FUNCTION(); EnsureValid(); - return imageManager->CreateImage(bmp); + return imageManager->CreateImage(bmp).Cast(); } - client::IModel *SWRenderer::CreateModel(spades::VoxelModel *model) { + Handle SWRenderer::CreateModel(spades::VoxelModel &model) { SPADES_MARK_FUNCTION(); EnsureInitialized(); - return modelManager->CreateModel(model); + return modelManager->CreateModel(model).Cast(); } - void SWRenderer::SetGameMap(client::GameMap *map) { + void SWRenderer::SetGameMap(stmp::optional map) { SPADES_MARK_FUNCTION(); if (map) EnsureInitialized(); - if (map == this->map) + if (map.get_pointer() == this->map.GetPointerOrNull()) return; flatMapRenderer.reset(); @@ -186,8 +184,9 @@ namespace spades { this->map = map; if (this->map) { this->map->AddListener(this); - flatMapRenderer = std::make_shared(this, map); - mapRenderer = std::make_shared(this, map, featureLevel); + flatMapRenderer = std::make_shared(*this, map); + mapRenderer = + std::make_shared(*this, map.get_pointer(), featureLevel); } } @@ -196,51 +195,13 @@ namespace spades { void SWRenderer::BuildProjectionMatrix() { SPADES_MARK_FUNCTION(); - float near = sceneDef.zNear; - float far = sceneDef.zFar; - float t = near * tanf(sceneDef.fovY * .5f); - float r = near * tanf(sceneDef.fovX * .5f); - float a = r * 2.f, b = t * 2.f, c = far - near; - Matrix4 mat; - mat.m[0] = near * 2.f / a; - mat.m[1] = 0.f; - mat.m[2] = 0.f; - mat.m[3] = 0.f; - mat.m[4] = 0.f; - mat.m[5] = near * 2.f / b; - mat.m[6] = 0.f; - mat.m[7] = 0.f; - mat.m[8] = 0.f; - mat.m[9] = 0.f; - mat.m[10] = -(far + near) / c; - mat.m[11] = -1.f; - mat.m[12] = 0.f; - mat.m[13] = 0.f; - mat.m[14] = -(far * near * 2.f) / c; - mat.m[15] = 0.f; - projectionMatrix = mat; + projectionMatrix = sceneDef.ToOpenGLProjectionMatrix(); } void SWRenderer::BuildView() { SPADES_MARK_FUNCTION(); - Matrix4 mat = Matrix4::Identity(); - mat.m[0] = sceneDef.viewAxis[0].x; - mat.m[4] = sceneDef.viewAxis[0].y; - mat.m[8] = sceneDef.viewAxis[0].z; - mat.m[1] = sceneDef.viewAxis[1].x; - mat.m[5] = sceneDef.viewAxis[1].y; - mat.m[9] = sceneDef.viewAxis[1].z; - mat.m[2] = -sceneDef.viewAxis[2].x; - mat.m[6] = -sceneDef.viewAxis[2].y; - mat.m[10] = -sceneDef.viewAxis[2].z; - - Vector4 v = mat * sceneDef.viewOrigin; - mat.m[12] = -v.x; - mat.m[13] = -v.y; - mat.m[14] = -v.z; - - viewMatrix = mat; + viewMatrix = sceneDef.ToViewMatrix(); } void SWRenderer::BuildFrustrum() { @@ -601,17 +562,15 @@ namespace spades { projectionViewMatrix = projectionMatrix * viewMatrix; } - void SWRenderer::RenderModel(client::IModel *model, const client::ModelRenderParam ¶m) { + void SWRenderer::RenderModel(client::IModel &model, const client::ModelRenderParam ¶m) { SPADES_MARK_FUNCTION(); EnsureInitialized(); EnsureSceneStarted(); - auto *mdl = dynamic_cast(model); - if (mdl == nullptr) - SPInvalidArgument("model"); + SWModel &swModel = dynamic_cast(model); Model m; - m.model = mdl; + m.model = swModel; m.param = param; models.push_back(m); @@ -705,7 +664,7 @@ namespace spades { debugLines.push_back(l); } - void SWRenderer::AddSprite(client::IImage *image, spades::Vector3 center, float radius, + void SWRenderer::AddSprite(client::IImage &image, spades::Vector3 center, float radius, float rotation) { SPADES_MARK_FUNCTION(); EnsureInitialized(); @@ -714,22 +673,19 @@ namespace spades { if (!SphereFrustrumCull(center, radius * 1.5f)) return; - SWImage *img = dynamic_cast(image); - if (!img) { - SPInvalidArgument("image"); - } + SWImage &swImage = dynamic_cast(image); sprites.push_back(Sprite()); auto &spr = sprites.back(); - spr.img = img; + spr.img = swImage; spr.center = center; spr.radius = radius; spr.rotation = rotation; spr.color = drawColorAlphaPremultiplied; } - void SWRenderer::AddLongSprite(client::IImage *, spades::Vector3 p1, spades::Vector3 p2, + void SWRenderer::AddLongSprite(client::IImage &, spades::Vector3 p1, spades::Vector3 p2, float radius) { SPADES_MARK_FUNCTION(); EnsureInitialized(); @@ -765,12 +721,12 @@ namespace spades { // flat map renderer sends 'Update RLE' to map renderer. // rendering map before this leads to the corrupted renderer image. flatMapRenderer->Update(); - mapRenderer->Render(sceneDef, fb, depthBuffer.data()); + mapRenderer->Render(sceneDef, *fb, depthBuffer.data()); } // draw models for (auto &m : models) { - modelRenderer->Render(m.model, m.param); + modelRenderer->Render(*m.model, m.param); } models.clear(); @@ -817,14 +773,14 @@ namespace spades { v2.position = x2; v3.uv = MakeVector2(0.f, 1.f); v3.position = x3; - imageRenderer->DrawPolygon(spr.img, v1, v2, v3); + imageRenderer->DrawPolygon(spr.img.GetPointerOrNull(), v1, v2, v3); v1.uv = MakeVector2(1.f, 0.f); v1.position = x2; v2.uv = MakeVector2(1.f, 1.f); v2.position = x4; v3.uv = MakeVector2(0.f, 1.f); v3.position = x3; - imageRenderer->DrawPolygon(spr.img, v1, v2, v3); + imageRenderer->DrawPolygon(spr.img.GetPointerOrNull(), v1, v2, v3); } sprites.clear(); } @@ -975,7 +931,8 @@ namespace spades { drawColorAlphaPremultiplied = col; } - void SWRenderer::DrawImage(client::IImage *image, const spades::Vector2 &outTopLeft) { + void SWRenderer::DrawImage(stmp::optional image, + const spades::Vector2 &outTopLeft) { SPADES_MARK_FUNCTION(); if (image == nullptr) { @@ -987,15 +944,16 @@ namespace spades { AABB2(0, 0, image->GetWidth(), image->GetHeight())); } - void SWRenderer::DrawImage(client::IImage *image, const spades::AABB2 &outRect) { + void SWRenderer::DrawImage(stmp::optional image, + const spades::AABB2 &outRect) { SPADES_MARK_FUNCTION(); DrawImage(image, outRect, AABB2(0, 0, image ? image->GetWidth() : 0, image ? image->GetHeight() : 0)); } - void SWRenderer::DrawImage(client::IImage *image, const spades::Vector2 &outTopLeft, - const spades::AABB2 &inRect) { + void SWRenderer::DrawImage(stmp::optional image, + const spades::Vector2 &outTopLeft, const spades::AABB2 &inRect) { SPADES_MARK_FUNCTION(); DrawImage(image, @@ -1003,8 +961,8 @@ namespace spades { inRect); } - void SWRenderer::DrawImage(client::IImage *image, const spades::AABB2 &outRect, - const spades::AABB2 &inRect) { + void SWRenderer::DrawImage(stmp::optional image, + const spades::AABB2 &outRect, const spades::AABB2 &inRect) { SPADES_MARK_FUNCTION(); DrawImage(image, Vector2::Make(outRect.GetMinX(), outRect.GetMinY()), @@ -1012,7 +970,8 @@ namespace spades { Vector2::Make(outRect.GetMinX(), outRect.GetMaxY()), inRect); } - void SWRenderer::DrawImage(client::IImage *image, const spades::Vector2 &outTopLeft, + void SWRenderer::DrawImage(stmp::optional image, + const spades::Vector2 &outTopLeft, const spades::Vector2 &outTopRight, const spades::Vector2 &outBottomLeft, const spades::AABB2 &inRect) { @@ -1025,7 +984,7 @@ namespace spades { // = b + c - a Vector2 outBottomRight = outTopRight + outBottomLeft - outTopLeft; - SWImage *img = dynamic_cast(image); + SWImage *img = dynamic_cast(image.get_pointer()); if (img == nullptr && image != nullptr) { // not SWImage SPInvalidArgument("image"); @@ -1113,10 +1072,10 @@ namespace spades { port->Swap(); // next frame's framebuffer - SetFramebuffer(port->GetFramebuffer()); + SetFramebuffer(&port->GetFramebuffer()); } - Bitmap *SWRenderer::ReadBitmap() { + Handle SWRenderer::ReadBitmap() { SPADES_MARK_FUNCTION(); EnsureValid(); EnsureSceneNotStarted(); @@ -1124,7 +1083,7 @@ namespace spades { int w = fb->GetWidth(); int h = fb->GetHeight(); uint32_t *inPix = fb->GetPixels(); - Bitmap *bm = new Bitmap(w, h); + auto bm = Handle::New(w, h); uint32_t *outPix = bm->GetPixels(); for (int y = 0; y < h; y++) { uint32_t *src = inPix + y * w; @@ -1187,7 +1146,7 @@ namespace spades { } void SWRenderer::GameMapChanged(int x, int y, int z, client::GameMap *map) { - if (map != this->map) { + if (map != this->map.GetPointerOrNull()) { return; } diff --git a/Sources/Draw/SWRenderer.h b/Sources/Draw/SWRenderer.h index 550ca7e33..5894f5601 100644 --- a/Sources/Draw/SWRenderer.h +++ b/Sources/Draw/SWRenderer.h @@ -149,20 +149,20 @@ namespace spades { ~SWRenderer(); public: - SWRenderer(SWPort *port, SWFeatureLevel featureLevel = DetectFeatureLevel()); + SWRenderer(Handle port, SWFeatureLevel featureLevel = DetectFeatureLevel()); void Init() override; void Shutdown() override; - client::IImage *RegisterImage(const char *filename) override; - client::IModel *RegisterModel(const char *filename) override; + Handle RegisterImage(const char *filename) override; + Handle RegisterModel(const char *filename) override; - client::IImage *CreateImage(Bitmap *) override; - client::IModel *CreateModel(VoxelModel *) override; + Handle CreateImage(Bitmap &) override; + Handle CreateModel(VoxelModel &) override; void ClearCache() override; - void SetGameMap(client::GameMap *) override; + void SetGameMap(stmp::optional) override; void SetFogColor(Vector3 v) override; void SetFogDistance(float f) override { fogDistance = f; } @@ -171,14 +171,14 @@ namespace spades { void StartScene(const client::SceneDefinition &) override; - void RenderModel(client::IModel *, const client::ModelRenderParam &) override; + void RenderModel(client::IModel &, const client::ModelRenderParam &) override; void AddLight(const client::DynamicLightParam &light) override; void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) override; - void AddSprite(client::IImage *, Vector3 center, float radius, float rotation) override; - void AddLongSprite(client::IImage *, Vector3 p1, Vector3 p2, float radius) override; + void AddSprite(client::IImage &, Vector3 center, float radius, float rotation) override; + void AddLongSprite(client::IImage &, Vector3 p1, Vector3 p2, float radius) override; void EndScene() override; @@ -187,19 +187,21 @@ namespace spades { void SetColor(Vector4) override; void SetColorAlphaPremultiplied(Vector4) override; - void DrawImage(client::IImage *, const Vector2 &outTopLeft) override; - void DrawImage(client::IImage *, const AABB2 &outRect) override; - void DrawImage(client::IImage *, const Vector2 &outTopLeft, + void DrawImage(stmp::optional, const Vector2 &outTopLeft) override; + void DrawImage(stmp::optional, const AABB2 &outRect) override; + void DrawImage(stmp::optional, const Vector2 &outTopLeft, + const AABB2 &inRect) override; + void DrawImage(stmp::optional, const AABB2 &outRect, + const AABB2 &inRect) override; + void DrawImage(stmp::optional, const Vector2 &outTopLeft, + const Vector2 &outTopRight, const Vector2 &outBottomLeft, const AABB2 &inRect) override; - void DrawImage(client::IImage *, const AABB2 &outRect, const AABB2 &inRect) override; - void DrawImage(client::IImage *, const Vector2 &outTopLeft, const Vector2 &outTopRight, - const Vector2 &outBottomLeft, const AABB2 &inRect) override; void DrawFlatGameMap(const AABB2 &outRect, const AABB2 &inRect) override; void FrameDone() override; void Flip() override; - Bitmap *ReadBitmap() override; + Handle ReadBitmap() override; float ScreenWidth() override; float ScreenHeight() override; @@ -215,5 +217,5 @@ namespace spades { bool BoxFrustrumCull(const AABB3 &); bool SphereFrustrumCull(const Vector3 ¢er, float radius); }; - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWUtils.cpp b/Sources/Draw/SWUtils.cpp index 47dcc72cb..c649180f6 100644 --- a/Sources/Draw/SWUtils.cpp +++ b/Sources/Draw/SWUtils.cpp @@ -26,5 +26,5 @@ SPADES_SETTING(r_swNumThreads); namespace spades { namespace draw { int GetNumSWRendererThreads() { return r_swNumThreads; } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/Draw/SWUtils.h b/Sources/Draw/SWUtils.h index 8dfb27d00..966ec839a 100644 --- a/Sources/Draw/SWUtils.h +++ b/Sources/Draw/SWUtils.h @@ -65,14 +65,14 @@ namespace spades { } } - static inline int ToFixed8(float v) { + static inline PURE int ToFixed8(float v) { int i = static_cast(v * 255.f + .5f); return std::max(std::min(i, 255), 0); } - static inline int ToFixedFactor8(float v) { + static inline PURE int ToFixedFactor8(float v) { int i = static_cast(v * 256.f + .5f); return std::max(std::min(i, 256), 0); } - } -} + } // namespace draw +} // namespace spades diff --git a/Sources/ENet/callbacks.c b/Sources/ENet/callbacks.c index f94128256..b3990af1f 100644 --- a/Sources/ENet/callbacks.c +++ b/Sources/ENet/callbacks.c @@ -27,6 +27,12 @@ enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits return enet_initialize (); } + +ENetVersion +enet_linked_version (void) +{ + return ENET_VERSION; +} void * enet_malloc (size_t size) diff --git a/Sources/ENet/host.c b/Sources/ENet/host.c index f7d384fb2..ed0c0eb31 100644 --- a/Sources/ENet/host.c +++ b/Sources/ENet/host.c @@ -4,7 +4,6 @@ */ #define ENET_BUILDING_LIB 1 #include -#include #include "enet/enet.h" /** @defgroup host ENet host functions @@ -38,6 +37,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL host = (ENetHost *) enet_malloc (sizeof (ENetHost)); if (host == NULL) return NULL; + memset (host, 0, sizeof (ENetHost)); host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer)); if (host -> peers == NULL) @@ -65,7 +65,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); - if (address != NULL) + if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0) host -> address = * address; if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) @@ -74,7 +74,8 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; - host -> randomSeed = (enet_uint32) time(NULL) + (enet_uint32) (size_t) host; + host -> randomSeed = (enet_uint32) (size_t) host; + host -> randomSeed += enet_host_random_seed (); host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16); host -> channelLimit = channelLimit; host -> incomingBandwidth = incomingBandwidth; @@ -90,18 +91,25 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL host -> receivedAddress.port = 0; host -> receivedData = NULL; host -> receivedDataLength = 0; - host -> receiveCallback = NULL; host -> totalSentData = 0; host -> totalSentPackets = 0; host -> totalReceivedData = 0; host -> totalReceivedPackets = 0; + host -> connectedPeers = 0; + host -> bandwidthLimitedPeers = 0; + host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID; + host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE; + host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA; + host -> compressor.context = NULL; host -> compressor.compress = NULL; host -> compressor.decompress = NULL; host -> compressor.destroy = NULL; + host -> intercept = NULL; + enet_list_clear (& host -> dispatchQueue); for (currentPeer = host -> peers; @@ -116,8 +124,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL enet_list_clear (& currentPeer -> acknowledgements); enet_list_clear (& currentPeer -> sentReliableCommands); enet_list_clear (& currentPeer -> sentUnreliableCommands); - enet_list_clear (& currentPeer -> outgoingReliableCommands); - enet_list_clear (& currentPeer -> outgoingUnreliableCommands); + enet_list_clear (& currentPeer -> outgoingCommands); enet_list_clear (& currentPeer -> dispatchedCommands); enet_peer_reset (currentPeer); @@ -134,6 +141,9 @@ enet_host_destroy (ENetHost * host) { ENetPeer * currentPeer; + if (host == NULL) + return; + enet_socket_destroy (host -> socket); for (currentPeer = host -> peers; @@ -150,6 +160,16 @@ enet_host_destroy (ENetHost * host) enet_free (host); } +enet_uint32 +enet_host_random (ENetHost * host) +{ + /* Mulberry32 by Tommy Ettinger */ + enet_uint32 n = (host -> randomSeed += 0x6D2B79F5U); + n = (n ^ (n >> 15)) * (n | 1U); + n ^= n + (n ^ (n >> 7)) * (n | 61U); + return n ^ (n >> 14); +} + /** Initiates a connection to a foreign host. @param host host seeking the connection @param address destination for the connection @@ -189,7 +209,7 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC currentPeer -> channelCount = channelCount; currentPeer -> state = ENET_PEER_STATE_CONNECTING; currentPeer -> address = * address; - currentPeer -> connectID = ++ host -> randomSeed; + currentPeer -> connectID = enet_host_random (host); if (host -> outgoingBandwidth == 0) currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; @@ -318,46 +338,44 @@ enet_host_bandwidth_throttle (ENetHost * host) { enet_uint32 timeCurrent = enet_time_get (), elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch, - peersTotal = 0, - dataTotal = 0, - peersRemaining, - bandwidth, + peersRemaining = (enet_uint32) host -> connectedPeers, + dataTotal = ~0, + bandwidth = ~0, throttle = 0, bandwidthLimit = 0; - int needsAdjustment; + int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0; ENetPeer * peer; ENetProtocol command; if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) return; - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) - { - if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) - continue; - - ++ peersTotal; - dataTotal += peer -> outgoingDataTotal; - } + host -> bandwidthThrottleEpoch = timeCurrent; - if (peersTotal == 0) + if (peersRemaining == 0) return; - peersRemaining = peersTotal; - needsAdjustment = 1; + if (host -> outgoingBandwidth != 0) + { + dataTotal = 0; + bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; - if (host -> outgoingBandwidth == 0) - bandwidth = ~0; - else - bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000; + for (peer = host -> peers; + peer < & host -> peers [host -> peerCount]; + ++ peer) + { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + continue; + + dataTotal += peer -> outgoingDataTotal; + } + } while (peersRemaining > 0 && needsAdjustment != 0) { needsAdjustment = 0; - if (dataTotal < bandwidth) + if (dataTotal <= bandwidth) throttle = ENET_PEER_PACKET_THROTTLE_SCALE; else throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; @@ -388,7 +406,9 @@ enet_host_bandwidth_throttle (ENetHost * host) peer -> outgoingBandwidthThrottleEpoch = timeCurrent; - + peer -> incomingDataTotal = 0; + peer -> outgoingDataTotal = 0; + needsAdjustment = 1; -- peersRemaining; bandwidth -= peerBandwidth; @@ -397,25 +417,35 @@ enet_host_bandwidth_throttle (ENetHost * host) } if (peersRemaining > 0) - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) { - if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || - peer -> outgoingBandwidthThrottleEpoch == timeCurrent) - continue; + if (dataTotal <= bandwidth) + throttle = ENET_PEER_PACKET_THROTTLE_SCALE; + else + throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; + + for (peer = host -> peers; + peer < & host -> peers [host -> peerCount]; + ++ peer) + { + if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) || + peer -> outgoingBandwidthThrottleEpoch == timeCurrent) + continue; - peer -> packetThrottleLimit = throttle; + peer -> packetThrottleLimit = throttle; - if (peer -> packetThrottle > peer -> packetThrottleLimit) - peer -> packetThrottle = peer -> packetThrottleLimit; + if (peer -> packetThrottle > peer -> packetThrottleLimit) + peer -> packetThrottle = peer -> packetThrottleLimit; + + peer -> incomingDataTotal = 0; + peer -> outgoingDataTotal = 0; + } } - + if (host -> recalculateBandwidthLimits) { host -> recalculateBandwidthLimits = 0; - peersRemaining = peersTotal; + peersRemaining = (enet_uint32) host -> connectedPeers; bandwidth = host -> incomingBandwidth; needsAdjustment = 1; @@ -466,16 +496,6 @@ enet_host_bandwidth_throttle (ENetHost * host) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } } - - host -> bandwidthThrottleEpoch = timeCurrent; - - for (peer = host -> peers; - peer < & host -> peers [host -> peerCount]; - ++ peer) - { - peer -> incomingDataTotal = 0; - peer -> outgoingDataTotal = 0; - } } /** @} */ diff --git a/Sources/ENet/include/enet/enet.h b/Sources/ENet/include/enet/enet.h index 9ef05e549..d422ef590 100644 --- a/Sources/ENet/include/enet/enet.h +++ b/Sources/ENet/include/enet/enet.h @@ -12,7 +12,7 @@ extern "C" #include -#ifdef WIN32 +#ifdef _WIN32 #include "enet/win32.h" #else #include "enet/unix.h" @@ -25,12 +25,19 @@ extern "C" #define ENET_VERSION_MAJOR 1 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 3 +#define ENET_VERSION_PATCH 17 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) +#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) +#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) +#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) #define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) typedef enet_uint32 ENetVersion; +struct _ENetHost; +struct _ENetEvent; +struct _ENetPacket; + typedef enum _ENetSocketType { ENET_SOCKET_TYPE_STREAM = 1, @@ -39,9 +46,10 @@ typedef enum _ENetSocketType typedef enum _ENetSocketWait { - ENET_SOCKET_WAIT_NONE = 0, - ENET_SOCKET_WAIT_SEND = (1 << 0), - ENET_SOCKET_WAIT_RECEIVE = (1 << 1) + ENET_SOCKET_WAIT_NONE = 0, + ENET_SOCKET_WAIT_SEND = (1 << 0), + ENET_SOCKET_WAIT_RECEIVE = (1 << 1), + ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) } ENetSocketWait; typedef enum _ENetSocketOption @@ -50,16 +58,23 @@ typedef enum _ENetSocketOption ENET_SOCKOPT_BROADCAST = 2, ENET_SOCKOPT_RCVBUF = 3, ENET_SOCKOPT_SNDBUF = 4, - ENET_SOCKOPT_REUSEADDR = 5 + ENET_SOCKOPT_REUSEADDR = 5, + ENET_SOCKOPT_RCVTIMEO = 6, + ENET_SOCKOPT_SNDTIMEO = 7, + ENET_SOCKOPT_ERROR = 8, + ENET_SOCKOPT_NODELAY = 9 } ENetSocketOption; -enum +typedef enum _ENetSocketShutdown { - ENET_HOST_ANY = 0, /**< specifies the default server host */ - ENET_HOST_BROADCAST = 0xFFFFFFFF, /**< specifies a subnet-wide broadcast */ + ENET_SOCKET_SHUTDOWN_READ = 0, + ENET_SOCKET_SHUTDOWN_WRITE = 1, + ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 +} ENetSocketShutdown; - ENET_PORT_ANY = 0 /**< specifies that a port should be automatically chosen */ -}; +#define ENET_HOST_ANY 0 +#define ENET_HOST_BROADCAST 0xFFFFFFFFU +#define ENET_PORT_ANY 0 /** * Portable internet address structure. @@ -99,10 +114,12 @@ typedef enum _ENetPacketFlag ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), /** packet will be fragmented using unreliable (instead of reliable) sends * if it exceeds the MTU */ - ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3) + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), + + /** whether the packet has been sent from all queues it has been entered into */ + ENET_PACKET_FLAG_SENT = (1<<8) } ENetPacketFlag; -struct _ENetPacket; typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *); /** @@ -121,7 +138,11 @@ typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *); * (not supported for reliable packets) * * ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead - + * + * ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable + * (instead of reliable) sends if it exceeds the MTU + * + * ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into @sa ENetPacketFlag */ typedef struct _ENetPacket @@ -131,6 +152,7 @@ typedef struct _ENetPacket enet_uint8 * data; /**< allocated data for packet */ size_t dataLength; /**< length of data */ ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ + void * userData; /**< application private data, may be freely modified */ } ENetPacket; typedef struct _ENetAcknowledgement @@ -191,6 +213,8 @@ enum ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, + ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, @@ -226,6 +250,11 @@ typedef struct _ENetChannel ENetList incomingUnreliableCommands; } ENetChannel; +typedef enum _ENetPeerFlag +{ + ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0) +} ENetPeerFlag; + /** * An ENet peer which data packets may be sent or received from. * @@ -267,6 +296,10 @@ typedef struct _ENetPeer enet_uint32 packetThrottleAcceleration; enet_uint32 packetThrottleDeceleration; enet_uint32 packetThrottleInterval; + enet_uint32 pingInterval; + enet_uint32 timeoutLimit; + enet_uint32 timeoutMinimum; + enet_uint32 timeoutMaximum; enet_uint32 lastRoundTripTime; enet_uint32 lowestRoundTripTime; enet_uint32 lastRoundTripTimeVariance; @@ -280,14 +313,15 @@ typedef struct _ENetPeer ENetList acknowledgements; ENetList sentReliableCommands; ENetList sentUnreliableCommands; - ENetList outgoingReliableCommands; - ENetList outgoingUnreliableCommands; + ENetList outgoingCommands; ENetList dispatchedCommands; - int needsDispatch; + enet_uint16 flags; + enet_uint16 reserved; enet_uint16 incomingUnsequencedGroup; enet_uint16 outgoingUnsequencedGroup; enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; enet_uint32 eventData; + size_t totalWaitingData; } ENetPeer; /** An ENet packet compressor for compressing UDP packets before socket sends or receives. @@ -306,6 +340,9 @@ typedef struct _ENetCompressor /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount); + +/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ +typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event); /** An ENet host for communicating with peers. * @@ -355,7 +392,12 @@ typedef struct _ENetHost enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ - int (*receiveCallback)(void); + ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ + size_t connectedPeers; + size_t bandwidthLimitedPeers; + size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ + size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ + size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ } ENetHost; /** @@ -372,7 +414,7 @@ typedef enum _ENetEventType ENET_EVENT_TYPE_CONNECT = 1, /** a peer has disconnected. This event is generated on a successful - * completion of a disconnect initiated by enet_pper_disconnect, if + * completion of a disconnect initiated by enet_peer_disconnect, if * a peer has timed out, or if a connection request intialized by * enet_host_connect has timed out. The peer field contains the peer * which disconnected. The data field contains user supplied data @@ -418,7 +460,7 @@ ENET_API int enet_initialize (void); Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use - @param inits user-overriden callbacks where any NULL callbacks will use ENet's defaults + @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults @returns 0 on success, < 0 on failure */ ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); @@ -429,6 +471,12 @@ ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCall */ ENET_API void enet_deinitialize (void); +/** + Gives the linked version of the ENet library. + @returns the version number +*/ +ENET_API ENetVersion enet_linked_version (void); + /** @} */ /** @defgroup private ENet private implementation functions */ @@ -448,6 +496,7 @@ ENET_API void enet_time_set (enet_uint32); */ ENET_API ENetSocket enet_socket_create (ENetSocketType); ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *); +ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *); ENET_API int enet_socket_listen (ENetSocket, int); ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *); @@ -455,6 +504,8 @@ ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENe ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int); +ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *); +ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown); ENET_API void enet_socket_destroy (ENetSocket); ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); @@ -463,6 +514,17 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock /** @defgroup Address ENet address functions @{ */ + +/** Attempts to parse the printable form of the IP address in the parameter hostName + and sets the host field in the address parameter if successful. + @param address destination to store the parsed IP address + @param hostName IP address to parse + @retval 0 on success + @retval < 0 on failure + @returns the address of the given hostName in address on success +*/ +ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName); + /** Attempts to resolve the host named by the parameter hostName and sets the host field in the address parameter if successful. @param address destination to store resolved address @@ -473,7 +535,7 @@ ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSock */ ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName); -/** Gives the printable form of the ip address specified in the address parameter. +/** Gives the printable form of the IP address specified in the address parameter. @param address address printed @param hostName destination for name, must not be NULL @param nameLength maximum length of hostName. @@ -498,7 +560,7 @@ ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32); ENET_API void enet_packet_destroy (ENetPacket *); ENET_API int enet_packet_resize (ENetPacket *, size_t); -extern enet_uint32 enet_crc32 (const ENetBuffer *, size_t); +ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t); ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); ENET_API void enet_host_destroy (ENetHost *); @@ -512,10 +574,14 @@ ENET_API int enet_host_compress_with_range_coder (ENetHost * host); ENET_API void enet_host_channel_limit (ENetHost *, size_t); ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); extern void enet_host_bandwidth_throttle (ENetHost *); +extern enet_uint32 enet_host_random_seed (void); +extern enet_uint32 enet_host_random (ENetHost *); ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); ENET_API void enet_peer_ping (ENetPeer *); +ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32); +ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); ENET_API void enet_peer_reset (ENetPeer *); ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32); ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32); @@ -525,10 +591,12 @@ extern int enet_peer_throttle (ENetPeer *, enet_uint32); extern void enet_peer_reset_queues (ENetPeer *); extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *); extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); -extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32); +extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); -extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *); -extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *); +extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *); +extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *); +extern void enet_peer_on_connect (ENetPeer *); +extern void enet_peer_on_disconnect (ENetPeer *); ENET_API void * enet_range_coder_create (void); ENET_API void enet_range_coder_destroy (void *); diff --git a/Sources/ENet/include/enet/protocol.h b/Sources/ENet/include/enet/protocol.h index faef91790..f8c73d8a6 100644 --- a/Sources/ENet/include/enet/protocol.h +++ b/Sources/ENet/include/enet/protocol.h @@ -13,10 +13,11 @@ enum ENET_PROTOCOL_MAXIMUM_MTU = 4096, ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, - ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768, + ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, - ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF + ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, + ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 }; typedef enum _ENetProtocolCommand @@ -52,10 +53,10 @@ typedef enum _ENetProtocolFlag ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 } ENetProtocolFlag; -#ifdef _MSC_VER_ +#ifdef _MSC_VER #pragma pack(push, 1) #define ENET_PACKED -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__clang__) #define ENET_PACKED __attribute__ ((packed)) #else #define ENET_PACKED @@ -189,7 +190,7 @@ typedef union _ENetProtocol ENetProtocolThrottleConfigure throttleConfigure; } ENET_PACKED ENetProtocol; -#ifdef _MSC_VER_ +#ifdef _MSC_VER #pragma pack(pop) #endif diff --git a/Sources/ENet/include/enet/unix.h b/Sources/ENet/include/enet/unix.h index 087015e51..b55be3310 100644 --- a/Sources/ENet/include/enet/unix.h +++ b/Sources/ENet/include/enet/unix.h @@ -8,15 +8,18 @@ #include #include #include +#include +#include #include #include +#ifdef MSG_MAXIOVLEN +#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN +#endif + typedef int ENetSocket; -enum -{ - ENET_SOCKET_NULL = -1 -}; +#define ENET_SOCKET_NULL -1 #define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ #define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ @@ -38,7 +41,7 @@ typedef fd_set ENetSocketSet; #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset)) +#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) #endif /* __ENET_UNIX_H__ */ diff --git a/Sources/ENet/include/enet/utility.h b/Sources/ENet/include/enet/utility.h index e48a476be..b04bb7a5b 100644 --- a/Sources/ENet/include/enet/utility.h +++ b/Sources/ENet/include/enet/utility.h @@ -7,6 +7,7 @@ #define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) +#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y)) #endif /* __ENET_UTILITY_H__ */ diff --git a/Sources/ENet/include/enet/win32.h b/Sources/ENet/include/enet/win32.h index 0e1cf0c5a..6fbd7c02c 100644 --- a/Sources/ENet/include/enet/win32.h +++ b/Sources/ENet/include/enet/win32.h @@ -5,11 +5,15 @@ #ifndef __ENET_WIN32_H__ #define __ENET_WIN32_H__ +#ifdef _MSC_VER #ifdef ENET_BUILDING_LIB -#pragma warning (disable: 4996) // 'strncpy' was declared deprecated #pragma warning (disable: 4267) // size_t to int conversion #pragma warning (disable: 4244) // 64bit to 32bit int #pragma warning (disable: 4018) // signed/unsigned mismatch +#pragma warning (disable: 4146) // unary minus operator applied to unsigned type +#define _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_WARNINGS +#endif #endif #include @@ -17,10 +21,7 @@ typedef SOCKET ENetSocket; -enum -{ - ENET_SOCKET_NULL = INVALID_SOCKET -}; +#define ENET_SOCKET_NULL INVALID_SOCKET #define ENET_HOST_TO_NET_16(value) (htons (value)) #define ENET_HOST_TO_NET_32(value) (htonl (value)) @@ -36,8 +37,8 @@ typedef struct #define ENET_CALLBACK __cdecl -#if defined ENET_DLL -#if defined ENET_BUILDING_LIB +#ifdef ENET_DLL +#ifdef ENET_BUILDING_LIB #define ENET_API __declspec( dllexport ) #else #define ENET_API __declspec( dllimport ) @@ -50,7 +51,7 @@ typedef fd_set ENetSocketSet; #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset)) +#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) #endif /* __ENET_WIN32_H__ */ diff --git a/Sources/ENet/packet.c b/Sources/ENet/packet.c index 2fc9a10e8..5fa78b28a 100644 --- a/Sources/ENet/packet.c +++ b/Sources/ENet/packet.c @@ -11,7 +11,7 @@ */ /** Creates a packet that may be sent to a peer. - @param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL. + @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. @param dataLength size of the data allocated for this packet @param flags flags for this packet as described for the ENetPacket structure. @returns the packet on success, NULL on failure @@ -26,6 +26,9 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) packet -> data = (enet_uint8 *) data; else + if (dataLength <= 0) + packet -> data = NULL; + else { packet -> data = (enet_uint8 *) enet_malloc (dataLength); if (packet -> data == NULL) @@ -42,6 +45,7 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) packet -> flags = flags; packet -> dataLength = dataLength; packet -> freeCallback = NULL; + packet -> userData = NULL; return packet; } @@ -52,9 +56,13 @@ enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags) void enet_packet_destroy (ENetPacket * packet) { + if (packet == NULL) + return; + if (packet -> freeCallback != NULL) (* packet -> freeCallback) (packet); - if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) && + packet -> data != NULL) enet_free (packet -> data); enet_free (packet); } @@ -108,7 +116,7 @@ reflect_crc (int val, int bits) } static void -initialize_crc32 () +initialize_crc32 (void) { int byte; diff --git a/Sources/ENet/peer.c b/Sources/ENet/peer.c index 44b0bc5a9..32f9809f3 100644 --- a/Sources/ENet/peer.c +++ b/Sources/ENet/peer.c @@ -25,7 +25,7 @@ the mean round trip time measured over the interval, then the throttle probability is decreased to limit traffic by an amount specified in the deceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has - a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by + a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by ENet, and so 100% of all unreliable packets will be sent. When the throttle has a value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable packets will be sent. Intermediate values for the throttle represent intermediate @@ -66,7 +66,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt) peer -> packetThrottle = peer -> packetThrottleLimit; } else - if (rtt < peer -> lastRoundTripTime) + if (rtt <= peer -> lastRoundTripTime) { peer -> packetThrottle += peer -> packetThrottleAcceleration; @@ -99,21 +99,23 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt) int enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) { - ENetChannel * channel = & peer -> channels [channelID]; + ENetChannel * channel; ENetProtocol command; size_t fragmentLength; if (peer -> state != ENET_PEER_STATE_CONNECTED || - channelID >= peer -> channelCount) + channelID >= peer -> channelCount || + packet -> dataLength > peer -> host -> maximumPacketSize) return -1; + channel = & peer -> channels [channelID]; fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment); if (peer -> host -> checksum != NULL) fragmentLength -= sizeof(enet_uint32); if (packet -> dataLength > fragmentLength) { - enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength), + enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset; enet_uint8 commandNumber; @@ -121,6 +123,9 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) ENetList fragments; ENetOutgoingCommand * fragment; + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + return -1; + if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && channel -> outgoingUnreliableSequenceNumber < 0xFFFF) { @@ -164,7 +169,7 @@ enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet) fragment -> command.header.channelID = channelID; fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber; fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength); - fragment -> command.sendFragment.fragmentCount = fragmentCount; + fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount); fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber); fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength); fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset); @@ -237,6 +242,8 @@ enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID) enet_free (incomingCommand); + peer -> totalWaitingData -= packet -> dataLength; + return packet; } @@ -262,7 +269,7 @@ enet_peer_reset_outgoing_commands (ENetList * queue) } static void -enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand) +enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand, ENetIncomingCommand * excludeCommand) { ENetListIterator currentCommand; @@ -272,6 +279,9 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm currentCommand = enet_list_next (currentCommand); + if (incomingCommand == excludeCommand) + continue; + enet_list_remove (& incomingCommand -> incomingCommandList); if (incomingCommand -> packet != NULL) @@ -292,7 +302,7 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm static void enet_peer_reset_incoming_commands (ENetList * queue) { - enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end(queue)); + enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue), NULL); } void @@ -300,11 +310,11 @@ enet_peer_reset_queues (ENetPeer * peer) { ENetChannel * channel; - if (peer -> needsDispatch) + if (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH) { enet_list_remove (& peer -> dispatchList); - peer -> needsDispatch = 0; + peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH; } while (! enet_list_empty (& peer -> acknowledgements)) @@ -312,8 +322,7 @@ enet_peer_reset_queues (ENetPeer * peer) enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands); enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands); - enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands); - enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands); + enet_peer_reset_outgoing_commands (& peer -> outgoingCommands); enet_peer_reset_incoming_commands (& peer -> dispatchedCommands); if (peer -> channels != NULL && peer -> channelCount > 0) @@ -333,6 +342,30 @@ enet_peer_reset_queues (ENetPeer * peer) peer -> channelCount = 0; } +void +enet_peer_on_connect (ENetPeer * peer) +{ + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + { + if (peer -> incomingBandwidth != 0) + ++ peer -> host -> bandwidthLimitedPeers; + + ++ peer -> host -> connectedPeers; + } +} + +void +enet_peer_on_disconnect (ENetPeer * peer) +{ + if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) + { + if (peer -> incomingBandwidth != 0) + -- peer -> host -> bandwidthLimitedPeers; + + -- peer -> host -> connectedPeers; + } +} + /** Forcefully disconnects a peer. @param peer peer to forcefully disconnect @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout @@ -341,6 +374,8 @@ enet_peer_reset_queues (ENetPeer * peer) void enet_peer_reset (ENetPeer * peer) { + enet_peer_on_disconnect (peer); + peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; peer -> connectID = 0; @@ -368,6 +403,10 @@ enet_peer_reset (ENetPeer * peer) peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; + peer -> pingInterval = ENET_PEER_PING_INTERVAL; + peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; + peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; + peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; peer -> lastRoundTripTimeVariance = 0; @@ -381,6 +420,8 @@ enet_peer_reset (ENetPeer * peer) peer -> incomingUnsequencedGroup = 0; peer -> outgoingUnsequencedGroup = 0; peer -> eventData = 0; + peer -> totalWaitingData = 0; + peer -> flags = 0; memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow)); @@ -390,7 +431,7 @@ enet_peer_reset (ENetPeer * peer) /** Sends a ping request to a peer. @param peer destination for the ping request @remarks ping requests factor into the mean round trip time as designated by the - roundTripTime field in the ENetPeer structure. Enet automatically pings all connected + roundTripTime field in the ENetPeer structure. ENet automatically pings all connected peers at regular intervals, however, this function may be called to ensure more frequent ping requests. */ @@ -408,11 +449,51 @@ enet_peer_ping (ENetPeer * peer) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); } +/** Sets the interval at which pings will be sent to a peer. + + Pings are used both to monitor the liveness of the connection and also to dynamically + adjust the throttle during periods of low traffic so that the throttle has reasonable + responsiveness during traffic spikes. + + @param peer the peer to adjust + @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 +*/ +void +enet_peer_ping_interval (ENetPeer * peer, enet_uint32 pingInterval) +{ + peer -> pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; +} + +/** Sets the timeout parameters for a peer. + + The timeout parameter control how and when a peer will timeout from a failure to acknowledge + reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable + packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, + the timeout will be doubled until it reaches a set limit. If the timeout is thus at this + limit and reliable packets have been sent but not acknowledged within a certain minimum time + period, the peer will be disconnected. Alternatively, if reliable packets have been sent + but not acknowledged for a certain maximum time period, the peer will be disconnected regardless + of the current timeout limit value. + + @param peer the peer to adjust + @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0 + @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0 + @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0 +*/ + +void +enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) +{ + peer -> timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; + peer -> timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; + peer -> timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; +} + /** Force an immediate disconnection from a peer. @param peer peer to disconnect @param data data describing the disconnection @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not - guarenteed to receive the disconnect notification, and is reset immediately upon + guaranteed to receive the disconnect notification, and is reset immediately upon return from this function. */ void @@ -471,7 +552,11 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data) enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0); if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) - peer -> state = ENET_PEER_STATE_DISCONNECTING; + { + enet_peer_on_disconnect (peer); + + peer -> state = ENET_PEER_STATE_DISCONNECTING; + } else { enet_host_flush (peer -> host); @@ -489,8 +574,7 @@ void enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data) { if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && - ! (enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && + ! (enet_list_empty (& peer -> outgoingCommands) && enet_list_empty (& peer -> sentReliableCommands))) { peer -> state = ENET_PEER_STATE_DISCONNECT_LATER; @@ -536,7 +620,7 @@ void enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand) { ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID]; - + peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength; if (outgoingCommand -> command.header.channelID == 0xFF) @@ -592,10 +676,7 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin break; } - if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) - enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); - else - enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); + enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand); } ENetOutgoingCommand * @@ -618,7 +699,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, } void -enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel) +enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand) { ENetListIterator droppedCommand, startCommand, currentCommand; @@ -630,49 +711,78 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) continue; - else - if (incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber) - break; - else - if (incomingCommand -> fragmentsRemaining <= 0) - channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; - else - if (startCommand == currentCommand) - startCommand = enet_list_next (currentCommand); - else + + if (incomingCommand -> reliableSequenceNumber == channel -> incomingReliableSequenceNumber) { - enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + if (incomingCommand -> fragmentsRemaining <= 0) + { + channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber; + continue; + } - if (! peer -> needsDispatch) - { + if (startCommand != currentCommand) + { + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + + if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)) + { enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); - peer -> needsDispatch = 1; - } + peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH; + } - droppedCommand = startCommand = enet_list_next (currentCommand); + droppedCommand = currentCommand; + } + else + if (droppedCommand != currentCommand) + droppedCommand = enet_list_previous (currentCommand); } + else + { + enet_uint16 reliableWindow = incomingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE, + currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber) + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) + break; + + droppedCommand = enet_list_next (currentCommand); + + if (startCommand != currentCommand) + { + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + + if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + + peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH; + } + } + } + + startCommand = enet_list_next (currentCommand); } if (startCommand != currentCommand) { - enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); + enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand)); - if (! peer -> needsDispatch) - { - enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); + if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)) + { + enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); - peer -> needsDispatch = 1; - } + peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH; + } - droppedCommand = startCommand = enet_list_next (currentCommand); + droppedCommand = currentCommand; } - enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand); + enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand, queuedCommand); } void -enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel) +enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand) { ENetListIterator currentCommand; @@ -699,18 +809,19 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand)); - if (! peer -> needsDispatch) + if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)) { enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList); - peer -> needsDispatch = 1; + peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH; } - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + if (! enet_list_empty (& channel -> incomingUnreliableCommands)) + enet_peer_dispatch_incoming_unreliable_commands (peer, channel, queuedCommand); } ENetIncomingCommand * -enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount) +enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) { static ENetIncomingCommand dummyCommand; @@ -719,9 +830,10 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, enet_uint16 reliableWindow, currentWindow; ENetIncomingCommand * incomingCommand; ENetListIterator currentCommand; + ENetPacket * packet = NULL; if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) - goto freePacket; + goto discardCommand; if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { @@ -733,7 +845,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, reliableWindow += ENET_PEER_RELIABLE_WINDOWS; if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) - goto freePacket; + goto discardCommand; } switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) @@ -741,7 +853,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber) - goto freePacket; + goto discardCommand; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); currentCommand != enet_list_end (& channel -> incomingReliableCommands); @@ -763,7 +875,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber) break; - goto freePacket; + goto discardCommand; } } break; @@ -774,7 +886,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber && unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber) - goto freePacket; + goto discardCommand; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); currentCommand != enet_list_end (& channel -> incomingUnreliableCommands); @@ -805,7 +917,7 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber) break; - goto freePacket; + goto discardCommand; } } break; @@ -815,9 +927,16 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, break; default: - goto freePacket; + goto discardCommand; } + if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData) + goto notifyError; + + packet = enet_packet_create (data, dataLength, flags); + if (packet == NULL) + goto notifyError; + incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand)); if (incomingCommand == NULL) goto notifyError; @@ -832,7 +951,8 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, if (fragmentCount > 0) { - incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); + if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) + incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32)); if (incomingCommand -> fragments == NULL) { enet_free (incomingCommand); @@ -843,7 +963,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, } if (packet != NULL) - ++ packet -> referenceCount; + { + ++ packet -> referenceCount; + + peer -> totalWaitingData += packet -> dataLength; + } enet_list_insert (enet_list_next (currentCommand), incomingCommand); @@ -851,17 +975,17 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, { case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: - enet_peer_dispatch_incoming_reliable_commands (peer, channel); + enet_peer_dispatch_incoming_reliable_commands (peer, channel, incomingCommand); break; default: - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + enet_peer_dispatch_incoming_unreliable_commands (peer, channel, incomingCommand); break; } return incomingCommand; -freePacket: +discardCommand: if (fragmentCount > 0) goto notifyError; diff --git a/Sources/ENet/protocol.c b/Sources/ENet/protocol.c index d12360bd2..991d88ac0 100644 --- a/Sources/ENet/protocol.c +++ b/Sources/ENet/protocol.c @@ -32,6 +32,30 @@ enet_protocol_command_size (enet_uint8 commandNumber) return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK]; } +static void +enet_protocol_change_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) +{ + if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER) + enet_peer_on_connect (peer); + else + enet_peer_on_disconnect (peer); + + peer -> state = state; +} + +static void +enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) +{ + enet_protocol_change_state (host, peer, state); + + if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)) + { + enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); + + peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH; + } +} + static int enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { @@ -39,13 +63,13 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) { ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue)); - peer -> needsDispatch = 0; + peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH; switch (peer -> state) { case ENET_PEER_STATE_CONNECTION_PENDING: case ENET_PEER_STATE_CONNECTION_SUCCEEDED: - peer -> state = ENET_PEER_STATE_CONNECTED; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED); event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; @@ -77,32 +101,21 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event) if (! enet_list_empty (& peer -> dispatchedCommands)) { - peer -> needsDispatch = 1; + peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH; enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); } return 1; - default: break; + + default: + break; } } return 0; } -static void -enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state) -{ - peer -> state = state; - - if (! peer -> needsDispatch) - { - enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList); - - peer -> needsDispatch = 1; - } -} - static void enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event) { @@ -110,7 +123,7 @@ enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * even if (event != NULL) { - peer -> state = ENET_PEER_STATE_CONNECTED; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED); event -> type = ENET_EVENT_TYPE_CONNECT; event -> peer = peer; @@ -148,9 +161,12 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e static void enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) { - ENetOutgoingCommand * outgoingCommand; + ENetOutgoingCommand * outgoingCommand = NULL; + + if (enet_list_empty (& peer -> sentUnreliableCommands)) + return; - while (! enet_list_empty (& peer -> sentUnreliableCommands)) + do { outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands); @@ -161,11 +177,20 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + { + outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT; + + enet_packet_destroy (outgoingCommand -> packet); + } } enet_free (outgoingCommand); - } + } while (! enet_list_empty (& peer -> sentUnreliableCommands)); + + if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && + enet_list_empty (& peer -> outgoingCommands) && + enet_list_empty (& peer -> sentReliableCommands)) + enet_peer_disconnect (peer, peer -> eventData); } static ENetProtocolCommand @@ -189,12 +214,15 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl if (currentCommand == enet_list_end (& peer -> sentReliableCommands)) { - for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands); - currentCommand != enet_list_end (& peer -> outgoingReliableCommands); + for (currentCommand = enet_list_begin (& peer -> outgoingCommands); + currentCommand != enet_list_end (& peer -> outgoingCommands); currentCommand = enet_list_next (currentCommand)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; + if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)) + continue; + if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE; if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber && @@ -202,12 +230,15 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl break; } - if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands)) + if (currentCommand == enet_list_end (& peer -> outgoingCommands)) return ENET_PROTOCOL_COMMAND_NONE; wasSent = 0; } + if (outgoingCommand == NULL) + return ENET_PROTOCOL_COMMAND_NONE; + if (channelID < peer -> channelCount) { ENetChannel * channel = & peer -> channels [channelID]; @@ -232,7 +263,11 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl -- outgoingCommand -> packet -> referenceCount; if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); + { + outgoingCommand -> packet -> flags |= ENET_PACKET_FLAG_SENT; + + enet_packet_destroy (outgoingCommand -> packet); + } } enet_free (outgoingCommand); @@ -253,8 +288,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet enet_uint8 incomingSessionID, outgoingSessionID; enet_uint32 mtu, windowSize; ENetChannel * channel; - size_t channelCount; - ENetPeer * currentPeer; + size_t channelCount, duplicatePeers = 0; + ENetPeer * currentPeer, * peer = NULL; ENetProtocol verifyCommand; channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount); @@ -263,59 +298,61 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) return NULL; - for (currentPeer = host -> peers; - currentPeer < & host -> peers [host -> peerCount]; - ++ currentPeer) - { - if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED && - currentPeer -> address.host == host -> receivedAddress.host && - currentPeer -> address.port == host -> receivedAddress.port && - currentPeer -> connectID == command -> connect.connectID) - return NULL; - } - for (currentPeer = host -> peers; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED) - break; + { + if (peer == NULL) + peer = currentPeer; + } + else + if (currentPeer -> state != ENET_PEER_STATE_CONNECTING && + currentPeer -> address.host == host -> receivedAddress.host) + { + if (currentPeer -> address.port == host -> receivedAddress.port && + currentPeer -> connectID == command -> connect.connectID) + return NULL; + + ++ duplicatePeers; + } } - if (currentPeer >= & host -> peers [host -> peerCount]) + if (peer == NULL || duplicatePeers >= host -> duplicatePeers) return NULL; if (channelCount > host -> channelLimit) channelCount = host -> channelLimit; - currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); - if (currentPeer -> channels == NULL) + peer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel)); + if (peer -> channels == NULL) return NULL; - currentPeer -> channelCount = channelCount; - currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; - currentPeer -> connectID = command -> connect.connectID; - currentPeer -> address = host -> receivedAddress; - currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); - currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); - currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); - currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); - currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); - currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); - currentPeer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); - - incomingSessionID = command -> connect.incomingSessionID == 0xFF ? currentPeer -> outgoingSessionID : command -> connect.incomingSessionID; + peer -> channelCount = channelCount; + peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; + peer -> connectID = command -> connect.connectID; + peer -> address = host -> receivedAddress; + peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID); + peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth); + peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth); + peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval); + peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration); + peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration); + peer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data); + + incomingSessionID = command -> connect.incomingSessionID == 0xFF ? peer -> outgoingSessionID : command -> connect.incomingSessionID; incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (incomingSessionID == currentPeer -> outgoingSessionID) + if (incomingSessionID == peer -> outgoingSessionID) incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - currentPeer -> outgoingSessionID = incomingSessionID; + peer -> outgoingSessionID = incomingSessionID; - outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? currentPeer -> incomingSessionID : command -> connect.outgoingSessionID; + outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? peer -> incomingSessionID : command -> connect.outgoingSessionID; outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (outgoingSessionID == currentPeer -> incomingSessionID) + if (outgoingSessionID == peer -> incomingSessionID) outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - currentPeer -> incomingSessionID = outgoingSessionID; + peer -> incomingSessionID = outgoingSessionID; - for (channel = currentPeer -> channels; - channel < & currentPeer -> channels [channelCount]; + for (channel = peer -> channels; + channel < & peer -> channels [channelCount]; ++ channel) { channel -> outgoingReliableSequenceNumber = 0; @@ -338,27 +375,27 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) mtu = ENET_PROTOCOL_MAXIMUM_MTU; - currentPeer -> mtu = mtu; + peer -> mtu = mtu; if (host -> outgoingBandwidth == 0 && - currentPeer -> incomingBandwidth == 0) - currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + peer -> incomingBandwidth == 0) + peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; else if (host -> outgoingBandwidth == 0 || - currentPeer -> incomingBandwidth == 0) - currentPeer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / + peer -> incomingBandwidth == 0) + peer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, peer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else - currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) / + peer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, peer -> incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) - currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) + peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else - if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) - currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) + peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; if (host -> incomingBandwidth == 0) windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; @@ -377,28 +414,27 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; verifyCommand.header.channelID = 0xFF; - verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID); + verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (peer -> incomingPeerID); verifyCommand.verifyConnect.incomingSessionID = incomingSessionID; verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID; - verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu); + verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32 (peer -> mtu); verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize); verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount); verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth); verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth); - verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval); - verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration); - verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration); - verifyCommand.verifyConnect.connectID = currentPeer -> connectID; + verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (peer -> packetThrottleInterval); + verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleAcceleration); + verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (peer -> packetThrottleDeceleration); + verifyCommand.verifyConnect.connectID = peer -> connectID; - enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0); + enet_peer_queue_outgoing_command (peer, & verifyCommand, NULL, 0, 0); - return currentPeer; + return peer; } static int enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { - ENetPacket * packet; size_t dataLength; if (command -> header.channelID >= peer -> channelCount || @@ -407,14 +443,12 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), - dataLength, - ENET_PACKET_FLAG_RELIABLE); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL) return -1; return 0; @@ -423,7 +457,6 @@ enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENet static int enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { - ENetPacket * packet; enet_uint32 unsequencedGroup, index; size_t dataLength; @@ -433,7 +466,9 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup); @@ -457,11 +492,7 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E if (peer -> unsequencedWindow [index / 32] & (1u << (index % 32))) return 0; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), - dataLength, - ENET_PACKET_FLAG_UNSEQUENCED); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED, 0) == NULL) return -1; peer -> unsequencedWindow [index / 32] |= 1u << (index % 32); @@ -472,7 +503,6 @@ enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const E static int enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData) { - ENetPacket * packet; size_t dataLength; if (command -> header.channelID >= peer -> channelCount || @@ -481,14 +511,12 @@ enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const EN dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength); * currentData += dataLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (dataLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; - packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), - dataLength, - 0); - if (packet == NULL || - enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL) + if (enet_peer_queue_incoming_command (peer, command, (const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL) return -1; return 0; @@ -514,7 +542,9 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -533,9 +563,11 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - if (fragmentOffset >= totalLength || - fragmentOffset + fragmentLength > totalLength || - fragmentNumber >= fragmentCount) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host -> maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands)); @@ -571,13 +603,10 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet if (startCommand == NULL) { ENetProtocol hostCommand = * command; - ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE); - if (packet == NULL) - return -1; hostCommand.header.reliableSequenceNumber = startSequenceNumber; - startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount); + startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount); if (startCommand == NULL) return -1; } @@ -596,7 +625,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentLength); if (startCommand -> fragmentsRemaining <= 0) - enet_peer_dispatch_incoming_reliable_commands (peer, channel); + enet_peer_dispatch_incoming_reliable_commands (peer, channel, NULL); } return 0; @@ -623,7 +652,9 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength); * currentData += fragmentLength; - if (* currentData > & host -> receivedData [host -> receivedDataLength]) + if (fragmentLength > host -> maximumPacketSize || + * currentData < host -> receivedData || + * currentData > & host -> receivedData [host -> receivedDataLength]) return -1; channel = & peer -> channels [command -> header.channelID]; @@ -648,9 +679,11 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset); totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength); - if (fragmentOffset >= totalLength || - fragmentOffset + fragmentLength > totalLength || - fragmentNumber >= fragmentCount) + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host -> maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset) return -1; for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands)); @@ -691,11 +724,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, if (startCommand == NULL) { - ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); - if (packet == NULL) - return -1; - - startCommand = enet_peer_queue_incoming_command (peer, command, packet, fragmentCount); + startCommand = enet_peer_queue_incoming_command (peer, command, NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount); if (startCommand == NULL) return -1; } @@ -714,7 +743,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentLength); if (startCommand -> fragmentsRemaining <= 0) - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + enet_peer_dispatch_incoming_unreliable_commands (peer, channel, NULL); } return 0; @@ -723,17 +752,33 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, static int enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + return 0; } static int enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + + if (peer -> incomingBandwidth != 0) + -- host -> bandwidthLimitedPeers; + peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth); peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth); + if (peer -> incomingBandwidth != 0) + ++ host -> bandwidthLimitedPeers; + if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0) peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + else + if (peer -> incomingBandwidth == 0 || host -> outgoingBandwidth == 0) + peer -> windowSize = (ENET_MAX (peer -> incomingBandwidth, host -> outgoingBandwidth) / + ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; else peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; @@ -750,6 +795,9 @@ enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const EN static int enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { + if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) + return -1; + peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval); peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration); peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration); @@ -760,12 +808,12 @@ enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const static int enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command) { - if (peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT) + if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT) return 0; enet_peer_reset_queues (peer); - if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING) + if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING || peer -> state == ENET_PEER_STATE_CONNECTING) enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); else if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) @@ -776,7 +824,7 @@ enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetPro } else if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) - peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT; + enet_protocol_change_state (host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT); else enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE); @@ -794,6 +842,9 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * receivedReliableSequenceNumber; ENetProtocolCommand commandNumber; + if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE) + return 0; + receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime); receivedSentTime |= host -> serviceTime & 0xFFFF0000; if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000)) @@ -802,42 +853,53 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime)) return 0; - peer -> lastReceiveTime = host -> serviceTime; - peer -> earliestTimeout = 0; - roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime); + roundTripTime = ENET_MAX (roundTripTime, 1); - enet_peer_throttle (peer, roundTripTime); + if (peer -> lastReceiveTime > 0) + { + enet_peer_throttle (peer, roundTripTime); - peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4; + peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4; - if (roundTripTime >= peer -> roundTripTime) - { - peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8; - peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4; + if (roundTripTime >= peer -> roundTripTime) + { + enet_uint32 diff = roundTripTime - peer -> roundTripTime; + peer -> roundTripTimeVariance += diff / 4; + peer -> roundTripTime += diff / 8; + } + else + { + enet_uint32 diff = peer -> roundTripTime - roundTripTime; + peer -> roundTripTimeVariance += diff / 4; + peer -> roundTripTime -= diff / 8; + } } else { - peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8; - peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4; + peer -> roundTripTime = roundTripTime; + peer -> roundTripTimeVariance = (roundTripTime + 1) / 2; } if (peer -> roundTripTime < peer -> lowestRoundTripTime) peer -> lowestRoundTripTime = peer -> roundTripTime; - if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance) + if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance) peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance; if (peer -> packetThrottleEpoch == 0 || ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval) { peer -> lastRoundTripTime = peer -> lowestRoundTripTime; - peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance; + peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 1); peer -> lowestRoundTripTime = peer -> roundTripTime; peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance; peer -> packetThrottleEpoch = host -> serviceTime; } + peer -> lastReceiveTime = ENET_MAX (host -> serviceTime, 1); + peer -> earliestTimeout = 0; + receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber); commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID); @@ -859,12 +921,13 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * break; case ENET_PEER_STATE_DISCONNECT_LATER: - if (enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && + if (enet_list_empty (& peer -> outgoingCommands) && enet_list_empty (& peer -> sentReliableCommands)) enet_peer_disconnect (peer, peer -> eventData); break; - default: break; + + default: + break; } return 0; @@ -1044,7 +1107,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber); - switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK) + switch (commandNumber) { case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE: if (enet_protocol_handle_acknowledge (host, event, peer, command)) @@ -1052,6 +1115,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) break; case ENET_PROTOCOL_COMMAND_CONNECT: + if (peer != NULL) + goto commandError; peer = enet_protocol_handle_connect (host, header, command); if (peer == NULL) goto commandError; @@ -1125,6 +1190,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) { case ENET_PEER_STATE_DISCONNECTING: case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: + case ENET_PEER_STATE_DISCONNECTED: + case ENET_PEER_STATE_ZOMBIE: break; case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT: @@ -1149,7 +1216,9 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) static int enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) { - for (;;) + int packets; + + for (packets = 0; packets < 256; ++ packets) { int receivedLength; ENetBuffer buffer; @@ -1173,10 +1242,25 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) host -> totalReceivedData += receivedLength; host -> totalReceivedPackets ++; - - if (host -> receiveCallback != NULL && host -> receiveCallback() == 1) - return 1; - + + if (host -> intercept != NULL) + { + switch (host -> intercept (host, event)) + { + case 1: + if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) + return 1; + + continue; + + case -1: + return -1; + + default: + break; + } + } + switch (enet_protocol_handle_incoming_commands (host, event)) { case 1: @@ -1190,7 +1274,7 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event) } } - return -1; + return 0; } static void @@ -1200,7 +1284,8 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetAcknowledgement * acknowledgement; ENetListIterator currentAcknowledgement; - + enet_uint16 reliableSequenceNumber; + currentAcknowledgement = enet_list_begin (& peer -> acknowledgements); while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements)) @@ -1222,10 +1307,13 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) buffer -> dataLength = sizeof (ENetProtocolAcknowledge); host -> packetSize += buffer -> dataLength; - + + reliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; command -> header.channelID = acknowledgement -> command.header.channelID; - command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber); + command -> header.reliableSequenceNumber = reliableSequenceNumber; + command -> acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber; command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime); if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) @@ -1242,107 +1330,6 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) host -> bufferCount = buffer - host -> buffers; } -static void -enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer) -{ - ENetProtocol * command = & host -> commands [host -> commandCount]; - ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; - ENetOutgoingCommand * outgoingCommand; - ENetListIterator currentCommand; - - currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands); - - while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands)) - { - size_t commandSize; - - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK]; - - if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || - buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || - peer -> mtu - host -> packetSize < commandSize || - (outgoingCommand -> packet != NULL && - peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength)) - { - host -> continueSending = 1; - - break; - } - - currentCommand = enet_list_next (currentCommand); - - if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0) - { - peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; - peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; - - if (peer -> packetThrottleCounter > peer -> packetThrottle) - { - enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber, - unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber; - for (;;) - { - -- outgoingCommand -> packet -> referenceCount; - - if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); - - enet_list_remove (& outgoingCommand -> outgoingCommandList); - enet_free (outgoingCommand); - - if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands)) - break; - - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber || - outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber) - break; - - currentCommand = enet_list_next (currentCommand); - } - - continue; - } - } - - buffer -> data = command; - buffer -> dataLength = commandSize; - - host -> packetSize += buffer -> dataLength; - - * command = outgoingCommand -> command; - - enet_list_remove (& outgoingCommand -> outgoingCommandList); - - if (outgoingCommand -> packet != NULL) - { - ++ buffer; - - buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset; - buffer -> dataLength = outgoingCommand -> fragmentLength; - - host -> packetSize += buffer -> dataLength; - - enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); - } - else - enet_free (outgoingCommand); - - ++ command; - ++ buffer; - } - - host -> commandCount = command - host -> commands; - host -> bufferCount = buffer - host -> buffers; - - if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && - enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && - enet_list_empty (& peer -> sentReliableCommands)) - enet_peer_disconnect (peer, peer -> eventData); -} - static int enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event) { @@ -1350,7 +1337,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even ENetListIterator currentCommand, insertPosition; currentCommand = enet_list_begin (& peer -> sentReliableCommands); - insertPosition = enet_list_begin (& peer -> outgoingReliableCommands); + insertPosition = enet_list_begin (& peer -> outgoingCommands); while (currentCommand != enet_list_end (& peer -> sentReliableCommands)) { @@ -1366,9 +1353,9 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even peer -> earliestTimeout = outgoingCommand -> sentTime; if (peer -> earliestTimeout != 0 && - (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MAXIMUM || + (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum || (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit && - ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MINIMUM))) + ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum))) { enet_protocol_notify_disconnect (host, peer, event); @@ -1397,60 +1384,63 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even } static int -enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) +enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer) { ENetProtocol * command = & host -> commands [host -> commandCount]; ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; ENetOutgoingCommand * outgoingCommand; ENetListIterator currentCommand; - ENetChannel *channel; - enet_uint16 reliableWindow; + ENetChannel *channel = NULL; + enet_uint16 reliableWindow = 0; size_t commandSize; int windowExceeded = 0, windowWrap = 0, canPing = 1; - currentCommand = enet_list_begin (& peer -> outgoingReliableCommands); + currentCommand = enet_list_begin (& peer -> outgoingCommands); - while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands)) + while (currentCommand != enet_list_end (& peer -> outgoingCommands)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; - channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL; - reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - if (channel != NULL) + if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - if (! windowWrap && - outgoingCommand -> sendAttempts < 1 && - ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && - (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || - channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) | - (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOW_SIZE - reliableWindow))))) - windowWrap = 1; - if (windowWrap) + channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL; + reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (channel != NULL) { - currentCommand = enet_list_next (currentCommand); + if (! windowWrap && + outgoingCommand -> sendAttempts < 1 && + ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && + (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || + channel -> usedReliableWindows & ((((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) << reliableWindow) | + (((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow))))) + windowWrap = 1; + if (windowWrap) + { + currentCommand = enet_list_next (currentCommand); - continue; + continue; + } } - } - if (outgoingCommand -> packet != NULL) - { - if (! windowExceeded) + if (outgoingCommand -> packet != NULL) { - enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; + if (! windowExceeded) + { + enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; - if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu)) - windowExceeded = 1; - } - if (windowExceeded) - { - currentCommand = enet_list_next (currentCommand); + if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu)) + windowExceeded = 1; + } + if (windowExceeded) + { + currentCommand = enet_list_next (currentCommand); - continue; + continue; + } } - } - canPing = 0; + canPing = 0; + } commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK]; if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || @@ -1466,33 +1456,80 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) currentCommand = enet_list_next (currentCommand); - if (channel != NULL && outgoingCommand -> sendAttempts < 1) + if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - channel -> usedReliableWindows |= 1 << reliableWindow; - ++ channel -> reliableWindows [reliableWindow]; - } + if (channel != NULL && outgoingCommand -> sendAttempts < 1) + { + channel -> usedReliableWindows |= 1 << reliableWindow; + ++ channel -> reliableWindows [reliableWindow]; + } - ++ outgoingCommand -> sendAttempts; + ++ outgoingCommand -> sendAttempts; - if (outgoingCommand -> roundTripTimeout == 0) - { - outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; - outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout; + if (outgoingCommand -> roundTripTimeout == 0) + { + outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; + outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout; + } + + if (enet_list_empty (& peer -> sentReliableCommands)) + peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout; + + enet_list_insert (enet_list_end (& peer -> sentReliableCommands), + enet_list_remove (& outgoingCommand -> outgoingCommandList)); + + outgoingCommand -> sentTime = host -> serviceTime; + + host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; + + peer -> reliableDataInTransit += outgoingCommand -> fragmentLength; } + else + { + if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0) + { + peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; + peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; - if (enet_list_empty (& peer -> sentReliableCommands)) - peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout; + if (peer -> packetThrottleCounter > peer -> packetThrottle) + { + enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber, + unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber; + for (;;) + { + -- outgoingCommand -> packet -> referenceCount; - enet_list_insert (enet_list_end (& peer -> sentReliableCommands), - enet_list_remove (& outgoingCommand -> outgoingCommandList)); + if (outgoingCommand -> packet -> referenceCount == 0) + enet_packet_destroy (outgoingCommand -> packet); - outgoingCommand -> sentTime = host -> serviceTime; + enet_list_remove (& outgoingCommand -> outgoingCommandList); + enet_free (outgoingCommand); + + if (currentCommand == enet_list_end (& peer -> outgoingCommands)) + break; + + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber || + outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber) + break; + + currentCommand = enet_list_next (currentCommand); + } + + continue; + } + } + + enet_list_remove (& outgoingCommand -> outgoingCommandList); + + if (outgoingCommand -> packet != NULL) + enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); + } buffer -> data = command; buffer -> dataLength = commandSize; host -> packetSize += buffer -> dataLength; - host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; * command = outgoingCommand -> command; @@ -1504,9 +1541,10 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) buffer -> dataLength = outgoingCommand -> fragmentLength; host -> packetSize += outgoingCommand -> fragmentLength; - - peer -> reliableDataInTransit += outgoingCommand -> fragmentLength; } + else + if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)) + enet_free (outgoingCommand); ++ peer -> packetsSent; @@ -1517,6 +1555,12 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) host -> commandCount = command - host -> commands; host -> bufferCount = buffer - host -> buffers; + if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && + enet_list_empty (& peer -> outgoingCommands) && + enet_list_empty (& peer -> sentReliableCommands) && + enet_list_empty (& peer -> sentUnreliableCommands)) + enet_peer_disconnect (peer, peer -> eventData); + return canPing; } @@ -1553,20 +1597,22 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch ! enet_list_empty (& currentPeer -> sentReliableCommands) && ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) && enet_protocol_check_timeouts (host, currentPeer, event) == 1) - return 1; + { + if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE) + return 1; + else + continue; + } - if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) || - enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) && + if ((enet_list_empty (& currentPeer -> outgoingCommands) || + enet_protocol_check_outgoing_commands (host, currentPeer)) && enet_list_empty (& currentPeer -> sentReliableCommands) && - ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL && + ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval && currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) { enet_peer_ping (currentPeer); - enet_protocol_send_reliable_outgoing_commands (host, currentPeer); + enet_protocol_check_outgoing_commands (host, currentPeer); } - - if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands)) - enet_protocol_send_unreliable_outgoing_commands (host, currentPeer); if (host -> commandCount == 0) continue; @@ -1580,26 +1626,11 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; #ifdef ENET_DEBUG -#ifdef WIN32 - printf ( -#else - fprintf (stderr, -#endif - "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); + printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); #endif - - currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4; - if (packetLoss >= currentPeer -> packetLoss) - { - currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8; - currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4; - } - else - { - currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8; - currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4; - } + currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4; + currentPeer -> packetLoss = (currentPeer -> packetLoss * 7 + packetLoss) / 8; currentPeer -> packetLossEpoch = host -> serviceTime; currentPeer -> packetsSent = 0; @@ -1630,12 +1661,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED; shouldCompress = compressedSize; #ifdef ENET_DEBUG_COMPRESS -#ifdef WIN32 - printf ( -#else - fprintf (stderr, -#endif - "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); + printf ("peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); #endif } } @@ -1739,7 +1765,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error dispatching incoming packets"); +#endif return -1; @@ -1763,7 +1791,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error sending outgoing packets"); +#endif return -1; @@ -1777,7 +1807,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error receiving incoming packets"); +#endif return -1; @@ -1791,7 +1823,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error sending outgoing packets"); +#endif return -1; @@ -1807,7 +1841,9 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) return 1; case -1: +#ifdef ENET_DEBUG perror ("Error dispatching incoming packets"); +#endif return -1; @@ -1816,18 +1852,25 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout) } } - host -> serviceTime = enet_time_get (); - if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout)) return 0; - waitCondition = ENET_SOCKET_WAIT_RECEIVE; + do + { + host -> serviceTime = enet_time_get (); + + if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout)) + return 0; + + waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT; + + if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0) + return -1; + } + while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT); - if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0) - return -1; - host -> serviceTime = enet_time_get (); - } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE); + } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE); return 0; } diff --git a/Sources/ENet/unix.c b/Sources/ENet/unix.c index 4277d7d19..d4ddc8cae 100644 --- a/Sources/ENet/unix.c +++ b/Sources/ENet/unix.c @@ -2,13 +2,13 @@ @file unix.c @brief ENet Unix system specific functions */ -#ifndef WIN32 +#ifndef _WIN32 #include #include #include #include -#include +#include #include #include #include @@ -18,19 +18,42 @@ #define ENET_BUILDING_LIB 1 #include "enet/enet.h" -#ifdef HAS_FCNTL -#include -#endif - #ifdef __APPLE__ +#ifdef HAS_POLL #undef HAS_POLL #endif +#ifndef HAS_FCNTL +#define HAS_FCNTL 1 +#endif +#ifndef HAS_INET_PTON +#define HAS_INET_PTON 1 +#endif +#ifndef HAS_INET_NTOP +#define HAS_INET_NTOP 1 +#endif +#ifndef HAS_MSGHDR_FLAGS +#define HAS_MSGHDR_FLAGS 1 +#endif +#ifndef HAS_SOCKLEN_T +#define HAS_SOCKLEN_T 1 +#endif +#ifndef HAS_GETADDRINFO +#define HAS_GETADDRINFO 1 +#endif +#ifndef HAS_GETNAMEINFO +#define HAS_GETNAMEINFO 1 +#endif +#endif + +#ifdef HAS_FCNTL +#include +#endif #ifdef HAS_POLL -#include +#include #endif -#ifndef HAS_SOCKLEN_T +#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined) typedef int socklen_t; #endif @@ -51,6 +74,12 @@ enet_deinitialize (void) { } +enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) time (NULL); +} + enet_uint32 enet_time_get (void) { @@ -71,16 +100,55 @@ enet_time_set (enet_uint32 newTimeBase) timeBase = (enet_uint32) (timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase); } +int +enet_address_set_host_ip (ENetAddress * address, const char * name) +{ +#ifdef HAS_INET_PTON + if (! inet_pton (AF_INET, name, & address -> host)) +#else + if (! inet_aton (name, (struct in_addr *) & address -> host)) +#endif + return -1; + + return 0; +} + int enet_address_set_host (ENetAddress * address, const char * name) { +#ifdef HAS_GETADDRINFO + struct addrinfo hints, * resultList = NULL, * result = NULL; + + memset (& hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; + + if (getaddrinfo (name, NULL, NULL, & resultList) != 0) + return -1; + + for (result = resultList; result != NULL; result = result -> ai_next) + { + if (result -> ai_family == AF_INET && result -> ai_addr != NULL && result -> ai_addrlen >= sizeof (struct sockaddr_in)) + { + struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr; + + address -> host = sin -> sin_addr.s_addr; + + freeaddrinfo (resultList); + + return 0; + } + } + + if (resultList != NULL) + freeaddrinfo (resultList); +#else struct hostent * hostEntry = NULL; #ifdef HAS_GETHOSTBYNAME_R struct hostent hostData; char buffer [2048]; int errnum; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum); @@ -89,21 +157,15 @@ enet_address_set_host (ENetAddress * address, const char * name) hostEntry = gethostbyname (name); #endif - if (hostEntry == NULL || - hostEntry -> h_addrtype != AF_INET) + if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET) { -#ifdef HAS_INET_PTON - if (! inet_pton (AF_INET, name, & address -> host)) -#else - if (! inet_aton (name, (struct in_addr *) & address -> host)) -#endif - return -1; + address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; + return 0; } +#endif - address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; - - return 0; + return enet_address_set_host_ip (address, name); } int @@ -114,7 +176,12 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL #else char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr != NULL) - strncpy (name, addr, nameLength); + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } else #endif return -1; @@ -124,6 +191,26 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL int enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) { +#ifdef HAS_GETNAMEINFO + struct sockaddr_in sin; + int err; + + memset (& sin, 0, sizeof (struct sockaddr_in)); + + sin.sin_family = AF_INET; + sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); + sin.sin_addr.s_addr = address -> host; + + err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD); + if (! err) + { + if (name != NULL && nameLength > 0 && ! memchr (name, '\0', nameLength)) + return -1; + return 0; + } + if (err != EAI_NONAME) + return -1; +#else struct in_addr in; struct hostent * hostEntry = NULL; #ifdef HAS_GETHOSTBYADDR_R @@ -133,7 +220,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng in.s_addr = address -> host; -#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum); #else hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum); @@ -144,12 +231,17 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); #endif - if (hostEntry == NULL) - return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + if (hostEntry != NULL) + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + return 0; + } +#endif - return 0; + return enet_address_get_host_ip (address, name, nameLength); } int @@ -177,6 +269,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) sizeof (struct sockaddr_in)); } +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + socklen_t sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + int enet_socket_listen (ENetSocket socket, int backlog) { @@ -197,7 +304,7 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) { case ENET_SOCKOPT_NONBLOCK: #ifdef HAS_FCNTL - result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL)); + result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK)); #else result = ioctl (socket, FIONBIO, & value); #endif @@ -219,6 +326,46 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_SNDTIMEO: + { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval)); + break; + } + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == -1 ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = -1; + socklen_t len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof (int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len); + break; + default: break; } @@ -229,6 +376,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -236,7 +384,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == -1 && errno == EINPROGRESS) + return 0; + + return result; } ENetSocket @@ -262,10 +414,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how); +} + void enet_socket_destroy (ENetSocket socket) { - close (socket); + if (socket != -1) + close (socket); } int @@ -383,7 +542,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou pollCount = poll (& pollSocket, 1, timeout); if (pollCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; @@ -417,7 +585,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); if (selectCount < 0) - return -1; + { + if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT) + { + * condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } * condition = ENET_SOCKET_WAIT_NONE; diff --git a/Sources/ENet/win32.c b/Sources/ENet/win32.c index e1fae2330..eebdb0335 100644 --- a/Sources/ENet/win32.c +++ b/Sources/ENet/win32.c @@ -2,11 +2,12 @@ @file win32.c @brief ENet Win32 system specific functions */ -#ifdef WIN32 +#ifdef _WIN32 -#include #define ENET_BUILDING_LIB 1 #include "enet/enet.h" +#include +#include static enet_uint32 timeBase = 0; @@ -40,6 +41,12 @@ enet_deinitialize (void) WSACleanup (); } +enet_uint32 +enet_host_random_seed (void) +{ + return (enet_uint32) timeGetTime (); +} + enet_uint32 enet_time_get (void) { @@ -52,6 +59,32 @@ enet_time_set (enet_uint32 newTimeBase) timeBase = (enet_uint32) timeGetTime () - newTimeBase; } +int +enet_address_set_host_ip (ENetAddress * address, const char * name) +{ + enet_uint8 vals [4] = { 0, 0, 0, 0 }; + int i; + + for (i = 0; i < 4; ++ i) + { + const char * next = name + 1; + if (* name != '0') + { + long val = strtol (name, (char **) & next, 10); + if (val < 0 || val > 255 || next == name || next - name > 3) + return -1; + vals [i] = (enet_uint8) val; + } + + if (* next != (i < 3 ? '.' : '\0')) + return -1; + name = next + 1; + } + + memcpy (& address -> host, vals, sizeof (enet_uint32)); + return 0; +} + int enet_address_set_host (ENetAddress * address, const char * name) { @@ -60,13 +93,7 @@ enet_address_set_host (ENetAddress * address, const char * name) hostEntry = gethostbyname (name); if (hostEntry == NULL || hostEntry -> h_addrtype != AF_INET) - { - unsigned long host = inet_addr (name); - if (host == INADDR_NONE) - return -1; - address -> host = host; - return 0; - } + return enet_address_set_host_ip (address, name); address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; @@ -79,7 +106,13 @@ enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameL char * addr = inet_ntoa (* (struct in_addr *) & address -> host); if (addr == NULL) return -1; - strncpy (name, addr, nameLength); + else + { + size_t addrLen = strlen(addr); + if (addrLen >= nameLength) + return -1; + memcpy (name, addr, addrLen + 1); + } return 0; } @@ -88,14 +121,19 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng { struct in_addr in; struct hostent * hostEntry; - + in.s_addr = address -> host; hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); if (hostEntry == NULL) return enet_address_get_host_ip (address, name, nameLength); - - strncpy (name, hostEntry -> h_name, nameLength); + else + { + size_t hostLen = strlen (hostEntry -> h_name); + if (hostLen >= nameLength) + return -1; + memcpy (name, hostEntry -> h_name, hostLen + 1); + } return 0; } @@ -125,6 +163,21 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address) sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; } +int +enet_socket_get_address (ENetSocket socket, ENetAddress * address) +{ + struct sockaddr_in sin; + int sinLength = sizeof (struct sockaddr_in); + + if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1) + return -1; + + address -> host = (enet_uint32) sin.sin_addr.s_addr; + address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + + return 0; +} + int enet_socket_listen (ENetSocket socket, int backlog) { @@ -166,6 +219,35 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int)); break; + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int)); + break; + + case ENET_SOCKOPT_NODELAY: + result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int)); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; +} + +int +enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value) +{ + int result = SOCKET_ERROR, len; + switch (option) + { + case ENET_SOCKOPT_ERROR: + len = sizeof(int); + result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len); + break; + default: break; } @@ -176,6 +258,7 @@ int enet_socket_connect (ENetSocket socket, const ENetAddress * address) { struct sockaddr_in sin; + int result; memset (& sin, 0, sizeof (struct sockaddr_in)); @@ -183,7 +266,11 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address) sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); sin.sin_addr.s_addr = address -> host; - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; + result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)); + if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK) + return -1; + + return 0; } ENetSocket @@ -209,10 +296,17 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) return result; } +int +enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) +{ + return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0; +} + void enet_socket_destroy (ENetSocket socket) { - closesocket (socket); + if (socket != INVALID_SOCKET) + closesocket (socket); } int @@ -222,7 +316,7 @@ enet_socket_send (ENetSocket socket, size_t bufferCount) { struct sockaddr_in sin; - DWORD sentLength; + DWORD sentLength = 0; if (address != NULL) { @@ -238,7 +332,7 @@ enet_socket_send (ENetSocket socket, (DWORD) bufferCount, & sentLength, 0, - address != NULL ? (struct sockaddr *) & sin : 0, + address != NULL ? (struct sockaddr *) & sin : NULL, address != NULL ? sizeof (struct sockaddr_in) : 0, NULL, NULL) == SOCKET_ERROR) @@ -260,7 +354,7 @@ enet_socket_receive (ENetSocket socket, { INT sinLength = sizeof (struct sockaddr_in); DWORD flags = 0, - recvLength; + recvLength = 0; struct sockaddr_in sin; if (WSARecvFrom (socket, diff --git a/Sources/Externals/include/ignore b/Sources/Externals/include/ignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/Sources/Externals/lib/ignore b/Sources/Externals/lib/ignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/Sources/Externals/readme.txt b/Sources/Externals/readme.txt deleted file mode 100644 index 844f757a2..000000000 --- a/Sources/Externals/readme.txt +++ /dev/null @@ -1,72 +0,0 @@ - -When building on Windows or macOS, external dependencies should be placed in this folder. - - -## For Windows users: - -C++ headers go in the 'include' folder, as shown in the file tree below. -Libraries go in the 'lib' folder, without any subfolders. - -This should be the resulting directory structure: - -Externals -| readme.txt (this file) -| -+---include/ -| +---zconf.h -| +---zlib.h -| +---ft2build.h -| | -| +---curl/ -| | \---(All curl headers) -| | -| +---GL/ -| | \---(All GL headers) -| | -| +---freetype/ -| | \---(All FreeType 2.7 headers) -| | -| +---opus/ -| | \---(All libopus/libopusfile/libogg headers) -| | -| \---SDL2/ -| \---(All SDL2 headers) -| -\---lib/ - (All libs here) - -You may not need to hunt and compile the headers and libraries all by yourself: - * There are pre-compiled zip files containing all required files for some versions of Visual Studio - * They're already packed in the correct layout. You just need to merge. - -Visual Studio 2015: -https://openspadesmedia.yvt.jp/development-packages/OpenSpades-Externals-Windows-VS2015-3.zip - -Visual Studio 2010 (FreeType, libopus and libopusfile is missing): -https://dl.dropboxusercontent.com/u/37804131/OpenSpades-Externals-Windows.zip - - -## For macOS users: - -C++ headers go in the 'include' folder, as shown in the file tree below. -Libraries and frameworks go in the 'lib' folder, without any subfolders. - -Externals -| readme.txt (this file) -| -+---include/ -| +---ft2build.h -| +---opusfile.h -| | -| +---ogg/ -| | \---(All libogg headers) -| | -| \---freetype/ -| \---(All FreeType 2.7 headers) -| -\---lib/ - (All libs here) - -The following URL provides a pre-compiled zip file containing all required files. - -https://openspadesmedia.yvt.jp/development-packages/OpenSpades-Externals-Darwin-5.zip diff --git a/Sources/Gui/ConfigConsoleResponder.cpp b/Sources/Gui/ConfigConsoleResponder.cpp index 428221d95..4112680a1 100644 --- a/Sources/Gui/ConfigConsoleResponder.cpp +++ b/Sources/Gui/ConfigConsoleResponder.cpp @@ -115,7 +115,7 @@ namespace spades { Handle ConfigConsoleResponder::AutocompleteCommandName(const std::string &name) { - return {new ConfigNameIterator(name), false}; + return Handle::New(name).Cast(); } } // namespace gui } // namespace spades diff --git a/Sources/Gui/ConsoleCommandCandidate.cpp b/Sources/Gui/ConsoleCommandCandidate.cpp index 5ab4ae5bb..bc600b7ff 100644 --- a/Sources/Gui/ConsoleCommandCandidate.cpp +++ b/Sources/Gui/ConsoleCommandCandidate.cpp @@ -84,7 +84,8 @@ namespace spades { Handle second) { SPADES_MARK_FUNCTION(); - return {new MergeConsoleCommandCandidates{std::move(first), std::move(second)}, false}; + return Handle::New(std::move(first), std::move(second)) + .Cast(); } namespace { @@ -135,7 +136,7 @@ namespace spades { Handle MakeCandidates(const std::map &items, const std::string &query) { - return {new MapIterator{items, query}, false}; + return Handle::New(items, query).Cast(); } } // namespace gui } // namespace spades diff --git a/Sources/Gui/ConsoleScreen.cpp b/Sources/Gui/ConsoleScreen.cpp index f2ef51a96..8070c4695 100644 --- a/Sources/Gui/ConsoleScreen.cpp +++ b/Sources/Gui/ConsoleScreen.cpp @@ -35,7 +35,7 @@ namespace spades { : renderer{renderer}, audioDevice{audioDevice}, subview{subview} { SPADES_MARK_FUNCTION(); - helper.Set(new ConsoleHelper(this), true); + helper = Handle::New(this); ScopedPrivilegeEscalation privilege; static ScriptFunction uiFactory("ConsoleUI@ CreateConsoleUI(Renderer@, " diff --git a/Sources/Gui/Main.cpp b/Sources/Gui/Main.cpp index f4a474ea8..4e8df93b5 100644 --- a/Sources/Gui/Main.cpp +++ b/Sources/Gui/Main.cpp @@ -22,7 +22,7 @@ #include #include -#if !defined(__APPLE__) && (__unix || __unix__) +#if (!defined(__APPLE__) && (__unix || __unix__)) || defined(__HAIKU__) #include #include #endif @@ -190,11 +190,12 @@ namespace { binaryName); } + std::regex const hostNameRegex{"aos://.*"}; + std::regex const v075Regex{"(?:v=)?0?\\.?75"}; + std::regex const v076Regex{"(?:v=)?0?\\.?76"}; + int handleCommandLineArgument(int argc, char **argv, int &i) { if (char *a = argv[i]) { - static std::regex hostNameRegex{"aos://.*"}; - static std::regex v075Regex{"(?:v=)?0?\\.?75"}; - static std::regex v076Regex{"(?:v=)?0?\\.?76"}; if (std::regex_match(a, hostNameRegex)) { g_autoconnect = true; @@ -233,9 +234,10 @@ namespace spades { protected: spades::gui::View *CreateView(spades::client::IRenderer *renderer, spades::client::IAudioDevice *audio) override { - Handle fontManager(new client::FontManager(renderer), false); - Handle innerView{new spades::client::Client(renderer, audio, addr, fontManager), false}; - return new spades::gui::ConsoleScreen(renderer, audio, fontManager, std::move(innerView)); + auto fontManager = Handle::New(renderer); + auto innerView = Handle::New(renderer, audio, addr, fontManager); + return new spades::gui::ConsoleScreen(renderer, audio, fontManager, + std::move(innerView).Cast()); } public: @@ -249,9 +251,10 @@ namespace spades { protected: spades::gui::View *CreateView(spades::client::IRenderer *renderer, spades::client::IAudioDevice *audio) override { - Handle fontManager(new client::FontManager(renderer), false); - Handle innerView{new spades::gui::MainScreen(renderer, audio, fontManager), false}; - return new spades::gui::ConsoleScreen(renderer, audio, fontManager, std::move(innerView)); + auto fontManager = Handle::New(renderer); + auto innerView = Handle::New(renderer, audio, fontManager); + return new spades::gui::ConsoleScreen(renderer, audio, fontManager, + std::move(innerView).Cast()); } public: @@ -285,6 +288,27 @@ static std::string Utf8FromWString(const wchar_t *ws) { } #endif +#ifndef WIN32 +/** + * A wrapper of `SDL_GetPrefPath` returning a `std::string`. + * + * See [the documentation of `SDL_GetPrefPath`][1] for the usage. The returned + * path is terminated by a platform-specific path separator. + * + * [1]: https://wiki.libsdl.org/SDL_GetPrefPath + */ +static std::string GetSDLPrefPath(const char *applicationName) { + char *path = SDL_GetPrefPath(nullptr, applicationName); + if (!path) { + SPRaise("SDL_GetPrefPath failed"); + } + std::string path2 = path; + SDL_free(path); + return path2; + +} +#endif + int main(int argc, char **argv) { #ifdef WIN32 SetUnhandledExceptionFilter(UnhandledExceptionProc); @@ -384,8 +408,7 @@ int main(int argc, char **argv) { } } - spades::g_userResourceDirectory = - home + "/Library/Application Support/OpenSpades/Resources"; + spades::g_userResourceDirectory = GetSDLPrefPath("OpenSpades") + "Resources"; spades::FileManager::AddFileSystem( new spades::DirectoryFileSystem(spades::g_userResourceDirectory, true)); @@ -397,25 +420,30 @@ int main(int argc, char **argv) { spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem( CMAKE_INSTALL_PREFIX "/" OPENSPADES_INSTALL_RESOURCES, false)); - std::string xdg_data_home = home + "/.local/share"; + std::string userDataDirectory = GetSDLPrefPath("openspades"); if (getenv("XDG_DATA_HOME") == NULL) { - SPLog("XDG_DATA_HOME not defined. Assuming that XDG_DATA_HOME is ~/.local/share"); + SPLog("XDG_DATA_HOME is not provided. Using the SDL 'pref dir' as " + "the user data directory: '%s'", + userDataDirectory.c_str()); } else { - std::string xdg_data_home = getenv("XDG_DATA_HOME"); - SPLog("XDG_DATA_HOME is %s", xdg_data_home.c_str()); + userDataDirectory = getenv("XDG_DATA_HOME"); + userDataDirectory += "/openspades/"; + SPLog("The user data directory is '%s' (determined based on $XDG_DATA_HOME)", + userDataDirectory.c_str()); } struct stat info; - if (stat((xdg_data_home + "/openspades").c_str(), &info) != 0) { + if (stat(userDataDirectory.c_str(), &info) != 0) { + // TODO: Remove this very old migration code if (stat((home + "/.openspades").c_str(), &info) != 0) { } else if (info.st_mode & S_IFDIR) { SPLog("Openspades directory in XDG_DATA_HOME not found, though old directory " "exists. Trying to resolve compatibility problem."); if (rename((home + "/.openspades").c_str(), - (xdg_data_home + "/openspades").c_str()) != 0) { + (userDataDirectory + "/openspades").c_str()) != 0) { SPLog("Failed to move old directory to new."); } else { SPLog("Successfully moved old directory."); @@ -425,7 +453,8 @@ int main(int argc, char **argv) { SDL_RWops *io = SDL_RWFromFile( (home + "/.openspades/CONTENT_MOVED_TO_NEW_DIR").c_str(), "wb"); if (io != NULL) { - std::string text = ("Content of this directory moved to " + xdg_data_home + "/openspades"); + std::string text = ("Content of this directory moved to " + + userDataDirectory + "/openspades"); io->write(io, text.c_str(), text.length(), 1); io->close(io); } @@ -434,7 +463,7 @@ int main(int argc, char **argv) { } } - spades::g_userResourceDirectory = xdg_data_home + "/openspades/Resources"; + spades::g_userResourceDirectory = userDataDirectory + "Resources"; spades::FileManager::AddFileSystem( new spades::DirectoryFileSystem(spades::g_userResourceDirectory, true)); @@ -549,12 +578,12 @@ int main(int argc, char **argv) { } if (spades::FileManager::FileExists(name.c_str())) { - spades::IStream *stream = spades::FileManager::OpenForReading(name.c_str()); - uLong crc = computeCrc32ForStream(stream); + auto stream = spades::FileManager::OpenForReading(name.c_str()); + uLong crc = computeCrc32ForStream(stream.get()); stream->SetPosition(0); - spades::ZipFileSystem *fs = new spades::ZipFileSystem(stream); + spades::ZipFileSystem *fs = new spades::ZipFileSystem(stream.release()); if (name[0] == '_' && false) { // last resort for #198 SPLog("Pak registered: %s: %08lx (marked as 'important')", name.c_str(), static_cast(crc)); @@ -601,9 +630,14 @@ int main(int argc, char **argv) { } pumpEvents(); + // make sure the user sees the "pre-release version" text + bool forceStartupWindow = + spades::PackageUpdateManager::GetInstance().GetCurrentVersionInfo().build < 4; + // everything is now ready! if (!g_autoconnect) { - if (!((int)cl_showStartupWindow != 0 || splashWindow->IsStartupScreenRequested())) { + if (!((int)cl_showStartupWindow != 0 || splashWindow->IsStartupScreenRequested() || + forceStartupWindow)) { splashWindow.reset(); SPLog("Starting main screen"); diff --git a/Sources/Gui/MainScreen.cpp b/Sources/Gui/MainScreen.cpp index f2d5cff92..fa396473f 100644 --- a/Sources/Gui/MainScreen.cpp +++ b/Sources/Gui/MainScreen.cpp @@ -29,14 +29,22 @@ namespace spades { namespace gui { - MainScreen::MainScreen(client::IRenderer *r, client::IAudioDevice *a, - client::FontManager *fontManager) - : renderer(r), audioDevice(a), fontManager(fontManager) { + MainScreen::MainScreen(Handle _renderer, + Handle _audioDevice, + Handle _fontManager) + : renderer(std::move(_renderer)), + audioDevice(std::move(_audioDevice)), + fontManager(std::move(_fontManager)) { SPADES_MARK_FUNCTION(); - if (r == NULL) - SPInvalidArgument("r"); - if (a == NULL) - SPInvalidArgument("a"); + if (!renderer) { + SPInvalidArgument("renderer"); + } + if (!audioDevice) { + SPInvalidArgument("audioDevice"); + } + if (!fontManager) { + SPInvalidArgument("fontManager"); + } helper = new MainScreenHelper(this); @@ -218,11 +226,11 @@ namespace spades { renderer->DrawImage(img, AABB2(0, 0, scrSize.x, scrSize.y)); std::string str = _Tr("MainScreen", "NOW LOADING"); - client::IFont *font = fontManager->GetGuiFont(); - Vector2 size = font->Measure(str); + client::IFont &font = fontManager->GetGuiFont(); + Vector2 size = font.Measure(str); Vector2 pos = MakeVector2(scrSize.x - 16.f, scrSize.y - 16.f); pos -= size; - font->DrawShadow(str, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.5)); + font.DrawShadow(str, pos, 1.f, MakeVector4(1, 1, 1, 1), MakeVector4(0, 0, 0, 0.5)); renderer->FrameDone(); renderer->Flip(); @@ -304,9 +312,9 @@ namespace spades { "AudioDevice@, FontManager@, MainScreenHelper@)"); { ScriptContextHandle ctx = uiFactory.Prepare(); - ctx->SetArgObject(0, renderer); - ctx->SetArgObject(1, audioDevice); - ctx->SetArgObject(2, fontManager); + ctx->SetArgObject(0, renderer.GetPointerOrNull()); + ctx->SetArgObject(1, audioDevice.GetPointerOrNull()); + ctx->SetArgObject(2, fontManager.GetPointerOrNull()); ctx->SetArgObject(3, &*helper); ctx.ExecuteChecked(); @@ -350,8 +358,8 @@ namespace spades { std::string MainScreen::Connect(const ServerAddress &host) { try { - subview.Set(new client::Client(&*renderer, &*audioDevice, host, fontManager), - false); + subview = Handle::New(&*renderer, &*audioDevice, host, fontManager) + .Cast(); } catch (const std::exception &ex) { SPLog("[!] Error while initializing a game client: %s", ex.what()); return ex.what(); diff --git a/Sources/Gui/MainScreen.h b/Sources/Gui/MainScreen.h index 04544aa6b..f1b5c20ea 100644 --- a/Sources/Gui/MainScreen.h +++ b/Sources/Gui/MainScreen.h @@ -55,7 +55,8 @@ namespace spades { ~MainScreen(); public: - MainScreen(client::IRenderer *, client::IAudioDevice *, client::FontManager *); + MainScreen(Handle, Handle, + Handle); client::IRenderer *GetRenderer() { return &*renderer; } client::IAudioDevice *GetAudioDevice() { return &*audioDevice; } diff --git a/Sources/Gui/MainScreenHelper.cpp b/Sources/Gui/MainScreenHelper.cpp index 6530aba1f..3e565afd5 100644 --- a/Sources/Gui/MainScreenHelper.cpp +++ b/Sources/Gui/MainScreenHelper.cpp @@ -43,7 +43,7 @@ namespace spades { struct CURLEasyDeleter { void operator()(CURL *ptr) const { curl_easy_cleanup(ptr); } }; - } + } // namespace class ServerItem { // NetClient::Connect @@ -119,7 +119,7 @@ namespace spades { void ProcessResponse() { Json::Reader reader; Json::Value root; - std::unique_ptr resp{new MainScreenServerList()}; + auto resp = stmp::make_unique(); if (reader.parse(buffer, root, false)) { for (Json::Value::iterator it = root.begin(); it != root.end(); ++it) { @@ -144,8 +144,9 @@ namespace spades { try { std::unique_ptr cHandle{curl_easy_init()}; if (cHandle) { - size_t (*curlWriteCallback)(void *, size_t, size_t, ServerListQuery *) = []( - void *ptr, size_t size, size_t nmemb, ServerListQuery *self) -> size_t { + size_t (*curlWriteCallback)(void *, size_t, size_t, ServerListQuery *) = + [](void *ptr, size_t size, size_t nmemb, + ServerListQuery *self) -> size_t { size_t numBytes = size * nmemb; self->buffer.append(reinterpret_cast(ptr), numBytes); return numBytes; @@ -154,20 +155,24 @@ namespace spades { curl_easy_setopt(cHandle.get(), CURLOPT_URL, cl_serverListUrl.CString()); curl_easy_setopt(cHandle.get(), CURLOPT_WRITEFUNCTION, curlWriteCallback); curl_easy_setopt(cHandle.get(), CURLOPT_WRITEDATA, this); - if (0 == curl_easy_perform(cHandle.get())) { + curl_easy_setopt(cHandle.get(), CURLOPT_LOW_SPEED_TIME, 30l); + curl_easy_setopt(cHandle.get(), CURLOPT_LOW_SPEED_LIMIT, 15l); + curl_easy_setopt(cHandle.get(), CURLOPT_CONNECTTIMEOUT, 30l); + auto reqret = curl_easy_perform(cHandle.get()); + if (CURLE_OK == reqret) { ProcessResponse(); } else { - SPRaise("HTTP request error."); + SPRaise("HTTP request error (%s).", curl_easy_strerror(reqret)); } } else { SPRaise("Failed to create cURL object."); } } catch (std::exception &ex) { - std::unique_ptr lst{new MainScreenServerList()}; + auto lst = stmp::make_unique(); lst->message = ex.what(); ReturnResult(std::move(lst)); } catch (...) { - std::unique_ptr lst{new MainScreenServerList()}; + auto lst = stmp::make_unique(); lst->message = "Unknown error."; ReturnResult(std::move(lst)); } @@ -213,7 +218,7 @@ namespace spades { Json::StyledWriter writer; Json::Value v(Json::ValueType::arrayValue); - IStream *fobj = spades::FileManager::OpenForWriting(FAVORITE_PATH); + auto fobj = spades::FileManager::OpenForWriting(FAVORITE_PATH); for (const auto &favorite : favorites) { v.append(Json::Value(favorite)); } @@ -230,9 +235,10 @@ namespace spades { } if (result && !result->list.empty()) { - auto entry = std::find_if( - result->list.begin(), result->list.end(), - [&](MainScreenServerItem *entry) { return entry->GetAddress() == ip; }); + auto entry = std::find_if(result->list.begin(), result->list.end(), + [&](const Handle &entry) { + return entry->GetAddress() == ip; + }); if (entry != result->list.end()) { (*entry)->SetFavorite(favorite); } @@ -409,5 +415,5 @@ namespace spades { } MainScreenServerItem::~MainScreenServerItem() { SPADES_MARK_FUNCTION(); } - } -} + } // namespace gui +} // namespace spades diff --git a/Sources/Gui/PackageUpdateManager.cpp b/Sources/Gui/PackageUpdateManager.cpp index 8a3bc3a07..a9cb3d128 100644 --- a/Sources/Gui/PackageUpdateManager.cpp +++ b/Sources/Gui/PackageUpdateManager.cpp @@ -73,7 +73,7 @@ namespace spades { return {components[0], components[1], components[2], components[3], versionText.asString()}; } - } + } // namespace class PackageUpdateManager::UpdateFeed { public: @@ -115,9 +115,7 @@ namespace spades { // Protected members of the base class is only accessible by // the current object, so... - void ReturnErrorVeneer(const std::string &reason) { - ReturnError(reason); - } + void ReturnErrorVeneer(const std::string &reason) { ReturnError(reason); } class RequestThread : public Thread { public: @@ -133,19 +131,34 @@ namespace spades { curl_easy_setopt( curl.get(), CURLOPT_WRITEFUNCTION, static_cast( - [](void *ptr, unsigned long size, unsigned long nmemb, void *data) -> unsigned long { + [](void *ptr, unsigned long size, unsigned long nmemb, + void *data) -> unsigned long { size_t dataSize = size * nmemb; reinterpret_cast(data)->append( reinterpret_cast(ptr), dataSize); return dataSize; - })); + })); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &responseBuffer); curl_easy_setopt(curl.get(), CURLOPT_USERAGENT, OpenSpades_VER_STR); + curl_easy_setopt(curl.get(), CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl.get(), CURLOPT_LOW_SPEED_TIME, 30l); + curl_easy_setopt(curl.get(), CURLOPT_LOW_SPEED_LIMIT, 15l); + curl_easy_setopt(curl.get(), CURLOPT_CONNECTTIMEOUT, 30l); + curl_easy_setopt( + curl.get(), CURLOPT_XFERINFOFUNCTION, + static_cast( + [](void *, curl_off_t total, curl_off_t downloaded, curl_off_t, curl_off_t) -> int { + if (total > 0) + SPLog("Downloaded %zd bytes/%zd bytes", downloaded, total); + return 0; + })); m_parent.SetupCURLRequest(curl.get()); + auto reqret = curl_easy_perform(curl.get()); - if (curl_easy_perform(curl.get())) { - m_parent.ReturnErrorVeneer("HTTP request error."); + if (reqret) { + m_parent.ReturnErrorVeneer( + Format("HTTP request error ({0}).", curl_easy_strerror(reqret))); return; } @@ -166,7 +179,7 @@ namespace spades { if (m_thread) { m_thread->Join(); } else { - m_thread.reset(new RequestThread{*this}); + m_thread = stmp::make_unique(*this); } m_thread->Start(); } @@ -341,7 +354,7 @@ namespace spades { std::string updateFeedType = jsonUpdateFeedType.asString(); if (updateFeedType == "Standard") { - m_updateFeed.reset(new StandardUpdateFeed(*this, jsonUpdateFeed)); + m_updateFeed = stmp::make_unique(*this, jsonUpdateFeed); } else { SPRaise("Failed to parse PackageInfo.json: root.UpdateFeed.Type contains an " "unrecognizable value."); @@ -411,4 +424,4 @@ namespace spades { SPLog("Update feed is not available."); } } -} +} // namespace spades diff --git a/Sources/Gui/SDLRunner.cpp b/Sources/Gui/SDLRunner.cpp index a73c98305..356808da5 100644 --- a/Sources/Gui/SDLRunner.cpp +++ b/Sources/Gui/SDLRunner.cpp @@ -24,6 +24,7 @@ #include "SDLRunner.h" +#include "Icon.h" #include "SDLGLDevice.h" #include