HAxis sos

This commit is contained in:
guus
2018-08-11 16:46:35 +02:00
commit 510654f8a1
480 changed files with 54126 additions and 0 deletions

171
Source/UnrealProject/External/Events.hpp vendored Normal file
View File

@@ -0,0 +1,171 @@
#pragma once
#pragma pack(push, 1)
enum class EventCode : uint8_t
{
PlayerSpawn = 0,
PlayerUpdate,
PlayerDie,
PlayerCast,
PlayerHealth,
PlayerMana,
PlayerMaxHealth,
PlayerMaxMana,
PlayerDealDamage,
PlayerLevel,
SessionEnd,
MetaEvents = 64,
MapData,
MapImage,
PlayerName,
PlayerTeam,
AbilityName,
};
struct PlayerSpawn
{
PlayerSpawn() = default;
PlayerSpawn(uint32_t time, uint8_t player, float playerX, float playerY) : event(EventCode::PlayerSpawn), time(time), player(player), playerX(playerX), playerY(playerY) {}
EventCode event;
uint32_t time;
uint8_t player;
float playerX;
float playerY;
};
struct PlayerUpdate
{
PlayerUpdate() = default;
PlayerUpdate(uint32_t time, uint8_t player, float playerX, float playerY) : event(EventCode::PlayerUpdate), time(time), player(player), playerX(playerX), playerY(playerY) {}
EventCode event;
uint32_t time;
uint8_t player;
float playerX;
float playerY;
};
struct PlayerDie
{
PlayerDie() = default;
PlayerDie(uint32_t time, uint8_t player, uint8_t source) : event(EventCode::PlayerDie), time(time), player(player), source(source) {}
EventCode event;
uint32_t time;
uint8_t player;
uint8_t source;
};
struct PlayerCast
{
PlayerCast() = default;
PlayerCast(uint32_t time, uint8_t player, uint32_t ability) : event(EventCode::PlayerCast), time(time), player(player), ability(ability) {}
EventCode event;
uint32_t time;
uint8_t player;
uint32_t ability;
};
struct PlayerHealth
{
PlayerHealth() = default;
PlayerHealth(uint32_t time, uint8_t player, int32_t health) : event(EventCode::PlayerHealth), time(time), player(player), health(health) {}
EventCode event;
uint32_t time;
uint8_t player;
int32_t health;
};
struct PlayerMana
{
PlayerMana() = default;
PlayerMana(uint32_t time, uint8_t player, int32_t mana) : event(EventCode::PlayerMana), time(time), player(player), mana(mana) {}
EventCode event;
uint32_t time;
uint8_t player;
int32_t mana;
};
struct PlayerMaxHealth
{
PlayerMaxHealth() = default;
PlayerMaxHealth(uint32_t time, uint8_t player, int32_t maxHealth) : event(EventCode::PlayerMaxHealth), time(time), player(player), maxHealth(maxHealth) {}
EventCode event;
uint32_t time;
uint8_t player;
int32_t maxHealth;
};
struct PlayerMaxMana
{
PlayerMaxMana() = default;
PlayerMaxMana(uint32_t time, uint8_t player, int32_t maxMana) : event(EventCode::PlayerMaxMana), time(time), player(player), maxMana(maxMana) {}
EventCode event;
uint32_t time;
uint8_t player;
int32_t maxMana;
};
struct PlayerDealDamage
{
PlayerDealDamage() = default;
PlayerDealDamage(uint32_t time, uint8_t player, uint32_t ability, int32_t damage) : event(EventCode::PlayerDealDamage), time(time), player(player), ability(ability), damage(damage) {}
EventCode event;
uint32_t time;
uint8_t player;
uint32_t ability;
int32_t damage;
};
struct PlayerLevel
{
PlayerLevel() = default;
PlayerLevel(uint32_t time, uint8_t player, uint8_t level) : event(EventCode::PlayerLevel), time(time), player(player), level(level) {}
EventCode event;
uint32_t time;
uint8_t player;
uint8_t level;
};
struct SessionEnd
{
SessionEnd() = default;
SessionEnd(uint32_t time) : event(EventCode::SessionEnd), time(time) {}
EventCode event;
uint32_t time;
};
struct MapData
{
MapData() = default;
MapData(float minX, float maxX, float minY, float maxY) : event(EventCode::MapData), minX(minX), maxX(maxX), minY(minY), maxY(maxY) {}
EventCode event;
float minX;
float maxX;
float minY;
float maxY;
};
struct MapImage
{
MapImage() = default;
MapImage(uint32_t width, uint32_t height) : event(EventCode::MapImage), width(width), height(height) {}
EventCode event;
uint32_t width;
uint32_t height;
};
struct PlayerName
{
PlayerName() = default;
PlayerName(uint8_t player, uint16_t length) : event(EventCode::PlayerName), player(player), length(length) {}
EventCode event;
uint8_t player;
uint16_t length;
};
struct PlayerTeam
{
PlayerTeam() = default;
PlayerTeam(uint8_t player, uint8_t team) : event(EventCode::PlayerTeam), player(player), team(team) {}
EventCode event;
uint8_t player;
uint8_t team;
};
struct AbilityName
{
AbilityName() = default;
AbilityName(uint32_t ability, uint16_t length) : event(EventCode::AbilityName), ability(ability), length(length) {}
EventCode event;
uint32_t ability;
uint16_t length;
};
#pragma pack(pop)

View File

@@ -0,0 +1,96 @@
// Project Lab - NHTV Igad
#include "UnrealProject.h"
#if PLATFORM_SPECIFIC_WIN == 0
#include "HeatMapMetrics.h"
#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
float HeatMapMetrics::s_timeMap[3][512][512];
void HeatMapMetrics::ResetMap()
{
memset(&s_timeMap, 0, sizeof(s_timeMap));
}
void HeatMapMetrics::AddTime(FVector2D position, float time, size_t team)
{
position *= 512.0f;
s_timeMap[team][(int)position.Y][(int)position.X] += time;
}
void HeatMapMetrics::ExportToFile()
{
char* envPath;
size_t envPathSize;
getenv_s(&envPathSize, NULL, 0, "APPDATA");
if (envPathSize == 0)
{
TERROR("APPDATA does not exist.");
return;
}
envPath = (char*)malloc(envPathSize * sizeof(char));
if (!envPath)
{
TERROR("Failed to allocate memory.");
return;
}
getenv_s(&envPathSize, envPath, envPathSize, "APPDATA");
string path = envPath;
free(envPath);
path.append("\\Haxis\\HaxisHeatmap");
path.append(m_GetCurrentDateTime());
path.append(".HME");
fstream fs;
fs.open(path.c_str(), fstream::out | fstream::binary);
if (!fs.is_open())
{
TERROR("failed to export metrics");
return;
}
fs.write((char*)&s_timeMap[0][0][0], sizeof(s_timeMap));
fs.close();
}
void HeatMapMetrics::m_RetrieveCurrentTM(std::tm& a_TM)
{
time_t currentTime = time(0);
localtime_s(&a_TM, &currentTime);
}
string HeatMapMetrics::m_GetCurrentTime()
{
tm tstruct;
char buffer[80];
m_RetrieveCurrentTM(tstruct);
strftime(buffer, sizeof(buffer), "(%H:%M:%S) ", &tstruct);
return buffer;
}
string HeatMapMetrics::m_GetCurrentDateTime()
{
tm tstruct;
char buffer[80];
m_RetrieveCurrentTM(tstruct);
strftime(buffer, sizeof(buffer), "%Y-%m-%d_%H-%M-%S", &tstruct);
return buffer;
}
#endif

View File

@@ -0,0 +1,27 @@
// Project Lab - NHTV Igad
#pragma once
#if PLATFORM_SPECIFIC_WIN == 0
#include <string.h>
#include <time.h>
/**
*
*/
class UNREALPROJECT_API HeatMapMetrics
{
public:
static void AddTime(struct FVector2D position, float time, size_t team);
static void ExportToFile();
static void ResetMap();
protected:
static void m_RetrieveCurrentTM(std::tm& a_TM);
static std::string m_GetCurrentTime();
static std::string m_GetCurrentDateTime();
private:
static float s_timeMap[3][512][512];
};
#endif

View File

@@ -0,0 +1,46 @@
#ifndef _HEADER_INPUT_DEVICE_BASES
#define _HEADER_INPUT_DEVICE_BASES
#include "InputEnums.hpp"
#include "TeaVector2.hpp"
#include "TeaVector3.hpp"
namespace Input
{
enum InputDeviceType
{
IDT_NONE,
IDT_NOTDEFINED,
IDT_XBOX,
IDT_DS4
};
class InputDevice
{
public:
virtual void Update() = 0;
};
class Keyboard : public InputDevice
{
public:
virtual bool GetKey(const InputKey a_Key) = 0;
virtual bool GetKeyDown(const InputKey a_Key) = 0;
};
class Joystick : public InputDevice
{
public:
virtual ~Joystick() {};
virtual bool GetButton(const InputJoystickButton a_JoystickButton) = 0;
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton) = 0;
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton) = 0;
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton) = 0;
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton) = 0;
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton) = 0;
virtual bool IsValid() = 0;
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick) = 0;
virtual InputDeviceType GetDeviceType() = 0;
};
}
#endif

