L7j : camera SecondScreen dotee d'une racine et placee (ERR-031) ; L7l : diagnostic du sol de neige (ERR-036)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
928826139f
commit
af1861b989
6 changed files with 228 additions and 6 deletions
Binary file not shown.
|
|
@ -150,8 +150,8 @@ Ordre indicatif, à réviser selon le registre :
|
||||||
| L7g | Packaging | build Shipping `LifePlay_Build_5.5_Shipping` construite (CHG-046), même structure que la version de l'auteur ; `McpAutomationBridge` déjà limité à l'éditeur ; ✅ validée en jeu le 2026-10-01 |
|
| L7g | Packaging | build Shipping `LifePlay_Build_5.5_Shipping` construite (CHG-046), même structure que la version de l'auteur ; `McpAutomationBridge` déjà limité à l'éditeur ; ✅ validée en jeu le 2026-10-01 |
|
||||||
| L7h | Vérification StreetMap | ✅ 280 villes et 280 maillages identiques 4.27/5.5 (ERR-018 clos, CHG-044) |
|
| L7h | Vérification StreetMap | ✅ 280 villes et 280 maillages identiques 4.27/5.5 (ERR-018 clos, CHG-044) |
|
||||||
| L7i | Variables DSL `Person` vides | ✅ ERR-030, ERR-037, ERR-003 préexistants en 4.27 ; ERR-005 corrigé par CX-B12 (385 nœuds `Contains`/`Split`/`FindSubstring`), validé en jeu le 2026-10-01 |
|
| L7i | Variables DSL `Person` vides | ✅ ERR-030, ERR-037, ERR-003 préexistants en 4.27 ; ERR-005 corrigé par CX-B12 (385 nœuds `Contains`/`Split`/`FindSubstring`), validé en jeu le 2026-10-01 |
|
||||||
| L7j | Écran secondaire (amélioration) | ERR-031, préexistant en 4.27 : caméra `SecondScreen` sans racine ; seulement si souhaité |
|
| L7j | Écran secondaire (amélioration) | caméra `SecondScreen` dotée d'une racine et placée sur `CameraScene` − 10 000 000 Y (CHG-052) ; test en jeu en attente |
|
||||||
| L7l | Personnages enfoncés dans le sol en extérieur (amélioration) | ERR-036, préexistant en 4.27 ; seulement si souhaité |
|
| L7l | Personnages enfoncés dans le sol en extérieur (amélioration) | diagnostic (CHG-053) : sol de neige `fnt_new208` étiré ×100 en hauteur dans `forest___vin01.lpworld` (donnée de module) ; correction à caler par une mesure en jeu |
|
||||||
| L7k | Erreurs d'exécution fréquentes (ex-L7b) | ✅ ERR-006 et ERR-007 revenus au niveau 4.27 avec CX-B12 ; signatures restantes au niveau 4.27 (CHG-045) |
|
| L7k | Erreurs d'exécution fréquentes (ex-L7b) | ✅ ERR-006 et ERR-007 revenus au niveau 4.27 avec CX-B12 ; signatures restantes au niveau 4.27 (CHG-045) |
|
||||||
|
|
||||||
## 4. Décisions
|
## 4. Décisions
|
||||||
|
|
|
||||||
|
|
@ -823,3 +823,34 @@ le rendu passait donc déjà par SkyAtmosphere. Éclairage précalculé : `Centr
|
||||||
sont déjà actifs ; ils exécutent les 34 actions et axes hérités de `DefaultInput.ini`. Une migration complète
|
sont déjà actifs ; ils exécutent les 34 actions et axes hérités de `DefaultInput.ini`. Une migration complète
|
||||||
(Input Actions, Mapping Contexts, réécriture des événements d'entrée des Blueprints) n'apporterait rien au joueur
|
(Input Actions, Mapping Contexts, réécriture des événements d'entrée des Blueprints) n'apporterait rien au joueur
|
||||||
et demanderait un test manuel des 34 commandes : reportée.
|
et demanderait un test manuel des 34 commandes : reportée.
|
||||||
|
|
||||||
|
### L7j — image du contact pendant un appel (ERR-031, amélioration), 2026-10-01
|
||||||
|
|
||||||
|
| CHG | Date | Lot | Fichiers | Raison | Retour arrière |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| CHG-052 | 2026-10-01 | L7j | `Source/LifePlayEditorTools/LPFixSceneCaptureCommandlet` (nouveau) ; `Content/Scenes/CentralLondon.umap` | ERR-031 (présent en 4.27) : la caméra `SecondScreen` filme le ciel | `Tools\Restore.ps1 -Lot L7j` |
|
||||||
|
|
||||||
|
Chaîne (L6f et L7j) : `GI::secondScreen` marque le contact (`Person.secondScreen`) ; `GI::Show` le place sur la position
|
||||||
|
de son emplacement de scène (`ActorTransforms[i]`) **décalée de −10 000 000 en Y**, sur la copie de studio
|
||||||
|
`SecondScreenFloor` (−3 131 543 ; −24 967 212, soit le studio des scènes − 10 000 000 Y) ; l'encadré affiche
|
||||||
|
`Render/SecondScreen`, rendu par la caméra `SecondScreen`. Aucun Blueprint ne déplace cette caméra ; dans la carte
|
||||||
|
(4.27 comme 5.5) elle n'a pas de racine (`RootComponent = None`) et ses composants sont à l'origine.
|
||||||
|
|
||||||
|
Correctif : racine = son `SceneComponent` existant, capture rattachée, position = `CameraScene` (cadrage des scènes du
|
||||||
|
studio : −3 131 132 ; −14 967 241 ; 50, lacet 180°) − 10 000 000 Y. Contrôle intégré (racine, rattachement, position
|
||||||
|
monde = cible) puis diff `LPDumpAssets` de la carte : **3 lignes modifiées**, toutes sur `SecondScreen`
|
||||||
|
(`Saved/Logs/portage/L7d_map_apres.txt` → `L7j_map_apres.txt`). Le cadrage (scène entière plutôt que portrait) est à
|
||||||
|
ajuster d'après le test en jeu si nécessaire (`-From=CameraPortrait`).
|
||||||
|
|
||||||
|
### L7l — personnages enfoncés dans le sol en extérieur (ERR-036, amélioration), 2026-10-01 : diagnostic
|
||||||
|
|
||||||
|
| CHG | Date | Lot | Fichiers | Raison | Retour arrière |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| CHG-053 | 2026-10-01 | L7l | `Source/LifePlayEditorTools/LPCheckMeshesCommandlet` (colonnes `MinZ`, `MaxZ`) | diagnostic | — |
|
||||||
|
|
||||||
|
Le lieu `Modules/vin_Base/World/forest___vin01.lpworld` (donnée de module, identique en 4.27) pose comme sol le meuble
|
||||||
|
`fnt_new208` (dalle 230 × 99 × 0,6) en Z = −31,2 avec une échelle (0,713 ; 1,481 ; **100**) ; ailleurs (`bathroom`,
|
||||||
|
`shower`, `sports_centre`) le même meuble est un petit objet (Z = 60, échelle 5). Les meubles sont rattachés à un point
|
||||||
|
d'ancrage en Z = 60 (`Room::addObject`). La hauteur exacte de la surface de neige par rapport au sol de marche dépend
|
||||||
|
de la chaîne de composants du meuble : une mesure en jeu est nécessaire avant de corriger le fichier (ou d'ajuster la
|
||||||
|
dalle avec l'éditeur de lieu intégré au jeu, « Edit building »).
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ int32 ULPCheckMeshesCommandlet::Main(const FString& Params)
|
||||||
Assets.Sort([](const FAssetData& A, const FAssetData& B) { return A.AssetName.LexicalLess(B.AssetName); });
|
Assets.Sort([](const FAssetData& A, const FAssetData& B) { return A.AssetName.LexicalLess(B.AssetName); });
|
||||||
|
|
||||||
TArray<FString> Lines;
|
TArray<FString> Lines;
|
||||||
Lines.Add(TEXT("Mesh;LODs;SommetsSource;TrianglesSource;SommetsRendu;TrianglesRendu;Sections;Materiaux;TailleX;TailleY;TailleZ"));
|
Lines.Add(TEXT("Mesh;LODs;SommetsSource;TrianglesSource;SommetsRendu;TrianglesRendu;Sections;Materiaux;TailleX;TailleY;TailleZ;MinZ;MaxZ"));
|
||||||
int32 Failures = 0;
|
int32 Failures = 0;
|
||||||
|
|
||||||
for (const FAssetData& AssetData : Assets)
|
for (const FAssetData& AssetData : Assets)
|
||||||
|
|
@ -66,11 +66,12 @@ int32 ULPCheckMeshesCommandlet::Main(const FString& Params)
|
||||||
const int32 RenderVerts = Mesh->GetNumVertices(0);
|
const int32 RenderVerts = Mesh->GetNumVertices(0);
|
||||||
const int32 RenderTris = Mesh->GetNumTriangles(0);
|
const int32 RenderTris = Mesh->GetNumTriangles(0);
|
||||||
const int32 Sections = Mesh->GetNumSections(0);
|
const int32 Sections = Mesh->GetNumSections(0);
|
||||||
const FVector Size = Mesh->GetBoundingBox().GetSize();
|
const FBox Box = Mesh->GetBoundingBox();
|
||||||
|
const FVector Size = Box.GetSize();
|
||||||
|
|
||||||
Lines.Add(FString::Printf(TEXT("%s;%d;%d;%d;%d;%d;%d;%d;%.0f;%.0f;%.0f"),
|
Lines.Add(FString::Printf(TEXT("%s;%d;%d;%d;%d;%d;%d;%d;%.0f;%.0f;%.0f;%.2f;%.2f"),
|
||||||
*AssetData.AssetName.ToString(), Mesh->GetNumLODs(), SrcVerts, SrcTris, RenderVerts, RenderTris,
|
*AssetData.AssetName.ToString(), Mesh->GetNumLODs(), SrcVerts, SrcTris, RenderVerts, RenderTris,
|
||||||
Sections, Mesh->GetStaticMaterials().Num(), Size.X, Size.Y, Size.Z));
|
Sections, Mesh->GetStaticMaterials().Num(), Size.X, Size.Y, Size.Z, Box.Min.Z, Box.Max.Z));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FFileHelper::SaveStringArrayToFile(Lines, *CsvPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
|
if (!FFileHelper::SaveStringArrayToFile(Lines, *CsvPath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
|
||||||
|
|
|
||||||
159
Source/LifePlayEditorTools/LPFixSceneCaptureCommandlet.cpp
Normal file
159
Source/LifePlayEditorTools/LPFixSceneCaptureCommandlet.cpp
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
// Portage UE 5.5 - voir LPFixSceneCaptureCommandlet.h
|
||||||
|
|
||||||
|
#include "LPFixSceneCaptureCommandlet.h"
|
||||||
|
|
||||||
|
#include "Components/SceneCaptureComponent2D.h"
|
||||||
|
#include "Engine/Level.h"
|
||||||
|
#include "Engine/SceneCapture2D.h"
|
||||||
|
#include "Engine/World.h"
|
||||||
|
#include "Misc/PackageName.h"
|
||||||
|
#include "UObject/Package.h"
|
||||||
|
#include "UObject/SavePackage.h"
|
||||||
|
|
||||||
|
DEFINE_LOG_CATEGORY_STATIC(LogLPFixSceneCapture, Log, All);
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
AActor* FindActorByLabelOrName(ULevel* Level, const FString& Name)
|
||||||
|
{
|
||||||
|
for (AActor* Actor : Level->Actors)
|
||||||
|
{
|
||||||
|
if (Actor && (Actor->GetActorLabel() == Name || Actor->GetName() == Name))
|
||||||
|
{
|
||||||
|
return Actor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULPFixSceneCaptureCommandlet::ULPFixSceneCaptureCommandlet()
|
||||||
|
{
|
||||||
|
IsClient = false;
|
||||||
|
IsServer = false;
|
||||||
|
IsEditor = true;
|
||||||
|
LogToConsole = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 ULPFixSceneCaptureCommandlet::Main(const FString& Params)
|
||||||
|
{
|
||||||
|
TArray<FString> Tokens, Switches;
|
||||||
|
TMap<FString, FString> ParamsMap;
|
||||||
|
ParseCommandLine(*Params, Tokens, Switches, ParamsMap);
|
||||||
|
const bool bDryRun = Switches.Contains(TEXT("DryRun"));
|
||||||
|
const FString MapPath = ParamsMap.FindRef(TEXT("Map"));
|
||||||
|
const FString ActorName = ParamsMap.FindRef(TEXT("Actor"));
|
||||||
|
const FString FromName = ParamsMap.FindRef(TEXT("From"));
|
||||||
|
FVector Offset = FVector::ZeroVector;
|
||||||
|
{
|
||||||
|
TArray<FString> Parts;
|
||||||
|
ParamsMap.FindRef(TEXT("Offset")).ParseIntoArray(Parts, TEXT(","), true);
|
||||||
|
if (Parts.Num() == 3)
|
||||||
|
{
|
||||||
|
Offset = FVector(FCString::Atod(*Parts[0]), FCString::Atod(*Parts[1]), FCString::Atod(*Parts[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MapPath.IsEmpty() || ActorName.IsEmpty() || FromName.IsEmpty())
|
||||||
|
{
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Error, TEXT("Usage : -Map=/Game/Scenes/X -Actor=<capture> -From=<acteur de reference> [-Offset=x,y,z] [-DryRun]"));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FString WorldPath = MapPath + TEXT(".") + FPackageName::GetShortName(MapPath);
|
||||||
|
UWorld* World = LoadObject<UWorld>(nullptr, *WorldPath);
|
||||||
|
if (!World || !World->PersistentLevel)
|
||||||
|
{
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Error, TEXT("Carte introuvable : %s"), *WorldPath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
World->AddToRoot();
|
||||||
|
|
||||||
|
ASceneCapture2D* Capture = Cast<ASceneCapture2D>(FindActorByLabelOrName(World->PersistentLevel, ActorName));
|
||||||
|
AActor* From = FindActorByLabelOrName(World->PersistentLevel, FromName);
|
||||||
|
if (!Capture || !From || !From->GetRootComponent())
|
||||||
|
{
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Error, TEXT("Acteur introuvable : %s (capture) ou %s (reference, avec racine)"), *ActorName, *FromName);
|
||||||
|
World->RemoveFromRoot();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
USceneCaptureComponent2D* CaptureComp = Capture->GetCaptureComponent2D();
|
||||||
|
USceneComponent* NewRoot = nullptr;
|
||||||
|
for (UActorComponent* Comp : Capture->GetComponents())
|
||||||
|
{
|
||||||
|
USceneComponent* SceneComp = Cast<USceneComponent>(Comp);
|
||||||
|
if (SceneComp && SceneComp != CaptureComp && SceneComp->GetClass() == USceneComponent::StaticClass())
|
||||||
|
{
|
||||||
|
NewRoot = SceneComp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!NewRoot)
|
||||||
|
{
|
||||||
|
NewRoot = CaptureComp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FTransform FromTransform = From->GetRootComponent()->GetRelativeTransform();
|
||||||
|
const FTransform Target(FromTransform.GetRotation(), FromTransform.GetLocation() + Offset, FVector::OneVector);
|
||||||
|
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Warning, TEXT("=== %s : racine %s -> %s, cible %s (= %s + %s)%s ==="),
|
||||||
|
*Capture->GetActorLabel(), *GetNameSafe(Capture->GetRootComponent()), *GetNameSafe(NewRoot),
|
||||||
|
*Target.ToString(), *FromName, *Offset.ToString(), bDryRun ? TEXT(" [DRY RUN]") : TEXT(""));
|
||||||
|
if (bDryRun)
|
||||||
|
{
|
||||||
|
World->RemoveFromRoot();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Capture->Modify();
|
||||||
|
Capture->SetRootComponent(NewRoot);
|
||||||
|
if (CaptureComp && CaptureComp != NewRoot)
|
||||||
|
{
|
||||||
|
CaptureComp->AttachToComponent(NewRoot, FAttachmentTransformRules::KeepRelativeTransform);
|
||||||
|
CaptureComp->SetRelativeTransform(FTransform::Identity);
|
||||||
|
}
|
||||||
|
NewRoot->SetRelativeTransform(Target);
|
||||||
|
NewRoot->UpdateComponentToWorld();
|
||||||
|
if (CaptureComp && CaptureComp != NewRoot)
|
||||||
|
{
|
||||||
|
CaptureComp->UpdateComponentToWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verification : racine, rattachement, position monde de la capture.
|
||||||
|
int32 Errors = 0;
|
||||||
|
if (Capture->GetRootComponent() != NewRoot) { ++Errors; UE_LOG(LogLPFixSceneCapture, Error, TEXT(" racine non affectee")); }
|
||||||
|
if (CaptureComp && CaptureComp != NewRoot && CaptureComp->GetAttachParent() != NewRoot) { ++Errors; UE_LOG(LogLPFixSceneCapture, Error, TEXT(" capture non rattachee")); }
|
||||||
|
const FTransform Final = CaptureComp ? CaptureComp->GetComponentTransform() : NewRoot->GetComponentTransform();
|
||||||
|
if (!Final.Equals(Target, 0.01))
|
||||||
|
{
|
||||||
|
++Errors;
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Error, TEXT(" position finale %s differente de la cible %s"), *Final.ToString(), *Target.ToString());
|
||||||
|
}
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Warning, TEXT(" capture : position monde %s"), *Final.ToString());
|
||||||
|
|
||||||
|
int32 Result = 0;
|
||||||
|
if (Errors == 0)
|
||||||
|
{
|
||||||
|
UPackage* Package = World->GetOutermost();
|
||||||
|
const FString Filename = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetMapPackageExtension());
|
||||||
|
FSavePackageArgs SaveArgs;
|
||||||
|
SaveArgs.TopLevelFlags = RF_Standalone;
|
||||||
|
SaveArgs.Error = GWarn;
|
||||||
|
if (UPackage::SavePackage(Package, World, *Filename, SaveArgs))
|
||||||
|
{
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Warning, TEXT(" -> carte sauvegardee"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Error, TEXT(" ECHEC de sauvegarde"));
|
||||||
|
Result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UE_LOG(LogLPFixSceneCapture, Error, TEXT(" %d ecart(s) : carte NON sauvegardee"), Errors);
|
||||||
|
Result = 1;
|
||||||
|
}
|
||||||
|
World->RemoveFromRoot();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
31
Source/LifePlayEditorTools/LPFixSceneCaptureCommandlet.h
Normal file
31
Source/LifePlayEditorTools/LPFixSceneCaptureCommandlet.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Portage UE 5.5 - lot L7j (ERR-031, amelioration : defaut deja present en 4.27).
|
||||||
|
//
|
||||||
|
// La camera SceneCapture2D "SecondScreen" de CentralLondon (image du contact dans l'encadre d'appel) n'a
|
||||||
|
// pas de composant racine (RootComponent = None) et ses composants sont a l'origine : elle filme le ciel.
|
||||||
|
// Les Blueprints ne la deplacent pas. Le contact affiche est place a la position de son emplacement de
|
||||||
|
// scene decalee de -10 000 000 en Y (GI::Show), sur la copie de scene SecondScreenFloor.
|
||||||
|
//
|
||||||
|
// Cette commandlet donne a l'acteur vise un composant racine (son SceneComponent existant, ou le
|
||||||
|
// composant de capture a defaut), y rattache le composant de capture, et le place sur la transformation
|
||||||
|
// d'un acteur de reference (camera du portrait) augmentee d'un decalage. Tout est verifie apres coup ;
|
||||||
|
// en cas d'ecart, la carte n'est pas sauvegardee.
|
||||||
|
//
|
||||||
|
// Usage :
|
||||||
|
// UnrealEditor-Cmd.exe <projet> -run=LPFixSceneCapture -Map=/Game/Scenes/CentralLondon -Actor=SecondScreen
|
||||||
|
// -From=CameraPortrait -Offset=0,-10000000,0 [-DryRun]
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Commandlets/Commandlet.h"
|
||||||
|
#include "LPFixSceneCaptureCommandlet.generated.h"
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class ULPFixSceneCaptureCommandlet : public UCommandlet
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
ULPFixSceneCaptureCommandlet();
|
||||||
|
virtual int32 Main(const FString& Params) override;
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue