LifePlay-Revival/Source/LifePlay/LPMapMarkersGuardSubsystem.cpp

150 lines
3.8 KiB
C++
Raw Normal View History

// Voir LPMapMarkersGuardSubsystem.h.
#include "LPMapMarkersGuardSubsystem.h"
#include "Components/WidgetComponent.h"
#include "Engine/GameInstance.h"
#include "GameFramework/Actor.h"
#include "LifePlay.h"
#include "UObject/UnrealType.h"
namespace LPMapMarkersGuard
{
AActor* FindMapMarkers(UGameInstance* GI)
{
if (!GI)
{
return nullptr;
}
if (const FObjectPropertyBase* Prop = CastField<FObjectPropertyBase>(GI->GetClass()->FindPropertyByName(TEXT("MapMarkers"))))
{
if (AActor* FromGI = Cast<AActor>(Prop->GetObjectPropertyValue_InContainer(GI)))
{
return FromGI;
}
}
for (TObjectIterator<AActor> It; It; ++It)
{
AActor* Candidate = *It;
if (!Candidate || Candidate->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
{
continue;
}
if (Candidate->GetClass()->GetName() != TEXT("MapMarkers_C"))
{
continue;
}
if (Candidate->GetGameInstance() != GI)
{
continue;
}
return Candidate;
}
return nullptr;
}
void ClearArrayProp(UObject* Object, FName Name)
{
FArrayProperty* Arr = Object ? CastField<FArrayProperty>(Object->GetClass()->FindPropertyByName(Name)) : nullptr;
if (!Arr)
{
return;
}
FScriptArrayHelper Helper(Arr, Arr->ContainerPtrToValuePtr<void>(Object));
Helper.EmptyValues();
}
}
void ULPMapMarkersGuardSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULPMapMarkersGuardSubsystem::Tick), 0.25f);
}
void ULPMapMarkersGuardSubsystem::Deinitialize()
{
FTSTicker::GetCoreTicker().RemoveTicker(TickHandle);
Super::Deinitialize();
}
bool ULPMapMarkersGuardSubsystem::Tick(float DeltaTime)
{
(void)DeltaTime;
if (AActor* Markers = LPMapMarkersGuard::FindMapMarkers(GetGameInstance()))
{
Guard(Markers);
}
return true;
}
void ULPMapMarkersGuardSubsystem::Guard(AActor* Markers)
{
FArrayProperty* Arr = CastField<FArrayProperty>(Markers->GetClass()->FindPropertyByName(TEXT("WidgetComponents")));
if (!Arr || !CastField<FObjectPropertyBase>(Arr->Inner))
{
return;
}
FScriptArrayHelper Helper(Arr, Arr->ContainerPtrToValuePtr<void>(Markers));
for (int32 Index = Helper.Num() - 1; Index >= 0; --Index)
{
UObject* Entry = *reinterpret_cast<UObject**>(Helper.GetRawPtr(Index));
if (!IsValid(Entry))
{
Helper.RemoveValues(Index);
}
}
if (Helper.Num() > 0)
{
return;
}
// Desync HideAllMarkers : composants detruits, Vector2Ds encore pleins → AddMarker ne recree rien.
LPMapMarkersGuard::ClearArrayProp(Markers, TEXT("Vector2Ds"));
TArray<UWidgetComponent*> Existing;
Markers->GetComponents<UWidgetComponent>(Existing);
for (UWidgetComponent* Comp : Existing)
{
if (!IsValid(Comp))
{
continue;
}
const int32 Slot = Helper.AddValue();
*reinterpret_cast<UObject**>(Helper.GetRawPtr(Slot)) = Comp;
}
if (Helper.Num() > 0)
{
if (!bLoggedOnce)
{
bLoggedOnce = true;
UE_LOG(LogLifePlay, Display, TEXT("MapMarkers : WidgetComponents reconstitue depuis %d composant(s) (ERR-008)"), Helper.Num());
}
return;
}
UWidgetComponent* Focus = NewObject<UWidgetComponent>(Markers, TEXT("LPFocusWidgetComponent"));
if (!Focus)
{
return;
}
if (USceneComponent* Root = Markers->GetRootComponent())
{
Focus->SetupAttachment(Root);
}
Focus->SetHiddenInGame(true);
Focus->SetVisibility(false);
Focus->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Focus->RegisterComponent();
const int32 Slot = Helper.AddValue();
*reinterpret_cast<UObject**>(Helper.GetRawPtr(Slot)) = Focus;
if (!bLoggedOnce)
{
bLoggedOnce = true;
UE_LOG(LogLifePlay, Display, TEXT("MapMarkers : slot de focus WidgetComponents[0] ajoute (ERR-008, SetInputMode sans crash)"));
}
}