View File

@@ -0,0 +1,285 @@
#ifndef _HEADER_INPUT_ENUMS
#define _HEADER_INPUT_ENUMS
namespace Input
{
// Keyboard input keys
enum InputKey : unsigned char
{
IK_ESCAPE = 0x01,
IK_1 = 0x02,
IK_2 = 0x03,
IK_3 = 0x04,
IK_4 = 0x05,
IK_5 = 0x06,
IK_6 = 0x07,
IK_7 = 0x08,
IK_8 = 0x09,
IK_9 = 0x0A,
IK_0 = 0x0B,
IK_MINUS = 0x0C,
IK_EQUALS = 0x0D,
IK_BACK = 0x0E,
IK_TAB = 0x0F,
IK_Q = 0x10,
IK_W = 0x11,
IK_E = 0x12,
IK_R = 0x13,
IK_T = 0x14,
IK_Y = 0x15,
IK_U = 0x16,
IK_I = 0x17,
IK_O = 0x18,
IK_P = 0x19,
IK_LBRACKET = 0x1A,
IK_RBRACKET = 0x1B,
IK_RETURN = 0x1C,
IK_LCONTROL = 0x1D,
IK_A = 0x1E,
IK_S = 0x1F,
IK_D = 0x20,
IK_F = 0x21,
IK_G = 0x22,
IK_H = 0x23,
IK_J = 0x24,
IK_K = 0x25,
IK_L = 0x26,
IK_SEMICOLON = 0x27,
IK_APOSTROPHE = 0x28,
IK_GRAVE = 0x29,
IK_LSHIFT = 0x2A,
IK_BACKSLASH = 0x2B,
IK_Z = 0x2C,
IK_X = 0x2D,
IK_C = 0x2E,
IK_V = 0x2F,
IK_B = 0x30,
IK_N = 0x31,
IK_M = 0x32,
IK_COMMA = 0x33,
IK_PERIOD = 0x34,
IK_SLASH = 0x35,
IK_RSHIFT = 0x36,
IK_MULTIPLY = 0x37,
IK_LMENU = 0x38,
IK_SPACE = 0x39,
IK_CAPITAL = 0x3A,
IK_F1 = 0x3B,
IK_F2 = 0x3C,
IK_F3 = 0x3D,
IK_F4 = 0x3E,
IK_F5 = 0x3F,
IK_F6 = 0x40,
IK_F7 = 0x41,
IK_F8 = 0x42,
IK_F9 = 0x43,
IK_F10 = 0x44,
IK_NUMLOCK = 0x45,
IK_SCROLL = 0x46,
IK_NUMPAD7 = 0x47,
IK_NUMPAD8 = 0x48,
IK_NUMPAD9 = 0x49,
IK_SUBTRACT = 0x4A,
IK_NUMPAD4 = 0x4B,
IK_NUMPAD5 = 0x4C,
IK_NUMPAD6 = 0x4D,
IK_ADD = 0x4E,
IK_NUMPAD1 = 0x4F,
IK_NUMPAD2 = 0x50,
IK_NUMPAD3 = 0x51,
IK_NUMPAD0 = 0x52,
IK_DECIMAL = 0x53,
IK_OEM_102 = 0x56,
IK_F11 = 0x57,
IK_F12 = 0x58,
IK_F13 = 0x64,
IK_F14 = 0x65,
IK_F15 = 0x66,
IK_KANA = 0x70,
IK_ABNT_C1 = 0x73,
IK_CONVERT = 0x79,
IK_NOCONVERT = 0x7B,
IK_YEN = 0x7D,
IK_ABNT_C2 = 0x7E,
IK_NUMPADEQUALS = 0x8D,
IK_PREVTRACK = 0x90,
IK_AT = 0x91,
IK_COLON = 0x92,
IK_UNDERLINE = 0x93,
IK_KANJI = 0x94,
IK_STOP = 0x95,
IK_AX = 0x96,
IK_UNLABELED = 0x97,
IK_NEXTTRACK = 0x99,
IK_NUMPADENTER = 0x9C,
IK_RCONTROL = 0x9D,
IK_MUTE = 0xA0,
IK_CALCULATOR = 0xA1,
IK_PLAYPAUSE = 0xA2,
IK_MEDIASTOP = 0xA4,
IK_VOLUMEDOWN = 0xAE,
IK_VOLUMEUP = 0xB0,
IK_WEBHOME = 0xB2,
IK_NUMPADCOMMA = 0xB3,
IK_DIVIDE = 0xB5,
IK_SYSRQ = 0xB7,
IK_RMENU = 0xB8,
IK_PAUSE = 0xC5,
IK_HOME = 0xC7,
IK_UP = 0xC8,
IK_PRIOR = 0xC9,
IK_LEFT = 0xCB,
IK_RIGHT = 0xCD,
IK_END = 0xCF,
IK_DOWN = 0xD0,
IK_NEXT = 0xD1,
IK_INSERT = 0xD2,
IK_DELETE = 0xD3,
IK_LWIN = 0xDB,
IK_RWIN = 0xDC,
IK_APPS = 0xDD,
IK_POWER = 0xDE,
IK_SLEEP = 0xDF,
IK_WAKE = 0xE3,
IK_WEBSEARCH = 0xE5,
IK_WEBFAVORITES = 0xE6,
IK_WEBREFRESH = 0xE7,
IK_WEBSTOP = 0xE8,
IK_WEBFORWARD = 0xE9,
IK_WEBBACK = 0xEA,
IK_MYCOMPUTER = 0xEB,
IK_MAIL = 0xEC,
IK_MEDIASELECT = 0xED,
IK_BACKSPACE = IK_BACK,
IK_NUMPADSTAR = IK_MULTIPLY,
IK_LALT = IK_LMENU,
IK_CAPSLOCK = IK_CAPITAL,
IK_NUMPADMINUS = IK_SUBTRACT,
IK_NUMPADPLUS = IK_ADD,
IK_NUMPADPERIOD = IK_DECIMAL,
IK_NUMPADSLASH = IK_DIVIDE,
IK_RALT = IK_RMENU,
IK_UPARROW = IK_UP,
IK_PGUP = IK_PRIOR,
IK_LEFTARROW = IK_LEFT,
IK_RIGHTARROW = IK_RIGHT,
IK_DOWNARROW = IK_DOWN,
IK_PGDN = IK_NEXT,
};
// Joystick axis
enum InputJoystickAxis
{
IJA_LSTICK,
IJA_RSTICK,
IJA_LRTRIGGER,
IJA_DPAD,
};
// Joystick buttons
enum InputJoystickButton : unsigned char
{
IJB_BUTTON0,
IJB_BUTTON1,
IJB_BUTTON2,
IJB_BUTTON3,
IJB_BUTTON4,
IJB_BUTTON5,
IJB_BUTTON6,
IJB_BUTTON7,
IJB_BUTTON8,
IJB_BUTTON9,
IJB_BUTTON10,
IJB_BUTTON11,
IJB_BUTTON12,
IJB_BUTTON13,
IJB_BUTTON14,
IJB_BUTTON15,
IJB_BUTTON16,
IJB_BUTTON17,
IJB_BUTTON18,
IJB_BUTTON19,
IJB_BUTTON20,
IJB_BUTTON21,
IJB_BUTTON22,
IJB_BUTTON23,
IJB_BUTTON24,
IJB_BUTTON25,
IJB_BUTTON26,
IJB_BUTTON27,
IJB_BUTTON28,
IJB_BUTTON29,
IJB_BUTTON30,
IJB_BUTTON31,
IJB_DPADUP = 200,
IJB_DPADRIGHT = 201,
IJB_DPADLEFT = 202,
IJB_DPADDOWN = 203,
// Xbox 360 buttons
IJB_XBOXA = IJB_BUTTON0,
IJB_XBOXB = IJB_BUTTON1,
IJB_XBOXX = IJB_BUTTON2,
IJB_XBOXY = IJB_BUTTON3,
IJB_XBOXLB = IJB_BUTTON4,
IJB_XBOXRB = IJB_BUTTON5,
IJB_XBOXBACK = IJB_BUTTON6,
IJB_XBOXSTART = IJB_BUTTON7,
IJB_XBOXLEFTSTICK = IJB_BUTTON8,
IJB_XBOXRIGHTSTICK = IJB_BUTTON9,
IJB_XBOXDPADUP = IJB_DPADUP,
IJB_XBOXDPADRIGHT = IJB_DPADRIGHT,
IJB_XBOXDPADLEFT = IJB_DPADLEFT,
IJB_XBOXDPADDOWN = IJB_DPADDOWN,
IJB_XBOXLT = 204,
IJB_XBOXRT = 205,
// Dualshock 4 buttons
IJB_DS4SQUARE = IJB_BUTTON0,
IJB_DS4CROSS = IJB_BUTTON1,
IJB_DS4CIRCLE = IJB_BUTTON2,
IJB_DS4TRIANGLE = IJB_BUTTON3,
IJB_DS4L1 = IJB_BUTTON4,
IJB_DS4R1 = IJB_BUTTON5,
IJB_DS4L2 = IJB_BUTTON6,
IJB_DS4R2 = IJB_BUTTON7,
IJB_DS4SHARE = IJB_BUTTON8,
IJB_DS4OPTIONS = IJB_BUTTON9,
IJB_DS4LEFTSTICK = IJB_BUTTON10,
IJB_DS4RIGHTSTICK = IJB_BUTTON11,
IJB_DS4PLAYSTATION = IJB_BUTTON12,
IJB_DS4TOUCH = IJB_BUTTON13,
IJB_DS4DPADUP = IJB_DPADUP,
IJB_DS4DPADRIGHT = IJB_DPADRIGHT,
IJB_DS4DPADLEFT = IJB_DPADLEFT,
IJB_DS4DPADDOWN = IJB_DPADDOWN,
};
enum InputJoystickPhysical : unsigned char
{
IJP_FACEDOWN = 0,
IJP_FACERIGHT = 1,
IJP_FACELEFT = 2,
IJP_FACEUP = 3,
IJP_DPADDOWN = 4,
IJP_DPADRIGHT = 5,
IJP_DPADLEFT = 6,
IJP_DPADUP = 7,
IJP_SHOULDERRIGHT = 8,
IJP_SHOULDERLEFT = 9,
IJP_TRIGGERRIGHT = 10,
IJP_TRIGGERLEFT = 11,
IJP_START = 12,
IJP_SELECT = 13,
IJP_STICKLEFT = 14,
IJP_STICKRIGHT = 15,
};
enum InputManagerEvent : unsigned char
{
IME_PRESSED = 0,
IME_RELEASED = 1,
IME_REPEAT = 2,
};
}
#endif

