Migration Guide: 6.6 to 6.7

We’re excited to bring you You.i Engine One version 6.7.0. As part of this release, there are some changes that may affect your application. For simplicity, the steps below are organized by the type of application you’re developing.

Affecting All Apps

Changes Required to CMakeLists.txt

Due to changes in the file structure for some build files, include paths in the application’s CMakeLists.txt are now loaded by a setup file.

As a result, you need to make the following changes to your app’s CMakeLists.txt file. You can find CMakeLists.txt in your app’s root directory or youi subdirectory.

Lines to remove

Remove the following lines from your app’s CMakeLists.txt file:

...
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${YouiEngine_DIR}/cmake)
include(Modules/YiUtility)
...
if(YI_BUILD_CLOUD_SERVER)
    find_path(YI_CLOUD_CMAKE_DIR
        Modules/YiCloudDeployment.cmake
        PATH_SUFFIXES
            cmake/cloud
            cloud/cmake
        PATHS ${YouiEngine_DIR}
    )
    mark_as_advanced(YI_CLOUD_CMAKE_DIR)
    list(INSERT CMAKE_MODULE_PATH 0 ${YI_CLOUD_CMAKE_DIR})
    include(Modules/YiCloud)
endif()
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
...
include(Modules/YiPlatformSourceFiles)
...
include(Modules/${YI_PLATFORM_LOWER}/YiConfigurePackagingForPlatform OPTIONAL)

Lines to add and move

Add the following line to your app’s CMakeLists.txt file, directly below the existing project() call:

include(${YouiEngine_DIR}/cmake/Modules/YiAppSetup.cmake)

Move the following line directly above the project() call:

option(YI_BUILD_CLOUD_SERVER "Build the application as a cloud server (for cloud-based Roku)" OFF)

Here’s what the three lines should look like:

option(YI_BUILD_CLOUD_SERVER "Build the application as a cloud server (for cloud-based Roku)" OFF)
project(${YI_PROJECT_NAME} LANGUAGES C CXX)
include(${YouiEngine_DIR}/cmake/Modules/YiAppSetup.cmake)

Change to the Optional Unity Build Feature

If you use Unity build features for your apps or for any app-side libraries and native modules, the functionality provided by cmake/Modules/YiConfigureUnityBuildFiles.cmake has changed.

We’ve removed the CMake functions yi_configure_unity_build_files() and yi_configure_unity_build_sets() and replaced them with a single function, yi_configure_unity_build(). This new function allows you to enable Unity builds for the entire target instead of for groups of files. This change leverages the built-in functionality of CMake, so it’s compatible with CMake’s Unity Build documentation.

The following example shows how to build eight files per compilation, with one skipped file due to its incompatibility with Unity builds:

    yi_configure_unity_build(TARGET ${PROJECT_NAME} BATCH_SIZE 8)

    set_source_files_properties(
        ${_SRC_DIR}/FileThatCannotBeBuiltWithUnity.cpp
    PROPERTIES 
        SKIP_UNITY_BUILD_INCLUSION ON
    )

C++ Applications

Changes to the castLabs and ExoPlayer Custom Players

Prior to release 6.7, when using a different custom player on each of your target platforms, you needed type-specific code to dynamically cast to each custom player before using its APIs.

In this release, we’ve added cross-platform functionality to CYIAbstractVideoPlayer.

To take advantage of this enhanced cross-platform functionality, you need to add the new CYIAbstractVideoPlayer interfaces to your custom player by inheriting from the corresponding public interface and implementing the mandatory APIs that are part of these interfaces. You also need to override the corresponding private override function to provide access to the interface implementation.

New CYIAbstractVideoPlayer API Public Interface Private Override Function
NetworkTimeoutInterface *GetNetworkTimeoutInterface() public CYIAbstractVideoPlayer::NetworkTimeoutInterface virtual const NetworkTimeoutInterface *GetNetworkTimeoutInterface_() const
LiveSessionInterface *GetLiveSessionInterface() public CYIAbstractVideoPlayer::LiveSessionInterface virtual const LiveSessionInterface *GetLiveSessionInterface_() const
AdaptiveResolutionInterface *GetAdaptiveResolutionInterface() public CYIAbstractVideoPlayer::AdaptiveResolutionInterface virtual const AdaptiveResolutionInterface *GetAdaptiveResolutionInterface_()

As a result of this feature, you must make some code changes if you’re using the castLabs and ExoPlayer custom players:

  • You must modify all dynamic cast-based code.
  • You must replace some player-specific APIs with CYIAbstractVideoPlayer interface APIs.

