Compare commits

..

29 Commits

Author SHA1 Message Date
Xackery b83fafb745 Added new dependency structure support. 2018-07-05 10:11:02 -07:00
Xackery bcc42edb16 added a gitignore entry for docker/db 2018-03-23 14:50:00 -07:00
Xackery 0eba5f2990 BT changed to BodyType, revised MessageType listings 2018-03-23 14:49:40 -07:00
Xackery c70bdc6b70 Repaired bug with guild chat 2018-03-21 14:39:14 -07:00
Xackery 6a25f30441 Added lua/perl support for nats AdminMessage, added more response fields 2018-03-17 18:45:31 -07:00
Xackery 825dbc9e9a Updated nats examples 2018-03-16 18:43:14 -07:00
Xackery a5f35bf32a Added partial OP_NewZone support 2018-03-15 15:54:31 -07:00
Xackery c09ab507dd Added opcode support for aaaction, aaexpupdate, zonecompleted. 2018-03-14 13:54:08 -07:00
Xackery 483ca9996b world/nats_message now properly uses byte for serializing 2018-03-14 13:22:12 -07:00
Xackery 122f1cd02d zone/natsmanager now properly uses byte for serializing 2018-03-14 12:02:39 -07:00
Xackery e0d4f9ecd1 Added door properties, and more entitylist types 2018-03-14 11:30:58 -07:00
Xackery cb72ad4d0f Added EncodeEntity 2018-03-13 22:02:33 -07:00
Xackery 98f4e570e7 Added MessageType and SpecialMessage support 2018-03-13 17:39:44 -07:00
Xackery 6532a81b80 Massive overhaul on zone/nats_manager 2018-03-13 15:29:28 -07:00
Xackery b0f591540c fixed minor typo 2018-03-13 00:24:06 -07:00
Xackery ac07e7d578 Cleaned up zone/nats_manager logic 2018-03-12 20:44:13 -07:00
Xackery 40ef387496 Added proper support for arena in nats_manager, misc cleanup 2018-03-12 10:00:00 -07:00
Xackery c9a79af79b Removed unused dailygain 2018-03-11 22:35:21 -07:00
Xackery 1a71237dc2 Protobuf is now module cmake loaded on linux, and generates files on build 2018-03-11 22:27:37 -07:00
Xackery f990292660 Removed the custom /deploy/server cmake config 2018-03-11 14:20:50 -07:00
Xackery e72f1e855f added csharp helloworld nats example 2018-03-10 22:34:48 -08:00
Xackery 3bc9e4bc24 Added python example 2018-03-10 19:47:02 -08:00
Xackery 22aef8ad79 Changed helloworld.go to use proper import 2018-03-10 18:44:01 -08:00
Xackery bf84fcd908 Added helloworld go example, repaired SendChannelMessage in world 2018-03-10 18:37:48 -08:00
Xackery 0c5779d2de Cleaned up channel message styles 2018-03-10 14:25:43 -08:00
Xackery 2270bd267d Merge branch 'master' into nats
# Conflicts:
#	world/client.cpp
#	zone/attack.cpp
#	zone/map.cpp
#	zone/map.h
#	zone/spells.cpp
2018-03-10 13:59:48 -08:00
Xackery feec425be9 Merge branch 'master' into nats
Conflicts:
	zone/loottables.cpp
2018-02-16 15:11:21 -08:00
Xackery dd5ef6523f repaired dependency issues for protobuf 2018-02-11 13:24:03 -08:00
Xackery c69b9a95b7 Nats initial commit 2018-02-10 23:42:38 -08:00
1675 changed files with 341537 additions and 109918 deletions
-23
View File
@@ -1,23 +0,0 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8
[*.cpp]
indent_style = tab
[*.h]
indent_style = tab
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
+17 -6
View File
@@ -23,13 +23,24 @@ CMakeFiles
Makefile Makefile
cmake_install.cmake cmake_install.cmake
install_manifest.txt install_manifest.txt
[Bb]uild*/ [Bb]uild/
[Bb]uild32/
[Bb]uild64/
[Bb]uild_32/
[Bb]uild_64/
deploy/server/
x64/
x86/
log/ log/
logs/ logs/
vcpkg/
.idea/* docker/db
*cbp
submodules/* # Protobuf generated files
cmake-build-debug/ *.pb.cc
*.pb.h
protobuf/csharp/*
protobuf/go/*
protobuf/java/*
protobuf/python/*
.vscode
-18
View File
@@ -1,18 +0,0 @@
[submodule "submodules/glm"]
path = submodules/glm
url = https://github.com/g-truc/glm.git
[submodule "submodules/fmt"]
path = submodules/fmt
url = https://github.com/fmtlib/fmt.git
[submodule "submodules/libuv"]
path = submodules/libuv
url = https://github.com/libuv/libuv.git
[submodule "submodules/cereal"]
path = submodules/cereal
url = https://github.com/USCiLab/cereal.git
[submodule "submodules/websocketpp"]
path = submodules/websocketpp
url = https://github.com/zaphoyd/websocketpp.git
[submodule "submodules/recastnavigation"]
path = submodules/recastnavigation
url = https://github.com/EQEmu/recastnavigation.git
+25 -20
View File
@@ -1,27 +1,32 @@
language: cpp language: cpp
compiler: gcc compiler: gcc
dist: trusty sudo: false
addons:
before_install: apt:
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sources:
- sudo apt-get update -qq - ubuntu-toolchain-r-test
- mkdir $HOME/usr packages:
- export PATH="$HOME/usr/bin:$PATH" - gcc-4.8
- wget https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.sh - g++-4.8
- chmod +x cmake-3.11.2-Linux-x86_64.sh - libmysqlclient-dev
- ./cmake-3.11.2-Linux-x86_64.sh --prefix=$HOME/usr --exclude-subdir --skip-license - libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
install: install:
- sudo apt-get install -qq g++-7 - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 90
- sudo apt-get install libmysqlclient-dev
- sudo apt-get install libperl-dev
- sudo apt-get install libboost-dev
- sudo apt-get install liblua5.1-0-dev
- sudo apt-get install zlib1g-dev
- sudo apt-get install uuid-dev
- sudo apt-get install libssl-dev
script: script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2 - make -j2
- ./bin/tests - ./bin/tests
branches:
only:
- master
- stable
notifications:
email: false
irc:
channels: "irc.eqemulator.net#eqemucoders"
os: linux
+208 -86
View File
@@ -6,8 +6,16 @@
#EQEMU_DISABLE_SAFESEH #EQEMU_DISABLE_SAFESEH
#EQEMU_BUILD_MSVC_MP #EQEMU_BUILD_MSVC_MP
#EQEMU_DEBUG_LEVEL #EQEMU_DEBUG_LEVEL
#EQEMU_LOG_LEVEL_STATUS
#EQEMU_LOG_LEVEL_NORMAL
#EQEMU_LOG_LEVEL_ERROR
#EQEMU_LOG_LEVEL_DEBUG #EQEMU_LOG_LEVEL_DEBUG
#EQEMU_LOG_LEVEL_QUEST
#EQEMU_LOG_LEVEL_COMMANDS
#EQEMU_LOG_LEVEL_CRASH
#EQEMU_DEPOP_INVALIDATES_CACHE
#EQEMU_ENABLE_BOTS #EQEMU_ENABLE_BOTS
#EQEMU_DISABLE_LOGSYS
#EQEMU_COMMANDS_LOGGING #EQEMU_COMMANDS_LOGGING
#EQEMU_BUILD_SERVER #EQEMU_BUILD_SERVER
#EQEMU_BUILD_LOGIN #EQEMU_BUILD_LOGIN
@@ -18,13 +26,10 @@
#EQEMU_BUILD_CLIENT_FILES #EQEMU_BUILD_CLIENT_FILES
#EQEMU_USE_MAP_MMFS #EQEMU_USE_MAP_MMFS
#EQEMU_MAP_DIR #EQEMU_MAP_DIR
#EQEMU_ARCH
#EQEMU_ARCH_ALT
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) #We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones
IF(POLICY CMP0074) #Can change this if you really want but you should upgrade!
cmake_policy(SET CMP0074 NEW) CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
ENDIF()
#FindMySQL is located here so lets make it so CMake can find it #FindMySQL is located here so lets make it so CMake can find it
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
@@ -37,8 +42,6 @@ IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dependencies" "${CMAKE_PREFIX_PATH}")
#Add our various windows definitions #Add our various windows definitions
IF(MSVC OR MINGW) IF(MSVC OR MINGW)
ADD_DEFINITIONS(-D_WINDOWS) ADD_DEFINITIONS(-D_WINDOWS)
@@ -49,38 +52,103 @@ IF(MSVC OR MINGW)
ENDIF(CMAKE_CL_64) ENDIF(CMAKE_CL_64)
ENDIF(MSVC OR MINGW) ENDIF(MSVC OR MINGW)
# include dirs are universal
SET(NATS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/nats")
#Try to find protobuf automatically
FIND_PACKAGE(Protobuf QUIET)
#IF(NOT PROTOBUF_FOUND)
SET(Protobuf_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/protobuf" CACHE PATH "Root protobuf directory" FORCE)
SET(PROTOBUF_FOUND TRUE CACHE BOOL "" FORCE)
IF(MSVC)
IF(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/windows/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/windows/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/windows/x64/bin/protoc.exe" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/windows/x64/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/windows/x64/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
ELSE(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/windows/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/windows/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/windows/x86/bin/protoc.exe" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/windows/x86/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/windows/x86/lib/libprotobufd.lib" CACHE PATH "Root protobuf directory" FORCE)
ENDIF(CMAKE_CL_64)
ELSE(MSVC)
IF(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/linux/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/linux/x86/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/linux/x86/bin/protoc" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/linux/x86/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/linux/x86/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
ELSE(CMAKE_CL_64)
SET(Protobuf_INCLUDE_DIR "${Protobuf_DIR}/linux/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_SRC_ROOT_FOLDER "${Protobuf_DIR}/linux/x64/include" CACHE PATH "Include dir" FORCE)
SET(Protobuf_PROTOC_EXECUTABLE "${Protobuf_DIR}/linux/x64/bin/protoc" CACHE PATH "Executable path" FORCE)
SET(Protobuf_LIBRARY_DEBUG "${Protobuf_DIR}/linux/x64/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
SET(Protobuf_LIBRARY_RELEASE "${Protobuf_DIR}/linux/x64/lib/libprotobuf.so.16" CACHE PATH "Root protobuf directory" FORCE)
ENDIF(CMAKE_CL_64)
ENDIF()
IF(NOT Protobuf_LIBRARY_DEBUG)
MESSAGE(ERROR "Protobuf library was not found in ${Protobuf_LIBRARY_DEBUG}. Please download the depenencies and extract them as noted.")
ENDIF()
FILE(COPY ${Protobuf_LIBRARY_DEBUG} DESTINATION ${CMAKE_HOME_DIRECTORY}/bin)
#ENDIF()
INCLUDE_DIRECTORIES(SYSTEM "${Protobuf_INCLUDE_DIR}")
IF(MSVC) IF(MSVC)
IF(CMAKE_CL_64) IF(CMAKE_CL_64)
SET(EQEMU_ARCH "x64") SET(NATS_INCLUDE_DIR "${NATS_ROOT}/windows/x64/include")
SET(EQEMU_ARCH_ALT "x64") SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/windows/x64/lib/nats.lib")
ELSE(CMAKE_CL_64) ELSE(CMAKE_CL_64)
SET(EQEMU_ARCH "x86") SET(NATS_INCLUDE_DIR "${NATS_ROOT}/windows/x86/include")
SET(EQEMU_ARCH_ALT "Win32") SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/windows/x86/lib/nats.lib")
ENDIF(CMAKE_CL_64) ENDIF(CMAKE_CL_64)
ELSE(MSVC)
IF(CMAKE_CL_64)
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/linux/x86/include")
SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/linux/x86/lib/libnats.so")
ELSE(CMAKE_CL_64)
SET(NATS_INCLUDE_DIR "${NATS_ROOT}/linux/x64/include")
SET(NATS_LIBRARY_DEBUG "${NATS_ROOT}/linux/x64/lib/libnats.so")
ENDIF(CMAKE_CL_64)
ENDIF()
IF(${NATS_LIBRARY_DEBUG})
MESSAGE(ERROR " NATS library was not found in ${NATS_LIBRARY_DEBUG}/libnats.so. Please download the depenencies and extract them as noted.")
ENDIF()
FILE(COPY ${NATS_LIBRARY_DEBUG} DESTINATION ${CMAKE_HOME_DIRECTORY}/bin)
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_${EQEMU_ARCH}") IF(MSVC)
#Set our default locations for zlib/mysql based on x86/x64
IF(VCPKG_TOOLCHAIN) IF(CMAKE_CL_64)
IF(NOT MSVC_VERSION GREATER 1800) SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64")
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64")
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64")
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include") SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
ENDIF()
ELSE(VCPKG_TOOLCHAIN)
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_${EQEMU_ARCH}")
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_${EQEMU_ARCH}")
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_${EQEMU_ARCH}")
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
ENDIF(VCPKG_TOOLCHAIN)
IF(SODIUM_INCLUDE_HINTS)
IF(MSVC_VERSION GREATER 1800) IF(MSVC_VERSION GREATER 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v140/dynamic") SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic")
ELSEIF(MSVC_VERSION EQUAL 1800) ELSEIF(MSVC_VERSION EQUAL 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v120/dynamic") SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic")
ELSE() ELSE()
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v110/dynamic") SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
ENDIF() ENDIF()
ENDIF(SODIUM_INCLUDE_HINTS) ELSE(CMAKE_CL_64)
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
SET(NATS_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/nats_x86")
IF(MSVC_VERSION GREATER 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
ELSEIF(MSVC_VERSION EQUAL 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic")
ELSE()
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
ENDIF()
ENDIF(CMAKE_CL_64)
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere #disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON) OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
@@ -100,6 +168,23 @@ IF(MSVC)
ADD_DEFINITIONS(-DCRASH_LOGGING) ADD_DEFINITIONS(-DCRASH_LOGGING)
ENDIF(EQEMU_ENABLE_CRASH_LOGGING) ENDIF(EQEMU_ENABLE_CRASH_LOGGING)
#Disable safe SEH or not?
OPTION(EQEMU_DISABLE_SAFESEH "Disable Safe SEH (Needed for Strawberry Perl)" OFF)
IF(EQEMU_DISABLE_SAFESEH)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
SET(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /SAFESEH:NO")
SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "${CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
ENDIF(EQEMU_DISABLE_SAFESEH)
OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON) OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON)
IF(EQEMU_BUILD_MSVC_MP) IF(EQEMU_BUILD_MSVC_MP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
@@ -114,6 +199,8 @@ IF(MSVC)
ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DNOMINMAX)
ELSE(MSVC) ELSE(MSVC)
#Normally set by perl but we don't use the perl flags anymore so we set it. #Normally set by perl but we don't use the perl flags anymore so we set it.
ADD_DEFINITIONS(-DHAS_UNION_SEMUN) ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC) ENDIF(MSVC)
@@ -142,6 +229,36 @@ SET(EQEMU_DEBUG_LEVEL 5 CACHE STRING "EQEmu debug level:
10 - More errors than you ever wanted to see" 10 - More errors than you ever wanted to see"
) )
SET(EQEMU_LOG_LEVEL_STATUS 2 CACHE STRING "EQEmu logging level for [Status]:
0 - Disabled
1 - Ouput to File Enabled
2 - Output to stdout Enabled
3 - Output to File and stdout Enabled
8 - Output to stderr Enabled
9 - Output to File and stderr Enabled
11 - Output to File, stdout and stderr Enabled"
)
SET(EQEMU_LOG_LEVEL_NORMAL 3 CACHE STRING "EQEmu logging level for [Normal]:
0 - Disabled
1 - Ouput to File Enabled
2 - Output to stdout Enabled
3 - Output to File and stdout Enabled
8 - Output to stderr Enabled
9 - Output to File and stderr Enabled
11 - Output to File, stdout and stderr Enabled"
)
SET(EQEMU_LOG_LEVEL_ERROR 2 CACHE STRING "EQEmu logging level for [Error]:
0 - Disabled
1 - Ouput to File Enabled
2 - Output to stdout Enabled
3 - Output to File and stdout Enabled
8 - Output to stderr Enabled
9 - Output to File and stderr Enabled
11 - Output to File, stdout and stderr Enabled"
)
SET(EQEMU_LOG_LEVEL_DEBUG 3 CACHE STRING "EQEmu logging level for [Debug]: SET(EQEMU_LOG_LEVEL_DEBUG 3 CACHE STRING "EQEmu logging level for [Debug]:
0 - Disabled 0 - Disabled
1 - Ouput to File Enabled 1 - Ouput to File Enabled
@@ -152,14 +269,47 @@ SET(EQEMU_LOG_LEVEL_DEBUG 3 CACHE STRING "EQEmu logging level for [Debug]:
11 - Output to File, stdout and stderr Enabled" 11 - Output to File, stdout and stderr Enabled"
) )
OPTION(EQEMU_LSPX "" OFF) SET(EQEMU_LOG_LEVEL_QUEST 2 CACHE STRING "EQEmu logging level for [Quest]:
MARK_AS_ADVANCED(EQEMU_LSPX) 0 - Disabled
1 - Ouput to File Enabled
2 - Output to stdout Enabled
3 - Output to File and stdout Enabled
8 - Output to stderr Enabled
9 - Output to File and stderr Enabled
11 - Output to File, stdout and stderr Enabled"
)
MARK_AS_ADVANCED(EQEMU_LOG_LEVEL_DEBUG) SET(EQEMU_LOG_LEVEL_COMMANDS 1 CACHE STRING "EQEmu logging level for [Commands]:
0 - Disabled
1 - Ouput to File Enabled
2 - Output to stdout Enabled
3 - Output to File and stdout Enabled
8 - Output to stderr Enabled
9 - Output to File and stderr Enabled
11 - Output to File, stdout and stderr Enabled"
)
SET(EQEMU_LOG_LEVEL_CRASH 3 CACHE STRING "EQEmu logging level for [Crash]:
0 - Disabled
1 - Ouput to File Enabled
2 - Output to stdout Enabled
3 - Output to File and stdout Enabled
8 - Output to stderr Enabled
9 - Output to File and stderr Enabled
11 - Output to File, stdout and stderr Enabled"
)
MARK_AS_ADVANCED(EQEMU_LOG_LEVEL_STATUS EQEMU_LOG_LEVEL_NORMAL EQEMU_LOG_LEVEL_ERROR EQEMU_LOG_LEVEL_DEBUG EQEMU_LOG_LEVEL_QUEST EQEMU_LOG_LEVEL_COMMANDS EQEMU_LOG_LEVEL_CRASH)
#NPC Types Cache Behavior
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
#Bots are a compile time option so on/off #Bots are a compile time option so on/off
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF) OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
#Disable entire _mlog system (excludes trade/command logs)
OPTION(EQEMU_DISABLE_LOGSYS "Disable Logging INI System" ON)
#Enable GM Command log system #Enable GM Command log system
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON) OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
@@ -167,9 +317,9 @@ IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING) ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING) ENDIF(EQEMU_COMMANDS_LOGGING)
IF(EQEMU_LSPX) IF(EQEMU_DISABLE_LOGSYS)
ADD_DEFINITIONS(-DLSPX=ON) ADD_DEFINITIONS(-DDISABLE_LOGSYS)
ENDIF(EQEMU_LSPX) ENDIF(EQEMU_DISABLE_LOGSYS)
IF(EQEMU_ENABLE_BOTS) IF(EQEMU_ENABLE_BOTS)
ADD_DEFINITIONS(-DBOTS) ADD_DEFINITIONS(-DBOTS)
@@ -201,11 +351,10 @@ IF(EQEMU_BUILD_LUA)
ADD_DEFINITIONS(-DLUA_EQEMU) ADD_DEFINITIONS(-DLUA_EQEMU)
ENDIF(EQEMU_BUILD_LUA) ENDIF(EQEMU_BUILD_LUA)
#Disabled until reevaluation performed OPTION(EQEMU_USE_MAP_MMFS "Create and use Zone Map MMF files." OFF)
#OPTION(EQEMU_USE_MAP_MMFS "Create and use Zone Map MMF files." OFF) IF(EQEMU_USE_MAP_MMFS)
#IF(EQEMU_USE_MAP_MMFS) ADD_DEFINITIONS(-DUSE_MAP_MMFS)
# ADD_DEFINITIONS(-DUSE_MAP_MMFS) ENDIF(EQEMU_USE_MAP_MMFS)
#ENDIF(EQEMU_USE_MAP_MMFS)
SET(EQEMU_MAP_DIR "./Maps" CACHE STRING "The dir that maps, water maps, and paths are located in.") SET(EQEMU_MAP_DIR "./Maps" CACHE STRING "The dir that maps, water maps, and paths are located in.")
@@ -213,20 +362,24 @@ ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL})
ADD_DEFINITIONS(-DINVERSEXY) ADD_DEFINITIONS(-DINVERSEXY)
ADD_DEFINITIONS(-DFIELD_ITEMS) ADD_DEFINITIONS(-DFIELD_ITEMS)
ADD_DEFINITIONS(-DMAP_DIR="${EQEMU_MAP_DIR}") ADD_DEFINITIONS(-DMAP_DIR="${EQEMU_MAP_DIR}")
ADD_DEFINITIONS(-DLOG_LEVEL_STATUS=${EQEMU_LOG_LEVEL_STATUS})
ADD_DEFINITIONS(-DLOG_LEVEL_NORMAL=${EQEMU_LOG_LEVEL_NORMAL})
ADD_DEFINITIONS(-DLOG_LEVEL_ERROR=${EQEMU_LOG_LEVEL_ERROR})
ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG}) ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG})
ADD_DEFINITIONS(-DLOG_LEVEL_QUEST=${EQEMU_LOG_LEVEL_QUEST})
ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS})
ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH})
ADD_DEFINITIONS(-DGLM_FORCE_RADIANS) ADD_DEFINITIONS(-DGLM_FORCE_RADIANS)
ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT)
ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
#Find everything we need #Find everything we need
FIND_PACKAGE(ZLIB) FIND_PACKAGE(ZLIB REQUIRED)
FIND_PACKAGE(MySQL REQUIRED) FIND_PACKAGE(MySQL REQUIRED)
IF(EQEMU_BUILD_PERL) IF(EQEMU_BUILD_PERL)
FIND_PACKAGE(PerlLibs REQUIRED) FIND_PACKAGE(PerlLibs REQUIRED)
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}") INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
ENDIF(EQEMU_BUILD_PERL) ENDIF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} uv_a fmt RecastNavigation::Detour) SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt ${NATS_LIBRARY_DEBUG} ${PROTOBUF_LIBRARY_DEBUG})
FIND_PACKAGE(Sodium REQUIRED) FIND_PACKAGE(Sodium REQUIRED)
IF(SODIUM_FOUND) IF(SODIUM_FOUND)
@@ -238,23 +391,6 @@ IF(SODIUM_FOUND)
ENDIF() ENDIF()
ENDIF() ENDIF()
IF(ZLIB_FOUND)
OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF)
IF(EQEMU_BUILD_ZLIB)
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
ELSE()
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
ENDIF()
ELSE()
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
SET(EQEMU_BUILD_ZLIB ON)
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
ENDIF()
IF(WIN32) IF(WIN32)
SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv") SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv")
ENDIF() ENDIF()
@@ -276,7 +412,7 @@ IF(EQEMU_BUILD_LUA)
FIND_PACKAGE(Boost REQUIRED) FIND_PACKAGE(Boost REQUIRED)
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}") INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/luabind")
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON) OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS) IF(EQEMU_SANITIZE_LUA_LIBS)
@@ -284,34 +420,20 @@ IF(EQEMU_BUILD_LUA)
ENDIF(EQEMU_SANITIZE_LUA_LIBS) ENDIF(EQEMU_SANITIZE_LUA_LIBS)
ENDIF(EQEMU_BUILD_LUA) ENDIF(EQEMU_BUILD_LUA)
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}") INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm") INCLUDE_DIRECTORIES(SYSTEM "${NATS_INCLUDE_DIR}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common/glm")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" ) INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" )
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Detour/Include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/src")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/format")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(libs) ADD_SUBDIRECTORY(libs)
ADD_SUBDIRECTORY(submodules/fmt)
ADD_SUBDIRECTORY(submodules/libuv)
SET(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Build demo")
SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests")
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
ADD_SUBDIRECTORY(submodules/recastnavigation)
IF(EQEMU_BUILD_ZLIB)
SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API")
SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries")
ADD_SUBDIRECTORY(libs/zlibng)
ENDIF()
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
IF(EQEMU_BUILD_SERVER) IF(EQEMU_BUILD_SERVER)
ADD_SUBDIRECTORY(shared_memory) ADD_SUBDIRECTORY(shared_memory)
+157 -666
View File
@@ -1,674 +1,165 @@
GNU GENERAL PUBLIC LICENSE GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble
This version of the GNU Lesser General Public License incorporates
The GNU General Public License is a free, copyleft license for the terms and conditions of version 3 of the GNU General Public
software and other kinds of works. License, supplemented by the additional permissions listed below.
The licenses for most software and other practical works are designed 0. Additional Definitions.
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to As used herein, "this License" refers to version 3 of the GNU Lesser
share and change all versions of a program--to make sure it remains free General Public License, and the "GNU GPL" refers to version 3 of the GNU
software for all its users. We, the Free Software Foundation, use the General Public License.
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to "The Library" refers to a covered work governed by this License,
your programs, too. other than an Application or a Combined Work as defined below.
When we speak of free software, we are referring to freedom, not An "Application" is any work that makes use of an interface provided
price. Our General Public Licenses are designed to make sure that you by the Library, but which is not otherwise based on the Library.
have the freedom to distribute copies of free software (and charge for Defining a subclass of a class defined by the Library is deemed a mode
them if you wish), that you receive source code or can get it if you of using an interface provided by the Library.
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things. A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
To protect your rights, we need to prevent others from denying you with which the Combined Work was made is also called the "Linked
these rights or asking you to surrender the rights. Therefore, you have Version".
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others. The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
For example, if you distribute copies of such a program, whether for portions of the Combined Work that, considered in isolation, are
gratis or for a fee, you must pass on to the recipients the same based on the Application, and not on the Linked Version.
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they The "Corresponding Application Code" for a Combined Work means the
know their rights. object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Developers that use the GNU GPL protect your rights with two steps: Application, but excluding the System Libraries of the Combined Work.
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it. 1. Exception to Section 3 of the GNU GPL.
For the developers' and authors' protection, the GPL clearly explains You may convey a covered work under sections 3 and 4 of this License
that there is no warranty for this free software. For both users' and without being bound by section 3 of the GNU GPL.
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to 2. Conveying Modified Versions.
authors of previous versions.
If you modify a copy of the Library, and, in your modifications, a
Some devices are designed to deny users access to install or run facility refers to a function or data to be supplied by an Application
modified versions of the software inside them, although the manufacturer that uses the facility (other than as an argument passed when the
can do so. This is fundamentally incompatible with the aim of facility is invoked), then you may convey a copy of the modified
protecting users' freedom to change the software. The systematic version:
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we a) under this License, provided that you make a good faith effort to
have designed this version of the GPL to prohibit the practice for those ensure that, in the event an Application does not supply the
products. If such problems arise substantially in other domains, we function or data, the facility still operates, and performs
stand ready to extend this provision to those domains in future versions whatever part of its purpose remains meaningful, or
of the GPL, as needed to protect the freedom of users.
b) under the GNU GPL, with none of the additional permissions of
Finally, every program is threatened constantly by software patents. this License applicable to that copy.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to 3. Object Code Incorporating Material from Library Header Files.
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that The object code form of an Application may incorporate material from
patents cannot be used to render the program non-free. a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
The precise terms and conditions for copying, distribution and material is not limited to numerical parameters, data structure
modification follow. layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
TERMS AND CONDITIONS
a) Give prominent notice with each copy of the object code that the
0. Definitions. Library is used in it and that the Library and its use are
covered by this License.
"This License" refers to version 3 of the GNU General Public License.
b) Accompany the object code with a copy of the GNU GPL and this license
"Copyright" also means copyright-like laws that apply to other kinds of document.
works, such as semiconductor masks.
4. Combined Works.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and You may convey a Combined Work under terms of your choice that,
"recipients" may be individuals or organizations. taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
To "modify" a work means to copy from or adapt all or part of the work engineering for debugging such modifications, if you also do each of
in a fashion requiring copyright permission, other than the making of an the following:
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work. a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
A "covered work" means either the unmodified Program or a work based covered by this License.
on the Program.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
To "propagate" a work means to do anything with it that, without document.
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a c) For a Combined Work that displays copyright notices during
computer or modifying a private copy. Propagation includes copying, execution, include the copyright notice for the Library among
distribution (with or without modification), making available to the these notices, as well as a reference directing the user to the
public, and in some countries other activities as well. copies of the GNU GPL and this license document.
To "convey" a work means any kind of propagation that enables other d) Do one of the following:
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying. 0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
An interactive user interface displays "Appropriate Legal Notices" suitable for, and under terms that permit, the user to
to the extent that it includes a convenient and prominently visible recombine or relink the Application with a modified version of
feature that (1) displays an appropriate copyright notice, and (2) the Linked Version to produce a modified Combined Work, in the
tells the user that there is no warranty for the work (except to the manner specified by section 6 of the GNU GPL for conveying
extent that warranties are provided), that licensees may convey the Corresponding Source.
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a 1) Use a suitable shared library mechanism for linking with the
menu, a prominent item in the list meets this criterion. Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
1. Source Code. system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
The "source code" for a work means the preferred form of the work Version.
for making modifications to it. "Object code" means any non-source
form of a work. e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
A "Standard Interface" means an interface that either is an official GNU GPL, and only to the extent that such information is
standard defined by a recognized standards body, or, in the case of necessary to install and execute a modified version of the
interfaces specified for a particular programming language, one that Combined Work produced by recombining or relinking the
is widely used among developers working in that language. Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
The "System Libraries" of an executable work include anything, other the Minimal Corresponding Source and Corresponding Application
than the work as a whole, that (a) is included in the normal form of Code. If you use option 4d1, you must provide the Installation
packaging a Major Component, but which is not part of that Major Information in the manner specified by section 6 of the GNU GPL
Component, and (b) serves only to enable use of the work with that for conveying Corresponding Source.)
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A 5. Combined Libraries.
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system You may place library facilities that are a work based on the
(if any) on which the executable work runs, or a compiler used to Library side by side in a single library together with other library
produce the work, or an object code interpreter used to run it. facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
The "Corresponding Source" for a work in object code form means all choice, if you do both of the following:
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to a) Accompany the combined library with a copy of the same work based
control those activities. However, it does not include the work's on the Library, uncombined with any other library facilities,
System Libraries, or general-purpose tools or generally available free conveyed under the terms of this License.
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source b) Give prominent notice with the combined library that part of it
includes interface definition files associated with source files for is a work based on the Library, and explaining where to find the
the work, and the source code for shared libraries and dynamically accompanying uncombined form of the same work.
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those 6. Revised Versions of the GNU Lesser General Public License.
subprograms and other parts of the work.
The Free Software Foundation may publish revised and/or new versions
The Corresponding Source need not include anything that users of the GNU Lesser General Public License from time to time. Such new
can regenerate automatically from other parts of the Corresponding versions will be similar in spirit to the present version, but may
Source. differ in detail to address new problems or concerns.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General Library as you received it specifies that a certain numbered version
Public License "or any later version" applies to it, you have the of the GNU Lesser General Public License "or any later version"
option of following the terms and conditions either of that numbered applies to it, you have the option of following the terms and
version or of any later version published by the Free Software conditions either of that published version or of any later version
Foundation. If the Program does not specify a version number of the published by the Free Software Foundation. If the Library as you
GNU General Public License, you may choose any version ever published received it does not specify a version number of the GNU Lesser
by the Free Software Foundation. General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future If the Library as you received it specifies that a proxy can decide
versions of the GNU General Public License can be used, that proxy's whether future versions of the GNU Lesser General Public License shall
public statement of acceptance of a version permanently authorizes you apply, that proxy's public statement of acceptance of any version is
to choose that version for the Program. permanent authorization for you to choose that version for the
Library.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
+3 -9
View File
@@ -1,7 +1,7 @@
# EQEmulator Core Server # EQEmulator Core Server
|Travis CI (Linux)|Appveyor w/ Bots (Windows) |Appveyor w/o Bots (Windows) | |Travis CI (Linux)|Appveyor (Windows) |
|:---:|:---:|:---:| |:---:|:---:|
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp/branch/master) |[![Build status](https://ci.appveyor.com/api/projects/status/mdwbr4o9l6mxqofj/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-w0pq2/branch/master) | |[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Windows CI](https://ci.appveyor.com/api/projects/status/d0cvokm7u732v8vl/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server/branch/master) |
*** ***
@@ -70,9 +70,3 @@ forum, although pull requests will be much quicker and easier on all parties.
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project) * GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
* CPPUnit - GLP StringUtilities - Apache * CPPUnit - GLP StringUtilities - Apache
* LUA - MIT * LUA - MIT
## Contributors
<a href="https://github.com/EQEmu/server/graphs/contributors">
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
</a>
-3
View File
@@ -1,3 +0,0 @@
# Security Policy - Reporting Vulnerabilities
When reporting active hacks, exploits and other vulnerabilities, please describe how to reproduce said report and if you can provide context into a possible solution
-21
View File
@@ -1,21 +0,0 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=ON -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb
appveyor PushArtifact build_x64-bots.zip
-21
View File
@@ -1,21 +0,0 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
cache: c:\tools\vcpkg\installed\
before_build:
- ps: "$wc = New-Object System.Net.WebClient\n$wc.DownloadFile(\"http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip\", \"c:\\projects\\eqemu\\strawberry-perl-5.26.2.1-64bit-portable.zip\")\ncd c:\\projects\\eqemu\n7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y\n(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h\nvcpkg install boost-geometry:x64-windows boost-dynamic-bitset:x64-windows luajit:x64-windows libsodium:x64-windows libmysql:x64-windows openssl:x64-windows zlib:x64-windows \nmkdir build\ncd build\ncmake -G \"Visual Studio 15 2017 Win64\" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=OFF -DPERL_EXECUTABLE=\"C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe\" -DPERL_INCLUDE_PATH=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE\" -DPERL_LIBRARY=\"C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a\" -DCMAKE_TOOLCHAIN_FILE=\"c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake\" .."
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb
appveyor PushArtifact build_x64-no-bots.zip
+478 -976
View File
File diff suppressed because it is too large Load Diff
+13 -35
View File
@@ -39,19 +39,20 @@ int main(int argc, char **argv) {
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
LogInfo("Client Files Export Utility"); Log(Logs::General, Logs::Status, "Client Files Export Utility");
if(!EQEmuConfig::LoadConfig()) { if(!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file"); Log(Logs::General, Logs::Error, "Unable to load configuration file.");
return 1; return 1;
} }
auto Config = EQEmuConfig::get(); auto Config = EQEmuConfig::get();
SharedDatabase database; SharedDatabase database;
LogInfo("Connecting to database"); Log(Logs::General, Logs::Status, "Connecting to database...");
if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(),
Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) {
LogError("Unable to connect to the database, cannot continue without a database connection"); Log(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a "
"database connection");
return 1; return 1;
} }
@@ -59,29 +60,6 @@ int main(int argc, char **argv) {
database.LoadLogSettings(LogSys.log_settings); database.LoadLogSettings(LogSys.log_settings);
LogSys.StartFileLogs(); LogSys.StartFileLogs();
std::string arg_1;
if (argv[1]) {
arg_1 = argv[1];
}
if (arg_1 == "spells") {
ExportSpells(&database);
return 0;
}
if (arg_1 == "skills") {
ExportSkillCaps(&database);
return 0;
}
if (arg_1 == "basedata") {
ExportBaseData(&database);
return 0;
}
if (arg_1 == "dbstring") {
ExportDBStrings(&database);
return 0;
}
ExportSpells(&database); ExportSpells(&database);
ExportSkillCaps(&database); ExportSkillCaps(&database);
ExportBaseData(&database); ExportBaseData(&database);
@@ -93,11 +71,11 @@ int main(int argc, char **argv) {
} }
void ExportSpells(SharedDatabase *db) { void ExportSpells(SharedDatabase *db) {
LogInfo("Exporting Spells"); Log(Logs::General, Logs::Status, "Exporting Spells...");
FILE *f = fopen("export/spells_us.txt", "w"); FILE *f = fopen("export/spells_us.txt", "w");
if(!f) { if(!f) {
LogError("Unable to open export/spells_us.txt to write, skipping."); Log(Logs::General, Logs::Error, "Unable to open export/spells_us.txt to write, skipping.");
return; return;
} }
@@ -164,11 +142,11 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) {
} }
void ExportSkillCaps(SharedDatabase *db) { void ExportSkillCaps(SharedDatabase *db) {
LogInfo("Exporting Skill Caps"); Log(Logs::General, Logs::Status, "Exporting Skill Caps...");
FILE *f = fopen("export/SkillCaps.txt", "w"); FILE *f = fopen("export/SkillCaps.txt", "w");
if(!f) { if(!f) {
LogError("Unable to open export/SkillCaps.txt to write, skipping."); Log(Logs::General, Logs::Error, "Unable to open export/SkillCaps.txt to write, skipping.");
return; return;
} }
@@ -193,11 +171,11 @@ void ExportSkillCaps(SharedDatabase *db) {
} }
void ExportBaseData(SharedDatabase *db) { void ExportBaseData(SharedDatabase *db) {
LogInfo("Exporting Base Data"); Log(Logs::General, Logs::Status, "Exporting Base Data...");
FILE *f = fopen("export/BaseData.txt", "w"); FILE *f = fopen("export/BaseData.txt", "w");
if(!f) { if(!f) {
LogError("Unable to open export/BaseData.txt to write, skipping."); Log(Logs::General, Logs::Error, "Unable to open export/BaseData.txt to write, skipping.");
return; return;
} }
@@ -224,11 +202,11 @@ void ExportBaseData(SharedDatabase *db) {
} }
void ExportDBStrings(SharedDatabase *db) { void ExportDBStrings(SharedDatabase *db) {
LogInfo("Exporting DB Strings"); Log(Logs::General, Logs::Status, "Exporting DB Strings...");
FILE *f = fopen("export/dbstr_us.txt", "w"); FILE *f = fopen("export/dbstr_us.txt", "w");
if(!f) { if(!f) {
LogError("Unable to open export/dbstr_us.txt to write, skipping."); Log(Logs::General, Logs::Error, "Unable to open export/dbstr_us.txt to write, skipping.");
return; return;
} }
+14 -14
View File
@@ -37,19 +37,19 @@ int main(int argc, char **argv) {
LogSys.LoadLogSettingsDefaults(); LogSys.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
LogInfo("Client Files Import Utility"); Log(Logs::General, Logs::Status, "Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) { if(!EQEmuConfig::LoadConfig()) {
LogError("Unable to load configuration file."); Log(Logs::General, Logs::Error, "Unable to load configuration file.");
return 1; return 1;
} }
auto Config = EQEmuConfig::get(); auto Config = EQEmuConfig::get();
SharedDatabase database; SharedDatabase database;
LogInfo("Connecting to database"); Log(Logs::General, Logs::Status, "Connecting to database...");
if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(),
Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) {
LogError("Unable to connect to the database, cannot continue without a " Log(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a "
"database connection"); "database connection");
return 1; return 1;
} }
@@ -97,10 +97,10 @@ bool IsStringField(int i) {
} }
void ImportSpells(SharedDatabase *db) { void ImportSpells(SharedDatabase *db) {
LogInfo("Importing Spells"); Log(Logs::General, Logs::Status, "Importing Spells...");
FILE *f = fopen("import/spells_us.txt", "r"); FILE *f = fopen("import/spells_us.txt", "r");
if(!f) { if(!f) {
LogError("Unable to open import/spells_us.txt to read, skipping."); Log(Logs::General, Logs::Error, "Unable to open import/spells_us.txt to read, skipping.");
return; return;
} }
@@ -173,23 +173,23 @@ void ImportSpells(SharedDatabase *db) {
spells_imported++; spells_imported++;
if(spells_imported % 1000 == 0) { if(spells_imported % 1000 == 0) {
LogInfo("[{}] spells imported", spells_imported); Log(Logs::General, Logs::Status, "%d spells imported.", spells_imported);
} }
} }
if(spells_imported % 1000 != 0) { if(spells_imported % 1000 != 0) {
LogInfo("[{}] spells imported", spells_imported); Log(Logs::General, Logs::Status, "%d spells imported.", spells_imported);
} }
fclose(f); fclose(f);
} }
void ImportSkillCaps(SharedDatabase *db) { void ImportSkillCaps(SharedDatabase *db) {
LogInfo("Importing Skill Caps"); Log(Logs::General, Logs::Status, "Importing Skill Caps...");
FILE *f = fopen("import/SkillCaps.txt", "r"); FILE *f = fopen("import/SkillCaps.txt", "r");
if(!f) { if(!f) {
LogError("Unable to open import/SkillCaps.txt to read, skipping."); Log(Logs::General, Logs::Error, "Unable to open import/SkillCaps.txt to read, skipping.");
return; return;
} }
@@ -220,11 +220,11 @@ void ImportSkillCaps(SharedDatabase *db) {
} }
void ImportBaseData(SharedDatabase *db) { void ImportBaseData(SharedDatabase *db) {
LogInfo("Importing Base Data"); Log(Logs::General, Logs::Status, "Importing Base Data...");
FILE *f = fopen("import/BaseData.txt", "r"); FILE *f = fopen("import/BaseData.txt", "r");
if(!f) { if(!f) {
LogError("Unable to open import/BaseData.txt to read, skipping."); Log(Logs::General, Logs::Error, "Unable to open import/BaseData.txt to read, skipping.");
return; return;
} }
@@ -265,11 +265,11 @@ void ImportBaseData(SharedDatabase *db) {
} }
void ImportDBStrings(SharedDatabase *db) { void ImportDBStrings(SharedDatabase *db) {
LogInfo("Importing DB Strings"); Log(Logs::General, Logs::Status, "Importing DB Strings...");
FILE *f = fopen("import/dbstr_us.txt", "r"); FILE *f = fopen("import/dbstr_us.txt", "r");
if(!f) { if(!f) {
LogError("Unable to open import/dbstr_us.txt to read, skipping."); Log(Logs::General, Logs::Error, "Unable to open import/dbstr_us.txt to read, skipping.");
return; return;
} }
+386
View File
@@ -0,0 +1,386 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindPackageHandleStandardArgs
-----------------------------
This module provides a function intended to be used in :ref:`Find Modules`
implementing :command:`find_package(<PackageName>)` calls. It handles the
``REQUIRED``, ``QUIET`` and version-related arguments of ``find_package``.
It also sets the ``<PackageName>_FOUND`` variable. The package is
considered found if all variables listed contain valid results, e.g.
valid filepaths.
.. command:: find_package_handle_standard_args
There are two signatures::
find_package_handle_standard_args(<PackageName>
(DEFAULT_MSG|<custom-failure-message>)
<required-var>...
)
find_package_handle_standard_args(<PackageName>
[FOUND_VAR <result-var>]
[REQUIRED_VARS <required-var>...]
[VERSION_VAR <version-var>]
[HANDLE_COMPONENTS]
[CONFIG_MODE]
[FAIL_MESSAGE <custom-failure-message>]
)
The ``<PackageName>_FOUND`` variable will be set to ``TRUE`` if all
the variables ``<required-var>...`` are valid and any optional
constraints are satisfied, and ``FALSE`` otherwise. A success or
failure message may be displayed based on the results and on
whether the ``REQUIRED`` and/or ``QUIET`` option was given to
the :command:`find_package` call.
The options are:
``(DEFAULT_MSG|<custom-failure-message>)``
In the simple signature this specifies the failure message.
Use ``DEFAULT_MSG`` to ask for a default message to be computed
(recommended). Not valid in the full signature.
``FOUND_VAR <result-var>``
Obsolete. Specifies either ``<PackageName>_FOUND`` or
``<PACKAGENAME>_FOUND`` as the result variable. This exists only
for compatibility with older versions of CMake and is now ignored.
Result variables of both names are always set for compatibility.
``REQUIRED_VARS <required-var>...``
Specify the variables which are required for this package.
These may be named in the generated failure message asking the
user to set the missing variable values. Therefore these should
typically be cache entries such as ``FOO_LIBRARY`` and not output
variables like ``FOO_LIBRARIES``.
``VERSION_VAR <version-var>``
Specify the name of a variable that holds the version of the package
that has been found. This version will be checked against the
(potentially) specified required version given to the
:command:`find_package` call, including its ``EXACT`` option.
The default messages include information about the required
version and the version which has been actually found, both
if the version is ok or not.
``HANDLE_COMPONENTS``
Enable handling of package components. In this case, the command
will report which components have been found and which are missing,
and the ``<PackageName>_FOUND`` variable will be set to ``FALSE``
if any of the required components (i.e. not the ones listed after
the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are
missing.
``CONFIG_MODE``
Specify that the calling find module is a wrapper around a
call to ``find_package(<PackageName> NO_MODULE)``. This implies
a ``VERSION_VAR`` value of ``<PackageName>_VERSION``. The command
will automatically check whether the package configuration file
was found.
``FAIL_MESSAGE <custom-failure-message>``
Specify a custom failure message instead of using the default
generated message. Not recommended.
Example for the simple signature:
.. code-block:: cmake
find_package_handle_standard_args(LibXml2 DEFAULT_MSG
LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
The ``LibXml2`` package is considered to be found if both
``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid.
Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found
and ``REQUIRED`` was used, it fails with a
:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was
used or not. If it is found, success will be reported, including
the content of the first ``<required-var>``. On repeated CMake runs,
the same message will not be printed again.
Example for the full signature:
.. code-block:: cmake
find_package_handle_standard_args(LibArchive
REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR
VERSION_VAR LibArchive_VERSION)
In this case, the ``LibArchive`` package is considered to be found if
both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid.
Also the version of ``LibArchive`` will be checked by using the version
contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given,
the default messages will be printed.
Another example for the full signature:
.. code-block:: cmake
find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
find_package_handle_standard_args(Automoc4 CONFIG_MODE)
In this case, a ``FindAutmoc4.cmake`` module wraps a call to
``find_package(Automoc4 NO_MODULE)`` and adds an additional search
directory for ``automoc4``. Then the call to
``find_package_handle_standard_args`` produces a proper success/failure
message.
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
# internal helper macro
macro(_FPHSA_FAILURE_MESSAGE _msg)
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${_msg}")
else ()
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${_msg}")
endif ()
endif ()
endmacro()
# internal helper macro to generate the failure message when used in CONFIG_MODE:
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
# <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
if(${_NAME}_CONFIG)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
else()
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
# List them all in the error message:
if(${_NAME}_CONSIDERED_CONFIGS)
set(configsText "")
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
math(EXPR configsCount "${configsCount} - 1")
foreach(currentConfigIndex RANGE ${configsCount})
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
string(APPEND configsText " ${filename} (version ${version})\n")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
string(APPEND configsText " Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
else()
# Simple case: No Config-file was found at all:
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
endif()
endif()
endmacro()
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# Set up the arguments for `cmake_parse_arguments`.
set(options CONFIG_MODE HANDLE_COMPONENTS)
set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)
# Check whether we are in 'simple' or 'extended' mode:
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
if(${INDEX} EQUAL -1)
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
set(FPHSA_REQUIRED_VARS ${ARGN})
set(FPHSA_VERSION_VAR)
else()
cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
if(FPHSA_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT FPHSA_FAIL_MESSAGE)
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
# In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
# when it successfully found the config-file, including version checking:
if(FPHSA_CONFIG_MODE)
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
endif()
if(NOT FPHSA_REQUIRED_VARS)
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
endif()
endif()
# now that we collected all arguments, process them
if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
endif()
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
string(TOUPPER ${_NAME} _NAME_UPPER)
string(TOLOWER ${_NAME} _NAME_LOWER)
if(FPHSA_FOUND_VAR)
if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
set(_FOUND_VAR ${FPHSA_FOUND_VAR})
else()
message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
endif()
else()
set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
endif()
# collect all variables which were not found, so they can be printed, so the
# user knows better what went wrong (#6375)
set(MISSING_VARS "")
set(DETAILS "")
# check if all passed variables are valid
set(FPHSA_FOUND_${_NAME} TRUE)
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
if(NOT ${_CURRENT_VAR})
set(FPHSA_FOUND_${_NAME} FALSE)
string(APPEND MISSING_VARS " ${_CURRENT_VAR}")
else()
string(APPEND DETAILS "[${${_CURRENT_VAR}}]")
endif()
endforeach()
if(FPHSA_FOUND_${_NAME})
set(${_NAME}_FOUND TRUE)
set(${_NAME_UPPER}_FOUND TRUE)
else()
set(${_NAME}_FOUND FALSE)
set(${_NAME_UPPER}_FOUND FALSE)
endif()
# component handling
unset(FOUND_COMPONENTS_MSG)
unset(MISSING_COMPONENTS_MSG)
if(FPHSA_HANDLE_COMPONENTS)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(${_NAME}_${comp}_FOUND)
if(NOT DEFINED FOUND_COMPONENTS_MSG)
set(FOUND_COMPONENTS_MSG "found components: ")
endif()
string(APPEND FOUND_COMPONENTS_MSG " ${comp}")
else()
if(NOT DEFINED MISSING_COMPONENTS_MSG)
set(MISSING_COMPONENTS_MSG "missing components: ")
endif()
string(APPEND MISSING_COMPONENTS_MSG " ${comp}")
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_NAME}_FOUND FALSE)
string(APPEND MISSING_VARS " ${comp}")
endif()
endif()
endforeach()
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
string(APPEND DETAILS "[c${COMPONENT_MSG}]")
endif()
# version handling:
set(VERSION_MSG "")
set(VERSION_OK TRUE)
# check with DEFINED here as the requested or found version may be "0"
if (DEFINED ${_NAME}_FIND_VERSION)
if(DEFINED ${FPHSA_VERSION_VAR})
set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
# count the dots in the version string
string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${_FOUND_VERSION}")
# add one dot because there is one dot more than there are components
string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
# Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
# is at most 4 here. Therefore a simple lookup table is used.
if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
set(_VERSION_REGEX "[^.]*")
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
set(_VERSION_REGEX "[^.]*\\.[^.]*")
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
else ()
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
endif ()
string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${_FOUND_VERSION}")
unset(_VERSION_REGEX)
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
unset(_VERSION_HEAD)
else ()
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _FOUND_VERSION)
set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")")
endif ()
endif ()
unset(_VERSION_DOTS)
else() # minimum version specified:
if (${_NAME}_FIND_VERSION VERSION_GREATER _FOUND_VERSION)
set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable version \"${_FOUND_VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
endif ()
endif()
else()
# if the package was not found, but a version was given, add that to the output:
if(${_NAME}_FIND_VERSION_EXACT)
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
else()
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
endif()
endif()
else ()
# Check with DEFINED as the found version may be 0.
if(DEFINED ${FPHSA_VERSION_VAR})
set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")")
endif()
endif ()
if(VERSION_OK)
string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]")
else()
set(${_NAME}_FOUND FALSE)
endif()
# print the result:
if (${_NAME}_FOUND)
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
else ()
if(FPHSA_CONFIG_MODE)
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
else()
if(NOT VERSION_OK)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
else()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}")
endif()
endif()
endif ()
set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
endfunction()
+47
View File
@@ -0,0 +1,47 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# FindPackageMessage
# ------------------
#
#
#
# FIND_PACKAGE_MESSAGE(<name> "message for user" "find result details")
#
# This macro is intended to be used in FindXXX.cmake modules files. It
# will print a message once for each unique find result. This is useful
# for telling the user where a package was found. The first argument
# specifies the name (XXX) of the package. The second argument
# specifies the message to display. The third argument lists details
# about the find result so that if they change the message will be
# displayed again. The macro also obeys the QUIET argument to the
# find_package command.
#
# Example:
#
# ::
#
# if(X11_FOUND)
# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}"
# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
# else()
# ...
# endif()
function(FIND_PACKAGE_MESSAGE pkg msg details)
# Avoid printing a message repeatedly for the same find result.
if(NOT ${pkg}_FIND_QUIETLY)
string(REPLACE "\n" "" details "${details}")
set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
# The message has not yet been printed.
message(STATUS "${msg}")
# Save the find details in the cache to avoid printing the same
# message again.
set("${DETAILS_VAR}" "${details}"
CACHE INTERNAL "Details about finding ${pkg}")
endif()
endif()
endfunction()
+579
View File
@@ -0,0 +1,579 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# FindProtobuf
# ------------
#
# Locate and configure the Google Protocol Buffers library.
#
# The following variables can be set and are optional:
#
# ``Protobuf_SRC_ROOT_FOLDER``
# When compiling with MSVC, if this cache variable is set
# the protobuf-default VS project build locations
# (vsprojects/Debug and vsprojects/Release
# or vsprojects/x64/Debug and vsprojects/x64/Release)
# will be searched for libraries and binaries.
# ``Protobuf_IMPORT_DIRS``
# List of additional directories to be searched for
# imported .proto files.
# ``Protobuf_DEBUG``
# Show debug messages.
# ``Protobuf_USE_STATIC_LIBS``
# Set to ON to force the use of the static libraries.
# Default is OFF.
#
# Defines the following variables:
#
# ``Protobuf_FOUND``
# Found the Google Protocol Buffers library
# (libprotobuf & header files)
# ``Protobuf_VERSION``
# Version of package found.
# ``Protobuf_INCLUDE_DIRS``
# Include directories for Google Protocol Buffers
# ``Protobuf_LIBRARIES``
# The protobuf libraries
# ``Protobuf_PROTOC_LIBRARIES``
# The protoc libraries
# ``Protobuf_LITE_LIBRARIES``
# The protobuf-lite libraries
#
# The following :prop_tgt:`IMPORTED` targets are also defined:
#
# ``protobuf::libprotobuf``
# The protobuf library.
# ``protobuf::libprotobuf-lite``
# The protobuf lite library.
# ``protobuf::libprotoc``
# The protoc library.
# ``protobuf::protoc``
# The protoc compiler.
#
# The following cache variables are also available to set or use:
#
# ``Protobuf_LIBRARY``
# The protobuf library
# ``Protobuf_PROTOC_LIBRARY``
# The protoc library
# ``Protobuf_INCLUDE_DIR``
# The include directory for protocol buffers
# ``Protobuf_PROTOC_EXECUTABLE``
# The protoc compiler
# ``Protobuf_LIBRARY_DEBUG``
# The protobuf library (debug)
# ``Protobuf_PROTOC_LIBRARY_DEBUG``
# The protoc library (debug)
# ``Protobuf_LITE_LIBRARY``
# The protobuf lite library
# ``Protobuf_LITE_LIBRARY_DEBUG``
# The protobuf lite library (debug)
#
# Example:
#
# .. code-block:: cmake
#
# find_package(Protobuf REQUIRED)
# include_directories(${Protobuf_INCLUDE_DIRS})
# include_directories(${CMAKE_CURRENT_BINARY_DIR})
# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
# protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS DESCRIPTORS PROTO_DESCS foo.proto)
# protobuf_generate_python(PROTO_PY foo.proto)
# add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
# target_link_libraries(bar ${Protobuf_LIBRARIES})
#
# .. note::
# The ``protobuf_generate_cpp`` and ``protobuf_generate_python``
# functions and :command:`add_executable` or :command:`add_library`
# calls only work properly within the same directory.
#
# .. command:: protobuf_generate_cpp
#
# Add custom commands to process ``.proto`` files to C++::
#
# protobuf_generate_cpp (<SRCS> <HDRS>
# [DESCRIPTORS <DESC>] [EXPORT_MACRO <MACRO>] [<ARGN>...])
#
# ``SRCS``
# Variable to define with autogenerated source files
# ``HDRS``
# Variable to define with autogenerated header files
# ``DESCRIPTORS``
# Variable to define with autogenerated descriptor files, if requested.
# ``EXPORT_MACRO``
# is a macro which should expand to ``__declspec(dllexport)`` or
# ``__declspec(dllimport)`` depending on what is being compiled.
# ``ARGN``
# ``.proto`` files
#
# .. command:: protobuf_generate_python
#
# Add custom commands to process ``.proto`` files to Python::
#
# protobuf_generate_python (<PY> [<ARGN>...])
#
# ``PY``
# Variable to define with autogenerated Python files
# ``ARGN``
# ``.proto`` filess
function(PROTOBUF_GENERATE_CPP SRCS HDRS)
cmake_parse_arguments(protobuf "" "EXPORT_MACRO;DESCRIPTORS" "" ${ARGN})
set(PROTO_FILES "${protobuf_UNPARSED_ARGUMENTS}")
if(NOT PROTO_FILES)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
return()
endif()
if(protobuf_EXPORT_MACRO)
set(DLL_EXPORT_DECL "dllexport_decl=${protobuf_EXPORT_MACRO}:")
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
foreach(FIL ${PROTO_FILES})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
endif()
if(DEFINED Protobuf_IMPORT_DIRS)
foreach(DIR ${Protobuf_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
endif()
set(${SRCS})
set(${HDRS})
if (protobuf_DESCRIPTORS)
set(${protobuf_DESCRIPTORS})
endif()
foreach(FIL ${PROTO_FILES})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
get_filename_component(FIL_DIR ${FIL} DIRECTORY)
if(FIL_DIR)
set(FIL_WE "${FIL_DIR}/${FIL_WE}")
endif()
endif()
set(_protobuf_protoc_src "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.pb.cc")
set(_protobuf_protoc_hdr "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.pb.h")
list(APPEND ${SRCS} "${_protobuf_protoc_src}")
list(APPEND ${HDRS} "${_protobuf_protoc_hdr}")
if(protobuf_DESCRIPTORS)
set(_protobuf_protoc_desc "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.desc")
set(_protobuf_protoc_flags "--descriptor_set_out=${_protobuf_protoc_desc}")
list(APPEND ${protobuf_DESCRIPTORS} "${_protobuf_protoc_desc}")
else()
set(_protobuf_protoc_desc "")
set(_protobuf_protoc_flags "")
endif()
add_custom_command(
OUTPUT "${_protobuf_protoc_src}"
"${_protobuf_protoc_hdr}"
${_protobuf_protoc_desc}
COMMAND protobuf::protoc
"--cpp_out=${DLL_EXPORT_DECL}${CMAKE_CURRENT_SOURCE_DIR}"
${_protobuf_protoc_flags}
${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL} protobuf::protoc
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
set(${SRCS} "${${SRCS}}" PARENT_SCOPE)
set(${HDRS} "${${HDRS}}" PARENT_SCOPE)
if(protobuf_DESCRIPTORS)
set(${protobuf_DESCRIPTORS} "${${protobuf_DESCRIPTORS}}" PARENT_SCOPE)
endif()
endfunction()
function(PROTOBUF_GENERATE_PYTHON SRCS)
if(NOT ARGN)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
return()
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
endif()
if(DEFINED Protobuf_IMPORT_DIRS)
foreach(DIR ${Protobuf_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
endif()
set(${SRCS})
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
get_filename_component(FIL_DIR ${FIL} DIRECTORY)
if(FIL_DIR)
set(FIL_WE "${FIL_DIR}/${FIL_WE}")
endif()
endif()
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py"
COMMAND protobuf::protoc --python_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL} protobuf::protoc
COMMENT "Running Python protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
endfunction()
if(Protobuf_DEBUG)
# Output some of their choices
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"Protobuf_USE_STATIC_LIBS = ${Protobuf_USE_STATIC_LIBS}")
endif()
# Backwards compatibility
# Define camel case versions of input variables
foreach(UPPER
PROTOBUF_SRC_ROOT_FOLDER
PROTOBUF_IMPORT_DIRS
PROTOBUF_DEBUG
PROTOBUF_LIBRARY
PROTOBUF_PROTOC_LIBRARY
PROTOBUF_INCLUDE_DIR
PROTOBUF_PROTOC_EXECUTABLE
PROTOBUF_LIBRARY_DEBUG
PROTOBUF_PROTOC_LIBRARY_DEBUG
PROTOBUF_LITE_LIBRARY
PROTOBUF_LITE_LIBRARY_DEBUG
)
if (DEFINED ${UPPER})
string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
if (NOT DEFINED ${Camel})
set(${Camel} ${${UPPER}})
endif()
endif()
endforeach()
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_PROTOBUF_ARCH_DIR x64/)
endif()
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
if( Protobuf_USE_STATIC_LIBS )
set( _protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
endif()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
# Internal function: search for normal library as well as a debug one
# if the debug one is specified also include debug/optimized keywords
# in *_LIBRARIES variable
function(_protobuf_find_libraries name filename)
if(${name}_LIBRARIES)
# Use result recorded by a previous call.
return()
elseif(${name}_LIBRARY)
# Honor cache entry used by CMake 3.5 and lower.
set(${name}_LIBRARIES "${${name}_LIBRARY}" PARENT_SCOPE)
else()
find_library(${name}_LIBRARY_RELEASE
NAMES ${filename}
PATHS ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Release)
mark_as_advanced(${name}_LIBRARY_RELEASE)
find_library(${name}_LIBRARY_DEBUG
NAMES ${filename}d ${filename}
PATHS ${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Debug)
mark_as_advanced(${name}_LIBRARY_DEBUG)
select_library_configurations(${name})
set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE)
set(${name}_LIBRARIES "${${name}_LIBRARIES}" PARENT_SCOPE)
endif()
endfunction()
# Internal function: find threads library
function(_protobuf_find_threads)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads)
if(Threads_FOUND)
list(APPEND Protobuf_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
set(Protobuf_LIBRARIES "${Protobuf_LIBRARIES}" PARENT_SCOPE)
endif()
endfunction()
#
# Main.
#
# By default have PROTOBUF_GENERATE_CPP macro pass -I to protoc
# for each directory where a proto file is referenced.
if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH)
set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE)
endif()
# Google's provided vcproj files generate libraries with a "lib"
# prefix on Windows
if(MSVC)
set(Protobuf_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
find_path(Protobuf_SRC_ROOT_FOLDER protobuf.pc.in)
endif()
# The Protobuf library
_protobuf_find_libraries(Protobuf protobuf)
#DOC "The Google Protocol Buffers RELEASE Library"
_protobuf_find_libraries(Protobuf_LITE protobuf-lite)
# The Protobuf Protoc Library
_protobuf_find_libraries(Protobuf_PROTOC protoc)
# Restore original find library prefixes
if(MSVC)
set(CMAKE_FIND_LIBRARY_PREFIXES "${Protobuf_ORIG_FIND_LIBRARY_PREFIXES}")
endif()
if(UNIX)
_protobuf_find_threads()
endif()
# Find the include directory
find_path(Protobuf_INCLUDE_DIR
google/protobuf/service.h
PATHS ${Protobuf_SRC_ROOT_FOLDER}/src
)
mark_as_advanced(Protobuf_INCLUDE_DIR)
# Find the protoc Executable
find_program(Protobuf_PROTOC_EXECUTABLE
NAMES protoc
DOC "The Google Protocol Buffers Compiler"
PATHS /usr/bin
${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Release
${Protobuf_SRC_ROOT_FOLDER}/vsprojects/${_PROTOBUF_ARCH_DIR}Debug
)
mark_as_advanced(Protobuf_PROTOC_EXECUTABLE)
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"requested version of Google Protobuf is ${Protobuf_FIND_VERSION}")
endif()
if(Protobuf_INCLUDE_DIR)
set(_PROTOBUF_COMMON_HEADER ${Protobuf_INCLUDE_DIR}/google/protobuf/stubs/common.h)
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"location of common.h: ${_PROTOBUF_COMMON_HEADER}")
endif()
set(Protobuf_VERSION "")
set(Protobuf_LIB_VERSION "")
file(STRINGS ${_PROTOBUF_COMMON_HEADER} _PROTOBUF_COMMON_H_CONTENTS REGEX "#define[ \t]+GOOGLE_PROTOBUF_VERSION[ \t]+")
if(_PROTOBUF_COMMON_H_CONTENTS MATCHES "#define[ \t]+GOOGLE_PROTOBUF_VERSION[ \t]+([0-9]+)")
set(Protobuf_LIB_VERSION "${CMAKE_MATCH_1}")
endif()
unset(_PROTOBUF_COMMON_H_CONTENTS)
math(EXPR _PROTOBUF_MAJOR_VERSION "${Protobuf_LIB_VERSION} / 1000000")
math(EXPR _PROTOBUF_MINOR_VERSION "${Protobuf_LIB_VERSION} / 1000 % 1000")
math(EXPR _PROTOBUF_SUBMINOR_VERSION "${Protobuf_LIB_VERSION} % 1000")
set(Protobuf_VERSION "${_PROTOBUF_MAJOR_VERSION}.${_PROTOBUF_MINOR_VERSION}.${_PROTOBUF_SUBMINOR_VERSION}")
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"${_PROTOBUF_COMMON_HEADER} reveals protobuf ${Protobuf_VERSION}")
endif()
# Check Protobuf compiler version to be aligned with libraries version
execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} --version
OUTPUT_VARIABLE _PROTOBUF_PROTOC_EXECUTABLE_VERSION)
if("${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" MATCHES "libprotoc ([0-9.]+)")
set(_PROTOBUF_PROTOC_EXECUTABLE_VERSION "${CMAKE_MATCH_1}")
endif()
if(Protobuf_DEBUG)
message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
"${Protobuf_PROTOC_EXECUTABLE} reveals version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}")
endif()
if(NOT "${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}" VERSION_EQUAL "${Protobuf_VERSION}")
message(WARNING "Protobuf compiler version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}"
" doesn't match library version ${Protobuf_VERSION}")
endif()
if(Protobuf_LIBRARY)
if(NOT TARGET protobuf::libprotobuf)
add_library(protobuf::libprotobuf UNKNOWN IMPORTED)
set_target_properties(protobuf::libprotobuf PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
if(EXISTS "${Protobuf_LIBRARY}")
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION "${Protobuf_LIBRARY}")
endif()
if(EXISTS "${Protobuf_LIBRARY_RELEASE}")
set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION_RELEASE "${Protobuf_LIBRARY_RELEASE}")
endif()
if(EXISTS "${Protobuf_LIBRARY_DEBUG}")
set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotobuf PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}")
endif()
endif()
endif()
if(Protobuf_LITE_LIBRARY)
if(NOT TARGET protobuf::libprotobuf-lite)
add_library(protobuf::libprotobuf-lite UNKNOWN IMPORTED)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
if(EXISTS "${Protobuf_LITE_LIBRARY}")
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION "${Protobuf_LITE_LIBRARY}")
endif()
if(EXISTS "${Protobuf_LITE_LIBRARY_RELEASE}")
set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION_RELEASE "${Protobuf_LITE_LIBRARY_RELEASE}")
endif()
if(EXISTS "${Protobuf_LITE_LIBRARY_DEBUG}")
set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}")
endif()
endif()
endif()
if(Protobuf_PROTOC_LIBRARY)
if(NOT TARGET protobuf::libprotoc)
add_library(protobuf::libprotoc UNKNOWN IMPORTED)
set_target_properties(protobuf::libprotoc PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
if(EXISTS "${Protobuf_PROTOC_LIBRARY}")
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}")
endif()
if(EXISTS "${Protobuf_PROTOC_LIBRARY_RELEASE}")
set_property(TARGET protobuf::libprotoc APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION_RELEASE "${Protobuf_PROTOC_LIBRARY_RELEASE}")
endif()
if(EXISTS "${Protobuf_PROTOC_LIBRARY_DEBUG}")
set_property(TARGET protobuf::libprotoc APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotoc PROPERTIES
IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}")
endif()
endif()
endif()
if(Protobuf_PROTOC_EXECUTABLE)
if(NOT TARGET protobuf::protoc)
add_executable(protobuf::protoc IMPORTED)
if(EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
set_target_properties(protobuf::protoc PROPERTIES
IMPORTED_LOCATION "${Protobuf_PROTOC_EXECUTABLE}")
endif()
endif()
endif()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Protobuf
REQUIRED_VARS Protobuf_LIBRARIES Protobuf_INCLUDE_DIR
VERSION_VAR Protobuf_VERSION
)
if(Protobuf_FOUND)
set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR})
endif()
# Restore the original find library ordering
if( Protobuf_USE_STATIC_LIBS )
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
# Backwards compatibility
# Define upper case versions of output variables
foreach(Camel
Protobuf_SRC_ROOT_FOLDER
Protobuf_IMPORT_DIRS
Protobuf_DEBUG
Protobuf_INCLUDE_DIRS
Protobuf_LIBRARIES
Protobuf_PROTOC_LIBRARIES
Protobuf_LITE_LIBRARIES
Protobuf_LIBRARY
Protobuf_PROTOC_LIBRARY
Protobuf_INCLUDE_DIR
Protobuf_PROTOC_EXECUTABLE
Protobuf_LIBRARY_DEBUG
Protobuf_PROTOC_LIBRARY_DEBUG
Protobuf_LITE_LIBRARY
Protobuf_LITE_LIBRARY_DEBUG
)
string(TOUPPER ${Camel} UPPER)
set(${UPPER} ${${Camel}})
endforeach()
+71
View File
@@ -0,0 +1,71 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# SelectLibraryConfigurations
# ---------------------------
#
#
#
# select_library_configurations( basename )
#
# This macro takes a library base name as an argument, and will choose
# good values for basename_LIBRARY, basename_LIBRARIES,
# basename_LIBRARY_DEBUG, and basename_LIBRARY_RELEASE depending on what
# has been found and set. If only basename_LIBRARY_RELEASE is defined,
# basename_LIBRARY will be set to the release value, and
# basename_LIBRARY_DEBUG will be set to basename_LIBRARY_DEBUG-NOTFOUND.
# If only basename_LIBRARY_DEBUG is defined, then basename_LIBRARY will
# take the debug value, and basename_LIBRARY_RELEASE will be set to
# basename_LIBRARY_RELEASE-NOTFOUND.
#
# If the generator supports configuration types, then basename_LIBRARY
# and basename_LIBRARIES will be set with debug and optimized flags
# specifying the library to be used for the given configuration. If no
# build type has been set or the generator in use does not support
# configuration types, then basename_LIBRARY and basename_LIBRARIES will
# take only the release value, or the debug value if the release one is
# not set.
# This macro was adapted from the FindQt4 CMake module and is maintained by Will
# Dicharry <wdicharry@stellarscience.com>.
macro( select_library_configurations basename )
if(NOT ${basename}_LIBRARY_RELEASE)
set(${basename}_LIBRARY_RELEASE "${basename}_LIBRARY_RELEASE-NOTFOUND" CACHE FILEPATH "Path to a library.")
endif()
if(NOT ${basename}_LIBRARY_DEBUG)
set(${basename}_LIBRARY_DEBUG "${basename}_LIBRARY_DEBUG-NOTFOUND" CACHE FILEPATH "Path to a library.")
endif()
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE AND
NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE AND
( _isMultiConfig OR CMAKE_BUILD_TYPE ) )
# if the generator is multi-config or if CMAKE_BUILD_TYPE is set for
# single-config generators, set optimized and debug libraries
set( ${basename}_LIBRARY "" )
foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE )
list( APPEND ${basename}_LIBRARY optimized "${_libname}" )
endforeach()
foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG )
list( APPEND ${basename}_LIBRARY debug "${_libname}" )
endforeach()
elseif( ${basename}_LIBRARY_RELEASE )
set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} )
elseif( ${basename}_LIBRARY_DEBUG )
set( ${basename}_LIBRARY ${${basename}_LIBRARY_DEBUG} )
else()
set( ${basename}_LIBRARY "${basename}_LIBRARY-NOTFOUND")
endif()
set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" )
if( ${basename}_LIBRARY )
set( ${basename}_FOUND TRUE )
endif()
mark_as_advanced( ${basename}_LIBRARY_RELEASE
${basename}_LIBRARY_DEBUG
)
endmacro()
+33 -27
View File
@@ -1,10 +1,11 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(PROTOBUF_GENERATE_CPP_APPEND_PATH "../../")
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HEADERS message.proto)
SET(common_sources SET(common_sources
base_packet.cpp base_packet.cpp
classes.cpp classes.cpp
cli/eqemu_command_handler.cpp
compression.cpp
condition.cpp condition.cpp
crash.cpp crash.cpp
crc16.cpp crc16.cpp
@@ -15,6 +16,7 @@ SET(common_sources
dbcore.cpp dbcore.cpp
deity.cpp deity.cpp
emu_constants.cpp emu_constants.cpp
emu_legacy.cpp
emu_limits.cpp emu_limits.cpp
emu_opcodes.cpp emu_opcodes.cpp
emu_versions.cpp emu_versions.cpp
@@ -36,7 +38,6 @@ SET(common_sources
inventory_profile.cpp inventory_profile.cpp
inventory_slot.cpp inventory_slot.cpp
ipc_mutex.cpp ipc_mutex.cpp
ip_util.cpp
item_data.cpp item_data.cpp
item_instance.cpp item_instance.cpp
json_config.cpp json_config.cpp
@@ -44,6 +45,7 @@ SET(common_sources
md5.cpp md5.cpp
memory_buffer.cpp memory_buffer.cpp
memory_mapped_file.cpp memory_mapped_file.cpp
message.pb.cc
misc.cpp misc.cpp
misc_functions.cpp misc_functions.cpp
mutex.cpp mutex.cpp
@@ -57,13 +59,11 @@ SET(common_sources
perl_eqdb.cpp perl_eqdb.cpp
perl_eqdb_res.cpp perl_eqdb_res.cpp
proc_launcher.cpp proc_launcher.cpp
profanity_manager.cpp
ptimer.cpp ptimer.cpp
races.cpp races.cpp
rdtsc.cpp rdtsc.cpp
rulesys.cpp rulesys.cpp
say_link.cpp say_link.cpp
serialize_buffer.cpp
serverinfo.cpp serverinfo.cpp
shareddb.cpp shareddb.cpp
skills.cpp skills.cpp
@@ -73,7 +73,9 @@ SET(common_sources
textures.cpp textures.cpp
timer.cpp timer.cpp
unix.cpp unix.cpp
xml_parser.cpp
platform.cpp platform.cpp
event/event_loop.cpp
json/jsoncpp.cpp json/jsoncpp.cpp
net/console_server.cpp net/console_server.cpp
net/console_server_connection.cpp net/console_server_connection.cpp
@@ -87,8 +89,6 @@ SET(common_sources
net/servertalk_server_connection.cpp net/servertalk_server_connection.cpp
net/tcp_connection.cpp net/tcp_connection.cpp
net/tcp_server.cpp net/tcp_server.cpp
net/websocket_server.cpp
net/websocket_server_connection.cpp
patches/patches.cpp patches/patches.cpp
patches/sod.cpp patches/sod.cpp
patches/sod_limits.cpp patches/sod_limits.cpp
@@ -103,8 +103,13 @@ SET(common_sources
patches/uf.cpp patches/uf.cpp
patches/uf_limits.cpp patches/uf_limits.cpp
StackWalker/StackWalker.cpp StackWalker/StackWalker.cpp
tinyxml/tinystr.cpp
tinyxml/tinyxml.cpp
tinyxml/tinyxmlerror.cpp
tinyxml/tinyxmlparser.cpp
util/directory.cpp util/directory.cpp
util/uuid.cpp) util/uuid.cpp
)
SET(common_headers SET(common_headers
any.h any.h
@@ -112,19 +117,16 @@ SET(common_headers
base_data.h base_data.h
bodytypes.h bodytypes.h
classes.h classes.h
compression.h
condition.h condition.h
crash.h crash.h
crc16.h crc16.h
crc32.h crc32.h
cli/argh.h
cli/eqemu_command_handler.h
cli/terminal_color.hpp
data_verification.h data_verification.h
database.h database.h
dbcore.h dbcore.h
deity.h deity.h
emu_constants.h emu_constants.h
emu_legacy.h
emu_limits.h emu_limits.h
emu_opcodes.h emu_opcodes.h
emu_oplist.h emu_oplist.h
@@ -137,7 +139,6 @@ SET(common_headers
eqemu_config.h eqemu_config.h
eqemu_config_elements.h eqemu_config_elements.h
eqemu_logsys.h eqemu_logsys.h
eqemu_logsys_log_aliases.h
eq_limits.h eq_limits.h
eq_packet.h eq_packet.h
eq_stream_ident.h eq_stream_ident.h
@@ -155,11 +156,9 @@ SET(common_headers
global_define.h global_define.h
guild_base.h guild_base.h
guilds.h guilds.h
http/httplib.h
inventory_profile.h inventory_profile.h
inventory_slot.h inventory_slot.h
ipc_mutex.h ipc_mutex.h
ip_util.h
item_data.h item_data.h
item_fieldlist.h item_fieldlist.h
item_instance.h item_instance.h
@@ -172,6 +171,7 @@ SET(common_headers
md5.h md5.h
memory_buffer.h memory_buffer.h
memory_mapped_file.h memory_mapped_file.h
message.pb.h
misc.h misc.h
misc_functions.h misc_functions.h
mutex.h mutex.h
@@ -185,7 +185,6 @@ SET(common_headers
packet_functions.h packet_functions.h
platform.h platform.h
proc_launcher.h proc_launcher.h
profanity_manager.h
profiler.h profiler.h
ptimer.h ptimer.h
queue.h queue.h
@@ -196,7 +195,6 @@ SET(common_headers
ruletypes.h ruletypes.h
say_link.h say_link.h
seperator.h seperator.h
serialize_buffer.h
serverinfo.h serverinfo.h
servertalk.h servertalk.h
shareddb.h shareddb.h
@@ -210,9 +208,10 @@ SET(common_headers
unix.h unix.h
useperl.h useperl.h
version.h version.h
xml_parser.h
zone_numbers.h zone_numbers.h
event/background_task.h
event/event_loop.h event/event_loop.h
event/task.h
event/timer.h event/timer.h
json/json.h json/json.h
json/json-forwards.h json/json-forwards.h
@@ -232,8 +231,6 @@ SET(common_headers
net/servertalk_server_connection.h net/servertalk_server_connection.h
net/tcp_connection.h net/tcp_connection.h
net/tcp_server.h net/tcp_server.h
net/websocket_server.h
net/websocket_server_connection.h
patches/patches.h patches/patches.h
patches/sod.h patches/sod.h
patches/sod_limits.h patches/sod_limits.h
@@ -263,14 +260,18 @@ SET(common_headers
patches/uf_ops.h patches/uf_ops.h
patches/uf_structs.h patches/uf_structs.h
StackWalker/StackWalker.h StackWalker/StackWalker.h
tinyxml/tinystr.h
tinyxml/tinyxml.h
util/memory_stream.h util/memory_stream.h
util/directory.h util/directory.h
util/uuid.h) util/uuid.h
)
SOURCE_GROUP(Event FILES SOURCE_GROUP(Event FILES
event/background_task.h
event/event_loop.cpp
event/event_loop.h event/event_loop.h
event/timer.h event/timer.h
event/task.h
) )
SOURCE_GROUP(Json FILES SOURCE_GROUP(Json FILES
@@ -310,10 +311,6 @@ SOURCE_GROUP(Net FILES
net/tcp_connection.h net/tcp_connection.h
net/tcp_server.cpp net/tcp_server.cpp
net/tcp_server.h net/tcp_server.h
net/websocket_server.cpp
net/websocket_server.h
net/websocket_server_connection.cpp
net/websocket_server_connection.h
) )
SOURCE_GROUP(Patches FILES SOURCE_GROUP(Patches FILES
@@ -365,6 +362,15 @@ SOURCE_GROUP(StackWalker FILES
StackWalker/StackWalker.cpp StackWalker/StackWalker.cpp
) )
SOURCE_GROUP(TinyXML FILES
tinyxml/tinystr.h
tinyxml/tinyxml.h
tinyxml/tinystr.cpp
tinyxml/tinyxml.cpp
tinyxml/tinyxmlerror.cpp
tinyxml/tinyxmlparser.cpp
)
SOURCE_GROUP(Util FILES SOURCE_GROUP(Util FILES
util/memory_stream.h util/memory_stream.h
util/directory.cpp util/directory.cpp
@@ -373,7 +379,7 @@ SOURCE_GROUP(Util FILES
util/uuid.h util/uuid.h
) )
INCLUDE_DIRECTORIES(Patches SocketLib StackWalker) INCLUDE_DIRECTORIES(Patches SocketLib StackWalker TinyXML)
ADD_LIBRARY(common ${common_sources} ${common_headers}) ADD_LIBRARY(common ${common_sources} ${common_headers})
-12
View File
@@ -39,18 +39,6 @@ BasePacket::BasePacket(const unsigned char *buf, uint32 len)
} }
} }
BasePacket::BasePacket(SerializeBuffer &buf)
{
pBuffer = buf.m_buffer;
buf.m_buffer = nullptr;
size = buf.m_pos;
buf.m_pos = 0;
buf.m_capacity = 0;
_wpos = 0;
_rpos = 0;
timestamp.tv_sec = 0;
}
BasePacket::~BasePacket() BasePacket::~BasePacket()
{ {
if (pBuffer) if (pBuffer)
-5
View File
@@ -19,7 +19,6 @@
#define BASEPACKET_H_ #define BASEPACKET_H_
#include "types.h" #include "types.h"
#include "serialize_buffer.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -64,8 +63,6 @@ public:
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); } void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); } void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; } void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
// this is used in task system a lot, it is NOT null-termed
void WriteLengthString(uint32 len, const char *str) { *(uint32 *)(pBuffer + _wpos) = len; _wpos += sizeof(uint32); memcpy(pBuffer + _wpos, str, len); _wpos += len; }
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; } void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; }
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; } uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
@@ -75,7 +72,6 @@ public:
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; } uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; } uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; } void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const; void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
uint32 GetWritePosition() { return _wpos; } uint32 GetWritePosition() { return _wpos; }
@@ -87,7 +83,6 @@ protected:
virtual ~BasePacket(); virtual ~BasePacket();
BasePacket() { pBuffer=nullptr; size=0; _wpos = 0; _rpos = 0; } BasePacket() { pBuffer=nullptr; size=0; _wpos = 0; _rpos = 0; }
BasePacket(const unsigned char *buf, const uint32 len); BasePacket(const unsigned char *buf, const uint32 len);
BasePacket(SerializeBuffer &buf);
}; };
extern void DumpPacketHex(const BasePacket* app); extern void DumpPacketHex(const BasePacket* app);
+104 -206
View File
@@ -18,332 +18,230 @@
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/classes.h" #include "../common/classes.h"
const char *GetClassIDName(uint8 class_id, uint8 level) const char* GetClassIDName(uint8 class_id, uint8 level)
{ {
switch (class_id) { switch (class_id) {
case WARRIOR: case WARRIOR:
if (level >= 70) { if (level >= 70)
return "Vanquisher"; return "Vanquisher";
} else if (level >= 65)
else if (level >= 65) {
return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE. return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE.
} else if (level >= 60)
else if (level >= 60) {
return "Warlord"; return "Warlord";
} else if (level >= 55)
else if (level >= 55) {
return "Myrmidon"; return "Myrmidon";
} else if (level >= 51)
else if (level >= 51) {
return "Champion"; return "Champion";
} else
else {
return "Warrior"; return "Warrior";
}
case CLERIC: case CLERIC:
if (level >= 70) { if (level >= 70)
return "Prelate"; return "Prelate";
} else if (level >= 65)
else if (level >= 65) {
return "Archon"; return "Archon";
} else if (level >= 60)
else if (level >= 60) {
return "High Priest"; return "High Priest";
} else if (level >= 55)
else if (level >= 55) {
return "Templar"; return "Templar";
} else if (level >= 51)
else if (level >= 51) {
return "Vicar"; return "Vicar";
} else
else {
return "Cleric"; return "Cleric";
}
case PALADIN: case PALADIN:
if (level >= 70) { if (level >= 70)
return "Lord"; return "Lord";
} else if (level >= 65)
else if (level >= 65) {
return "Lord Protector"; return "Lord Protector";
} else if (level >= 60)
else if (level >= 60) {
return "Crusader"; return "Crusader";
} else if (level >= 55)
else if (level >= 55) {
return "Knight"; return "Knight";
} else if (level >= 51)
else if (level >= 51) {
return "Cavalier"; return "Cavalier";
} else
else {
return "Paladin"; return "Paladin";
}
case RANGER: case RANGER:
if (level >= 70) { if (level >= 70)
return "Plainswalker"; return "Plainswalker";
} else if (level >= 65)
else if (level >= 65) {
return "Forest Stalker"; return "Forest Stalker";
} else if (level >= 60)
else if (level >= 60) {
return "Warder"; return "Warder";
} else if (level >= 55)
else if (level >= 55) {
return "Outrider"; return "Outrider";
} else if (level >= 51)
else if (level >= 51) {
return "Pathfinder"; return "Pathfinder";
} else
else {
return "Ranger"; return "Ranger";
}
case SHADOWKNIGHT: case SHADOWKNIGHT:
if (level >= 70) { if (level >= 70)
return "Scourge Knight"; return "Scourge Knight";
} else if (level >= 65)
else if (level >= 65) {
return "Dread Lord"; return "Dread Lord";
} else if (level >= 60)
else if (level >= 60) {
return "Grave Lord"; return "Grave Lord";
} else if (level >= 55)
else if (level >= 55) {
return "Revenant"; return "Revenant";
} else if (level >= 51)
else if (level >= 51) {
return "Reaver"; return "Reaver";
} else
else {
return "Shadowknight"; return "Shadowknight";
}
case DRUID: case DRUID:
if (level >= 70) { if (level >= 70)
return "Natureguard"; return "Natureguard";
} else if (level >= 65)
else if (level >= 65) {
return "Storm Warden"; return "Storm Warden";
} else if (level >= 60)
else if (level >= 60) {
return "Hierophant"; return "Hierophant";
} else if (level >= 55)
else if (level >= 55) {
return "Preserver"; return "Preserver";
} else if (level >= 51)
else if (level >= 51) {
return "Wanderer"; return "Wanderer";
} else
else {
return "Druid"; return "Druid";
}
case MONK: case MONK:
if (level >= 70) { if (level >= 70)
return "Stone Fist"; return "Stone Fist";
} else if (level >= 65)
else if (level >= 65) {
return "Transcendent"; return "Transcendent";
} else if (level >= 60)
else if (level >= 60) {
return "Grandmaster"; return "Grandmaster";
} else if (level >= 55)
else if (level >= 55) {
return "Master"; return "Master";
} else if (level >= 51)
else if (level >= 51) {
return "Disciple"; return "Disciple";
} else
else {
return "Monk"; return "Monk";
}
case BARD: case BARD:
if (level >= 70) { if (level >= 70)
return "Performer"; return "Performer";
} else if (level >= 65)
else if (level >= 65) {
return "Maestro"; return "Maestro";
} else if (level >= 60)
else if (level >= 60) {
return "Virtuoso"; return "Virtuoso";
} else if (level >= 55)
else if (level >= 55) {
return "Troubadour"; return "Troubadour";
} else if (level >= 51)
else if (level >= 51) {
return "Minstrel"; return "Minstrel";
} else
else {
return "Bard"; return "Bard";
}
case ROGUE: case ROGUE:
if (level >= 70) { if (level >= 70)
return "Nemesis"; return "Nemesis";
} else if (level >= 65)
else if (level >= 65) {
return "Deceiver"; return "Deceiver";
} else if (level >= 60)
else if (level >= 60) {
return "Assassin"; return "Assassin";
} else if (level >= 55)
else if (level >= 55) {
return "Blackguard"; return "Blackguard";
} else if (level >= 51)
else if (level >= 51) {
return "Rake"; return "Rake";
} else
else {
return "Rogue"; return "Rogue";
}
case SHAMAN: case SHAMAN:
if (level >= 70) { if (level >= 70)
return "Soothsayer"; return "Soothsayer";
} else if (level >= 65)
else if (level >= 65) {
return "Prophet"; return "Prophet";
} else if (level >= 60)
else if (level >= 60) {
return "Oracle"; return "Oracle";
} else if (level >= 55)
else if (level >= 55) {
return "Luminary"; return "Luminary";
} else if (level >= 51)
else if (level >= 51) {
return "Mystic"; return "Mystic";
} else
else {
return "Shaman"; return "Shaman";
}
case NECROMANCER: case NECROMANCER:
if (level >= 70) { if (level >= 70)
return "Wraith"; return "Wraith";
} else if (level >= 65)
else if (level >= 65) {
return "Arch Lich"; return "Arch Lich";
} else if (level >= 60)
else if (level >= 60) {
return "Warlock"; return "Warlock";
} else if (level >= 55)
else if (level >= 55) {
return "Defiler"; return "Defiler";
} else if (level >= 51)
else if (level >= 51) {
return "Heretic"; return "Heretic";
} else
else {
return "Necromancer"; return "Necromancer";
}
case WIZARD: case WIZARD:
if (level >= 70) { if (level >= 70)
return "Grand Arcanist"; return "Grand Arcanist";
} else if (level >= 65)
else if (level >= 65) {
return "Arcanist"; return "Arcanist";
} else if (level >= 60)
else if (level >= 60) {
return "Sorcerer"; return "Sorcerer";
} else if (level >= 55)
else if (level >= 55) {
return "Evoker"; return "Evoker";
} else if (level >= 51)
else if (level >= 51) {
return "Channeler"; return "Channeler";
} else
else {
return "Wizard"; return "Wizard";
}
case MAGICIAN: case MAGICIAN:
if (level >= 70) { if (level >= 70)
return "Arch Magus"; return "Arch Magus";
} else if (level >= 65)
else if (level >= 65) {
return "Arch Convoker"; return "Arch Convoker";
} else if (level >= 60)
else if (level >= 60) {
return "Arch Mage"; return "Arch Mage";
} else if (level >= 55)
else if (level >= 55) {
return "Conjurer"; return "Conjurer";
} if (level >= 51)
if (level >= 51) {
return "Elementalist"; return "Elementalist";
} else
else {
return "Magician"; return "Magician";
}
case ENCHANTER: case ENCHANTER:
if (level >= 70) { if (level >= 70)
return "Bedazzler"; return "Bedazzler";
} else if (level >= 65)
else if (level >= 65) {
return "Coercer"; return "Coercer";
} else if (level >= 60)
else if (level >= 60) {
return "Phantasmist"; return "Phantasmist";
} else if (level >= 55)
else if (level >= 55) {
return "Beguiler"; return "Beguiler";
} else if (level >= 51)
else if (level >= 51) {
return "Illusionist"; return "Illusionist";
} else
else {
return "Enchanter"; return "Enchanter";
}
case BEASTLORD: case BEASTLORD:
if (level >= 70) { if (level >= 70)
return "Wildblood"; return "Wildblood";
} else if (level >= 65)
else if (level >= 65) {
return "Feral Lord"; return "Feral Lord";
} else if (level >= 60)
else if (level >= 60) {
return "Savage Lord"; return "Savage Lord";
} else if (level >= 55)
else if (level >= 55) {
return "Animist"; return "Animist";
} else if (level >= 51)
else if (level >= 51) {
return "Primalist"; return "Primalist";
} else
else {
return "Beastlord"; return "Beastlord";
}
case BERSERKER: case BERSERKER:
if (level >= 70) { if (level >= 70)
return "Ravager"; return "Ravager";
} else if (level >= 65)
else if (level >= 65) {
return "Fury"; return "Fury";
} else if (level >= 60)
else if (level >= 60) {
return "Rager"; return "Rager";
} else if (level >= 55)
else if (level >= 55) {
return "Vehement"; return "Vehement";
} else if (level >= 51)
else if (level >= 51) {
return "Brawler"; return "Brawler";
} else
else {
return "Berserker"; return "Berserker";
}
case BANKER: case BANKER:
if (level >= 70) { if (level >= 70)
return "Master Banker"; return "Master Banker";
} else if (level >= 65)
else if (level >= 65) {
return "Elder Banker"; return "Elder Banker";
} else if (level >= 60)
else if (level >= 60) {
return "Oldest Banker"; return "Oldest Banker";
} else if (level >= 55)
else if (level >= 55) {
return "Older Banker"; return "Older Banker";
} else if (level >= 51)
else if (level >= 51) {
return "Old Banker"; return "Old Banker";
} else
else {
return "Banker"; return "Banker";
}
case WARRIORGM: case WARRIORGM:
return "Warrior Guildmaster"; return "Warrior Guildmaster";
case CLERICGM: case CLERICGM:
@@ -393,7 +291,7 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
} }
} }
const char *GetPlayerClassName(uint32 player_class_value, uint8 level) const char* GetPlayerClassName(uint32 player_class_value, uint8 level)
{ {
return GetClassIDName(GetClassIDFromPlayerClassValue(player_class_value), level); return GetClassIDName(GetClassIDFromPlayerClassValue(player_class_value), level);
} }
-434
View File
@@ -1,434 +0,0 @@
#pragma once
#include <algorithm>
#include <sstream>
#include <limits>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cassert>
namespace argh
{
// Terminology:
// A command line is composed of 2 types of args:
// 1. Positional args, i.e. free standing values
// 2. Options: args beginning with '-'. We identify two kinds:
// 2.1: Flags: boolean options => (exist ? true : false)
// 2.2: Parameters: a name followed by a non-option value
#if !defined(__GNUC__) || (__GNUC__ >= 5)
using string_stream = std::istringstream;
#else
// Until GCC 5, istringstream did not have a move constructor.
// stringstream_proxy is used instead, as a workaround.
class stringstream_proxy
{
public:
stringstream_proxy() = default;
// Construct with a value.
stringstream_proxy(std::string const& value) :
stream_(value)
{}
// Copy constructor.
stringstream_proxy(const stringstream_proxy& other) :
stream_(other.stream_.str())
{
stream_.setstate(other.stream_.rdstate());
}
void setstate(std::ios_base::iostate state) { stream_.setstate(state); }
// Stream out the value of the parameter.
// If the conversion was not possible, the stream will enter the fail state,
// and operator bool will return false.
template<typename T>
stringstream_proxy& operator >> (T& thing)
{
stream_ >> thing;
return *this;
}
// Get the string value.
std::string str() const { return stream_.str(); }
std::stringbuf* rdbuf() const { return stream_.rdbuf(); }
// Check the state of the stream.
// False when the most recent stream operation failed
operator bool() const { return !!stream_; }
~stringstream_proxy() = default;
private:
std::istringstream stream_;
};
using string_stream = stringstream_proxy;
#endif
class parser
{
public:
enum Mode { PREFER_FLAG_FOR_UNREG_OPTION = 1 << 0,
PREFER_PARAM_FOR_UNREG_OPTION = 1 << 1,
NO_SPLIT_ON_EQUALSIGN = 1 << 2,
SINGLE_DASH_IS_MULTIFLAG = 1 << 3,
};
parser() = default;
parser(std::initializer_list<char const* const> pre_reg_names)
{ add_params(pre_reg_names); }
parser(const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION)
{ parse(argv, mode); }
parser(int argc, const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION)
{ parse(argc, argv, mode); }
void add_param(std::string const& name);
void add_params(std::initializer_list<char const* const> init_list);
void parse(const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION);
void parse(int argc, const char* const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION);
std::multiset<std::string> const& flags() const { return flags_; }
std::map<std::string, std::string> const& params() const { return params_; }
std::vector<std::string> const& pos_args() const { return pos_args_; }
// begin() and end() for using range-for over positional args.
std::vector<std::string>::const_iterator begin() const { return pos_args_.cbegin(); }
std::vector<std::string>::const_iterator end() const { return pos_args_.cend(); }
size_t size() const { return pos_args_.size(); }
//////////////////////////////////////////////////////////////////////////
// Accessors
// flag (boolean) accessors: return true if the flag appeared, otherwise false.
bool operator[](std::string const& name) const;
// multiple flag (boolean) accessors: return true if at least one of the flag appeared, otherwise false.
bool operator[](std::initializer_list<char const* const> init_list) const;
// returns positional arg string by order. Like argv[] but without the options
std::string const& operator[](size_t ind) const;
// returns a std::istream that can be used to convert a positional arg to a typed value.
string_stream operator()(size_t ind) const;
// same as above, but with a default value in case the arg is missing (index out of range).
template<typename T>
string_stream operator()(size_t ind, T&& def_val) const;
// parameter accessors, give a name get an std::istream that can be used to convert to a typed value.
// call .str() on result to get as string
string_stream operator()(std::string const& name) const;
// accessor for a parameter with multiple names, give a list of names, get an std::istream that can be used to convert to a typed value.
// call .str() on result to get as string
// returns the first value in the list to be found.
string_stream operator()(std::initializer_list<char const* const> init_list) const;
// same as above, but with a default value in case the param was missing.
// Non-string def_val types must have an operator<<() (output stream operator)
// If T only has an input stream operator, pass the string version of the type as in "3" instead of 3.
template<typename T>
string_stream operator()(std::string const& name, T&& def_val) const;
// same as above but for a list of names. returns the first value to be found.
template<typename T>
string_stream operator()(std::initializer_list<char const* const> init_list, T&& def_val) const;
private:
string_stream bad_stream() const;
std::string trim_leading_dashes(std::string const& name) const;
bool is_number(std::string const& arg) const;
bool is_option(std::string const& arg) const;
bool got_flag(std::string const& name) const;
bool is_param(std::string const& name) const;
private:
std::vector<std::string> args_;
std::map<std::string, std::string> params_;
std::vector<std::string> pos_args_;
std::multiset<std::string> flags_;
std::set<std::string> registeredParams_;
std::string empty_;
};
//////////////////////////////////////////////////////////////////////////
inline void parser::parse(const char * const argv[], int mode)
{
int argc = 0;
for (auto argvp = argv; *argvp; ++argc, ++argvp);
parse(argc, argv, mode);
}
//////////////////////////////////////////////////////////////////////////
inline void parser::parse(int argc, const char* const argv[], int mode /*= PREFER_FLAG_FOR_UNREG_OPTION*/)
{
// convert to strings
args_.resize(argc);
std::transform(argv, argv + argc, args_.begin(), [](const char* const arg) { return arg; });
// parse line
for (auto i = 0u; i < args_.size(); ++i)
{
if (!is_option(args_[i]))
{
pos_args_.emplace_back(args_[i]);
continue;
}
auto name = trim_leading_dashes(args_[i]);
if (!(mode & NO_SPLIT_ON_EQUALSIGN))
{
auto equalPos = name.find('=');
if (equalPos != std::string::npos)
{
params_.insert({ name.substr(0, equalPos), name.substr(equalPos + 1) });
continue;
}
}
// if the option is unregistered and should be a multi-flag
if (1 == (args_[i].size() - name.size()) && // single dash
argh::parser::SINGLE_DASH_IS_MULTIFLAG & mode && // multi-flag mode
!is_param(name)) // unregistered
{
std::string keep_param;
if (!name.empty() && is_param(std::string(1ul, name.back()))) // last char is param
{
keep_param += name.back();
name.resize(name.size() - 1);
}
for (auto const& c : name)
{
flags_.emplace(std::string{ c });
}
if (!keep_param.empty())
{
name = keep_param;
}
else
{
continue; // do not consider other options for this arg
}
}
// any potential option will get as its value the next arg, unless that arg is an option too
// in that case it will be determined a flag.
if (i == args_.size() - 1 || is_option(args_[i + 1]))
{
flags_.emplace(name);
continue;
}
// if 'name' is a pre-registered option, then the next arg cannot be a free parameter to it is skipped
// otherwise we have 2 modes:
// PREFER_FLAG_FOR_UNREG_OPTION: a non-registered 'name' is determined a flag.
// The following value (the next arg) will be a free parameter.
//
// PREFER_PARAM_FOR_UNREG_OPTION: a non-registered 'name' is determined a parameter, the next arg
// will be the value of that option.
assert(!(mode & argh::parser::PREFER_FLAG_FOR_UNREG_OPTION)
|| !(mode & argh::parser::PREFER_PARAM_FOR_UNREG_OPTION));
bool preferParam = mode & argh::parser::PREFER_PARAM_FOR_UNREG_OPTION;
if (is_param(name) || preferParam)
{
params_.insert({ name, args_[i + 1] });
++i; // skip next value, it is not a free parameter
continue;
}
else
{
flags_.emplace(name);
}
};
}
//////////////////////////////////////////////////////////////////////////
inline string_stream parser::bad_stream() const
{
string_stream bad;
bad.setstate(std::ios_base::failbit);
return bad;
}
//////////////////////////////////////////////////////////////////////////
inline bool parser::is_number(std::string const& arg) const
{
// inefficient but simple way to determine if a string is a number (which can start with a '-')
std::istringstream istr(arg);
double number;
istr >> number;
return !(istr.fail() || istr.bad());
}
//////////////////////////////////////////////////////////////////////////
inline bool parser::is_option(std::string const& arg) const
{
assert(0 != arg.size());
if (is_number(arg))
return false;
return '-' == arg[0];
}
//////////////////////////////////////////////////////////////////////////
inline std::string parser::trim_leading_dashes(std::string const& name) const
{
auto pos = name.find_first_not_of('-');
return std::string::npos != pos ? name.substr(pos) : name;
}
//////////////////////////////////////////////////////////////////////////
inline bool argh::parser::got_flag(std::string const& name) const
{
return flags_.end() != flags_.find(trim_leading_dashes(name));
}
//////////////////////////////////////////////////////////////////////////
inline bool argh::parser::is_param(std::string const& name) const
{
return registeredParams_.count(name);
}
//////////////////////////////////////////////////////////////////////////
inline bool parser::operator[](std::string const& name) const
{
return got_flag(name);
}
//////////////////////////////////////////////////////////////////////////
inline bool parser::operator[](std::initializer_list<char const* const> init_list) const
{
return std::any_of(init_list.begin(), init_list.end(), [&](char const* const name) { return got_flag(name); });
}
//////////////////////////////////////////////////////////////////////////
inline std::string const& parser::operator[](size_t ind) const
{
if (ind < pos_args_.size())
return pos_args_[ind];
return empty_;
}
//////////////////////////////////////////////////////////////////////////
inline string_stream parser::operator()(std::string const& name) const
{
auto optIt = params_.find(trim_leading_dashes(name));
if (params_.end() != optIt)
return string_stream(optIt->second);
return bad_stream();
}
//////////////////////////////////////////////////////////////////////////
inline string_stream parser::operator()(std::initializer_list<char const* const> init_list) const
{
for (auto& name : init_list)
{
auto optIt = params_.find(trim_leading_dashes(name));
if (params_.end() != optIt)
return string_stream(optIt->second);
}
return bad_stream();
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
string_stream parser::operator()(std::string const& name, T&& def_val) const
{
auto optIt = params_.find(trim_leading_dashes(name));
if (params_.end() != optIt)
return string_stream(optIt->second);
std::ostringstream ostr;
ostr.precision(std::numeric_limits<long double>::max_digits10);
ostr << def_val;
return string_stream(ostr.str()); // use default
}
//////////////////////////////////////////////////////////////////////////
// same as above but for a list of names. returns the first value to be found.
template<typename T>
string_stream parser::operator()(std::initializer_list<char const* const> init_list, T&& def_val) const
{
for (auto& name : init_list)
{
auto optIt = params_.find(trim_leading_dashes(name));
if (params_.end() != optIt)
return string_stream(optIt->second);
}
std::ostringstream ostr;
ostr.precision(std::numeric_limits<long double>::max_digits10);
ostr << def_val;
return string_stream(ostr.str()); // use default
}
//////////////////////////////////////////////////////////////////////////
inline string_stream parser::operator()(size_t ind) const
{
if (pos_args_.size() <= ind)
return bad_stream();
return string_stream(pos_args_[ind]);
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
string_stream parser::operator()(size_t ind, T&& def_val) const
{
if (pos_args_.size() <= ind)
{
std::ostringstream ostr;
ostr.precision(std::numeric_limits<long double>::max_digits10);
ostr << def_val;
return string_stream(ostr.str());
}
return string_stream(pos_args_[ind]);
}
//////////////////////////////////////////////////////////////////////////
inline void parser::add_param(std::string const& name)
{
registeredParams_.insert(trim_leading_dashes(name));
}
//////////////////////////////////////////////////////////////////////////
inline void parser::add_params(std::initializer_list<char const* const> init_list)
{
for (auto& name : init_list)
registeredParams_.insert(trim_leading_dashes(name));
}
}
-193
View File
@@ -1,193 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <fmt/format.h>
#include "eqemu_command_handler.h"
#include "terminal_color.hpp"
#include "../platform.h"
namespace EQEmuCommand {
std::map<std::string, void (*)(
int argc,
char **argv,
argh::parser &cmd,
std::string &description
)> function_map;
/**
* @param cmd
*/
void DisplayDebug(argh::parser &cmd)
{
if (cmd[{"-d", "--debug"}]) {
std::cout << "Positional args:\n";
for (auto &pos_arg : cmd)
std::cout << '\t' << pos_arg << std::endl;
std::cout << "Positional args:\n";
for (auto &pos_arg : cmd.pos_args())
std::cout << '\t' << pos_arg << std::endl;
std::cout << "\nFlags:\n";
for (auto &flag : cmd.flags())
std::cout << '\t' << flag << std::endl;
std::cout << "\nParameters:\n";
for (auto &param : cmd.params())
std::cout << '\t' << param.first << " : " << param.second << std::endl;
}
}
/**
* @param arguments
* @param options
* @param cmd
* @param argc
* @param argv
*/
void ValidateCmdInput(
std::vector<std::string> &arguments,
std::vector<std::string> &options,
argh::parser &cmd,
int argc,
char **argv
)
{
bool arguments_filled = true;
for (auto &arg : arguments) {
if (cmd(arg).str().empty()) {
arguments_filled = false;
}
}
if (!arguments_filled || argc == 2) {
std::string arguments_string;
for (auto &arg : arguments) {
arguments_string += " " + arg + "=*\n";
}
std::string options_string;
for (auto &opt : options) {
options_string += " " + opt + "\n";
}
std::cout << fmt::format(
"Command\n\n{0} \n\nArgs\n{1}\nOptions\n{2}",
argv[1],
arguments_string,
options_string
) << std::endl;
exit(1);
}
}
/**
* @param in_function_map
* @param cmd
* @param argc
* @param argv
*/
void HandleMenu(
std::map<std::string, void (*)(
int argc,
char **argv,
argh::parser &cmd,
std::string &description
)> &in_function_map,
argh::parser &cmd,
int argc,
char **argv
)
{
std::string description;
bool ran_command = false;
for (auto &it: in_function_map) {
if (it.first == argv[1]) {
std::cout << std::endl;
std::cout << "> " << termcolor::cyan << "Executing CLI Command" << termcolor::reset << std::endl;
std::cout << std::endl;
(it.second)(argc, argv, cmd, description);
ran_command = true;
}
}
if (cmd[{"-h", "--help"}]) {
std::cout << std::endl;
std::cout <<
"> " <<
termcolor::yellow <<
"EQEmulator [" + GetPlatformName() + "] CLI Menu" <<
termcolor::reset
<< std::endl
<< std::endl;
/**
* Get max command length for padding length
*/
int max_command_length = 0;
for (auto &it: in_function_map) {
std::stringstream command;
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
if (command.str().length() > max_command_length) {
max_command_length = command.str().length() + 1;
}
}
/**
* Display command menu
*/
std::string command_section;
for (auto &it: in_function_map) {
description = "";
(it.second)(argc, argv, cmd, description);
/**
* Print section header
*/
std::string command_prefix = it.first.substr(0, it.first.find(":"));
if (command_section != command_prefix) {
command_section = command_prefix;
std::cout << termcolor::reset << command_prefix << std::endl;
}
/**
* Print commands
*/
std::stringstream command;
command << termcolor::colorize << termcolor::yellow << it.first << termcolor::reset;
printf(" %-*s %s\n", max_command_length, command.str().c_str(), description.c_str());
}
std::cout << std::endl;
}
else if (!ran_command) {
std::cerr << "Unknown command [" << argv[1] << "] ! Try --help" << std::endl;
}
exit(1);
}
}
-75
View File
@@ -1,75 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_EQEMU_COMMAND_HANDLER_H
#define EQEMU_EQEMU_COMMAND_HANDLER_H
#include "argh.h"
namespace EQEmuCommand {
extern std::map<std::string, void (*)(
int argc,
char **argv,
argh::parser &cmd,
std::string &description
)> function_map;
/**
* @param arguments
* @param options
* @param cmd
* @param argc
* @param argv
*/
void ValidateCmdInput(
std::vector<std::string> &arguments,
std::vector<std::string> &options,
argh::parser &cmd,
int argc,
char **argv
);
/**
* @param cmd
*/
void DisplayDebug(argh::parser &cmd);
/**
* @param in_function_map
* @param cmd
* @param argc
* @param argv
*/
void HandleMenu(
std::map<std::string, void (*)(
int argc,
char **argv,
argh::parser &cmd,
std::string &description
)> &in_function_map,
argh::parser &cmd,
int argc,
char **argv
);
};
#endif //EQEMU_EQEMU_COMMAND_HANDLER_H
-557
View File
@@ -1,557 +0,0 @@
//!
//! termcolor
//! ~~~~~~~~~
//!
//! termcolor is a header-only c++ library for printing colored messages
//! to the terminal. Written just for fun with a help of the Force.
//!
//! :copyright: (c) 2013 by Ihor Kalnytskyi
//! :license: BSD, see LICENSE for details
//!
#ifndef TERMCOLOR_HPP_
#define TERMCOLOR_HPP_
// the following snippet of code detects the current OS and
// defines the appropriate macro that is used to wrap some
// platform specific things
#if defined(_WIN32) || defined(_WIN64)
# define TERMCOLOR_OS_WINDOWS
#elif defined(__APPLE__)
# define TERMCOLOR_OS_MACOS
#elif defined(__unix__) || defined(__unix)
# define TERMCOLOR_OS_LINUX
#else
# error unsupported platform
#endif
// This headers provides the `isatty()`/`fileno()` functions,
// which are used for testing whether a standart stream refers
// to the terminal. As for Windows, we also need WinApi funcs
// for changing colors attributes of the terminal.
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
# include <unistd.h>
#elif defined(TERMCOLOR_OS_WINDOWS)
# include <io.h>
# include <windows.h>
#endif
#include <iostream>
#include <cstdio>
namespace termcolor
{
// Forward declaration of the `_internal` namespace.
// All comments are below.
namespace _internal
{
// An index to be used to access a private storage of I/O streams. See
// colorize / nocolorize I/O manipulators for details.
static int colorize_index = std::ios_base::xalloc();
inline FILE* get_standard_stream(const std::ostream& stream);
inline bool is_colorized(std::ostream& stream);
inline bool is_atty(const std::ostream& stream);
#if defined(TERMCOLOR_OS_WINDOWS)
inline void win_change_attributes(std::ostream& stream, int foreground, int background=-1);
#endif
}
inline
std::ostream& colorize(std::ostream& stream)
{
stream.iword(_internal::colorize_index) = 1L;
return stream;
}
inline
std::ostream& nocolorize(std::ostream& stream)
{
stream.iword(_internal::colorize_index) = 0L;
return stream;
}
inline
std::ostream& reset(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;00m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, -1);
#endif
}
return stream;
}
inline
std::ostream& bold(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;1m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& dark(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;2m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& underline(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;4m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& blink(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;5m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& reverse(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;7m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& concealed(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;8m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& grey(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;30m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
0 // grey (black)
);
#endif
}
return stream;
}
inline
std::ostream& red(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;31m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& green(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;32m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_GREEN
);
#endif
}
return stream;
}
inline
std::ostream& yellow(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;33m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_GREEN | FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& blue(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;34m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE
);
#endif
}
return stream;
}
inline
std::ostream& magenta(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;35m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& cyan(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;36m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_GREEN
);
#endif
}
return stream;
}
inline
std::ostream& white(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;37m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_grey(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;40m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
0 // grey (black)
);
#endif
}
return stream;
}
inline
std::ostream& on_red(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;41m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_green(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;42m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN
);
#endif
}
return stream;
}
inline
std::ostream& on_yellow(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;43m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_blue(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;44m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_BLUE
);
#endif
}
return stream;
}
inline
std::ostream& on_magenta(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;45m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_BLUE | BACKGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_cyan(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;46m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_BLUE
);
#endif
}
return stream;
}
inline
std::ostream& on_white(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\e[1;47m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
);
#endif
}
return stream;
}
//! Since C++ hasn't a way to hide something in the header from
//! the outer access, I have to introduce this namespace which
//! is used for internal purpose and should't be access from
//! the user code.
namespace _internal
{
//! Since C++ hasn't a true way to extract stream handler
//! from the a given `std::ostream` object, I have to write
//! this kind of hack.
inline
FILE* get_standard_stream(const std::ostream& stream)
{
if (&stream == &std::cout)
return stdout;
else if ((&stream == &std::cerr) || (&stream == &std::clog))
return stderr;
return 0;
}
// Say whether a given stream should be colorized or not. It's always
// true for ATTY streams and may be true for streams marked with
// colorize flag.
inline
bool is_colorized(std::ostream& stream)
{
return is_atty(stream) || static_cast<bool>(stream.iword(colorize_index));
}
//! Test whether a given `std::ostream` object refers to
//! a terminal.
inline
bool is_atty(const std::ostream& stream)
{
FILE* std_stream = get_standard_stream(stream);
// Unfortunately, fileno() ends with segmentation fault
// if invalid file descriptor is passed. So we need to
// handle this case gracefully and assume it's not a tty
// if standard stream is not detected, and 0 is returned.
if (!std_stream)
return false;
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
return ::isatty(fileno(std_stream));
#elif defined(TERMCOLOR_OS_WINDOWS)
return ::_isatty(_fileno(std_stream));
#endif
}
#if defined(TERMCOLOR_OS_WINDOWS)
//! Change Windows Terminal colors attribute. If some
//! parameter is `-1` then attribute won't changed.
inline void win_change_attributes(std::ostream& stream, int foreground, int background)
{
// yeah, i know.. it's ugly, it's windows.
static WORD defaultAttributes = 0;
// Windows doesn't have ANSI escape sequences and so we use special
// API to change Terminal output color. That means we can't
// manipulate colors by means of "std::stringstream" and hence
// should do nothing in this case.
if (!_internal::is_atty(stream))
return;
// get terminal handle
HANDLE hTerminal = INVALID_HANDLE_VALUE;
if (&stream == &std::cout)
hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
else if (&stream == &std::cerr)
hTerminal = GetStdHandle(STD_ERROR_HANDLE);
// save default terminal attributes if it unsaved
if (!defaultAttributes)
{
CONSOLE_SCREEN_BUFFER_INFO info;
if (!GetConsoleScreenBufferInfo(hTerminal, &info))
return;
defaultAttributes = info.wAttributes;
}
// restore all default settings
if (foreground == -1 && background == -1)
{
SetConsoleTextAttribute(hTerminal, defaultAttributes);
return;
}
// get current settings
CONSOLE_SCREEN_BUFFER_INFO info;
if (!GetConsoleScreenBufferInfo(hTerminal, &info))
return;
if (foreground != -1)
{
info.wAttributes &= ~(info.wAttributes & 0x0F);
info.wAttributes |= static_cast<WORD>(foreground);
}
if (background != -1)
{
info.wAttributes &= ~(info.wAttributes & 0xF0);
info.wAttributes |= static_cast<WORD>(background);
}
SetConsoleTextAttribute(hTerminal, info.wAttributes);
}
#endif // TERMCOLOR_OS_WINDOWS
} // namespace _internal
} // namespace termcolor
#undef TERMCOLOR_OS_WINDOWS
#undef TERMCOLOR_OS_MACOS
#undef TERMCOLOR_OS_LINUX
#endif // TERMCOLOR_HPP_
-82
View File
@@ -1,82 +0,0 @@
#include "global_define.h"
#include "types.h"
#include <string.h>
#include <zlib.h>
namespace EQEmu
{
uint32 EstimateDeflateBuffer(uint32 len) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
if (deflateInit(&zstream, Z_FINISH) != Z_OK)
return 0;
return deflateBound(&zstream, len);
}
uint32 DeflateData(const char *buffer, uint32 len, char *out_buffer, uint32 out_len_max) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
int zerror;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);
zstream.avail_out = out_len_max;
zerror = deflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END)
{
deflateEnd(&zstream);
return (uint32)zstream.total_out;
}
else
{
zerror = deflateEnd(&zstream);
return 0;
}
}
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max) {
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);;
zstream.avail_out = out_len_max;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
i = inflateInit2(&zstream, 15);
if (i != Z_OK) {
return 0;
}
zerror = inflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END) {
inflateEnd(&zstream);
return zstream.total_out;
}
else {
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd(&zstream);
return 0;
}
}
}
-8
View File
@@ -1,8 +0,0 @@
#pragma once
namespace EQEmu
{
uint32 EstimateDeflateBuffer(uint32 len);
uint32 DeflateData(const char *buffer, uint32 len, char *out_buffer, uint32 out_len_max);
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max);
}
+1 -54
View File
@@ -111,60 +111,7 @@ void set_exception_handler() {
SetUnhandledExceptionFilter(windows_exception_handler); SetUnhandledExceptionFilter(windows_exception_handler);
} }
#else #else
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/fcntl.h>
void print_trace()
{
auto uid = geteuid();
std::string temp_output_file = "/tmp/dump-output";
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)] = 0;
int child_pid = fork();
if (!child_pid) {
int fd = open(temp_output_file.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // redirect output to stderr
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
if (uid == 0) {
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
}
else {
execlp("sudo", "gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
}
close(fd);
abort(); /* If gdb failed to start */
}
else {
waitpid(child_pid, NULL, 0);
}
std::ifstream input(temp_output_file);
for (std::string line; getline(input, line);) {
LogCrash("{}", line);
}
std::remove(temp_output_file.c_str());
exit(1);
}
// crash is off or an unhandled platform // crash is off or an unhandled platform
void set_exception_handler() void set_exception_handler() {
{
signal(SIGABRT, reinterpret_cast<void (*)(int)>(print_trace));
signal(SIGFPE, reinterpret_cast<void (*)(int)>(print_trace));
signal(SIGFPE, reinterpret_cast<void (*)(int)>(print_trace));
signal(SIGSEGV, reinterpret_cast<void (*)(int)>(print_trace));
} }
#endif #endif
+36 -38
View File
@@ -1,57 +1,55 @@
/** /* EQEMu: Everquest Server Emulator
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#pragma once Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program 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; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMMON_DATA_VERIFICATION_H
#define COMMON_DATA_VERIFICATION_H
#include <algorithm> #include <algorithm>
#include <cmath>
namespace EQEmu {
template<typename T> namespace EQEmu
T Clamp(const T &value, const T &lower, const T &upper) {
{ template <typename T>
T Clamp(const T& value, const T& lower, const T& upper) {
return std::max(lower, std::min(value, upper)); return std::max(lower, std::min(value, upper));
} }
template<typename T> template <typename T>
T ClampLower(const T &value, const T &lower) T ClampLower(const T& value, const T& lower) {
{
return std::max(lower, value); return std::max(lower, value);
} }
template<typename T> template <typename T>
T ClampUpper(const T &value, const T &upper) T ClampUpper(const T& value, const T& upper) {
{
return std::min(value, upper); return std::min(value, upper);
} }
template<typename T> template <typename T>
bool ValueWithin(const T &value, const T &lower, const T &upper) bool ValueWithin(const T& value, const T& lower, const T& upper) {
{
return value >= lower && value <= upper; return value >= lower && value <= upper;
} }
template<typename T1, typename T2, typename T3> template <typename T1, typename T2, typename T3>
bool ValueWithin(const T1 &value, const T2 &lower, const T3 &upper) bool ValueWithin(const T1& value, const T2& lower, const T3& upper) {
{ return value >= (T1)lower && value <= (T1)upper;
return value >= (T1) lower && value <= (T1) upper;
} }
} /*EQEmu*/ } /*EQEmu*/
#endif /*COMMON_DATA_VERIFICATION_H*/
+103 -221
View File
@@ -64,11 +64,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c
uint32 errnum= 0; uint32 errnum= 0;
char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf[MYSQL_ERRMSG_SIZE];
if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { if (!Open(host, user, passwd, database, port, &errnum, errbuf)) {
LogError("Failed to connect to database: Error: {}", errbuf); Log(Logs::General, Logs::Error, "Failed to connect to database: Error: %s", errbuf);
return false; return false;
} }
else { else {
LogInfo("Using database [{}] at [{}]:[{}]", database, host,port); Log(Logs::General, Logs::Status, "Using database '%s' at %s:%d", database, host,port);
return true; return true;
} }
} }
@@ -86,7 +86,7 @@ Database::~Database()
Return the account id or zero if no account matches. Return the account id or zero if no account matches.
Zero will also be returned if there is a database error. Zero will also be returned if there is a database error.
*/ */
uint32 Database::CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus) { uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) {
if(strlen(name) >= 50 || strlen(password) >= 50) if(strlen(name) >= 50 || strlen(password) >= 50)
return(0); return(0);
@@ -97,10 +97,9 @@ uint32 Database::CheckLogin(const char* name, const char* password, const char *
DoEscapeString(tmpUN, name, strlen(name)); DoEscapeString(tmpUN, name, strlen(name));
DoEscapeString(tmpPW, password, strlen(password)); DoEscapeString(tmpPW, password, strlen(password));
std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND ls_id='%s' AND password is not null " std::string query = StringFormat("SELECT id, status FROM account WHERE name='%s' AND password is not null "
"and length(password) > 0 and (password='%s' or password=MD5('%s'))", "and length(password) > 0 and (password='%s' or password=MD5('%s'))",
tmpUN, EscapeString(loginserver).c_str(), tmpPW, tmpPW); tmpUN, tmpPW, tmpPW);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
@@ -172,87 +171,61 @@ void Database::LoginIP(uint32 AccountID, const char* LoginIP) {
QueryDatabase(query); QueryDatabase(query);
} }
int16 Database::CheckStatus(uint32 account_id) int16 Database::CheckStatus(uint32 account_id) {
{ std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`"
std::string query = StringFormat( " FROM `account` WHERE `id` = %i", account_id);
"SELECT `status`, TIMESTAMPDIFF(SECOND, NOW(), `suspendeduntil`) FROM `account` WHERE `id` = %i",
account_id);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success()) {
return 0; return 0;
}
if (results.RowCount() != 1) if (results.RowCount() != 1)
return 0; return 0;
auto row = results.begin(); auto row = results.begin();
int16 status = atoi(row[0]); int16 status = atoi(row[0]);
int32 date_diff = 0; int32 suspendeduntil = 0;
if (row[1] != nullptr) // MariaDB initalizes with NULL if unix_timestamp() is out of range
date_diff = atoi(row[1]); if (row[1] != nullptr) {
suspendeduntil = atoi(row[1]);
}
if (date_diff > 0) int32 current = atoi(row[2]);
if(suspendeduntil > current)
return -1; return -1;
return status; return status;
} }
/** uint32 Database::CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id) {
* @param name
* @param password
* @param status
* @param loginserver
* @param lsaccount_id
* @return
*/
uint32 Database::CreateAccount(
const char *name,
const char *password,
int16 status,
const char *loginserver,
uint32 lsaccount_id
)
{
std::string query; std::string query;
if (password) { if (password)
query = StringFormat( query = StringFormat("INSERT INTO account SET name='%s', password='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name,password,status, lsaccount_id);
"INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();", else
name, query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id);
password,
status,
loginserver,
lsaccount_id
);
}
else {
query = StringFormat(
"INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
name,
status,
loginserver,
lsaccount_id
);
}
LogInfo("Account Attempting to be created: [{0}:{1}] status: {2}", loginserver, name, status); Log(Logs::General, Logs::World_Server, "Account Attempting to be created: '%s' status: %i", name, status);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return 0; return 0;
} }
if (results.LastInsertedID() == 0) { if (results.LastInsertedID() == 0)
{
return 0; return 0;
} }
return results.LastInsertedID(); return results.LastInsertedID();
} }
bool Database::DeleteAccount(const char* name, const char *loginserver) { bool Database::DeleteAccount(const char* name) {
std::string query = StringFormat("DELETE FROM account WHERE name='%s' AND ls_id='%s'", name, loginserver); std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name);
LogInfo("Account Attempting to be deleted:'[{}]:[{}]'", loginserver, name); Log(Logs::General, Logs::World_Server, "Account Attempting to be deleted:'%s'", name);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@@ -299,7 +272,7 @@ bool Database::ReserveName(uint32 account_id, char* name) {
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
if (row[0] && atoi(row[0]) > 0){ if (row[0] && atoi(row[0]) > 0){
LogInfo("Account: [{}] tried to request name: [{}], but it is already taken", account_id, name); Log(Logs::General, Logs::World_Server, "Account: %i tried to request name: %s, but it is already taken...", account_id, name);
return false; return false;
} }
} }
@@ -317,17 +290,17 @@ bool Database::ReserveName(uint32 account_id, char* name) {
bool Database::DeleteCharacter(char *name) { bool Database::DeleteCharacter(char *name) {
uint32 charid = 0; uint32 charid = 0;
if(!name || !strlen(name)) { if(!name || !strlen(name)) {
LogInfo("DeleteCharacter: request to delete without a name (empty char slot)"); Log(Logs::General, Logs::World_Server, "DeleteCharacter: request to delete without a name (empty char slot)");
return false; return false;
} }
LogInfo("Database::DeleteCharacter name : [{}]", name); Log(Logs::General, Logs::World_Server, "Database::DeleteCharacter name : '%s'", name);
/* Get id from character_data before deleting record so we can clean up the rest of the tables */ /* Get id from character_data before deleting record so we can clean up the rest of the tables */
std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name); std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); } for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); }
if (charid <= 0){ if (charid <= 0){
LogError("Database::DeleteCharacter :: Character ({}) not found, stopping delete...", name); Log(Logs::General, Logs::Error, "Database::DeleteCharacter :: Character (%s) not found, stopping delete...", name);
return false; return false;
} }
@@ -714,7 +687,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, EQEmu
charid = GetCharacterID(pp->name); charid = GetCharacterID(pp->name);
if(!charid) { if(!charid) {
LogError("StoreCharacter: no character id"); Log(Logs::General, Logs::Error, "StoreCharacter: no character id");
return false; return false;
} }
@@ -735,7 +708,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, EQEmu
/* Insert starting inventory... */ /* Insert starting inventory... */
std::string invquery; std::string invquery;
for (int16 i = EQEmu::invslot::EQUIPMENT_BEGIN; i <= EQEmu::invbag::BANK_BAGS_END;) { for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::BANK_BAGS_END;) {
const EQEmu::ItemInstance* newinv = inv->GetItem(i); const EQEmu::ItemInstance* newinv = inv->GetItem(i);
if (newinv) { if (newinv) {
invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)",
@@ -744,16 +717,16 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, EQEmu
auto results = QueryDatabase(invquery); auto results = QueryDatabase(invquery);
} }
if (i == EQEmu::invslot::slotCursor) { if (i == EQEmu::inventory::slotCursor) {
i = EQEmu::invbag::GENERAL_BAGS_BEGIN; i = EQEmu::legacy::GENERAL_BAGS_BEGIN;
continue; continue;
} }
else if (i == EQEmu::invbag::CURSOR_BAG_END) { else if (i == EQEmu::legacy::CURSOR_BAG_END) {
i = EQEmu::invslot::BANK_BEGIN; i = EQEmu::legacy::BANK_BEGIN;
continue; continue;
} }
else if (i == EQEmu::invslot::BANK_END) { else if (i == EQEmu::legacy::BANK_END) {
i = EQEmu::invbag::BANK_BAGS_BEGIN; i = EQEmu::legacy::BANK_BAGS_BEGIN;
continue; continue;
} }
i++; i++;
@@ -815,12 +788,11 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) {
return atoi(row[0]); return atoi(row[0]);
} }
uint32 Database::GetAccountIDByName(const char* accname, const char *loginserver, int16* status, uint32* lsid) { uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* lsid) {
if (!isAlphaNumeric(accname)) if (!isAlphaNumeric(accname))
return 0; return 0;
std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' AND `ls_id`='%s' LIMIT 1", std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' LIMIT 1", accname);
EscapeString(accname).c_str(), EscapeString(loginserver).c_str());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@@ -949,6 +921,18 @@ bool Database::SetVariable(const std::string varname, const std::string &varvalu
return true; return true;
} }
uint32 Database::GetMiniLoginAccount(char* ip)
{
std::string query = StringFormat("SELECT `id` FROM `account` WHERE `minilogin_ip` = '%s'", ip);
auto results = QueryDatabase(query);
if (!results.Success())
return 0;
auto row = results.begin();
return atoi(row[0]);
}
// Get zone starting points from DB // Get zone starting points from DB
bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) { bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe_x, float* safe_y, float* safe_z, int16* minstatus, uint8* minlevel, char *flag_needed) {
@@ -1210,46 +1194,25 @@ bool Database::AddToNameFilter(const char* name) {
return true; return true;
} }
/** uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) {
* @param in_loginserver_id
* @param in_loginserver_account_id
* @param in_account_name
* @param in_status
* @return
*/
uint32 Database::GetAccountIDFromLSID(
const std::string &in_loginserver_id,
uint32 in_loginserver_account_id,
char *in_account_name,
int16 *in_status
)
{
uint32 account_id = 0; uint32 account_id = 0;
auto query = fmt::format( std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID);
"SELECT id, name, status FROM account WHERE lsaccount_id = {0} AND ls_id = '{1}'",
in_loginserver_account_id,
in_loginserver_id
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return 0; return 0;
} }
if (results.RowCount() != 1) { if (results.RowCount() != 1)
return 0; return 0;
}
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
account_id = std::stoi(row[0]); account_id = atoi(row[0]);
if (in_account_name) { if (oAccountName)
strcpy(in_account_name, row[1]); strcpy(oAccountName, row[1]);
} if (oStatus)
if (in_status) { *oStatus = atoi(row[2]);
*in_status = std::stoi(row[2]);
}
} }
return account_id; return account_id;
@@ -1445,46 +1408,32 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16
return base_cap; return base_cap;
} }
uint32 Database::GetCharacterInfo( uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZoneID, uint32* oInstanceID, float* oX, float* oY, float* oZ) {
const char *iName, std::string query = StringFormat("SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'", iName);
uint32 *oAccID,
uint32 *oZoneID,
uint32 *oInstanceID,
float *oX,
float *oY,
float *oZ
)
{
std::string query = StringFormat(
"SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'",
EscapeString(iName).c_str()
);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
return 0; return 0;
} }
if (results.RowCount() != 1) { if (results.RowCount() != 1)
return 0; return 0;
}
auto row = results.begin(); auto row = results.begin();
uint32 charid = atoi(row[0]); uint32 charid = atoi(row[0]);
if (oAccID) { *oAccID = atoi(row[1]); } if (oAccID){ *oAccID = atoi(row[1]); }
if (oZoneID) { *oZoneID = atoi(row[2]); } if (oZoneID){ *oZoneID = atoi(row[2]); }
if (oInstanceID) { *oInstanceID = atoi(row[3]); } if (oInstanceID){ *oInstanceID = atoi(row[3]); }
if (oX) { *oX = atof(row[4]); } if (oX){ *oX = atof(row[4]); }
if (oY) { *oY = atof(row[5]); } if (oY){ *oY = atof(row[5]); }
if (oZ) { *oZ = atof(row[6]); } if (oZ){ *oZ = atof(row[6]); }
return charid; return charid;
} }
bool Database::UpdateLiveChar(char* charname, uint32 account_id) { bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) {
std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;", charname, account_id); std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id);
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()){ if (!results.Success()){
@@ -1551,7 +1500,7 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
LogError("Error deleting character from group id: {}", results.ErrorMessage().c_str()); Log(Logs::General, Logs::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str());
return; return;
} }
@@ -1594,7 +1543,7 @@ uint32 Database::GetGroupID(const char* name){
if (results.RowCount() == 0) if (results.RowCount() == 0)
{ {
// Commenting this out until logging levels can prevent this from going to console // Commenting this out until logging levels can prevent this from going to console
//LogDebug(, "Character not in a group: [{}]", name); //Log(Logs::General, Logs::None,, "Character not in a group: %s", name);
return 0; return 0;
} }
@@ -1641,7 +1590,7 @@ void Database::SetGroupLeaderName(uint32 gid, const char* name) {
result = QueryDatabase(query); result = QueryDatabase(query);
if(!result.Success()) { if(!result.Success()) {
LogDebug("Error in Database::SetGroupLeaderName: [{}]", result.ErrorMessage().c_str()); Log(Logs::General, Logs::None, "Error in Database::SetGroupLeaderName: %s", result.ErrorMessage().c_str());
} }
} }
@@ -1803,15 +1752,6 @@ void Database::ClearRaidDetails(uint32 rid) {
std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl; std::cout << "Unable to clear raid details: " << results.ErrorMessage() << std::endl;
} }
void Database::PurgeAllDeletedDataBuckets() {
std::string query = StringFormat(
"DELETE FROM `data_buckets` WHERE (`expires` < %lld AND `expires` > 0)",
(long long) std::time(nullptr)
);
QueryDatabase(query);
}
// returns 0 on error or no raid for that character, or // returns 0 on error or no raid for that character, or
// the raid id that the character is a member of. // the raid id that the character is a member of.
uint32 Database::GetRaidID(const char* name) uint32 Database::GetRaidID(const char* name)
@@ -1847,7 +1787,7 @@ const char* Database::GetRaidLeaderName(uint32 raid_id)
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
LogDebug("Unable to get Raid Leader Name for Raid ID: [{}]", raid_id); Log(Logs::General, Logs::Debug, "Unable to get Raid Leader Name for Raid ID: %u", raid_id);
return "UNKNOWN"; return "UNKNOWN";
} }
@@ -2114,11 +2054,10 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id)
return atoi(row[0]); return atoi(row[0]);
} }
/** void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
* @param log_settings
*/
void Database::LoadLogSettings(EQEmuLogSys::LogSettings *log_settings)
{ {
// log_settings previously initialized to '0' by EQEmuLogSys::LoadLogSettingsDefaults()
std::string query = std::string query =
"SELECT " "SELECT "
"log_category_id, " "log_category_id, "
@@ -2129,101 +2068,44 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings *log_settings)
"FROM " "FROM "
"logsys_categories " "logsys_categories "
"ORDER BY log_category_id"; "ORDER BY log_category_id";
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
int log_category_id = 0;
int *categories_in_database = new int[1000]; int log_category = 0;
LogSys.file_logs_enabled = false;
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
log_category_id = atoi(row[0]); log_category = atoi(row[0]);
if (log_category_id <= Logs::None || log_category_id >= Logs::MaxCategoryID) { if (log_category <= Logs::None || log_category >= Logs::MaxCategoryID)
continue; continue;
}
log_settings[log_category_id].log_to_console = static_cast<uint8>(atoi(row[2])); log_settings[log_category].log_to_console = atoi(row[2]);
log_settings[log_category_id].log_to_file = static_cast<uint8>(atoi(row[3])); log_settings[log_category].log_to_file = atoi(row[3]);
log_settings[log_category_id].log_to_gmsay = static_cast<uint8>(atoi(row[4])); log_settings[log_category].log_to_gmsay = atoi(row[4]);
/** /* Determine if any output method is enabled for the category
* Determine if any output method is enabled for the category and set it to 1 so it can used to check if category is enabled */
* and set it to 1 so it can used to check if category is enabled const bool log_to_console = log_settings[log_category].log_to_console > 0;
*/ const bool log_to_file = log_settings[log_category].log_to_file > 0;
const bool log_to_console = log_settings[log_category_id].log_to_console > 0; const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0;
const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay; const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
if (is_category_enabled) { if (is_category_enabled)
log_settings[log_category_id].is_category_enabled = 1; log_settings[log_category].is_category_enabled = 1;
}
/** /*
* This determines whether or not the process needs to actually file log anything. This determines whether or not the process needs to actually file log anything.
* If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open
*/ */
if (log_settings[log_category_id].log_to_file > 0) { if (log_settings[log_category].log_to_file > 0){
LogSys.file_logs_enabled = true; LogSys.file_logs_enabled = true;
} }
categories_in_database[log_category_id] = 1;
} }
/**
* Auto inject categories that don't exist in the database...
*/
for (int log_index = Logs::AA; log_index != Logs::MaxCategoryID; log_index++) {
if (categories_in_database[log_index] != 1) {
LogInfo(
"New Log Category [{0}] doesn't exist... Automatically adding to [logsys_categories] table...",
Logs::LogCategoryName[log_index]
);
auto inject_query = fmt::format(
"INSERT INTO logsys_categories "
"(log_category_id, "
"log_category_description, "
"log_to_console, "
"log_to_file, "
"log_to_gmsay) "
"VALUES "
"({0}, '{1}', {2}, {3}, {4})",
log_index,
EscapeString(Logs::LogCategoryName[log_index]),
std::to_string(log_settings[log_index].log_to_console),
std::to_string(log_settings[log_index].log_to_file),
std::to_string(log_settings[log_index].log_to_gmsay)
);
QueryDatabase(inject_query);
}
}
delete[] categories_in_database;
} }
int Database::CountInvSnapshots() { void Database::ClearInvSnapshots(bool use_rule)
std::string query = StringFormat("SELECT COUNT(*) FROM (SELECT * FROM `inventory_snapshots` a GROUP BY `charid`, `time_index`) b"); {
auto results = QueryDatabase(query);
if (!results.Success())
return -1;
auto row = results.begin();
int64 count = atoll(row[0]);
if (count > 2147483647)
return -2;
if (count < 0)
return -3;
return count;
}
void Database::ClearInvSnapshots(bool from_now) {
uint32 del_time = time(nullptr); uint32 del_time = time(nullptr);
if (!from_now) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; } if (use_rule) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; }
std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time); std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time);
QueryDatabase(query); QueryDatabase(query);
@@ -2237,7 +2119,7 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0){ if (!results.Success() || results.RowCount() == 0){
LogInfo("Loading EQ time of day failed. Using defaults"); Log(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults.");
eqTime.minute = 0; eqTime.minute = 0;
eqTime.hour = 9; eqTime.hour = 9;
eqTime.day = 1; eqTime.day = 1;
+8 -12
View File
@@ -94,8 +94,6 @@ class PTimerList;
# define _ISNAN_(a) std::isnan(a) # define _ISNAN_(a) std::isnan(a)
#endif #endif
#define SQL(...) #__VA_ARGS__
class Database : public DBcore { class Database : public DBcore {
public: public:
Database(); Database();
@@ -129,7 +127,7 @@ public:
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(const char* accname, const char *loginserver, int16* status = 0, uint32* lsid = 0); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name); uint32 GetCharacterID(const char *name);
uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0); uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
uint32 GetGuildIDByCharID(uint32 char_id); uint32 GetGuildIDByCharID(uint32 char_id);
@@ -176,17 +174,18 @@ public:
/* Account Related */ /* Account Related */
bool DeleteAccount(const char *name, const char* loginserver); bool DeleteAccount(const char* name);
bool GetLiveChar(uint32 account_id, char* cname); bool GetLiveChar(uint32 account_id, char* cname);
bool SetAccountStatus(const char* name, int16 status); bool SetAccountStatus(const char* name, int16 status);
bool SetLocalPassword(uint32 accid, const char* password); bool SetLocalPassword(uint32 accid, const char* password);
bool UpdateLiveChar(char* charname, uint32 account_id); bool UpdateLiveChar(char* charname, uint32 lsaccount_id);
int16 CheckStatus(uint32 account_id); int16 CheckStatus(uint32 account_id);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0); uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id); uint32 CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id = 0);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0); uint32 GetAccountIDFromLSID(uint32 iLSID, char* oAccountName = 0, int16* oStatus = 0);
uint32 GetMiniLoginAccount(char* ip);
uint8 GetAgreementFlag(uint32 acctid); uint8 GetAgreementFlag(uint32 acctid);
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
@@ -222,8 +221,6 @@ public:
void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr); void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, RaidLeadershipAA_Struct* RLAA = nullptr);
void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid); void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid);
void PurgeAllDeletedDataBuckets();
/* Database Conversions 'database_conversions.cpp' */ /* Database Conversions 'database_conversions.cpp' */
bool CheckDatabaseConversions(); bool CheckDatabaseConversions();
@@ -265,8 +262,7 @@ public:
void SetLFP(uint32 CharID, bool LFP); void SetLFP(uint32 CharID, bool LFP);
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
int CountInvSnapshots(); void ClearInvSnapshots(bool use_rule = true);
void ClearInvSnapshots(bool from_now = false);
/* EQEmuLogSys */ /* EQEmuLogSys */
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings); void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
+8 -11
View File
@@ -41,9 +41,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#pragma pack(1) #pragma pack(1)
// all const/macro reference values should really be converted to a magic number for this
// process to ensure that the struct sizes and offsets match up to the corresponding blob
/* Conversion Structs */ /* Conversion Structs */
namespace Convert { namespace Convert {
@@ -217,7 +214,7 @@ namespace Convert {
/*0245*/ uint8 guildbanker; /*0245*/ uint8 guildbanker;
/*0246*/ uint8 unknown0246[6]; // /*0246*/ uint8 unknown0246[6]; //
/*0252*/ uint32 intoxication; /*0252*/ uint32 intoxication;
/*0256*/ uint32 spellSlotRefresh[9]; //in ms /*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms
/*0292*/ uint32 abilitySlotRefresh; /*0292*/ uint32 abilitySlotRefresh;
/*0296*/ uint8 haircolor; // Player hair color /*0296*/ uint8 haircolor; // Player hair color
/*0297*/ uint8 beardcolor; // Player beard color /*0297*/ uint8 beardcolor; // Player beard color
@@ -256,9 +253,9 @@ namespace Convert {
/*2505*/ uint8 unknown2541[47]; // ? /*2505*/ uint8 unknown2541[47]; // ?
/*2552*/ uint8 languages[MAX_PP_LANGUAGE]; /*2552*/ uint8 languages[MAX_PP_LANGUAGE];
/*2580*/ uint8 unknown2616[4]; /*2580*/ uint8 unknown2616[4];
/*2584*/ uint32 spell_book[480]; /*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
/*4632*/ uint32 mem_spells[9]; /*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL];
/*4668*/ uint8 unknown4704[32]; // /*4668*/ uint8 unknown4704[32]; //
/*4700*/ float y; // Player y position /*4700*/ float y; // Player y position
/*4704*/ float x; // Player x position /*4704*/ float x; // Player x position
@@ -333,7 +330,7 @@ namespace Convert {
/*7212*/ uint32 tribute_points; /*7212*/ uint32 tribute_points;
/*7216*/ uint32 unknown7252; /*7216*/ uint32 unknown7252;
/*7220*/ uint32 tribute_active; //1=active /*7220*/ uint32 tribute_active; //1=active
/*7224*/ Convert::Tribute_Struct tributes[5]; /*7224*/ Convert::Tribute_Struct tributes[EQEmu::legacy::TRIBUTE_SIZE];
/*7264*/ Convert::Disciplines_Struct disciplines; /*7264*/ Convert::Disciplines_Struct disciplines;
/*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use)
/*7744*/ char unknown7780[160]; /*7744*/ char unknown7780[160];
@@ -476,7 +473,7 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertCorpseDeblob(); CheckDatabaseConvertCorpseDeblob();
/* Run EQEmu Server script (Checks for database updates) */ /* Run EQEmu Server script (Checks for database updates) */
if(system("perl eqemu_server.pl ran_from_world")); system("perl eqemu_server.pl ran_from_world");
return true; return true;
} }
@@ -1360,7 +1357,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
if (rquery != ""){ results = QueryDatabase(rquery); } if (rquery != ""){ results = QueryDatabase(rquery); }
/* Run Spell Convert */ /* Run Spell Convert */
first_entry = 0; rquery = ""; first_entry = 0; rquery = "";
for (i = 0; i < 480; i++){ for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){
if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){
if (first_entry != 1){ if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]);
@@ -1372,7 +1369,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
if (rquery != ""){ results = QueryDatabase(rquery); } if (rquery != ""){ results = QueryDatabase(rquery); }
/* Run Max Memmed Spell Convert */ /* Run Max Memmed Spell Convert */
first_entry = 0; rquery = ""; first_entry = 0; rquery = "";
for (i = 0; i < 9; i++){ for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){
if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){ if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){
if (first_entry != 1){ if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]);
@@ -1408,7 +1405,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
if (rquery != ""){ results = QueryDatabase(rquery); } if (rquery != ""){ results = QueryDatabase(rquery); }
/* Run Tribute Convert */ /* Run Tribute Convert */
first_entry = 0; rquery = ""; first_entry = 0; rquery = "";
for (i = 0; i < 5; i++){ for (i = 0; i < EQEmu::legacy::TRIBUTE_SIZE; i++){
if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){
if (first_entry != 1){ if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute);
+2 -9
View File
@@ -38,23 +38,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <sys/time.h> #include <sys/time.h>
#endif #endif
/**
* @param instance_id
* @param char_id
* @return
*/
bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id)
{ {
std::string query = StringFormat( std::string query = StringFormat(
"REPLACE INTO `instance_list_player` (id, charid) " "REPLACE INTO `instance_list_player` (id, charid) "
"VALUES " "VALUES "
"(%lu, %lu)", "(%lu, %lu)",
(unsigned long) instance_id, (unsigned long)instance_id,
(unsigned long) char_id (unsigned long)char_id
); );
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
return results.Success(); return results.Success();
} }
+50 -102
View File
@@ -2,9 +2,8 @@
#include <winsock2.h> #include <winsock2.h>
#endif #endif
#include "misc_functions.h" #include "../common/misc_functions.h"
#include "eqemu_logsys.h" #include "../common/eqemu_logsys.h"
#include "timer.h"
#include "dbcore.h" #include "dbcore.h"
@@ -15,25 +14,22 @@
#include <string.h> #include <string.h>
#ifdef _WINDOWS #ifdef _WINDOWS
#define snprintf _snprintf #define snprintf _snprintf
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#define strcasecmp _stricmp #define strcasecmp _stricmp
#include <process.h> #include <process.h>
#else #else
#include "unix.h"
#include "unix.h" #include <pthread.h>
#include <pthread.h>
#endif #endif
#ifdef _EQDEBUG #ifdef _EQDEBUG
#define DEBUG_MYSQL_QUERIES 0 #define DEBUG_MYSQL_QUERIES 0
#else #else
#define DEBUG_MYSQL_QUERIES 0 #define DEBUG_MYSQL_QUERIES 0
#endif #endif
DBcore::DBcore() DBcore::DBcore() {
{
mysql_init(&mysql); mysql_init(&mysql);
pHost = 0; pHost = 0;
pUser = 0; pUser = 0;
@@ -44,8 +40,7 @@ DBcore::DBcore()
pStatus = Closed; pStatus = Closed;
} }
DBcore::~DBcore() DBcore::~DBcore() {
{
mysql_close(&mysql); mysql_close(&mysql);
safe_delete_array(pHost); safe_delete_array(pHost);
safe_delete_array(pUser); safe_delete_array(pUser);
@@ -54,8 +49,7 @@ DBcore::~DBcore()
} }
// Sends the MySQL server a keepalive // Sends the MySQL server a keepalive
void DBcore::ping() void DBcore::ping() {
{
if (!MDatabase.trylock()) { if (!MDatabase.trylock()) {
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive // well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
return; return;
@@ -69,35 +63,34 @@ MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureO
return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce); return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce);
} }
MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, bool retryOnFailureOnce) MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce)
{ {
BenchTimer timer;
timer.reset();
LockMutex lock(&MDatabase); LockMutex lock(&MDatabase);
// Reconnect if we are not connected before hand. // Reconnect if we are not connected before hand.
if (pStatus != Connected) { if (pStatus != Connected)
Open(); Open();
}
// request query. != 0 indicates some kind of error. // request query. != 0 indicates some kind of error.
if (mysql_real_query(&mysql, query, querylen) != 0) { if (mysql_real_query(&mysql, query, querylen) != 0)
{
unsigned int errorNumber = mysql_errno(&mysql); unsigned int errorNumber = mysql_errno(&mysql);
if (errorNumber == CR_SERVER_GONE_ERROR) { if (errorNumber == CR_SERVER_GONE_ERROR)
pStatus = Error; pStatus = Error;
}
// error appears to be a disconnect error, may need to try again. // error appears to be a disconnect error, may need to try again.
if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR) { if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR)
{
if (retryOnFailureOnce) { if (retryOnFailureOnce)
LogInfo("Database Error: Lost connection, attempting to recover"); {
std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl;
MySQLRequestResult requestResult = QueryDatabase(query, querylen, false); MySQLRequestResult requestResult = QueryDatabase(query, querylen, false);
if (requestResult.Success()) { if (requestResult.Success())
LogInfo("Reconnection to database successful"); {
std::cout << "Reconnection to database successful." << std::endl;
return requestResult; return requestResult;
} }
@@ -109,100 +102,63 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32) mysql_errno(&mysql), errorBuffer); return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer);
} }
auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; auto errorBuffer = new char[MYSQL_ERRMSG_SIZE];
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
/* Implement Logging at the Root */ /* Implement Logging at the Root */
if (mysql_errno(&mysql) > 0 && strlen(query) > 0) { if (mysql_errno(&mysql) > 0 && strlen(query) > 0){
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1) if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)
Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query); Log(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query);
} }
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql), errorBuffer); return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer);
} }
// successful query. get results. // successful query. get results.
MYSQL_RES *res = mysql_store_result(&mysql); MYSQL_RES* res = mysql_store_result(&mysql);
uint32 rowCount = 0; uint32 rowCount = 0;
if (res != nullptr) { if (res != nullptr)
rowCount = (uint32) mysql_num_rows(res); rowCount = (uint32)mysql_num_rows(res);
}
MySQLRequestResult requestResult( MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
res,
(uint32) mysql_affected_rows(&mysql),
rowCount,
(uint32) mysql_field_count(&mysql),
(uint32) mysql_insert_id(&mysql)
);
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1) { if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
{
if ((strncasecmp(query, "select", 6) == 0)) { if ((strncasecmp(query, "select", 6) == 0)) {
LogF( Log(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s");
Logs::General,
Logs::MySQLQuery,
"{0} ({1} row{2} returned) ({3}ms)",
query,
requestResult.RowCount(),
requestResult.RowCount() == 1 ? "" : "s",
std::to_string(timer.elapsed())
);
} }
else { else {
LogF( Log(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s");
Logs::General,
Logs::MySQLQuery,
"{0} ({1} row{2} affected) ({3}ms)",
query,
requestResult.RowsAffected(),
requestResult.RowsAffected() == 1 ? "" : "s",
std::to_string(timer.elapsed())
);
} }
} }
return requestResult; return requestResult;
} }
void DBcore::TransactionBegin() void DBcore::TransactionBegin() {
{
QueryDatabase("START TRANSACTION"); QueryDatabase("START TRANSACTION");
} }
void DBcore::TransactionCommit() void DBcore::TransactionCommit() {
{
QueryDatabase("COMMIT"); QueryDatabase("COMMIT");
} }
void DBcore::TransactionRollback() void DBcore::TransactionRollback() {
{
QueryDatabase("ROLLBACK"); QueryDatabase("ROLLBACK");
} }
uint32 DBcore::DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen) uint32 DBcore::DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen) {
{
// No good reason to lock the DB, we only need it in the first place to check char encoding. // No good reason to lock the DB, we only need it in the first place to check char encoding.
// LockMutex lock(&MDatabase); // LockMutex lock(&MDatabase);
return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen); return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
} }
bool DBcore::Open( bool DBcore::Open(const char* iHost, const char* iUser, const char* iPassword, const char* iDatabase,uint32 iPort, uint32* errnum, char* errbuf, bool iCompress, bool iSSL) {
const char *iHost,
const char *iUser,
const char *iPassword,
const char *iDatabase,
uint32 iPort,
uint32 *errnum,
char *errbuf,
bool iCompress,
bool iSSL
)
{
LockMutex lock(&MDatabase); LockMutex lock(&MDatabase);
safe_delete(pHost); safe_delete(pHost);
safe_delete(pUser); safe_delete(pUser);
@@ -218,45 +174,37 @@ bool DBcore::Open(
return Open(errnum, errbuf); return Open(errnum, errbuf);
} }
bool DBcore::Open(uint32 *errnum, char *errbuf) bool DBcore::Open(uint32* errnum, char* errbuf) {
{ if (errbuf)
if (errbuf) {
errbuf[0] = 0; errbuf[0] = 0;
}
LockMutex lock(&MDatabase); LockMutex lock(&MDatabase);
if (GetStatus() == Connected) { if (GetStatus() == Connected)
return true; return true;
}
if (GetStatus() == Error) { if (GetStatus() == Error) {
mysql_close(&mysql); mysql_close(&mysql);
mysql_init(&mysql); // Initialize structure again mysql_init(&mysql); // Initialize structure again
} }
if (!pHost) { if (!pHost)
return false; return false;
}
/* /*
Added CLIENT_FOUND_ROWS flag to the connect Added CLIENT_FOUND_ROWS flag to the connect
otherwise DB update calls would say 0 rows affected when the value already equalled otherwise DB update calls would say 0 rows affected when the value already equalled
what the function was tring to set it to, therefore the function would think it failed what the function was tring to set it to, therefore the function would think it failed
*/ */
uint32 flags = CLIENT_FOUND_ROWS; uint32 flags = CLIENT_FOUND_ROWS;
if (pCompress) { if (pCompress)
flags |= CLIENT_COMPRESS; flags |= CLIENT_COMPRESS;
} if (pSSL)
if (pSSL) {
flags |= CLIENT_SSL; flags |= CLIENT_SSL;
}
if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
pStatus = Connected; pStatus = Connected;
return true; return true;
} }
else { else {
if (errnum) { if (errnum)
*errnum = mysql_errno(&mysql); *errnum = mysql_errno(&mysql);
} if (errbuf)
if (errbuf) {
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
}
pStatus = Error; pStatus = Error;
return false; return false;
} }
-69
View File
@@ -20,41 +20,6 @@
#include "emu_constants.h" #include "emu_constants.h"
int16 EQEmu::invtype::GetInvTypeSize(int16 inv_type) {
static const int16 local_array[] = {
POSSESSIONS_SIZE,
BANK_SIZE,
SHARED_BANK_SIZE,
TRADE_SIZE,
WORLD_SIZE,
LIMBO_SIZE,
TRIBUTE_SIZE,
TROPHY_TRIBUTE_SIZE,
GUILD_TRIBUTE_SIZE,
MERCHANT_SIZE,
DELETED_SIZE,
CORPSE_SIZE,
BAZAAR_SIZE,
INSPECT_SIZE,
REAL_ESTATE_SIZE,
VIEW_MOD_PC_SIZE,
VIEW_MOD_BANK_SIZE,
VIEW_MOD_SHARED_BANK_SIZE,
VIEW_MOD_LIMBO_SIZE,
ALT_STORAGE_SIZE,
ARCHIVED_SIZE,
MAIL_SIZE,
GUILD_TROPHY_TRIBUTE_SIZE,
KRONO_SIZE,
OTHER_SIZE,
};
if (inv_type < TYPE_BEGIN || inv_type > TYPE_END)
return INULL;
return local_array[inv_type];
}
const char* EQEmu::bug::CategoryIDToCategoryName(CategoryID category_id) { const char* EQEmu::bug::CategoryIDToCategoryName(CategoryID category_id) {
switch (category_id) { switch (category_id) {
case catVideo: case catVideo:
@@ -118,37 +83,3 @@ EQEmu::bug::CategoryID EQEmu::bug::CategoryNameToCategoryID(const char* category
return catOther; return catOther;
} }
const char *EQEmu::constants::GetStanceName(StanceType stance_type) {
switch (stance_type) {
case stanceUnknown:
return "Unknown";
case stancePassive:
return "Passive";
case stanceBalanced:
return "Balanced";
case stanceEfficient:
return "Efficient";
case stanceReactive:
return "Reactive";
case stanceAggressive:
return "Aggressive";
case stanceAssist:
return "Assist";
case stanceBurn:
return "Burn";
case stanceEfficient2:
return "Efficient2";
case stanceBurnAE:
return "BurnAE";
default:
return "Invalid";
}
}
int EQEmu::constants::ConvertStanceTypeToIndex(StanceType stance_type) {
if (stance_type >= EQEmu::constants::stancePassive && stance_type <= EQEmu::constants::stanceBurnAE)
return (stance_type - EQEmu::constants::stancePassive);
return 0;
}
+111 -246
View File
@@ -21,265 +21,115 @@
#define COMMON_EMU_CONSTANTS_H #define COMMON_EMU_CONSTANTS_H
#include "eq_limits.h" #include "eq_limits.h"
#include "emu_legacy.h"
#include "emu_versions.h" #include "emu_versions.h"
#include <string.h> #include <string.h>
// local definitions are the result of using hybrid-client or server-only values and methods
namespace EQEmu namespace EQEmu
{ {
using RoF2::IINVALID;
using RoF2::INULL;
namespace inventory { namespace inventory {
//using namespace RoF2::invtype;
//using namespace RoF2::invslot;
//using namespace RoF2::invbag;
//using namespace RoF2::invaug;
enum : int16 { typeInvalid = -1, slotInvalid = -1, containerInvalid = -1, socketInvalid = -1 }; // temporary
enum : int16 { typeBegin = 0, slotBegin = 0, containerBegin = 0, socketBegin = 0 }; // temporary
enum PossessionsSlots : int16 { // temporary
slotCharm = 0,
slotEar1,
slotHead,
slotFace,
slotEar2,
slotNeck, // 5
slotShoulders,
slotArms,
slotBack,
slotWrist1,
slotWrist2, // 10
slotRange,
slotHands,
slotPrimary,
slotSecondary,
slotFinger1, // 15
slotFinger2,
slotChest,
slotLegs,
slotFeet,
slotWaist, // 20
slotPowerSource = 9999,
slotAmmo = 21,
slotGeneral1,
slotGeneral2,
slotGeneral3,
slotGeneral4, // 25
slotGeneral5,
slotGeneral6,
slotGeneral7,
slotGeneral8,
slotCursor, // 30
slotCount
};
enum InventoryTypes : int16 { // temporary
typePossessions = 0,
typeBank,
typeSharedBank,
typeTrade,
typeWorld,
typeLimbo, // 5
typeTribute,
typeTrophyTribute,
typeGuildTribute,
typeMerchant,
typeDeleted, // 10
typeCorpse,
typeBazaar,
typeInspect,
typeRealEstate,
typeViewMODPC, // 15
typeViewMODBank,
typeViewMODSharedBank,
typeViewMODLimbo,
typeAltStorage,
typeArchived, // 20
typeMail,
typeGuildTrophyTribute,
typeKrono,
typeOther,
typeCount
};
static int16 SlotCount(int16 type_index) { return 0; } // temporary
const int16 ContainerCount = 10; // temporary
const int16 SocketCount = 6; // temporary
} /*inventory*/ } /*inventory*/
namespace invtype {
using namespace RoF2::invtype::enum_;
using RoF2::invtype::POSSESSIONS_SIZE;
using RoF2::invtype::BANK_SIZE;
using RoF2::invtype::SHARED_BANK_SIZE;
using RoF2::invtype::TRADE_SIZE;
using RoF2::invtype::WORLD_SIZE;
using RoF2::invtype::LIMBO_SIZE;
using RoF2::invtype::TRIBUTE_SIZE;
using RoF2::invtype::TROPHY_TRIBUTE_SIZE;
using RoF2::invtype::GUILD_TRIBUTE_SIZE;
using RoF2::invtype::MERCHANT_SIZE;
using RoF2::invtype::DELETED_SIZE;
using RoF2::invtype::CORPSE_SIZE;
using RoF2::invtype::BAZAAR_SIZE;
using RoF2::invtype::INSPECT_SIZE;
using RoF2::invtype::REAL_ESTATE_SIZE;
using RoF2::invtype::VIEW_MOD_PC_SIZE;
using RoF2::invtype::VIEW_MOD_BANK_SIZE;
using RoF2::invtype::VIEW_MOD_SHARED_BANK_SIZE;
using RoF2::invtype::VIEW_MOD_LIMBO_SIZE;
using RoF2::invtype::ALT_STORAGE_SIZE;
using RoF2::invtype::ARCHIVED_SIZE;
using RoF2::invtype::MAIL_SIZE;
using RoF2::invtype::GUILD_TROPHY_TRIBUTE_SIZE;
using RoF2::invtype::KRONO_SIZE;
using RoF2::invtype::OTHER_SIZE;
using Titanium::invtype::TRADE_NPC_SIZE;
using RoF2::invtype::TYPE_INVALID;
using RoF2::invtype::TYPE_BEGIN;
using RoF2::invtype::TYPE_END;
using RoF2::invtype::TYPE_COUNT;
int16 GetInvTypeSize(int16 inv_type);
using RoF2::invtype::GetInvTypeName;
} // namespace invtype
namespace DevTools {
const int32 GM_ACCOUNT_STATUS_LEVEL = 150;
}
namespace popupresponse {
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
const int32 MOB_INFO_DISMISS = 2000000001;
}
namespace invslot {
using namespace RoF2::invslot::enum_;
using RoF2::invslot::SLOT_INVALID;
using RoF2::invslot::SLOT_BEGIN;
using Titanium::invslot::SLOT_TRADESKILL_EXPERIMENT_COMBINE;
const int16 SLOT_AUGMENT_GENERIC_RETURN = 1001; // clients don't appear to use this method... (internal inventory return value)
using RoF2::invslot::POSSESSIONS_BEGIN;
using RoF2::invslot::POSSESSIONS_END;
using RoF2::invslot::POSSESSIONS_COUNT;
using RoF2::invslot::EQUIPMENT_BEGIN;
using RoF2::invslot::EQUIPMENT_END;
using RoF2::invslot::EQUIPMENT_COUNT;
using RoF2::invslot::GENERAL_BEGIN;
using RoF2::invslot::GENERAL_END;
using RoF2::invslot::GENERAL_COUNT;
using RoF2::invslot::BONUS_BEGIN;
using RoF2::invslot::BONUS_STAT_END;
using RoF2::invslot::BONUS_SKILL_END;
using Titanium::invslot::BANK_BEGIN;
using SoF::invslot::BANK_END;
using Titanium::invslot::SHARED_BANK_BEGIN;
using Titanium::invslot::SHARED_BANK_END;
using Titanium::invslot::TRADE_BEGIN;
using Titanium::invslot::TRADE_END;
using Titanium::invslot::TRADE_NPC_END;
using Titanium::invslot::WORLD_BEGIN;
using Titanium::invslot::WORLD_END;
using Titanium::invslot::TRIBUTE_BEGIN;
using Titanium::invslot::TRIBUTE_END;
using Titanium::invslot::GUILD_TRIBUTE_BEGIN;
using Titanium::invslot::GUILD_TRIBUTE_END;
const int16 CORPSE_BEGIN = invslot::slotGeneral1;
const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor;
using RoF2::invslot::EQUIPMENT_BITMASK;
using RoF2::invslot::GENERAL_BITMASK;
using RoF2::invslot::CURSOR_BITMASK;
using RoF2::invslot::POSSESSIONS_BITMASK;
using RoF2::invslot::CORPSE_BITMASK;
using RoF2::invslot::GetInvPossessionsSlotName;
using RoF2::invslot::GetInvSlotName;
} // namespace invslot
namespace invbag {
using Titanium::invbag::SLOT_INVALID;
using Titanium::invbag::SLOT_BEGIN;
using Titanium::invbag::SLOT_END;
using Titanium::invbag::SLOT_COUNT;
using Titanium::invbag::GENERAL_BAGS_BEGIN;
const int16 GENERAL_BAGS_COUNT = invslot::GENERAL_COUNT * SLOT_COUNT;
const int16 GENERAL_BAGS_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_COUNT) - 1;
const int16 GENERAL_BAGS_8_COUNT = 8 * SLOT_COUNT;
const int16 GENERAL_BAGS_8_END = (GENERAL_BAGS_BEGIN + GENERAL_BAGS_8_COUNT) - 1;
const int16 CURSOR_BAG_BEGIN = 351;
const int16 CURSOR_BAG_COUNT = SLOT_COUNT;
const int16 CURSOR_BAG_END = (CURSOR_BAG_BEGIN + CURSOR_BAG_COUNT) - 1;
using Titanium::invbag::BANK_BAGS_BEGIN;
const int16 BANK_BAGS_COUNT = (invtype::BANK_SIZE * SLOT_COUNT);
const int16 BANK_BAGS_END = (BANK_BAGS_BEGIN + BANK_BAGS_COUNT) - 1;
const int16 BANK_BAGS_16_COUNT = 16 * SLOT_COUNT;
const int16 BANK_BAGS_16_END = (BANK_BAGS_BEGIN + BANK_BAGS_16_COUNT) - 1;
using Titanium::invbag::SHARED_BANK_BAGS_BEGIN;
const int16 SHARED_BANK_BAGS_COUNT = invtype::SHARED_BANK_SIZE * SLOT_COUNT;
const int16 SHARED_BANK_BAGS_END = (SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_COUNT) - 1;
using Titanium::invbag::TRADE_BAGS_BEGIN;
const int16 TRADE_BAGS_COUNT = invtype::TRADE_SIZE * SLOT_COUNT;
const int16 TRADE_BAGS_END = (TRADE_BAGS_BEGIN + TRADE_BAGS_COUNT) - 1;
using Titanium::invbag::GetInvBagIndexName;
} // namespace invbag
namespace invaug {
using RoF2::invaug::SOCKET_INVALID;
using RoF2::invaug::SOCKET_BEGIN;
using RoF2::invaug::SOCKET_END;
using RoF2::invaug::SOCKET_COUNT;
using RoF2::invaug::GetInvAugIndexName;
} // namespace invaug
namespace constants { namespace constants {
const EQEmu::versions::ClientVersion CHARACTER_CREATION_CLIENT = EQEmu::versions::ClientVersion::Titanium; const EQEmu::versions::ClientVersion CharacterCreationClient = EQEmu::versions::ClientVersion::RoF2;
const size_t CharacterCreationMax = RoF2::constants::CharacterCreationLimit;
using RoF2::constants::EXPANSION; const size_t SayLinkOpenerSize = 1;
using RoF2::constants::EXPANSION_BIT; const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize;
using RoF2::constants::EXPANSIONS_MASK; const size_t SayLinkTextSize = 256; // this may be varied until it breaks something (tested:374) - the others are constant
const size_t SayLinkCloserSize = 1;
const size_t SayLinkMaximumSize = (SayLinkOpenerSize + SayLinkBodySize + SayLinkTextSize + SayLinkCloserSize);
using RoF2::constants::CHARACTER_CREATION_LIMIT; const int LongBuffs = RoF2::constants::LongBuffs;
const int ShortBuffs = RoF2::constants::ShortBuffs;
const size_t SAY_LINK_OPENER_SIZE = 1; const int DiscBuffs = RoF2::constants::DiscBuffs;
using RoF2::constants::SAY_LINK_BODY_SIZE; const int TotalBuffs = RoF2::constants::TotalBuffs;
const size_t SAY_LINK_TEXT_SIZE = 256; // this may be varied until it breaks something (tested:374) - the others are constant const int NPCBuffs = RoF2::constants::NPCBuffs;
const size_t SAY_LINK_CLOSER_SIZE = 1; const int PetBuffs = RoF2::constants::PetBuffs;
const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE); const int MercBuffs = RoF2::constants::MercBuffs;
enum StanceType : int {
stanceUnknown = 0,
stancePassive,
stanceBalanced,
stanceEfficient,
stanceReactive,
stanceAggressive,
stanceAssist,
stanceBurn,
stanceEfficient2,
stanceBurnAE
};
const char *GetStanceName(StanceType stance_type);
int ConvertStanceTypeToIndex(StanceType stance_type);
const int STANCE_TYPE_FIRST = stancePassive;
const int STANCE_TYPE_LAST = stanceBurnAE;
const int STANCE_TYPE_COUNT = stanceBurnAE;
} /*constants*/ } /*constants*/
namespace profile {
using RoF2::profile::BANDOLIERS_SIZE;
using RoF2::profile::BANDOLIER_ITEM_COUNT;
using RoF2::profile::POTION_BELT_SIZE;
using RoF2::profile::SKILL_ARRAY_SIZE;
} // namespace profile
namespace behavior {
using RoF2::behavior::CoinHasWeight;
} // namespace behavior
namespace spells {
enum class CastingSlot : uint32 { // hybrid declaration
Gem1 = 0,
Gem2 = 1,
Gem3 = 2,
Gem4 = 3,
Gem5 = 4,
Gem6 = 5,
Gem7 = 6,
Gem8 = 7,
Gem9 = 8,
Gem10 = 9,
Gem11 = 10,
Gem12 = 11,
MaxGems = 12,
Ability = 20, // HT/LoH for Tit
PotionBelt = 21, // Tit uses a different slot for PB
Item = 22,
Discipline = 23,
AltAbility = 0xFF
};
using RoF2::spells::SPELL_ID_MAX;
using RoF2::spells::SPELLBOOK_SIZE;
using UF::spells::SPELL_GEM_COUNT; // RoF+ clients define more than UF client..but, they are not valid beyond UF
using RoF2::spells::LONG_BUFFS;
using RoF2::spells::SHORT_BUFFS;
using RoF2::spells::DISC_BUFFS;
using RoF2::spells::TOTAL_BUFFS;
using RoF2::spells::NPC_BUFFS;
using RoF2::spells::PET_BUFFS;
using RoF2::spells::MERC_BUFFS;
} // namespace spells
namespace bug { namespace bug {
enum CategoryID : uint32 { enum CategoryID : uint32 {
catOther = 0, catOther = 0,
@@ -311,10 +161,25 @@ namespace EQEmu
} // namespace bug } // namespace bug
enum WaypointStatus : int { enum class CastingSlot : uint32 {
RoamBoxPauseInProgress = -3, Gem1 = 0,
QuestControlNoGrid = -2, Gem2 = 1,
QuestControlGrid = -1 Gem3 = 2,
Gem4 = 3,
Gem5 = 4,
Gem6 = 5,
Gem7 = 6,
Gem8 = 7,
Gem9 = 8,
Gem10 = 9,
Gem11 = 10,
Gem12 = 11,
MaxGems = 12,
Ability = 20, // HT/LoH for Tit
PotionBelt = 21, // Tit uses a different slot for PB
Item = 22,
Discipline = 23,
AltAbility = 0xFF
}; };
} /*EQEmu*/ } /*EQEmu*/
+20
View File
@@ -0,0 +1,20 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program 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; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "emu_legacy.h"
+182
View File
@@ -0,0 +1,182 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
This program 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; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMMON_EMU_LEGACY_H
#define COMMON_EMU_LEGACY_H
#include "types.h"
#include <stdlib.h>
namespace EQEmu
{
// this is for perl and other legacy systems
namespace legacy {
enum InventorySlot {
SLOT_CHARM = 0,
SLOT_EAR01 = 1,
SLOT_HEAD = 2,
SLOT_FACE = 3,
SLOT_EAR02 = 4,
SLOT_NECK = 5,
SLOT_SHOULDER = 6,
SLOT_ARMS = 7,
SLOT_BACK = 8,
SLOT_BRACER01 = 9,
SLOT_BRACER02 = 10,
SLOT_RANGE = 11,
SLOT_HANDS = 12,
SLOT_PRIMARY = 13,
SLOT_SECONDARY = 14,
SLOT_RING01 = 15,
SLOT_RING02 = 16,
SLOT_CHEST = 17,
SLOT_LEGS = 18,
SLOT_FEET = 19,
SLOT_WAIST = 20,
SLOT_POWER_SOURCE = 9999,
SLOT_AMMO = 21,
SLOT_GENERAL_1 = 22,
SLOT_GENERAL_2 = 23,
SLOT_GENERAL_3 = 24,
SLOT_GENERAL_4 = 25,
SLOT_GENERAL_5 = 26,
SLOT_GENERAL_6 = 27,
SLOT_GENERAL_7 = 28,
SLOT_GENERAL_8 = 29,
SLOT_CURSOR = 30,
SLOT_CURSOR_END = (int16)0xFFFE, // I hope no one is using this...
SLOT_TRADESKILL = 1000,
SLOT_AUGMENT = 1001,
SLOT_INVALID = (int16)0xFFFF,
SLOT_POSSESSIONS_BEGIN = 0,
SLOT_POSSESSIONS_END = 30,
SLOT_EQUIPMENT_BEGIN = 0,
SLOT_EQUIPMENT_END = 21,
SLOT_PERSONAL_BEGIN = 22,
SLOT_PERSONAL_END = 29,
SLOT_PERSONAL_BAGS_BEGIN = 251,
SLOT_PERSONAL_BAGS_END = 330,
SLOT_CURSOR_BAG_BEGIN = 331,
SLOT_CURSOR_BAG_END = 340,
SLOT_TRIBUTE_BEGIN = 400,
SLOT_TRIBUTE_END = 404,
SLOT_GUILD_TRIBUTE_BEGIN = 450,
SLOT_GUILD_TRIBUTE_END = 451,
SLOT_BANK_BEGIN = 2000,
SLOT_BANK_END = 2023,
SLOT_BANK_BAGS_BEGIN = 2031,
SLOT_BANK_BAGS_END = 2270,
SLOT_SHARED_BANK_BEGIN = 2500,
SLOT_SHARED_BANK_END = 2501,
SLOT_SHARED_BANK_BAGS_BEGIN = 2531,
SLOT_SHARED_BANK_BAGS_END = 2550,
SLOT_TRADE_BEGIN = 3000,
SLOT_TRADE_END = 3007,
SLOT_TRADE_BAGS_BEGIN = 3031,
SLOT_TRADE_BAGS_END = 3110,
SLOT_WORLD_BEGIN = 4000,
SLOT_WORLD_END = 4009
};
// these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready
static const uint16 TYPE_POSSESSIONS_SIZE = 31;
static const uint16 TYPE_BANK_SIZE = 24;
static const uint16 TYPE_SHARED_BANK_SIZE = 2;
static const uint16 TYPE_TRADE_SIZE = 8;
static const uint16 TYPE_WORLD_SIZE = 10;
static const uint16 TYPE_LIMBO_SIZE = 36;
static const uint16 TYPE_TRIBUTE_SIZE = 5; // (need client values)
static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0;
static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0;
static const uint16 TYPE_MERCHANT_SIZE = 0;
static const uint16 TYPE_DELETED_SIZE = 0;
static const uint16 TYPE_CORPSE_SIZE = 31; // no bitmask use..limits to size of client corpse window (see EQLimits::InventoryMapSize(MapCorpse, <EQClientVersion))
static const uint16 TYPE_BAZAAR_SIZE = 80;
static const uint16 TYPE_INSPECT_SIZE = 22;
static const uint16 TYPE_REAL_ESTATE_SIZE = 0;
static const uint16 TYPE_VIEW_MOD_PC_SIZE = 0;
static const uint16 TYPE_VIEW_MOD_BANK_SIZE = 0;
static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = 0;
static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = 0;
static const uint16 TYPE_ALT_STORAGE_SIZE = 0;
static const uint16 TYPE_ARCHIVED_SIZE = 0;
static const uint16 TYPE_MAIL_SIZE = 0;
static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0;
static const uint16 TYPE_KRONO_SIZE = 0;
static const uint16 TYPE_OTHER_SIZE = 0;
// most of these definitions will go away with the structure-based system..this maintains compatibility for now
// (these are mainly to assign specific values to constants used in conversions and to identify per-client ranges/offsets)
static const int16 EQUIPMENT_BEGIN = 0;
static const int16 EQUIPMENT_END = 21;
static const uint16 EQUIPMENT_SIZE = 22; // does not account for 'Power Source' - used mainly for npc equipment arrays
static const int16 GENERAL_BEGIN = 22;
static const int16 GENERAL_END = 29;
static const uint16 GENERAL_SIZE = 8;
static const int16 GENERAL_BAGS_BEGIN = 251;
static const int16 GENERAL_BAGS_END_OFFSET = 79;
static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET;
static const int16 CURSOR_BAG_BEGIN = 331;
static const int16 CURSOR_BAG_END_OFFSET = 9;
static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET;
static const int16 BANK_BEGIN = 2000;
static const int16 BANK_END = 2023;
static const int16 BANK_BAGS_BEGIN = 2031;
static const int16 BANK_BAGS_END_OFFSET = 239;
static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET;
static const int16 SHARED_BANK_BEGIN = 2500;
static const int16 SHARED_BANK_END = 2501;
static const int16 SHARED_BANK_BAGS_BEGIN = 2531;
static const int16 SHARED_BANK_BAGS_END_OFFSET = 19;
static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET;
static const int16 TRADE_BEGIN = 3000;
static const int16 TRADE_END = 3007;
static const int16 TRADE_NPC_END = 3003;
static const int16 TRADE_BAGS_BEGIN = 3031;
static const int16 TRADE_BAGS_END_OFFSET = 79;
static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET;
static const int16 WORLD_BEGIN = 4000;
static const int16 WORLD_END = 4009;
static const int16 WORLD_SIZE = TYPE_WORLD_SIZE;
static const int16 TRIBUTE_BEGIN = 400;
static const int16 TRIBUTE_END = 404;
static const int16 TRIBUTE_SIZE = TYPE_TRIBUTE_SIZE;
static const int16 CORPSE_BEGIN = 22;
// BANDOLIERS_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances
static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance
// POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?)
static const size_t POTION_BELT_ITEM_COUNT = 5;
}
}
#endif /* COMMON_EMU_LEGACY_H */
+24 -48
View File
@@ -28,98 +28,74 @@
namespace EntityLimits namespace EntityLimits
{ {
namespace NPC { namespace NPC {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*NPC*/ } /*NPC*/
namespace NPCMerchant { namespace NPCMerchant {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*NPCMerchant*/ } /*NPCMerchant*/
namespace Merc { namespace Merc {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*Merc*/ } /*Merc*/
namespace Bot { namespace Bot {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 8;
} // namespace invtype const size_t InvTypeTradeSize = 8;
namespace invslot {
const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF;
const uint64 GENERAL_BITMASK = 0x0000000000000000;
const uint64 CURSOR_BITMASK = 0x0000000000000000;
const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+)
} // namespace invslot
} /*Bot*/ } /*Bot*/
namespace ClientPet { namespace ClientPet {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*Pet*/ } /*Pet*/
namespace NPCPet { namespace NPCPet {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*Pet*/ } /*Pet*/
namespace MercPet { namespace MercPet {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*Pet*/ } /*Pet*/
namespace BotPet { namespace BotPet {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace invtype { enum : bool { False = false, True = true };
const int16 TRADE_SIZE = 4;
} // namespace invtype const size_t InvTypeTradeSize = 4;
} /*Pet*/ } /*Pet*/
+34 -222
View File
@@ -18,7 +18,6 @@
*/ */
#include "emu_versions.h" #include "emu_versions.h"
#include "emu_constants.h"
bool EQEmu::versions::IsValidClientVersion(ClientVersion client_version) bool EQEmu::versions::IsValidClientVersion(ClientVersion client_version)
@@ -64,26 +63,32 @@ const char* EQEmu::versions::ClientVersionName(ClientVersion client_version)
uint32 EQEmu::versions::ConvertClientVersionToClientVersionBit(ClientVersion client_version) uint32 EQEmu::versions::ConvertClientVersionToClientVersionBit(ClientVersion client_version)
{ {
switch (client_version) { switch (client_version) {
case ClientVersion::Unknown:
case ClientVersion::Client62:
return bit_Unknown;
case ClientVersion::Titanium: case ClientVersion::Titanium:
return bitTitanium; return bit_Titanium;
case ClientVersion::SoF: case ClientVersion::SoF:
return bitSoF; return bit_SoF;
case ClientVersion::SoD: case ClientVersion::SoD:
return bitSoD; return bit_SoD;
case ClientVersion::UF: case ClientVersion::UF:
return bitUF; return bit_UF;
case ClientVersion::RoF: case ClientVersion::RoF:
return bitRoF; return bit_RoF;
case ClientVersion::RoF2: case ClientVersion::RoF2:
return bitRoF2; return bit_RoF2;
default: default:
return bitUnknown; return bit_Unknown;
} }
} }
EQEmu::versions::ClientVersion EQEmu::versions::ConvertClientVersionBitToClientVersion(uint32 client_version_bit) EQEmu::versions::ClientVersion EQEmu::versions::ConvertClientVersionBitToClientVersion(uint32 client_version_bit)
{ {
switch (client_version_bit) { switch (client_version_bit) {
case (uint32)static_cast<unsigned int>(ClientVersion::Unknown) :
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Client62) - 1)) :
return ClientVersion::Unknown;
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Titanium) - 1)) : case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::Titanium) - 1)) :
return ClientVersion::Titanium; return ClientVersion::Titanium;
case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::SoF) - 1)) : case ((uint32)1 << (static_cast<unsigned int>(ClientVersion::SoF) - 1)) :
@@ -101,6 +106,27 @@ EQEmu::versions::ClientVersion EQEmu::versions::ConvertClientVersionBitToClientV
} }
} }
uint32 EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion client_version)
{
switch (client_version) {
case ClientVersion::Unknown:
case ClientVersion::Client62:
case ClientVersion::Titanium:
return 0x000007FFU;
case ClientVersion::SoF:
return 0x00007FFFU;
case ClientVersion::SoD:
return 0x0000FFFFU;
case ClientVersion::UF:
return 0x0001FFFFU;
case ClientVersion::RoF:
case ClientVersion::RoF2:
return 0x000FFFFFU;
default:
return 0;
}
}
bool EQEmu::versions::IsValidMobVersion(MobVersion mob_version) bool EQEmu::versions::IsValidMobVersion(MobVersion mob_version)
{ {
if (mob_version <= MobVersion::Unknown || mob_version > LastMobVersion) if (mob_version <= MobVersion::Unknown || mob_version > LastMobVersion)
@@ -342,217 +368,3 @@ EQEmu::versions::MobVersion EQEmu::versions::ConvertClientVersionToOfflinePCMobV
return MobVersion::Unknown; return MobVersion::Unknown;
} }
} }
const char* EQEmu::expansions::ExpansionName(Expansion expansion)
{
switch (expansion) {
case Expansion::EverQuest:
return "EverQuest";
case Expansion::RoK:
return "The Ruins of Kunark";
case Expansion::SoV:
return "The Scars of Velious";
case Expansion::SoL:
return "The Shadows of Luclin";
case Expansion::PoP:
return "The Planes of Power";
case Expansion::LoY:
return "The Legacy of Ykesha";
case Expansion::LDoN:
return "Lost Dungeons of Norrath";
case Expansion::GoD:
return "Gates of Discord";
case Expansion::OoW:
return "Omens of War";
case Expansion::DoN:
return "Dragons of Norrath";
case Expansion::DoD:
return "Depths of Darkhollow";
case Expansion::PoR:
return "Prophecy of Ro";
case Expansion::TSS:
return "The Serpent's Spine";
case Expansion::TBS:
return "The Buried Sea";
case Expansion::SoF:
return "Secrets of Faydwer";
case Expansion::SoD:
return "Seeds of Destruction";
case Expansion::UF:
return "Underfoot";
case Expansion::HoT:
return "House of Thule";
case Expansion::VoA:
return "Veil of Alaris";
case Expansion::RoF:
return "Rain of Fear";
case Expansion::CotF:
return "Call of the Forsaken";
default:
return "Invalid Expansion";
}
}
const char* EQEmu::expansions::ExpansionName(uint32 expansion_bit)
{
return ExpansionName(ConvertExpansionBitToExpansion(expansion_bit));
}
uint32 EQEmu::expansions::ConvertExpansionToExpansionBit(Expansion expansion)
{
switch (expansion) {
case Expansion::RoK:
return bitRoK;
case Expansion::SoV:
return bitSoV;
case Expansion::SoL:
return bitSoL;
case Expansion::PoP:
return bitPoP;
case Expansion::LoY:
return bitLoY;
case Expansion::LDoN:
return bitLDoN;
case Expansion::GoD:
return bitGoD;
case Expansion::OoW:
return bitOoW;
case Expansion::DoN:
return bitDoN;
case Expansion::DoD:
return bitDoD;
case Expansion::PoR:
return bitPoR;
case Expansion::TSS:
return bitTSS;
case Expansion::TBS:
return bitTBS;
case Expansion::SoF:
return bitSoF;
case Expansion::SoD:
return bitSoD;
case Expansion::UF:
return bitUF;
case Expansion::HoT:
return bitHoT;
case Expansion::VoA:
return bitVoA;
case Expansion::RoF:
return bitRoF;
case Expansion::CotF:
return bitCotF;
default:
return bitEverQuest;
}
}
EQEmu::expansions::Expansion EQEmu::expansions::ConvertExpansionBitToExpansion(uint32 expansion_bit)
{
switch (expansion_bit) {
case bitRoK:
return Expansion::RoK;
case bitSoV:
return Expansion::SoV;
case bitSoL:
return Expansion::SoL;
case bitPoP:
return Expansion::PoP;
case bitLoY:
return Expansion::LoY;
case bitLDoN:
return Expansion::LDoN;
case bitGoD:
return Expansion::GoD;
case bitOoW:
return Expansion::OoW;
case bitDoN:
return Expansion::DoN;
case bitDoD:
return Expansion::DoD;
case bitPoR:
return Expansion::PoR;
case bitTSS:
return Expansion::TSS;
case bitTBS:
return Expansion::TBS;
case bitSoF:
return Expansion::SoF;
case bitSoD:
return Expansion::SoD;
case bitUF:
return Expansion::UF;
case bitHoT:
return Expansion::HoT;
case bitVoA:
return Expansion::VoA;
case bitRoF:
return Expansion::RoF;
case bitCotF:
return Expansion::CotF;
default:
return Expansion::EverQuest;
}
}
uint32 EQEmu::expansions::ConvertExpansionToExpansionsMask(Expansion expansion)
{
switch (expansion) {
case Expansion::RoK:
return maskRoK;
case Expansion::SoV:
return maskSoV;
case Expansion::SoL:
return maskSoL;
case Expansion::PoP:
return maskPoP;
case Expansion::LoY:
return maskLoY;
case Expansion::LDoN:
return maskLDoN;
case Expansion::GoD:
return maskGoD;
case Expansion::OoW:
return maskOoW;
case Expansion::DoN:
return maskDoN;
case Expansion::DoD:
return maskDoD;
case Expansion::PoR:
return maskPoR;
case Expansion::TSS:
return maskTSS;
case Expansion::TBS:
return maskTBS;
case Expansion::SoF:
return maskSoF;
case Expansion::SoD:
return maskSoD;
case Expansion::UF:
return maskUF;
case Expansion::HoT:
return maskHoT;
case Expansion::VoA:
return maskVoA;
case Expansion::RoF:
return maskRoF;
case Expansion::CotF:
return maskCotF;
default:
return maskEverQuest;
}
}
EQEmu::expansions::Expansion EQEmu::expansions::ConvertClientVersionToExpansion(versions::ClientVersion client_version)
{
return EQEmu::constants::StaticLookup(client_version)->Expansion;
}
uint32 EQEmu::expansions::ConvertClientVersionToExpansionBit(versions::ClientVersion client_version)
{
return EQEmu::constants::StaticLookup(client_version)->ExpansionBit;
}
uint32 EQEmu::expansions::ConvertClientVersionToExpansionsMask(versions::ClientVersion client_version)
{
return EQEmu::constants::StaticLookup(client_version)->ExpansionsMask;
}
+22 -102
View File
@@ -39,27 +39,26 @@ namespace EQEmu
RoF2 // Build: 'May 10 2013 23:30:08' RoF2 // Build: 'May 10 2013 23:30:08'
}; };
enum ClientVersionBitmask : uint32 { enum ClientVersionBit : uint32 {
bitUnknown = 0x00000000, bit_Unknown = 0,
bitClient62 = 0x00000001, // unsupported (placeholder for scripts) bit_Client62 = 0x00000001, // unsupported (placeholder for scripts)
bitTitanium = 0x00000002, bit_Titanium = 0x00000002,
bitSoF = 0x00000004, bit_SoF = 0x00000004,
bitSoD = 0x00000008, bit_SoD = 0x00000008,
bitUF = 0x00000010, bit_UF = 0x00000010,
bitRoF = 0x00000020, bit_RoF = 0x00000020,
bitRoF2 = 0x00000040, bit_RoF2 = 0x00000040,
maskUnknown = 0x00000000, bit_TitaniumAndEarlier = 0x00000003,
maskTitaniumAndEarlier = 0x00000003, bit_SoFAndEarlier = 0x00000007,
maskSoFAndEarlier = 0x00000007, bit_SoDAndEarlier = 0x0000000F,
maskSoDAndEarlier = 0x0000000F, bit_UFAndEarlier = 0x0000001F,
maskUFAndEarlier = 0x0000001F, bit_RoFAndEarlier = 0x0000003F,
maskRoFAndEarlier = 0x0000003F, bit_SoFAndLater = 0xFFFFFFFC,
maskSoFAndLater = 0xFFFFFFFC, bit_SoDAndLater = 0xFFFFFFF8,
maskSoDAndLater = 0xFFFFFFF8, bit_UFAndLater = 0xFFFFFFF0,
maskUFAndLater = 0xFFFFFFF0, bit_RoFAndLater = 0xFFFFFFE0,
maskRoFAndLater = 0xFFFFFFE0, bit_RoF2AndLater = 0xFFFFFFC0,
maskRoF2AndLater = 0xFFFFFFC0, bit_AllClients = 0xFFFFFFFF
maskAllClients = 0xFFFFFFFF
}; };
const ClientVersion LastClientVersion = ClientVersion::RoF2; const ClientVersion LastClientVersion = ClientVersion::RoF2;
@@ -70,6 +69,8 @@ namespace EQEmu
const char* ClientVersionName(ClientVersion client_version); const char* ClientVersionName(ClientVersion client_version);
uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version); uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version);
ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit); ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit);
uint32 ConvertClientVersionToExpansion(ClientVersion client_version);
enum class MobVersion : uint32 { enum class MobVersion : uint32 {
Unknown = 0, Unknown = 0,
@@ -136,87 +137,6 @@ namespace EQEmu
} /*versions*/ } /*versions*/
namespace expansions {
enum class Expansion : uint32 {
EverQuest = 0,
RoK,
SoV,
SoL,
PoP,
LoY,
LDoN,
GoD,
OoW,
DoN,
DoD,
PoR,
TSS,
TBS,
SoF,
SoD,
UF,
HoT,
VoA,
RoF,
CotF
};
enum ExpansionBitmask : uint32 {
bitEverQuest = 0x00000000,
bitRoK = 0x00000001,
bitSoV = 0x00000002,
bitSoL = 0x00000004,
bitPoP = 0x00000008,
bitLoY = 0x00000010,
bitLDoN = 0x00000020,
bitGoD = 0x00000040,
bitOoW = 0x00000080,
bitDoN = 0x00000100,
bitDoD = 0x00000200,
bitPoR = 0x00000400,
bitTSS = 0x00000800,
bitTBS = 0x00001000,
bitSoF = 0x00002000,
bitSoD = 0x00004000,
bitUF = 0x00008000,
bitHoT = 0x00010000,
bitVoA = 0x00020000,
bitRoF = 0x00040000,
bitCotF = 0x00080000,
maskEverQuest = 0x00000000,
maskRoK = 0x00000001,
maskSoV = 0x00000003,
maskSoL = 0x00000007,
maskPoP = 0x0000000F,
maskLoY = 0x0000001F,
maskLDoN = 0x0000003F,
maskGoD = 0x0000007F,
maskOoW = 0x000000FF,
maskDoN = 0x000001FF,
maskDoD = 0x000003FF,
maskPoR = 0x000007FF,
maskTSS = 0x00000FFF,
maskTBS = 0x00001FFF,
maskSoF = 0x00003FFF,
maskSoD = 0x00007FFF,
maskUF = 0x0000FFFF,
maskHoT = 0x0001FFFF,
maskVoA = 0x0003FFFF,
maskRoF = 0x0007FFFF,
maskCotF = 0x000FFFFF
};
const char* ExpansionName(Expansion expansion);
const char* ExpansionName(uint32 expansion_bit);
uint32 ConvertExpansionToExpansionBit(Expansion expansion);
Expansion ConvertExpansionBitToExpansion(uint32 expansion_bit);
uint32 ConvertExpansionToExpansionsMask(Expansion expansion);
Expansion ConvertClientVersionToExpansion(versions::ClientVersion client_version);
uint32 ConvertClientVersionToExpansionBit(versions::ClientVersion client_version);
uint32 ConvertClientVersionToExpansionsMask(versions::ClientVersion client_version);
} /*expansions*/
} /*EQEmu*/ } /*EQEmu*/
#endif /*COMMON_EMU_VERSIONS_H*/ #endif /*COMMON_EMU_VERSIONS_H*/
+191 -132
View File
@@ -87,114 +87,199 @@ typedef enum {
_eaMaxAppearance _eaMaxAppearance
} EmuAppearance; } EmuAppearance;
namespace Chat { // msg_type's for custom usercolors
const uint16 White = 0; #define MT_Say 256
const uint16 DimGray = 1; #define MT_Tell 257
const uint16 Default = 1; #define MT_Group 258
const uint16 Green = 2; #define MT_Guild 259
const uint16 BrightBlue = 3; #define MT_OOC 260
const uint16 LightBlue = 4; #define MT_Auction 261
const uint16 Magenta = 5; #define MT_Shout 262
const uint16 Gray = 6; #define MT_Emote 263
const uint16 LightGray = 7; #define MT_Spells 264
const uint16 NPCQuestSay = 10; #define MT_YouHitOther 265
const uint16 DarkGray = 12; #define MT_OtherHitsYou 266
const uint16 Red = 13; #define MT_YouMissOther 267
const uint16 Lime = 14; #define MT_OtherMissesYou 268
const uint16 Yellow = 15; #define MT_Broadcasts 269
const uint16 Blue = 16; #define MT_Skills 270
const uint16 LightNavy = 17; #define MT_Disciplines 271
const uint16 Cyan = 18; #define MT_Unused1 272
const uint16 Black = 20; #define MT_DefaultText 273
#define MT_Unused2 274
#define MT_MerchantOffer 275
#define MT_MerchantBuySell 276
#define MT_YourDeath 277
#define MT_OtherDeath 278
#define MT_OtherHits 279
#define MT_OtherMisses 280
#define MT_Who 281
#define MT_YellForHelp 282
#define MT_NonMelee 283
#define MT_WornOff 284
#define MT_MoneySplit 285
#define MT_LootMessages 286
#define MT_DiceRoll 287
#define MT_OtherSpells 288
#define MT_SpellFailure 289
#define MT_Chat 290
#define MT_Channel1 291
#define MT_Channel2 292
#define MT_Channel3 293
#define MT_Channel4 294
#define MT_Channel5 295
#define MT_Channel6 296
#define MT_Channel7 297
#define MT_Channel8 298
#define MT_Channel9 299
#define MT_Channel10 300
#define MT_CritMelee 301
#define MT_SpellCrits 302
#define MT_TooFarAway 303
#define MT_NPCRampage 304
#define MT_NPCFlurry 305
#define MT_NPCEnrage 306
#define MT_SayEcho 307
#define MT_TellEcho 308
#define MT_GroupEcho 309
#define MT_GuildEcho 310
#define MT_OOCEcho 311
#define MT_AuctionEcho 312
#define MT_ShoutECho 313
#define MT_EmoteEcho 314
#define MT_Chat1Echo 315
#define MT_Chat2Echo 316
#define MT_Chat3Echo 317
#define MT_Chat4Echo 318
#define MT_Chat5Echo 319
#define MT_Chat6Echo 320
#define MT_Chat7Echo 321
#define MT_Chat8Echo 322
#define MT_Chat9Echo 323
#define MT_Chat10Echo 324
#define MT_DoTDamage 325
#define MT_ItemLink 326
#define MT_RaidSay 327
#define MT_MyPet 328
#define MT_DS 329
#define MT_Leadership 330
#define MT_PetFlurry 331
#define MT_PetCrit 332
#define MT_FocusEffect 333
#define MT_Experience 334
#define MT_System 335
#define MT_PetSpell 336
#define MT_PetResponse 337
#define MT_ItemSpeech 338
#define MT_StrikeThrough 339
#define MT_Stun 340
/** // TODO: Really should combine above and below into one
* User colors
//from showeq
enum ChatColor
{
/*
CC_Default = 0,
CC_DarkGrey = 1,
CC_DarkGreen = 2,
CC_DarkBlue = 3,
CC_Purple = 5,
CC_LightGrey = 6,
*/ */
const uint16 Say = 256;
const uint16 Tell = 257; CC_WhiteSmoke = 0, // FF|F0F0F0
const uint16 Group = 258; CC_Green = 2, // FF|008000
const uint16 Guild = 259; CC_BrightBlue = 3, // FF|0040FF
const uint16 OOC = 260; CC_Magenta = 5, // FF|F000F0
const uint16 Auction = 261; CC_Gray = 6, // FF|808080
const uint16 Shout = 262; CC_LightGray = 7, // FF|E0E0E0
const uint16 Emote = 263; //CC_WhiteSmoke2 = 10, // FF|F0F0F0
const uint16 Spells = 264; CC_DarkGray = 12, // FF|A0A0A0
const uint16 YouHitOther = 265; CC_Red = 13, // FF|F00000
const uint16 OtherHitYou = 266; CC_Lime = 14, // FF|00F000
const uint16 YouMissOther = 267; CC_Yellow = 15, // FF|F0F000
const uint16 OtherMissYou = 268; CC_Blue = 16, // FF|0000F0
const uint16 Broadcasts = 269; CC_LightNavy = 17, // FF|0000AF
const uint16 Skills = 270; CC_Cyan = 18, // FF|00F0F0
const uint16 Disciplines = 271; CC_Black = 20, // FF|000000
const uint16 Unused1 = 272;
const uint16 DefaultText = 273; // any index <= 255 that is not defined above
const uint16 Unused2 = 274; CC_DimGray = 1, // FF|606060
const uint16 MerchantOffer = 275; CC_Default = 1,
const uint16 MerchantExchange = 276;
const uint16 YourDeath = 277; CC_User_Say = 256,
const uint16 OtherDeath = 278; CC_User_Tell = 257,
const uint16 OtherHitOther = 279; CC_User_Group = 258,
const uint16 OtherMissOther = 280; CC_User_Guild = 259,
const uint16 Who = 281; CC_User_OOC = 260,
const uint16 YellForHelp = 282; CC_User_Auction = 261,
const uint16 NonMelee = 283; CC_User_Shout = 262,
const uint16 SpellWornOff = 284; CC_User_Emote = 263,
const uint16 MoneySplit = 285; CC_User_Spells = 264,
const uint16 Loot = 286; CC_User_YouHitOther = 265,
const uint16 DiceRoll = 287; CC_User_OtherHitYou = 266,
const uint16 OtherSpells = 288; CC_User_YouMissOther = 267,
const uint16 SpellFailure = 289; CC_User_OtherMissYou = 268,
const uint16 ChatChannel = 290; CC_User_Duels = 269,
const uint16 Chat1 = 291; CC_User_Skills = 270,
const uint16 Chat2 = 292; CC_User_Disciplines = 271,
const uint16 Chat3 = 293; CC_User_Default = 273,
const uint16 Chat4 = 294; CC_User_MerchantOffer = 275,
const uint16 Chat5 = 295; CC_User_MerchantExchange = 276,
const uint16 Chat6 = 296; CC_User_YourDeath = 277,
const uint16 Chat7 = 297; CC_User_OtherDeath = 278,
const uint16 Chat8 = 298; CC_User_OtherHitOther = 279,
const uint16 Chat9 = 299; CC_User_OtherMissOther = 280,
const uint16 Chat10 = 300; CC_User_Who = 281,
const uint16 MeleeCrit = 301; CC_User_Yell = 282,
const uint16 SpellCrit = 302; CC_User_NonMelee = 283,
const uint16 TooFarAway = 303; CC_User_SpellWornOff = 284,
const uint16 NPCRampage = 304; CC_User_MoneySplit = 285,
const uint16 NPCFlurry = 305; CC_User_Loot = 286,
const uint16 NPCEnrage = 306; CC_User_Random = 287,
const uint16 EchoSay = 307; CC_User_OtherSpells = 288,
const uint16 EchoTell = 308; CC_User_SpellFailure = 289,
const uint16 EchoGroup = 309; CC_User_ChatChannel = 290,
const uint16 EchoGuild = 310; CC_User_Chat1 = 291,
const uint16 EchoOOC = 311; CC_User_Chat2 = 292,
const uint16 EchoAuction = 312; CC_User_Chat3 = 293,
const uint16 EchoShout = 313; CC_User_Chat4 = 294,
const uint16 EchoEmote = 314; CC_User_Chat5 = 295,
const uint16 EchoChat1 = 315; CC_User_Chat6 = 296,
const uint16 EchoChat2 = 316; CC_User_Chat7 = 297,
const uint16 EchoChat3 = 317; CC_User_Chat8 = 298,
const uint16 EchoChat4 = 318; CC_User_Chat9 = 299,
const uint16 EchoChat5 = 319; CC_User_Chat10 = 300,
const uint16 EchoChat6 = 320; CC_User_MeleeCrit = 301,
const uint16 EchoChat7 = 321; CC_User_SpellCrit = 302,
const uint16 EchoChat8 = 322; CC_User_TooFarAway = 303,
const uint16 EchoChat9 = 323; CC_User_NPCRampage = 304,
const uint16 EchoChat10 = 324; CC_User_NPCFurry = 305,
const uint16 DotDamage = 325; CC_User_NPCEnrage = 306,
const uint16 ItemLink = 326; CC_User_EchoSay = 307,
const uint16 RaidSay = 327; CC_User_EchoTell = 308,
const uint16 MyPet = 328; CC_User_EchoGroup = 309,
const uint16 DamageShield = 329; CC_User_EchoGuild = 310,
const uint16 LeaderShip = 330; CC_User_EchoOOC = 311,
const uint16 PetFlurry = 331; CC_User_EchoAuction = 312,
const uint16 PetCritical = 332; CC_User_EchoShout = 313,
const uint16 FocusEffect = 333; CC_User_EchoEmote = 314,
const uint16 Experience = 334; CC_User_EchoChat1 = 315,
const uint16 System = 335; CC_User_EchoChat2 = 316,
const uint16 PetSpell = 336; CC_User_EchoChat3 = 317,
const uint16 PetResponse = 337; CC_User_EchoChat4 = 318,
const uint16 ItemSpeech = 338; CC_User_EchoChat5 = 319,
const uint16 StrikeThrough = 339; CC_User_EchoChat6 = 320,
const uint16 Stun = 340; CC_User_EchoChat7 = 321,
CC_User_EchoChat8 = 322,
CC_User_EchoChat9 = 323,
CC_User_EchoChat10 = 324,
CC_User_UnusedAtThisTime = 325,
CC_User_ItemTags = 326,
CC_User_RaidSay = 327,
CC_User_MyPet = 328,
CC_User_DamageShield = 329,
}; };
//ZoneChange_Struct->success values //ZoneChange_Struct->success values
@@ -438,30 +523,4 @@ static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // chang
static const uint32 MAX_SPELL_DB_ID_VAL = 65535; static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
enum ChatChannelNames : uint16
{
ChatChannel_Guild = 0,
ChatChannel_Group = 2,
ChatChannel_Shout = 3,
ChatChannel_Auction = 4,
ChatChannel_OOC = 5,
ChatChannel_Broadcast = 6,
ChatChannel_Tell = 7,
ChatChannel_Say = 8,
ChatChannel_Petition = 10,
ChatChannel_GMSAY = 11,
ChatChannel_TellEcho = 14,
ChatChannel_Raid = 15,
ChatChannel_UNKNOWN_Guild = 17,
ChatChannel_UNKNOWN_GMSAY = 18,
ChatChannel_UCSRelay = 20,
ChatChannel_Emotes = 22
};
namespace ZoneBlockedSpellTypes {
const uint8 ZoneWide = 1;
const uint8 Region = 2;
};
#endif /*COMMON_EQ_CONSTANTS_H*/ #endif /*COMMON_EQ_CONSTANTS_H*/
+873 -1139
View File
File diff suppressed because it is too large Load Diff
+38 -206
View File
@@ -20,6 +20,7 @@
#ifndef COMMON_EQ_LIMITS_H #ifndef COMMON_EQ_LIMITS_H
#define COMMON_EQ_LIMITS_H #define COMMON_EQ_LIMITS_H
#include "emu_legacy.h"
#include "types.h" #include "types.h"
#include "eq_constants.h" #include "eq_constants.h"
#include "emu_versions.h" #include "emu_versions.h"
@@ -33,166 +34,10 @@
namespace EQEmu namespace EQEmu
{ {
void InitializeDynamicLookups();
namespace constants { namespace constants {
struct LookupEntry { class LookupEntry {
EQEmu::expansions::Expansion Expansion; public:
uint32 ExpansionBit; size_t CharacterCreationLimit;
uint32 ExpansionsMask;
int16 CharacterCreationLimit;
size_t SayLinkBodySize;
LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry(
EQEmu::expansions::Expansion Expansion,
uint32 ExpansionBit,
uint32 ExpansionsMask,
int16 CharacterCreationLimit,
size_t SayLinkBodySize
) :
Expansion(Expansion),
ExpansionBit(ExpansionBit),
ExpansionsMask(ExpansionsMask),
CharacterCreationLimit(CharacterCreationLimit),
SayLinkBodySize(SayLinkBodySize)
{ }
};
void InitializeDynamicLookups();
const LookupEntry* DynamicLookup(versions::ClientVersion client_version, bool gm_flag);
const LookupEntry* DynamicNonGMLookup(versions::ClientVersion client_version);
const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version);
const LookupEntry* StaticLookup(versions::ClientVersion client_version);
} /*constants*/
namespace inventory {
struct LookupEntry {
// note: 'PossessionsBitmask' needs to be attuned to the client version with the highest number
// of possessions slots and 'InventoryTypeSize[typePossessions]' should reflect the same count
// with translators adjusting for valid slot indices. Server-side validations will be performed
// against 'PossessionsBitmask' (note: the same applies to CorpseBitmask..size is not dependent)
struct InventoryTypeSize_Struct { // should reflect count and naming conventions referenced in emu_constants.h
int16 Possessions, Bank, SharedBank;
int16 Trade, World, Limbo;
int16 Tribute, TrophyTribute, GuildTribute;
int16 Merchant, Deleted, Corpse;
int16 Bazaar, Inspect, RealEstate;
int16 ViewMODPC, ViewMODBank, ViewMODSharedBank;
int16 ViewMODLimbo, AltStorage, Archived;
int16 Mail, GuildTrophyTribute, Krono;
int16 Other;
InventoryTypeSize_Struct(
int16 Possessions, int16 Bank, int16 SharedBank,
int16 Trade, int16 World, int16 Limbo,
int16 Tribute, int16 TrophyTribute, int16 GuildTribute,
int16 Merchant, int16 Deleted, int16 Corpse,
int16 Bazaar, int16 Inspect, int16 RealEstate,
int16 ViewMODPC, int16 ViewMODBank, int16 ViewMODSharedBank,
int16 ViewMODLimbo, int16 AltStorage, int16 Archived,
int16 Mail, int16 GuildTrophyTribute, int16 Krono,
int16 Other
) :
Possessions(Possessions), Bank(Bank), SharedBank(SharedBank),
Trade(Trade), World(World), Limbo(Limbo),
Tribute(Tribute), TrophyTribute(TrophyTribute), GuildTribute(GuildTribute),
Merchant(Merchant), Deleted(Deleted), Corpse(Corpse),
Bazaar(Bazaar), Inspect(Inspect), RealEstate(RealEstate),
ViewMODPC(ViewMODPC), ViewMODBank(ViewMODBank), ViewMODSharedBank(ViewMODSharedBank),
ViewMODLimbo(ViewMODLimbo), AltStorage(AltStorage), Archived(Archived),
Mail(Mail), GuildTrophyTribute(GuildTrophyTribute), Krono(Krono),
Other(Other)
{ }
};
union {
InventoryTypeSize_Struct InventoryTypeSize;
int16 InventoryTypeSizeArray[25]; // should reflect EQEmu::invtype::TYPE_COUNT referenced in emu_constants.h
};
uint64 EquipmentBitmask;
uint64 GeneralBitmask;
uint64 CursorBitmask;
uint64 PossessionsBitmask;
uint64 CorpseBitmask;
int16 BagSlotCount;
int16 AugSocketCount;
bool AllowEmptyBagInBag;
bool AllowClickCastFromBag;
bool ConcatenateInvTypeLimbo;
bool AllowOverLevelEquipment;
LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry(
InventoryTypeSize_Struct InventoryTypeSize,
uint64 EquipmentBitmask,
uint64 GeneralBitmask,
uint64 CursorBitmask,
uint64 PossessionsBitmask,
uint64 CorpseBitmask,
int16 BagSlotCount,
int16 AugSocketCount,
bool AllowEmptyBagInBag,
bool AllowClickCastFromBag,
bool ConcatenateInvTypeLimbo,
bool AllowOverLevelEquipment
) :
InventoryTypeSize(InventoryTypeSize),
EquipmentBitmask(EquipmentBitmask),
GeneralBitmask(GeneralBitmask),
CursorBitmask(CursorBitmask),
PossessionsBitmask(PossessionsBitmask),
CorpseBitmask(CorpseBitmask),
BagSlotCount(BagSlotCount),
AugSocketCount(AugSocketCount),
AllowEmptyBagInBag(AllowEmptyBagInBag),
AllowClickCastFromBag(AllowClickCastFromBag),
ConcatenateInvTypeLimbo(ConcatenateInvTypeLimbo),
AllowOverLevelEquipment(AllowOverLevelEquipment)
{ }
};
void InitializeDynamicLookups();
const LookupEntry* DynamicLookup(versions::MobVersion mob_version, bool gm_flag);
const LookupEntry* DynamicNonGMLookup(versions::MobVersion mob_version);
const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version);
const LookupEntry* StaticLookup(versions::MobVersion mob_version);
} /*inventory*/
namespace behavior {
struct LookupEntry {
bool CoinHasWeight;
LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry(
bool CoinHasWeight
) :
CoinHasWeight(CoinHasWeight)
{ }
};
void InitializeDynamicLookups();
const LookupEntry* DynamicLookup(versions::MobVersion mob_version, bool gm_flag);
const LookupEntry* DynamicNonGMLookup(versions::MobVersion mob_version);
const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version);
const LookupEntry* StaticLookup(versions::MobVersion mob_version);
} /*behavior*/
namespace spells {
struct LookupEntry {
int SpellIdMax;
int SpellbookSize;
int SpellGemCount;
int LongBuffs; int LongBuffs;
int ShortBuffs; int ShortBuffs;
int DiscBuffs; int DiscBuffs;
@@ -200,69 +45,56 @@ namespace EQEmu
int NPCBuffs; int NPCBuffs;
int PetBuffs; int PetBuffs;
int MercBuffs; int MercBuffs;
LookupEntry(const LookupEntry *lookup_entry) { }
LookupEntry(
int SpellIdMax,
int SpellbookSize,
int SpellGemCount,
int LongBuffs,
int ShortBuffs,
int DiscBuffs,
int TotalBuffs,
int NPCBuffs,
int PetBuffs,
int MercBuffs
) :
SpellIdMax(SpellIdMax),
SpellbookSize(SpellbookSize),
SpellGemCount(SpellGemCount),
LongBuffs(LongBuffs),
ShortBuffs(ShortBuffs),
DiscBuffs(DiscBuffs),
TotalBuffs(TotalBuffs),
NPCBuffs(NPCBuffs),
PetBuffs(PetBuffs),
MercBuffs(MercBuffs)
{ }
}; };
void InitializeDynamicLookups(); const LookupEntry* Lookup(versions::ClientVersion client_version);
const LookupEntry* DynamicLookup(versions::ClientVersion client_version, bool gm_flag); } /*constants*/
const LookupEntry* DynamicNonGMLookup(versions::ClientVersion client_version);
const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version);
const LookupEntry* StaticLookup(versions::ClientVersion client_version);
} /*spells*/ namespace inventory {
class LookupEntry {
public:
size_t InventoryTypeSize[25]; // should reflect EQEmu::inventory::typeCount referenced in emu_constants.h
uint64 PossessionsBitmask;
size_t ItemBagSize;
size_t ItemAugSize;
bool AllowEmptyBagInBag;
bool AllowClickCastFromBag;
bool ConcatenateInvTypeLimbo;
bool AllowOverLevelEquipment;
};
const LookupEntry* Lookup(versions::MobVersion mob_version);
} /*inventory*/
namespace behavior {
class LookupEntry {
public:
bool CoinHasWeight;
};
const LookupEntry* Lookup(versions::MobVersion mob_version);
} /*behavior*/
} /*EQEmu*/ } /*EQEmu*/
namespace ClientUnknown namespace ClientUnknown
{ {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace constants { enum : bool { False = false, True = true };
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::EverQuest;
const uint32 EXPANSION_BIT = EQEmu::expansions::bitEverQuest;
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskEverQuest;
} // namespace constants
} /*ClientUnknown*/ } /*ClientUnknown*/
namespace Client62 namespace Client62
{ {
const int16 IINVALID = -1; enum : int { Invalid = -1, Null, Safety };
const int16 INULL = 0;
namespace constants { enum : bool { False = false, True = true };
const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::EverQuest;
const uint32 EXPANSION_BIT = EQEmu::expansions::bitEverQuest;
const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskEverQuest;
} // namespace constants
} /*Client62*/ } /*Client62*/
-3
View File
@@ -51,7 +51,6 @@ protected:
EmuOpcode emu_opcode; EmuOpcode emu_opcode;
EQPacket(EmuOpcode opcode, const unsigned char *buf, const uint32 len); EQPacket(EmuOpcode opcode, const unsigned char *buf, const uint32 len);
EQPacket(EmuOpcode opcode, SerializeBuffer &buf) : BasePacket(buf), emu_opcode(opcode) { };
// EQPacket(const EQPacket &p) { } // EQPacket(const EQPacket &p) { }
EQPacket() { emu_opcode=OP_Unknown; pBuffer=nullptr; size=0; } EQPacket() { emu_opcode=OP_Unknown; pBuffer=nullptr; size=0; }
@@ -105,8 +104,6 @@ public:
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op, buf, len), opcode_bypass(0) EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op, buf, len), opcode_bypass(0)
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
EQApplicationPacket(const EmuOpcode op, SerializeBuffer &buf) : EQPacket(op, buf), opcode_bypass(0)
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
bool combine(const EQApplicationPacket *rhs); bool combine(const EQApplicationPacket *rhs);
uint32 serialize (uint16 opcode, unsigned char *dest) const; uint32 serialize (uint16 opcode, unsigned char *dest) const;
uint32 Size() const { return size+app_opcode_size; } uint32 Size() const { return size+app_opcode_size; }
+32 -66
View File
@@ -306,6 +306,7 @@ union
uint32 DestructibleUnk9; uint32 DestructibleUnk9;
bool targetable_with_hotkey; bool targetable_with_hotkey;
bool show_name; bool show_name;
}; };
struct PlayerState_Struct { struct PlayerState_Struct {
@@ -375,11 +376,7 @@ struct NewZone_Struct {
/*0692*/ uint8 unknown692[8]; /*0692*/ uint8 unknown692[8];
/*0700*/ float fog_density; /*0700*/ float fog_density;
/*0704*/ uint32 SuspendBuffs; /*0704*/ uint32 SuspendBuffs;
/*0708*/ uint32 FastRegenHP; /*0704*/
/*0712*/ uint32 FastRegenMana;
/*0716*/ uint32 FastRegenEndurance;
/*0720*/ uint32 NPCAggroMaxDist;
/*0724*/
}; };
/* /*
@@ -734,7 +731,7 @@ struct BandolierItem_Struct
struct Bandolier_Struct struct Bandolier_Struct
{ {
char Name[32]; char Name[32];
BandolierItem_Struct Items[EQEmu::profile::BANDOLIER_ITEM_COUNT]; BandolierItem_Struct Items[EQEmu::legacy::BANDOLIER_ITEM_COUNT];
}; };
//len = 72 //len = 72
@@ -748,7 +745,7 @@ struct PotionBeltItem_Struct
//len = 288 //len = 288
struct PotionBelt_Struct struct PotionBelt_Struct
{ {
PotionBeltItem_Struct Items[EQEmu::profile::POTION_BELT_SIZE]; PotionBeltItem_Struct Items[EQEmu::legacy::POTION_BELT_ITEM_COUNT];
}; };
struct MovePotionToBelt_Struct struct MovePotionToBelt_Struct
@@ -852,6 +849,10 @@ struct SuspendedMinion_Struct
** OpCode: 0x006a ** OpCode: 0x006a
*/ */
static const uint32 MAX_PP_LANGUAGE = 28; static const uint32 MAX_PP_LANGUAGE = 28;
static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions
static const uint32 MAX_PP_MEMSPELL = static_cast<uint32>(EQEmu::CastingSlot::MaxGems); // Set to latest client so functions can work right -- 12
static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain
static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_INNATE_SKILL = 25;
@@ -909,7 +910,7 @@ sed -e 's/_t//g' -e 's/MAX_AA/MAX_PP_AA_ARRAY/g' \
struct PlayerProfile_Struct struct PlayerProfile_Struct
{ {
// /*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum /*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum
/*0004*/ char name[64]; // Name of player sizes not right /*0004*/ char name[64]; // Name of player sizes not right
/*0068*/ char last_name[32]; // Last name of player sizes not right /*0068*/ char last_name[32]; // Last name of player sizes not right
/*0100*/ uint32 gender; // Player Gender - 0 Male, 1 Female /*0100*/ uint32 gender; // Player Gender - 0 Male, 1 Female
@@ -931,7 +932,7 @@ struct PlayerProfile_Struct
/*0245*/ uint8 guildbanker; /*0245*/ uint8 guildbanker;
/*0246*/ uint8 unknown0246[6]; // /*0246*/ uint8 unknown0246[6]; //
/*0252*/ uint32 intoxication; /*0252*/ uint32 intoxication;
/*0256*/ uint32 spellSlotRefresh[EQEmu::spells::SPELL_GEM_COUNT]; //in ms /*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms
/*0292*/ uint32 abilitySlotRefresh; /*0292*/ uint32 abilitySlotRefresh;
/*0296*/ uint8 haircolor; // Player hair color /*0296*/ uint8 haircolor; // Player hair color
/*0297*/ uint8 beardcolor; // Player beard color /*0297*/ uint8 beardcolor; // Player beard color
@@ -970,9 +971,9 @@ struct PlayerProfile_Struct
/*2505*/ uint8 unknown2541[47]; // ? /*2505*/ uint8 unknown2541[47]; // ?
/*2552*/ uint8 languages[MAX_PP_LANGUAGE]; /*2552*/ uint8 languages[MAX_PP_LANGUAGE];
/*2580*/ uint8 unknown2616[4]; /*2580*/ uint8 unknown2616[4];
/*2584*/ uint32 spell_book[EQEmu::spells::SPELLBOOK_SIZE]; /*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
/*4632*/ uint32 mem_spells[EQEmu::spells::SPELL_GEM_COUNT]; /*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL];
/*4668*/ uint8 unknown4704[32]; // /*4668*/ uint8 unknown4704[32]; //
/*4700*/ float y; // Player y position /*4700*/ float y; // Player y position
/*4704*/ float x; // Player x position /*4704*/ float x; // Player x position
@@ -1048,7 +1049,7 @@ struct PlayerProfile_Struct
/*7212*/ uint32 tribute_points; /*7212*/ uint32 tribute_points;
/*7216*/ uint32 unknown7252; /*7216*/ uint32 unknown7252;
/*7220*/ uint32 tribute_active; //1=active /*7220*/ uint32 tribute_active; //1=active
/*7224*/ Tribute_Struct tributes[EQEmu::invtype::TRIBUTE_SIZE]; /*7224*/ Tribute_Struct tributes[EQEmu::legacy::TRIBUTE_SIZE];
/*7264*/ Disciplines_Struct disciplines; /*7264*/ Disciplines_Struct disciplines;
/*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use)
/*7744*/ char unknown7780[160]; /*7744*/ char unknown7780[160];
@@ -1075,7 +1076,7 @@ struct PlayerProfile_Struct
/*12800*/ uint32 expAA; /*12800*/ uint32 expAA;
/*12804*/ uint32 aapoints; //avaliable, unspent /*12804*/ uint32 aapoints; //avaliable, unspent
/*12808*/ uint8 unknown12844[36]; /*12808*/ uint8 unknown12844[36];
/*12844*/ Bandolier_Struct bandoliers[EQEmu::profile::BANDOLIERS_SIZE]; /*12844*/ Bandolier_Struct bandoliers[EQEmu::legacy::BANDOLIERS_SIZE];
/*14124*/ uint8 unknown14160[4506]; /*14124*/ uint8 unknown14160[4506];
/*18630*/ SuspendedMinion_Struct SuspendedMinion; // No longer in use /*18630*/ SuspendedMinion_Struct SuspendedMinion; // No longer in use
/*19240*/ uint32 timeentitledonaccount; /*19240*/ uint32 timeentitledonaccount;
@@ -1091,18 +1092,6 @@ struct PlayerProfile_Struct
/*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005) /*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005)
/*19564*/ uint32 RestTimer; /*19564*/ uint32 RestTimer;
/*19568*/ /*19568*/
// All player profile packets are translated and this overhead is ignored in out-bound packets
PlayerProfile_Struct() : m_player_profile_version(EQEmu::versions::MobVersion::Unknown) { }
EQEmu::versions::MobVersion PlayerProfileVersion() { return m_player_profile_version; }
void SetPlayerProfileVersion(EQEmu::versions::MobVersion mob_version) { m_player_profile_version = EQEmu::versions::ValidateMobVersion(mob_version); }
void SetPlayerProfileVersion(EQEmu::versions::ClientVersion client_version) { SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version)); }
private:
// No need for gm flag since pp already has one
// No need for lookup pointer since this struct is not tied to any one system
EQEmu::versions::MobVersion m_player_profile_version;
}; };
@@ -1188,25 +1177,11 @@ struct SpecialMesg_Struct
/*24*/ char message[1]; // What is being said? /*24*/ char message[1]; // What is being said?
}; };
struct SpecialMesgHeader_Struct
{
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
/*01*/ char JournalMode; // 1 and 2 go to journal
/*02*/ char language;
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
/*07*/ uint32 target_spawn_id; // Who is it being said to?
/*11*/ // speaker's name
/*xx*/ // unknown, location, client doesn't care
/*xx*/ // unknown
/*xx*/ // unknown
/*xx*/ // message
};
/* /*
** When somebody changes what they're wearing or give a pet a weapon (model changes) ** When somebody changes what they're wearing or give a pet a weapon (model changes)
** Length: 19 Bytes ** Length: 19 Bytes
*/ */
struct WearChange_Struct { struct WearChange_Struct{
/*000*/ uint16 spawn_id; /*000*/ uint16 spawn_id;
/*002*/ uint32 material; /*002*/ uint32 material;
/*006*/ uint32 unknown06; /*006*/ uint32 unknown06;
@@ -1808,15 +1783,6 @@ struct CombatAbility_Struct {
uint32 m_skill; uint32 m_skill;
}; };
// Disarm Struct incoming from Client [Size: 16]
struct Disarm_Struct
{
uint32 source;
uint32 target;
uint32 skill;
uint32 unknown;
};
//Instill Doubt //Instill Doubt
struct Instill_Doubt_Struct { struct Instill_Doubt_Struct {
uint8 i_id; uint8 i_id;
@@ -3483,8 +3449,8 @@ struct SelectTributeReply_Struct {
struct TributeInfo_Struct { struct TributeInfo_Struct {
uint32 active; //0 == inactive, 1 == active uint32 active; //0 == inactive, 1 == active
uint32 tributes[EQEmu::invtype::TRIBUTE_SIZE]; //-1 == NONE uint32 tributes[EQEmu::legacy::TRIBUTE_SIZE]; //-1 == NONE
uint32 tiers[EQEmu::invtype::TRIBUTE_SIZE]; //all 00's uint32 tiers[EQEmu::legacy::TRIBUTE_SIZE]; //all 00's
uint32 tribute_master_id; uint32 tribute_master_id;
}; };
@@ -3816,7 +3782,7 @@ struct AcceptNewTask_Struct {
//was all 0's from client, server replied with same op, all 0's //was all 0's from client, server replied with same op, all 0's
struct CancelTask_Struct { struct CancelTask_Struct {
uint32 SequenceNumber; uint32 SequenceNumber;
uint32 type; // Only seen 0x00000002 uint32 unknown4; // Only seen 0x00000002
}; };
#if 0 #if 0
@@ -3870,28 +3836,28 @@ struct AvailableTaskTrailer_Struct {
struct TaskDescriptionHeader_Struct { struct TaskDescriptionHeader_Struct {
uint32 SequenceNumber; // The order the tasks appear in the journal. 0 for first task, 1 for second, etc. uint32 SequenceNumber; // The order the tasks appear in the journal. 0 for first task, 1 for second, etc.
uint32 TaskID; uint32 TaskID;
uint8 open_window; uint32 unknown2;
uint32 task_type; uint32 unknown3;
uint32 reward_type; // if this != 4 says Ebon Crystals else Radiant Crystals uint8 unknown4;
}; };
struct TaskDescriptionData1_Struct { struct TaskDescriptionData1_Struct {
uint32 Duration; uint32 Duration;
uint32 dur_code; // if Duration == 0 uint32 unknown2;
uint32 StartTime; uint32 StartTime;
}; };
struct TaskDescriptionData2_Struct { struct TaskDescriptionData2_Struct {
uint8 has_rewards; uint32 RewardCount; // ??
uint32 coin_reward; uint32 unknown1;
uint32 xp_reward; uint32 unknown2;
uint32 faction_reward; uint16 unknown3;
//uint8 unknown4;
}; };
struct TaskDescriptionTrailer_Struct { struct TaskDescriptionTrailer_Struct {
//uint16 unknown1; // 0x0012 //uint16 unknown1; // 0x0012
uint32 Points; uint32 Points;
uint8 has_reward_selection; // uses newer reward selection window, not in all clients
}; };
struct TaskActivityHeader_Struct { struct TaskActivityHeader_Struct {
@@ -3931,11 +3897,11 @@ struct TaskActivityShort_Struct {
struct TaskActivityComplete_Struct { struct TaskActivityComplete_Struct {
uint32 TaskIndex; uint32 TaskIndex;
uint32 TaskType; // task, shared task, quest uint32 unknown2; // 0x00000002
uint32 TaskID; // must match uint32 unknown3;
uint32 ActivityID; uint32 ActivityID;
uint32 task_completed; // Broadcasts "Task '%1' Completed" it not 0 and "Task '%1' Failed." if 0 uint32 unknown4; // 0x00000001
uint32 stage_complete; // Broadcasts "Task Stage Completed" uint32 unknown5; // 0x00000001
}; };
#if 0 #if 0
@@ -4395,7 +4361,7 @@ struct AnnoyingZoneUnknown_Struct {
}; };
struct LoadSpellSet_Struct { struct LoadSpellSet_Struct {
uint32 spell[EQEmu::spells::SPELL_GEM_COUNT]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 uint32 spell[MAX_PP_MEMSPELL]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0
uint32 unknown; //there seems to be an extra field in this packet... uint32 unknown; //there seems to be an extra field in this packet...
}; };
+104 -104
View File
@@ -84,14 +84,14 @@ void EQStream::init(bool resetSession) {
OpMgr = nullptr; OpMgr = nullptr;
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "init Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
} }
EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
{ {
EQRawApplicationPacket *ap=nullptr; EQRawApplicationPacket *ap=nullptr;
LogNetcode(_L "Creating new application packet, length [{}]" __L, p->size); Log(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, p->size);
// _raw(NET__APP_CREATE_HEX, 0xFFFF, p); // _raw(NET__APP_CREATE_HEX, 0xFFFF, p);
ap = p->MakeAppPacket(); ap = p->MakeAppPacket();
return ap; return ap;
@@ -100,7 +100,7 @@ EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len) EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len)
{ {
EQRawApplicationPacket *ap=nullptr; EQRawApplicationPacket *ap=nullptr;
LogNetcode(_L "Creating new application packet, length [{}]" __L, len); Log(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, len);
ap = new EQRawApplicationPacket(buf, len); ap = new EQRawApplicationPacket(buf, len);
return ap; return ap;
} }
@@ -130,7 +130,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
} }
if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) {
LogNetcode(_L "Session not initialized, packet ignored" __L); Log(Logs::Detail, Logs::Netcode, _L "Session not initialized, packet ignored" __L);
// _raw(NET__DEBUG, 0xFFFF, p); // _raw(NET__DEBUG, 0xFFFF, p);
return; return;
} }
@@ -141,7 +141,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
while(processed < p->size) { while(processed < p->size) {
subpacket_length=*(p->pBuffer+processed); subpacket_length=*(p->pBuffer+processed);
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length); EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length);
LogNetcode(_L "Extracting combined packet of length [{}]" __L, subpacket_length); Log(Logs::Detail, Logs::Netcode, _L "Extracting combined packet of length %d" __L, subpacket_length);
// _raw(NET__NET_CREATE_HEX, 0xFFFF, subp); // _raw(NET__NET_CREATE_HEX, 0xFFFF, subp);
subp->copyInfo(p); subp->copyInfo(p);
ProcessPacket(subp); ProcessPacket(subp);
@@ -156,12 +156,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
while(processed<p->size) { while(processed<p->size) {
EQRawApplicationPacket *ap=nullptr; EQRawApplicationPacket *ap=nullptr;
if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) { if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) {
LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length); Log(Logs::Detail, Logs::Netcode, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length);
ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length); ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length);
processed+=subpacket_length+1; processed+=subpacket_length+1;
} else { } else {
subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1)); subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1));
LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length); Log(Logs::Detail, Logs::Netcode, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length);
ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length); ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length);
processed+=subpacket_length+3; processed+=subpacket_length+3;
} }
@@ -176,29 +176,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_Packet: { case OP_Packet: {
if(!p->pBuffer || (p->Size() < 4)) if(!p->pBuffer || (p->Size() < 4))
{ {
LogNetcode(_L "Received OP_Packet that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_Packet that was of malformed size" __L);
break; break;
} }
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
SeqOrder check=CompareSequence(NextInSeq,seq); SeqOrder check=CompareSequence(NextInSeq,seq);
if (check == SeqFuture) { if (check == SeqFuture) {
LogNetcode(_L "Future OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); Log(Logs::Detail, Logs::Netcode, _L "Future OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
// _raw(NET__DEBUG, seq, p); // _raw(NET__DEBUG, seq, p);
PacketQueue[seq]=p->Copy(); PacketQueue[seq]=p->Copy();
LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); Log(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size());
//SendOutOfOrderAck(seq); //SendOutOfOrderAck(seq);
} else if (check == SeqPast) { } else if (check == SeqPast) {
LogNetcode(_L "Duplicate OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); Log(Logs::Detail, Logs::Netcode, _L "Duplicate OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
// _raw(NET__DEBUG, seq, p); // _raw(NET__DEBUG, seq, p);
SendOutOfOrderAck(seq); //we already got this packet but it was out of order SendOutOfOrderAck(seq); //we already got this packet but it was out of order
} else { } else {
// In case we did queue one before as well. // In case we did queue one before as well.
EQProtocolPacket *qp=RemoveQueue(seq); EQProtocolPacket *qp=RemoveQueue(seq);
if (qp) { if (qp) {
LogNetcode("[NET_TRACE] OP_Packet: Removing older queued packet with sequence [{}]", seq); Log(Logs::General, Logs::Netcode, "[NET_TRACE] OP_Packet: Removing older queued packet with sequence %d", seq);
delete qp; delete qp;
} }
@@ -207,7 +207,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
// Check for an embedded OP_AppCombinded (protocol level 0x19) // Check for an embedded OP_AppCombinded (protocol level 0x19)
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2); EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2);
LogNetcode(_L "seq [{}], Extracting combined packet of length [{}]" __L, seq, subp->size); Log(Logs::Detail, Logs::Netcode, _L "seq %d, Extracting combined packet of length %d" __L, seq, subp->size);
// _raw(NET__NET_CREATE_HEX, seq, subp); // _raw(NET__NET_CREATE_HEX, seq, subp);
subp->copyInfo(p); subp->copyInfo(p);
ProcessPacket(subp); ProcessPacket(subp);
@@ -226,29 +226,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_Fragment: { case OP_Fragment: {
if(!p->pBuffer || (p->Size() < 4)) if(!p->pBuffer || (p->Size() < 4))
{ {
LogNetcode(_L "Received OP_Fragment that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_Fragment that was of malformed size" __L);
break; break;
} }
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
SeqOrder check=CompareSequence(NextInSeq,seq); SeqOrder check=CompareSequence(NextInSeq,seq);
if (check == SeqFuture) { if (check == SeqFuture) {
LogNetcode(_L "Future OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); Log(Logs::Detail, Logs::Netcode, _L "Future OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
// _raw(NET__DEBUG, seq, p); // _raw(NET__DEBUG, seq, p);
PacketQueue[seq]=p->Copy(); PacketQueue[seq]=p->Copy();
LogNetcode(_L "OP_Fragment Queue size=[{}]" __L, PacketQueue.size()); Log(Logs::Detail, Logs::Netcode, _L "OP_Fragment Queue size=%d" __L, PacketQueue.size());
//SendOutOfOrderAck(seq); //SendOutOfOrderAck(seq);
} else if (check == SeqPast) { } else if (check == SeqPast) {
LogNetcode(_L "Duplicate OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); Log(Logs::Detail, Logs::Netcode, _L "Duplicate OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq);
// _raw(NET__DEBUG, seq, p); // _raw(NET__DEBUG, seq, p);
SendOutOfOrderAck(seq); SendOutOfOrderAck(seq);
} else { } else {
// In case we did queue one before as well. // In case we did queue one before as well.
EQProtocolPacket *qp=RemoveQueue(seq); EQProtocolPacket *qp=RemoveQueue(seq);
if (qp) { if (qp) {
LogNetcode("[NET_TRACE] OP_Fragment: Removing older queued packet with sequence [{}]", seq); Log(Logs::General, Logs::Netcode, "[NET_TRACE] OP_Fragment: Removing older queued packet with sequence %d", seq);
delete qp; delete qp;
} }
SetNextAckToSend(seq); SetNextAckToSend(seq);
@@ -256,18 +256,18 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
if (oversize_buffer) { if (oversize_buffer) {
memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2); memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2);
oversize_offset+=p->size-2; oversize_offset+=p->size-2;
LogNetcode(_L "Fragment of oversized of length [{}], seq [{}]: now at [{}]/[{}]" __L, p->size-2, seq, oversize_offset, oversize_length); Log(Logs::Detail, Logs::Netcode, _L "Fragment of oversized of length %d, seq %d: now at %d/%d" __L, p->size-2, seq, oversize_offset, oversize_length);
if (oversize_offset==oversize_length) { if (oversize_offset==oversize_length) {
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset); EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset);
LogNetcode(_L "seq [{}], Extracting combined oversize packet of length [{}]" __L, seq, subp->size); Log(Logs::Detail, Logs::Netcode, _L "seq %d, Extracting combined oversize packet of length %d" __L, seq, subp->size);
//// _raw(NET__NET_CREATE_HEX, subp); //// _raw(NET__NET_CREATE_HEX, subp);
subp->copyInfo(p); subp->copyInfo(p);
ProcessPacket(subp); ProcessPacket(subp);
delete subp; delete subp;
} else { } else {
EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset); EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset);
LogNetcode(_L "seq [{}], completed combined oversize packet of length [{}]" __L, seq, ap->size); Log(Logs::Detail, Logs::Netcode, _L "seq %d, completed combined oversize packet of length %d" __L, seq, ap->size);
if (ap) { if (ap) {
ap->copyInfo(p); ap->copyInfo(p);
InboundQueuePush(ap); InboundQueuePush(ap);
@@ -282,20 +282,20 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
oversize_buffer=new unsigned char[oversize_length]; oversize_buffer=new unsigned char[oversize_length];
memcpy(oversize_buffer,p->pBuffer+6,p->size-6); memcpy(oversize_buffer,p->pBuffer+6,p->size-6);
oversize_offset=p->size-6; oversize_offset=p->size-6;
LogNetcode(_L "First fragment of oversized of seq [{}]: now at [{}]/[{}]" __L, seq, oversize_offset, oversize_length); Log(Logs::Detail, Logs::Netcode, _L "First fragment of oversized of seq %d: now at %d/%d" __L, seq, oversize_offset, oversize_length);
} }
} }
} }
break; break;
case OP_KeepAlive: { case OP_KeepAlive: {
NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size)); NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size));
LogNetcode(_L "Received and queued reply to keep alive" __L); Log(Logs::Detail, Logs::Netcode, _L "Received and queued reply to keep alive" __L);
} }
break; break;
case OP_Ack: { case OP_Ack: {
if(!p->pBuffer || (p->Size() < 4)) if(!p->pBuffer || (p->Size() < 4))
{ {
LogNetcode(_L "Received OP_Ack that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_Ack that was of malformed size" __L);
break; break;
} }
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
@@ -309,11 +309,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_SessionRequest: { case OP_SessionRequest: {
if(p->Size() < sizeof(SessionRequest)) if(p->Size() < sizeof(SessionRequest))
{ {
LogNetcode(_L "Received OP_SessionRequest that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest that was of malformed size" __L);
break; break;
} }
if (GetState()==ESTABLISHED) { if (GetState()==ESTABLISHED) {
LogNetcode(_L "Received OP_SessionRequest in ESTABLISHED state ([{}]) streamactive ([{}]) attempt ([{}])" __L, GetState(),streamactive,sessionAttempts); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest in ESTABLISHED state (%d) streamactive (%i) attempt (%i)" __L, GetState(),streamactive,sessionAttempts);
// client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case // client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case
// streamactive means we identified the opcode for the stream, we cannot re-establish this connection // streamactive means we identified the opcode for the stream, we cannot re-establish this connection
@@ -331,7 +331,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
SessionRequest *Request=(SessionRequest *)p->pBuffer; SessionRequest *Request=(SessionRequest *)p->pBuffer;
Session=ntohl(Request->Session); Session=ntohl(Request->Session);
SetMaxLen(ntohl(Request->MaxLength)); SetMaxLen(ntohl(Request->MaxLength));
LogNetcode(_L "Received OP_SessionRequest: session [{}], maxlen [{}]" __L, (unsigned long)Session, MaxLen); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest: session %lu, maxlen %d" __L, (unsigned long)Session, MaxLen);
SetState(ESTABLISHED); SetState(ESTABLISHED);
Key=0x11223344; Key=0x11223344;
SendSessionResponse(); SendSessionResponse();
@@ -340,7 +340,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_SessionResponse: { case OP_SessionResponse: {
if(p->Size() < sizeof(SessionResponse)) if(p->Size() < sizeof(SessionResponse))
{ {
LogNetcode(_L "Received OP_SessionResponse that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionResponse that was of malformed size" __L);
break; break;
} }
@@ -356,7 +356,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
compressed=(Response->Format&FLAG_COMPRESSED); compressed=(Response->Format&FLAG_COMPRESSED);
encoded=(Response->Format&FLAG_ENCODED); encoded=(Response->Format&FLAG_ENCODED);
LogNetcode(_L "Received OP_SessionResponse: session [{}], maxlen [{}], key [{}], compressed? [{}], encoded? [{}]" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no"); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionResponse: session %lu, maxlen %d, key %lu, compressed? %s, encoded? %s" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no");
// Kinda kludgy, but trie for now // Kinda kludgy, but trie for now
if (StreamType==UnknownStream) { if (StreamType==UnknownStream) {
@@ -379,17 +379,17 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
EQStreamState state = GetState(); EQStreamState state = GetState();
if(state == ESTABLISHED) { if(state == ESTABLISHED) {
//client initiated disconnect? //client initiated disconnect?
LogNetcode(_L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect" __L); Log(Logs::Detail, Logs::Netcode, _L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect." __L);
_SendDisconnect(); _SendDisconnect();
SetState(CLOSED); SetState(CLOSED);
} else if(state == CLOSING) { } else if(state == CLOSING) {
//we were waiting for this anyways, ignore pending messages, send the reply and be closed. //we were waiting for this anyways, ignore pending messages, send the reply and be closed.
LogNetcode(_L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though." __L);
_SendDisconnect(); _SendDisconnect();
SetState(CLOSED); SetState(CLOSED);
} else { } else {
//we are expecting this (or have already gotten it, but dont care either way) //we are expecting this (or have already gotten it, but dont care either way)
LogNetcode(_L "Received expected OP_SessionDisconnect. Moving to closed state" __L); Log(Logs::Detail, Logs::Netcode, _L "Received expected OP_SessionDisconnect. Moving to closed state." __L);
SetState(CLOSED); SetState(CLOSED);
} }
} }
@@ -397,14 +397,14 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_OutOfOrderAck: { case OP_OutOfOrderAck: {
if(!p->pBuffer || (p->Size() < 4)) if(!p->pBuffer || (p->Size() < 4))
{ {
LogNetcode(_L "Received OP_OutOfOrderAck that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck that was of malformed size" __L);
break; break;
} }
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
MOutboundQueue.lock(); MOutboundQueue.lock();
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
//if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid.
@@ -414,7 +414,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
uint16 sqsize = SequencedQueue.size(); uint16 sqsize = SequencedQueue.size();
uint16 index = seq - SequencedBase; uint16 index = seq - SequencedBase;
LogNetcode(_L "OP_OutOfOrderAck marking packet acked in queue (queue index = [{}], queue size = [{}])" __L, index, sqsize); Log(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize);
if (index < sqsize) { if (index < sqsize) {
SequencedQueue[index]->acked = true; SequencedQueue[index]->acked = true;
// flag packets for a resend // flag packets for a resend
@@ -423,7 +423,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) { for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) {
if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) { if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) {
(*sitr)->sent_time = 0; (*sitr)->sent_time = 0;
LogNetcode(_L "OP_OutOfOrderAck Flagging packet [{}] for retransmission" __L, SequencedBase + count); Log(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck Flagging packet %d for retransmission" __L, SequencedBase + count);
} }
} }
} }
@@ -432,11 +432,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
retransmittimer = Timer::GetCurrentTime(); retransmittimer = Timer::GetCurrentTime();
} }
} else { } else {
LogNetcode(_L "Received OP_OutOfOrderAck for out-of-window [{}]. Window ([{}]->[{}])" __L, seq, SequencedBase, NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq);
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "Post-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
MOutboundQueue.unlock(); MOutboundQueue.unlock();
@@ -445,7 +445,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_SessionStatRequest: { case OP_SessionStatRequest: {
if(p->Size() < sizeof(ClientSessionStats)) if(p->Size() < sizeof(ClientSessionStats))
{ {
LogNetcode(_L "Received OP_SessionStatRequest that was of malformed size" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L);
break; break;
} }
ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer; ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer;
@@ -468,7 +468,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
retransmittimeout += 300; retransmittimeout += 300;
if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX) if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
retransmittimeout = RETRANSMIT_TIMEOUT_MAX; retransmittimeout = RETRANSMIT_TIMEOUT_MAX;
LogNetcode(_L "Retransmit timeout recalculated to [{}]ms" __L, retransmittimeout); Log(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout);
} }
} }
@@ -485,11 +485,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
} }
break; break;
case OP_SessionStatResponse: { case OP_SessionStatResponse: {
LogNetcode(_L "Received OP_SessionStatResponse. Ignoring" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatResponse. Ignoring." __L);
} }
break; break;
case OP_OutOfSession: { case OP_OutOfSession: {
LogNetcode(_L "Received OP_OutOfSession. Ignoring" __L); Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfSession. Ignoring." __L);
} }
break; break;
default: default:
@@ -520,7 +520,7 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
return; return;
if(OpMgr == nullptr || *OpMgr == nullptr) { if(OpMgr == nullptr || *OpMgr == nullptr) {
LogNetcode(_L "Packet enqueued into a stream with no opcode manager, dropping" __L); Log(Logs::Detail, Logs::Netcode, _L "Packet enqueued into a stream with no opcode manager, dropping." __L);
delete pack; delete pack;
return; return;
} }
@@ -559,18 +559,18 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
// Convert the EQApplicationPacket to 1 or more EQProtocolPackets // Convert the EQApplicationPacket to 1 or more EQProtocolPackets
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2)
LogNetcode(_L "Making oversized packet, len [{}]" __L, p->Size()); Log(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->Size());
auto tmpbuff = new unsigned char[p->size + 3]; auto tmpbuff = new unsigned char[p->size + 3];
length=p->serialize(opcode, tmpbuff); length=p->serialize(opcode, tmpbuff);
if (length != p->Size()) if (length != p->Size())
LogNetcode(_L "Packet adjustment, len [{}] to [{}]" __L, p->Size(), length); Log(Logs::Detail, Logs::Netcode, _L "Packet adjustment, len %d to %d" __L, p->Size(), length);
auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4); auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4);
*(uint32 *)(out->pBuffer+2)=htonl(length); *(uint32 *)(out->pBuffer+2)=htonl(length);
used=MaxLen-10; used=MaxLen-10;
memcpy(out->pBuffer+6,tmpbuff,used); memcpy(out->pBuffer+6,tmpbuff,used);
LogNetcode(_L "First fragment: used [{}]/[{}]. Payload size [{}] in the packet" __L, used, length, p->size); Log(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Payload size %d in the packet" __L, used, length, p->size);
SequencedPush(out); SequencedPush(out);
@@ -581,7 +581,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
out->size=chunksize+2; out->size=chunksize+2;
SequencedPush(out); SequencedPush(out);
used+=chunksize; used+=chunksize;
LogNetcode(_L "Subsequent fragment: len [{}], used [{}]/[{}]" __L, chunksize, used, length); Log(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, length);
} }
delete p; delete p;
delete[] tmpbuff; delete[] tmpbuff;
@@ -623,7 +623,7 @@ void EQStream::SequencedPush(EQProtocolPacket *p)
void EQStream::NonSequencedPush(EQProtocolPacket *p) void EQStream::NonSequencedPush(EQProtocolPacket *p)
{ {
MOutboundQueue.lock(); MOutboundQueue.lock();
LogNetcode(_L "Pushing non-sequenced packet of length [{}]" __L, p->size); Log(Logs::Detail, Logs::Netcode, _L "Pushing non-sequenced packet of length %d" __L, p->size);
NonSequencedQueue.push(p); NonSequencedQueue.push(p);
MOutboundQueue.unlock(); MOutboundQueue.unlock();
} }
@@ -631,14 +631,14 @@ void EQStream::NonSequencedPush(EQProtocolPacket *p)
void EQStream::SendAck(uint16 seq) void EQStream::SendAck(uint16 seq)
{ {
uint16 Seq=htons(seq); uint16 Seq=htons(seq);
LogNetcode(_L "Sending ack with sequence [{}]" __L, seq); Log(Logs::Detail, Logs::Netcode, _L "Sending ack with sequence %d" __L, seq);
SetLastAckSent(seq); SetLastAckSent(seq);
NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16))); NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16)));
} }
void EQStream::SendOutOfOrderAck(uint16 seq) void EQStream::SendOutOfOrderAck(uint16 seq)
{ {
LogNetcode(_L "Sending out of order ack with sequence [{}]" __L, seq); Log(Logs::Detail, Logs::Netcode, _L "Sending out of order ack with sequence %d" __L, seq);
uint16 Seq=htons(seq); uint16 Seq=htons(seq);
NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16))); NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16)));
} }
@@ -688,24 +688,24 @@ void EQStream::Write(int eq_fd)
// If we don't have a packet to try to combine into, use this one as the base // If we don't have a packet to try to combine into, use this one as the base
// And remove it form the queue // And remove it form the queue
p = NonSequencedQueue.front(); p = NonSequencedQueue.front();
LogNetcode(_L "Starting combined packet with non-seq packet of len [{}]" __L, p->size); Log(Logs::Detail, Logs::Netcode, _L "Starting combined packet with non-seq packet of len %d" __L, p->size);
NonSequencedQueue.pop(); NonSequencedQueue.pop();
} else if (!p->combine(NonSequencedQueue.front())) { } else if (!p->combine(NonSequencedQueue.front())) {
// Trying to combine this packet with the base didn't work (too big maybe) // Trying to combine this packet with the base didn't work (too big maybe)
// So just send the base packet (we'll try this packet again later) // So just send the base packet (we'll try this packet again later)
LogNetcode(_L "Combined packet full at len [{}], next non-seq packet is len [{}]" __L, p->size, (NonSequencedQueue.front())->size); Log(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next non-seq packet is len %d" __L, p->size, (NonSequencedQueue.front())->size);
ReadyToSend.push(p); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
p=nullptr; p=nullptr;
if (BytesWritten > threshold) { if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair // Sent enough this round, lets stop to be fair
LogNetcode(_L "Exceeded write threshold in nonseq ([{}] > [{}])" __L, BytesWritten, threshold); Log(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in nonseq (%d > %d)" __L, BytesWritten, threshold);
break; break;
} }
} else { } else {
// Combine worked, so just remove this packet and it's spot in the queue // Combine worked, so just remove this packet and it's spot in the queue
LogNetcode(_L "Combined non-seq packet of len [{}], yeilding [{}] combined" __L, (NonSequencedQueue.front())->size, p->size); Log(Logs::Detail, Logs::Netcode, _L "Combined non-seq packet of len %d, yeilding %d combined." __L, (NonSequencedQueue.front())->size, p->size);
delete NonSequencedQueue.front(); delete NonSequencedQueue.front();
NonSequencedQueue.pop(); NonSequencedQueue.pop();
} }
@@ -718,7 +718,7 @@ void EQStream::Write(int eq_fd)
uint16 seq_send = SequencedBase + count; //just for logging... uint16 seq_send = SequencedBase + count; //just for logging...
if(SequencedQueue.empty()) { if(SequencedQueue.empty()) {
LogNetcode(_L "Tried to write a packet with an empty queue ([{}] is past next out [{}])" __L, seq_send, NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq);
SeqEmpty=true; SeqEmpty=true;
continue; continue;
} }
@@ -728,35 +728,35 @@ void EQStream::Write(int eq_fd)
++sitr; ++sitr;
++count; ++count;
if (p) { if (p) {
LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); Log(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size);
ReadyToSend.push(p); ReadyToSend.push(p);
BytesWritten += p->size; BytesWritten += p->size;
p = nullptr; p = nullptr;
} }
LogNetcode(_L "Not retransmitting seq packet [{}] because already marked as acked" __L, seq_send); Log(Logs::Detail, Logs::Netcode, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send);
} else if (!p) { } else if (!p) {
// If we don't have a packet to try to combine into, use this one as the base // If we don't have a packet to try to combine into, use this one as the base
// Copy it first as it will still live until it is acked // Copy it first as it will still live until it is acked
p=(*sitr)->Copy(); p=(*sitr)->Copy();
LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size); Log(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
(*sitr)->sent_time = Timer::GetCurrentTime(); (*sitr)->sent_time = Timer::GetCurrentTime();
++sitr; ++sitr;
++count; ++count;
} else if (!p->combine(*sitr)) { } else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe) // Trying to combine this packet with the base didn't work (too big maybe)
// So just send the base packet (we'll try this packet again later) // So just send the base packet (we'll try this packet again later)
LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send + 1, (*sitr)->size); Log(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send + 1, (*sitr)->size);
ReadyToSend.push(p); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
p=nullptr; p=nullptr;
if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) { if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair // Sent enough this round, lets stop to be fair
LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold); Log(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold);
break; break;
} }
} else { } else {
// Combine worked // Combine worked
LogNetcode(_L "Combined seq packet [{}] of len [{}], yeilding [{}] combined" __L, seq_send, (*sitr)->size, p->size); Log(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size);
(*sitr)->sent_time = Timer::GetCurrentTime(); (*sitr)->sent_time = Timer::GetCurrentTime();
++sitr; ++sitr;
++count; ++count;
@@ -766,7 +766,7 @@ void EQStream::Write(int eq_fd)
++sitr; ++sitr;
++count; ++count;
if (p) { if (p) {
LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); Log(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size);
ReadyToSend.push(p); ReadyToSend.push(p);
BytesWritten += p->size; BytesWritten += p->size;
p = nullptr; p = nullptr;
@@ -776,25 +776,25 @@ void EQStream::Write(int eq_fd)
// Copy it first as it will still live until it is acked // Copy it first as it will still live until it is acked
p=(*sitr)->Copy(); p=(*sitr)->Copy();
(*sitr)->sent_time = Timer::GetCurrentTime(); (*sitr)->sent_time = Timer::GetCurrentTime();
LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size); Log(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size);
++sitr; ++sitr;
++count; ++count;
} else if (!p->combine(*sitr)) { } else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe) // Trying to combine this packet with the base didn't work (too big maybe)
// So just send the base packet (we'll try this packet again later) // So just send the base packet (we'll try this packet again later)
LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send, (*sitr)->size); Log(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size);
ReadyToSend.push(p); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
p=nullptr; p=nullptr;
if (BytesWritten > threshold) { if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair // Sent enough this round, lets stop to be fair
LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold); Log(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold);
break; break;
} }
} else { } else {
// Combine worked // Combine worked
LogNetcode(_L "Combined seq packet [{}] of len [{}], yielding [{}] combined" __L, seq_send, (*sitr)->size, p->size); Log(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yielding %d combined." __L, seq_send, (*sitr)->size, p->size);
(*sitr)->sent_time = Timer::GetCurrentTime(); (*sitr)->sent_time = Timer::GetCurrentTime();
++sitr; ++sitr;
++count; ++count;
@@ -802,7 +802,7 @@ void EQStream::Write(int eq_fd)
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "Post send Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
} else { } else {
// No more sequenced packets // No more sequenced packets
@@ -814,7 +814,7 @@ void EQStream::Write(int eq_fd)
// We have a packet still, must have run out of both seq and non-seq, so send it // We have a packet still, must have run out of both seq and non-seq, so send it
if (p) { if (p) {
LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); Log(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size);
ReadyToSend.push(p); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
} }
@@ -831,7 +831,7 @@ void EQStream::Write(int eq_fd)
if(SeqEmpty && NonSeqEmpty) { if(SeqEmpty && NonSeqEmpty) {
//no more data to send //no more data to send
if(CheckState(CLOSING)) { if(CheckState(CLOSING)) {
LogNetcode(_L "All outgoing data flushed, closing stream" __L ); Log(Logs::Detail, Logs::Netcode, _L "All outgoing data flushed, closing stream." __L );
//we are waiting for the queues to empty, now we can do our disconnect. //we are waiting for the queues to empty, now we can do our disconnect.
//this packet will not actually go out until the next call to Write(). //this packet will not actually go out until the next call to Write().
_SendDisconnect(); _SendDisconnect();
@@ -910,7 +910,7 @@ void EQStream::SendSessionRequest()
Request->Session=htonl(time(nullptr)); Request->Session=htonl(time(nullptr));
Request->MaxLength=htonl(512); Request->MaxLength=htonl(512);
LogNetcode(_L "Sending OP_SessionRequest: session [{}], maxlen=[{}]" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength)); Log(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionRequest: session %lu, maxlen=%d" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength));
NonSequencedPush(out); NonSequencedPush(out);
} }
@@ -924,7 +924,7 @@ void EQStream::_SendDisconnect()
*(uint32 *)out->pBuffer=htonl(Session); *(uint32 *)out->pBuffer=htonl(Session);
NonSequencedPush(out); NonSequencedPush(out);
LogNetcode(_L "Sending OP_SessionDisconnect: session [{}]" __L, (unsigned long)Session); Log(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionDisconnect: session %lu" __L, (unsigned long)Session);
} }
void EQStream::InboundQueuePush(EQRawApplicationPacket *p) void EQStream::InboundQueuePush(EQRawApplicationPacket *p)
@@ -976,7 +976,7 @@ EQRawApplicationPacket *p=nullptr;
if(OpMgr != nullptr && *OpMgr != nullptr) { if(OpMgr != nullptr && *OpMgr != nullptr) {
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
if(emu_op == OP_Unknown) { if(emu_op == OP_Unknown) {
LogNetcode("Unable to convert EQ opcode {:#04x} to an Application opcode", p->opcode); Log(Logs::General, Logs::Netcode, "Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode);
} }
p->SetOpcode(emu_op); p->SetOpcode(emu_op);
@@ -1004,7 +1004,7 @@ void EQStream::InboundQueueClear()
{ {
EQApplicationPacket *p=nullptr; EQApplicationPacket *p=nullptr;
LogNetcode(_L "Clearing inbound queue" __L); Log(Logs::Detail, Logs::Netcode, _L "Clearing inbound queue" __L);
MInboundQueue.lock(); MInboundQueue.lock();
if (!InboundQueue.empty()) { if (!InboundQueue.empty()) {
@@ -1047,7 +1047,7 @@ void EQStream::OutboundQueueClear()
{ {
EQProtocolPacket *p=nullptr; EQProtocolPacket *p=nullptr;
LogNetcode(_L "Clearing outbound queue" __L); Log(Logs::Detail, Logs::Netcode, _L "Clearing outbound queue" __L);
MOutboundQueue.lock(); MOutboundQueue.lock();
while(!NonSequencedQueue.empty()) { while(!NonSequencedQueue.empty()) {
@@ -1069,7 +1069,7 @@ void EQStream::PacketQueueClear()
{ {
EQProtocolPacket *p=nullptr; EQProtocolPacket *p=nullptr;
LogNetcode(_L "Clearing future packet queue" __L); Log(Logs::Detail, Logs::Netcode, _L "Clearing future packet queue" __L);
if(!PacketQueue.empty()) { if(!PacketQueue.empty()) {
std::map<unsigned short,EQProtocolPacket *>::iterator itr; std::map<unsigned short,EQProtocolPacket *>::iterator itr;
@@ -1101,7 +1101,7 @@ void EQStream::Process(const unsigned char *buffer, const uint32 length)
delete p; delete p;
ProcessQueue(); ProcessQueue();
} else { } else {
LogNetcode(_L "Incoming packet failed checksum" __L); Log(Logs::Detail, Logs::Netcode, _L "Incoming packet failed checksum" __L);
} }
} }
@@ -1132,23 +1132,23 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
SeqOrder ord = CompareSequence(SequencedBase, seq); SeqOrder ord = CompareSequence(SequencedBase, seq);
if(ord == SeqInOrder) { if(ord == SeqInOrder) {
//they are not acking anything new... //they are not acking anything new...
LogNetcode(_L "Received an ack with no window advancement (seq [{}])" __L, seq); Log(Logs::Detail, Logs::Netcode, _L "Received an ack with no window advancement (seq %d)." __L, seq);
} else if(ord == SeqPast) { } else if(ord == SeqPast) {
//they are nacking blocks going back before our buffer, wtf? //they are nacking blocks going back before our buffer, wtf?
LogNetcode(_L "Received an ack with backward window advancement (they gave [{}], our window starts at [{}]). This is bad" __L, seq, SequencedBase); Log(Logs::Detail, Logs::Netcode, _L "Received an ack with backward window advancement (they gave %d, our window starts at %d). This is bad." __L, seq, SequencedBase);
} else { } else {
LogNetcode(_L "Received an ack up through sequence [{}]. Our base is [{}]" __L, seq, SequencedBase); Log(Logs::Detail, Logs::Netcode, _L "Received an ack up through sequence %d. Our base is %d." __L, seq, SequencedBase);
//this is a good ack, we get to ack some blocks. //this is a good ack, we get to ack some blocks.
seq++; //we stop at the block right after their ack, counting on the wrap of both numbers. seq++; //we stop at the block right after their ack, counting on the wrap of both numbers.
while(SequencedBase != seq) { while(SequencedBase != seq) {
if(SequencedQueue.empty()) { if(SequencedQueue.empty()) {
LogNetcode(_L "OUT OF PACKETS acked packet with sequence [{}]. Next send is [{}] before this" __L, (unsigned long)SequencedBase, SequencedQueue.size()); Log(Logs::Detail, Logs::Netcode, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, SequencedQueue.size());
SequencedBase = NextOutSeq; SequencedBase = NextOutSeq;
break; break;
} }
LogNetcode(_L "Removing acked packet with sequence [{}]" __L, (unsigned long)SequencedBase); Log(Logs::Detail, Logs::Netcode, _L "Removing acked packet with sequence %lu." __L, (unsigned long)SequencedBase);
//clean out the acked packet //clean out the acked packet
delete SequencedQueue.front(); delete SequencedQueue.front();
SequencedQueue.pop_front(); SequencedQueue.pop_front();
@@ -1156,7 +1156,7 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
SequencedBase++; SequencedBase++;
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
LogNetcode(_L "Post-Ack on [{}] Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); Log(Logs::Detail, Logs::Netcode, _L "Post-Ack on %d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq);
} }
} }
@@ -1166,7 +1166,7 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
void EQStream::SetNextAckToSend(uint32 seq) void EQStream::SetNextAckToSend(uint32 seq)
{ {
MAcks.lock(); MAcks.lock();
LogNetcode(_L "Set Next Ack To Send to [{}]" __L, (unsigned long)seq); Log(Logs::Detail, Logs::Netcode, _L "Set Next Ack To Send to %lu" __L, (unsigned long)seq);
NextAckToSend=seq; NextAckToSend=seq;
MAcks.unlock(); MAcks.unlock();
} }
@@ -1174,7 +1174,7 @@ void EQStream::SetNextAckToSend(uint32 seq)
void EQStream::SetLastAckSent(uint32 seq) void EQStream::SetLastAckSent(uint32 seq)
{ {
MAcks.lock(); MAcks.lock();
LogNetcode(_L "Set Last Ack Sent to [{}]" __L, (unsigned long)seq); Log(Logs::Detail, Logs::Netcode, _L "Set Last Ack Sent to %lu" __L, (unsigned long)seq);
LastAckSent=seq; LastAckSent=seq;
MAcks.unlock(); MAcks.unlock();
} }
@@ -1187,10 +1187,10 @@ void EQStream::ProcessQueue()
EQProtocolPacket *qp=nullptr; EQProtocolPacket *qp=nullptr;
while((qp=RemoveQueue(NextInSeq))!=nullptr) { while((qp=RemoveQueue(NextInSeq))!=nullptr) {
LogNetcode(_L "Processing Queued Packet: Seq=[{}]" __L, NextInSeq); Log(Logs::Detail, Logs::Netcode, _L "Processing Queued Packet: Seq=%d" __L, NextInSeq);
ProcessPacket(qp); ProcessPacket(qp);
delete qp; delete qp;
LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); Log(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size());
} }
} }
@@ -1201,21 +1201,21 @@ EQProtocolPacket *qp=nullptr;
if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) { if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) {
qp=itr->second; qp=itr->second;
PacketQueue.erase(itr); PacketQueue.erase(itr);
LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); Log(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size());
} }
return qp; return qp;
} }
void EQStream::SetStreamType(EQStreamType type) void EQStream::SetStreamType(EQStreamType type)
{ {
LogNetcode(_L "Changing stream type from [{}] to [{}]" __L, StreamTypeString(StreamType), StreamTypeString(type)); Log(Logs::Detail, Logs::Netcode, _L "Changing stream type from %s to %s" __L, StreamTypeString(StreamType), StreamTypeString(type));
StreamType=type; StreamType=type;
switch (StreamType) { switch (StreamType) {
case LoginStream: case LoginStream:
app_opcode_size=1; app_opcode_size=1;
compressed=false; compressed=false;
encoded=false; encoded=false;
LogNetcode(_L "Login stream has app opcode size [{}], is not compressed or encoded" __L, app_opcode_size); Log(Logs::Detail, Logs::Netcode, _L "Login stream has app opcode size %d, is not compressed or encoded." __L, app_opcode_size);
break; break;
case ChatOrMailStream: case ChatOrMailStream:
case ChatStream: case ChatStream:
@@ -1223,7 +1223,7 @@ void EQStream::SetStreamType(EQStreamType type)
app_opcode_size=1; app_opcode_size=1;
compressed=false; compressed=false;
encoded=true; encoded=true;
LogNetcode(_L "Chat/Mail stream has app opcode size [{}], is not compressed, and is encoded" __L, app_opcode_size); Log(Logs::Detail, Logs::Netcode, _L "Chat/Mail stream has app opcode size %d, is not compressed, and is encoded." __L, app_opcode_size);
break; break;
case ZoneStream: case ZoneStream:
case WorldStream: case WorldStream:
@@ -1231,7 +1231,7 @@ void EQStream::SetStreamType(EQStreamType type)
app_opcode_size=2; app_opcode_size=2;
compressed=true; compressed=true;
encoded=false; encoded=false;
LogNetcode(_L "World/Zone stream has app opcode size [{}], is compressed, and is not encoded" __L, app_opcode_size); Log(Logs::Detail, Logs::Netcode, _L "World/Zone stream has app opcode size %d, is compressed, and is not encoded." __L, app_opcode_size);
break; break;
} }
} }
@@ -1281,7 +1281,7 @@ EQStream::SeqOrder EQStream::CompareSequence(uint16 expected_seq , uint16 seq)
void EQStream::SetState(EQStreamState state) { void EQStream::SetState(EQStreamState state) {
MState.lock(); MState.lock();
LogNetcode(_L "Changing state from [{}] to [{}]" __L, State, state); Log(Logs::Detail, Logs::Netcode, _L "Changing state from %d to %d" __L, State, state);
State=state; State=state;
MState.unlock(); MState.unlock();
} }
@@ -1293,29 +1293,29 @@ void EQStream::CheckTimeout(uint32 now, uint32 timeout) {
EQStreamState orig_state = GetState(); EQStreamState orig_state = GetState();
if (orig_state == CLOSING && !outgoing_data) { if (orig_state == CLOSING && !outgoing_data) {
LogNetcode(_L "Out of data in closing state, disconnecting" __L); Log(Logs::Detail, Logs::Netcode, _L "Out of data in closing state, disconnecting." __L);
_SendDisconnect(); _SendDisconnect();
SetState(DISCONNECTING); SetState(DISCONNECTING);
} else if (LastPacket && (now-LastPacket) > timeout) { } else if (LastPacket && (now-LastPacket) > timeout) {
switch(orig_state) { switch(orig_state) {
case CLOSING: case CLOSING:
//if we time out in the closing state, they are not acking us, just give up //if we time out in the closing state, they are not acking us, just give up
LogNetcode(_L "Timeout expired in closing state. Moving to closed state" __L); Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in closing state. Moving to closed state." __L);
_SendDisconnect(); _SendDisconnect();
SetState(CLOSED); SetState(CLOSED);
break; break;
case DISCONNECTING: case DISCONNECTING:
//we timed out waiting for them to send us the disconnect reply, just give up. //we timed out waiting for them to send us the disconnect reply, just give up.
LogNetcode(_L "Timeout expired in disconnecting state. Moving to closed state" __L); Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in disconnecting state. Moving to closed state." __L);
SetState(CLOSED); SetState(CLOSED);
break; break;
case CLOSED: case CLOSED:
LogNetcode(_L "Timeout expired in closed state??" __L); Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in closed state??" __L);
break; break;
case ESTABLISHED: case ESTABLISHED:
//we timed out during normal operation. Try to be nice about it. //we timed out during normal operation. Try to be nice about it.
//we will almost certainly time out again waiting for the disconnect reply, but oh well. //we will almost certainly time out again waiting for the disconnect reply, but oh well.
LogNetcode(_L "Timeout expired in established state. Closing connection" __L); Log(Logs::Detail, Logs::Netcode, _L "Timeout expired in established state. Closing connection." __L);
_SendDisconnect(); _SendDisconnect();
SetState(DISCONNECTING); SetState(DISCONNECTING);
break; break;
@@ -1342,7 +1342,7 @@ void EQStream::Decay()
for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) { for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) {
if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) { if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) {
(*sitr)->sent_time = 0; (*sitr)->sent_time = 0;
LogNetcode(_L "Timeout exceeded for seq [{}]. Flagging packet for retransmission" __L, SequencedBase + count); Log(Logs::Detail, Logs::Netcode, _L "Timeout exceeded for seq %d. Flagging packet for retransmission" __L, SequencedBase + count);
} }
} }
MOutboundQueue.unlock(); MOutboundQueue.unlock();
@@ -1384,12 +1384,12 @@ void EQStream::AdjustRates(uint32 average_delta)
void EQStream::Close() { void EQStream::Close() {
if(HasOutgoingData()) { if(HasOutgoingData()) {
//there is pending data, wait for it to go out. //there is pending data, wait for it to go out.
LogNetcode(_L "Stream requested to Close(), but there is pending data, waiting for it" __L); Log(Logs::Detail, Logs::Netcode, _L "Stream requested to Close(), but there is pending data, waiting for it." __L);
SetState(CLOSING); SetState(CLOSING);
} else { } else {
//otherwise, we are done, we can drop immediately. //otherwise, we are done, we can drop immediately.
_SendDisconnect(); _SendDisconnect();
LogNetcode(_L "Stream closing immediate due to Close()" __L); Log(Logs::Detail, Logs::Netcode, _L "Stream closing immediate due to Close()" __L);
SetState(DISCONNECTING); SetState(DISCONNECTING);
} }
} }
@@ -1417,19 +1417,19 @@ EQStream::MatchState EQStream::CheckSignature(const Signature *sig) {
} else if(p->opcode == sig->first_eq_opcode) { } else if(p->opcode == sig->first_eq_opcode) {
//opcode matches, check length.. //opcode matches, check length..
if(p->size == sig->first_length) { if(p->size == sig->first_length) {
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length matched [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x and length matched %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size);
res = MatchSuccessful; res = MatchSuccessful;
} else if(sig->first_length == 0) { } else if(sig->first_length == 0) {
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length ([{}]) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x and length (%d) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size);
res = MatchSuccessful; res = MatchSuccessful;
} else { } else {
//opcode matched but length did not. //opcode matched but length did not.
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x}, but length [{}] did not match expected [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length); Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x, but length %d did not match expected %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length);
res = MatchFailed; res = MatchFailed;
} }
} else { } else {
//first opcode did not match.. //first opcode did not match..
LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode {:#04x} did not match expected {:#04x}", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode); Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode 0x%x did not match expected 0x%x", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode);
res = MatchFailed; res = MatchFailed;
} }
} }
+11 -11
View File
@@ -46,7 +46,7 @@ void EQStreamIdentifier::Process() {
//first see if this stream has expired //first see if this stream has expired
if(r.expire.Check(false)) { if(r.expire.Check(false)) {
LogNetcode("[StreamIdentify] Unable to identify stream from [{}:{}] before timeout", r.stream->GetRemoteAddr().c_str(), ntohs(r.stream->GetRemotePort())); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d before timeout.", r.stream->GetRemoteAddr().c_str(), ntohs(r.stream->GetRemotePort()));
r.stream->Close(); r.stream->Close();
cur = m_streams.erase(cur); cur = m_streams.erase(cur);
@@ -62,23 +62,23 @@ void EQStreamIdentifier::Process() {
} }
if(r.stream->GetState() != ESTABLISHED) { if(r.stream->GetState() != ESTABLISHED) {
//the stream closed before it was identified. //the stream closed before it was identified.
LogNetcode("[StreamIdentify] Unable to identify stream from [{}:{}] before it closed", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort())); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d before it closed.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()));
switch(r.stream->GetState()) switch(r.stream->GetState())
{ {
case ESTABLISHED: case ESTABLISHED:
LogNetcode("[StreamIdentify] Stream state was Established"); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Established");
break; break;
case CLOSING: case CLOSING:
LogNetcode("[StreamIdentify] Stream state was Closing"); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closing");
break; break;
case DISCONNECTING: case DISCONNECTING:
LogNetcode("[StreamIdentify] Stream state was Disconnecting"); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Disconnecting");
break; break;
case CLOSED: case CLOSED:
LogNetcode("[StreamIdentify] Stream state was Closed"); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closed");
break; break;
default: default:
LogNetcode("[StreamIdentify] Stream state was Unestablished or unknown"); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Unestablished or unknown");
break; break;
} }
r.stream->ReleaseFromUse(); r.stream->ReleaseFromUse();
@@ -102,13 +102,13 @@ void EQStreamIdentifier::Process() {
switch(res) { switch(res) {
case EQStreamInterface::MatchNotReady: case EQStreamInterface::MatchNotReady:
//the stream has not received enough packets to compare with this signature //the stream has not received enough packets to compare with this signature
// Log.LogDebugType(Logs::General, Logs::Netcode, "[StreamIdentify] %s:%d: Tried patch %s, but stream is not ready for it.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str()); // Log.LogDebugType(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: Tried patch %s, but stream is not ready for it.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
all_ready = false; all_ready = false;
break; break;
case EQStreamInterface::MatchSuccessful: { case EQStreamInterface::MatchSuccessful: {
//yay, a match. //yay, a match.
LogNetcode("[StreamIdentify] Identified stream [{}:{}] with signature [{}]", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str()); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Identified stream %s:%d with signature %s", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
// before we assign the eqstream to an interface, let the stream recognize it is in use and the session should not be reset any further // before we assign the eqstream to an interface, let the stream recognize it is in use and the session should not be reset any further
r.stream->SetActive(true); r.stream->SetActive(true);
@@ -122,7 +122,7 @@ void EQStreamIdentifier::Process() {
} }
case EQStreamInterface::MatchFailed: case EQStreamInterface::MatchFailed:
//do nothing... //do nothing...
LogNetcode("[StreamIdentify] [{}:{}] Tried patch [{}] and it did not match", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str()); Log(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: Tried patch %s, and it did not match.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str());
break; break;
} }
} }
@@ -130,7 +130,7 @@ void EQStreamIdentifier::Process() {
//if we checked all patches and did not find a match. //if we checked all patches and did not find a match.
if(all_ready && !found_one) { if(all_ready && !found_one) {
//the stream cannot be identified. //the stream cannot be identified.
LogNetcode("[StreamIdentify] Unable to identify stream from [{}:{}], no match found", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort())); Log(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d, no match found.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()));
r.stream->ReleaseFromUse(); r.stream->ReleaseFromUse();
} }
+5 -53
View File
@@ -6,7 +6,6 @@
#include <string> #include <string>
#include "emu_versions.h" #include "emu_versions.h"
#include "eq_packet.h" #include "eq_packet.h"
#include "net/daybreak_connection.h"
typedef enum { typedef enum {
ESTABLISHED, ESTABLISHED,
@@ -19,47 +18,6 @@ typedef enum {
class EQApplicationPacket; class EQApplicationPacket;
class OpcodeManager; class OpcodeManager;
struct EQStreamManagerInterfaceOptions
{
EQStreamManagerInterfaceOptions() {
opcode_size = 2;
}
EQStreamManagerInterfaceOptions(int port, bool encoded, bool compressed) {
opcode_size = 2;
//World seems to support both compression and xor zone supports one or the others.
//Enforce one or the other in the convienence construct
//Login I had trouble getting to recognize compression at all
//but that might be because it was still a bit buggy when i was testing that.
if (compressed) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression;
}
else if (encoded) {
daybreak_options.encode_passes[0] = EQ::Net::EncodeXOR;
}
daybreak_options.port = port;
}
int opcode_size;
bool track_opcode_stats;
EQ::Net::DaybreakConnectionManagerOptions daybreak_options;
};
class EQStreamManagerInterface
{
public:
EQStreamManagerInterface(const EQStreamManagerInterfaceOptions &options) { m_options = options; }
virtual ~EQStreamManagerInterface() { };
EQStreamManagerInterfaceOptions GetOptions() { return m_options; }
const EQStreamManagerInterfaceOptions& GetOptions() const { return m_options; }
virtual void SetOptions(const EQStreamManagerInterfaceOptions& options) = 0;
protected:
EQStreamManagerInterfaceOptions m_options;
};
class EQStreamInterface { class EQStreamInterface {
public: public:
virtual ~EQStreamInterface() {} virtual ~EQStreamInterface() {}
@@ -71,20 +29,12 @@ public:
uint16 first_eq_opcode; uint16 first_eq_opcode;
uint32 first_length; //0=dont check length uint32 first_length; //0=dont check length
}; };
typedef enum { typedef enum {
MatchNotReady, MatchNotReady,
MatchSuccessful, MatchSuccessful,
MatchFailed MatchFailed
} MatchState; } MatchState;
struct Stats
{
EQ::Net::DaybreakConnectionStats DaybreakStats;
int RecvCount[_maxEmuOpcode];
int SentCount[_maxEmuOpcode];
};
virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) = 0; virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req=true) = 0;
virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true) = 0; virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true) = 0;
virtual EQApplicationPacket *PopPacket() = 0; virtual EQApplicationPacket *PopPacket() = 0;
@@ -100,10 +50,12 @@ public:
virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; } virtual MatchState CheckSignature(const Signature *sig) { return MatchFailed; }
virtual EQStreamState GetState() = 0; virtual EQStreamState GetState() = 0;
virtual void SetOpcodeManager(OpcodeManager **opm) = 0; virtual void SetOpcodeManager(OpcodeManager **opm) = 0;
virtual const uint32 GetBytesSent() const { return 0; }
virtual const uint32 GetBytesRecieved() const { return 0; }
virtual const uint32 GetBytesSentPerSecond() const { return 0; }
virtual const uint32 GetBytesRecvPerSecond() const { return 0; }
virtual const EQEmu::versions::ClientVersion ClientVersion() const { return EQEmu::versions::ClientVersion::Unknown; } virtual const EQEmu::versions::ClientVersion ClientVersion() const { return EQEmu::versions::ClientVersion::Unknown; }
virtual Stats GetStats() const = 0;
virtual void ResetStats() = 0;
virtual EQStreamManagerInterface* GetManager() const = 0;
}; };
#endif /*EQSTREAMINTF_H_*/ #endif /*EQSTREAMINTF_H_*/
+22 -17
View File
@@ -42,8 +42,8 @@ void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
return; return;
if (p->GetOpcode() != OP_SpecialMesg) { if (p->GetOpcode() != OP_SpecialMesg) {
Log(Logs::General, Logs::PacketServerClient, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size()); Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
Log(Logs::General, Logs::PacketServerClientWithDump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str()); Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
} }
EQApplicationPacket *newp = p->Copy(); EQApplicationPacket *newp = p->Copy();
@@ -82,6 +82,26 @@ uint16 EQStreamProxy::GetRemotePort() const {
return(m_stream->GetRemotePort()); return(m_stream->GetRemotePort());
} }
const uint32 EQStreamProxy::GetBytesSent() const
{
return(m_stream->GetBytesSent());
}
const uint32 EQStreamProxy::GetBytesRecieved() const
{
return(m_stream->GetBytesRecieved());
}
const uint32 EQStreamProxy::GetBytesSentPerSecond() const
{
return(m_stream->GetBytesSentPerSecond());
}
const uint32 EQStreamProxy::GetBytesRecvPerSecond() const
{
return(m_stream->GetBytesRecvPerSecond());
}
void EQStreamProxy::ReleaseFromUse() { void EQStreamProxy::ReleaseFromUse() {
m_stream->ReleaseFromUse(); m_stream->ReleaseFromUse();
} }
@@ -90,21 +110,6 @@ void EQStreamProxy::RemoveData() {
m_stream->RemoveData(); m_stream->RemoveData();
} }
EQStreamInterface::Stats EQStreamProxy::GetStats() const
{
return m_stream->GetStats();
}
void EQStreamProxy::ResetStats()
{
m_stream->ResetStats();
}
EQStreamManagerInterface *EQStreamProxy::GetManager() const
{
return m_stream->GetManager();
}
bool EQStreamProxy::CheckState(EQStreamState state) { bool EQStreamProxy::CheckState(EQStreamState state) {
if(m_stream) if(m_stream)
return(m_stream->CheckState(state)); return(m_stream->CheckState(state));
+5 -3
View File
@@ -31,9 +31,11 @@ public:
virtual const EQEmu::versions::ClientVersion ClientVersion() const; virtual const EQEmu::versions::ClientVersion ClientVersion() const;
virtual EQStreamState GetState(); virtual EQStreamState GetState();
virtual void SetOpcodeManager(OpcodeManager **opm); virtual void SetOpcodeManager(OpcodeManager **opm);
virtual Stats GetStats() const;
virtual void ResetStats(); virtual const uint32 GetBytesSent() const;
virtual EQStreamManagerInterface* GetManager() const; virtual const uint32 GetBytesRecieved() const;
virtual const uint32 GetBytesSentPerSecond() const;
virtual const uint32 GetBytesRecvPerSecond() const;
protected: protected:
std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object. std::shared_ptr<EQStreamInterface> const m_stream; //we own this stream object.
+9 -43
View File
@@ -26,8 +26,7 @@
std::string EQEmuConfig::ConfigFile = "eqemu_config.json"; std::string EQEmuConfig::ConfigFile = "eqemu_config.json";
EQEmuConfig *EQEmuConfig::_config = nullptr; EQEmuConfig *EQEmuConfig::_config = nullptr;
void EQEmuConfig::parse_config() void EQEmuConfig::parse_config() {
{
ShortName = _root["server"]["world"].get("shortname", "").asString(); ShortName = _root["server"]["world"].get("shortname", "").asString();
LongName = _root["server"]["world"].get("longname", "").asString(); LongName = _root["server"]["world"].get("longname", "").asString();
@@ -41,11 +40,10 @@ void EQEmuConfig::parse_config()
LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString(); LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString();
LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str()); LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str());
LoginLegacy = false; LoginLegacy = false;
if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; } if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") LoginLegacy = true;
LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString(); LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString();
LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString(); LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString();
} } else {
else {
char str[32]; char str[32];
loginlist.Clear(); loginlist.Clear();
do { do {
@@ -61,7 +59,7 @@ void EQEmuConfig::parse_config()
loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString(); loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString();
loginconfig->LoginLegacy = false; loginconfig->LoginLegacy = false;
if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") { loginconfig->LoginLegacy = true; } if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") loginconfig->LoginLegacy = true;
loginlist.Insert(loginconfig); loginlist.Insert(loginconfig);
} while (LoginCount < 100); } while (LoginCount < 100);
} }
@@ -70,67 +68,46 @@ void EQEmuConfig::parse_config()
//<locked> from xml converts to json as locked: "", so i default to "false". //<locked> from xml converts to json as locked: "", so i default to "false".
//The only way to enable locked is by switching to true, meaning this value is always false until manually set true //The only way to enable locked is by switching to true, meaning this value is always false until manually set true
Locked = false; Locked = false;
if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; } if (_root["server"]["world"].get("locked", "false").asString() == "true") Locked = true;
WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString(); WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString();
WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str()); WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str());
TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString(); TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString();
TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str()); TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str());
TelnetEnabled = false; TelnetEnabled = false;
if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; } if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") TelnetEnabled = true;
WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString(); WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString();
WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str()); WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str());
WorldHTTPEnabled = false; WorldHTTPEnabled = false;
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") WorldHTTPEnabled = true;
if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") {
WorldHTTPEnabled = true;
}
/**
* UCS
*/
ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString(); ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString();
ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str()); ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str());
MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString(); MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString();
MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str()); MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str());
/**
* Database
*/
DatabaseUsername = _root["server"]["database"].get("username", "eq").asString(); DatabaseUsername = _root["server"]["database"].get("username", "eq").asString();
DatabasePassword = _root["server"]["database"].get("password", "eq").asString(); DatabasePassword = _root["server"]["database"].get("password", "eq").asString();
DatabaseHost = _root["server"]["database"].get("host", "localhost").asString(); DatabaseHost = _root["server"]["database"].get("host", "localhost").asString();
DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str()); DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str());
DatabaseDB = _root["server"]["database"].get("db", "eq").asString(); DatabaseDB = _root["server"]["database"].get("db", "eq").asString();
/**
* QS
*/
QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString(); QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString();
QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str()); QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str());
QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString(); QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString();
QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString(); QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString();
QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString();
/**
* Zones
*/
DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str()); DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str());
ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str()); ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str());
ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str()); ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str());
/**
* Files
*/
SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString(); SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString();
OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString(); OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString();
MailOpCodesFile = _root["server"]["files"].get("mail_opcodes", "mail_opcodes.conf").asString();
PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString(); PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString();
/**
* Directories
*/
MapDir = _root["server"]["directories"].get("maps", "Maps/").asString(); MapDir = _root["server"]["directories"].get("maps", "Maps/").asString();
QuestDir = _root["server"]["directories"].get("quests", "quests/").asString(); QuestDir = _root["server"]["directories"].get("quests", "quests/").asString();
PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString(); PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString();
@@ -139,15 +116,8 @@ void EQEmuConfig::parse_config()
SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString(); SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString();
LogDir = _root["server"]["directories"].get("logs", "logs/").asString(); LogDir = _root["server"]["directories"].get("logs", "logs/").asString();
/**
* Logs
*/
LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString(); LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString();
LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString(); LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString();
/**
* Launcher
*/
RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str()); RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str());
TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str()); TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str());
InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str()); InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str());
@@ -260,9 +230,6 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
if (var_name == "OpCodesFile") { if (var_name == "OpCodesFile") {
return (OpCodesFile); return (OpCodesFile);
} }
if (var_name == "MailOpCodesFile") {
return (MailOpCodesFile);
}
if (var_name == "PluginPlFile") { if (var_name == "PluginPlFile") {
return (PluginPlFile); return (PluginPlFile);
} }
@@ -345,7 +312,6 @@ void EQEmuConfig::Dump() const
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl; std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
std::cout << "SpellsFile = " << SpellsFile << std::endl; std::cout << "SpellsFile = " << SpellsFile << std::endl;
std::cout << "OpCodesFile = " << OpCodesFile << std::endl; std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
std::cout << "MailOpcodesFile = " << MailOpCodesFile << std::endl;
std::cout << "PluginPlFile = " << PluginPlFile << std::endl; std::cout << "PluginPlFile = " << PluginPlFile << std::endl;
std::cout << "MapDir = " << MapDir << std::endl; std::cout << "MapDir = " << MapDir << std::endl;
std::cout << "QuestDir = " << QuestDir << std::endl; std::cout << "QuestDir = " << QuestDir << std::endl;
@@ -356,6 +322,6 @@ void EQEmuConfig::Dump() const
std::cout << "LogDir = " << LogDir << std::endl; std::cout << "LogDir = " << LogDir << std::endl;
std::cout << "ZonePortLow = " << ZonePortLow << std::endl; std::cout << "ZonePortLow = " << ZonePortLow << std::endl;
std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl; std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl;
std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl; std::cout << "DefaultStatus = " << (int)DefaultStatus << std::endl;
// std::cout << "DynamicCount = " << DynamicCount << std::endl; // std::cout << "DynamicCount = " << DynamicCount << std::endl;
} }
+4 -1
View File
@@ -81,10 +81,13 @@ class EQEmuConfig
std::string QSDatabaseDB; std::string QSDatabaseDB;
uint16 QSDatabasePort; uint16 QSDatabasePort;
// From <nats/>
std::string NATSHost;
uint16 NATSPort;
// From <files/> // From <files/>
std::string SpellsFile; std::string SpellsFile;
std::string OpCodesFile; std::string OpCodesFile;
std::string MailOpCodesFile;
std::string PluginPlFile; std::string PluginPlFile;
// From <directories/> // From <directories/>
+115 -338
View File
@@ -1,25 +1,23 @@
/** /* EQEMu: Everquest Server Emulator
* EQEmulator: Everquest Server Emulator Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
* it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License.
* the Free Software Foundation; version 2 of the License.
* This program is distributed in the hope that it will be useful,
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY except by those people which sell it, which
* but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product;
* are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
* along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "rulesys.h"
#include "platform.h" #include "platform.h"
#include "string_util.h" #include "string_util.h"
#include "database.h" #include "database.h"
@@ -35,22 +33,18 @@
std::ofstream process_log; std::ofstream process_log;
#ifdef _WINDOWS #ifdef _WINDOWS
#include <direct.h> #include <direct.h>
#include <conio.h> #include <conio.h>
#include <iostream> #include <iostream>
#include <dos.h> #include <dos.h>
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
#else #else
#include <unistd.h>
#include <unistd.h> #include <sys/stat.h>
#include <sys/stat.h>
#endif #endif
/** /* Linux ANSI console color defines */
* Linux ANSI console color defines
*/
#define LC_RESET "\033[0m" #define LC_RESET "\033[0m"
#define LC_BLACK "\033[30m" /* Black */ #define LC_BLACK "\033[30m" /* Black */
#define LC_RED "\033[31m" /* Red */ #define LC_RED "\033[31m" /* Red */
@@ -82,182 +76,95 @@ namespace Console {
}; };
} }
/**
* EQEmuLogSys Constructor
*/
EQEmuLogSys::EQEmuLogSys() EQEmuLogSys::EQEmuLogSys()
{ {
on_log_gmsay_hook = [](uint16 log_type, const std::string &) {}; on_log_gmsay_hook = [](uint16 log_type, const std::string&) {};
on_log_console_hook = [](uint16 debug_level, uint16 log_type, const std::string &) {}; bool file_logs_enabled = false;
int log_platform = 0;
} }
/** EQEmuLogSys::~EQEmuLogSys()
* EQEmuLogSys Deconstructor {
*/ }
EQEmuLogSys::~EQEmuLogSys() = default;
void EQEmuLogSys::LoadLogSettingsDefaults() void EQEmuLogSys::LoadLogSettingsDefaults()
{ {
/** /* Get Executable platform currently running this code (Zone/World/etc) */
* Get Executable platform currently running this code (Zone/World/etc)
*/
log_platform = GetExecutablePlatformInt(); log_platform = GetExecutablePlatformInt();
for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) { /* Zero out Array */
log_settings[log_category_id].log_to_console = 0; memset(log_settings, 0, sizeof(LogSettings) * Logs::LogCategory::MaxCategoryID);
log_settings[log_category_id].log_to_file = 0;
log_settings[log_category_id].log_to_gmsay = 0;
log_settings[log_category_id].is_category_enabled = 0;
}
file_logs_enabled = false; /* Set Defaults */
log_settings[Logs::World_Server].log_to_console = Logs::General;
log_settings[Logs::Zone_Server].log_to_console = Logs::General;
log_settings[Logs::QS_Server].log_to_console = Logs::General;
log_settings[Logs::UCS_Server].log_to_console = Logs::General;
log_settings[Logs::Crash].log_to_console = Logs::General;
log_settings[Logs::MySQLError].log_to_console = Logs::General;
log_settings[Logs::Login_Server].log_to_console = Logs::General;
log_settings[Logs::Headless_Client].log_to_console = Logs::General;
log_settings[Logs::NATS].log_to_console = Logs::General;
/** /* Set Category enabled status on defaults */
* Set Defaults log_settings[Logs::World_Server].is_category_enabled = 1;
log_settings[Logs::Zone_Server].is_category_enabled = 1;
log_settings[Logs::QS_Server].is_category_enabled = 1;
log_settings[Logs::UCS_Server].is_category_enabled = 1;
log_settings[Logs::Crash].is_category_enabled = 1;
log_settings[Logs::MySQLError].is_category_enabled = 1;
log_settings[Logs::Login_Server].is_category_enabled = 1;
log_settings[Logs::NATS].is_category_enabled = 1;
/* Declare process file names for log writing
If there is no process_file_name declared, no log file will be written, simply
*/ */
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General); if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld)
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
/**
* RFC 5424
*/
log_settings[Logs::Emergency].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Alert].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Critical].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Error].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Notice].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
/**
* Set Category enabled status on defaults
*/
for (int log_category_id = Logs::AA; log_category_id != Logs::MaxCategoryID; log_category_id++) {
const bool log_to_console = log_settings[log_category_id].log_to_console > 0;
const bool log_to_file = log_settings[log_category_id].log_to_file > 0;
const bool log_to_gmsay = log_settings[log_category_id].log_to_gmsay > 0;
const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay;
if (is_category_enabled) {
log_settings[log_category_id].is_category_enabled = 1;
}
}
/**
* Declare process file names for log writing=
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) {
platform_file_name = "world"; platform_file_name = "world";
} else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) {
platform_file_name = "query_server"; platform_file_name = "query_server";
} else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
platform_file_name = "zone"; platform_file_name = "zone";
} else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) {
platform_file_name = "ucs"; platform_file_name = "ucs";
} else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) {
platform_file_name = "login"; platform_file_name = "login";
} else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch) {
platform_file_name = "launcher"; platform_file_name = "launcher";
} else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC)
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformHC) {
platform_file_name = "hc"; platform_file_name = "hc";
}
} }
/** std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message)
* @param log_category
* @return
*/
bool EQEmuLogSys::IsRfc5424LogCategory(uint16 log_category)
{ {
return ( std::string ret;
log_category == Logs::Emergency || ret.push_back('[');
log_category == Logs::Alert || ret.append(Logs::LogCategoryName[log_category]);
log_category == Logs::Critical || ret.push_back(']');
log_category == Logs::Error || ret.push_back(' ');
log_category == Logs::Warning || ret.append(in_message);
log_category == Logs::Notice || return ret;
log_category == Logs::Info ||
log_category == Logs::Debug
);
} }
/** void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message)
* @param log_category
* @param in_message
* @return
*/
std::string EQEmuLogSys::FormatOutMessageString(
uint16 log_category,
const std::string &in_message
)
{ {
std::string return_string; /* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash */
if (log_category == Logs::LogCategory::Netcode)
if (IsRfc5424LogCategory(log_category)) {
return_string = "[" + GetPlatformName() + "] ";
}
return return_string + "[" + Logs::LogCategoryName[log_category] + "] " + in_message;
}
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessGMSay(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
{
/**
* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash
*/
if (log_category == Logs::LogCategory::Netcode) {
return; return;
}
/** /* Check to see if the process that actually ran this is zone */
* Check to see if the process that actually ran this is zone if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone)
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
on_log_gmsay_hook(log_category, message); on_log_gmsay_hook(log_category, message);
}
} }
/** void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message)
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessLogWrite(
uint16 debug_level,
uint16 log_category,
const std::string &message
)
{ {
if (log_category == Logs::Crash) { if (log_category == Logs::Crash) {
char time_stamp[80]; char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp); EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
std::ofstream crash_log; std::ofstream crash_log;
EQEmuLogSys::MakeDirectory("logs/crashes"); EQEmuLogSys::MakeDirectory("logs/crashes");
crash_log.open( crash_log.open(StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out);
StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
crash_log << time_stamp << " " << message << "\n"; crash_log << time_stamp << " " << message << "\n";
crash_log.close(); crash_log.close();
} }
@@ -265,17 +172,11 @@ void EQEmuLogSys::ProcessLogWrite(
char time_stamp[80]; char time_stamp[80];
EQEmuLogSys::SetCurrentTimeStamp(time_stamp); EQEmuLogSys::SetCurrentTimeStamp(time_stamp);
if (process_log) { if (process_log)
process_log << time_stamp << " " << message << std::endl; process_log << time_stamp << " " << message << std::endl;
}
} }
/** uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category) {
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
@@ -298,19 +199,12 @@ uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category)
} }
} }
/** std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category) {
* @param log_category
* @return
*/
std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
{
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
return LC_YELLOW; return LC_YELLOW;
case Logs::MySQLError: case Logs::MySQLError:
case Logs::Warning:
case Logs::Critical:
case Logs::Error: case Logs::Error:
return LC_RED; return LC_RED;
case Logs::MySQLQuery: case Logs::MySQLQuery:
@@ -328,42 +222,33 @@ std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category)
} }
} }
/** uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) {
* @param log_category
* @return
*/
uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
{
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
return Chat::Yellow; return 15; /* Yellow */
case Logs::MySQLError: case Logs::MySQLError:
case Logs::Error: case Logs::Error:
return Chat::Red; return 13; /* Red */
case Logs::MySQLQuery: case Logs::MySQLQuery:
case Logs::Debug: case Logs::Debug:
return Chat::Lime; return 14; /* Light Green */
case Logs::Quests: case Logs::Quests:
return Chat::Group; return 258; /* Light Cyan */
case Logs::Commands: case Logs::Commands:
case Logs::Mercenaries: case Logs::Mercenaries:
return Chat::Magenta; return 5; /* Light Purple */
case Logs::Crash: case Logs::Crash:
return Chat::Red; return 13; /* Red */
default: default:
return Chat::Yellow; return 15; /* Yellow */
} }
} }
/**
* @param debug_level
* @param log_category
* @param message
*/
void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message) void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message)
{ {
#ifdef _WINDOWS
#ifdef _WINDOWS
HANDLE console_handle; HANDLE console_handle;
console_handle = GetStdHandle(STD_OUTPUT_HANDLE); console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFOEX info = { 0 }; CONSOLE_FONT_INFOEX info = { 0 };
@@ -375,67 +260,14 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category)); SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category));
std::cout << message << "\n"; std::cout << message << "\n";
SetConsoleTextAttribute(console_handle, Console::Color::White); SetConsoleTextAttribute(console_handle, Console::Color::White);
#else #else
std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl; std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl;
#endif #endif
on_log_console_hook(debug_level, log_category, message);
} }
/** void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...)
* @param str
* @return
*/
constexpr const char *str_end(const char *str)
{ {
return *str ? str_end(str + 1) : str;
}
/**
* @param str
* @return
*/
constexpr bool str_slant(const char *str)
{
return *str == '/' ? true : (*str ? str_slant(str + 1) : false);
}
/**
* @param str
* @return
*/
constexpr const char *r_slant(const char *str)
{
return *str == '/' ? (str + 1) : r_slant(str - 1);
}
/**
* @param str
* @return
*/
constexpr const char *base_file_name(const char *str)
{
return str_slant(str) ? r_slant(str_end(str)) : str;
}
/**
* Core logging function
*
* @param debug_level
* @param log_category
* @param message
* @param ...
*/
void EQEmuLogSys::Out(
Logs::DebugLevel debug_level,
uint16 log_category,
const char *file,
const char *func,
int line,
const char *message,
...
)
{
bool log_to_console = true; bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) { if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false; log_to_console = false;
@@ -452,49 +284,30 @@ void EQEmuLogSys::Out(
} }
const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay; const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay;
if (nothing_to_log) { if (nothing_to_log)
return; return;
}
std::string prefix;
if (RuleB(Logging, PrintFileFunctionAndLine)) {
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
}
va_list args; va_list args;
va_start(args, message); va_start(args, message);
std::string output_message = vStringFormat(message, args); std::string output_message = vStringFormat(message.c_str(), args);
va_end(args); va_end(args);
std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, prefix + output_message); std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message);
if (log_to_console) { if (log_to_console) EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message);
EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message); if (log_to_gmsay) EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
} if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
if (log_to_gmsay) {
EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message);
}
if (log_to_file) {
EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message);
}
} }
/** void EQEmuLogSys::SetCurrentTimeStamp(char* time_stamp)
* @param time_stamp
*/
void EQEmuLogSys::SetCurrentTimeStamp(char *time_stamp)
{ {
time_t raw_time; time_t raw_time;
struct tm *time_info; struct tm * time_info;
time(&raw_time); time(&raw_time);
time_info = localtime(&raw_time); time_info = localtime(&raw_time);
strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info); strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info);
} }
/**
* @param directory_name
*/
void EQEmuLogSys::MakeDirectory(const std::string &directory_name) void EQEmuLogSys::MakeDirectory(const std::string &directory_name)
{ {
#ifdef _WINDOWS #ifdef _WINDOWS
@@ -503,10 +316,9 @@ void EQEmuLogSys::MakeDirectory(const std::string &directory_name)
return; return;
_mkdir(directory_name.c_str()); _mkdir(directory_name.c_str());
#else #else
struct stat st{}; struct stat st;
if (stat(directory_name.c_str(), &st) == 0) { // exists if (stat(directory_name.c_str(), &st) == 0) // exists
return; return;
}
mkdir(directory_name.c_str(), 0755); mkdir(directory_name.c_str(), 0755);
#endif #endif
} }
@@ -518,64 +330,29 @@ void EQEmuLogSys::CloseFileLogs()
} }
} }
/**
* @param log_name
*/
void EQEmuLogSys::StartFileLogs(const std::string &log_name) void EQEmuLogSys::StartFileLogs(const std::string &log_name)
{ {
EQEmuLogSys::CloseFileLogs(); EQEmuLogSys::CloseFileLogs();
/** /* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... */
* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... if (file_logs_enabled == false)
*/
if (!file_logs_enabled) {
return; return;
}
/**
* Zone
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) { if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) {
if (!log_name.empty()) { if (!log_name.empty())
platform_file_name = log_name; platform_file_name = log_name;
}
if (platform_file_name.empty()) { if (platform_file_name.empty())
return; return;
}
LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid()); EQEmuLogSys::Out(Logs::General, Logs::Status, "Starting File Log 'logs/%s_%i.log'", platform_file_name.c_str(), getpid());
/**
* Make directory if not exists
*/
EQEmuLogSys::MakeDirectory("logs/zone"); EQEmuLogSys::MakeDirectory("logs/zone");
process_log.open(StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out);
/** } else {
* Open file pointer if (platform_file_name.empty())
*/
process_log.open(
StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
}
else {
/**
* All other processes
*/
if (platform_file_name.empty()) {
return; return;
}
LogInfo("Starting File Log [logs/{}_{}.log]", platform_file_name.c_str(), getpid()); EQEmuLogSys::Out(Logs::General, Logs::Status, "Starting File Log 'logs/%s_%i.log'", platform_file_name.c_str(), getpid());
process_log.open(StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out);
/**
* Open file pointer
*/
process_log.open(
StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()),
std::ios_base::app | std::ios_base::out
);
} }
} }
+96 -219
View File
@@ -1,38 +1,30 @@
/**
* EQEmulator: Everquest Server Emulator /* EQEMu: Everquest Server Emulator
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server) Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
*
* This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License. the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product; are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#ifndef EQEMU_LOGSYS_H #ifndef EQEMU_LOGSYS_H
#define EQEMU_LOGSYS_H #define EQEMU_LOGSYS_H
#include <fmt/format.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <stdio.h> #include <stdio.h>
#include <functional> #include <functional>
#ifdef _WIN32
#ifdef utf16_to_utf8
#undef utf16_to_utf8
#endif
#endif
#include <fmt/format.h>
#include "types.h" #include "types.h"
namespace Logs { namespace Logs {
@@ -42,18 +34,18 @@ namespace Logs {
Detail /* 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication */ Detail /* 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication */
}; };
/** /*
* If you add to this, make sure you update LogCategoryName If you add to this, make sure you update LogCategoryName
* NOTE: Only add to the bottom of the enum because that is the type ID assignment
* NOTE: Only add to the bottom of the enum because that is the type ID assignment
*/ */
enum LogCategory {
enum LogCategory {
None = 0, None = 0,
AA, AA,
AI, AI,
Aggro, Aggro,
Attack, Attack,
PacketClientServer, Client_Server_Packet,
Combat, Combat,
Commands, Commands,
Crash, Crash,
@@ -67,53 +59,43 @@ namespace Logs {
Normal, Normal,
Object, Object,
Pathing, Pathing,
QSServer, QS_Server,
Quests, Quests,
Rules, Rules,
Skills, Skills,
Spawns, Spawns,
Spells, Spells,
Status, Status,
TCPConnection, TCP_Connection,
Tasks, Tasks,
Tradeskills, Tradeskills,
Trading, Trading,
Tribute, Tribute,
UCSServer, UCS_Server,
WebInterfaceServer, WebInterface_Server,
WorldServer, World_Server,
ZoneServer, Zone_Server,
MySQLError, MySQLError,
MySQLQuery, MySQLQuery,
Mercenaries, Mercenaries,
QuestDebug, QuestDebug,
PacketServerClient, Server_Client_Packet,
PacketClientServerUnhandled, Client_Server_Packet_Unhandled,
PacketServerClientWithDump, Server_Client_Packet_With_Dump,
PacketClientServerWithDump, Client_Server_Packet_With_Dump,
Loginserver, Login_Server,
ClientLogin, Client_Login,
HeadlessClient, Headless_Client,
HPUpdate, HP_Update,
FixZ, FixZ,
Food, Food,
Traps, Traps,
NPCRoamBox, NATS,
NPCScaling, MaxCategoryID /* Don't Remove this*/
MobAppearance, };
Info,
Warning,
Critical,
Emergency,
Alert,
Notice,
MaxCategoryID /* Don't Remove this */
};
/** /* If you add to this, make sure you update LogCategory */
* If you add to this, make sure you update LogCategory static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
*/
static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
"", "",
"AA", "AA",
"AI", "AI",
@@ -164,77 +146,58 @@ namespace Logs {
"FixZ", "FixZ",
"Food", "Food",
"Traps", "Traps",
"NPC Roam Box", "NATS"
"NPC Scaling", };
"Mob Appearance",
"Info",
"Warning",
"Critical",
"Emergency",
"Alert",
"Notice"
};
} }
#include "eqemu_logsys_log_aliases.h" #define Log(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
LogSys.Out(debug_level, log_category, message, ##__VA_ARGS__);\
} while (0)
#define LogF(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
LogSys.OutF(debug_level, log_category, message, ##__VA_ARGS__);\
} while (0)
class EQEmuLogSys { class EQEmuLogSys {
public: public:
EQEmuLogSys(); EQEmuLogSys();
~EQEmuLogSys(); ~EQEmuLogSys();
/** void CloseFileLogs(); /* Close File Logs wherever necessary, either at zone shutdown or entire process shutdown for everything else. This should be handled on deconstructor but to be safe we use it anyways. */
* Close File Logs wherever necessary, either at zone shutdown or entire process shutdown for everything else. void LoadLogSettingsDefaults(); /* Initializes log_settings and sets some defaults if DB is not present */
* This should be handled on deconstructor but to be safe we use it anyways. void MakeDirectory(const std::string &directory_name); /* Platform independent way of performing a MakeDirectory based on name */
*/ /*
void CloseFileLogs(); The one and only Logging function that uses a debug level as a parameter, as well as a log_category
void LoadLogSettingsDefaults(); log_category - defined in Logs::LogCategory::[]
log_category name resolution works by passing the enum int ID to Logs::LogCategoryName[category_id]
/** Example: EQEmuLogSys::Out(Logs::General, Logs::Guilds, "This guild has no leader present");
* @param directory_name - This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would
be checked against to see if that piped output is set to actually process it for the category and debug level
*/ */
void MakeDirectory(const std::string &directory_name); void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...);
void SetCurrentTimeStamp(char* time_stamp); /* Used in file logs to prepend a timestamp entry for logs */
void StartFileLogs(const std::string &log_name = ""); /* Used to declare the processes file log and to keep it open for later use */
/** template <typename... Args>
* The one and only Logging function that uses a debug level as a parameter, as well as a log_category void OutF(Logs::DebugLevel debug_level, uint16 log_category, const char *fmt, const Args&... args)
* log_category - defined in Logs::LogCategory::[] {
* log_category name resolution works by passing the enum int ID to Logs::LogCategoryName[category_id] std::string log_str = fmt::format(fmt, args...);
* Out(debug_level, log_category, log_str);
* Example: EQEmuLogSys::Out(Logs::General, Logs::Guilds, "This guild has no leader present"); }
* - This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would
* be checked against to see if that piped output is set to actually process it for the category and debug level
*/
void Out(
Logs::DebugLevel debug_level,
uint16 log_category,
const char *file,
const char *func,
int line,
const char *message,
...
);
/** /*
* Used in file logs to prepend a timestamp entry for logs LogSettings Struct
* @param time_stamp
*/
void SetCurrentTimeStamp(char* time_stamp);
/** This struct is the master reference for all settings for each category, and for each output
* @param log_name
*/
void StartFileLogs(const std::string &log_name = "");
/** log_to_file[category_id] = [1-3] - Sets debug level for category to output to file
* LogSettings Struct log_to_console[category_id] = [1-3] - Sets debug level for category to output to console
* log_to_gmsay[category_id] = [1-3] - Sets debug level for category to output to gmsay
* This struct is the master reference for all settings for each category, and for each output
*
* log_to_file[category_id] = [1-3] - Sets debug level for category to output to file
* log_to_console[category_id] = [1-3] - Sets debug level for category to output to console
* log_to_gmsay[category_id] = [1-3] - Sets debug level for category to output to gmsay
*
*/ */
struct LogSettings { struct LogSettings {
uint8 log_to_file; uint8 log_to_file;
uint8 log_to_console; uint8 log_to_console;
@@ -242,120 +205,34 @@ public:
uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */ uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */
}; };
/** /* Internally used memory reference for all log settings per category.
* Internally used memory reference for all log settings per category These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults.
* These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults Database loaded via Database::LoadLogSettings(log_settings)
* Database loaded via Database::LoadLogSettings(log_settings)
*/ */
LogSettings log_settings[Logs::LogCategory::MaxCategoryID]{}; LogSettings log_settings[Logs::LogCategory::MaxCategoryID];
bool file_logs_enabled = false; bool file_logs_enabled; /* Set when log settings are loaded to determine if keeping a file open is necessary */
/** int log_platform; /* Sets Executable platform (Zone/World/UCS) etc. */
* Sets Executable platform (Zone/World/UCS) etc.
*/
int log_platform = 0;
/** std::string platform_file_name; /* File name used in writing logs */
* File name used in writing logs
*/
std::string platform_file_name;
/** uint16 GetGMSayColorFromCategory(uint16 log_category); /* GMSay Client Message colors mapped by category */
* GMSay Client Message colors mapped by category
*
* @param log_category
* @return
*/
uint16 GetGMSayColorFromCategory(uint16 log_category);
/** void OnLogHookCallBackZone(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
* @param f
*/
void SetGMSayHandler(std::function<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
/**
* @param f
*/
void SetConsoleHandler(std::function<void(uint16 debug_level, uint16 log_type, const std::string&)> f) { on_log_console_hook = f; }
private: private:
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook; /* Callback pointer to zone process for hooking logs to zone using GMSay */
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message); /* Formats log messages like '[Category] This is a log message' */
std::string GetLinuxConsoleColorFromCategory(uint16 log_category); /* Linux console color messages mapped by category */
/** uint16 GetWindowsConsoleColorFromCategory(uint16 log_category); /* Windows console color messages mapped by category */
* Callback pointer to zone process for hooking logs to zone using GMSay
*/
std::function<void(uint16 log_category, const std::string&)> on_log_gmsay_hook;
std::function<void(uint16 debug_level, uint16 log_category, const std::string&)> on_log_console_hook;
/** void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessConsoleMessage called via Log */
* Formats log messages like '[Category] This is a log message' void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessGMSay called via Log */
*/ void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessLogWrite called via Log */
std::string FormatOutMessageString(uint16 log_category, const std::string &in_message);
/**
* Linux console color messages mapped by category
*
* @param log_category
* @return
*/
std::string GetLinuxConsoleColorFromCategory(uint16 log_category);
/**
* Windows console color messages mapped by category
*/
uint16 GetWindowsConsoleColorFromCategory(uint16 log_category);
/**
* @param debug_level
* @param log_category
* @param message
*/
void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message);
/**
* @param debug_level
* @param log_category
* @param message
*/
void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message);
/**
* @param debug_level
* @param log_category
* @param message
*/
void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message);
/**
* @param log_category
* @return
*/
bool IsRfc5424LogCategory(uint16 log_category);
}; };
extern EQEmuLogSys LogSys; extern EQEmuLogSys LogSys;
/**
template<typename... Args>
void OutF(
EQEmuLogSys &ls,
Logs::DebugLevel debug_level,
uint16 log_category,
const char *file,
const char *func,
int line,
const char *fmt,
const Args &... args
)
{
std::string log_str = fmt::format(fmt, args...);
ls.Out(debug_level, log_category, file, func, line, log_str.c_str());
}
**/
#define OutF(ls, debug_level, log_category, file, func, line, formatStr, ...) \
do { \
ls.Out(debug_level, log_category, file, func, line, fmt::format(formatStr, ##__VA_ARGS__).c_str()); \
} while(0)
#endif #endif
-507
View File
@@ -1,507 +0,0 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
#define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
/**
* RFC 5424
*/
#define LogEmergency(message, ...) do {\
if (LogSys.log_settings[Logs::Emergency].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAlert(message, ...) do {\
if (LogSys.log_settings[Logs::Alert].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCritical(message, ...) do {\
if (LogSys.log_settings[Logs::Critical].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogError(message, ...) do {\
if (LogSys.log_settings[Logs::Error].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogWarning(message, ...) do {\
if (LogSys.log_settings[Logs::Warning].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNotice(message, ...) do {\
if (LogSys.log_settings[Logs::Notice].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogInfo(message, ...) do {\
if (LogSys.log_settings[Logs::Info].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogDebug(message, ...) do {\
if (LogSys.log_settings[Logs::Debug].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
/**
* Category
*/
#define LogAA(message, ...) do {\
if (LogSys.log_settings[Logs::AA].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAADetail(message, ...) do {\
if (LogSys.log_settings[Logs::AA].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAI(message, ...) do {\
if (LogSys.log_settings[Logs::AI].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAIDetail(message, ...) do {\
if (LogSys.log_settings[Logs::AI].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAggro(message, ...) do {\
if (LogSys.log_settings[Logs::Aggro].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAggroDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Aggro].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAttack(message, ...) do {\
if (LogSys.log_settings[Logs::Attack].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogAttackDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Attack].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogPacketClientServer(message, ...) do {\
if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogPacketClientServerDetail(message, ...) do {\
if (LogSys.log_settings[Logs::PacketClientServer].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCombat(message, ...) do {\
if (LogSys.log_settings[Logs::Combat].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCombatDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Combat].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCommands(message, ...) do {\
if (LogSys.log_settings[Logs::Commands].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCommandsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Commands].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCrash(message, ...) do {\
if (LogSys.log_settings[Logs::Crash].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogCrashDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Crash].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogDoors(message, ...) do {\
if (LogSys.log_settings[Logs::Doors].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogDoorsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Doors].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogGuilds(message, ...) do {\
if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogGuildsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogInventory(message, ...) do {\
if (LogSys.log_settings[Logs::Inventory].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogInventoryDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Inventory].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogLauncher(message, ...) do {\
if (LogSys.log_settings[Logs::Launcher].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogLauncherDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Launcher].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNetcode(message, ...) do {\
if (LogSys.log_settings[Logs::Netcode].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNetcodeDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Netcode].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNormal(message, ...) do {\
if (LogSys.log_settings[Logs::Normal].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNormalDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Normal].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogObject(message, ...) do {\
if (LogSys.log_settings[Logs::Object].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogObjectDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Object].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogPathing(message, ...) do {\
if (LogSys.log_settings[Logs::Pathing].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogPathingDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Pathing].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogQSServer(message, ...) do {\
if (LogSys.log_settings[Logs::QSServer].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogQSServerDetail(message, ...) do {\
if (LogSys.log_settings[Logs::QSServer].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::QSServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogQuests(message, ...) do {\
if (LogSys.log_settings[Logs::Quests].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogQuestsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Quests].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogRules(message, ...) do {\
if (LogSys.log_settings[Logs::Rules].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogRulesDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Rules].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogSkills(message, ...) do {\
if (LogSys.log_settings[Logs::Skills].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogSkillsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Skills].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogSpawns(message, ...) do {\
if (LogSys.log_settings[Logs::Spawns].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogSpawnsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Spawns].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogSpells(message, ...) do {\
if (LogSys.log_settings[Logs::Spells].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogSpellsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Spells].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTCPConnection(message, ...) do {\
if (LogSys.log_settings[Logs::TCPConnection].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTCPConnectionDetail(message, ...) do {\
if (LogSys.log_settings[Logs::TCPConnection].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::TCPConnection, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTasks(message, ...) do {\
if (LogSys.log_settings[Logs::Tasks].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTasksDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Tasks].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTradeskills(message, ...) do {\
if (LogSys.log_settings[Logs::Tradeskills].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTradeskillsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Tradeskills].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTrading(message, ...) do {\
if (LogSys.log_settings[Logs::Trading].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTradingDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Trading].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTribute(message, ...) do {\
if (LogSys.log_settings[Logs::Tribute].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTributeDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Tribute].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMySQLError(message, ...) do {\
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMySQLErrorDetail(message, ...) do {\
if (LogSys.log_settings[Logs::MySQLError].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMySQLQuery(message, ...) do {\
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMySQLQueryDetail(message, ...) do {\
if (LogSys.log_settings[Logs::MySQLQuery].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMercenaries(message, ...) do {\
if (LogSys.log_settings[Logs::Mercenaries].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMercenariesDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Mercenaries].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogQuestDebug(message, ...) do {\
if (LogSys.log_settings[Logs::QuestDebug].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogQuestDebugDetail(message, ...) do {\
if (LogSys.log_settings[Logs::QuestDebug].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogLoginserver(message, ...) do {\
if (LogSys.log_settings[Logs::Loginserver].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogLoginserverDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Loginserver].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogClientLogin(message, ...) do {\
if (LogSys.log_settings[Logs::ClientLogin].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogClientLoginDetail(message, ...) do {\
if (LogSys.log_settings[Logs::ClientLogin].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogHeadlessClient(message, ...) do {\
if (LogSys.log_settings[Logs::HeadlessClient].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogHeadlessClientDetail(message, ...) do {\
if (LogSys.log_settings[Logs::HeadlessClient].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::HeadlessClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogHPUpdate(message, ...) do {\
if (LogSys.log_settings[Logs::HPUpdate].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogHPUpdateDetail(message, ...) do {\
if (LogSys.log_settings[Logs::HPUpdate].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogFixZ(message, ...) do {\
if (LogSys.log_settings[Logs::FixZ].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogFixZDetail(message, ...) do {\
if (LogSys.log_settings[Logs::FixZ].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogFood(message, ...) do {\
if (LogSys.log_settings[Logs::Food].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogFoodDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Food].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTraps(message, ...) do {\
if (LogSys.log_settings[Logs::Traps].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogTrapsDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Traps].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNPCRoamBox(message, ...) do {\
if (LogSys.log_settings[Logs::NPCRoamBox].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNPCRoamBoxDetail(message, ...) do {\
if (LogSys.log_settings[Logs::NPCRoamBox].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNPCScaling(message, ...) do {\
if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogNPCScalingDetail(message, ...) do {\
if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMobAppearance(message, ...) do {\
if (LogSys.log_settings[Logs::MobAppearance].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogMobAppearanceDetail(message, ...) do {\
if (LogSys.log_settings[Logs::MobAppearance].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogStatus(message, ...) do {\
if (LogSys.log_settings[Logs::Status].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::Status, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogStatusDetail(message, ...) do {\
if (LogSys.log_settings[Logs::Status].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::Status, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
/**
* Misc
*/
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogF(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
OutF(LogSys, debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <functional>
#include "event_loop.h"
namespace EQ {
class BackgroundTask
{
public:
typedef std::function<void(void)> BackgroundTaskFunction;
struct BackgroundTaskBaton
{
BackgroundTaskFunction fn;
BackgroundTaskFunction on_finish;
};
BackgroundTask(BackgroundTaskFunction fn, BackgroundTaskFunction on_finish) {
uv_work_t *m_work = new uv_work_t;
memset(m_work, 0, sizeof(uv_work_t));
BackgroundTaskBaton *baton = new BackgroundTaskBaton();
baton->fn = fn;
baton->on_finish = on_finish;
m_work->data = baton;
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
baton->fn();
}, [](uv_work_t* req, int status) {
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
baton->on_finish();
delete baton;
delete req;
});
}
~BackgroundTask() {
}
};
}
View File
+1 -1
View File
@@ -9,7 +9,7 @@ namespace EQ
{ {
public: public:
static EventLoop &Get() { static EventLoop &Get() {
static thread_local EventLoop inst; static EventLoop inst;
return inst; return inst;
} }
-100
View File
@@ -1,100 +0,0 @@
#pragma once
#include <functional>
#include <exception>
#include "event_loop.h"
#include "../any.h"
namespace EQ {
class Task
{
public:
typedef std::function<void(const EQEmu::Any&)> ResolveFn;
typedef std::function<void(const std::exception&)> RejectFn;
typedef std::function<void()> FinallyFn;
typedef std::function<void(ResolveFn, RejectFn)> TaskFn;
struct TaskBaton
{
TaskFn fn;
ResolveFn on_then;
RejectFn on_catch;
FinallyFn on_finally;
bool has_result;
EQEmu::Any result;
bool has_error;
std::exception error;
};
Task(TaskFn fn) {
m_fn = fn;
}
~Task() {
}
Task& Then(ResolveFn fn) {
m_then = fn;
return *this;
}
Task& Catch(RejectFn fn) {
m_catch = fn;
return *this;
}
Task& Finally(FinallyFn fn) {
m_finally = fn;
return *this;
}
void Run() {
uv_work_t *m_work = new uv_work_t;
memset(m_work, 0, sizeof(uv_work_t));
TaskBaton *baton = new TaskBaton();
baton->fn = m_fn;
baton->on_then = m_then;
baton->on_catch = m_catch;
baton->on_finally = m_finally;
baton->has_result = false;
baton->has_error = false;
m_work->data = baton;
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
TaskBaton *baton = (TaskBaton*)req->data;
baton->fn([baton](const EQEmu::Any& result) {
baton->has_error = false;
baton->has_result = true;
baton->result = result;
}, [baton](const std::exception &err) {
baton->has_error = true;
baton->has_result = false;
baton->error = err;
});
}, [](uv_work_t* req, int status) {
TaskBaton *baton = (TaskBaton*)req->data;
if (baton->has_error && baton->on_catch) {
baton->on_catch(baton->error);
}
else if (baton->has_result && baton->on_then) {
baton->on_then(baton->result);
}
if (baton->on_finally) {
baton->on_finally();
}
delete baton;
delete req;
});
}
private:
TaskFn m_fn;
ResolveFn m_then;
RejectFn m_catch;
FinallyFn m_finally;
};
}
-114
View File
@@ -1,114 +0,0 @@
#pragma once
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <queue>
#include <future>
namespace EQ
{
namespace Event
{
class TaskScheduler
{
public:
static const int DefaultThreadCount = 4;
TaskScheduler() : _running(false)
{
Start(DefaultThreadCount);
}
TaskScheduler(size_t threads) : _running(false)
{
Start(threads);
}
~TaskScheduler() {
Stop();
}
void Start(size_t threads) {
if (true == _running) {
return;
}
_running = true;
for (size_t i = 0; i < threads; ++i) {
_threads.push_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this)));
}
}
void Stop() {
if (false == _running) {
return;
}
{
std::unique_lock<std::mutex> lock(_lock);
_running = false;
}
_cv.notify_all();
for (auto &t : _threads) {
t.join();
}
}
template<typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::result_of<Fn(Args...)>::type> {
using return_type = typename std::result_of<Fn(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(_lock);
if (false == _running) {
throw std::runtime_error("Enqueue on stopped scheduler.");
}
_tasks.emplace([task]() { (*task)(); });
}
_cv.notify_one();
return res;
}
private:
void ProcessWork() {
for (;;) {
std::function<void()> work;
{
std::unique_lock<std::mutex> lock(_lock);
_cv.wait(lock, [this] { return !_running || !_tasks.empty(); });
if (false == _running) {
return;
}
work = std::move(_tasks.front());
_tasks.pop();
}
work();
}
}
bool _running = true;
std::vector<std::thread> _threads;
std::mutex _lock;
std::condition_variable _cv;
std::queue<std::function<void()>> _tasks;
};
}
}
+1
View File
@@ -1,4 +1,5 @@
#include "event_sub.h" #include "event_sub.h"
#include <string.h>
void EventSubscriptionWatcher::Subscribe(const std::string &event_name) void EventSubscriptionWatcher::Subscribe(const std::string &event_name)
{ {
-1
View File
@@ -1,7 +1,6 @@
#pragma once #pragma once
#include <unordered_map> #include <unordered_map>
#include <string>
class EventSubscriptionWatcher class EventSubscriptionWatcher
{ {
+11 -9
View File
@@ -18,7 +18,6 @@
#include "faction.h" #include "faction.h"
#include "races.h" #include "races.h"
#include "rulesys.h"
const char *FactionValueToString(FACTION_VALUE fv) const char *FactionValueToString(FACTION_VALUE fv)
{ {
@@ -60,31 +59,34 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
if (fm) { if (fm) {
character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod; character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod;
} }
if (character_value >= RuleI(Faction, AllyFactionMinimum)) { if (character_value >= 1101) {
return FACTION_ALLY; return FACTION_ALLY;
} }
if (character_value >= RuleI(Faction, WarmlyFactionMinimum)) { if (character_value >= 701 && character_value <= 1100) {
return FACTION_WARMLY; return FACTION_WARMLY;
} }
if (character_value >= RuleI(Faction, KindlyFactionMinimum)) { if (character_value >= 401 && character_value <= 700) {
return FACTION_KINDLY; return FACTION_KINDLY;
} }
if (character_value >= RuleI(Faction, AmiablyFactionMinimum)) { if (character_value >= 101 && character_value <= 400) {
return FACTION_AMIABLE; return FACTION_AMIABLE;
} }
if (character_value >= RuleI(Faction, IndifferentlyFactionMinimum)) { if (character_value >= 0 && character_value <= 100) {
return FACTION_INDIFFERENT; return FACTION_INDIFFERENT;
} }
if (character_value >= RuleI(Faction, ApprehensivelyFactionMinimum)) { if (character_value >= -100 && character_value <= -1) {
return FACTION_APPREHENSIVE; return FACTION_APPREHENSIVE;
} }
if (character_value >= RuleI(Faction, DubiouslyFactionMinimum)) { if (character_value >= -700 && character_value <= -101) {
return FACTION_DUBIOUS; return FACTION_DUBIOUS;
} }
if (character_value >= RuleI(Faction, ThreateninglyFactionMinimum)) { if (character_value >= -999 && character_value <= -701) {
return FACTION_THREATENLY; return FACTION_THREATENLY;
} }
if (character_value <= -1000) {
return FACTION_SCOWLS; return FACTION_SCOWLS;
}
return FACTION_INDIFFERENT;
} }
// this function should check if some races have more than one race define // this function should check if some races have more than one race define
Executable → Regular
-4
View File
@@ -50,8 +50,6 @@ struct NPCFactionList {
struct FactionMods struct FactionMods
{ {
int32 base; int32 base;
int16 min; // The lowest your personal earned faction can go - before race/class/diety adjustments.
int16 max; // The highest your personal earned faction can go - before race/class/diety adjustments.
int32 class_mod; int32 class_mod;
int32 race_mod; int32 race_mod;
int32 deity_mod; int32 deity_mod;
@@ -61,8 +59,6 @@ struct Faction {
int32 id; int32 id;
std::map<std::string, int16> mods; std::map<std::string, int16> mods;
int16 base; int16 base;
int16 min; // The lowest your personal earned faction can go - before race/class/diety adjustments.
int16 max; // The highest your personal earned faction can go - before race/class/diety adjustments.
char name[50]; char name[50];
}; };
+6 -4
View File
@@ -150,11 +150,10 @@ enum { //reuse times
enum { //timer settings, all in milliseconds enum { //timer settings, all in milliseconds
AImovement_duration = 100, AImovement_duration = 100,
AIthink_duration = 50, AIthink_duration = 150,
AIscanarea_delay = 6000, AIscanarea_delay = 6000,
AIfeignremember_delay = 500, AIfeignremember_delay = 500,
AItarget_check_duration = 500, AItarget_check_duration = 500,
AI_scan_door_open_interval = 1000,
// AIClientScanarea_delay = 750, //used in REVERSE_AGGRO // AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed
@@ -268,10 +267,13 @@ enum {
commandBanPlayers = 100, //can set bans on players commandBanPlayers = 100, //can set bans on players
commandChangeDatarate = 201, //edit client's data rate commandChangeDatarate = 201, //edit client's data rate
commandZoneToCoords = 0, //can #zone with coords commandZoneToCoords = 0, //can #zone with coords
commandInterrogateInv = 100, //below this == only log on error state and self-only target dump commandInterrogateInv = 100 //below this == only log on error state and self-only target dump
commandInvSnapshot = 150 //ability to clear/restore snapshots
}; };
//default states for logging flag on NPCs and clients (having NPCs on by default is prolly a bad idea)
#define CLIENT_DEFAULT_LOGGING_ENABLED true
#define NPC_DEFAULT_LOGGING_ENABLED false
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars // This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
#define SAYLINK_ITEM_ID 0xFFFFF #define SAYLINK_ITEM_ID 0xFFFFF
+54
View File
@@ -0,0 +1,54 @@
================================================================================
OpenGL Mathematics (GLM)
--------------------------------------------------------------------------------
GLM can be distributed and/or modified under the terms of either
a) The Happy Bunny License, or b) the MIT License.
================================================================================
The Happy Bunny License (Modified MIT License)
--------------------------------------------------------------------------------
Copyright (c) 2005 - 2016 G-Truc Creation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Restrictions: By making use of the Software for military purposes, you choose
to make a Bunny unhappy.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================================================
The MIT License
--------------------------------------------------------------------------------
Copyright (c) 2005 - 2016 G-Truc Creation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+67
View File
@@ -0,0 +1,67 @@
file(GLOB ROOT_SOURCE *.cpp)
file(GLOB ROOT_INLINE *.inl)
file(GLOB ROOT_HEADER *.hpp)
file(GLOB ROOT_TEXT ../*.txt)
file(GLOB ROOT_MD ../*.md)
file(GLOB ROOT_NAT ../util/glm.natvis)
file(GLOB_RECURSE CORE_SOURCE ./detail/*.cpp)
file(GLOB_RECURSE CORE_INLINE ./detail/*.inl)
file(GLOB_RECURSE CORE_HEADER ./detail/*.hpp)
file(GLOB_RECURSE GTC_SOURCE ./gtc/*.cpp)
file(GLOB_RECURSE GTC_INLINE ./gtc/*.inl)
file(GLOB_RECURSE GTC_HEADER ./gtc/*.hpp)
file(GLOB_RECURSE GTX_SOURCE ./gtx/*.cpp)
file(GLOB_RECURSE GTX_INLINE ./gtx/*.inl)
file(GLOB_RECURSE GTX_HEADER ./gtx/*.hpp)
file(GLOB_RECURSE SIMD_SOURCE ./simd/*.cpp)
file(GLOB_RECURSE SIMD_INLINE ./simd/*.inl)
file(GLOB_RECURSE SIMD_HEADER ./simd/*.h)
source_group("Text Files" FILES ${ROOT_TEXT} ${ROOT_MD})
source_group("Core Files" FILES ${CORE_SOURCE})
source_group("Core Files" FILES ${CORE_INLINE})
source_group("Core Files" FILES ${CORE_HEADER})
source_group("GTC Files" FILES ${GTC_SOURCE})
source_group("GTC Files" FILES ${GTC_INLINE})
source_group("GTC Files" FILES ${GTC_HEADER})
source_group("GTX Files" FILES ${GTX_SOURCE})
source_group("GTX Files" FILES ${GTX_INLINE})
source_group("GTX Files" FILES ${GTX_HEADER})
source_group("SIMD Files" FILES ${SIMD_SOURCE})
source_group("SIMD Files" FILES ${SIMD_INLINE})
source_group("SIMD Files" FILES ${SIMD_HEADER})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
if(GLM_STATIC_LIBRARY_ENABLE OR GLM_DYNAMIC_LIBRARY_ENABLE)
if(GLM_STATIC_LIBRARY_ENABLE)
add_library(glm_static STATIC ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT}
${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER}
${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER}
${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER}
${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}
${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER})
endif(GLM_STATIC_LIBRARY_ENABLE)
if(GLM_DYNAMIC_LIBRARY_ENABLE)
add_library(glm_shared SHARED ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT}
${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER}
${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER}
${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER}
${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}
${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER})
endif(GLM_DYNAMIC_LIBRARY_ENABLE)
else(GLM_STATIC_LIBRARY_ENABLE OR GLM_DYNAMIC_LIBRARY_ENABLE)
add_executable(glm_dummy ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT}
${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER}
${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER}
${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER}
${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}
${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER})
endif(GLM_STATIC_LIBRARY_ENABLE OR GLM_DYNAMIC_LIBRARY_ENABLE)
+6
View File
@@ -0,0 +1,6 @@
/// @ref core
/// @file glm/common.hpp
#pragma once
#include "detail/func_common.hpp"
+399
View File
@@ -0,0 +1,399 @@
/// @ref core
/// @file glm/detail/_features.hpp
#pragma once
// #define GLM_CXX98_EXCEPTIONS
// #define GLM_CXX98_RTTI
// #define GLM_CXX11_RVALUE_REFERENCES
// Rvalue references - GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html
// GLM_CXX11_TRAILING_RETURN
// Rvalue references for *this - GCC not supported
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm
// GLM_CXX11_NONSTATIC_MEMBER_INIT
// Initialization of class objects by rvalues - GCC any
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1610.html
// GLM_CXX11_NONSTATIC_MEMBER_INIT
// Non-static data member initializers - GCC 4.7
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm
// #define GLM_CXX11_VARIADIC_TEMPLATE
// Variadic templates - GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf
//
// Extending variadic template template parameters - GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf
// #define GLM_CXX11_GENERALIZED_INITIALIZERS
// Initializer lists - GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm
// #define GLM_CXX11_STATIC_ASSERT
// Static assertions - GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html
// #define GLM_CXX11_AUTO_TYPE
// auto-typed variables - GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf
// #define GLM_CXX11_AUTO_TYPE
// Multi-declarator auto - GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1737.pdf
// #define GLM_CXX11_AUTO_TYPE
// Removal of auto as a storage-class specifier - GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2546.htm
// #define GLM_CXX11_AUTO_TYPE
// New function declarator syntax - GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm
// #define GLM_CXX11_LAMBDAS
// New wording for C++0x lambdas - GCC 4.5
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf
// #define GLM_CXX11_DECLTYPE
// Declared type of an expression - GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf
//
// Right angle brackets - GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
//
// Default template arguments for function templates DR226 GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226
//
// Solving the SFINAE problem for expressions DR339 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html
// #define GLM_CXX11_ALIAS_TEMPLATE
// Template aliases N2258 GCC 4.7
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf
//
// Extern templates N1987 Yes
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm
// #define GLM_CXX11_NULLPTR
// Null pointer constant N2431 GCC 4.6
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
// #define GLM_CXX11_STRONG_ENUMS
// Strongly-typed enums N2347 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf
//
// Forward declarations for enums N2764 GCC 4.6
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf
//
// Generalized attributes N2761 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf
//
// Generalized constant expressions N2235 GCC 4.6
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf
//
// Alignment support N2341 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf
// #define GLM_CXX11_DELEGATING_CONSTRUCTORS
// Delegating constructors N1986 GCC 4.7
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf
//
// Inheriting constructors N2540 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm
// #define GLM_CXX11_EXPLICIT_CONVERSIONS
// Explicit conversion operators N2437 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf
//
// New character types N2249 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html
//
// Unicode string literals N2442 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm
//
// Raw string literals N2442 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm
//
// Universal character name literals N2170 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html
// #define GLM_CXX11_USER_LITERALS
// User-defined literals N2765 GCC 4.7
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf
//
// Standard Layout Types N2342 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm
// #define GLM_CXX11_DEFAULTED_FUNCTIONS
// #define GLM_CXX11_DELETED_FUNCTIONS
// Defaulted and deleted functions N2346 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm
//
// Extended friend declarations N1791 GCC 4.7
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf
//
// Extending sizeof N2253 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html
// #define GLM_CXX11_INLINE_NAMESPACES
// Inline namespaces N2535 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm
// #define GLM_CXX11_UNRESTRICTED_UNIONS
// Unrestricted unions N2544 GCC 4.6
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf
// #define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS
// Local and unnamed types as template arguments N2657 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm
// #define GLM_CXX11_RANGE_FOR
// Range-based for N2930 GCC 4.6
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html
// #define GLM_CXX11_OVERRIDE_CONTROL
// Explicit virtual overrides N2928 N3206 N3272 GCC 4.7
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm
//
// Minimal support for garbage collection and reachability-based leak detection N2670 No
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2670.htm
// #define GLM_CXX11_NOEXCEPT
// Allowing move constructors to throw [noexcept] N3050 GCC 4.6 (core language only)
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html
//
// Defining move special member functions N3053 GCC 4.6
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html
//
// Sequence points N2239 Yes
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html
//
// Atomic operations N2427 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html
//
// Strong Compare and Exchange N2748 GCC 4.5
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html
//
// Bidirectional Fences N2752 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm
//
// Memory model N2429 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm
//
// Data-dependency ordering: atomics and memory model N2664 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm
//
// Propagating exceptions N2179 GCC 4.4
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html
//
// Abandoning a process and at_quick_exit N2440 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2440.htm
//
// Allow atomics use in signal handlers N2547 Yes
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2547.htm
//
// Thread-local storage N2659 GCC 4.8
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm
//
// Dynamic initialization and destruction with concurrency N2660 GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm
//
// __func__ predefined identifier N2340 GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm
//
// C99 preprocessor N1653 GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm
//
// long long N1811 GCC 4.3
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf
//
// Extended integral types N1988 Yes
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf
#if(GLM_COMPILER & GLM_COMPILER_GCC)
# if(GLM_COMPILER >= GLM_COMPILER_GCC43)
# define GLM_CXX11_STATIC_ASSERT
# endif
#elif(GLM_COMPILER & GLM_COMPILER_CLANG)
# if(__has_feature(cxx_exceptions))
# define GLM_CXX98_EXCEPTIONS
# endif
# if(__has_feature(cxx_rtti))
# define GLM_CXX98_RTTI
# endif
# if(__has_feature(cxx_access_control_sfinae))
# define GLM_CXX11_ACCESS_CONTROL_SFINAE
# endif
# if(__has_feature(cxx_alias_templates))
# define GLM_CXX11_ALIAS_TEMPLATE
# endif
# if(__has_feature(cxx_alignas))
# define GLM_CXX11_ALIGNAS
# endif
# if(__has_feature(cxx_attributes))
# define GLM_CXX11_ATTRIBUTES
# endif
# if(__has_feature(cxx_constexpr))
# define GLM_CXX11_CONSTEXPR
# endif
# if(__has_feature(cxx_decltype))
# define GLM_CXX11_DECLTYPE
# endif
# if(__has_feature(cxx_default_function_template_args))
# define GLM_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS
# endif
# if(__has_feature(cxx_defaulted_functions))
# define GLM_CXX11_DEFAULTED_FUNCTIONS
# endif
# if(__has_feature(cxx_delegating_constructors))
# define GLM_CXX11_DELEGATING_CONSTRUCTORS
# endif
# if(__has_feature(cxx_deleted_functions))
# define GLM_CXX11_DELETED_FUNCTIONS
# endif
# if(__has_feature(cxx_explicit_conversions))
# define GLM_CXX11_EXPLICIT_CONVERSIONS
# endif
# if(__has_feature(cxx_generalized_initializers))
# define GLM_CXX11_GENERALIZED_INITIALIZERS
# endif
# if(__has_feature(cxx_implicit_moves))
# define GLM_CXX11_IMPLICIT_MOVES
# endif
# if(__has_feature(cxx_inheriting_constructors))
# define GLM_CXX11_INHERITING_CONSTRUCTORS
# endif
# if(__has_feature(cxx_inline_namespaces))
# define GLM_CXX11_INLINE_NAMESPACES
# endif
# if(__has_feature(cxx_lambdas))
# define GLM_CXX11_LAMBDAS
# endif
# if(__has_feature(cxx_local_type_template_args))
# define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS
# endif
# if(__has_feature(cxx_noexcept))
# define GLM_CXX11_NOEXCEPT
# endif
# if(__has_feature(cxx_nonstatic_member_init))
# define GLM_CXX11_NONSTATIC_MEMBER_INIT
# endif
# if(__has_feature(cxx_nullptr))
# define GLM_CXX11_NULLPTR
# endif
# if(__has_feature(cxx_override_control))
# define GLM_CXX11_OVERRIDE_CONTROL
# endif
# if(__has_feature(cxx_reference_qualified_functions))
# define GLM_CXX11_REFERENCE_QUALIFIED_FUNCTIONS
# endif
# if(__has_feature(cxx_range_for))
# define GLM_CXX11_RANGE_FOR
# endif
# if(__has_feature(cxx_raw_string_literals))
# define GLM_CXX11_RAW_STRING_LITERALS
# endif
# if(__has_feature(cxx_rvalue_references))
# define GLM_CXX11_RVALUE_REFERENCES
# endif
# if(__has_feature(cxx_static_assert))
# define GLM_CXX11_STATIC_ASSERT
# endif
# if(__has_feature(cxx_auto_type))
# define GLM_CXX11_AUTO_TYPE
# endif
# if(__has_feature(cxx_strong_enums))
# define GLM_CXX11_STRONG_ENUMS
# endif
# if(__has_feature(cxx_trailing_return))
# define GLM_CXX11_TRAILING_RETURN
# endif
# if(__has_feature(cxx_unicode_literals))
# define GLM_CXX11_UNICODE_LITERALS
# endif
# if(__has_feature(cxx_unrestricted_unions))
# define GLM_CXX11_UNRESTRICTED_UNIONS
# endif
# if(__has_feature(cxx_user_literals))
# define GLM_CXX11_USER_LITERALS
# endif
# if(__has_feature(cxx_variadic_templates))
# define GLM_CXX11_VARIADIC_TEMPLATES
# endif
#endif//(GLM_COMPILER & GLM_COMPILER_CLANG)
+30
View File
@@ -0,0 +1,30 @@
/// @ref core
/// @file glm/detail/_fixes.hpp
#include <cmath>
//! Workaround for compatibility with other libraries
#ifdef max
#undef max
#endif
//! Workaround for compatibility with other libraries
#ifdef min
#undef min
#endif
//! Workaround for Android
#ifdef isnan
#undef isnan
#endif
//! Workaround for Android
#ifdef isinf
#undef isinf
#endif
//! Workaround for Chrone Native Client
#ifdef log2
#undef log2
#endif
+107
View File
@@ -0,0 +1,107 @@
/// @ref core
/// @file glm/detail/_noise.hpp
#pragma once
#include "../vec2.hpp"
#include "../vec3.hpp"
#include "../vec4.hpp"
#include "../common.hpp"
namespace glm{
namespace detail
{
template <typename T>
GLM_FUNC_QUALIFIER T mod289(T const & x)
{
return x - floor(x * static_cast<T>(1.0) / static_cast<T>(289.0)) * static_cast<T>(289.0);
}
template <typename T>
GLM_FUNC_QUALIFIER T permute(T const & x)
{
return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec2<T, P> permute(tvec2<T, P> const & x)
{
return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> permute(tvec3<T, P> const & x)
{
return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec4<T, P> permute(tvec4<T, P> const & x)
{
return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x);
}
/*
template <typename T, precision P, template<typename> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> permute(vecType<T, P> const & x)
{
return mod289(((x * T(34)) + T(1)) * x);
}
*/
template <typename T>
GLM_FUNC_QUALIFIER T taylorInvSqrt(T const & r)
{
return T(1.79284291400159) - T(0.85373472095314) * r;
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec2<T, P> taylorInvSqrt(tvec2<T, P> const & r)
{
return T(1.79284291400159) - T(0.85373472095314) * r;
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> taylorInvSqrt(tvec3<T, P> const & r)
{
return T(1.79284291400159) - T(0.85373472095314) * r;
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec4<T, P> taylorInvSqrt(tvec4<T, P> const & r)
{
return T(1.79284291400159) - T(0.85373472095314) * r;
}
/*
template <typename T, precision P, template<typename> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> taylorInvSqrt(vecType<T, P> const & r)
{
return T(1.79284291400159) - T(0.85373472095314) * r;
}
*/
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec2<T, P> fade(tvec2<T, P> const & t)
{
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> fade(tvec3<T, P> const & t)
{
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec4<T, P> fade(tvec4<T, P> const & t)
{
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
}
/*
template <typename T, precision P, template <typename> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> fade(vecType<T, P> const & t)
{
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
}
*/
}//namespace detail
}//namespace glm
+797
View File
@@ -0,0 +1,797 @@
/// @ref core
/// @file glm/detail/_swizzle.hpp
#pragma once
namespace glm{
namespace detail
{
// Internal class for implementing swizzle operators
template <typename T, int N>
struct _swizzle_base0
{
protected:
GLM_FUNC_QUALIFIER T& elem(size_t i){ return (reinterpret_cast<T*>(_buffer))[i]; }
GLM_FUNC_QUALIFIER T const& elem(size_t i) const{ return (reinterpret_cast<const T*>(_buffer))[i]; }
// Use an opaque buffer to *ensure* the compiler doesn't call a constructor.
// The size 1 buffer is assumed to aligned to the actual members so that the
// elem()
char _buffer[1];
};
template <int N, typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3, bool Aligned>
struct _swizzle_base1 : public _swizzle_base0<T, N>
{
};
template <typename T, precision P, template <typename, precision> class vecType, int E0, int E1, bool Aligned>
struct _swizzle_base1<2, T, P, vecType, E0,E1,-1,-2, Aligned> : public _swizzle_base0<T, 2>
{
GLM_FUNC_QUALIFIER vecType<T, P> operator ()() const { return vecType<T, P>(this->elem(E0), this->elem(E1)); }
};
template <typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, bool Aligned>
struct _swizzle_base1<3, T, P, vecType, E0,E1,E2,-1, Aligned> : public _swizzle_base0<T, 3>
{
GLM_FUNC_QUALIFIER vecType<T, P> operator ()() const { return vecType<T, P>(this->elem(E0), this->elem(E1), this->elem(E2)); }
};
template <typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3, bool Aligned>
struct _swizzle_base1<4, T, P, vecType, E0,E1,E2,E3, Aligned> : public _swizzle_base0<T, 4>
{
GLM_FUNC_QUALIFIER vecType<T, P> operator ()() const { return vecType<T, P>(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); }
};
// Internal class for implementing swizzle operators
/*
Template parameters:
ValueType = type of scalar values (e.g. float, double)
VecType = class the swizzle is applies to (e.g. tvec3<float>)
N = number of components in the vector (e.g. 3)
E0...3 = what index the n-th element of this swizzle refers to in the unswizzled vec
DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles
containing duplicate elements so that they cannot be used as r-values).
*/
template <int N, typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3, int DUPLICATE_ELEMENTS>
struct _swizzle_base2 : public _swizzle_base1<N, T, P, vecType, E0,E1,E2,E3, detail::is_aligned<P>::value>
{
GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const T& t)
{
for (int i = 0; i < N; ++i)
(*this)[i] = t;
return *this;
}
GLM_FUNC_QUALIFIER _swizzle_base2& operator= (vecType<T, P> const& that)
{
struct op {
GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e = t; }
};
_apply_op(that, op());
return *this;
}
GLM_FUNC_QUALIFIER void operator -= (vecType<T, P> const& that)
{
struct op {
GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e -= t; }
};
_apply_op(that, op());
}
GLM_FUNC_QUALIFIER void operator += (vecType<T, P> const& that)
{
struct op {
GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e += t; }
};
_apply_op(that, op());
}
GLM_FUNC_QUALIFIER void operator *= (vecType<T, P> const& that)
{
struct op {
GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e *= t; }
};
_apply_op(that, op());
}
GLM_FUNC_QUALIFIER void operator /= (vecType<T, P> const& that)
{
struct op {
GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e /= t; }
};
_apply_op(that, op());
}
GLM_FUNC_QUALIFIER T& operator[](size_t i)
{
const int offset_dst[4] = { E0, E1, E2, E3 };
return this->elem(offset_dst[i]);
}
GLM_FUNC_QUALIFIER T operator[](size_t i) const
{
const int offset_dst[4] = { E0, E1, E2, E3 };
return this->elem(offset_dst[i]);
}
protected:
template <typename U>
GLM_FUNC_QUALIFIER void _apply_op(vecType<T, P> const& that, U op)
{
// Make a copy of the data in this == &that.
// The copier should optimize out the copy in cases where the function is
// properly inlined and the copy is not necessary.
T t[N];
for (int i = 0; i < N; ++i)
t[i] = that[i];
for (int i = 0; i < N; ++i)
op( (*this)[i], t[i] );
}
};
// Specialization for swizzles containing duplicate elements. These cannot be modified.
template <int N, typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3>
struct _swizzle_base2<N, T, P, vecType, E0,E1,E2,E3, 1> : public _swizzle_base1<N, T, P, vecType, E0,E1,E2,E3, detail::is_aligned<P>::value>
{
struct Stub {};
GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const &) { return *this; }
GLM_FUNC_QUALIFIER T operator[] (size_t i) const
{
const int offset_dst[4] = { E0, E1, E2, E3 };
return this->elem(offset_dst[i]);
}
};
template <int N, typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3>
struct _swizzle : public _swizzle_base2<N, T, P, vecType, E0, E1, E2, E3, (E0 == E1 || E0 == E2 || E0 == E3 || E1 == E2 || E1 == E3 || E2 == E3)>
{
typedef _swizzle_base2<N, T, P, vecType, E0, E1, E2, E3, (E0 == E1 || E0 == E2 || E0 == E3 || E1 == E2 || E1 == E3 || E2 == E3)> base_type;
using base_type::operator=;
GLM_FUNC_QUALIFIER operator vecType<T, P> () const { return (*this)(); }
};
//
// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros
//
#define _GLM_SWIZZLE_TEMPLATE1 template <int N, typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3>
#define _GLM_SWIZZLE_TEMPLATE2 template <int N, typename T, precision P, template <typename, precision> class vecType, int E0, int E1, int E2, int E3, int F0, int F1, int F2, int F3>
#define _GLM_SWIZZLE_TYPE1 _swizzle<N, T, P, vecType, E0, E1, E2, E3>
#define _GLM_SWIZZLE_TYPE2 _swizzle<N, T, P, vecType, F0, F1, F2, F3>
//
// Wrapper for a binary operator (e.g. u.yy + v.zy)
//
#define _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \
_GLM_SWIZZLE_TEMPLATE2 \
GLM_FUNC_QUALIFIER vecType<T, P> operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \
{ \
return a() OPERAND b(); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER vecType<T, P> operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const vecType<T, P>& b) \
{ \
return a() OPERAND b; \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER vecType<T, P> operator OPERAND ( const vecType<T, P>& a, const _GLM_SWIZZLE_TYPE1& b) \
{ \
return a OPERAND b(); \
}
//
// Wrapper for a operand between a swizzle and a binary (e.g. 1.0f - u.xyz)
//
#define _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER vecType<T, P> operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const T& b) \
{ \
return a() OPERAND b; \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER vecType<T, P> operator OPERAND ( const T& a, const _GLM_SWIZZLE_TYPE1& b) \
{ \
return a OPERAND b(); \
}
//
// Macro for wrapping a function taking one argument (e.g. abs())
//
#define _GLM_SWIZZLE_FUNCTION_1_ARGS(RETURN_TYPE,FUNCTION) \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a) \
{ \
return FUNCTION(a()); \
}
//
// Macro for wrapping a function taking two vector arguments (e.g. dot()).
//
#define _GLM_SWIZZLE_FUNCTION_2_ARGS(RETURN_TYPE,FUNCTION) \
_GLM_SWIZZLE_TEMPLATE2 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \
{ \
return FUNCTION(a(), b()); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b) \
{ \
return FUNCTION(a(), b()); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename V& b) \
{ \
return FUNCTION(a(), b); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const V& a, const _GLM_SWIZZLE_TYPE1& b) \
{ \
return FUNCTION(a, b()); \
}
//
// Macro for wrapping a function take 2 vec arguments followed by a scalar (e.g. mix()).
//
#define _GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(RETURN_TYPE,FUNCTION) \
_GLM_SWIZZLE_TEMPLATE2 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b, const T& c) \
{ \
return FUNCTION(a(), b(), c); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \
{ \
return FUNCTION(a(), b(), c); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b, const T& c)\
{ \
return FUNCTION(a(), b, c); \
} \
_GLM_SWIZZLE_TEMPLATE1 \
GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const typename V& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \
{ \
return FUNCTION(a, b(), c); \
}
}//namespace detail
}//namespace glm
namespace glm
{
namespace detail
{
_GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(-)
_GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*)
_GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(+)
_GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(-)
_GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(*)
_GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(/)
}
//
// Swizzles are distinct types from the unswizzled type. The below macros will
// provide template specializations for the swizzle types for the given functions
// so that the compiler does not have any ambiguity to choosing how to handle
// the function.
//
// The alternative is to use the operator()() when calling the function in order
// to explicitly convert the swizzled type to the unswizzled type.
//
//_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, abs);
//_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acos);
//_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acosh);
//_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, all);
//_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, any);
//_GLM_SWIZZLE_FUNCTION_2_ARGS(value_type, dot);
//_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, cross);
//_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, step);
//_GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(vec_type, mix);
}
#define _GLM_SWIZZLE2_2_MEMBERS(T, P, V, E0,E1) \
struct { detail::_swizzle<2, T, P, V, 0,0,-1,-2> E0 ## E0; }; \
struct { detail::_swizzle<2, T, P, V, 0,1,-1,-2> E0 ## E1; }; \
struct { detail::_swizzle<2, T, P, V, 1,0,-1,-2> E1 ## E0; }; \
struct { detail::_swizzle<2, T, P, V, 1,1,-1,-2> E1 ## E1; };
#define _GLM_SWIZZLE2_3_MEMBERS(T, P, V, E0,E1) \
struct { detail::_swizzle<3,T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \
struct { detail::_swizzle<3,T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \
struct { detail::_swizzle<3,T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \
struct { detail::_swizzle<3,T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \
struct { detail::_swizzle<3,T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \
struct { detail::_swizzle<3,T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \
struct { detail::_swizzle<3,T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \
struct { detail::_swizzle<3,T, P, V, 1,1,1,-1> E1 ## E1 ## E1; };
#define _GLM_SWIZZLE2_4_MEMBERS(T, P, V, E0,E1) \
struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; };
#define _GLM_SWIZZLE3_2_MEMBERS(T, P, V, E0,E1,E2) \
struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \
struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \
struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; };
#define _GLM_SWIZZLE3_3_MEMBERS(T, P, V ,E0,E1,E2) \
struct { detail::_swizzle<3, T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,2,-1> E2 ## E2 ## E2; };
#define _GLM_SWIZZLE3_4_MEMBERS(T, P, V, E0,E1,E2) \
struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4,T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; };
#define _GLM_SWIZZLE4_2_MEMBERS(T, P, V, E0,E1,E2,E3) \
struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \
struct { detail::_swizzle<2,T, P, V, 0,3,-1,-2> E0 ## E3; }; \
struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \
struct { detail::_swizzle<2,T, P, V, 1,3,-1,-2> E1 ## E3; }; \
struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; \
struct { detail::_swizzle<2,T, P, V, 2,3,-1,-2> E2 ## E3; }; \
struct { detail::_swizzle<2,T, P, V, 3,0,-1,-2> E3 ## E0; }; \
struct { detail::_swizzle<2,T, P, V, 3,1,-1,-2> E3 ## E1; }; \
struct { detail::_swizzle<2,T, P, V, 3,2,-1,-2> E3 ## E2; }; \
struct { detail::_swizzle<2,T, P, V, 3,3,-1,-2> E3 ## E3; };
#define _GLM_SWIZZLE4_3_MEMBERS(T, P, V, E0,E1,E2,E3) \
struct { detail::_swizzle<3, T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 0,0,3,-1> E0 ## E0 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 0,1,3,-1> E0 ## E1 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 0,2,3,-1> E0 ## E2 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 0,3,0,-1> E0 ## E3 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 0,3,1,-1> E0 ## E3 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 0,3,2,-1> E0 ## E3 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 0,3,3,-1> E0 ## E3 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,0,3,-1> E1 ## E0 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,1,3,-1> E1 ## E1 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,2,3,-1> E1 ## E2 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 1,3,0,-1> E1 ## E3 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 1,3,1,-1> E1 ## E3 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 1,3,2,-1> E1 ## E3 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 1,3,3,-1> E1 ## E3 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,0,3,-1> E2 ## E0 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,1,3,-1> E2 ## E1 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,2,-1> E2 ## E2 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,2,3,-1> E2 ## E2 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 2,3,0,-1> E2 ## E3 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 2,3,1,-1> E2 ## E3 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 2,3,2,-1> E2 ## E3 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 2,3,3,-1> E2 ## E3 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 3,0,0,-1> E3 ## E0 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 3,0,1,-1> E3 ## E0 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 3,0,2,-1> E3 ## E0 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 3,0,3,-1> E3 ## E0 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 3,1,0,-1> E3 ## E1 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 3,1,1,-1> E3 ## E1 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 3,1,2,-1> E3 ## E1 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 3,1,3,-1> E3 ## E1 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 3,2,0,-1> E3 ## E2 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 3,2,1,-1> E3 ## E2 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 3,2,2,-1> E3 ## E2 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 3,2,3,-1> E3 ## E2 ## E3; }; \
struct { detail::_swizzle<3, T, P, V, 3,3,0,-1> E3 ## E3 ## E0; }; \
struct { detail::_swizzle<3, T, P, V, 3,3,1,-1> E3 ## E3 ## E1; }; \
struct { detail::_swizzle<3, T, P, V, 3,3,2,-1> E3 ## E3 ## E2; }; \
struct { detail::_swizzle<3, T, P, V, 3,3,3,-1> E3 ## E3 ## E3; };
#define _GLM_SWIZZLE4_4_MEMBERS(T, P, V, E0,E1,E2,E3) \
struct { detail::_swizzle<4, T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \
struct { detail::_swizzle<4, T, P, V, 3,3,3,3> E3 ## E3 ## E3 ## E3; };
+696
View File
@@ -0,0 +1,696 @@
/// @ref core
/// @file glm/detail/_swizzle_func.hpp
#pragma once
#define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \
SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B() CONST \
{ \
return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B); \
}
#define GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \
SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B ## C() CONST \
{ \
return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C); \
}
#define GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \
SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B ## C ## D() CONST \
{ \
return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C, this->D); \
}
#define GLM_SWIZZLE_GEN_VEC2_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \
template <typename TMPL_TYPE> \
SWIZZLED_TYPE<TMPL_TYPE> CLASS_TYPE<TMPL_TYPE, PRECISION>::A ## B() CONST \
{ \
return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B); \
}
#define GLM_SWIZZLE_GEN_VEC3_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \
template <typename TMPL_TYPE> \
SWIZZLED_TYPE<TMPL_TYPE> CLASS_TYPE<TMPL_TYPE, PRECISION>::A ## B ## C() CONST \
{ \
return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C); \
}
#define GLM_SWIZZLE_GEN_VEC4_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \
template <typename TMPL_TYPE> \
SWIZZLED_TYPE<TMPL_TYPE> CLASS_TYPE<TMPL_TYPE, PRECISION>::A ## B ## C ## D() CONST \
{ \
return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C, this->D); \
}
#define GLM_MUTABLE
#define GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A)
#define GLM_SWIZZLE_GEN_REF_FROM_VEC2(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE) \
GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, x, y) \
GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, r, g) \
GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, s, t)
//GLM_SWIZZLE_GEN_REF_FROM_VEC2(valType, detail::vec2, detail::ref2)
#define GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B)
#define GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B, A)
#define GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C)
#define GLM_SWIZZLE_GEN_REF_FROM_VEC3(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE) \
GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, x, y, z) \
GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, r, g, b) \
GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, s, t, p)
//GLM_SWIZZLE_GEN_REF_FROM_VEC3(valType, detail::vec3, detail::ref2, detail::ref3)
#define GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, C)
#define GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B)
#define GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C, A)
#define GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D)
#define GLM_SWIZZLE_GEN_REF_FROM_VEC4(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \
GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \
GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \
GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q)
//GLM_SWIZZLE_GEN_REF_FROM_VEC4(valType, detail::vec4, detail::ref2, detail::ref3, detail::ref4)
#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B)
#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B)
#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B)
#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B) \
GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B)
#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t)
//GLM_SWIZZLE_GEN_VEC_FROM_VEC2(valType, detail::vec2, detail::vec2, detail::vec3, detail::vec4)
#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C)
#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C)
#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C)
#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C)
#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p)
//GLM_SWIZZLE_GEN_VEC_FROM_VEC3(valType, detail::vec3, detail::vec2, detail::vec3, detail::vec4)
#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C) \
GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D)
#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C) \
GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D)
#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, D) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, A) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, B) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, C) \
GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, D)
#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \
GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D)
#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \
GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q)
//GLM_SWIZZLE_GEN_VEC_FROM_VEC4(valType, detail::vec4, detail::vec2, detail::vec3, detail::vec4)
+131
View File
@@ -0,0 +1,131 @@
/// @ref core
/// @file glm/detail/_vectorize.hpp
#pragma once
#include "type_vec1.hpp"
#include "type_vec2.hpp"
#include "type_vec3.hpp"
#include "type_vec4.hpp"
namespace glm{
namespace detail
{
template <typename R, typename T, precision P, template <typename, precision> class vecType>
struct functor1{};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec1>
{
GLM_FUNC_QUALIFIER static tvec1<R, P> call(R (*Func) (T x), tvec1<T, P> const & v)
{
return tvec1<R, P>(Func(v.x));
}
};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec2>
{
GLM_FUNC_QUALIFIER static tvec2<R, P> call(R (*Func) (T x), tvec2<T, P> const & v)
{
return tvec2<R, P>(Func(v.x), Func(v.y));
}
};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec3>
{
GLM_FUNC_QUALIFIER static tvec3<R, P> call(R (*Func) (T x), tvec3<T, P> const & v)
{
return tvec3<R, P>(Func(v.x), Func(v.y), Func(v.z));
}
};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<R, P> call(R (*Func) (T x), tvec4<T, P> const & v)
{
return tvec4<R, P>(Func(v.x), Func(v.y), Func(v.z), Func(v.w));
}
};
template <typename T, precision P, template <typename, precision> class vecType>
struct functor2{};
template <typename T, precision P>
struct functor2<T, P, tvec1>
{
GLM_FUNC_QUALIFIER static tvec1<T, P> call(T (*Func) (T x, T y), tvec1<T, P> const & a, tvec1<T, P> const & b)
{
return tvec1<T, P>(Func(a.x, b.x));
}
};
template <typename T, precision P>
struct functor2<T, P, tvec2>
{
GLM_FUNC_QUALIFIER static tvec2<T, P> call(T (*Func) (T x, T y), tvec2<T, P> const & a, tvec2<T, P> const & b)
{
return tvec2<T, P>(Func(a.x, b.x), Func(a.y, b.y));
}
};
template <typename T, precision P>
struct functor2<T, P, tvec3>
{
GLM_FUNC_QUALIFIER static tvec3<T, P> call(T (*Func) (T x, T y), tvec3<T, P> const & a, tvec3<T, P> const & b)
{
return tvec3<T, P>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z));
}
};
template <typename T, precision P>
struct functor2<T, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<T, P> call(T (*Func) (T x, T y), tvec4<T, P> const & a, tvec4<T, P> const & b)
{
return tvec4<T, P>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w));
}
};
template <typename T, precision P, template <typename, precision> class vecType>
struct functor2_vec_sca{};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec1>
{
GLM_FUNC_QUALIFIER static tvec1<T, P> call(T (*Func) (T x, T y), tvec1<T, P> const & a, T b)
{
return tvec1<T, P>(Func(a.x, b));
}
};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec2>
{
GLM_FUNC_QUALIFIER static tvec2<T, P> call(T (*Func) (T x, T y), tvec2<T, P> const & a, T b)
{
return tvec2<T, P>(Func(a.x, b), Func(a.y, b));
}
};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec3>
{
GLM_FUNC_QUALIFIER static tvec3<T, P> call(T (*Func) (T x, T y), tvec3<T, P> const & a, T b)
{
return tvec3<T, P>(Func(a.x, b), Func(a.y, b), Func(a.z, b));
}
};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<T, P> call(T (*Func) (T x, T y), tvec4<T, P> const & a, T b)
{
return tvec4<T, P>(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b));
}
};
}//namespace detail
}//namespace glm
+207
View File
@@ -0,0 +1,207 @@
/// @ref core
/// @file glm/core/dummy.cpp
///
/// GLM is a header only library. There is nothing to compile.
/// dummy.cpp exist only a wordaround for CMake file.
/*
#define GLM_MESSAGES
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <limits>
struct material
{
glm::vec4 emission; // Ecm
glm::vec4 ambient; // Acm
glm::vec4 diffuse; // Dcm
glm::vec4 specular; // Scm
float shininess; // Srm
};
struct light
{
glm::vec4 ambient; // Acli
glm::vec4 diffuse; // Dcli
glm::vec4 specular; // Scli
glm::vec4 position; // Ppli
glm::vec4 halfVector; // Derived: Hi
glm::vec3 spotDirection; // Sdli
float spotExponent; // Srli
float spotCutoff; // Crli
// (range: [0.0,90.0], 180.0)
float spotCosCutoff; // Derived: cos(Crli)
// (range: [1.0,0.0],-1.0)
float constantAttenuation; // K0
float linearAttenuation; // K1
float quadraticAttenuation;// K2
};
// Sample 1
#include <glm/vec3.hpp>// glm::vec3
#include <glm/geometric.hpp>// glm::cross, glm::normalize
glm::vec3 computeNormal
(
glm::vec3 const & a,
glm::vec3 const & b,
glm::vec3 const & c
)
{
return glm::normalize(glm::cross(c - a, b - a));
}
typedef unsigned int GLuint;
#define GL_FALSE 0
void glUniformMatrix4fv(GLuint, int, int, float*){}
// Sample 2
#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4, glm::ivec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include <glm/gtc/type_ptr.hpp> // glm::value_ptr
void func(GLuint LocationMVP, float Translate, glm::vec2 const & Rotate)
{
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.f);
glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate));
glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f));
glm::mat4 View = glm::rotate(ViewRotateX, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(LocationMVP, 1, GL_FALSE, glm::value_ptr(MVP));
}
// Sample 3
#include <glm/vec2.hpp>// glm::vec2
#include <glm/packing.hpp>// glm::packUnorm2x16
#include <glm/integer.hpp>// glm::uint
#include <glm/gtc/type_precision.hpp>// glm::i8vec2, glm::i32vec2
std::size_t const VertexCount = 4;
// Float quad geometry
std::size_t const PositionSizeF32 = VertexCount * sizeof(glm::vec2);
glm::vec2 const PositionDataF32[VertexCount] =
{
glm::vec2(-1.0f,-1.0f),
glm::vec2( 1.0f,-1.0f),
glm::vec2( 1.0f, 1.0f),
glm::vec2(-1.0f, 1.0f)
};
// Half-float quad geometry
std::size_t const PositionSizeF16 = VertexCount * sizeof(glm::uint);
glm::uint const PositionDataF16[VertexCount] =
{
glm::uint(glm::packUnorm2x16(glm::vec2(-1.0f, -1.0f))),
glm::uint(glm::packUnorm2x16(glm::vec2( 1.0f, -1.0f))),
glm::uint(glm::packUnorm2x16(glm::vec2( 1.0f, 1.0f))),
glm::uint(glm::packUnorm2x16(glm::vec2(-1.0f, 1.0f)))
};
// 8 bits signed integer quad geometry
std::size_t const PositionSizeI8 = VertexCount * sizeof(glm::i8vec2);
glm::i8vec2 const PositionDataI8[VertexCount] =
{
glm::i8vec2(-1,-1),
glm::i8vec2( 1,-1),
glm::i8vec2( 1, 1),
glm::i8vec2(-1, 1)
};
// 32 bits signed integer quad geometry
std::size_t const PositionSizeI32 = VertexCount * sizeof(glm::i32vec2);
glm::i32vec2 const PositionDataI32[VertexCount] =
{
glm::i32vec2 (-1,-1),
glm::i32vec2 ( 1,-1),
glm::i32vec2 ( 1, 1),
glm::i32vec2 (-1, 1)
};
struct intersection
{
glm::vec4 position;
glm::vec3 normal;
};
*/
/*
// Sample 4
#include <glm/vec3.hpp>// glm::vec3
#include <glm/geometric.hpp>// glm::normalize, glm::dot, glm::reflect
#include <glm/exponential.hpp>// glm::pow
#include <glm/gtc/random.hpp>// glm::vecRand3
glm::vec3 lighting
(
intersection const & Intersection,
material const & Material,
light const & Light,
glm::vec3 const & View
)
{
glm::vec3 Color(0.0f);
glm::vec3 LightVertor(glm::normalize(
Light.position - Intersection.position +
glm::vecRand3(0.0f, Light.inaccuracy));
if(!shadow(Intersection.position, Light.position, LightVertor))
{
float Diffuse = glm::dot(Intersection.normal, LightVector);
if(Diffuse <= 0.0f)
return Color;
if(Material.isDiffuse())
Color += Light.color() * Material.diffuse * Diffuse;
if(Material.isSpecular())
{
glm::vec3 Reflect(glm::reflect(
glm::normalize(-LightVector),
glm::normalize(Intersection.normal)));
float Dot = glm::dot(Reflect, View);
float Base = Dot > 0.0f ? Dot : 0.0f;
float Specular = glm::pow(Base, Material.exponent);
Color += Material.specular * Specular;
}
}
return Color;
}
*/
/*
template <typename T, glm::precision P, template<typename, glm::precision> class vecType>
T normalizeDotA(vecType<T, P> const & x, vecType<T, P> const & y)
{
return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y));
}
#define GLM_TEMPLATE_GENTYPE typename T, glm::precision P, template<typename, glm::precision> class
template <GLM_TEMPLATE_GENTYPE vecType>
T normalizeDotB(vecType<T, P> const & x, vecType<T, P> const & y)
{
return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y));
}
template <typename vecType>
typename vecType::value_type normalizeDotC(vecType const & a, vecType const & b)
{
return glm::dot(a, b) * glm::inversesqrt(glm::dot(a, a) * glm::dot(b, b));
}
*/
int main()
{
/*
glm::vec1 o(1);
glm::vec2 a(1);
glm::vec3 b(1);
glm::vec4 c(1);
glm::quat q;
glm::dualquat p;
glm::mat4 m(1);
float a0 = normalizeDotA(a, a);
float b0 = normalizeDotB(b, b);
float c0 = normalizeDotC(c, c);
*/
return 0;
}
+427
View File
@@ -0,0 +1,427 @@
/// @ref core
/// @file glm/detail/func_common.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
///
/// @defgroup core_func_common Common functions
/// @ingroup core
///
/// These all operate component-wise. The description is per component.
#pragma once
#include "setup.hpp"
#include "precision.hpp"
#include "type_int.hpp"
#include "_fixes.hpp"
namespace glm
{
/// @addtogroup core_func_common
/// @{
/// Returns x if x >= 0; otherwise, it returns -x.
///
/// @tparam genType floating-point or signed integer; scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType abs(genType x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> abs(vecType<T, P> const & x);
/// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0.
///
/// @tparam genType Floating-point or signed integer; scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sign.xml">GLSL sign man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> sign(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer that is less then or equal to x.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floor.xml">GLSL floor man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> floor(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer to x
/// whose absolute value is not larger than the absolute value of x.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/trunc.xml">GLSL trunc man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> trunc(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer to x.
/// The fraction 0.5 will round in a direction chosen by the
/// implementation, presumably the direction that is fastest.
/// This includes the possibility that round(x) returns the
/// same value as roundEven(x) for all values of x.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> round(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer to x.
/// A fractional part of 0.5 will round toward the nearest even
/// integer. (Both 3.5 and 4.5 for x will return 4.0.)
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/roundEven.xml">GLSL roundEven man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
/// @see <a href="http://developer.amd.com/documentation/articles/pages/New-Round-to-Even-Technique.aspx">New round to even technique</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> roundEven(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer
/// that is greater than or equal to x.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ceil.xml">GLSL ceil man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> ceil(vecType<T, P> const & x);
/// Return x - floor(x).
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fract.xml">GLSL fract man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType fract(genType x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> fract(vecType<T, P> const & x);
/// Modulus. Returns x - y * floor(x / y)
/// for each component in x using the floating point value y.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType mod(genType x, genType y);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, T y);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the fractional part of x and sets i to the integer
/// part (as a whole number floating point value). Both the
/// return value and the output parameter will have the same
/// sign as x.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/modf.xml">GLSL modf man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType modf(genType x, genType & i);
/// Returns y if y < x; otherwise, it returns x.
///
/// @tparam genType Floating-point or integer; scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType min(genType x, genType y);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> min(vecType<T, P> const & x, T y);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> min(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns y if x < y; otherwise, it returns x.
///
/// @tparam genType Floating-point or integer; scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType max(genType x, genType y);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> max(vecType<T, P> const & x, T y);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> max(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns min(max(x, minVal), maxVal) for each component in x
/// using the floating-point values minVal and maxVal.
///
/// @tparam genType Floating-point or integer; scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType clamp(genType x, genType minVal, genType maxVal);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> clamp(vecType<T, P> const & x, T minVal, T maxVal);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> clamp(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal);
/// If genTypeU is a floating scalar or vector:
/// Returns x * (1.0 - a) + y * a, i.e., the linear blend of
/// x and y using the floating-point value a.
/// The value for a is not restricted to the range [0, 1].
///
/// If genTypeU is a boolean scalar or vector:
/// Selects which vector each returned component comes
/// from. For a component of <a> that is false, the
/// corresponding component of x is returned. For a
/// component of a that is true, the corresponding
/// component of y is returned. Components of x and y that
/// are not selected are allowed to be invalid floating point
/// values and will have no effect on the results. Thus, this
/// provides different functionality than
/// genType mix(genType x, genType y, genType(a))
/// where a is a Boolean vector.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mix.xml">GLSL mix man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
///
/// @param[in] x Value to interpolate.
/// @param[in] y Value to interpolate.
/// @param[in] a Interpolant.
///
/// @tparam genTypeT Floating point scalar or vector.
/// @tparam genTypeU Floating point or boolean scalar or vector. It can't be a vector if it is the length of genTypeT.
///
/// @code
/// #include <glm/glm.hpp>
/// ...
/// float a;
/// bool b;
/// glm::dvec3 e;
/// glm::dvec3 f;
/// glm::vec4 g;
/// glm::vec4 h;
/// ...
/// glm::vec4 r = glm::mix(g, h, a); // Interpolate with a floating-point scalar two vectors.
/// glm::vec4 s = glm::mix(g, h, b); // Teturns g or h;
/// glm::dvec3 t = glm::mix(e, f, a); // Types of the third parameter is not required to match with the first and the second.
/// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter.
/// @endcode
template <typename T, typename U, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a);
template <typename T, typename U, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, U a);
template <typename genTypeT, typename genTypeU>
GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a);
/// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType step(genType edge, genType x);
/// Returns 0.0 if x < edge, otherwise it returns 1.0.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, typename T, precision P>
GLM_FUNC_DECL vecType<T, P> step(T edge, vecType<T, P> const & x);
/// Returns 0.0 if x < edge, otherwise it returns 1.0.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, typename T, precision P>
GLM_FUNC_DECL vecType<T, P> step(vecType<T, P> const & edge, vecType<T, P> const & x);
/// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and
/// performs smooth Hermite interpolation between 0 and 1
/// when edge0 < x < edge1. This is useful in cases where
/// you would want a threshold function with a smooth
/// transition. This is equivalent to:
/// genType t;
/// t = clamp ((x - edge0) / (edge1 - edge0), 0, 1);
/// return t * t * (3 - 2 * t);
/// Results are undefined if edge0 >= edge1.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/smoothstep.xml">GLSL smoothstep man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType smoothstep(genType edge0, genType edge1, genType x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> smoothstep(T edge0, T edge1, vecType<T, P> const & x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> smoothstep(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x);
/// Returns true if x holds a NaN (not a number)
/// representation in the underlying implementation's set of
/// floating point representations. Returns false otherwise,
/// including for implementations with no NaN
/// representations.
///
/// /!\ When using compiler fast math, this function may fail.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> isnan(vecType<T, P> const & x);
/// Returns true if x holds a positive infinity or negative
/// infinity representation in the underlying implementation's
/// set of floating point representations. Returns false
/// otherwise, including for implementations with no infinity
/// representations.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isinf.xml">GLSL isinf man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> isinf(vecType<T, P> const & x);
/// Returns a signed integer value representing
/// the encoding of a floating-point value. The floating-point
/// value's bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToInt.xml">GLSL floatBitsToInt man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
GLM_FUNC_DECL int floatBitsToInt(float const & v);
/// Returns a signed integer value representing
/// the encoding of a floating-point value. The floatingpoint
/// value's bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToInt.xml">GLSL floatBitsToInt man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_DECL vecType<int, P> floatBitsToInt(vecType<float, P> const & v);
/// Returns a unsigned integer value representing
/// the encoding of a floating-point value. The floatingpoint
/// value's bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToUint.xml">GLSL floatBitsToUint man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
GLM_FUNC_DECL uint floatBitsToUint(float const & v);
/// Returns a unsigned integer value representing
/// the encoding of a floating-point value. The floatingpoint
/// value's bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToUint.xml">GLSL floatBitsToUint man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_DECL vecType<uint, P> floatBitsToUint(vecType<float, P> const & v);
/// Returns a floating-point value corresponding to a signed
/// integer encoding of a floating-point value.
/// If an inf or NaN is passed in, it will not signal, and the
/// resulting floating point value is unspecified. Otherwise,
/// the bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/intBitsToFloat.xml">GLSL intBitsToFloat man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
GLM_FUNC_DECL float intBitsToFloat(int const & v);
/// Returns a floating-point value corresponding to a signed
/// integer encoding of a floating-point value.
/// If an inf or NaN is passed in, it will not signal, and the
/// resulting floating point value is unspecified. Otherwise,
/// the bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/intBitsToFloat.xml">GLSL intBitsToFloat man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_DECL vecType<float, P> intBitsToFloat(vecType<int, P> const & v);
/// Returns a floating-point value corresponding to a
/// unsigned integer encoding of a floating-point value.
/// If an inf or NaN is passed in, it will not signal, and the
/// resulting floating point value is unspecified. Otherwise,
/// the bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uintBitsToFloat.xml">GLSL uintBitsToFloat man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
GLM_FUNC_DECL float uintBitsToFloat(uint const & v);
/// Returns a floating-point value corresponding to a
/// unsigned integer encoding of a floating-point value.
/// If an inf or NaN is passed in, it will not signal, and the
/// resulting floating point value is unspecified. Otherwise,
/// the bit-level representation is preserved.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uintBitsToFloat.xml">GLSL uintBitsToFloat man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_DECL vecType<float, P> uintBitsToFloat(vecType<uint, P> const & v);
/// Computes and returns a * b + c.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fma.xml">GLSL fma man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType fma(genType const & a, genType const & b, genType const & c);
/// Splits x into a floating-point significand in the range
/// [0.5, 1.0) and an integral exponent of two, such that:
/// x = significand * exp(2, exponent)
///
/// The significand is returned by the function and the
/// exponent is returned in the parameter exp. For a
/// floating-point value of zero, the significant and exponent
/// are both zero. For a floating-point value that is an
/// infinity or is not a number, the results are undefined.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/frexp.xml">GLSL frexp man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType, typename genIType>
GLM_FUNC_DECL genType frexp(genType const & x, genIType & exp);
/// Builds a floating-point number from x and the
/// corresponding integral exponent of two in exp, returning:
/// significand * exp(2, exponent)
///
/// If this product is too large to be represented in the
/// floating-point type, the result is undefined.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ldexp.xml">GLSL ldexp man page</a>;
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType, typename genIType>
GLM_FUNC_DECL genType ldexp(genType const & x, genIType const & exp);
/// @}
}//namespace glm
#include "func_common.inl"
+849
View File
@@ -0,0 +1,849 @@
/// @ref core
/// @file glm/detail/func_common.inl
#include "func_vector_relational.hpp"
#include "type_vec2.hpp"
#include "type_vec3.hpp"
#include "type_vec4.hpp"
#include "_vectorize.hpp"
#include <limits>
namespace glm
{
// min
template <typename genType>
GLM_FUNC_QUALIFIER genType min(genType x, genType y)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'min' only accept floating-point or integer inputs");
return x < y ? x : y;
}
// max
template <typename genType>
GLM_FUNC_QUALIFIER genType max(genType x, genType y)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'max' only accept floating-point or integer inputs");
return x > y ? x : y;
}
// abs
template <>
GLM_FUNC_QUALIFIER int32 abs(int32 x)
{
int32 const y = x >> 31;
return (x ^ y) - y;
}
// round
# if GLM_HAS_CXX11_STL
using ::std::round;
# else
template <typename genType>
GLM_FUNC_QUALIFIER genType round(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'round' only accept floating-point inputs");
return x < static_cast<genType>(0) ? static_cast<genType>(int(x - static_cast<genType>(0.5))) : static_cast<genType>(int(x + static_cast<genType>(0.5)));
}
# endif
// trunc
# if GLM_HAS_CXX11_STL
using ::std::trunc;
# else
template <typename genType>
GLM_FUNC_QUALIFIER genType trunc(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'trunc' only accept floating-point inputs");
return x < static_cast<genType>(0) ? -std::floor(-x) : std::floor(x);
}
# endif
}//namespace glm
namespace glm{
namespace detail
{
template <typename genFIType, bool /*signed*/>
struct compute_abs
{};
template <typename genFIType>
struct compute_abs<genFIType, true>
{
GLM_FUNC_QUALIFIER static genFIType call(genFIType x)
{
GLM_STATIC_ASSERT(
std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::is_signed || GLM_UNRESTRICTED_GENTYPE,
"'abs' only accept floating-point and integer scalar or vector inputs");
return x >= genFIType(0) ? x : -x;
// TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff;
}
};
#if GLM_COMPILER & GLM_COMPILER_CUDA
template <>
struct compute_abs<float, true>
{
GLM_FUNC_QUALIFIER static float call(float x)
{
return fabsf(x);
}
};
#endif
template <typename genFIType>
struct compute_abs<genFIType, false>
{
GLM_FUNC_QUALIFIER static genFIType call(genFIType x)
{
GLM_STATIC_ASSERT(
(!std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer) || GLM_UNRESTRICTED_GENTYPE,
"'abs' only accept floating-point and integer scalar or vector inputs");
return x;
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_abs_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(abs, x);
}
};
template <typename T, typename U, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_mix_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a)
{
GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x));
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_mix_vector<T, bool, P, vecType, Aligned>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<bool, P> const & a)
{
vecType<T, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = a[i] ? y[i] : x[i];
return Result;
}
};
template <typename T, typename U, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_mix_scalar
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, U const & a)
{
GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x));
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_mix_scalar<T, bool, P, vecType, Aligned>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, bool const & a)
{
return a ? y : x;
}
};
template <typename T, typename U>
struct compute_mix
{
GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, U const & a)
{
GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
return static_cast<T>(static_cast<U>(x) + a * static_cast<U>(y - x));
}
};
template <typename T>
struct compute_mix<T, bool>
{
GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, bool const & a)
{
return a ? y : x;
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool isFloat, bool Aligned>
struct compute_sign
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return vecType<T, P>(glm::lessThan(vecType<T, P>(0), x)) - vecType<T, P>(glm::lessThan(x, vecType<T, P>(0)));
}
};
# if GLM_ARCH == GLM_ARCH_X86
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_sign<T, P, vecType, false, Aligned>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
T const Shift(static_cast<T>(sizeof(T) * 8 - 1));
vecType<T, P> const y(vecType<typename make_unsigned<T>::type, P>(-x) >> typename make_unsigned<T>::type(Shift));
return (x >> Shift) | y;
}
};
# endif
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_floor
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(std::floor, x);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_ceil
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(std::ceil, x);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_fract
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return x - floor(x);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_trunc
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(trunc, x);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_round
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(round, x);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_mod
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & a, vecType<T, P> const & b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'mod' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs.");
return a - b * floor(a / b);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_min_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y)
{
return detail::functor2<T, P, vecType>::call(min, x, y);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_max_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y)
{
return detail::functor2<T, P, vecType>::call(max, x, y);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_clamp_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal)
{
return min(max(x, minVal), maxVal);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_step_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & edge, vecType<T, P> const & x)
{
return mix(vecType<T, P>(1), vecType<T, P>(0), glm::lessThan(x, edge));
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_smoothstep_vector
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'step' only accept floating-point inputs");
vecType<T, P> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1)));
return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp);
}
};
}//namespace detail
template <typename genFIType>
GLM_FUNC_QUALIFIER genFIType abs(genFIType x)
{
return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> abs(vecType<T, P> const & x)
{
return detail::compute_abs_vector<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
// sign
// fast and works for any type
template <typename genFIType>
GLM_FUNC_QUALIFIER genFIType sign(genFIType x)
{
GLM_STATIC_ASSERT(
std::numeric_limits<genFIType>::is_iec559 || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer),
"'sign' only accept signed inputs");
return detail::compute_sign<genFIType, defaultp, tvec1, std::numeric_limits<genFIType>::is_iec559, highp>::call(tvec1<genFIType>(x)).x;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> sign(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(
std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer),
"'sign' only accept signed inputs");
return detail::compute_sign<T, P, vecType, std::numeric_limits<T>::is_iec559, detail::is_aligned<P>::value>::call(x);
}
// floor
using ::std::floor;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> floor(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'floor' only accept floating-point inputs.");
return detail::compute_floor<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> trunc(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'trunc' only accept floating-point inputs");
return detail::compute_trunc<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> round(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'round' only accept floating-point inputs");
return detail::compute_round<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
/*
// roundEven
template <typename genType>
GLM_FUNC_QUALIFIER genType roundEven(genType const& x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs");
return genType(int(x + genType(int(x) % 2)));
}
*/
// roundEven
template <typename genType>
GLM_FUNC_QUALIFIER genType roundEven(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs");
int Integer = static_cast<int>(x);
genType IntegerPart = static_cast<genType>(Integer);
genType FractionalPart = fract(x);
if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5))
{
return round(x);
}
else if((Integer % 2) == 0)
{
return IntegerPart;
}
else if(x <= static_cast<genType>(0)) // Work around...
{
return IntegerPart - static_cast<genType>(1);
}
else
{
return IntegerPart + static_cast<genType>(1);
}
//else // Bug on MinGW 4.5.2
//{
// return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0));
//}
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> roundEven(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'roundEven' only accept floating-point inputs");
return detail::functor1<T, T, P, vecType>::call(roundEven, x);
}
// ceil
using ::std::ceil;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> ceil(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ceil' only accept floating-point inputs");
return detail::compute_ceil<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
// fract
template <typename genType>
GLM_FUNC_QUALIFIER genType fract(genType x)
{
return fract(tvec1<genType>(x)).x;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> fract(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fract' only accept floating-point inputs");
return detail::compute_fract<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
// mod
template <typename genType>
GLM_FUNC_QUALIFIER genType mod(genType x, genType y)
{
# if GLM_COMPILER & GLM_COMPILER_CUDA
// Another Cuda compiler bug https://github.com/g-truc/glm/issues/530
tvec1<genType, defaultp> Result(mod(tvec1<genType, defaultp>(x), y));
return Result.x;
# else
return mod(tvec1<genType, defaultp>(x), y).x;
# endif
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> mod(vecType<T, P> const & x, T y)
{
return detail::compute_mod<T, P, vecType, detail::is_aligned<P>::value>::call(x, vecType<T, P>(y));
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y)
{
return detail::compute_mod<T, P, vecType, detail::is_aligned<P>::value>::call(x, y);
}
// modf
template <typename genType>
GLM_FUNC_QUALIFIER genType modf(genType x, genType & i)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'modf' only accept floating-point inputs");
return std::modf(x, &i);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec1<T, P> modf(tvec1<T, P> const & x, tvec1<T, P> & i)
{
return tvec1<T, P>(
modf(x.x, i.x));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec2<T, P> modf(tvec2<T, P> const & x, tvec2<T, P> & i)
{
return tvec2<T, P>(
modf(x.x, i.x),
modf(x.y, i.y));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> modf(tvec3<T, P> const & x, tvec3<T, P> & i)
{
return tvec3<T, P>(
modf(x.x, i.x),
modf(x.y, i.y),
modf(x.z, i.z));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec4<T, P> modf(tvec4<T, P> const & x, tvec4<T, P> & i)
{
return tvec4<T, P>(
modf(x.x, i.x),
modf(x.y, i.y),
modf(x.z, i.z),
modf(x.w, i.w));
}
//// Only valid if (INT_MIN <= x-y <= INT_MAX)
//// min(x,y)
//r = y + ((x - y) & ((x - y) >> (sizeof(int) *
//CHAR_BIT - 1)));
//// max(x,y)
//r = x - ((x - y) & ((x - y) >> (sizeof(int) *
//CHAR_BIT - 1)));
// min
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> min(vecType<T, P> const & a, T b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'min' only accept floating-point inputs for the interpolator a");
return detail::compute_min_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, vecType<T, P>(b));
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> min(vecType<T, P> const & a, vecType<T, P> const & b)
{
return detail::compute_min_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, b);
}
// max
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> max(vecType<T, P> const & a, T b)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'max' only accept floating-point inputs for the interpolator a");
return detail::compute_max_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, vecType<T, P>(b));
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> max(vecType<T, P> const & a, vecType<T, P> const & b)
{
return detail::compute_max_vector<T, P, vecType, detail::is_aligned<P>::value>::call(a, b);
}
// clamp
template <typename genType>
GLM_FUNC_QUALIFIER genType clamp(genType x, genType minVal, genType maxVal)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs");
return min(max(x, minVal), maxVal);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const & x, T minVal, T maxVal)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs");
return detail::compute_clamp_vector<T, P, vecType, detail::is_aligned<P>::value>::call(x, vecType<T, P>(minVal), vecType<T, P>(maxVal));
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs");
return detail::compute_clamp_vector<T, P, vecType, detail::is_aligned<P>::value>::call(x, minVal, maxVal);
}
template <typename genTypeT, typename genTypeU>
GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a)
{
return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a);
}
template <typename T, typename U, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, U a)
{
return detail::compute_mix_scalar<T, U, P, vecType, detail::is_aligned<P>::value>::call(x, y, a);
}
template <typename T, typename U, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a)
{
return detail::compute_mix_vector<T, U, P, vecType, detail::is_aligned<P>::value>::call(x, y, a);
}
// step
template <typename genType>
GLM_FUNC_QUALIFIER genType step(genType edge, genType x)
{
return mix(static_cast<genType>(1), static_cast<genType>(0), glm::lessThan(x, edge));
}
template <template <typename, precision> class vecType, typename T, precision P>
GLM_FUNC_QUALIFIER vecType<T, P> step(T edge, vecType<T, P> const & x)
{
return detail::compute_step_vector<T, P, vecType, detail::is_aligned<P>::value>::call(vecType<T, P>(edge), x);
}
template <template <typename, precision> class vecType, typename T, precision P>
GLM_FUNC_QUALIFIER vecType<T, P> step(vecType<T, P> const & edge, vecType<T, P> const & x)
{
return detail::compute_step_vector<T, P, vecType, detail::is_aligned<P>::value>::call(edge, x);
}
// smoothstep
template <typename genType>
GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs");
genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1)));
return tmp * tmp * (genType(3) - genType(2) * tmp);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> smoothstep(T edge0, T edge1, vecType<T, P> const & x)
{
return detail::compute_smoothstep_vector<T, P, vecType, detail::is_aligned<P>::value>::call(vecType<T, P>(edge0), vecType<T, P>(edge1), x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> smoothstep(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x)
{
return detail::compute_smoothstep_vector<T, P, vecType, detail::is_aligned<P>::value>::call(edge0, edge1, x);
}
# if GLM_HAS_CXX11_STL
using std::isnan;
# else
template <typename genType>
GLM_FUNC_QUALIFIER bool isnan(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isnan' only accept floating-point inputs");
# if GLM_HAS_CXX11_STL
return std::isnan(x);
# elif GLM_COMPILER & GLM_COMPILER_VC
return _isnan(x) != 0;
# elif GLM_COMPILER & GLM_COMPILER_INTEL
# if GLM_PLATFORM & GLM_PLATFORM_WINDOWS
return _isnan(x) != 0;
# else
return ::isnan(x) != 0;
# endif
# elif (GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) && (GLM_PLATFORM & GLM_PLATFORM_ANDROID) && __cplusplus < 201103L
return _isnan(x) != 0;
# elif GLM_COMPILER & GLM_COMPILER_CUDA
return isnan(x) != 0;
# else
return std::isnan(x);
# endif
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> isnan(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
return detail::functor1<bool, T, P, vecType>::call(isnan, x);
}
# if GLM_HAS_CXX11_STL
using std::isinf;
# else
template <typename genType>
GLM_FUNC_QUALIFIER bool isinf(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isinf' only accept floating-point inputs");
# if GLM_HAS_CXX11_STL
return std::isinf(x);
# elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC)
# if(GLM_PLATFORM & GLM_PLATFORM_WINDOWS)
return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF;
# else
return ::isinf(x);
# endif
# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)
# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L)
return _isinf(x) != 0;
# else
return std::isinf(x);
# endif
# elif GLM_COMPILER & GLM_COMPILER_CUDA
// http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab
return isinf(double(x)) != 0;
# else
return std::isinf(x);
# endif
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> isinf(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
return detail::functor1<bool, T, P, vecType>::call(isinf, x);
}
GLM_FUNC_QUALIFIER int floatBitsToInt(float const & v)
{
return reinterpret_cast<int&>(const_cast<float&>(v));
}
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_QUALIFIER vecType<int, P> floatBitsToInt(vecType<float, P> const & v)
{
return reinterpret_cast<vecType<int, P>&>(const_cast<vecType<float, P>&>(v));
}
GLM_FUNC_QUALIFIER uint floatBitsToUint(float const & v)
{
return reinterpret_cast<uint&>(const_cast<float&>(v));
}
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_QUALIFIER vecType<uint, P> floatBitsToUint(vecType<float, P> const & v)
{
return reinterpret_cast<vecType<uint, P>&>(const_cast<vecType<float, P>&>(v));
}
GLM_FUNC_QUALIFIER float intBitsToFloat(int const & v)
{
return reinterpret_cast<float&>(const_cast<int&>(v));
}
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_QUALIFIER vecType<float, P> intBitsToFloat(vecType<int, P> const & v)
{
return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<int, P>&>(v));
}
GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const & v)
{
return reinterpret_cast<float&>(const_cast<uint&>(v));
}
template <template <typename, precision> class vecType, precision P>
GLM_FUNC_QUALIFIER vecType<float, P> uintBitsToFloat(vecType<uint, P> const & v)
{
return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<uint, P>&>(v));
}
template <typename genType>
GLM_FUNC_QUALIFIER genType fma(genType const & a, genType const & b, genType const & c)
{
return a * b + c;
}
template <typename genType>
GLM_FUNC_QUALIFIER genType frexp(genType x, int & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs");
return std::frexp(x, &exp);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec1<T, P> frexp(tvec1<T, P> const & x, tvec1<int, P> & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs");
return tvec1<T, P>(std::frexp(x.x, &exp.x));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec2<T, P> frexp(tvec2<T, P> const & x, tvec2<int, P> & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs");
return tvec2<T, P>(
frexp(x.x, exp.x),
frexp(x.y, exp.y));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> frexp(tvec3<T, P> const & x, tvec3<int, P> & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs");
return tvec3<T, P>(
frexp(x.x, exp.x),
frexp(x.y, exp.y),
frexp(x.z, exp.z));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec4<T, P> frexp(tvec4<T, P> const & x, tvec4<int, P> & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'frexp' only accept floating-point inputs");
return tvec4<T, P>(
frexp(x.x, exp.x),
frexp(x.y, exp.y),
frexp(x.z, exp.z),
frexp(x.w, exp.w));
}
template <typename genType>
GLM_FUNC_QUALIFIER genType ldexp(genType const & x, int const & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs");
return std::ldexp(x, exp);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec1<T, P> ldexp(tvec1<T, P> const & x, tvec1<int, P> const & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs");
return tvec1<T, P>(
ldexp(x.x, exp.x));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec2<T, P> ldexp(tvec2<T, P> const & x, tvec2<int, P> const & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs");
return tvec2<T, P>(
ldexp(x.x, exp.x),
ldexp(x.y, exp.y));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> ldexp(tvec3<T, P> const & x, tvec3<int, P> const & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs");
return tvec3<T, P>(
ldexp(x.x, exp.x),
ldexp(x.y, exp.y),
ldexp(x.z, exp.z));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec4<T, P> ldexp(tvec4<T, P> const & x, tvec4<int, P> const & exp)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'ldexp' only accept floating-point inputs");
return tvec4<T, P>(
ldexp(x.x, exp.x),
ldexp(x.y, exp.y),
ldexp(x.z, exp.z),
ldexp(x.w, exp.w));
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_common_simd.inl"
#endif
+231
View File
@@ -0,0 +1,231 @@
/// @ref core
/// @file glm/detail/func_common_simd.inl
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
#include "../simd/common.h"
#include <immintrin.h>
namespace glm{
namespace detail
{
template <precision P>
struct compute_abs_vector<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_abs(v.data);
return result;
}
};
template <precision P>
struct compute_abs_vector<int, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<int, P> call(tvec4<int, P> const & v)
{
tvec4<int, P> result(uninitialize);
result.data = glm_ivec4_abs(v.data);
return result;
}
};
template <precision P>
struct compute_floor<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_floor(v.data);
return result;
}
};
template <precision P>
struct compute_ceil<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_ceil(v.data);
return result;
}
};
template <precision P>
struct compute_fract<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_fract(v.data);
return result;
}
};
template <precision P>
struct compute_round<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_round(v.data);
return result;
}
};
template <precision P>
struct compute_mod<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & x, tvec4<float, P> const & y)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_mod(x.data, y.data);
return result;
}
};
template <precision P>
struct compute_min_vector<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v1, tvec4<float, P> const & v2)
{
tvec4<float, P> result(uninitialize);
result.data = _mm_min_ps(v1.data, v2.data);
return result;
}
};
template <precision P>
struct compute_min_vector<int32, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<int32, P> call(tvec4<int32, P> const & v1, tvec4<int32, P> const & v2)
{
tvec4<int32, P> result(uninitialize);
result.data = _mm_min_epi32(v1.data, v2.data);
return result;
}
};
template <precision P>
struct compute_min_vector<uint32, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<int32, P> call(tvec4<uint32, P> const & v1, tvec4<uint32, P> const & v2)
{
tvec4<uint32, P> result(uninitialize);
result.data = _mm_min_epu32(v1.data, v2.data);
return result;
}
};
template <precision P>
struct compute_max_vector<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v1, tvec4<float, P> const & v2)
{
tvec4<float, P> result(uninitialize);
result.data = _mm_max_ps(v1.data, v2.data);
return result;
}
};
template <precision P>
struct compute_max_vector<int32, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<int32, P> call(tvec4<int32, P> const & v1, tvec4<int32, P> const & v2)
{
tvec4<int32, P> result(uninitialize);
result.data = _mm_max_epi32(v1.data, v2.data);
return result;
}
};
template <precision P>
struct compute_max_vector<uint32, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<uint32, P> call(tvec4<uint32, P> const & v1, tvec4<uint32, P> const & v2)
{
tvec4<uint32, P> result(uninitialize);
result.data = _mm_max_epu32(v1.data, v2.data);
return result;
}
};
template <precision P>
struct compute_clamp_vector<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & x, tvec4<float, P> const & minVal, tvec4<float, P> const & maxVal)
{
tvec4<float, P> result(uninitialize);
result.data = _mm_min_ps(_mm_max_ps(x.data, minVal.data), maxVal.data);
return result;
}
};
template <precision P>
struct compute_clamp_vector<int32, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<int32, P> call(tvec4<int32, P> const & x, tvec4<int32, P> const & minVal, tvec4<int32, P> const & maxVal)
{
tvec4<int32, P> result(uninitialize);
result.data = _mm_min_epi32(_mm_max_epi32(x.data, minVal.data), maxVal.data);
return result;
}
};
template <precision P>
struct compute_clamp_vector<uint32, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<uint32, P> call(tvec4<uint32, P> const & x, tvec4<uint32, P> const & minVal, tvec4<uint32, P> const & maxVal)
{
tvec4<uint32, P> result(uninitialize);
result.data = _mm_min_epu32(_mm_max_epu32(x.data, minVal.data), maxVal.data);
return result;
}
};
template <precision P>
struct compute_mix_vector<float, bool, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & x, tvec4<float, P> const & y, tvec4<bool, P> const & a)
{
__m128i const Load = _mm_set_epi32(-(int)a.w, -(int)a.z, -(int)a.y, -(int)a.x);
__m128 const Mask = _mm_castsi128_ps(Load);
tvec4<float, P> Result(uninitialize);
# if 0 && GLM_ARCH & GLM_ARCH_AVX
Result.data = _mm_blendv_ps(x.data, y.data, Mask);
# else
Result.data = _mm_or_ps(_mm_and_ps(Mask, y.data), _mm_andnot_ps(Mask, x.data));
# endif
return Result;
}
};
/* FIXME
template <precision P>
struct compute_step_vector<float, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const& edge, tvec4<float, P> const& x)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_step(edge.data, x.data);
return result;
}
};
*/
template <precision P>
struct compute_smoothstep_vector<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const& edge0, tvec4<float, P> const& edge1, tvec4<float, P> const& x)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_smoothstep(edge0.data, edge1.data, x.data);
return result;
}
};
}//namespace detail
}//namespace glm
#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT
+103
View File
@@ -0,0 +1,103 @@
/// @ref core
/// @file glm/detail/func_exponential.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
///
/// @defgroup core_func_exponential Exponential functions
/// @ingroup core
///
/// These all operate component-wise. The description is per component.
#pragma once
#include "type_vec1.hpp"
#include "type_vec2.hpp"
#include "type_vec3.hpp"
#include "type_vec4.hpp"
#include <cmath>
namespace glm
{
/// @addtogroup core_func_exponential
/// @{
/// Returns 'base' raised to the power 'exponent'.
///
/// @param base Floating point value. pow function is defined for input values of 'base' defined in the range (inf-, inf+) in the limit of the type precision.
/// @param exponent Floating point value representing the 'exponent'.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/pow.xml">GLSL pow man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> pow(vecType<T, P> const & base, vecType<T, P> const & exponent);
/// Returns the natural exponentiation of x, i.e., e^x.
///
/// @param v exp function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp.xml">GLSL exp man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> exp(vecType<T, P> const & v);
/// Returns the natural logarithm of v, i.e.,
/// returns the value y which satisfies the equation x = e^y.
/// Results are undefined if v <= 0.
///
/// @param v log function is defined for input values of v defined in the range (0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log.xml">GLSL log man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> log(vecType<T, P> const & v);
/// Returns 2 raised to the v power.
///
/// @param v exp2 function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp2.xml">GLSL exp2 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> exp2(vecType<T, P> const & v);
/// Returns the base 2 log of x, i.e., returns the value y,
/// which satisfies the equation x = 2 ^ y.
///
/// @param v log2 function is defined for input values of v defined in the range (0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log2.xml">GLSL log2 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> log2(vecType<T, P> const & v);
/// Returns the positive square root of v.
///
/// @param v sqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sqrt.xml">GLSL sqrt man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
//template <typename genType>
//GLM_FUNC_DECL genType sqrt(genType const & x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> sqrt(vecType<T, P> const & v);
/// Returns the reciprocal of the positive square root of v.
///
/// @param v inversesqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inversesqrt.xml">GLSL inversesqrt man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> inversesqrt(vecType<T, P> const & v);
/// @}
}//namespace glm
#include "func_exponential.inl"
+146
View File
@@ -0,0 +1,146 @@
/// @ref core
/// @file glm/detail/func_exponential.inl
#include "func_vector_relational.hpp"
#include "_vectorize.hpp"
#include <limits>
#include <cmath>
#include <cassert>
namespace glm{
namespace detail
{
# if GLM_HAS_CXX11_STL
using std::log2;
# else
template <typename genType>
genType log2(genType Value)
{
return std::log(Value) * static_cast<genType>(1.4426950408889634073599246810019);
}
# endif
template <typename T, precision P, template <class, precision> class vecType, bool isFloat, bool Aligned>
struct compute_log2
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & vec)
{
return detail::functor1<T, T, P, vecType>::call(log2, vec);
}
};
template <template <class, precision> class vecType, typename T, precision P, bool Aligned>
struct compute_sqrt
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(std::sqrt, x);
}
};
template <template <class, precision> class vecType, typename T, precision P, bool Aligned>
struct compute_inversesqrt
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
{
return static_cast<T>(1) / sqrt(x);
}
};
template <template <class, precision> class vecType, bool Aligned>
struct compute_inversesqrt<vecType, float, lowp, Aligned>
{
GLM_FUNC_QUALIFIER static vecType<float, lowp> call(vecType<float, lowp> const & x)
{
vecType<float, lowp> tmp(x);
vecType<float, lowp> xhalf(tmp * 0.5f);
vecType<uint, lowp>* p = reinterpret_cast<vecType<uint, lowp>*>(const_cast<vecType<float, lowp>*>(&x));
vecType<uint, lowp> i = vecType<uint, lowp>(0x5f375a86) - (*p >> vecType<uint, lowp>(1));
vecType<float, lowp>* ptmp = reinterpret_cast<vecType<float, lowp>*>(&i);
tmp = *ptmp;
tmp = tmp * (1.5f - xhalf * tmp * tmp);
return tmp;
}
};
}//namespace detail
// pow
using std::pow;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> pow(vecType<T, P> const & base, vecType<T, P> const & exponent)
{
return detail::functor2<T, P, vecType>::call(pow, base, exponent);
}
// exp
using std::exp;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> exp(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(exp, x);
}
// log
using std::log;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> log(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(log, x);
}
//exp2, ln2 = 0.69314718055994530941723212145818f
template <typename genType>
GLM_FUNC_QUALIFIER genType exp2(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'exp2' only accept floating-point inputs");
return std::exp(static_cast<genType>(0.69314718055994530941723212145818) * x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> exp2(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(exp2, x);
}
// log2, ln2 = 0.69314718055994530941723212145818f
template <typename genType>
GLM_FUNC_QUALIFIER genType log2(genType x)
{
return log2(tvec1<genType>(x)).x;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> log2(vecType<T, P> const & x)
{
return detail::compute_log2<T, P, vecType, std::numeric_limits<T>::is_iec559, detail::is_aligned<P>::value>::call(x);
}
// sqrt
using std::sqrt;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> sqrt(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sqrt' only accept floating-point inputs");
return detail::compute_sqrt<vecType, T, P, detail::is_aligned<P>::value>::call(x);
}
// inversesqrt
template <typename genType>
GLM_FUNC_QUALIFIER genType inversesqrt(genType x)
{
return static_cast<genType>(1) / sqrt(x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> inversesqrt(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inversesqrt' only accept floating-point inputs");
return detail::compute_inversesqrt<vecType, T, P, detail::is_aligned<P>::value>::call(x);
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_exponential_simd.inl"
#endif
@@ -0,0 +1,35 @@
/// @ref core
/// @file glm/detail/func_exponential_simd.inl
#include "../simd/exponential.h"
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
namespace glm{
namespace detail
{
template <precision P>
struct compute_sqrt<tvec4, float, P, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = _mm_sqrt_ps(v.data);
return result;
}
};
template <>
struct compute_sqrt<tvec4, float, aligned_lowp, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, aligned_lowp> call(tvec4<float, aligned_lowp> const & v)
{
tvec4<float, aligned_lowp> result(uninitialize);
result.data = glm_vec4_sqrt_lowp(v.data);
return result;
}
};
}//namespace detail
}//namespace glm
#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT
+113
View File
@@ -0,0 +1,113 @@
/// @ref core
/// @file glm/detail/func_geometric.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
///
/// @defgroup core_func_geometric Geometric functions
/// @ingroup core
///
/// These operate on vectors as vectors, not component-wise.
#pragma once
#include "type_vec3.hpp"
namespace glm
{
/// @addtogroup core_func_geometric
/// @{
/// Returns the length of x, i.e., sqrt(x * x).
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/length.xml">GLSL length man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL T length(
vecType<T, P> const & x);
/// Returns the distance betwwen p0 and p1, i.e., length(p0 - p1).
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/distance.xml">GLSL distance man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL T distance(
vecType<T, P> const & p0,
vecType<T, P> const & p1);
/// Returns the dot product of x and y, i.e., result = x * y.
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/dot.xml">GLSL dot man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL T dot(
vecType<T, P> const & x,
vecType<T, P> const & y);
/// Returns the cross product of x and y.
///
/// @tparam valType Floating-point scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cross.xml">GLSL cross man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P>
GLM_FUNC_DECL tvec3<T, P> cross(
tvec3<T, P> const & x,
tvec3<T, P> const & y);
/// Returns a vector in the same direction as x but with length of 1.
/// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefined and generate an error.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/normalize.xml">GLSL normalize man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> normalize(
vecType<T, P> const & x);
/// If dot(Nref, I) < 0.0, return N, otherwise, return -N.
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/faceforward.xml">GLSL faceforward man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> faceforward(
vecType<T, P> const & N,
vecType<T, P> const & I,
vecType<T, P> const & Nref);
/// For the incident vector I and surface orientation N,
/// returns the reflection direction : result = I - 2.0 * dot(N, I) * N.
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/reflect.xml">GLSL reflect man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename genType>
GLM_FUNC_DECL genType reflect(
genType const & I,
genType const & N);
/// For the incident vector I and surface normal N,
/// and the ratio of indices of refraction eta,
/// return the refraction vector.
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/refract.xml">GLSL refract man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> refract(
vecType<T, P> const & I,
vecType<T, P> const & N,
T eta);
/// @}
}//namespace glm
#include "func_geometric.inl"
+247
View File
@@ -0,0 +1,247 @@
/// @ref core
/// @file glm/detail/func_geometric.inl
#include "func_exponential.hpp"
#include "func_common.hpp"
#include "type_vec2.hpp"
#include "type_vec4.hpp"
#include "type_float.hpp"
namespace glm{
namespace detail
{
template <template <typename, precision> class vecType, typename T, precision P, bool Aligned>
struct compute_length
{
GLM_FUNC_QUALIFIER static T call(vecType<T, P> const & v)
{
return sqrt(dot(v, v));
}
};
template <template <typename, precision> class vecType, typename T, precision P, bool Aligned>
struct compute_distance
{
GLM_FUNC_QUALIFIER static T call(vecType<T, P> const & p0, vecType<T, P> const & p1)
{
return length(p1 - p0);
}
};
template <template <class, precision> class vecType, typename T, precision P, bool Aligned>
struct compute_dot{};
template <typename T, precision P, bool Aligned>
struct compute_dot<tvec1, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tvec1<T, P> const & a, tvec1<T, P> const & b)
{
return a.x * b.x;
}
};
template <typename T, precision P, bool Aligned>
struct compute_dot<tvec2, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tvec2<T, P> const & x, tvec2<T, P> const & y)
{
tvec2<T, P> tmp(x * y);
return tmp.x + tmp.y;
}
};
template <typename T, precision P, bool Aligned>
struct compute_dot<tvec3, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tvec3<T, P> const & x, tvec3<T, P> const & y)
{
tvec3<T, P> tmp(x * y);
return tmp.x + tmp.y + tmp.z;
}
};
template <typename T, precision P, bool Aligned>
struct compute_dot<tvec4, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tvec4<T, P> const & x, tvec4<T, P> const & y)
{
tvec4<T, P> tmp(x * y);
return (tmp.x + tmp.y) + (tmp.z + tmp.w);
}
};
template <typename T, precision P, bool Aligned>
struct compute_cross
{
GLM_FUNC_QUALIFIER static tvec3<T, P> call(tvec3<T, P> const & x, tvec3<T, P> const & y)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' accepts only floating-point inputs");
return tvec3<T, P>(
x.y * y.z - y.y * x.z,
x.z * y.x - y.z * x.x,
x.x * y.y - y.x * x.y);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_normalize
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs");
return v * inversesqrt(dot(v, v));
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_faceforward
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & N, vecType<T, P> const & I, vecType<T, P> const & Nref)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs");
return dot(Nref, I) < static_cast<T>(0) ? N : -N;
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_reflect
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & I, vecType<T, P> const & N)
{
return I - N * dot(N, I) * static_cast<T>(2);
}
};
template <typename T, precision P, template <typename, precision> class vecType, bool Aligned>
struct compute_refract
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & I, vecType<T, P> const & N, T eta)
{
T const dotValue(dot(N, I));
T const k(static_cast<T>(1) - eta * eta * (static_cast<T>(1) - dotValue * dotValue));
return (eta * I - (eta * dotValue + std::sqrt(k)) * N) * static_cast<T>(k >= static_cast<T>(0));
}
};
}//namespace detail
// length
template <typename genType>
GLM_FUNC_QUALIFIER genType length(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' accepts only floating-point inputs");
return abs(x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER T length(vecType<T, P> const & v)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' accepts only floating-point inputs");
return detail::compute_length<vecType, T, P, detail::is_aligned<P>::value>::call(v);
}
// distance
template <typename genType>
GLM_FUNC_QUALIFIER genType distance(genType const & p0, genType const & p1)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' accepts only floating-point inputs");
return length(p1 - p0);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER T distance(vecType<T, P> const & p0, vecType<T, P> const & p1)
{
return detail::compute_distance<vecType, T, P, detail::is_aligned<P>::value>::call(p0, p1);
}
// dot
template <typename T>
GLM_FUNC_QUALIFIER T dot(T x, T y)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs");
return x * y;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER T dot(vecType<T, P> const & x, vecType<T, P> const & y)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs");
return detail::compute_dot<vecType, T, P, detail::is_aligned<P>::value>::call(x, y);
}
// cross
template <typename T, precision P>
GLM_FUNC_QUALIFIER tvec3<T, P> cross(tvec3<T, P> const & x, tvec3<T, P> const & y)
{
return detail::compute_cross<T, P, detail::is_aligned<P>::value>::call(x, y);
}
// normalize
template <typename genType>
GLM_FUNC_QUALIFIER genType normalize(genType const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' accepts only floating-point inputs");
return x < genType(0) ? genType(-1) : genType(1);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> normalize(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs");
return detail::compute_normalize<T, P, vecType, detail::is_aligned<P>::value>::call(x);
}
// faceforward
template <typename genType>
GLM_FUNC_QUALIFIER genType faceforward(genType const & N, genType const & I, genType const & Nref)
{
return dot(Nref, I) < static_cast<genType>(0) ? N : -N;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> faceforward(vecType<T, P> const & N, vecType<T, P> const & I, vecType<T, P> const & Nref)
{
return detail::compute_faceforward<T, P, vecType, detail::is_aligned<P>::value>::call(N, I, Nref);
}
// reflect
template <typename genType>
GLM_FUNC_QUALIFIER genType reflect(genType const & I, genType const & N)
{
return I - N * dot(N, I) * genType(2);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> reflect(vecType<T, P> const & I, vecType<T, P> const & N)
{
return detail::compute_reflect<T, P, vecType, detail::is_aligned<P>::value>::call(I, N);
}
// refract
template <typename genType>
GLM_FUNC_QUALIFIER genType refract(genType const & I, genType const & N, genType eta)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' accepts only floating-point inputs");
genType const dotValue(dot(N, I));
genType const k(static_cast<genType>(1) - eta * eta * (static_cast<genType>(1) - dotValue * dotValue));
return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast<genType>(k >= static_cast<genType>(0));
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> refract(vecType<T, P> const & I, vecType<T, P> const & N, T eta)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' accepts only floating-point inputs");
return detail::compute_refract<T, P, vecType, detail::is_aligned<P>::value>::call(I, N, eta);
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_geometric_simd.inl"
#endif
@@ -0,0 +1,99 @@
/// @ref core
/// @file glm/detail/func_geometric_simd.inl
#include "../simd/geometric.h"
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
namespace glm{
namespace detail
{
template <precision P>
struct compute_length<tvec4, float, P, true>
{
GLM_FUNC_QUALIFIER static float call(tvec4<float, P> const & v)
{
return _mm_cvtss_f32(glm_vec4_length(v.data));
}
};
template <precision P>
struct compute_distance<tvec4, float, P, true>
{
GLM_FUNC_QUALIFIER static float call(tvec4<float, P> const & p0, tvec4<float, P> const & p1)
{
return _mm_cvtss_f32(glm_vec4_distance(p0.data, p1.data));
}
};
template <precision P>
struct compute_dot<tvec4, float, P, true>
{
GLM_FUNC_QUALIFIER static float call(tvec4<float, P> const& x, tvec4<float, P> const& y)
{
return _mm_cvtss_f32(glm_vec1_dot(x.data, y.data));
}
};
template <precision P>
struct compute_cross<float, P, true>
{
GLM_FUNC_QUALIFIER static tvec3<float, P> call(tvec3<float, P> const & a, tvec3<float, P> const & b)
{
__m128 const set0 = _mm_set_ps(0.0f, a.z, a.y, a.x);
__m128 const set1 = _mm_set_ps(0.0f, b.z, b.y, b.x);
__m128 const xpd0 = glm_vec4_cross(set0, set1);
tvec4<float, P> result(uninitialize);
result.data = xpd0;
return tvec3<float, P>(result);
}
};
template <precision P>
struct compute_normalize<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const & v)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_normalize(v.data);
return result;
}
};
template <precision P>
struct compute_faceforward<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const& N, tvec4<float, P> const& I, tvec4<float, P> const& Nref)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_faceforward(N.data, I.data, Nref.data);
return result;
}
};
template <precision P>
struct compute_reflect<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const& I, tvec4<float, P> const& N)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_reflect(I.data, N.data);
return result;
}
};
template <precision P>
struct compute_refract<float, P, tvec4, true>
{
GLM_FUNC_QUALIFIER static tvec4<float, P> call(tvec4<float, P> const& I, tvec4<float, P> const& N, float eta)
{
tvec4<float, P> result(uninitialize);
result.data = glm_vec4_refract(I.data, N.data, _mm_set1_ps(eta));
return result;
}
};
}//namespace detail
}//namespace glm
#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT
+203
View File
@@ -0,0 +1,203 @@
/// @ref core
/// @file glm/detail/func_integer.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
///
/// @defgroup core_func_integer Integer functions
/// @ingroup core
///
/// These all operate component-wise. The description is per component.
/// The notation [a, b] means the set of bits from bit-number a through bit-number
/// b, inclusive. The lowest-order bit is bit 0.
#pragma once
#include "setup.hpp"
#include "precision.hpp"
#include "func_common.hpp"
#include "func_vector_relational.hpp"
namespace glm
{
/// @addtogroup core_func_integer
/// @{
/// Adds 32-bit unsigned integer x and y, returning the sum
/// modulo pow(2, 32). The value carry is set to 0 if the sum was
/// less than pow(2, 32), or to 1 otherwise.
///
/// @tparam genUType Unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uaddCarry.xml">GLSL uaddCarry man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<uint, P> uaddCarry(
vecType<uint, P> const & x,
vecType<uint, P> const & y,
vecType<uint, P> & carry);
/// Subtracts the 32-bit unsigned integer y from x, returning
/// the difference if non-negative, or pow(2, 32) plus the difference
/// otherwise. The value borrow is set to 0 if x >= y, or to 1 otherwise.
///
/// @tparam genUType Unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/usubBorrow.xml">GLSL usubBorrow man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<uint, P> usubBorrow(
vecType<uint, P> const & x,
vecType<uint, P> const & y,
vecType<uint, P> & borrow);
/// Multiplies 32-bit integers x and y, producing a 64-bit
/// result. The 32 least-significant bits are returned in lsb.
/// The 32 most-significant bits are returned in msb.
///
/// @tparam genUType Unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/umulExtended.xml">GLSL umulExtended man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL void umulExtended(
vecType<uint, P> const & x,
vecType<uint, P> const & y,
vecType<uint, P> & msb,
vecType<uint, P> & lsb);
/// Multiplies 32-bit integers x and y, producing a 64-bit
/// result. The 32 least-significant bits are returned in lsb.
/// The 32 most-significant bits are returned in msb.
///
/// @tparam genIType Signed integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/imulExtended.xml">GLSL imulExtended man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL void imulExtended(
vecType<int, P> const & x,
vecType<int, P> const & y,
vecType<int, P> & msb,
vecType<int, P> & lsb);
/// Extracts bits [offset, offset + bits - 1] from value,
/// returning them in the least significant bits of the result.
/// For unsigned data types, the most significant bits of the
/// result will be set to zero. For signed data types, the
/// most significant bits will be set to the value of bit offset + base - 1.
///
/// If bits is zero, the result will be zero. The result will be
/// undefined if offset or bits is negative, or if the sum of
/// offset and bits is greater than the number of bits used
/// to store the operand.
///
/// @tparam T Signed or unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldExtract.xml">GLSL bitfieldExtract man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> bitfieldExtract(
vecType<T, P> const & Value,
int Offset,
int Bits);
/// Returns the insertion the bits least-significant bits of insert into base.
///
/// The result will have bits [offset, offset + bits - 1] taken
/// from bits [0, bits - 1] of insert, and all other bits taken
/// directly from the corresponding bits of base. If bits is
/// zero, the result will simply be base. The result will be
/// undefined if offset or bits is negative, or if the sum of
/// offset and bits is greater than the number of bits used to
/// store the operand.
///
/// @tparam T Signed or unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldInsert.xml">GLSL bitfieldInsert man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> bitfieldInsert(
vecType<T, P> const & Base,
vecType<T, P> const & Insert,
int Offset,
int Bits);
/// Returns the reversal of the bits of value.
/// The bit numbered n of the result will be taken from bit (bits - 1) - n of value,
/// where bits is the total number of bits used to represent value.
///
/// @tparam T Signed or unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldReverse.xml">GLSL bitfieldReverse man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> bitfieldReverse(vecType<T, P> const & v);
/// Returns the number of bits set to 1 in the binary representation of value.
///
/// @tparam T Signed or unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genType>
GLM_FUNC_DECL int bitCount(genType v);
/// Returns the number of bits set to 1 in the binary representation of value.
///
/// @tparam T Signed or unsigned integer scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<int, P> bitCount(vecType<T, P> const & v);
/// Returns the bit number of the least significant bit set to
/// 1 in the binary representation of value.
/// If value is zero, -1 will be returned.
///
/// @tparam T Signed or unsigned integer scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType>
GLM_FUNC_DECL int findLSB(genIUType x);
/// Returns the bit number of the least significant bit set to
/// 1 in the binary representation of value.
/// If value is zero, -1 will be returned.
///
/// @tparam T Signed or unsigned integer scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<int, P> findLSB(vecType<T, P> const & v);
/// Returns the bit number of the most significant bit in the binary representation of value.
/// For positive integers, the result will be the bit number of the most significant bit set to 1.
/// For negative integers, the result will be the bit number of the most significant
/// bit set to 0. For a value of zero or negative one, -1 will be returned.
///
/// @tparam T Signed or unsigned integer scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType>
GLM_FUNC_DECL int findMSB(genIUType x);
/// Returns the bit number of the most significant bit in the binary representation of value.
/// For positive integers, the result will be the bit number of the most significant bit set to 1.
/// For negative integers, the result will be the bit number of the most significant
/// bit set to 0. For a value of zero or negative one, -1 will be returned.
///
/// @tparam T Signed or unsigned integer scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<int, P> findMSB(vecType<T, P> const & v);
/// @}
}//namespace glm
#include "func_integer.inl"
+368
View File
@@ -0,0 +1,368 @@
/// @ref core
/// @file glm/detail/func_integer.inl
#include "type_vec2.hpp"
#include "type_vec3.hpp"
#include "type_vec4.hpp"
#include "type_int.hpp"
#include "_vectorize.hpp"
#if(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC)
# include <intrin.h>
# pragma intrinsic(_BitScanReverse)
#endif//(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC)
#include <limits>
#if !GLM_HAS_EXTENDED_INTEGER_TYPE
# if GLM_COMPILER & GLM_COMPILER_GCC
# pragma GCC diagnostic ignored "-Wlong-long"
# endif
# if (GLM_COMPILER & GLM_COMPILER_CLANG)
# pragma clang diagnostic ignored "-Wc++11-long-long"
# endif
#endif
namespace glm{
namespace detail
{
template <typename T>
GLM_FUNC_QUALIFIER T mask(T Bits)
{
return Bits >= sizeof(T) * 8 ? ~static_cast<T>(0) : (static_cast<T>(1) << Bits) - static_cast<T>(1);
}
template <typename T, glm::precision P, template <typename, glm::precision> class vecType, bool Aligned, bool EXEC>
struct compute_bitfieldReverseStep
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T, T)
{
return v;
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType, bool Aligned>
struct compute_bitfieldReverseStep<T, P, vecType, Aligned, true>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Mask, T Shift)
{
return (v & Mask) << Shift | (v & (~Mask)) >> Shift;
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType, bool Aligned, bool EXEC>
struct compute_bitfieldBitCountStep
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T, T)
{
return v;
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType, bool Aligned>
struct compute_bitfieldBitCountStep<T, P, vecType, Aligned, true>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Mask, T Shift)
{
return (v & Mask) + ((v >> Shift) & Mask);
}
};
template <typename genIUType, size_t Bits>
struct compute_findLSB
{
GLM_FUNC_QUALIFIER static int call(genIUType Value)
{
if(Value == 0)
return -1;
return glm::bitCount(~Value & (Value - static_cast<genIUType>(1)));
}
};
# if GLM_HAS_BITSCAN_WINDOWS
template <typename genIUType>
struct compute_findLSB<genIUType, 32>
{
GLM_FUNC_QUALIFIER static int call(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanForward(&Result, *reinterpret_cast<unsigned long*>(&Value));
return IsNotNull ? int(Result) : -1;
}
};
# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32))
template <typename genIUType>
struct compute_findLSB<genIUType, 64>
{
GLM_FUNC_QUALIFIER static int call(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanForward64(&Result, *reinterpret_cast<unsigned __int64*>(&Value));
return IsNotNull ? int(Result) : -1;
}
};
# endif
# endif//GLM_HAS_BITSCAN_WINDOWS
template <typename T, glm::precision P, template <class, glm::precision> class vecType, bool EXEC = true>
struct compute_findMSB_step_vec
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, T Shift)
{
return x | (x >> Shift);
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType>
struct compute_findMSB_step_vec<T, P, vecType, false>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, T)
{
return x;
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType, int>
struct compute_findMSB_vec
{
GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & vec)
{
vecType<T, P> x(vec);
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 1));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 2));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 4));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 16>::call(x, static_cast<T>( 8));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 32>::call(x, static_cast<T>(16));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 64>::call(x, static_cast<T>(32));
return vecType<int, P>(sizeof(T) * 8 - 1) - glm::bitCount(~x);
}
};
# if GLM_HAS_BITSCAN_WINDOWS
template <typename genIUType>
GLM_FUNC_QUALIFIER int compute_findMSB_32(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanReverse(&Result, *reinterpret_cast<unsigned long*>(&Value));
return IsNotNull ? int(Result) : -1;
}
template <typename T, glm::precision P, template<typename, glm::precision> class vecType>
struct compute_findMSB_vec<T, P, vecType, 32>
{
GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & x)
{
return detail::functor1<int, T, P, vecType>::call(compute_findMSB_32, x);
}
};
# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32))
template <typename genIUType>
GLM_FUNC_QUALIFIER int compute_findMSB_64(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanReverse64(&Result, *reinterpret_cast<unsigned __int64*>(&Value));
return IsNotNull ? int(Result) : -1;
}
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
struct compute_findMSB_vec<T, P, vecType, 64>
{
GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & x)
{
return detail::functor1<int, T, P, vecType>::call(compute_findMSB_64, x);
}
};
# endif
# endif//GLM_HAS_BITSCAN_WINDOWS
}//namespace detail
// uaddCarry
GLM_FUNC_QUALIFIER uint uaddCarry(uint const & x, uint const & y, uint & Carry)
{
uint64 const Value64(static_cast<uint64>(x) + static_cast<uint64>(y));
uint64 const Max32((static_cast<uint64>(1) << static_cast<uint64>(32)) - static_cast<uint64>(1));
Carry = Value64 > Max32 ? 1u : 0u;
return static_cast<uint32>(Value64 % (Max32 + static_cast<uint64>(1)));
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<uint, P> uaddCarry(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & Carry)
{
vecType<uint64, P> Value64(vecType<uint64, P>(x) + vecType<uint64, P>(y));
vecType<uint64, P> Max32((static_cast<uint64>(1) << static_cast<uint64>(32)) - static_cast<uint64>(1));
Carry = mix(vecType<uint32, P>(0), vecType<uint32, P>(1), greaterThan(Value64, Max32));
return vecType<uint32,P>(Value64 % (Max32 + static_cast<uint64>(1)));
}
// usubBorrow
GLM_FUNC_QUALIFIER uint usubBorrow(uint const & x, uint const & y, uint & Borrow)
{
GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
Borrow = x >= y ? static_cast<uint32>(0) : static_cast<uint32>(1);
if(y >= x)
return y - x;
else
return static_cast<uint32>((static_cast<int64>(1) << static_cast<int64>(32)) + (static_cast<int64>(y) - static_cast<int64>(x)));
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<uint, P> usubBorrow(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & Borrow)
{
Borrow = mix(vecType<uint, P>(1), vecType<uint, P>(0), greaterThanEqual(x, y));
vecType<uint, P> const YgeX(y - x);
vecType<uint, P> const XgeY(vecType<uint32, P>((static_cast<int64>(1) << static_cast<int64>(32)) + (vecType<int64, P>(y) - vecType<int64, P>(x))));
return mix(XgeY, YgeX, greaterThanEqual(y, x));
}
// umulExtended
GLM_FUNC_QUALIFIER void umulExtended(uint const & x, uint const & y, uint & msb, uint & lsb)
{
GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
uint64 Value64 = static_cast<uint64>(x) * static_cast<uint64>(y);
msb = static_cast<uint>(Value64 >> static_cast<uint64>(32));
lsb = static_cast<uint>(Value64);
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER void umulExtended(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & msb, vecType<uint, P> & lsb)
{
GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
vecType<uint64, P> Value64(vecType<uint64, P>(x) * vecType<uint64, P>(y));
msb = vecType<uint32, P>(Value64 >> static_cast<uint64>(32));
lsb = vecType<uint32, P>(Value64);
}
// imulExtended
GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int & msb, int & lsb)
{
GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
int64 Value64 = static_cast<int64>(x) * static_cast<int64>(y);
msb = static_cast<int>(Value64 >> static_cast<int64>(32));
lsb = static_cast<int>(Value64);
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER void imulExtended(vecType<int, P> const & x, vecType<int, P> const & y, vecType<int, P> & msb, vecType<int, P> & lsb)
{
GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
vecType<int64, P> Value64(vecType<int64, P>(x) * vecType<int64, P>(y));
lsb = vecType<int32, P>(Value64 & static_cast<int64>(0xFFFFFFFF));
msb = vecType<int32, P>((Value64 >> static_cast<int64>(32)) & static_cast<int64>(0xFFFFFFFF));
}
// bitfieldExtract
template <typename genIUType>
GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits)
{
return bitfieldExtract(tvec1<genIUType>(Value), Offset, Bits).x;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> bitfieldExtract(vecType<T, P> const & Value, int Offset, int Bits)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldExtract' only accept integer inputs");
return (Value >> static_cast<T>(Offset)) & static_cast<T>(detail::mask(Bits));
}
// bitfieldInsert
template <typename genIUType>
GLM_FUNC_QUALIFIER genIUType bitfieldInsert(genIUType const & Base, genIUType const & Insert, int Offset, int Bits)
{
return bitfieldInsert(tvec1<genIUType>(Base), tvec1<genIUType>(Insert), Offset, Bits).x;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> bitfieldInsert(vecType<T, P> const & Base, vecType<T, P> const & Insert, int Offset, int Bits)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldInsert' only accept integer values");
T const Mask = static_cast<T>(detail::mask(Bits) << Offset);
return (Base & ~Mask) | (Insert & Mask);
}
// bitfieldReverse
template <typename genType>
GLM_FUNC_QUALIFIER genType bitfieldReverse(genType x)
{
return bitfieldReverse(glm::tvec1<genType, glm::defaultp>(x)).x;
}
template <typename T, glm::precision P, template <typename, glm::precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> bitfieldReverse(vecType<T, P> const & v)
{
vecType<T, P> x(v);
x = detail::compute_bitfieldReverseStep<T, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 2>::call(x, T(0x5555555555555555ull), static_cast<T>( 1));
x = detail::compute_bitfieldReverseStep<T, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 4>::call(x, T(0x3333333333333333ull), static_cast<T>( 2));
x = detail::compute_bitfieldReverseStep<T, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 8>::call(x, T(0x0F0F0F0F0F0F0F0Full), static_cast<T>( 4));
x = detail::compute_bitfieldReverseStep<T, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 16>::call(x, T(0x00FF00FF00FF00FFull), static_cast<T>( 8));
x = detail::compute_bitfieldReverseStep<T, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 32>::call(x, T(0x0000FFFF0000FFFFull), static_cast<T>(16));
x = detail::compute_bitfieldReverseStep<T, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 64>::call(x, T(0x00000000FFFFFFFFull), static_cast<T>(32));
return x;
}
// bitCount
template <typename genType>
GLM_FUNC_QUALIFIER int bitCount(genType x)
{
return bitCount(glm::tvec1<genType, glm::defaultp>(x)).x;
}
template <typename T, glm::precision P, template <typename, glm::precision> class vecType>
GLM_FUNC_QUALIFIER vecType<int, P> bitCount(vecType<T, P> const & v)
{
vecType<typename detail::make_unsigned<T>::type, P> x(*reinterpret_cast<vecType<typename detail::make_unsigned<T>::type, P> const *>(&v));
x = detail::compute_bitfieldBitCountStep<typename detail::make_unsigned<T>::type, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 2>::call(x, typename detail::make_unsigned<T>::type(0x5555555555555555ull), typename detail::make_unsigned<T>::type( 1));
x = detail::compute_bitfieldBitCountStep<typename detail::make_unsigned<T>::type, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 4>::call(x, typename detail::make_unsigned<T>::type(0x3333333333333333ull), typename detail::make_unsigned<T>::type( 2));
x = detail::compute_bitfieldBitCountStep<typename detail::make_unsigned<T>::type, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 8>::call(x, typename detail::make_unsigned<T>::type(0x0F0F0F0F0F0F0F0Full), typename detail::make_unsigned<T>::type( 4));
x = detail::compute_bitfieldBitCountStep<typename detail::make_unsigned<T>::type, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 16>::call(x, typename detail::make_unsigned<T>::type(0x00FF00FF00FF00FFull), typename detail::make_unsigned<T>::type( 8));
x = detail::compute_bitfieldBitCountStep<typename detail::make_unsigned<T>::type, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 32>::call(x, typename detail::make_unsigned<T>::type(0x0000FFFF0000FFFFull), typename detail::make_unsigned<T>::type(16));
x = detail::compute_bitfieldBitCountStep<typename detail::make_unsigned<T>::type, P, vecType, detail::is_aligned<P>::value, sizeof(T) * 8>= 64>::call(x, typename detail::make_unsigned<T>::type(0x00000000FFFFFFFFull), typename detail::make_unsigned<T>::type(32));
return vecType<int, P>(x);
}
// findLSB
template <typename genIUType>
GLM_FUNC_QUALIFIER int findLSB(genIUType Value)
{
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findLSB' only accept integer values");
return detail::compute_findLSB<genIUType, sizeof(genIUType) * 8>::call(Value);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<int, P> findLSB(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findLSB' only accept integer values");
return detail::functor1<int, T, P, vecType>::call(findLSB, x);
}
// findMSB
template <typename genIUType>
GLM_FUNC_QUALIFIER int findMSB(genIUType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
return findMSB(tvec1<genIUType>(x)).x;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<int, P> findMSB(vecType<T, P> const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findMSB' only accept integer values");
return detail::compute_findMSB_vec<T, P, vecType, sizeof(T) * 8>::call(x);
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_integer_simd.inl"
#endif
@@ -0,0 +1,68 @@
/// @ref core
/// @file glm/detail/func_integer_simd.inl
#include "../simd/integer.h"
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
namespace glm{
namespace detail
{
template <glm::precision P>
struct compute_bitfieldReverseStep<uint32, P, tvec4, true, true>
{
GLM_FUNC_QUALIFIER static tvec4<uint32, P> call(tvec4<uint32, P> const & v, uint32 Mask, uint32 Shift)
{
__m128i const set0 = v.data;
__m128i const set1 = _mm_set1_epi32(Mask);
__m128i const and1 = _mm_and_si128(set0, set1);
__m128i const sft1 = _mm_slli_epi32(and1, Shift);
__m128i const set2 = _mm_andnot_si128(set0, _mm_set1_epi32(-1));
__m128i const and2 = _mm_and_si128(set0, set2);
__m128i const sft2 = _mm_srai_epi32(and2, Shift);
__m128i const or0 = _mm_or_si128(sft1, sft2);
return or0;
}
};
template <glm::precision P>
struct compute_bitfieldBitCountStep<uint32, P, tvec4, true, true>
{
GLM_FUNC_QUALIFIER static tvec4<uint32, P> call(tvec4<uint32, P> const & v, uint32 Mask, uint32 Shift)
{
__m128i const set0 = v.data;
__m128i const set1 = _mm_set1_epi32(Mask);
__m128i const and0 = _mm_and_si128(set0, set1);
__m128i const sft0 = _mm_slli_epi32(set0, Shift);
__m128i const and1 = _mm_and_si128(sft0, set1);
__m128i const add0 = _mm_add_epi32(and0, and1);
return add0;
}
};
}//namespace detail
# if GLM_ARCH & GLM_ARCH_AVX_BIT
template <>
GLM_FUNC_QUALIFIER int bitCount(uint32 x)
{
return _mm_popcnt_u32(x);
}
# if(GLM_MODEL == GLM_MODEL_64)
template <>
GLM_FUNC_QUALIFIER int bitCount(uint64 x)
{
return static_cast<int>(_mm_popcnt_u64(x));
}
# endif//GLM_MODEL
# endif//GLM_ARCH
}//namespace glm
#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT
+149
View File
@@ -0,0 +1,149 @@
/// @ref core
/// @file glm/detail/func_matrix.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
///
/// @defgroup core_func_matrix Matrix functions
/// @ingroup core
///
/// For each of the following built-in matrix functions, there is both a
/// single-precision floating point version, where all arguments and return values
/// are single precision, and a double-precision floating version, where all
/// arguments and return values are double precision. Only the single-precision
/// floating point version is shown.
#pragma once
// Dependencies
#include "../detail/precision.hpp"
#include "../detail/setup.hpp"
#include "../detail/type_mat.hpp"
#include "../vec2.hpp"
#include "../vec3.hpp"
#include "../vec4.hpp"
#include "../mat2x2.hpp"
#include "../mat2x3.hpp"
#include "../mat2x4.hpp"
#include "../mat3x2.hpp"
#include "../mat3x3.hpp"
#include "../mat3x4.hpp"
#include "../mat4x2.hpp"
#include "../mat4x3.hpp"
#include "../mat4x4.hpp"
namespace glm{
namespace detail
{
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec2, tvec2>
{
typedef tmat2x2<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec2, tvec3>
{
typedef tmat3x2<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec2, tvec4>
{
typedef tmat4x2<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec3, tvec2>
{
typedef tmat2x3<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec3, tvec3>
{
typedef tmat3x3<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec3, tvec4>
{
typedef tmat4x3<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec4, tvec2>
{
typedef tmat2x4<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec4, tvec3>
{
typedef tmat3x4<T, P> type;
};
template <typename T, precision P>
struct outerProduct_trait<T, P, tvec4, tvec4>
{
typedef tmat4x4<T, P> type;
};
}//namespace detail
/// @addtogroup core_func_matrix
/// @{
/// Multiply matrix x by matrix y component-wise, i.e.,
/// result[i][j] is the scalar product of x[i][j] and y[i][j].
///
/// @tparam matType Floating-point matrix types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/matrixCompMult.xml">GLSL matrixCompMult man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_DECL matType<T, P> matrixCompMult(matType<T, P> const & x, matType<T, P> const & y);
/// Treats the first parameter c as a column vector
/// and the second parameter r as a row vector
/// and does a linear algebraic matrix multiply c * r.
///
/// @tparam matType Floating-point matrix types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/outerProduct.xml">GLSL outerProduct man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
template <typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB>
GLM_FUNC_DECL typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r);
/// Returns the transposed matrix of x
///
/// @tparam matType Floating-point matrix types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/transpose.xml">GLSL transpose man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
# if((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC11))
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_DECL typename matType<T, P>::transpose_type transpose(matType<T, P> const & x);
# endif
/// Return the determinant of a squared matrix.
///
/// @tparam valType Floating-point scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/determinant.xml">GLSL determinant man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_DECL T determinant(matType<T, P> const & m);
/// Return the inverse of a squared matrix.
///
/// @tparam valType Floating-point scalar types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inverse.xml">GLSL inverse man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_DECL matType<T, P> inverse(matType<T, P> const & m);
/// @}
}//namespace glm
#include "func_matrix.inl"
+401
View File
@@ -0,0 +1,401 @@
/// @ref core
/// @file glm/detail/func_matrix.inl
#include "../geometric.hpp"
#include <limits>
namespace glm{
namespace detail
{
template <template <typename, precision> class matType, typename T, precision P, bool Aligned>
struct compute_matrixCompMult
{
GLM_FUNC_QUALIFIER static matType<T, P> call(matType<T, P> const& x, matType<T, P> const& y)
{
matType<T, P> result(uninitialize);
for(length_t i = 0; i < result.length(); ++i)
result[i] = x[i] * y[i];
return result;
}
};
template <template <class, precision> class matType, typename T, precision P, bool Aligned>
struct compute_transpose{};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat2x2, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat2x2<T, P> call(tmat2x2<T, P> const & m)
{
tmat2x2<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat2x3, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat3x2<T, P> call(tmat2x3<T, P> const & m)
{
tmat3x2<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[2][0] = m[0][2];
result[2][1] = m[1][2];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat2x4, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat4x2<T, P> call(tmat2x4<T, P> const & m)
{
tmat4x2<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[2][0] = m[0][2];
result[2][1] = m[1][2];
result[3][0] = m[0][3];
result[3][1] = m[1][3];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat3x2, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat2x3<T, P> call(tmat3x2<T, P> const & m)
{
tmat2x3<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[0][2] = m[2][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[1][2] = m[2][1];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat3x3, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat3x3<T, P> call(tmat3x3<T, P> const & m)
{
tmat3x3<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[0][2] = m[2][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[1][2] = m[2][1];
result[2][0] = m[0][2];
result[2][1] = m[1][2];
result[2][2] = m[2][2];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat3x4, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat4x3<T, P> call(tmat3x4<T, P> const & m)
{
tmat4x3<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[0][2] = m[2][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[1][2] = m[2][1];
result[2][0] = m[0][2];
result[2][1] = m[1][2];
result[2][2] = m[2][2];
result[3][0] = m[0][3];
result[3][1] = m[1][3];
result[3][2] = m[2][3];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat4x2, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat2x4<T, P> call(tmat4x2<T, P> const & m)
{
tmat2x4<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[0][2] = m[2][0];
result[0][3] = m[3][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[1][2] = m[2][1];
result[1][3] = m[3][1];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat4x3, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat3x4<T, P> call(tmat4x3<T, P> const & m)
{
tmat3x4<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[0][2] = m[2][0];
result[0][3] = m[3][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[1][2] = m[2][1];
result[1][3] = m[3][1];
result[2][0] = m[0][2];
result[2][1] = m[1][2];
result[2][2] = m[2][2];
result[2][3] = m[3][2];
return result;
}
};
template <typename T, precision P, bool Aligned>
struct compute_transpose<tmat4x4, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat4x4<T, P> call(tmat4x4<T, P> const & m)
{
tmat4x4<T, P> result(uninitialize);
result[0][0] = m[0][0];
result[0][1] = m[1][0];
result[0][2] = m[2][0];
result[0][3] = m[3][0];
result[1][0] = m[0][1];
result[1][1] = m[1][1];
result[1][2] = m[2][1];
result[1][3] = m[3][1];
result[2][0] = m[0][2];
result[2][1] = m[1][2];
result[2][2] = m[2][2];
result[2][3] = m[3][2];
result[3][0] = m[0][3];
result[3][1] = m[1][3];
result[3][2] = m[2][3];
result[3][3] = m[3][3];
return result;
}
};
template <template <typename, precision> class matType, typename T, precision P, bool Aligned>
struct compute_determinant{};
template <typename T, precision P, bool Aligned>
struct compute_determinant<tmat2x2, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tmat2x2<T, P> const & m)
{
return m[0][0] * m[1][1] - m[1][0] * m[0][1];
}
};
template <typename T, precision P, bool Aligned>
struct compute_determinant<tmat3x3, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tmat3x3<T, P> const & m)
{
return
+ m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
- m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
+ m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
}
};
template <typename T, precision P, bool Aligned>
struct compute_determinant<tmat4x4, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static T call(tmat4x4<T, P> const & m)
{
T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
tvec4<T, P> DetCof(
+ (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
- (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
+ (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
- (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05));
return
m[0][0] * DetCof[0] + m[0][1] * DetCof[1] +
m[0][2] * DetCof[2] + m[0][3] * DetCof[3];
}
};
template <template <typename, precision> class matType, typename T, precision P, bool Aligned>
struct compute_inverse{};
template <typename T, precision P, bool Aligned>
struct compute_inverse<tmat2x2, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat2x2<T, P> call(tmat2x2<T, P> const& m)
{
T OneOverDeterminant = static_cast<T>(1) / (
+ m[0][0] * m[1][1]
- m[1][0] * m[0][1]);
tmat2x2<T, P> Inverse(
+ m[1][1] * OneOverDeterminant,
- m[0][1] * OneOverDeterminant,
- m[1][0] * OneOverDeterminant,
+ m[0][0] * OneOverDeterminant);
return Inverse;
}
};
template <typename T, precision P, bool Aligned>
struct compute_inverse<tmat3x3, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat3x3<T, P> call(tmat3x3<T, P> const& m)
{
T OneOverDeterminant = static_cast<T>(1) / (
+ m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
- m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
+ m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]));
tmat3x3<T, P> Inverse(uninitialize);
Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant;
Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant;
Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant;
Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant;
Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant;
Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant;
Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant;
Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant;
Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant;
return Inverse;
}
};
template <typename T, precision P, bool Aligned>
struct compute_inverse<tmat4x4, T, P, Aligned>
{
GLM_FUNC_QUALIFIER static tmat4x4<T, P> call(tmat4x4<T, P> const& m)
{
T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
tvec4<T, P> Fac0(Coef00, Coef00, Coef02, Coef03);
tvec4<T, P> Fac1(Coef04, Coef04, Coef06, Coef07);
tvec4<T, P> Fac2(Coef08, Coef08, Coef10, Coef11);
tvec4<T, P> Fac3(Coef12, Coef12, Coef14, Coef15);
tvec4<T, P> Fac4(Coef16, Coef16, Coef18, Coef19);
tvec4<T, P> Fac5(Coef20, Coef20, Coef22, Coef23);
tvec4<T, P> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
tvec4<T, P> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
tvec4<T, P> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
tvec4<T, P> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
tvec4<T, P> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
tvec4<T, P> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
tvec4<T, P> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
tvec4<T, P> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
tvec4<T, P> SignA(+1, -1, +1, -1);
tvec4<T, P> SignB(-1, +1, -1, +1);
tmat4x4<T, P> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB);
tvec4<T, P> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
tvec4<T, P> Dot0(m[0] * Row0);
T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w);
T OneOverDeterminant = static_cast<T>(1) / Dot1;
return Inverse * OneOverDeterminant;
}
};
}//namespace detail
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_QUALIFIER matType<T, P> matrixCompMult(matType<T, P> const & x, matType<T, P> const & y)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'matrixCompMult' only accept floating-point inputs");
return detail::compute_matrixCompMult<matType, T, P, detail::is_aligned<P>::value>::call(x, y);
}
template<typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB>
GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'outerProduct' only accept floating-point inputs");
typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type m(uninitialize);
for(length_t i = 0; i < m.length(); ++i)
m[i] = c * r[i];
return m;
}
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_QUALIFIER typename matType<T, P>::transpose_type transpose(matType<T, P> const & m)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'transpose' only accept floating-point inputs");
return detail::compute_transpose<matType, T, P, detail::is_aligned<P>::value>::call(m);
}
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_QUALIFIER T determinant(matType<T, P> const & m)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'determinant' only accept floating-point inputs");
return detail::compute_determinant<matType, T, P, detail::is_aligned<P>::value>::call(m);
}
template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_QUALIFIER matType<T, P> inverse(matType<T, P> const & m)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'inverse' only accept floating-point inputs");
return detail::compute_inverse<matType, T, P, detail::is_aligned<P>::value>::call(m);
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_matrix_simd.inl"
#endif
@@ -0,0 +1,88 @@
/// @ref core
/// @file glm/detail/func_matrix_simd.inl
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
#include "type_mat4x4.hpp"
#include "func_geometric.hpp"
#include "../simd/matrix.h"
namespace glm{
namespace detail
{
template <precision P>
struct compute_matrixCompMult<tmat4x4, float, P, true>
{
GLM_STATIC_ASSERT(detail::is_aligned<P>::value, "Specialization requires aligned");
GLM_FUNC_QUALIFIER static tmat4x4<float, P> call(tmat4x4<float, P> const & x, tmat4x4<float, P> const & y)
{
tmat4x4<float, P> result(uninitialize);
glm_mat4_matrixCompMult(
*(glm_vec4 const (*)[4])&x[0].data,
*(glm_vec4 const (*)[4])&y[0].data,
*(glm_vec4(*)[4])&result[0].data);
return result;
}
};
template <precision P>
struct compute_transpose<tmat4x4, float, P, true>
{
GLM_FUNC_QUALIFIER static tmat4x4<float, P> call(tmat4x4<float, P> const & m)
{
tmat4x4<float, P> result(uninitialize);
glm_mat4_transpose(
*(glm_vec4 const (*)[4])&m[0].data,
*(glm_vec4(*)[4])&result[0].data);
return result;
}
};
template <precision P>
struct compute_determinant<tmat4x4, float, P, true>
{
GLM_FUNC_QUALIFIER static float call(tmat4x4<float, P> const& m)
{
return _mm_cvtss_f32(glm_mat4_determinant(*reinterpret_cast<__m128 const(*)[4]>(&m[0].data)));
}
};
template <precision P>
struct compute_inverse<tmat4x4, float, P, true>
{
GLM_FUNC_QUALIFIER static tmat4x4<float, P> call(tmat4x4<float, P> const& m)
{
tmat4x4<float, P> Result(uninitialize);
glm_mat4_inverse(*reinterpret_cast<__m128 const(*)[4]>(&m[0].data), *reinterpret_cast<__m128(*)[4]>(&Result[0].data));
return Result;
}
};
}//namespace detail
template<>
GLM_FUNC_QUALIFIER tmat4x4<float, aligned_lowp> outerProduct<float, aligned_lowp, tvec4, tvec4>(tvec4<float, aligned_lowp> const & c, tvec4<float, aligned_lowp> const & r)
{
tmat4x4<float, aligned_lowp> m(uninitialize);
glm_mat4_outerProduct(c.data, r.data, *reinterpret_cast<__m128(*)[4]>(&m[0].data));
return m;
}
template<>
GLM_FUNC_QUALIFIER tmat4x4<float, aligned_mediump> outerProduct<float, aligned_mediump, tvec4, tvec4>(tvec4<float, aligned_mediump> const & c, tvec4<float, aligned_mediump> const & r)
{
tmat4x4<float, aligned_mediump> m(uninitialize);
glm_mat4_outerProduct(c.data, r.data, *reinterpret_cast<__m128(*)[4]>(&m[0].data));
return m;
}
template<>
GLM_FUNC_QUALIFIER tmat4x4<float, aligned_highp> outerProduct<float, aligned_highp, tvec4, tvec4>(tvec4<float, aligned_highp> const & c, tvec4<float, aligned_highp> const & r)
{
tmat4x4<float, aligned_highp> m(uninitialize);
glm_mat4_outerProduct(c.data, r.data, *reinterpret_cast<__m128(*)[4]>(&m[0].data));
return m;
}
}//namespace glm
#endif
+168
View File
@@ -0,0 +1,168 @@
/// @ref core
/// @file glm/detail/func_packing.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
/// @see gtc_packing
///
/// @defgroup core_func_packing Floating-Point Pack and Unpack Functions
/// @ingroup core
///
/// These functions do not operate component-wise, rather as described in each case.
#pragma once
#include "type_vec2.hpp"
#include "type_vec4.hpp"
namespace glm
{
/// @addtogroup core_func_packing
/// @{
/// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values.
/// Then, the results are packed into the returned 32-bit unsigned integer.
///
/// The conversion for component c of v to fixed point is done as follows:
/// packUnorm2x16: round(clamp(c, 0, +1) * 65535.0)
///
/// The first component of the vector will be written to the least significant bits of the output;
/// the last component will be written to the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm2x16.xml">GLSL packUnorm2x16 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL uint packUnorm2x16(vec2 const & v);
/// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values.
/// Then, the results are packed into the returned 32-bit unsigned integer.
///
/// The conversion for component c of v to fixed point is done as follows:
/// packSnorm2x16: round(clamp(v, -1, +1) * 32767.0)
///
/// The first component of the vector will be written to the least significant bits of the output;
/// the last component will be written to the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm2x16.xml">GLSL packSnorm2x16 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL uint packSnorm2x16(vec2 const & v);
/// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values.
/// Then, the results are packed into the returned 32-bit unsigned integer.
///
/// The conversion for component c of v to fixed point is done as follows:
/// packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
///
/// The first component of the vector will be written to the least significant bits of the output;
/// the last component will be written to the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL uint packUnorm4x8(vec4 const & v);
/// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values.
/// Then, the results are packed into the returned 32-bit unsigned integer.
///
/// The conversion for component c of v to fixed point is done as follows:
/// packSnorm4x8: round(clamp(c, -1, +1) * 127.0)
///
/// The first component of the vector will be written to the least significant bits of the output;
/// the last component will be written to the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL uint packSnorm4x8(vec4 const & v);
/// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers.
/// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector.
///
/// The conversion for unpacked fixed-point value f to floating point is done as follows:
/// unpackUnorm2x16: f / 65535.0
///
/// The first component of the returned vector will be extracted from the least significant bits of the input;
/// the last component will be extracted from the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL vec2 unpackUnorm2x16(uint p);
/// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers.
/// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector.
///
/// The conversion for unpacked fixed-point value f to floating point is done as follows:
/// unpackSnorm2x16: clamp(f / 32767.0, -1, +1)
///
/// The first component of the returned vector will be extracted from the least significant bits of the input;
/// the last component will be extracted from the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm2x16.xml">GLSL unpackSnorm2x16 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL vec2 unpackSnorm2x16(uint p);
/// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers.
/// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector.
///
/// The conversion for unpacked fixed-point value f to floating point is done as follows:
/// unpackUnorm4x8: f / 255.0
///
/// The first component of the returned vector will be extracted from the least significant bits of the input;
/// the last component will be extracted from the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL vec4 unpackUnorm4x8(uint p);
/// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers.
/// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector.
///
/// The conversion for unpacked fixed-point value f to floating point is done as follows:
/// unpackSnorm4x8: clamp(f / 127.0, -1, +1)
///
/// The first component of the returned vector will be extracted from the least significant bits of the input;
/// the last component will be extracted from the most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL vec4 unpackSnorm4x8(uint p);
/// Returns a double-precision value obtained by packing the components of v into a 64-bit value.
/// If an IEEE 754 Inf or NaN is created, it will not signal, and the resulting floating point value is unspecified.
/// Otherwise, the bit- level representation of v is preserved.
/// The first vector component specifies the 32 least significant bits;
/// the second component specifies the 32 most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packDouble2x32.xml">GLSL packDouble2x32 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL double packDouble2x32(uvec2 const & v);
/// Returns a two-component unsigned integer vector representation of v.
/// The bit-level representation of v is preserved.
/// The first component of the vector contains the 32 least significant bits of the double;
/// the second component consists the 32 most significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackDouble2x32.xml">GLSL unpackDouble2x32 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL uvec2 unpackDouble2x32(double v);
/// Returns an unsigned integer obtained by converting the components of a two-component floating-point vector
/// to the 16-bit floating-point representation found in the OpenGL Specification,
/// and then packing these two 16- bit integers into a 32-bit unsigned integer.
/// The first vector component specifies the 16 least-significant bits of the result;
/// the second component specifies the 16 most-significant bits.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL uint packHalf2x16(vec2 const & v);
/// Returns a two-component floating-point vector with components obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
/// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification,
/// and converting them to 32-bit floating-point values.
/// The first component of the vector is obtained from the 16 least-significant bits of v;
/// the second component is obtained from the 16 most-significant bits of v.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
GLM_FUNC_DECL vec2 unpackHalf2x16(uint v);
/// @}
}//namespace glm
#include "func_packing.inl"
+190
View File
@@ -0,0 +1,190 @@
/// @ref core
/// @file glm/detail/func_packing.inl
#include "func_common.hpp"
#include "type_half.hpp"
#include "../fwd.hpp"
namespace glm
{
GLM_FUNC_QUALIFIER uint packUnorm2x16(vec2 const & v)
{
union
{
u16 in[2];
uint out;
} u;
u16vec2 result(round(clamp(v, 0.0f, 1.0f) * 65535.0f));
u.in[0] = result[0];
u.in[1] = result[1];
return u.out;
}
GLM_FUNC_QUALIFIER vec2 unpackUnorm2x16(uint p)
{
union
{
uint in;
u16 out[2];
} u;
u.in = p;
return vec2(u.out[0], u.out[1]) * 1.5259021896696421759365224689097e-5f;
}
GLM_FUNC_QUALIFIER uint packSnorm2x16(vec2 const & v)
{
union
{
i16 in[2];
uint out;
} u;
i16vec2 result(round(clamp(v, -1.0f, 1.0f) * 32767.0f));
u.in[0] = result[0];
u.in[1] = result[1];
return u.out;
}
GLM_FUNC_QUALIFIER vec2 unpackSnorm2x16(uint p)
{
union
{
uint in;
i16 out[2];
} u;
u.in = p;
return clamp(vec2(u.out[0], u.out[1]) * 3.0518509475997192297128208258309e-5f, -1.0f, 1.0f);
}
GLM_FUNC_QUALIFIER uint packUnorm4x8(vec4 const & v)
{
union
{
u8 in[4];
uint out;
} u;
u8vec4 result(round(clamp(v, 0.0f, 1.0f) * 255.0f));
u.in[0] = result[0];
u.in[1] = result[1];
u.in[2] = result[2];
u.in[3] = result[3];
return u.out;
}
GLM_FUNC_QUALIFIER vec4 unpackUnorm4x8(uint p)
{
union
{
uint in;
u8 out[4];
} u;
u.in = p;
return vec4(u.out[0], u.out[1], u.out[2], u.out[3]) * 0.0039215686274509803921568627451f;
}
GLM_FUNC_QUALIFIER uint packSnorm4x8(vec4 const & v)
{
union
{
i8 in[4];
uint out;
} u;
i8vec4 result(round(clamp(v, -1.0f, 1.0f) * 127.0f));
u.in[0] = result[0];
u.in[1] = result[1];
u.in[2] = result[2];
u.in[3] = result[3];
return u.out;
}
GLM_FUNC_QUALIFIER glm::vec4 unpackSnorm4x8(uint p)
{
union
{
uint in;
i8 out[4];
} u;
u.in = p;
return clamp(vec4(u.out[0], u.out[1], u.out[2], u.out[3]) * 0.0078740157480315f, -1.0f, 1.0f);
}
GLM_FUNC_QUALIFIER double packDouble2x32(uvec2 const & v)
{
union
{
uint in[2];
double out;
} u;
u.in[0] = v[0];
u.in[1] = v[1];
return u.out;
}
GLM_FUNC_QUALIFIER uvec2 unpackDouble2x32(double v)
{
union
{
double in;
uint out[2];
} u;
u.in = v;
return uvec2(u.out[0], u.out[1]);
}
GLM_FUNC_QUALIFIER uint packHalf2x16(vec2 const & v)
{
union
{
i16 in[2];
uint out;
} u;
u.in[0] = detail::toFloat16(v.x);
u.in[1] = detail::toFloat16(v.y);
return u.out;
}
GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint v)
{
union
{
uint in;
i16 out[2];
} u;
u.in = v;
return vec2(
detail::toFloat32(u.out[0]),
detail::toFloat32(u.out[1]));
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_packing_simd.inl"
#endif
@@ -0,0 +1,9 @@
/// @ref core
/// @file glm/detail/func_packing_simd.inl
namespace glm{
namespace detail
{
}//namespace detail
}//namespace glm
@@ -0,0 +1,176 @@
/// @ref core
/// @file glm/detail/func_trigonometric.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
///
/// @defgroup core_func_trigonometric Angle and Trigonometry Functions
/// @ingroup core
///
/// Function parameters specified as angle are assumed to be in units of radians.
/// In no case will any of these functions result in a divide by zero error. If
/// the divisor of a ratio is 0, then results will be undefined.
///
/// These all operate component-wise. The description is per component.
#pragma once
#include "setup.hpp"
#include "precision.hpp"
namespace glm
{
/// @addtogroup core_func_trigonometric
/// @{
/// Converts degrees to radians and returns the result.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/radians.xml">GLSL radians man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL GLM_CONSTEXPR vecType<T, P> radians(vecType<T, P> const & degrees);
/// Converts radians to degrees and returns the result.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/degrees.xml">GLSL degrees man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL GLM_CONSTEXPR vecType<T, P> degrees(vecType<T, P> const & radians);
/// The standard trigonometric sine function.
/// The values returned by this function will range from [-1, 1].
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sin.xml">GLSL sin man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> sin(vecType<T, P> const & angle);
/// The standard trigonometric cosine function.
/// The values returned by this function will range from [-1, 1].
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cos.xml">GLSL cos man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> cos(vecType<T, P> const & angle);
/// The standard trigonometric tangent function.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tan.xml">GLSL tan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> tan(vecType<T, P> const & angle);
/// Arc sine. Returns an angle whose sine is x.
/// The range of values returned by this function is [-PI/2, PI/2].
/// Results are undefined if |x| > 1.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asin.xml">GLSL asin man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> asin(vecType<T, P> const & x);
/// Arc cosine. Returns an angle whose sine is x.
/// The range of values returned by this function is [0, PI].
/// Results are undefined if |x| > 1.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acos.xml">GLSL acos man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> acos(vecType<T, P> const & x);
/// Arc tangent. Returns an angle whose tangent is y/x.
/// The signs of x and y are used to determine what
/// quadrant the angle is in. The range of values returned
/// by this function is [-PI, PI]. Results are undefined
/// if x and y are both 0.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> atan(vecType<T, P> const & y, vecType<T, P> const & x);
/// Arc tangent. Returns an angle whose tangent is y_over_x.
/// The range of values returned by this function is [-PI/2, PI/2].
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> atan(vecType<T, P> const & y_over_x);
/// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sinh.xml">GLSL sinh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> sinh(vecType<T, P> const & angle);
/// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cosh.xml">GLSL cosh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> cosh(vecType<T, P> const & angle);
/// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle)
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tanh.xml">GLSL tanh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> tanh(vecType<T, P> const & angle);
/// Arc hyperbolic sine; returns the inverse of sinh.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asinh.xml">GLSL asinh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> asinh(vecType<T, P> const & x);
/// Arc hyperbolic cosine; returns the non-negative inverse
/// of cosh. Results are undefined if x < 1.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acosh.xml">GLSL acosh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> acosh(vecType<T, P> const & x);
/// Arc hyperbolic tangent; returns the inverse of tanh.
/// Results are undefined if abs(x) >= 1.
///
/// @tparam genType Floating-point scalar or vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atanh.xml">GLSL atanh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> atanh(vecType<T, P> const & x);
/// @}
}//namespace glm
#include "func_trigonometric.inl"
@@ -0,0 +1,200 @@
/// @ref core
/// @file glm/detail/func_trigonometric.inl
#include "_vectorize.hpp"
#include <cmath>
#include <limits>
namespace glm
{
// radians
template <typename genType>
GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType radians(genType degrees)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'radians' only accept floating-point input");
return degrees * static_cast<genType>(0.01745329251994329576923690768489);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER GLM_CONSTEXPR vecType<T, P> radians(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(radians, v);
}
// degrees
template <typename genType>
GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType degrees(genType radians)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'degrees' only accept floating-point input");
return radians * static_cast<genType>(57.295779513082320876798154814105);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER GLM_CONSTEXPR vecType<T, P> degrees(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(degrees, v);
}
// sin
using ::std::sin;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> sin(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(sin, v);
}
// cos
using std::cos;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> cos(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(cos, v);
}
// tan
using std::tan;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> tan(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(tan, v);
}
// asin
using std::asin;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> asin(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(asin, v);
}
// acos
using std::acos;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> acos(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(acos, v);
}
// atan
template <typename genType>
GLM_FUNC_QUALIFIER genType atan(genType y, genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atan' only accept floating-point input");
return ::std::atan2(y, x);
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> atan(vecType<T, P> const & a, vecType<T, P> const & b)
{
return detail::functor2<T, P, vecType>::call(::std::atan2, a, b);
}
using std::atan;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> atan(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(atan, v);
}
// sinh
using std::sinh;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> sinh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(sinh, v);
}
// cosh
using std::cosh;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> cosh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(cosh, v);
}
// tanh
using std::tanh;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> tanh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(tanh, v);
}
// asinh
# if GLM_HAS_CXX11_STL
using std::asinh;
# else
template <typename genType>
GLM_FUNC_QUALIFIER genType asinh(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asinh' only accept floating-point input");
return (x < static_cast<genType>(0) ? static_cast<genType>(-1) : (x > static_cast<genType>(0) ? static_cast<genType>(1) : static_cast<genType>(0))) * log(std::abs(x) + sqrt(static_cast<genType>(1) + x * x));
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> asinh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(asinh, v);
}
// acosh
# if GLM_HAS_CXX11_STL
using std::acosh;
# else
template <typename genType>
GLM_FUNC_QUALIFIER genType acosh(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acosh' only accept floating-point input");
if(x < static_cast<genType>(1))
return static_cast<genType>(0);
return log(x + sqrt(x * x - static_cast<genType>(1)));
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> acosh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(acosh, v);
}
// atanh
# if GLM_HAS_CXX11_STL
using std::atanh;
# else
template <typename genType>
GLM_FUNC_QUALIFIER genType atanh(genType x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atanh' only accept floating-point input");
if(std::abs(x) >= static_cast<genType>(1))
return 0;
return static_cast<genType>(0.5) * log((static_cast<genType>(1) + x) / (static_cast<genType>(1) - x));
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> atanh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(atanh, v);
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_trigonometric_simd.inl"
#endif
@@ -0,0 +1,111 @@
/// @ref core
/// @file glm/detail/func_vector_relational.hpp
///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
///
/// @defgroup core_func_vector_relational Vector Relational Functions
/// @ingroup core
///
/// Relational and equality operators (<, <=, >, >=, ==, !=) are defined to
/// operate on scalars and produce scalar Boolean results. For vector results,
/// use the following built-in functions.
///
/// In all cases, the sizes of all the input and return vectors for any particular
/// call must match.
#pragma once
#include "precision.hpp"
#include "setup.hpp"
namespace glm
{
/// @addtogroup core_func_vector_relational
/// @{
/// Returns the component-wise comparison result of x < y.
///
/// @tparam vecType Floating-point or integer vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThan.xml">GLSL lessThan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> lessThan(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x <= y.
///
/// @tparam vecType Floating-point or integer vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThanEqual.xml">GLSL lessThanEqual man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x > y.
///
/// @tparam vecType Floating-point or integer vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThan.xml">GLSL greaterThan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> greaterThan(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x >= y.
///
/// @tparam vecType Floating-point or integer vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThanEqual.xml">GLSL greaterThanEqual man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x == y.
///
/// @tparam vecType Floating-point, integer or boolean vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/equal.xml">GLSL equal man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> equal(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x != y.
///
/// @tparam vecType Floating-point, integer or boolean vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/notEqual.xml">GLSL notEqual man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> notEqual(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns true if any component of x is true.
///
/// @tparam vecType Boolean vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/any.xml">GLSL any man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL bool any(vecType<bool, P> const & v);
/// Returns true if all components of x are true.
///
/// @tparam vecType Boolean vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/all.xml">GLSL all man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL bool all(vecType<bool, P> const & v);
/// Returns the component-wise logical complement of x.
/// /!\ Because of language incompatibilities between C++ and GLSL, GLM defines the function not but not_ instead.
///
/// @tparam vecType Boolean vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/not.xml">GLSL not man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<bool, P> not_(vecType<bool, P> const & v);
/// @}
}//namespace glm
#include "func_vector_relational.inl"
@@ -0,0 +1,105 @@
/// @ref core
/// @file glm/detail/func_vector_relational.inl
#include <limits>
namespace glm
{
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> lessThan(vecType<T, P> const & x, vecType<T, P> const & y)
{
assert(x.length() == y.length());
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = x[i] < y[i];
return Result;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y)
{
assert(x.length() == y.length());
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = x[i] <= y[i];
return Result;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> greaterThan(vecType<T, P> const & x, vecType<T, P> const & y)
{
assert(x.length() == y.length());
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = x[i] > y[i];
return Result;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y)
{
assert(x.length() == y.length());
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = x[i] >= y[i];
return Result;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> equal(vecType<T, P> const & x, vecType<T, P> const & y)
{
assert(x.length() == y.length());
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = x[i] == y[i];
return Result;
}
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> notEqual(vecType<T, P> const & x, vecType<T, P> const & y)
{
assert(x.length() == y.length());
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < x.length(); ++i)
Result[i] = x[i] != y[i];
return Result;
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER bool any(vecType<bool, P> const & v)
{
bool Result = false;
for(length_t i = 0; i < v.length(); ++i)
Result = Result || v[i];
return Result;
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER bool all(vecType<bool, P> const & v)
{
bool Result = true;
for(length_t i = 0; i < v.length(); ++i)
Result = Result && v[i];
return Result;
}
template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> not_(vecType<bool, P> const & v)
{
vecType<bool, P> Result(uninitialize);
for(length_t i = 0; i < v.length(); ++i)
Result[i] = !v[i];
return Result;
}
}//namespace glm
#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS
# include "func_vector_relational_simd.inl"
#endif
@@ -0,0 +1,9 @@
/// @ref core
/// @file glm/detail/func_vector_relational_simd.inl
namespace glm{
namespace detail
{
}//namespace detail
}//namespace glm

Some files were not shown because too many files have changed in this diff Show More