View File

@@ -0,0 +1,688 @@
#include "UnrealProject.h"
#if PLATFORM_SPECIFIC_WIN == 0
#define _SOURCE_INPUT_MANAGER
#include "InputManager.hpp"
#include "AllowWindowsPlatformTypes.h"
#pragma comment(lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
#define DIRECTINPUT_VERSION 0x0800
#include <Windows.h>
#include <dinput.h>
#include <map>
using namespace std;
#define DUALSHOCK4PRODUCTDATA (0x05C4054CUL)
#define DUALSHOCK4DEVTYPE (0x00010318UL)
#define WIREDXBOXDEVTYPE (0x00010215UL)
#define PI 3.14159265359f
namespace Input
{
struct GUID_Impl
{
GUID instance;
DWORD devType;
unsigned long productData1;
};
LPDIRECTINPUT8 g_DirectInput;
HWND g_HWND;
InputManager* InputManager::s_instance;
bool InputManager::s_isInitialized = false;
vector<GUID_Impl> g_GUIDs;
bool InputManager::IsInitialized()
{
return s_isInitialized;
}
bool InputManager::Initialize()
{
if (!IsInitialized())
{
g_HWND = GetActiveWindow();
HRESULT hr;
HINSTANCE hInstance = GetModuleHandle(nullptr);
hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&g_DirectInput, NULL);
if (FAILED(hr))
{
return false;
}
s_instance = new InputManager();
s_isInitialized = true;
return true;
}
return false;
}
void InputManager::Cleanup()
{
if (IsInitialized())
{
delete s_instance;
s_instance = nullptr;
g_DirectInput->Release();
s_isInitialized = false;
}
}
InputManager* InputManager::GetInstance()
{
if (!s_isInitialized)
Initialize();
return s_instance;
}
// Implementation of Input Devices
class Keyboard_Impl : public Keyboard
{
public:
Keyboard_Impl()
{
HRESULT hr;
hr = g_DirectInput->CreateDevice(GUID_SysKeyboard, &m_Device, NULL);
if (FAILED(hr))
{
}
hr = m_Device->SetDataFormat(&c_dfDIKeyboard);
if (FAILED(hr))
{
}
hr = m_Device->SetCooperativeLevel(g_HWND, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(hr))
{
}
}
~Keyboard_Impl()
{
m_Device->Unacquire();
}
virtual void Update() override final
{
HRESULT hr;
hr = m_Device->Acquire();
memcpy(m_PreviousState, m_CurrentState, sizeof(BYTE) * 256);
m_Device->GetDeviceState(sizeof(m_CurrentState), (LPVOID)&m_CurrentState);
}
virtual bool GetKey(const InputKey a_Key) override final
{
return (m_CurrentState[a_Key] & 0x80) != 0;
}
virtual bool GetKeyDown(const InputKey a_Key) override final
{
return m_CurrentState[a_Key] & 0x80 && !(m_PreviousState[a_Key] & 0x80);
}
private:
IDirectInputDevice8* m_Device;
BYTE m_CurrentState[256];
BYTE m_PreviousState[256];
};
class Joystick_Impl : public Joystick
{
public:
Joystick_Impl(IDirectInputDevice8* a_Device)
{
HRESULT hr;
m_Device = a_Device;
hr = m_Device->SetDataFormat(&c_dfDIJoystick);
if (FAILED(hr))
{
}
hr = m_Device->SetCooperativeLevel(g_HWND, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(hr))
{
}
}
virtual ~Joystick_Impl()
{
m_Device->Unacquire();
m_Device->Release();
}
virtual void Update() override final
{
HRESULT hr;
m_PreviousState = m_CurrentState;
hr = m_Device->Acquire();
if (FAILED(hr))
{
m_IsValid = false;
return;
}
hr = m_Device->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID)&m_CurrentState);
if (FAILED(hr))
{
m_IsValid = false;
return;
}
m_IsValid = true;
}
virtual bool IsValid() override final
{
return m_IsValid;
}
virtual bool GetButton(const InputJoystickButton a_JoystickButton)
{
return (m_CurrentState.rgbButtons[a_JoystickButton] & 0x80) != 0;
}
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton)
{
return false;
}
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton)
{
return m_CurrentState.rgbButtons[a_JoystickButton] & 0x80 && !(m_PreviousState.rgbButtons[a_JoystickButton] & 0x80);
}
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton)
{
return false;
}
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton)
{
return m_PreviousState.rgbButtons[a_JoystickButton] & 0x80 && !(m_CurrentState.rgbButtons[a_JoystickButton] & 0x80);
}
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton)
{
return false;
}
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick)
{
if (IsValid())
{
switch (a_InputStick)
{
case Input::IJA_LSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lX, (float)m_CurrentState.lY) / 32767.0f;
case Input::IJA_RSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lRx, (float)m_CurrentState.lRy) / 32767.0f;
case Input::IJA_LRTRIGGER:
return TeaLib::Math::Vector2f((float)m_CurrentState.lZ, (float)m_CurrentState.lRz) / 32767.0f;
default:
return TeaLib::Math::Vector2f();
}
}
return TeaLib::Math::Vector2f();
}
virtual InputDeviceType GetDeviceType()
{
return IDT_NOTDEFINED;
}
protected:
bool m_IsValid = false;
IDirectInputDevice8* m_Device;
DIJOYSTATE m_CurrentState, m_PreviousState;
};
class JoystickDS4_Impl : public Joystick_Impl
{
public:
JoystickDS4_Impl(IDirectInputDevice8* a_Device) : Joystick_Impl(a_Device)
{
m_PhysicalBindings[IJP_FACEDOWN] = IJB_DS4CROSS;
m_PhysicalBindings[IJP_FACERIGHT] = IJB_DS4CIRCLE;
m_PhysicalBindings[IJP_FACELEFT] = IJB_BUTTON0;
m_PhysicalBindings[IJP_FACEUP] = IJB_BUTTON3;
m_PhysicalBindings[IJP_DPADDOWN] = IJB_DS4DPADDOWN;
m_PhysicalBindings[IJP_DPADRIGHT] = IJB_DS4DPADRIGHT;
m_PhysicalBindings[IJP_DPADLEFT] = IJB_DS4DPADLEFT;
m_PhysicalBindings[IJP_DPADUP] = IJB_DS4DPADUP;
m_PhysicalBindings[IJP_SHOULDERRIGHT] = IJB_DS4R1;
m_PhysicalBindings[IJP_SHOULDERLEFT] = IJB_DS4L1;
m_PhysicalBindings[IJP_TRIGGERRIGHT] = IJB_DS4R2;
m_PhysicalBindings[IJP_TRIGGERLEFT] = IJB_DS4L2;
m_PhysicalBindings[IJP_START] = IJB_DS4OPTIONS;
m_PhysicalBindings[IJP_SELECT] = IJB_DS4SHARE;
m_PhysicalBindings[IJP_STICKLEFT] = IJB_DS4LEFTSTICK;
m_PhysicalBindings[IJP_STICKRIGHT] = IJB_DS4RIGHTSTICK;
}
virtual bool GetButton(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return (m_CurrentState.rgbButtons[a_JoystickButton] & 0x80) != 0;
else
{
switch (a_JoystickButton)
{
case Input::IJB_DS4DPADUP:
if (m_CurrentState.rgdwPOV[0] < 36000 && m_CurrentState.rgdwPOV[0] > 27000 || m_CurrentState.rgdwPOV[0] < 9000)
return true;
break;
case Input::IJB_DS4DPADRIGHT:
if (m_CurrentState.rgdwPOV[0] > 0 && m_CurrentState.rgdwPOV[0] < 18000)
return true;
break;
case Input::IJB_DS4DPADDOWN:
if (m_CurrentState.rgdwPOV[0] > 9000 && m_CurrentState.rgdwPOV[0] < 27000)
return true;
break;
case Input::IJB_DS4DPADLEFT:
if (m_CurrentState.rgdwPOV[0] > 18000 && m_CurrentState.rgdwPOV[0] < 36000)
return true;
break;
default:
break;
}
return false;
}
}
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButton(m_PhysicalBindings[a_JoystickButton]);
}
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_CurrentState.rgbButtons[a_JoystickButton] & 0x80 && !(m_PreviousState.rgbButtons[a_JoystickButton] & 0x80);
else
{
switch (a_JoystickButton)
{
case Input::IJB_DS4DPADUP:
if (m_CurrentState.rgdwPOV[0] == 0 && m_PreviousState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_DS4DPADRIGHT:
if (m_CurrentState.rgdwPOV[0] == 9000 && m_PreviousState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_DS4DPADDOWN:
if (m_CurrentState.rgdwPOV[0] == 18000 && m_PreviousState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_DS4DPADLEFT:
if (m_CurrentState.rgdwPOV[0] == 27000 && m_PreviousState.rgdwPOV[0] != 27000)
return true;
break;
default:
break;
}
return false;
}
}
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButtonDown(m_PhysicalBindings[a_JoystickButton]);
}
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_PreviousState.rgbButtons[a_JoystickButton] & 0x80 && !(m_CurrentState.rgbButtons[a_JoystickButton] & 0x80);
else
{
switch (a_JoystickButton)
{
case Input::IJB_DS4DPADUP:
if (m_PreviousState.rgdwPOV[0] == 0 && m_CurrentState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_DS4DPADRIGHT:
if (m_PreviousState.rgdwPOV[0] == 9000 && m_CurrentState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_DS4DPADDOWN:
if (m_PreviousState.rgdwPOV[0] == 18000 && m_CurrentState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_DS4DPADLEFT:
if (m_PreviousState.rgdwPOV[0] == 27000 && m_CurrentState.rgdwPOV[0] != 27000)
return true;
break;
default:
break;
}
return false;
}
}
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButtonUp(m_PhysicalBindings[a_JoystickButton]);
}
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick) override final
{
if (IsValid())
{
float angle;
switch (a_InputStick)
{
case Input::IJA_LSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lX - 32767.0f, (float)m_CurrentState.lY - 32767.0f) / 32767.0f;
case Input::IJA_RSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lZ - 32767.0f, (float)m_CurrentState.lRz - 32767.0f) / 32767.0f;
case Input::IJA_LRTRIGGER:
return TeaLib::Math::Vector2f((float)m_CurrentState.lRx, (float)m_CurrentState.lRy) / 65534.0f;
case Input::IJA_DPAD:
if (m_PreviousState.rgdwPOV[0] < 90000)
{
angle = (((float)m_PreviousState.rgdwPOV[0] / 100.0f) * PI / 180.0f);
return TeaLib::Math::Vector2f(sinf(angle), -cosf(angle));
}
return TeaLib::Math::Vector2f();
default:
return TeaLib::Math::Vector2f();
}
}
return TeaLib::Math::Vector2f();
}
virtual InputDeviceType GetDeviceType() override final
{
return IDT_DS4;
}
private:
map<InputJoystickPhysical, InputJoystickButton> m_PhysicalBindings;
};
class JoystickXbox360_Impl : public Joystick_Impl
{
public:
JoystickXbox360_Impl(IDirectInputDevice8* a_Device) : Joystick_Impl(a_Device)
{
m_PhysicalBindings[IJP_FACEDOWN] = IJB_XBOXA;
m_PhysicalBindings[IJP_FACERIGHT] = IJB_XBOXB;
m_PhysicalBindings[IJP_FACELEFT] = IJB_XBOXX;
m_PhysicalBindings[IJP_FACEUP] = IJB_XBOXY;
m_PhysicalBindings[IJP_DPADDOWN] = IJB_XBOXDPADDOWN;
m_PhysicalBindings[IJP_DPADRIGHT] = IJB_XBOXDPADRIGHT;
m_PhysicalBindings[IJP_DPADLEFT] = IJB_XBOXDPADLEFT;
m_PhysicalBindings[IJP_DPADUP] = IJB_XBOXDPADUP;
m_PhysicalBindings[IJP_SHOULDERRIGHT] = IJB_XBOXRB;
m_PhysicalBindings[IJP_SHOULDERLEFT] = IJB_XBOXLB;
m_PhysicalBindings[IJP_TRIGGERRIGHT] = IJB_XBOXRT;
m_PhysicalBindings[IJP_TRIGGERLEFT] = IJB_XBOXLT;
m_PhysicalBindings[IJP_START] = IJB_XBOXSTART;
m_PhysicalBindings[IJP_SELECT] = IJB_XBOXBACK;
m_PhysicalBindings[IJP_STICKLEFT] = IJB_XBOXLEFTSTICK;
m_PhysicalBindings[IJP_STICKRIGHT] = IJB_XBOXRIGHTSTICK;
}
virtual TeaLib::Math::Vector2f GetDelta(const InputJoystickAxis a_InputStick) override final
{
if (IsValid())
{
float result;
float angle;
switch (a_InputStick)
{
case Input::IJA_LSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lX - 32767.0f, (float)m_CurrentState.lY - 32767.0f) / 32767.0f;
case Input::IJA_RSTICK:
return TeaLib::Math::Vector2f((float)m_CurrentState.lRx - 32767.0f, (float)m_CurrentState.lRy - 32767.0f) / 32767.0f;
case Input::IJA_LRTRIGGER:
result = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
return TeaLib::Math::Vector2f(result, result);
case Input::IJA_DPAD:
if (m_PreviousState.rgdwPOV[0] < 90000)
{
angle = (((float)m_PreviousState.rgdwPOV[0] / 100.0f) * PI / 180.0f);
return TeaLib::Math::Vector2f(sinf(angle), -cosf(angle));
}
return TeaLib::Math::Vector2f();
default:
return TeaLib::Math::Vector2f();
}
}
return TeaLib::Math::Vector2f();
}
virtual bool GetButton(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return (m_CurrentState.rgbButtons[a_JoystickButton] & 0x80) != 0;
else
{
float val;
switch (a_JoystickButton)
{
case Input::IJB_XBOXDPADUP:
if (m_CurrentState.rgdwPOV[0] < 36000 && m_CurrentState.rgdwPOV[0] > 27000 || m_CurrentState.rgdwPOV[0] < 9000)
return true;
break;
case Input::IJB_XBOXDPADRIGHT:
if (m_CurrentState.rgdwPOV[0] > 0 && m_CurrentState.rgdwPOV[0] < 18000)
return true;
break;
case Input::IJB_XBOXDPADDOWN:
if (m_CurrentState.rgdwPOV[0] > 9000 && m_CurrentState.rgdwPOV[0] < 27000)
return true;
break;
case Input::IJB_XBOXDPADLEFT:
if (m_CurrentState.rgdwPOV[0] > 18000 && m_CurrentState.rgdwPOV[0] < 36000)
return true;
break;
case Input::IJB_XBOXLT:
val = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;;
return val > 0.1f;
case Input::IJB_XBOXRT:
val = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;;
return val < -0.1f;
default:
break;
}
return false;
}
}
virtual bool GetButton(const InputJoystickPhysical a_JoystickButton) override final
{
return GetButton(m_PhysicalBindings[a_JoystickButton]);
}
virtual bool GetButtonDown(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_CurrentState.rgbButtons[a_JoystickButton] & 0x80 && !(m_PreviousState.rgbButtons[a_JoystickButton] & 0x80);
else
{
float curr, prev;
switch (a_JoystickButton)
{
case Input::IJB_XBOXDPADUP:
if (m_CurrentState.rgdwPOV[0] == 0 && m_PreviousState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_XBOXDPADRIGHT:
if (m_CurrentState.rgdwPOV[0] == 9000 && m_PreviousState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_XBOXDPADDOWN:
if (m_CurrentState.rgdwPOV[0] == 18000 && m_PreviousState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_XBOXDPADLEFT:
if (m_CurrentState.rgdwPOV[0] == 27000 && m_PreviousState.rgdwPOV[0] != 27000)
return true;
break;
case Input::IJB_XBOXLT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr > 0.1f && prev <= 0.1f;
case Input::IJB_XBOXRT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr < -0.1f && prev >= -0.1f;
default:
break;
}
return false;
}
}
virtual bool GetButtonDown(const InputJoystickPhysical a_JoystickButton) override final
{
if (m_PhysicalBindings.find(a_JoystickButton) != m_PhysicalBindings.end())
return GetButtonDown(m_PhysicalBindings[a_JoystickButton]);
return false;
}
virtual bool GetButtonUp(const InputJoystickButton a_JoystickButton) override final
{
if (a_JoystickButton < 200)
return m_PreviousState.rgbButtons[a_JoystickButton] & 0x80 && !(m_CurrentState.rgbButtons[a_JoystickButton] & 0x80);
else
{
float curr, prev;
switch (a_JoystickButton)
{
case Input::IJB_XBOXDPADUP:
if (m_PreviousState.rgdwPOV[0] == 0 && m_CurrentState.rgdwPOV[0] != 0)
return true;
break;
case Input::IJB_XBOXDPADRIGHT:
if (m_PreviousState.rgdwPOV[0] == 9000 && m_CurrentState.rgdwPOV[0] != 9000)
return true;
break;
case Input::IJB_XBOXDPADDOWN:
if (m_PreviousState.rgdwPOV[0] == 18000 && m_CurrentState.rgdwPOV[0] != 18000)
return true;
break;
case Input::IJB_XBOXDPADLEFT:
if (m_PreviousState.rgdwPOV[0] == 27000 && m_CurrentState.rgdwPOV[0] != 27000)
return true;
break;
case Input::IJB_XBOXLT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr <= 0.1f && prev > 0.1f;
case Input::IJB_XBOXRT:
curr = ((float)m_CurrentState.lZ - 32767.0f) / 32767.0f;
prev = ((float)m_PreviousState.lZ - 32767.0f) / 32767.0f;
return curr >= -0.1f && prev < -0.1f;
default:
break;
}
return false;
}
}
virtual bool GetButtonUp(const InputJoystickPhysical a_JoystickButton) override final
{
if (m_PhysicalBindings.find(a_JoystickButton) != m_PhysicalBindings.end())
return GetButtonUp(m_PhysicalBindings[a_JoystickButton]);
return false;
}
virtual InputDeviceType GetDeviceType() override final
{
return IDT_XBOX;
}
private:
map<InputJoystickPhysical, InputJoystickButton> m_PhysicalBindings;
};
InputManager::InputManager() : joystick(nullptr)
{
keyboard = new Keyboard_Impl();
}
void InputManager::Update()
{
keyboard->Update();
if (joystick)
{
joystick->Update();
if (joystick->IsValid())
{
for (auto it : m_joystickCallbacks)
{
switch (it.first.second)
{
case IME_PRESSED:
if (joystick->GetButtonDown(it.first.first))
{
it.second->Call();
}
break;
case IME_RELEASED:
if (joystick->GetButtonUp(it.first.first))
{
it.second->Call();
}
break;
case IME_REPEAT:
if (joystick->GetButton(it.first.first))
{
it.second->Call();
}
break;
}
}
}
}
}
BOOL __stdcall JoystickEnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
InputManager* inputInstance = InputManager::GetInstance();
inputInstance->AddJoystickName(lpddi->tszProductName);
GUID_Impl newGUID;
newGUID.devType = lpddi->dwDevType;
newGUID.instance = lpddi->guidInstance;
newGUID.productData1 = lpddi->guidProduct.Data1;
g_GUIDs.push_back(newGUID);
return DIENUM_CONTINUE;
}
void InputManager::AddJoystickName(std::wstring a_name)
{
m_joystickNames.push_back(a_name);
}
void InputManager::SearchForJoystick()
{
m_joystickNames.clear();
g_GUIDs.clear();
g_DirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL, &JoystickEnumCallback, NULL, DIEDFL_ATTACHEDONLY);
}
vector<wstring>& InputManager::GetJoystickNames()
{
return m_joystickNames;
}
void InputManager::ConnectJoystickByIndex(size_t a_index)
{
if (joystick)
delete joystick;
if (a_index >= g_GUIDs.size())
return;
HRESULT hr;
IDirectInputDevice8* device;
hr = g_DirectInput->CreateDevice(g_GUIDs[a_index].instance, &device, NULL);
if (!FAILED(hr))
{
if (g_GUIDs[a_index].devType == DUALSHOCK4DEVTYPE || g_GUIDs[a_index].productData1 == DUALSHOCK4PRODUCTDATA)
joystick = new JoystickDS4_Impl(device);
else if (g_GUIDs[a_index].devType == WIREDXBOXDEVTYPE)
joystick = new JoystickXbox360_Impl(device);
else
joystick = new Joystick_Impl(device);
}
}
InputManager::~InputManager()
{
delete keyboard;
delete joystick;
ClearCallbacks();
}
void InputManager::ClearCallbacks()
{
for (auto it : m_joystickCallbacks)
{
delete it.second;
}
m_joystickCallbacks.clear();
}
}
#endif

