G6b : PreloadCityPackages au démarrage (LPDataCompat, LPModInfoSubsystem ; rattrape FindCenterOfPolygon et le renommage ModInfoCheckInterval)
Phase G6b (CHG-116). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7b5e1a5179
commit
81f75d4e95
3 changed files with 114 additions and 2 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "LPDataCompat.h"
|
#include "LPDataCompat.h"
|
||||||
|
|
||||||
|
#include "Engine/StreamableManager.h"
|
||||||
#include "Kismet/KismetStringLibrary.h"
|
#include "Kismet/KismetStringLibrary.h"
|
||||||
#include "LifePlay.h"
|
#include "LifePlay.h"
|
||||||
#include "LPStringCompat.h"
|
#include "LPStringCompat.h"
|
||||||
|
|
@ -185,3 +186,94 @@ void ULPDataCompat::WhatWhereToArray(UObject* Target, const FString& Line, TArra
|
||||||
It->DestroyValue_InContainer(Params);
|
It->DestroyValue_InContainer(Params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
FMapProperty* FindAreasMap(const UObject* GI)
|
||||||
|
{
|
||||||
|
if (!GI)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
for (TFieldIterator<FMapProperty> It(GI->GetClass()); It; ++It)
|
||||||
|
{
|
||||||
|
if (It->GetAuthoredName() == TEXT("Areas"))
|
||||||
|
{
|
||||||
|
return *It;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULPDataCompat::FindCenterOfPolygon(UObject* Target, const TArray<FVector2D>& BuildingPoints, FVector2D& Center, double& Area)
|
||||||
|
{
|
||||||
|
// Le graphe copie X et Y dans des tableaux de float (MinOfFloatArray), puis calcule en double.
|
||||||
|
float MinX = 0.f, MaxX = 0.f, MinY = 0.f, MaxY = 0.f;
|
||||||
|
if (BuildingPoints.Num() > 0)
|
||||||
|
{
|
||||||
|
MinX = MaxX = static_cast<float>(BuildingPoints[0].X);
|
||||||
|
MinY = MaxY = static_cast<float>(BuildingPoints[0].Y);
|
||||||
|
for (const FVector2D& Point : BuildingPoints)
|
||||||
|
{
|
||||||
|
const float X = static_cast<float>(Point.X);
|
||||||
|
const float Y = static_cast<float>(Point.Y);
|
||||||
|
MinX = FMath::Min(MinX, X);
|
||||||
|
MaxX = FMath::Max(MaxX, X);
|
||||||
|
MinY = FMath::Min(MinY, Y);
|
||||||
|
MaxY = FMath::Max(MaxY, Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Center.X = (static_cast<double>(MinX) + static_cast<double>(MaxX)) / 2.0;
|
||||||
|
Center.Y = (static_cast<double>(MinY) + static_cast<double>(MaxY)) / 2.0;
|
||||||
|
Area = FMath::Abs(static_cast<double>(MaxX) - static_cast<double>(MinX))
|
||||||
|
* FMath::Abs(static_cast<double>(MaxY) - static_cast<double>(MinY))
|
||||||
|
/ 1000.0;
|
||||||
|
|
||||||
|
FMapProperty* Areas = FindAreasMap(Target);
|
||||||
|
if (!Areas)
|
||||||
|
{
|
||||||
|
UE_LOG(LogLifePlay, Error, TEXT("FindCenterOfPolygon : GI.Areas introuvable sur %s"), *GetNameSafe(Target));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const FStructProperty* KeyStruct = CastField<FStructProperty>(Areas->KeyProp);
|
||||||
|
if (!KeyStruct || KeyStruct->Struct != TBaseStructure<FVector2D>::Get())
|
||||||
|
{
|
||||||
|
UE_LOG(LogLifePlay, Error, TEXT("FindCenterOfPolygon : GI.Areas n'est pas indexe par Vector2D"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FScriptMapHelper Helper(Areas, Areas->ContainerPtrToValuePtr<void>(Target));
|
||||||
|
if (const FDoubleProperty* AsDouble = CastField<FDoubleProperty>(Areas->ValueProp))
|
||||||
|
{
|
||||||
|
(void)AsDouble;
|
||||||
|
Helper.AddPair(&Center, &Area);
|
||||||
|
}
|
||||||
|
else if (CastField<FFloatProperty>(Areas->ValueProp))
|
||||||
|
{
|
||||||
|
const float AreaFloat = static_cast<float>(Area);
|
||||||
|
Helper.AddPair(&Center, &AreaFloat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogLifePlay, Error, TEXT("FindCenterOfPolygon : valeur de GI.Areas ni float ni double"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULPDataCompat::PreloadCityPackages()
|
||||||
|
{
|
||||||
|
// Le handle doit vivre : sinon le fluxable libere le paquet avant le clic Continuer.
|
||||||
|
static FStreamableManager Manager;
|
||||||
|
static TSharedPtr<FStreamableHandle> Handle;
|
||||||
|
if (Handle.IsValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const TArray<FSoftObjectPath> Paths = {
|
||||||
|
FSoftObjectPath(TEXT("/Game/Heavy/StreetMap/Static/CentralLondon.CentralLondon")),
|
||||||
|
FSoftObjectPath(TEXT("/Game/Heavy/StreetMap/CentralLondon.CentralLondon")),
|
||||||
|
};
|
||||||
|
Handle = Manager.RequestAsyncLoad(Paths, FStreamableDelegate(), FStreamableManager::AsyncLoadHighPriority);
|
||||||
|
UE_LOG(LogLifePlay, Display, TEXT("Preload ville : %s"), Handle.IsValid() ? TEXT("demande envoyee") : TEXT("echec"));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,20 @@ public:
|
||||||
|
|
||||||
/** Implementation pure (sans verification), exposee pour les tests. */
|
/** Implementation pure (sans verification), exposee pour les tests. */
|
||||||
static TArray<FString> ComputeWhatWhere(const UObject* GI, const FString& Line);
|
static TArray<FString> ComputeWhatWhere(const UObject* GI, const FString& Line);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equivalent C++ de GI::FindCenterOfPolygon (centre de la boite englobante, pas le centroide).
|
||||||
|
* Appelee une fois par batiment au chargement de la ville (49 425 fois, 0,74 s inclus dans la trace
|
||||||
|
* Development du 2026-10-04). Meme resultat que le graphe : coordonnees ramenees en float avant
|
||||||
|
* min/max, centre = milieu de la boite, aire = |dx| * |dy| / 1000, puis GI.Areas[centre] = aire.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "LifePlay|Compat", meta = (DefaultToSelf = "Target", HidePin = "Target"))
|
||||||
|
static void FindCenterOfPolygon(UObject* Target, const TArray<FVector2D>& BuildingPoints, FVector2D& Center, double& Area);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demarre la lecture des paquets de la ville (maillage statique et donnees StreetMap) avant le
|
||||||
|
* clic Continuer. Separer du correctif FindCenterOfPolygon : la trace I6 attribuait ~164 Mo a
|
||||||
|
* l'image de plusieurs secondes ; ces deux paquets sont ceux que le canal loadtime nomme.
|
||||||
|
*/
|
||||||
|
static void PreloadCityPackages();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "HAL/FileManager.h"
|
#include "HAL/FileManager.h"
|
||||||
#include "HAL/PlatformTime.h"
|
#include "HAL/PlatformTime.h"
|
||||||
#include "LifePlay.h"
|
#include "LifePlay.h"
|
||||||
|
#include "LPDataCompat.h"
|
||||||
#include "Misc/FileHelper.h"
|
#include "Misc/FileHelper.h"
|
||||||
#include "Misc/Paths.h"
|
#include "Misc/Paths.h"
|
||||||
#include "Styling/CoreStyle.h"
|
#include "Styling/CoreStyle.h"
|
||||||
|
|
@ -22,7 +23,7 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr double CheckInterval = 2.0;
|
constexpr double ModInfoCheckInterval = 2.0;
|
||||||
|
|
||||||
FString FieldText(const UStruct* Struct, const void* Data, const TCHAR* AuthoredName)
|
FString FieldText(const UStruct* Struct, const void* Data, const TCHAR* AuthoredName)
|
||||||
{
|
{
|
||||||
|
|
@ -70,6 +71,9 @@ void ULPModInfoSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
WithGameVersion += Keys.Contains(TEXT("MODULE_GAME_VERSION")) ? 1 : 0;
|
WithGameVersion += Keys.Contains(TEXT("MODULE_GAME_VERSION")) ? 1 : 0;
|
||||||
}
|
}
|
||||||
UE_LOG(LogLifePlay, Display, TEXT("Modules : %d .lpmod lu(s), %d avec MODULE_GAME_VERSION (jeu %s)"), Metadata.Num(), WithGameVersion, *GameVersion);
|
UE_LOG(LogLifePlay, Display, TEXT("Modules : %d .lpmod lu(s), %d avec MODULE_GAME_VERSION (jeu %s)"), Metadata.Num(), WithGameVersion, *GameVersion);
|
||||||
|
// Lot separe du correctif FindCenterOfPolygon : lancer la lecture des ~164 Mo de la ville
|
||||||
|
// des l'instance de jeu, pas dans l'image du clic Continuer.
|
||||||
|
ULPDataCompat::PreloadCityPackages();
|
||||||
if (WithGameVersion > 0)
|
if (WithGameVersion > 0)
|
||||||
{
|
{
|
||||||
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULPModInfoSubsystem::Tick));
|
TickHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &ULPModInfoSubsystem::Tick));
|
||||||
|
|
@ -124,7 +128,7 @@ bool ULPModInfoSubsystem::Tick(float DeltaTime)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
NextCheck = Now + CheckInterval;
|
NextCheck = Now + ModInfoCheckInterval;
|
||||||
TArray<FString> Lines;
|
TArray<FString> Lines;
|
||||||
for (const TPair<FString, TMap<FString, FString>>& Pair : Metadata)
|
for (const TPair<FString, TMap<FString, FString>>& Pair : Metadata)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue