214 lines
5.4 KiB
C++
214 lines
5.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MosisPhoneComponent.h"
|
|
#include "MosisSDK.h"
|
|
#include "MosisPhoneTexture.h"
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
#include "RenderingThread.h"
|
|
|
|
#if PLATFORM_ANDROID
|
|
#include "MosisClient.h"
|
|
#endif
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogMosisPhone, Log, All);
|
|
|
|
UMosisPhoneComponent::UMosisPhoneComponent()
|
|
{
|
|
PrimaryComponentTick.bCanEverTick = true;
|
|
PrimaryComponentTick.bStartWithTickEnabled = true;
|
|
}
|
|
|
|
void UMosisPhoneComponent::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
UE_LOG(LogMosisPhone, Log, TEXT("BeginPlay"));
|
|
|
|
#if PLATFORM_ANDROID
|
|
// Get the client and set up callbacks
|
|
auto Client = FMosisSDKModule::GetClient();
|
|
if (Client)
|
|
{
|
|
// Use weak pointer to prevent dangling references in callbacks
|
|
TWeakObjectPtr<UMosisPhoneComponent> WeakThis(this);
|
|
|
|
// Set up callbacks (these run on binder thread)
|
|
Client->SetBufferCallback([WeakThis](AHardwareBuffer* buffer) {
|
|
if (WeakThis.IsValid())
|
|
{
|
|
WeakThis->bNeedsTextureCreate.Store(true);
|
|
}
|
|
});
|
|
|
|
Client->SetFrameCallback([WeakThis]() {
|
|
if (WeakThis.IsValid())
|
|
{
|
|
WeakThis->bPendingTextureUpdate.Store(true);
|
|
}
|
|
});
|
|
|
|
UE_LOG(LogMosisPhone, Log, TEXT("BeginPlay: Callbacks registered"));
|
|
|
|
// Check if buffer is already available (we may have missed the callback)
|
|
if (Client->GetHardwareBuffer() != nullptr)
|
|
{
|
|
UE_LOG(LogMosisPhone, Log, TEXT("BeginPlay: Buffer already available, triggering update"));
|
|
bNeedsTextureCreate.Store(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogMosisPhone, Warning, TEXT("BeginPlay: MosisClient not available yet"));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void UMosisPhoneComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
UE_LOG(LogMosisPhone, Log, TEXT("EndPlay"));
|
|
|
|
#if PLATFORM_ANDROID
|
|
// Clear callbacks
|
|
auto Client = FMosisSDKModule::GetClient();
|
|
if (Client)
|
|
{
|
|
Client->SetBufferCallback(nullptr);
|
|
Client->SetFrameCallback(nullptr);
|
|
}
|
|
#endif
|
|
|
|
// Release texture
|
|
PhoneTexture = nullptr;
|
|
|
|
Super::EndPlay(EndPlayReason);
|
|
}
|
|
|
|
void UMosisPhoneComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
|
{
|
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
|
|
|
#if PLATFORM_ANDROID
|
|
// Check if we need to create texture from new buffer
|
|
if (bNeedsTextureCreate.Exchange(false))
|
|
{
|
|
OnBufferAvailable();
|
|
}
|
|
|
|
// Check if we need to update texture for new frame
|
|
if (bPendingTextureUpdate.Exchange(false) && PhoneTexture)
|
|
{
|
|
OnFrameAvailable();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool UMosisPhoneComponent::IsConnected() const
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
auto Client = FMosisSDKModule::GetClient();
|
|
return Client && Client->IsInitialized() && Client->GetHardwareBuffer() != nullptr;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void UMosisPhoneComponent::SendTouch(FVector2D NormalizedUV, EMosisTouchType TouchType)
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
auto Client = FMosisSDKModule::GetClient();
|
|
if (!Client)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float X = FMath::Clamp(NormalizedUV.X, 0.0f, 1.0f);
|
|
float Y = FMath::Clamp(NormalizedUV.Y, 0.0f, 1.0f);
|
|
|
|
switch (TouchType)
|
|
{
|
|
case EMosisTouchType::Down:
|
|
Client->SendTouchDown(X, Y);
|
|
break;
|
|
case EMosisTouchType::Move:
|
|
Client->SendTouchMove(X, Y);
|
|
break;
|
|
case EMosisTouchType::Up:
|
|
Client->SendTouchUp(X, Y);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void UMosisPhoneComponent::OnBufferAvailable()
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
auto Client = FMosisSDKModule::GetClient();
|
|
if (!Client)
|
|
{
|
|
return;
|
|
}
|
|
|
|
AHardwareBuffer* Buffer = Client->GetHardwareBuffer();
|
|
if (!Buffer)
|
|
{
|
|
UE_LOG(LogMosisPhone, Warning, TEXT("OnBufferAvailable: No buffer"));
|
|
return;
|
|
}
|
|
|
|
// Get buffer dimensions
|
|
AHardwareBuffer_Desc Desc{};
|
|
AHardwareBuffer_describe(Buffer, &Desc);
|
|
ScreenWidth = Desc.width;
|
|
ScreenHeight = Desc.height;
|
|
|
|
UE_LOG(LogMosisPhone, Log, TEXT("OnBufferAvailable: %dx%d"), ScreenWidth, ScreenHeight);
|
|
|
|
// Create phone texture if needed
|
|
if (!PhoneTexture)
|
|
{
|
|
PhoneTexture = NewObject<UMosisPhoneTexture>(this);
|
|
PhoneTexture->Initialize(ScreenWidth, ScreenHeight);
|
|
UE_LOG(LogMosisPhone, Log, TEXT("OnBufferAvailable: Created phone texture"));
|
|
}
|
|
|
|
// Import the hardware buffer for GPU-accelerated updates
|
|
PhoneTexture->ImportHardwareBuffer(Buffer);
|
|
|
|
// Update material if set
|
|
if (PhoneMaterial && PhoneTexture)
|
|
{
|
|
PhoneMaterial->SetTextureParameterValue(TextureParameterName, PhoneTexture);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void UMosisPhoneComponent::OnFrameAvailable()
|
|
{
|
|
#if PLATFORM_ANDROID
|
|
if (!PhoneTexture || !PhoneTexture->HasImportedBuffer())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Perform GPU-to-GPU copy from imported hardware buffer
|
|
PhoneTexture->CopyFromImportedBuffer();
|
|
|
|
// Log occasionally to avoid spam
|
|
static int32 FrameCount = 0;
|
|
if (++FrameCount % 60 == 0)
|
|
{
|
|
UE_LOG(LogMosisPhone, Log, TEXT("OnFrameAvailable: Frame %d (GPU copy)"), FrameCount);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void UMosisPhoneComponent::UpdateTextureOnRenderThread()
|
|
{
|
|
// No longer needed - handled by UMosisPhoneTexture
|
|
}
|
|
|
|
UTexture* UMosisPhoneComponent::GetPhoneTexture() const
|
|
{
|
|
return PhoneTexture;
|
|
}
|