View File

@@ -0,0 +1,95 @@
#ifndef _HEADER_INPUT_MANAGER
#define _HEADER_INPUT_MANAGER
#include "InputDeviceBases.hpp"
#include "TeaCallback.hpp"
#include <map>
#include <string.h>
#include <vector>
namespace Input
{
class InputManager
{
public:
static bool IsInitialized();
static bool Initialize();
static void Cleanup();
static InputManager* GetInstance();
private:
static bool s_isInitialized;
static InputManager* s_instance;
public:
InputManager();
~InputManager();
InputDeviceType GetConnectedType()
{
if (joystick)
return joystick->GetDeviceType();
return IDT_NONE;
}
bool IsJoystickConnected(const unsigned int a_Channel);
void SearchForJoystick();
std::vector<std::wstring>& GetJoystickNames();
void AddJoystickName(std::wstring a_name);
void ConnectJoystickByIndex(size_t m_index);
void Update();
void RegisterCallback(InputJoystickPhysical a_Button, InputManagerEvent a_Event, void(*a_CallbackFunction)())
{
std::pair<InputJoystickPhysical, InputManagerEvent> newEvent(a_Button, a_Event);
if (m_joystickCallbacks.find(newEvent) == m_joystickCallbacks.end())
{
m_joystickCallbacks[newEvent] = new TeaLib::Utility::Callback<>();
}
m_joystickCallbacks[newEvent]->Register(a_CallbackFunction);
}
template<typename ClassType> void RegisterCallback(InputJoystickPhysical a_Button, InputManagerEvent a_Event, ClassType* a_ClassInstance, void(ClassType::*a_CallbackFunction)())
{
std::pair<InputJoystickPhysical, InputManagerEvent> newEvent(a_Button, a_Event);
if (m_joystickCallbacks.find(newEvent) == m_joystickCallbacks.end())
{
m_joystickCallbacks[newEvent] = new TeaLib::Utility::Callback<>();
}
m_joystickCallbacks[newEvent]->Register(a_ClassInstance, a_CallbackFunction);
}
void DeregisterCallback(InputJoystickPhysical a_Button, InputManagerEvent a_Event, void(*a_CallbackFunction)())
{
if (!this)
return;
std::pair<InputJoystickPhysical, InputManagerEvent> newEvent(a_Button, a_Event);
if (m_joystickCallbacks.find(newEvent) != m_joystickCallbacks.end())
{
m_joystickCallbacks[newEvent]->Deregister(a_CallbackFunction);
};
}
template<typename ClassType> void DeregisterCallback(InputJoystickPhysical a_Button, InputManagerEvent a_Event, ClassType* a_ClassInstance, void(ClassType::*a_CallbackFunction)())
{
if (!this)
return;
std::pair<InputJoystickPhysical, InputManagerEvent> newEvent(a_Button, a_Event);
if (m_joystickCallbacks.find(newEvent) != m_joystickCallbacks.end())
{
m_joystickCallbacks[newEvent]->Deregister(a_ClassInstance, a_CallbackFunction);
}
}
void ClearCallbacks();
Keyboard* keyboard;
Joystick* joystick;
private:
std::vector<std::wstring> m_joystickNames;
std::map<std::pair<InputJoystickPhysical, InputManagerEvent>, TeaLib::Utility::Callback<>*> m_joystickCallbacks;
};
}
#endif

