147 lines
4.2 KiB
C++
147 lines
4.2 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "MosisPhoneActor.h"
|
|
#include "Components/StaticMeshComponent.h"
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "UObject/ConstructorHelpers.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogMosisPhoneActor, Log, All);
|
|
|
|
AMosisPhoneActor::AMosisPhoneActor()
|
|
{
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
PrimaryActorTick.bStartWithTickEnabled = true;
|
|
|
|
// Create phone mesh component
|
|
PhoneMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PhoneMesh"));
|
|
RootComponent = PhoneMesh;
|
|
|
|
// Load the default plane mesh
|
|
static ConstructorHelpers::FObjectFinder<UStaticMesh> PlaneMeshFinder(
|
|
TEXT("/Engine/BasicShapes/Plane.Plane"));
|
|
if (PlaneMeshFinder.Succeeded())
|
|
{
|
|
PhoneMesh->SetStaticMesh(PlaneMeshFinder.Object);
|
|
}
|
|
|
|
// Load the phone screen material
|
|
static ConstructorHelpers::FObjectFinder<UMaterialInterface> PhoneMaterialFinder(
|
|
TEXT("/Game/Mosis/Materials/M_PhoneScreen.M_PhoneScreen"));
|
|
if (PhoneMaterialFinder.Succeeded())
|
|
{
|
|
BaseMaterial = PhoneMaterialFinder.Object;
|
|
}
|
|
|
|
// Create phone component
|
|
PhoneComponent = CreateDefaultSubobject<UMosisPhoneComponent>(TEXT("PhoneComponent"));
|
|
}
|
|
|
|
void AMosisPhoneActor::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
UE_LOG(LogMosisPhoneActor, Log, TEXT("BeginPlay"));
|
|
|
|
// Scale mesh to match phone screen size
|
|
// The default plane is 100x100 units, so scale accordingly
|
|
if (PhoneMesh)
|
|
{
|
|
float ScaleX = ScreenSizeWorld.X / 100.0f;
|
|
float ScaleY = ScreenSizeWorld.Y / 100.0f;
|
|
PhoneMesh->SetRelativeScale3D(FVector(ScaleX, ScaleY, 1.0f));
|
|
|
|
// Update screen bounds based on scaled size
|
|
float HalfWidth = ScreenSizeWorld.X / 2.0f;
|
|
float HalfHeight = ScreenSizeWorld.Y / 2.0f;
|
|
ScreenBoundsLocal = FVector4(-HalfWidth, -HalfHeight, HalfWidth, HalfHeight);
|
|
}
|
|
|
|
// Create dynamic material for the screen
|
|
if (PhoneMesh)
|
|
{
|
|
UMaterialInterface* MaterialToUse = BaseMaterial;
|
|
|
|
// If no base material set, use the mesh's existing material
|
|
if (!MaterialToUse)
|
|
{
|
|
MaterialToUse = PhoneMesh->GetMaterial(0);
|
|
}
|
|
|
|
if (MaterialToUse)
|
|
{
|
|
ScreenMaterial = UMaterialInstanceDynamic::Create(MaterialToUse, this);
|
|
PhoneMesh->SetMaterial(0, ScreenMaterial);
|
|
|
|
// Set it on the phone component
|
|
if (PhoneComponent)
|
|
{
|
|
PhoneComponent->PhoneMaterial = ScreenMaterial;
|
|
}
|
|
|
|
UE_LOG(LogMosisPhoneActor, Log, TEXT("BeginPlay: Created dynamic material"));
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogMosisPhoneActor, Warning, TEXT("BeginPlay: No base material available"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void AMosisPhoneActor::Tick(float DeltaSeconds)
|
|
{
|
|
Super::Tick(DeltaSeconds);
|
|
|
|
// Update material texture if phone component has a new texture
|
|
if (ScreenMaterial && PhoneComponent)
|
|
{
|
|
UTexture* PhoneTexture = PhoneComponent->GetPhoneTexture();
|
|
if (PhoneTexture)
|
|
{
|
|
ScreenMaterial->SetTextureParameterValue(PhoneComponent->TextureParameterName, PhoneTexture);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AMosisPhoneActor::SendTouchAtWorldLocation(FVector HitLocation, EMosisTouchType TouchType)
|
|
{
|
|
FVector2D UV;
|
|
if (!WorldToPhoneUV(HitLocation, UV))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (PhoneComponent)
|
|
{
|
|
PhoneComponent->SendTouch(UV, TouchType);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool AMosisPhoneActor::WorldToPhoneUV(FVector WorldLocation, FVector2D& OutUV) const
|
|
{
|
|
// Convert world location to local space
|
|
FVector LocalLocation = GetActorTransform().InverseTransformPosition(WorldLocation);
|
|
|
|
// Get bounds
|
|
float MinX = ScreenBoundsLocal.X;
|
|
float MinY = ScreenBoundsLocal.Y;
|
|
float MaxX = ScreenBoundsLocal.Z;
|
|
float MaxY = ScreenBoundsLocal.W;
|
|
|
|
// Check if within bounds
|
|
if (LocalLocation.X < MinX || LocalLocation.X > MaxX ||
|
|
LocalLocation.Y < MinY || LocalLocation.Y > MaxY)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Calculate UV (0-1 range)
|
|
OutUV.X = (LocalLocation.X - MinX) / (MaxX - MinX);
|
|
OutUV.Y = (LocalLocation.Y - MinY) / (MaxY - MinY);
|
|
|
|
return true;
|
|
}
|