diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index fce32ecf..6a1fe0cb 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -31,17 +31,17 @@ jobs: # # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-22.04, windows-latest, macOS-latest] build_type: ${{ fromJSON(format('[{0}]', inputs.build_type || '"Debug","Release"')) }} c_compiler: [gcc, clang, cl] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - - os: ubuntu-latest + - os: ubuntu-22.04 c_compiler: gcc cpp_compiler: g++ - - os: ubuntu-latest + - os: ubuntu-22.04 c_compiler: clang cpp_compiler: clang++ - os: macOS-latest @@ -52,7 +52,7 @@ jobs: c_compiler: gcc - os: windows-latest c_compiler: clang - - os: ubuntu-latest + - os: ubuntu-22.04 c_compiler: cl - os: macOS-latest c_compiler: cl @@ -71,22 +71,8 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - name: Install Clang and Libraries - if: matrix.os == 'ubuntu-latest' && matrix.c_compiler == 'clang' - run: | - sudo apt-get update - sudo apt-get install -y clang libc++-dev libc++abi-dev - - - name: Set Clang 16 as Default - if: matrix.os == 'ubuntu-24.04' && matrix.c_compiler == 'clang' - run: | - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100 - sudo update-alternatives --set clang /usr/bin/clang-16 - sudo update-alternatives --set clang++ /usr/bin/clang++-16 - - name: Check Clang Settings - if: matrix.os == 'ubuntu-latest' && matrix.c_compiler == 'clang' + if: matrix.os == 'ubuntu-22.04' && matrix.c_compiler == 'clang' run: | clang --version clang++ --version diff --git a/CHANGELOG.md b/CHANGELOG.md index b26b7b13..b9f80700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +# 5.1.0 + +### Added + +- **Previous session time**: functionality to get the last session time + +### Fixed + +- **Playtime Metrics**: Fixed annotations for session time and total session time +- **MacOS**: GPU model detection + ## 5.0.0 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 868c6b1b..c4072dc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,8 @@ elseif(APPLE) "-framework Foundation" "-framework CoreServices" "-framework SystemConfiguration" + "-framework Metal" + "-framework MetalKit" ) create_source_groups(MACOS_SOURCES) diff --git a/include/GameAnalytics/GameAnalytics.h b/include/GameAnalytics/GameAnalytics.h index c1da53c0..31bbcb49 100644 --- a/include/GameAnalytics/GameAnalytics.h +++ b/include/GameAnalytics/GameAnalytics.h @@ -120,6 +120,7 @@ namespace gameanalytics static int64_t getElapsedSessionTime(); static int64_t getElapsedTimeFromAllSessions(); + static int64_t getElapsedTimeForPreviousSession(); // game state changes // will affect how session is started / ended diff --git a/source/gameanalytics/GACommon.h b/source/gameanalytics/GACommon.h index 37f533c6..c6890c34 100644 --- a/source/gameanalytics/GACommon.h +++ b/source/gameanalytics/GACommon.h @@ -85,7 +85,7 @@ namespace gameanalytics class GAState; } - constexpr const char* GA_VERSION_STR = "cpp 5.0.0"; + constexpr const char* GA_VERSION_STR = "cpp 5.1.0"; constexpr int MAX_CUSTOM_FIELDS_COUNT = 50; constexpr int MAX_CUSTOM_FIELDS_KEY_LENGTH = 64; diff --git a/source/gameanalytics/GALogger.h b/source/gameanalytics/GALogger.h index 7a1fb097..4f681a14 100644 --- a/source/gameanalytics/GALogger.h +++ b/source/gameanalytics/GALogger.h @@ -26,6 +26,11 @@ namespace gameanalytics return; } + if(logType == LogInfo && !getInstance().infoLogEnabled) + { + return; + } + std::string tag = getInstance().tag; tag += " :"; diff --git a/source/gameanalytics/GAState.cpp b/source/gameanalytics/GAState.cpp index ae3ba089..ff201230 100644 --- a/source/gameanalytics/GAState.cpp +++ b/source/gameanalytics/GAState.cpp @@ -426,6 +426,10 @@ namespace gameanalytics out["session_num"] = getInstance()._sessionNum; out["connection_type"] = device::GADevice::getConnectionType(); + // playtime metrics + out["current_session_length"] = getInstance().calculateSessionLength(); + out["lifetime_session_length"] = getInstance().getTotalSessionLength(); + // ---- OPTIONAL ---- // // A/B testing @@ -535,6 +539,11 @@ namespace gameanalytics return ""; } + int64_t GAState::getLastSessionLength() const + { + return _lastSessionTime; + } + int64_t GAState::getTotalSessionLength() const { return _totalElapsedSessionTime + calculateSessionLength(); @@ -586,10 +595,11 @@ namespace gameanalytics try { - std::string cachedSessionTime = utilities::getOptionalValue(state_dict, "total_session_time", "0"); + std::string cachedLastSessionTime = utilities::getOptionalValue(state_dict, "last_session_time", "0"); + std::string cachedTotalSessionTime = utilities::getOptionalValue(state_dict, "total_session_time", "0"); - _totalElapsedSessionTime = std::stoull(cachedSessionTime); - + _lastSessionTime = std::stoull(cachedLastSessionTime); + _totalElapsedSessionTime = std::stoull(cachedTotalSessionTime); } catch(const std::exception& e) { @@ -1090,8 +1100,11 @@ namespace gameanalytics void GAState::updateTotalSessionTime() { - int64_t totalSessionTime = getTotalSessionLength(); - _gaStore.setState("total_session_time", std::to_string(totalSessionTime)); + _lastSessionTime = calculateSessionLength(); + _totalElapsedSessionTime += _lastSessionTime; + + _gaStore.setState("last_session_time", std::to_string(_lastSessionTime)); + _gaStore.setState("total_session_time", std::to_string(_totalElapsedSessionTime)); } std::string GAState::getBuild() diff --git a/source/gameanalytics/GAState.h b/source/gameanalytics/GAState.h index 346a0b86..af504e32 100644 --- a/source/gameanalytics/GAState.h +++ b/source/gameanalytics/GAState.h @@ -169,6 +169,8 @@ namespace gameanalytics int64_t getTotalSessionLength() const; + int64_t getLastSessionLength() const; + void populateConfigurations(json& sdkConfig); json getRemoteConfigAnnotations(); @@ -229,6 +231,7 @@ namespace gameanalytics int64_t _sessionNum = 0; int64_t _transactionNum = 0; + int64_t _lastSessionTime = 0; int64_t _totalElapsedSessionTime = 0; std::chrono::high_resolution_clock::time_point _startTimepoint; diff --git a/source/gameanalytics/GAStore.cpp b/source/gameanalytics/GAStore.cpp index 69e463b5..2a2c5e09 100644 --- a/source/gameanalytics/GAStore.cpp +++ b/source/gameanalytics/GAStore.cpp @@ -206,30 +206,6 @@ namespace gameanalytics { return sqlDatabase; } - - bool GAStore::fixOldDatabase() - { - std::filesystem::path oldPath = dbPath; - std::filesystem::path filename = oldPath.filename(); - - oldPath = oldPath.parent_path() / ".." / filename; - - if(std::filesystem::exists(oldPath) && !std::filesystem::exists(dbPath)) - { - try - { - std::filesystem::rename(oldPath, dbPath); - } - catch(...) - { - return false; - } - - return true; - } - - return false; - } bool GAStore::initDatabaseLocation() { @@ -244,8 +220,6 @@ namespace gameanalytics { if(!std::filesystem::create_directory(p)) return false; - - fixOldDatabase(); } return true; diff --git a/source/gameanalytics/GAValidator.cpp b/source/gameanalytics/GAValidator.cpp index e6d2b573..f831836b 100644 --- a/source/gameanalytics/GAValidator.cpp +++ b/source/gameanalytics/GAValidator.cpp @@ -275,6 +275,9 @@ namespace gameanalytics bool validateProgressionString(std::string const& progression, ValidationResult& out, int progressionLvl) { + if(progressionLvl > 0 && progression.empty()) + return true; + if (!GAValidator::validateEventPartLength(progression, true)) { logging::GALogger::w("Validation fail - progression event - - progression0%d: Cannot be empty or above 64 characters. String: %s", progressionLvl + 1, progression.c_str()); @@ -458,17 +461,12 @@ namespace gameanalytics { constexpr uint32_t MAX_SIZE = 64u; - size_t size = eventPart.length(); - if (allowNull == true && size == 0) + if (eventPart.empty()) { - return true; - } - - if (size == 0) - { - return false; + return allowNull; } + size_t size = eventPart.length(); if (size > MAX_SIZE) { return false; diff --git a/source/gameanalytics/GameAnalytics.cpp b/source/gameanalytics/GameAnalytics.cpp index 76a8604f..8d524620 100644 --- a/source/gameanalytics/GameAnalytics.cpp +++ b/source/gameanalytics/GameAnalytics.cpp @@ -998,4 +998,9 @@ namespace gameanalytics return state::GAState::getInstance().calculateSessionLength(); } + int64_t GameAnalytics::getElapsedTimeForPreviousSession() + { + return state::GAState::getInstance().getLastSessionLength(); + } + } // namespace gameanalytics diff --git a/source/gameanalytics/GameAnalyticsExtern.cpp b/source/gameanalytics/GameAnalyticsExtern.cpp index cce12908..86989e77 100644 --- a/source/gameanalytics/GameAnalyticsExtern.cpp +++ b/source/gameanalytics/GameAnalyticsExtern.cpp @@ -2,38 +2,13 @@ #include "GameAnalytics/GameAnalytics.h" #include "GAUtilities.h" +#include "GameAnalyticsExtern.h" -void ga_string_alloc(GAString* s, unsigned int size) -{ - if(s) - { - s->str = (const char*)std::malloc(size); - if(s->str) - { - s->size = size; - std::memset(s->str, '\0', s->size); - } - } -} - -void ga_string_free(GAString* s) -{ - if(s) - { - if(s->str && s->size) - { - std::free(s->str); - s->str = NULL; - s->size = 0; - } - } -} - -StringVector makeStringVector(const char** arr, int size) +gameanalytics::StringVector makeStringVector(const char** arr, int size) { if(size > 0 && arr) { - StringVector v; + gameanalytics::StringVector v; v.reserve(size); for(int i = 0; i < size; ++i) @@ -48,67 +23,72 @@ StringVector makeStringVector(const char** arr, int size) return {}; } -GAString ga_string_fromString(std::string const& s) +GAErrorCode copyStringBuffer(std::string const& s, char* out, int* size) { - GAString gaStr = {}; - const unsigned int len = s.length() + 1; - ga_string_alloc(&gaStr, len); - - if(gaStr->str && gaStr->size) + if(size && (*size > 0)) { - std::memcpy(gaStr, s.data(), s.length()); - gaStr[len - 1] = '\0'; + if(out && (*size >= s.size())) + { + std::memcpy(out, s.data(), s.size()); + } + else + { + return EGABufferError; + } + + *size = static_cast(s.size()); + return EGANoError; } - return gaStr; + return EGAFailure; } -void configureAvailableCustomDimensions01(const char **customDimensions, int size) +void gameAnalytics_configureAvailableCustomDimensions01(const char **customDimensions, int size) { - StringVector values = makeStringVector(customDimensions, size); + gameanalytics::StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions01(values); } -void configureAvailableCustomDimensions02(const char **customDimensions, int size) +void gameAnalytics_configureAvailableCustomDimensions02(const char **customDimensions, int size) { - StringVector values = makeStringVector(customDimensions, size); + gameanalytics::StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions02(values); } -void configureAvailableCustomDimensions03(const char **customDimensions, int size) +void gameAnalytics_configureAvailableCustomDimensions03(const char **customDimensions, int size) { - StringVector values = makeStringVector(customDimensions, size); + gameanalytics::StringVector values = makeStringVector(customDimensions, size); gameanalytics::GameAnalytics::configureAvailableCustomDimensions03(values); } -void configureAvailableResourceCurrencies(const char** currencies, int size) +void gameAnalytics_configureAvailableResourceCurrencies(const char** currencies, int size) { - StringVector values = makeStringVector(currencies, size); + gameanalytics::StringVector values = makeStringVector(currencies, size); gameanalytics::GameAnalytics::configureAvailableResourceCurrencies(values); } -void configureAvailableResourceItemTypes(const char** resources, int size) +void gameAnalytics_configureAvailableResourceItemTypes(const char** resources, int size) { - StringVector values = makeStringVector(resources, size); + gameanalytics::StringVector values = makeStringVector(resources, size); gameanalytics::GameAnalytics::configureAvailableResourceItemTypes(values); } -void configureBuild(const char *build) +void gameAnalytics_configureBuild(const char *build) { gameanalytics::GameAnalytics::configureBuild(build); } -void configureWritablePath(const char *writablePath) +void gameAnalytics_configureWritablePath(const char *writablePath) { gameanalytics::GameAnalytics::configureWritablePath(writablePath); } -void configureDeviceModel(const char *deviceModel) +void gameAnalytics_configureDeviceModel(const char *deviceModel) { gameanalytics::GameAnalytics::configureDeviceModel(deviceModel); } -void configureDeviceManufacturer(const char *deviceManufacturer) +void gameAnalytics_configureDeviceManufacturer(const char *deviceManufacturer) { gameanalytics::GameAnalytics::configureDeviceManufacturer(deviceManufacturer); } @@ -116,177 +96,224 @@ void configureDeviceManufacturer(const char *deviceManufacturer) // the version of SDK code used in an engine. Used for sdk_version field. // !! if set then it will override the SdkWrapperVersion. // example "unity 4.6.9" -void configureSdkGameEngineVersion(const char *sdkGameEngineVersion) +void gameAnalytics_configureSdkGameEngineVersion(const char *sdkGameEngineVersion) { gameanalytics::GameAnalytics::configureSdkGameEngineVersion(sdkGameEngineVersion); } // the version of the game engine (if used and version is available) -void configureGameEngineVersion(const char *engineVersion) +void gameAnalytics_configureGameEngineVersion(const char *engineVersion) { gameanalytics::GameAnalytics::configureGameEngineVersion(engineVersion); } -void configureUserId(const char *uId) +void gameAnalytics_configureUserId(const char *uId) { gameanalytics::GameAnalytics::configureUserId(uId); } -void configureExternalUserId(const char* extId) +void gameAnalytics_configureExternalUserId(const char* extId) { gameanalytics::GameAnalytics::configureExternalUserId(extId); } // initialize - starting SDK (need configuration before starting) -void initialize(const char *gameKey, const char *gameSecret) +void gameAnalytics_initialize(const char *gameKey, const char *gameSecret) { gameanalytics::GameAnalytics::initialize(gameKey, gameSecret); } // add events -void addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addBusinessEvent(currency, (int)amount, itemType, itemId, cartType, fields, mergeFields); } -void addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addResourceEvent((gameanalytics::EGAResourceFlowType)flowType, currency, (float)amount, itemType, itemId, fields, mergeFields); } -void addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *fields, GAStatus mergeFields) { gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, fields, mergeFields); } -void addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, int score, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, (int)score, fields, mergeFields); + gameanalytics::GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, score, progression01, progression02, progression03, fields, mergeFields); } -void addDesignEvent(const char *eventId, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addDesignEvent(const char *eventId, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addDesignEvent(eventId, fields, mergeFields); + gameanalytics::GameAnalytics::addDesignEvent(eventId, fields, (bool)mergeFields); } -void addDesignEventWithValue(const char *eventId, double value, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addDesignEventWithValue(const char *eventId, double value, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addDesignEvent(eventId, value, fields, mergeFields); + gameanalytics::GameAnalytics::addDesignEvent(eventId, value, fields, (bool)mergeFields); } -void addErrorEvent(int severity, const char *message, const char *fields, GA_BOOL mergeFields) +void gameAnalytics_addErrorEvent(int severity, const char *message, const char *fields, GAStatus mergeFields) { - gameanalytics::GameAnalytics::addErrorEvent((gameanalytics::EGAErrorSeverity)severity, message, fields, mergeFields); + gameanalytics::GameAnalytics::addErrorEvent((gameanalytics::EGAErrorSeverity)severity, message, fields, (bool)mergeFields); } // set calls can be changed at any time (pre- and post-initialize) // some calls only work after a configure is called (setCustomDimension) -void setEnabledInfoLog(GA_BOOL flag) +void gameAnalytics_setEnabledInfoLog(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledInfoLog(flag); } -void setEnabledVerboseLog(GA_BOOL flag) +void gameAnalytics_setEnabledVerboseLog(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledVerboseLog(flag); } -void setEnabledManualSessionHandling(GA_BOOL flag) +void gameAnalytics_setEnabledManualSessionHandling(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledManualSessionHandling(flag); } -void setEnabledErrorReporting(GA_BOOL flag) +void gameAnalytics_setEnabledErrorReporting(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledErrorReporting(flag); } -void setEnabledEventSubmission(GA_BOOL flag) +void gameAnalytics_setEnabledEventSubmission(GAStatus flag) { gameanalytics::GameAnalytics::setEnabledEventSubmission(flag); } -void setCustomDimension01(const char *dimension01) +void gameAnalytics_setCustomDimension01(const char *dimension01) { gameanalytics::GameAnalytics::setCustomDimension01(dimension01); } -void setCustomDimension02(const char *dimension02) +void gameAnalytics_setCustomDimension02(const char *dimension02) { gameanalytics::GameAnalytics::setCustomDimension02(dimension02); } -void setCustomDimension03(const char *dimension03) +void gameAnalytics_setCustomDimension03(const char *dimension03) { gameanalytics::GameAnalytics::setCustomDimension03(dimension03); } -void setGlobalCustomEventFields(const char *customFields) +void gameAnalytics_setGlobalCustomEventFields(const char *customFields) { gameanalytics::GameAnalytics::setGlobalCustomEventFields(customFields); } -void gameAnalyticsStartSession() +void gameAnalytics_startSession() { gameanalytics::GameAnalytics::startSession(); } -void gameAnalyticsEndSession() +void gameAnalytics_endSession() { gameanalytics::GameAnalytics::endSession(); } // game state changes // will affect how session is started / ended -void onResume() +void gameAnalytics_onResume() { gameanalytics::GameAnalytics::onResume(); } -void onSuspend() +void gameAnalytics_onSuspend() { gameanalytics::GameAnalytics::onSuspend(); } -void onQuit() +void gameAnalytics_onQuit() { gameanalytics::GameAnalytics::onQuit(); } -GAString getRemoteConfigsValueAsString(const char *key) +GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsString(key); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GAString getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue) +GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue, char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsString(key, defaultValue); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GA_BOOL isRemoteConfigsReady() +GAStatus gameAnalytics_isRemoteConfigsReady() { - return gameanalytics::GameAnalytics::isRemoteConfigsReady() ? GA_TRUE : GA_FALSE; + return gameanalytics::GameAnalytics::isRemoteConfigsReady() ? EGAEnabled : EGADisabled; } -GAString getRemoteConfigsContentAsString() +GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsContentAsString(); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); +} + +GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(const char* key, char* out, int* size) +{ + std::string returnValue = gameanalytics::GameAnalytics::getRemoteConfigsValueAsJson(key); + return copyStringBuffer(returnValue, out, size); } -GAString getABTestingId() +GAErrorCode gameAnalytics_getABTestingId(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getABTestingId(); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); } -GAString getABTestingVariantId() +GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size) { std::string returnValue = gameanalytics::GameAnalytics::getABTestingVariantId(); - return ga_string_fromString(returnValue); + return copyStringBuffer(returnValue, out, size); +} + +long long gameAnalytics_getElapsedSessionTime() +{ + return gameanalytics::GameAnalytics::getElapsedSessionTime(); +} + +long long gameAnalytics_getElapsedTimeFromAllSessions() +{ + return gameanalytics::GameAnalytics::getElapsedTimeFromAllSessions(); +} + +long long gameAnalytics_getElapsedTimeForPreviousSession() +{ + return gameanalytics::GameAnalytics::getElapsedTimeForPreviousSession(); +} + +void gameAnalytics_enableSDKInitEvent(GAStatus status) +{ + return gameanalytics::GameAnalytics::enableSDKInitEvent(status); +} + +void gameAnalytics_enableMemoryHistogram(GAStatus status) +{ + return gameanalytics::GameAnalytics::enableMemoryHistogram(status); +} + +void gameAnalytics_enableFPSHistogram(GAFpsTracker tracker, GAStatus status) +{ + gameanalytics::FPSTracker fpsTracker = + [=]() -> float + { + return tracker(); + }; + + return gameanalytics::GameAnalytics::enableFPSHistogram(fpsTracker, status); +} + +void gameAnalytics_enableHardwareTracking(GAStatus status) +{ + return gameanalytics::GameAnalytics::enableHardwareTracking(status); } #endif diff --git a/source/gameanalytics/GameAnalyticsExtern.h b/source/gameanalytics/GameAnalyticsExtern.h index 24a4d4ad..0d60af7d 100644 --- a/source/gameanalytics/GameAnalyticsExtern.h +++ b/source/gameanalytics/GameAnalyticsExtern.h @@ -8,100 +8,103 @@ extern "C" { #if GA_SHARED_LIB #if defined(_WIN32) - #define EXPORT __declspec(dllexport) + #define GA_EXPORT __declspec(dllexport) #else - #define EXPORT __attribute__((visibility("default"))) + #define GA_EXPORT __attribute__((visibility("default"))) #endif #else - #define EXPORT + #define GA_EXPORT #endif -typedef struct GAString_ +enum GAErrorCode { - const char* str = 0; - unsigned int size = 0; + EGANoError = 0, + EGAFailure, + EGABufferError +}; -} GAString; - -#ifdef __cplusplus - #define GA_BOOL bool - #define GA_TRUE true - #define GA_FALSE false -#else - #define GA_BOOL char - #define GA_TRUE ((char)1) - #define GA_FALSE ((char)0) -#endif - -EXPORT void ga_string_alloc(GAString* s, unsigned int size); -EXPORT void ga_string_free(GAString* s); - -EXPORT void configureAvailableCustomDimensions01(const char **customDimensions, int size); -EXPORT void configureAvailableCustomDimensions02(const char **customDimensions, int size); -EXPORT void configureAvailableCustomDimensions03(const char **customDimensions, int size); -EXPORT void configureAvailableResourceCurrencies(const char **resourceCurrencies, int size); -EXPORT void configureAvailableResourceItemTypes(const char **resourceItemTypes, int size); -EXPORT void configureBuild(const char *build); -EXPORT void configureWritablePath(const char *writablePath); -EXPORT void configureDeviceModel(const char *deviceModel); -EXPORT void configureDeviceManufacturer(const char *deviceManufacturer); +enum GAStatus: char +{ + EGADisabled = 0, + EGAEnabled +}; + +typedef float(*GAFpsTracker)(void); + +GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions01(const char **customDimensions, int size); +GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions02(const char **customDimensions, int size); +GA_EXPORT void gameAnalytics_configureAvailableCustomDimensions03(const char **customDimensions, int size); +GA_EXPORT void gameAnalytics_configureAvailableResourceCurrencies(const char **resourceCurrencies, int size); +GA_EXPORT void gameAnalytics_configureAvailableResourceItemTypes(const char **resourceItemTypes, int size); +GA_EXPORT void gameAnalytics_configureBuild(const char *build); +GA_EXPORT void gameAnalytics_configureWritablePath(const char *writablePath); +GA_EXPORT void gameAnalytics_configureDeviceModel(const char *deviceModel); +GA_EXPORT void gameAnalytics_configureDeviceManufacturer(const char *deviceManufacturer); // the version of SDK code used in an engine. Used for sdk_version field. // !! if set then it will override the SdkWrapperVersion. // example "unity 4.6.9" -EXPORT void configureSdkGameEngineVersion(const char *sdkGameEngineVersion); +GA_EXPORT void gameAnalytics_configureSdkGameEngineVersion(const char *sdkGameEngineVersion); + // the version of the game engine (if used and version is available) -EXPORT void configureGameEngineVersion(const char *engineVersion); +GA_EXPORT void gameAnalytics_configureGameEngineVersion(const char *engineVersion); -EXPORT void configureUserId(const char *uId); +GA_EXPORT void gameAnalytics_configureUserId(const char *uId); -EXPORT void configureExternalUserId(const char* extId); +GA_EXPORT void gameAnalytics_configureExternalUserId(const char* extId); // initialize - starting SDK (need configuration before starting) -EXPORT void initialize(const char *gameKey, const char *gameSecret); +GA_EXPORT void gameAnalytics_initialize(const char *gameKey, const char *gameSecret); // add events -EXPORT void addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, double score, const char *customFields, GA_BOOL mergeFields); - -EXPORT void addDesignEvent(const char *eventId, const char *customFields, GA_BOOL mergeFields); -EXPORT void addDesignEventWithValue(const char *eventId, double value, const char *customFields, GA_BOOL mergeFields); -EXPORT void addErrorEvent(int severity, const char *message, const char *customFields, GA_BOOL mergeFields); +GA_EXPORT void gameAnalytics_addBusinessEvent(const char *currency, double amount, const char *itemType, const char *itemId, const char *cartType, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addResourceEvent(int flowType, const char *currency, double amount, const char *itemType, const char *itemId, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, int score, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addDesignEvent(const char *eventId, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addDesignEventWithValue(const char *eventId, double value, const char *customFields, GAStatus mergeFields); +GA_EXPORT void gameAnalytics_addErrorEvent(int severity, const char *message, const char *customFields, GAStatus mergeFields); // set calls can be changed at any time (pre- and post-initialize) // some calls only work after a configure is called (setCustomDimension) -EXPORT void setEnabledInfoLog(GA_BOOL flag); -EXPORT void setEnabledVerboseLog(GA_BOOL flag); -EXPORT void setEnabledManualSessionHandling(GA_BOOL flag); -EXPORT void setEnabledErrorReporting(GA_BOOL flag); -EXPORT void setEnabledEventSubmission(GA_BOOL flag); -EXPORT void setCustomDimension01(const char *dimension01); -EXPORT void setCustomDimension02(const char *dimension02); -EXPORT void setCustomDimension03(const char *dimension03); +GA_EXPORT void gameAnalytics_setEnabledInfoLog(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledVerboseLog(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledManualSessionHandling(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledErrorReporting(GAStatus flag); +GA_EXPORT void gameAnalytics_setEnabledEventSubmission(GAStatus flag); +GA_EXPORT void gameAnalytics_setCustomDimension01(const char *dimension01); +GA_EXPORT void gameAnalytics_setCustomDimension02(const char *dimension02); +GA_EXPORT void gameAnalytics_setCustomDimension03(const char *dimension03); -EXPORT void setGlobalCustomEventFields(const char *customFields); +GA_EXPORT void gameAnalytics_setGlobalCustomEventFields(const char *customFields); -EXPORT void gameAnalyticsStartSession(); -EXPORT void gameAnalyticsEndSession(); +GA_EXPORT void gameAnalytics_startSession(); +GA_EXPORT void gameAnalytics_endSession(); // game state changes // will affect how session is started / ended -EXPORT void onResume(); -EXPORT void onSuspend(); -EXPORT void onQuit(); +GA_EXPORT void gameAnalytics_onResume(); +GA_EXPORT void gameAnalytics_onSuspend(); +GA_EXPORT void gameAnalytics_onQuit(); + +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsString(const char *key, char* out, int* size); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue, char* out, int* bufferSize); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsValueAsJson(const char* key, char* out, int* size); + +GA_EXPORT GAStatus gameAnalytics_isRemoteConfigsReady(); +GA_EXPORT GAErrorCode gameAnalytics_getRemoteConfigsContentAsString(char* out, int* size); + +GA_EXPORT GAErrorCode gameAnalytics_getABTestingId(char* out, int* size); +GA_EXPORT GAErrorCode gameAnalytics_getABTestingVariantId(char* out, int* size); -EXPORT GAString getRemoteConfigsValueAsString(const char *key); -EXPORT GAString getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue); -EXPORT GA_BOOL isRemoteConfigsReady(); -EXPORT GA_BOOL getRemoteConfigsContentAsString(char* out, int size); +GA_EXPORT long long gameAnalytics_getElapsedSessionTime(); +GA_EXPORT long long gameAnalytics_getElapsedTimeFromAllSessions(); +GA_EXPORT long long gameAnalytics_getElapsedTimeForPreviousSession(); -EXPORT GAString getABTestingId(); -EXPORT GAString getABTestingVariantId(); +GA_EXPORT void gameAnalytics_enableSDKInitEvent(GAStatus status); +GA_EXPORT void gameAnalytics_enableMemoryHistogram(GAStatus status); +GA_EXPORT void gameAnalytics_enableFPSHistogram(GAFpsTracker tracker, GAStatus status); +GA_EXPORT void gameAnalytics_enableHardwareTracking(GAStatus status); #ifdef __cplusplus } diff --git a/source/gameanalytics/Platform/GADeviceOSX.h b/source/gameanalytics/Platform/GADeviceOSX.h index 0d63299f..5686019b 100644 --- a/source/gameanalytics/Platform/GADeviceOSX.h +++ b/source/gameanalytics/Platform/GADeviceOSX.h @@ -2,13 +2,15 @@ #define _GADEVICEOSX_H #include "GACommon.h" +#include #if IS_MAC -const char* getOSXVersion(); -const char* getConnectionType(); +std::string getOSXVersion(); +std::string getConnectionType(); int getNumCpuCores(); int64_t getTotalDeviceMemory(); +std::string getGPUName(); #endif diff --git a/source/gameanalytics/Platform/GADeviceOSX.mm b/source/gameanalytics/Platform/GADeviceOSX.mm index df799fc4..35443109 100644 --- a/source/gameanalytics/Platform/GADeviceOSX.mm +++ b/source/gameanalytics/Platform/GADeviceOSX.mm @@ -16,13 +16,17 @@ #import #import +#import + +#include + typedef struct { NSInteger majorVersion; NSInteger minorVersion; NSInteger patchVersion; } MyOperatingSystemVersion; -const char* getOSXVersion() +std::string getOSXVersion() { if (floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9) { @@ -60,7 +64,7 @@ SCNetworkReachabilityRef createReachabilityRef() return reachabilityRef; } -const char* getConnectionType() +std::string getConnectionType() { // todo: keep this in a class static SCNetworkReachabilityRef reachabilityRef = createReachabilityRef(); @@ -103,4 +107,17 @@ int64_t getTotalDeviceMemory() return (uint64_t)info.physicalMemory; } +std::string getGPUName() +{ + NSArray* devices = MTLCopyAllDevices(); + if(devices && [devices count]) + { + id device = devices[0]; + NSString* name = [device name]; + return [name UTF8String]; + } + + return ""; +} + #endif // IS_MAC diff --git a/source/gameanalytics/Platform/GAMacOS.cpp b/source/gameanalytics/Platform/GAMacOS.cpp index 1fba913b..72d2b983 100644 --- a/source/gameanalytics/Platform/GAMacOS.cpp +++ b/source/gameanalytics/Platform/GAMacOS.cpp @@ -17,7 +17,7 @@ static struct sigaction prevSigAction; std::string gameanalytics::GAPlatformMacOS::getOSVersion() { - const char* osxVersion = getOSXVersion(); + std::string osxVersion = getOSXVersion(); return getBuildPlatform() + " " + osxVersion; } @@ -193,7 +193,12 @@ std::string gameanalytics::GAPlatformMacOS::getCpuModel() const std::string gameanalytics::GAPlatformMacOS::getGpuModel() const { - return "Apple"; + if(_gpuModel.empty()) + { + _gpuModel = ::getGPUName(); + } + + return _gpuModel; } int gameanalytics::GAPlatformMacOS::getNumCpuCores() const diff --git a/source/gameanalytics/Platform/GAMacOS.h b/source/gameanalytics/Platform/GAMacOS.h index f8f529c3..82d377c3 100644 --- a/source/gameanalytics/Platform/GAMacOS.h +++ b/source/gameanalytics/Platform/GAMacOS.h @@ -38,6 +38,7 @@ namespace gameanalytics private: + mutable std::string _gpuModel; static void signalHandler(int sig, siginfo_t* info, void* context); }; }