View File

@@ -0,0 +1,362 @@
#include "UnrealProject.h"
#if WITH_EDITOR
#include "Metrics.hpp"
//#include <append>
#include <timer>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
#include <chrono>
#include <algorithm>
#if PLATFORM_SPECIFIC_WIN == 0
#include "AllowWindowsPlatformTypes.h"
#include <Windows.h>
#endif
using namespace jlib;
using namespace std;
using namespace std::chrono;
#include "Events.hpp"
#include <type_traits>
namespace Metrics
{
ofstream writeStream;
timer writeTime;
uint32_t lastWriteTime;
unordered_map<uint8_t, PlayerHandle*> players;
uint32_t CurrentTime()
{
return uint32_t(writeTime.milliseconds());
}
uint32_t TimeOffset()
{
const uint32_t currentTime = uint32_t(writeTime.milliseconds());
const uint32_t offset = currentTime - lastWriteTime;
lastWriteTime = currentTime;
return offset;
}
wstring FormatNumber(uint16_t number, size_t desiredLength)
{
wstring result = wstring() + number;
while (result.size() < desiredLength)
result = wstring(L"0") + result;
return result;
}
template<typename Event> void WriteEvent(const Event& event)
{
writeStream.write((const char*)&event, streamsize(sizeof(Event)));
}
void WriteBinary(void* addr, size_t size)
{
writeStream.write((const char*)addr, size);
}
void Clear()
{
for (auto iter = players.begin(); iter != players.end(); iter++)
delete iter->second;
players.clear();
}
}
bool Metrics::StartSession(const wstring& filePath)
{
EndSession();
time_t timePoint = system_clock::to_time_t(std::chrono::system_clock::now());
const char* timeData = ctime(&timePoint);
wstring dateTime = convert_cstring_type<wchar_t, char>(timeData);
wstring dateTimeFiltered;
for (size_t i = 0; i < dateTime.size(); i++)
{
if (dateTime[i] == L'\n' || dateTime[i] == L'\r')
continue;
dateTimeFiltered += dateTime[i];
}
dateTime = dateTimeFiltered;
wstring sessionName = L"MetricsSession";
#if PLATFORM_SPECIFIC_WIN == 0
sessionName.clear();
sessionName.resize(256);
DWORD length = 256;
GetComputerName(&sessionName[0], &length);
sessionName.resize(length);
wstring sessionNameFiltered;
for (size_t i = 0; i < sessionName.size(); i++)
{
wchar_t character = sessionName[i];
if ((character >= L'0' && character <= L'9') || (character >= L'a' && character <= L'z') || (character >= L'A' && character <= L'Z') || character == L'-' || character == L'_')
sessionNameFiltered += character;
}
sessionName = sessionNameFiltered;
#endif
wstring fileName = sessionName + L" - " + dateTime + L".hms";
replace(fileName.begin(), fileName.end(), L':', L'-');
writeStream.open(convert_string_type<char, wchar_t>(filePath + fileName), ios::out | ios::binary | ios::trunc);
writeTime.restart();
lastWriteTime = 0;
// Write the header
writeStream.write("HMS", 3);
return writeStream.is_open();
}
bool Metrics::EndSession()
{
if (writeStream.is_open())
{
WriteEvent(SessionEnd(TimeOffset()));
Clear();
writeStream.close();
return true;
}
Clear();
return false;
}
struct Metrics::PlayerHandleSet
{
static void Enable(PlayerHandle& handle, uint8_t id, uint8_t team)
{
handle.m_id = id;
handle.m_isValid = true;
handle.m_team = team;
}
};
void Metrics::SetMapData(float minX, float maxX, float minY, float maxY)
{
if (!writeStream.is_open())
return;
WriteEvent(MapData(minX, maxX, minY, maxY));
}
void Metrics::SetMapImage(uint8_t* ptr, uint32_t width, uint32_t height)
{
if (!writeStream.is_open())
return;
WriteEvent(MapImage(width, height));
WriteBinary(ptr, width * height * 4);
}
Metrics::PlayerHandle::PlayerHandle() : m_isValid(false), m_id(-1), m_team(-1), m_updateTime(0), m_alive(false), m_health(INT_MAX), m_mana(INT_MAX), m_maxHealth(INT_MAX), m_maxMana(INT_MAX), m_level(255), m_playerX(FLT_MAX), m_playerY(FLT_MAX)
{
}
void Metrics::PlayerHandle::OnPlayerSpawn(float playerX, float playerY)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (m_alive)
return;
m_alive = true;
m_playerX = playerX;
m_playerY = playerY;
WriteEvent(PlayerSpawn(TimeOffset(), m_id, playerX, playerY));
}
void Metrics::PlayerHandle::OnPlayerUpdate(float playerX, float playerY)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
// No need to write an event if the player hasnt moved
if (fabsf(playerX - m_playerX) < 0.01f && fabsf(playerY - m_playerY) < 0.01f)
return;
// Only update position 30 times per second
const uint32_t currentTime = CurrentTime();
if (currentTime - m_updateTime < 33)
return;
m_updateTime = currentTime;
m_playerX = playerX;
m_playerY = playerY;
WriteEvent(PlayerUpdate(TimeOffset(), m_id, playerX, playerY));
}
void Metrics::PlayerHandle::OnPlayerDie(uint8_t source)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
m_alive = false;
WriteEvent(PlayerDie(TimeOffset(), m_id, source));
}
void Metrics::PlayerHandle::OnPlayerCast(uint32_t ability)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
WriteEvent(PlayerCast(TimeOffset(), m_id, ability));
}
void Metrics::PlayerHandle::OnPlayerHealth(int32_t health)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
// No need to write an event if the player hasnt lost/gained health
if (m_health == health)
return;
m_health = health;
WriteEvent(PlayerHealth(TimeOffset(), m_id, health));
}
void Metrics::PlayerHandle::OnPlayerMana(int32_t mana)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
// No need to write an event if the player hasnt lost/gained mana
if (m_mana == mana)
return;
m_mana = mana;
WriteEvent(PlayerMana(TimeOffset(), m_id, mana));
}
void Metrics::PlayerHandle::OnPlayerMaxHealth(int32_t maxHealth)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
// No need to write an event if the player hasnt changed max health
if (m_maxHealth == maxHealth)
return;
m_maxHealth = maxHealth;
WriteEvent(PlayerMaxHealth(TimeOffset(), m_id, maxHealth));
}
void Metrics::PlayerHandle::OnPlayerMaxMana(int32_t maxMana)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
// No need to write an event if the player hasnt changed max mana
if (m_maxMana == maxMana)
return;
m_maxMana = maxMana;
WriteEvent(PlayerMaxMana(TimeOffset(), m_id, maxMana));
}
void Metrics::PlayerHandle::OnPlayerDealDamage(uint32_t ability, int32_t damage)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (!m_alive)
return;
WriteEvent(PlayerDealDamage(TimeOffset(), m_id, ability, damage));
}
void Metrics::PlayerHandle::OnPlayerLevel(uint8_t level)
{
if (!writeStream.is_open() || !m_isValid)
return;
if (m_level == level)
return;
m_level = level;
WriteEvent(PlayerLevel(TimeOffset(), m_id, level));
}
bool Metrics::PlayerHandle::IsValid() const
{
return m_isValid;
}
uint8_t Metrics::PlayerHandle::Id() const
{
return m_id;
}
uint8_t Metrics::PlayerHandle::Team() const
{
return m_team;
}
Metrics::PlayerHandle& Metrics::RegisterPlayer(const wstring& name, uint8_t team)
{
static PlayerHandle errorHandle;
if (!writeStream.is_open())
return errorHandle;
const uint8_t id = uint8_t(players.size() + 1);
PlayerHandle* newHandle = new PlayerHandle();
PlayerHandleSet::Enable(*newHandle, id, team);
players.emplace(id, newHandle);
wstring copy = name;
if (copy.size() > 128)
copy.resize(128);
else if (copy.empty())
copy = L"UNKNOWN PLAYER";
WriteEvent(PlayerName(id, (uint16_t)copy.size()));
WriteBinary((void*)copy.data(), copy.size() * sizeof(wstring::value_type));
WriteEvent(PlayerTeam(id, team));
return *newHandle;
}
void Metrics::RegisterAbility(uint32_t ability, const std::wstring& name)
{
if (!writeStream.is_open())
return;
wstring copy = name;
if (copy.size() > 128)
copy.resize(128);
else if (copy.empty())
copy = L"UNKNOWN ABILITY";
WriteEvent(AbilityName(ability, (uint16_t)copy.size()));
WriteBinary((void*)copy.data(), copy.size() * sizeof(wstring::value_type));
}
#endif