Migrate all dynamic cast-based code

The following snippets show you the basic method for migrating from specific custom player APIs to the new CYIAbstractVideoPlayer interfaces, using the castLabs player as an example.

Prior to 6.7
#include <player/YiAbstractVideoPlayer.h>
#include <player/YiCastLabsVideoPlayer.h>

CYIAbstractVideoPlayer *m_pPlayer;
CYICastLabsVideoPlayer *pCastLabsPlayer = YiDynamicCast<CYICastLabsVideoPlayer>(m_pPlayer);
if (pCastLabsPlayer)
{
   pCastLabsPlayer->SetMaxResolution(m_maxResolution);
}
Now in 6.7

You no longer need to include the custom player’s header or use YiDynamicCast.

#include <player/YiAbstractVideoPlayer.h>

CYIAbstractVideoPlayer *m_pPlayer;
auto *pInterface = m_pPlayer->GetAdaptiveResolutionInterface();
if (pInterface)
{
   pInterface->SetMaxResolution(glm::ivec2(640, 480));
}

Removed castLabs player APIs

If you’re using the castLabs player on PS4, you must replace the following CYICastLabsVideoPlayer APIs with CYIAbstractVideoPlayer interface APIs.

CYICastLabsVideoPlayer API New Interface New Interface API
void SetMinimumBufferTime(uint64_t) CYIAbstractVideoPlayer::BufferingInterface BufferLength(std::chrono::milliseconds, std::chrono::milliseconds) (accepts min/max values)
void SetMaximumBufferTime(uint64_t) CYIAbstractVideoPlayer::BufferingInterface BufferLength(std::chrono::milliseconds, std::chrono::milliseconds) (accepts min/max values)
SetMaxResolution CYIAbstractVideoPlayer::AdaptiveResolutionInterface SetMaxResolution (same name)
void SetLiveDelayTime(uint64_t) CYIAbstractVideoPlayer::LiveSessionInterface virtual void SetLivePresentationDelay(std::chrono::milliseconds)
uint64_t GetRequestConnectTimeout() CYIAbstractVideoPlayer::NetworkTimeoutInterface virtual void GetConnectionTimeout(std::chrono::milliseconds)
void SetRequestConnectTimeout(uint64_t) CYIAbstractVideoPlayer::NetworkTimeoutInterface virtual void SetConnectionTimeout(std::chrono::milliseconds)
uint64_t GetRequestReadTimeout() CYIAbstractVideoPlayer::NetworkTimeoutInterface virtual void GetRequestTimeout(std::chrono::milliseconds)
void SetRequestReadTimeout(uint64_t) CYIAbstractVideoPlayer::NetworkTimeoutInterface virtual void SetRequestTimeout(std::chrono::milliseconds)
Prior to 6.7
   // Example using `SetMinimumBufferTime` and `SetMaximumBufferTime`
   SetMinimumBufferTime(2000);
   SetMaximumBufferTime(5000);

   // Example using `SetRequestConnectTimeout`
   SetRequestConnectTimeout(60000);
Now in 6.7
   // Example using `SetBufferLength`
   SetBufferLength(CYIAbstractVideoPlayer::BufferLength(std::chrono::milliseconds(2000), std::chrono::milliseconds(5000)));

   // Example using `SetConnectionTimeout`
   SetConnectionTimeout(std::chrono::milliseconds{60000});

Removed ExoPlayer API

If you’re using the ExoPlayer custom player on Android, you must replace the following CYIExoPlayerVideoPlayer API with a CYIAbstractVideoPlayer interface API.

CYIExoPlayerVideoPlayer API New Interface New Interface API
SetLivePresentationDelay CYIAbstractVideoPlayer::LiveSessionInterface SetLivePresentationDelay (same name)
Prior to 6.7
   void SetLivePresentationDelay(uint64_t presentationDelayMs, bool overridesManifest);
Now in 6.7
   virtual void SetLivePresentationDelay(std::chrono::milliseconds liveDelay);

Other C++ Breaking Changes

Changes to application paths

We’ve standardized paths within You.i Engine One to not end with a trailing directory separator. This follows the Unix convention of paths being “files”, and thus not ending with directory separators. As a result, the paths returned by the following functions no longer end with a directory separator by default:

  • CYIApp::GetAssetsPath()
  • CYIApp::GetCachePath()
  • CYIApp::GetDataPath()
  • CYIApp::GetExternalPath()

Setters support paths both with and without a trailing directory separator.