View File

@@ -0,0 +1,71 @@
#pragma once
#include <string>
#if WITH_EDITOR
#define UE_INCLUDE_METRICS 1
#define METRICS_EXPR(expr) expr
namespace Metrics
{
bool StartSession(const std::wstring& filePath);
bool EndSession();
void SetMapData(float minX, float maxX, float minY, float maxY);
void SetMapImage(uint8_t* ptr, uint32_t width, uint32_t height);
struct PlayerHandleSet;
struct PlayerHandle
{
public:
PlayerHandle();
void OnPlayerSpawn(float playerX, float playerY);
void OnPlayerUpdate(float playerX, float playerY);
void OnPlayerDie(uint8_t source);
void OnPlayerCast(uint32_t ability);
void OnPlayerHealth(int32_t health);
void OnPlayerMana(int32_t mana);
void OnPlayerMaxHealth(int32_t maxHealth);
void OnPlayerMaxMana(int32_t maxMana);
void OnPlayerDealDamage(uint32_t ability, int32_t damage);
void OnPlayerLevel(uint8_t level);
bool IsValid() const;
uint8_t Id() const;
uint8_t Team() const;
private:
PlayerHandle(const PlayerHandle& other) = delete;
PlayerHandle& operator=(const PlayerHandle& other) = delete;
friend struct PlayerHandleSet;
bool m_isValid;
uint8_t m_id;
uint8_t m_team;
uint32_t m_updateTime;
bool m_alive;
int32_t m_health;
int32_t m_mana;
int32_t m_maxHealth;
int32_t m_maxMana;
uint8_t m_level;
float m_playerX;
float m_playerY;
};
PlayerHandle& RegisterPlayer(const std::wstring& name, uint8_t team);
void RegisterAbility(uint32_t ability, const std::wstring& name);
}
#else
#define UE_INCLUDE_METRICS 0
#define METRICS_EXPR(expr)
#endif

View File

@@ -0,0 +1,137 @@
#ifndef _HEADER_TEA_CALLBACK
#define _HEADER_TEA_CALLBACK
#include <vector>
#include <type_traits>
namespace TeaLib
{
namespace Utility
{
#define NOVOIDFUNC(FuncRetVal) template<typename Test = ReturnValue> typename std::enable_if<!std::is_void<Test>::value, FuncRetVal>::type
template<typename ReturnValue, typename... Arguments>
class ReturnCallback
{
private:
// Typedef for comparing function pointers.
typedef ReturnValue(ReturnCallback::*CompareHandle)(Arguments...);
struct CallbackStructBase
{
public:
virtual ~CallbackStructBase() {};
virtual ReturnValue Call(Arguments...) = 0;
virtual bool Compare(ReturnValue(*a_CallbackFunction)(Arguments...))
{
return false;
};
virtual bool Compare(void* a_ClassInstance, CompareHandle a_CallbackFunction)
{
return false;
};
};
struct CallbackStruct : public CallbackStructBase
{
public:
virtual ReturnValue Call(Arguments... a_Arg)
{
return m_CallbackFunction(a_Arg...);
}
virtual bool Compare(ReturnValue(*a_CallbackFunction)(Arguments...))
{
return (a_CallbackFunction == m_CallbackFunction);
};
ReturnValue(*m_CallbackFunction)(Arguments...);
};
template<typename ClassType> struct ClassCallbackStruct : public CallbackStructBase
{
public:
virtual ReturnValue Call(Arguments... a_Arg)
{
return (m_ClassInstance->*m_CallbackFunction)(a_Arg...);
}
virtual bool Compare(void* a_ClassInstance, CompareHandle a_CallbackFunction)
{
CompareHandle compareHandle;
memcpy(&compareHandle, &m_CallbackFunction, sizeof(CompareHandle));
return ((a_ClassInstance == m_ClassInstance) && (a_CallbackFunction == compareHandle));
};
ClassType* m_ClassInstance;
ReturnValue(ClassType::*m_CallbackFunction)(Arguments...);
};
public:
virtual ~ReturnCallback()
{
for (int i = (int)m_CallbackFunctions.size() - 1; i >= 0; i--)
{
delete m_CallbackFunctions[i];
}
m_CallbackFunctions.clear();
}
void Call(Arguments... a_Arg)
{
for (auto it : m_CallbackFunctions)
{
it->Call(a_Arg...);
}
}
NOVOIDFUNC(void) Call(std::vector<ReturnValue>* a_ReturnValues, Arguments... a_Arg)
{
for (auto it : m_CallbackFunctions)
{
a_ReturnValues->push_back(it->Call(a_Arg...));
}
}
void Register(ReturnValue(*a_CallbackFunction)(Arguments...))
{
CallbackStruct* newCallback = new CallbackStruct();
newCallback->m_CallbackFunction = a_CallbackFunction;
m_CallbackFunctions.push_back(newCallback);
}
template<typename ClassType> void Register(ClassType* a_ClassInstance, ReturnValue(ClassType::*a_CallbackFunction)(Arguments...))
{
ClassCallbackStruct<ClassType>* newCallback = new ClassCallbackStruct<ClassType>();
newCallback->m_ClassInstance = a_ClassInstance;
newCallback->m_CallbackFunction = a_CallbackFunction;
m_CallbackFunctions.push_back(newCallback);
}
// Removes the first registered callback that matches the function.
void Deregister(ReturnValue(*a_CallbackFunction)(Arguments...))
{
for (unsigned int i = 0; i < m_CallbackFunctions.size(); i++)
{
if (m_CallbackFunctions[i]->Compare(a_CallbackFunction))
{
delete m_CallbackFunctions[i];
m_CallbackFunctions.erase(m_CallbackFunctions.begin() + i);
break;
}
}
}
// Removes the first registered callback that matches the class instance and the function.
template<typename ClassType> void Deregister(ClassType* a_ClassInstance, ReturnValue(ClassType::*a_CallbackFunction)(Arguments...))
{
CompareHandle compareHandle;
memcpy(&compareHandle, &a_CallbackFunction, sizeof(CompareHandle));
for (unsigned int i = 0; i < m_CallbackFunctions.size(); i++)
{
if (m_CallbackFunctions[i]->Compare(a_ClassInstance, compareHandle))
{
delete m_CallbackFunctions[i];
m_CallbackFunctions.erase(m_CallbackFunctions.begin() + i);
break;
}
}
}
private:
std::vector<CallbackStructBase*> m_CallbackFunctions;
};
// Alias template for callbacks that return void.
template<typename... Arguments>
using Callback = ReturnCallback<void, Arguments...>;
#undef NOVOIDFUNC
};
};
#endif

View File

@@ -0,0 +1,91 @@
#ifndef _HEADER_TEA_MATH_VECTOR2
#define _HEADER_TEA_MATH_VECTOR2
namespace TeaLib
{
namespace Math
{
template<typename T>
class Vector2
{
public:
Vector2() : x(0), y(0){};
Vector2(const T a_X, const T a_Y) : x(a_X), y(a_Y){};
Vector2& operator+=(const Vector2& rhs)
{
this->x += rhs.x;
this->y += rhs.y;
return *this;
}
Vector2& operator-=(const Vector2& rhs)
{
this->x -= rhs.x;
this->y -= rhs.y;
return *this;
}
Vector2& operator*=(const float& rhs)
{
this->x *= rhs;
this->y *= rhs;
return *this;
}
Vector2& operator/=(const float& rhs)
{
this->x /= rhs;
this->y /= rhs;
return *this;
}
Vector2 operator+(const Vector2& rhs)
{
Vector2 retVal;
retVal.x = this->x + rhs.x;
retVal.y = this->y + rhs.y;
return retVal;
}
Vector2 operator-(const Vector2& rhs)
{
Vector2 retVal;
retVal.x = this->x - rhs.x;
retVal.y = this->y - rhs.y;
return retVal;
}
Vector2 operator*(const float& rhs)
{
Vector2 retVal;
retVal.x = this->x * rhs;
retVal.y = this->y * rhs;
return retVal;
}
Vector2 operator/(const float& rhs)
{
Vector2 retVal;
retVal.x = this->x / rhs;
retVal.y = this->y / rhs;
return retVal;
}
bool operator==(const Vector2& rhs)
{
return ((this->x == rhs.x) && (this->y == rhs.y));
}
float LengthSquared()
{
return ((x*x) + (y*y));
}
float Length()
{
return sqrtf(LengthSquared());
}
T x, y;
};
typedef Vector2<float> Vector2f;
typedef Vector2<int> Vector2i;
typedef Vector2<unsigned int> Vector2u;
};
};
#endif

View File

@@ -0,0 +1,149 @@
#ifndef _HEADER_TEA_MATH_VECTOR3
#define _HEADER_TEA_MATH_VECTOR3
namespace TeaLib
{
namespace Math
{
template<typename T>
class Vector3
{
public:
Vector3() : x(0), y(0), z(0){};
Vector3(const T a_X, const T a_Y, const T a_Z) : x(a_X), y(a_Y), z(a_Z){};
Vector3& operator+=(const Vector3& rhs)
{
this->x += rhs.x;
this->y += rhs.y;
this->z += rhs.z;
return *this;
}
Vector3& operator-=(const Vector3& rhs)
{
this->x -= rhs.x;
this->y -= rhs.y;
this->z -= rhs.z;
return *this;
}
Vector3& operator*=(const float& rhs)
{
this->x *= rhs;
this->y *= rhs;
this->z *= rhs;
return *this;
}
Vector3& operator/=(const float& rhs)
{
this->x /= rhs;
this->y /= rhs;
this->z /= rhs;
return *this;
}
Vector3 operator+(const Vector3& rhs)
{
Vector3 retVal;
retVal.x = this->x + rhs.x;
retVal.y = this->y + rhs.y;
retVal.z = this->z + rhs.z;
return retVal;
}
Vector3 operator-(const Vector3& rhs)
{
Vector3 retVal;
retVal.x = this->x - rhs.x;
retVal.y = this->y - rhs.y;
retVal.z = this->z - rhs.z;
return retVal;
}
Vector3 operator*(const float& rhs)
{
Vector3 retVal;
retVal.x = this->x * rhs;
retVal.y = this->y * rhs;
retVal.z = this->z * rhs;
return retVal;
}
friend Vector3 operator*(const float& lhs, const Vector3& rhs)
{
Vector3 retVal;
retVal.x = rhs.x * lhs;
retVal.y = rhs.y * lhs;
retVal.z = rhs.z * lhs;
return retVal;
}
Vector3 operator/(const float& rhs)
{
Vector3 retVal;
retVal.x = this->x / rhs;
retVal.y = this->y / rhs;
retVal.z = this->z / rhs;
return retVal;
}
Vector3 operator-()
{
Vector3 retVal;
retVal.x = -this->x;
retVal.y = -this->y;
retVal.z = -this->z;
return retVal;
}
bool operator==(const Vector3& rhs)
{
return ((this->x == rhs.x) && (this->y == rhs.y) && (this->z == rhs.z));
}
float LengthSquared()
{
return ((x*x) + (y*y) + (z*z));
}
float Length()
{
return sqrtf(LengthSquared());
}
Vector3 Normalized()
{
return ((*this) / Length());
}
T x, y, z;
public:
static Vector3 Cross(Vector3& lhs, Vector3& rhs)
{
Vector3 retVal;
retVal.x = lhs.y * rhs.z - lhs.z * rhs.y;
retVal.y = lhs.z * rhs.x - lhs.x * rhs.z;
retVal.z = lhs.x * rhs.y - lhs.y * rhs.x;
return retVal;
}
static float Dot(Vector3& lhs, Vector3& rhs)
{
float retVal;
retVal = lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
return retVal;
}
static Vector3 Lerp(Vector3& a_Source, Vector3& a_Destination, float a_Scale)
{
Vector3 between = a_Destination - a_Source;
return a_Source + between * a_Scale;
}
};
typedef Vector3<float> Vector3f;
typedef Vector3<int> Vector3i;
typedef Vector3<unsigned int> Vector3u;
typedef Vector3<long> Vector3l;
};
};
#endif