If your app makes use of paths returned by CYIApp, you must update these implementations. You can use the CYIFile::Join utility to facilitate building paths. That function adds directory separators as needed and supports an arbitrary number of arguments.

Prior to 6.7
CYIString filename = pApp->GetAssetsPath() + "limericks/bernard_shaw.txt";
CYIString contents = CYIFile::ReadAsString(filename);
Now in 6.7
CYIString filename = CYIFile::Join(pApp->GetAssetsPath(), "limericks", "bernard_shaw.txt");
CYIString contents = CYIFile::ReadAsString(filename);

Changes to CYIApp::HandleActionInputs() API parameters

We have aligned the two CYIApp interfaces that accept events into You.i Engine One to work directly with the appropriate event objects (CYIActionEvent and CYIKeyEvent). With this change, CYIApp::HandleActionInputs conforms to the style used by CYIApp::HandleKeyInputs. To summarize, the following are now aligned to accept a properly constructed event object:

  • void HandleKeyInputs(const CYIKeyEvent &keyEvent);
  • void HandleActionInputs(const CYIActionEvent &actionEvent);

To assist with this, we’ve expanded the set of constructors available for CYIActionEvent objects:

  • CYIActionEvent(CYIEvent::Type eventType, int32_t x, int32_t y, uint8_t pointerID = 0);
  • CYIActionEvent(CYIEvent::Type eventType, int32_t x, int32_t y, ButtonType button, uint8_t pointerID = 0, bool hover = false);
  • CYIActionEvent(int32_t x, int32_t y, int32_t wheelDelta, CYIEvent::Type eventType = CYIEvent::Type::ActionWheel);
Prior to 6.7
CYIApp *pApp;

// 1. For events that use ButtonType or the verbose API:
// void CYIApp::HandleActionInputs(int32_t x, int32_t y, int32_t wheelDelta, CYIActionEvent::ButtonType button, CYIEvent::Type eventType, uint8_t pointerID = 0, bool hover = false);
pApp->HandleActionInputs(x, y, 0, CYIActionEvent::ButtonType::None, CYIEvent::Type::ActionMove, 0, true);

// 2. For events that use the mouse wheel parameter in the verbose API:
// void CYIApp::HandleActionInputs(int32_t x, int32_t y, int32_t wheelDelta, CYIActionEvent::ButtonType button, CYIEvent::Type eventType, uint8_t pointerID = 0, bool hover = false);
pApp->HandleActionInputs(x, y, yOffset, CYIActionEvent::ButtonType::None, CYIEvent::Type::ActionWheel, 0, true);

// 3. For events that use a simpler pointer-based API, or for single touch events that do not require the CYIActionEvent::ButtonType parameter:
// void HandleActionInputs(int32_t x, int32_t y, CYIEvent::Type eventType, uint8_t pointerID = 0, bool hover = false);
pApp->HandleActionInputs(x, y, CYIEvent::Type::ActionDown));
Now in 6.7
CYIApp *pApp;

// 1. For events that use ButtonType or the verbose API, use the corresponding CYIActionEvent constructor :
// CYIActionEvent::CYIActionEvent(CYIEvent::Type eventType, int32_t x, int32_t y, ButtonType button, uint8_t pointerID = 0, bool hover = false);
pApp->HandleActionInputs(CYIActionEvent(CYIEvent::Type::ActionMove, x, y, CYIActionEvent::ButtonType::None, 0, true));

// 2. For events that use the mouse wheel parameter in the verbose API, use the CYIActionEvent constructor that accepts the mouse wheel delta:
// CYIActionEvent(int32_t x, int32_t y, int32_t wheelDelta, CYIEvent::Type eventType = CYIEvent::Type::ActionWheel);
pApp->HandleActionInputs(CYIActionEvent(x, y, yOffset));

// 3. For events that use a simpler pointer-based API, or for single touch events that do not require the CYIActionEvent::ButtonType parameter:
// CYIActionEvent(CYIEvent::Type eventType, int32_t x, int32_t y, uint8_t pointerID = 0);
pApp->HandleActionInputs(CYIActionEvent(CYIEvent::Type::ActionDown, x, y));

Multi-button support through bitmasking added to CYIActionEvent

CYIActionEvent, a class used to report mouse events, previously reported only one pressed mouse button at a time. If the right mouse button was pressed, it would take precedence over the middle mouse button, and if the left mouse button was pressed, it would take precedence over both the right and middle mouse buttons. Information about the other mouse buttons within the event was lost.