146
Source/UnrealProject/External/append vendored Normal file
View File

@@ -0,0 +1,146 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2012-2015, Jan de Graaf (jan@jlib.nl) //
// //
// Permission to use, copy, modify, and/or distribute this software for any purpose with or //
// without fee is hereby granted, provided that the above copyright notice and this permission //
// notice appear in all copies. //
// //
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS //
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL //
// THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES //
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE //
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _JLIB_HEADER_APPEND
#define _JLIB_HEADER_APPEND
#include <string>
#include <sstream>
#include <iostream>
#include <type_traits>
namespace std
{
// Stream operator
template<typename char_type_t, typename input_type_t> inline basic_string<char_type_t>& operator<<(basic_string<char_type_t>& lhs, const input_type_t& rhs)
{
basic_ostringstream<char_type_t> stream;
return lhs.append(static_cast<basic_ostringstream<char_type_t>*>(&(stream << rhs))->str());
}
// Parsing numbers
template<typename char_type_t, typename input_type_t> inline bool operator>>(const basic_string<char_type_t>& lhs, input_type_t& rhs)
{
return (bool)(basic_istringstream<char_type_t>(lhs) >> rhs);
}
// Addition operators
// Utilizes enable_if to prevent colliding with string's existing operators
template<typename char_type_t, typename value_type> struct is_string_operand
{
static const bool value = std::is_same<typename std::decay<value_type>::type, char_type_t>::value || std::is_same<typename std::decay<value_type>::type, char_type_t*>::value || std::is_same<typename std::decay<value_type>::type, std::basic_string<char_type_t>>::value;
};
template<typename char_type_t, typename input_type_t> inline typename std::enable_if<!is_string_operand<char_type_t, input_type_t>::value, basic_string<char_type_t>&>::type operator+=(basic_string<char_type_t>& lhs, const input_type_t& rhs)
{
basic_ostringstream<char_type_t> stream;
return lhs.append(static_cast<basic_ostringstream<char_type_t>*>(&(stream << rhs))->str());
}
template<typename char_type_t, typename input_type_t> inline typename std::enable_if<!is_string_operand<char_type_t, input_type_t>::value, basic_string<char_type_t>>::type operator+(const basic_string<char_type_t>& lhs, const input_type_t& rhs)
{
basic_ostringstream<char_type_t> stream;
return basic_string<char_type_t>(lhs).append(static_cast<basic_ostringstream<char_type_t>*>(&(stream << rhs))->str());
}
}
template<typename to_type_t, typename from_type_t> inline std::basic_string<to_type_t> convert_cstring_type(const from_type_t* cstr)
{
static_assert(std::is_same<to_type_t, from_type_t>::value, "Invalid char overload");
return std::basic_string<to_type_t>(cstr);
}
template<> inline std::basic_string<char> convert_cstring_type(const wchar_t* wcstr)
{
std::string str;
size_t i = 0;
while (wcstr[i] != L'\0')
{
const uint32_t c = uint32_t(wcstr[i]);
str.resize(i + 1);
str[i++] = (c < 32 || c >= 126) ? '?' : char(c);
}
return str;
}
template<> inline std::basic_string<wchar_t> convert_cstring_type(const char* cstr)
{
std::wstring wstr;
size_t i = 0;
while (cstr[i] != L'\0')
{
const wchar_t c = wchar_t(cstr[i]);
wstr.resize(i + 1);
wstr[i++] = c;
}
return wstr;
}
template<typename to_type_t, typename from_type_t> inline std::basic_string<to_type_t> convert_string_type(const std::basic_string<from_type_t>& from_string)
{
static_assert(std::is_same<to_type_t, from_type_t>::value, "Invalid char overload");
return from_string;
}
template<> inline std::basic_string<char> convert_string_type(const std::basic_string<wchar_t>& wstr)
{
return convert_cstring_type<char, wchar_t>(wstr.data());
}
template<> inline std::basic_string<wchar_t> convert_string_type(const std::basic_string<char>& str)
{
return convert_cstring_type<wchar_t, char>(str.data());
}
namespace std
{
#ifndef _NOUNREAL
template<typename char_type_t> inline basic_string<char_type_t> operator+(const basic_string<char_type_t>& lhs, const class FString& rhs)
{
if (rhs.GetCharArray().GetData())
return basic_string<char_type_t>(lhs).append((convert_cstring_type<char_type_t, wchar_t>(rhs.GetCharArray().GetData())));
return basic_string<char_type_t>(lhs);
}
template<typename char_type_t> inline basic_string<char_type_t> operator+(const basic_string<char_type_t>& lhs, const class FName& rhs)
{
return basic_string<char_type_t>(lhs) + rhs.ToString();
}
template<typename char_type_t> inline basic_string<char_type_t> operator+(const basic_string<char_type_t>& lhs, const class FText& rhs)
{
return basic_string<char_type_t>(lhs) + rhs.ToString();
}
template<typename char_type_t> inline basic_string<char_type_t> operator+(const basic_string<char_type_t>& lhs, const struct FVector& rhs)
{
static const char __LogSpace = ' ';
static const char __FVectorOpen = '{';
static const char __FVectorEnd = '}';
static const char __LogSep = ',';
return lhs + (char_type_t)__FVectorOpen + rhs.X + (char_type_t)__LogSep + (char_type_t)__LogSpace + rhs.Y + (char_type_t)__LogSep + (char_type_t)__LogSpace + rhs.Z + (char_type_t)__FVectorEnd;
}
template<typename char_type_t> inline basic_string<char_type_t> operator+(const basic_string<char_type_t>& lhs, const struct FVector2D& rhs)
{
static const char __LogSpace = ' ';
static const char __FVectorOpen = '{';
static const char __FVectorEnd = '}';
static const char __LogSep = ',';
return lhs + (char_type_t)__FVectorOpen + rhs.X + (char_type_t)__LogSep + (char_type_t)__LogSpace + rhs.Y + (char_type_t)__FVectorEnd;
}
template<typename char_type_t> inline basic_string<char_type_t> operator+(const basic_string<char_type_t>& lhs, const struct FRotator& rhs)
{
static const char __LogSpace = ' ';
static const char __FVectorOpen = '{';
static const char __FVectorEnd = '}';
static const char __LogSep = ',';
return lhs + (char_type_t)__FVectorOpen + rhs.Pitch + (char_type_t)__LogSep + (char_type_t)__LogSpace + rhs.Yaw + (char_type_t)__LogSep + (char_type_t)__LogSpace + rhs.Roll + (char_type_t)__FVectorEnd;
}
#endif
}
#endif

106
Source/UnrealProject/External/timer vendored Normal file
View File

@@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2012-2015, Jan de Graaf (jan@jlib.nl) //
// //
// Permission to use, copy, modify, and/or distribute this software for any purpose with or //
// without fee is hereby granted, provided that the above copyright notice and this permission //
// notice appear in all copies. //
// //
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS //
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL //
// THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES //
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE //
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. //
// //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _JLIB_HEADER_TIMER
#define _JLIB_HEADER_TIMER
/*
Template chrono timer class
Wraps std chrono basic time functions in a timer object.
*/
#include <chrono>
namespace jlib
{
class timer
{
public:
// Constructors
timer() : m_start(std::chrono::high_resolution_clock::now()) {}
template<typename rep, typename period> timer(std::chrono::duration<rep, period> duration) : m_start(std::chrono::high_resolution_clock::now())
{
m_start -= duration;
}
template<typename rep, typename period> timer& operator=(std::chrono::duration<rep, period> duration)
{
restart();
m_start -= duration;
return *this;
}
inline void restart()
{
m_start = std::chrono::high_resolution_clock::now();
}
template<typename dur> inline dur duration() const
{
return std::chrono::duration_cast<dur>(std::chrono::high_resolution_clock::now() - m_start);
}
// Simplified get functions
inline std::chrono::nanoseconds::rep nanoseconds() const
{
return duration<std::chrono::nanoseconds>().count();
}
inline std::chrono::microseconds::rep microseconds() const
{
return duration<std::chrono::microseconds>().count();
}
inline std::chrono::milliseconds::rep milliseconds() const
{
return duration<std::chrono::milliseconds>().count();
}
inline std::chrono::seconds::rep seconds() const
{
return duration<std::chrono::seconds>().count();
}
inline std::chrono::minutes::rep minutes() const
{
return duration<std::chrono::minutes>().count();
}
inline std::chrono::hours::rep hours() const
{
return duration<std::chrono::hours>().count();
}
inline float seconds_float() const
{
return duration<std::chrono::duration<float>>().count();
}
// Addition or substraction
// Allows to add or substract time periods from the timer
template<typename rep, typename period> inline timer& operator+=(std::chrono::duration<rep, period> duration)
{
m_start -= duration;
return *this;
}
template<typename rep, typename period> inline timer& operator-=(std::chrono::duration<rep, period> duration)
{
m_start += duration;
return *this;
}
private:
std::chrono::high_resolution_clock::time_point m_start;
};
}
#endif