We have added the ability for CYIActionEvent to report multiple mouse buttons in one event through bitmasking. For example, if both the left and right mouse buttons are held down when the mouse moves, a movement CYIActionEvent will be reported with m_button set to be the bitwise AND result of CYIActionEvent::ButtonType::Left and CYIActionEvent::ButtonType::Right.

If your app listens for instances of CYIEvent and checks the button type to decide how to react, you may need to update your app logic to correctly handle bitmasked button types.

Prior to 6.7

Code like the following, which checks for equality between CYIEvent::m_button and one of the enum values in CYIActionEvent::ButtonType, is no longer correct.

if (pActionEvent->m_button == CYIActionEvent::ButtonType::Left)
{
    // Logic for when the left mouse button is pressed.
}

if (pActionEvent->m_button == CYIActionEvent::ButtonType::Right)
{
    // Logic for when the right mouse button is pressed.
}

if (pActionEvent->m_button == CYIActionEvent::ButtonType::Middle)
{
    // Logic for when the middle mouse button is pressed.
}

if (pActionEvent->m_button == CYIActionEvent::ButtonType::None)
{
    // Logic for when no mouse buttons are pressed.
}

This also includes checking the button type in a switch statement.

switch (pActionEvent->m_button)
{
    case CYIActionEvent::ButtonType::Left:
        // Logic for when the left mouse button is pressed.
        break;
    case CYIActionEvent::ButtonType::Right:
        // Logic for when the right mouse button is pressed.
        break;
    case CYIActionEvent::ButtonType::Middle:
        // Logic for when the middle mouse button is pressed.
        break;
    case CYIActionEvent::ButtonType::None:
        // Logic for when no mouse buttons are pressed.
        break;
}
Now in 6.7

Replace any checks for the button type of a CYIActionEvent with a check for inclusion with the bitmasked button type.

if (Any(pActionEvent->m_button & CYIActionEvent::ButtonType::Left))
{
    // Logic for when the left mouse button is pressed.
}

if (Any(pActionEvent->m_button & CYIActionEvent::ButtonType::Right))
{
    // Logic for when the right mouse button is pressed.
}

if (Any(pActionEvent->m_button & CYIActionEvent::ButtonType::Middle))
{
    // Logic for when the middle mouse button is pressed.
}

if (pActionEvent->m_button == CYIActionEvent::ButtonType::None)
{
    // Logic for when no mouse buttons are pressed.
}

Changes to platform bridges initialization

In You.i Engine One 6.7, the initialization of platform bridges has been modified. As a result, it is now necessary to call CYIBridgeConfiguration::AssignBridgeFactories() prior to app initialization. If your app uses a custom main file (such as mainDefault.cpp), it must be modified to call that function.

Prior to 6.7
int main(int argc, char *argv[])
{
    CYILogger::Initialize();

    ...
}
Now in 6.7
#include <platform/YiBridgeConfiguration.h>

int main(int argc, char *argv[])
{
    CYILogger::Initialize();

    CYIBridgeConfiguration::AssignBridgeFactories();

    ...
}

Removal of GetDeviceUID for Android DeviceInformationBridge

In You.i Engine One 6.7, the GetDeviceUID API has been removed from the Android DeviceInformationBridge. This was due to the deprecation of the getDeviceId API in Android SDK API 29 and higher. GetDeviceUID now returns an empty string. We encourage you to use the Advertising ID in place of the Device ID.

Prior to 6.7
#include <platform/YiDeviceBridgeLocator.h>
#include <platform/YiDeviceInformationBridge.h>

CYIString deviceUID = CYIDeviceBridgeLocator::GetDeviceInformationBridge()->GetDeviceUID();
Now in 6.7
#include <platform/YiDeviceBridgeLocator.h>
#include <platform/YiAdvertisingInformationBridge.h>

CYIString advertisingId;
CYIDeviceBridgeLocator::GetAdvertisingInformationBridge()->RequestAdvertisingId([this](const CYIString &advertisingIdCallback) {
    advertisingId = advertisingIdCallback;
});

Changes to const correctness of CYIAbstractVideoPlayer interface getters

We’ve updated APIs that were defined as const APIs but returned non-const interface pointers. We now provide both a const and non-const version of these APIs. You shouldn’t have to update your code for this change, unless you were incorrectly using a non-const pointer returned from a const player object.

Removal of CYIFileWatcher and CYIPreferences

As part of API simplification efforts, the CYIFileWatcher and CYIPreferences classes have been removed.

CYIFileWatcher had previously been deprecated and was available on only some of the You.i Engine supported platforms. CYIPreferences was a simple key-value pair container that could read values from a file or write values to a file. The engine does not provide a replacement for either of the removed classes.