351 lines
26 KiB
Markdown
351 lines
26 KiB
Markdown
|
|
Fiche U7b-T4 — Niveau N1 (rédaction N3) — Modèle prévu lp-impl | utilisé claude-opus-5-5 — Agent lp-impl — Skills sk-protocol (préchargés aussi : ue-cpp-build, lp-build, lp-ue-compat)
|
|||
|
|
|
|||
|
|
# U7b-T4 : tournée Mesure hors écran (T1, option A) et garde-fou de RetargetPack sous UE ≥ 5.6 (T2 reporté)
|
|||
|
|
|
|||
|
|
Date : 2026-10-09. Addon = worktree `D:\Game\LifePlay-Sandbox-5.8`, branche `ue5.8`, HEAD `d1efdd1` (tag `U7b-avant`).
|
|||
|
|
Rien n'a été commité. Je n'ai lancé ni le jeu, ni l'éditeur, ni le pipeline. Les essais statiques du § 6 tournent hors
|
|||
|
|
moteur : un faux module `unreal` et un faux `UnrealEditor.exe`, tous deux dans le bloc-notes de session.
|
|||
|
|
Le checkout 5.5 `D:\Game\LifePlay-Sandbox` est intact (`git status --short` : 0 ligne).
|
|||
|
|
|
|||
|
|
## 0. Résumé
|
|||
|
|
|
|||
|
|
| Point | État | Preuve |
|
|||
|
|
|---|---|---|
|
|||
|
|
| (a) `-RenderOffScreen` est passé à la seule tournée Mesure du pilote | fait | § 3 (chaîne d'appel) et § 6.2 (cas 4 : la ligne reçue se termine par ` -RenderOffScreen`) |
|
|||
|
|
| (a) usage interactif inchangé | **établi, à l'octet près**, sur la ligne de commande reçue par l'exécutable | § 4 et § 6.2 (cas 1/2/5/6 identiques) |
|
|||
|
|
| (b) refus sous UE ≥ 5.6, avant toute suppression ou création | fait | § 5 : appel `RP:436`, première suppression `RP:265` atteinte par `RP:451` ; essai § 6.1 : 0 appel d'asset |
|
|||
|
|
| (b) BuildMod / AnimPipeline voient un échec | **établi par le code + essai statique de la regex** | § 5.2 et § 6.3 |
|
|||
|
|
| Correctif de portage T2 (diff § 5 de la CART) | **non appliqué**, conformément à la fiche | `grep -c "run_batch_retarget\|add_retarget_op" RetargetPack.py` = 0 |
|
|||
|
|
|
|||
|
|
## 1. Fichiers, instantané, fins de ligne
|
|||
|
|
|
|||
|
|
| Fichier (addon 5.8) | Instantané `U7b-addon` (MD5 avant) | MD5 après | Fins de ligne / encodage avant → après | `git diff --stat` |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| `Tools\anim\AnimPipeline.ps1` | `6BC085152D53C3A15DDDFABF9505F0E0` (fait par l'orchestrateur) | `adc7a19ebfa1cb0b93b382e7f40ee526` | LF 568 → LF 573, sans BOM, 4 octets non ASCII inchangés | 7 +, 2 − |
|
|||
|
|
| `Tools\anim\RetargetPack.py` | `3C6491C6FF0DCCF4D44462FADC02C0ED` (fait par l'orchestrateur) | `182c60f3e8e0693ff9f6dcefc98790f9` | LF 463 → LF 486, ASCII | 23 + |
|
|||
|
|
| `Tools\debug\LifePlay_interaction_sandbox.bat` | `EF13A3929D5E9A7332BFA2BA9FCE8984`, **ajouté par moi** avant modification (commande de la fiche, sortie `sauvegarde : ... 1 entree(s) ajoutee(s)`) | `7ec8d6350e2cbd36bedf2ccbef50fbd1` | CRLF 10 → CRLF 15, ASCII, sans LF nu | 6 +, 1 − |
|
|||
|
|
|
|||
|
|
- Manifeste : `D:\Game\LifePlay_Backup_5.5\U7b-addon\manifest.csv`, 3 entrées. Le MD5 du .bat sauvegardé est égal à celui de
|
|||
|
|
`git show HEAD:Tools/debug/LifePlay_interaction_sandbox.bat` (`md5sum` : `ef13a392…`).
|
|||
|
|
- Comptes produits par Python sur les octets (`d.count(b"\r\n")`, `d.count(b"\n")`, BOM, octets > 127). `.gitattributes`
|
|||
|
|
de l'addon : `* -text`, donc aucune conversion par git.
|
|||
|
|
- Pourquoi le .bat est modifié : il ne transmettait aucun argument (`%*` absent, `.bat:9` d'avant ; U7b-T1-CART § 1.1).
|
|||
|
|
Sans cette modification, il aurait fallu lancer l'exécutable depuis le pilote en recopiant la résolution GAME/UE/PROJ
|
|||
|
|
du .bat, ce qui duplique la logique du lanceur.
|
|||
|
|
|
|||
|
|
## 2. Diffs (`git -C D:\Game\LifePlay-Sandbox-5.8 diff`)
|
|||
|
|
|
|||
|
|
```diff
|
|||
|
|
--- a/Tools/anim/AnimPipeline.ps1
|
|||
|
|
+++ b/Tools/anim/AnimPipeline.ps1
|
|||
|
|
@@ -304,6 +304,10 @@ function Invoke-Sandbox {
|
|||
|
|
$modeF = Join-Path $saved 'sandbox_mode.txt'
|
|||
|
|
$tourF = Join-Path $saved 'sandbox_tour.txt'
|
|||
|
|
$bat = Join-Path $LPSbRoot 'Tools\debug\LifePlay_interaction_sandbox.bat'
|
|||
|
|
+ # U7b (option A, U7b-T1-CART section 5) : la tournee rend hors ecran (pas de fenetre systeme), donc une fenetre reduite
|
|||
|
|
+ # ne ramene plus le back buffer a 8x8 (assertion D3D12 de UE 5.8 a la capture). Option propre au pilote, passee en
|
|||
|
|
+ # argument du .bat ; l'ouverture interactive (BuildMod.ps1 -Open) lance le .bat sans argument et garde sa fenetre.
|
|||
|
|
+ $sbArgs = '-RenderOffScreen'
|
|||
|
|
$sbRel = ($c.sortie.clips -replace '^/Game/', '')
|
|||
|
|
$clipRel = ($c.source.clips -replace '^/Game/', '')
|
|||
|
|
$sbRoot = [string] $c.sandbox
|
|||
|
|
@@ -314,7 +318,7 @@ function Invoke-Sandbox {
|
|||
|
|
$outDir = Join-Path $saved ($sbRoot -replace '/', '\')
|
|||
|
|
Add-Cmd "ecrire Saved\sandbox_pack.ini (Name=$Pack, ...)"
|
|||
|
|
Add-Cmd 'ecrire Saved\sandbox_mode.txt = Mesure ; Saved\sandbox_tour.txt = vignettes planches quitter'
|
|||
|
|
- Add-Cmd "Tools\debug\LifePlay_interaction_sandbox.bat (attente de la fermeture de UnrealEditor, 40 min maximum)"
|
|||
|
|
+ Add-Cmd "Tools\debug\LifePlay_interaction_sandbox.bat $sbArgs (attente de la fermeture de UnrealEditor, 40 min maximum)"
|
|||
|
|
Add-Cmd "deplacer Saved\sandbox_pack.ini vers $(Get-WorkRel)\sandbox_pack.ini ; restaurer sandbox_mode.txt d'origine"
|
|||
|
|
@@ -331,7 +335,8 @@ function Invoke-Sandbox {
|
|||
|
|
Write-Text $tourF 'vignettes planches quitter'
|
|||
|
|
# Sans tuyau ni attente : avec `& $bat | Out-Null`, PowerShell attendait la fin de l'editeur lance par le .bat
|
|||
|
|
# (heritier de la sortie), puis ne le trouvait plus et concluait a tort « pas lancee » (AP7).
|
|||
|
|
- Start-Process -FilePath 'cmd.exe' -ArgumentList ('/c "{0}"' -f $bat) -WindowStyle Hidden | Out-Null
|
|||
|
|
+ # Commande entre guillemets doubles : cmd /c retire le premier et le dernier, le chemin du .bat reste entre guillemets.
|
|||
|
|
+ Start-Process -FilePath 'cmd.exe' -ArgumentList ('/c ""{0}" {1}"' -f $bat, $sbArgs) -WindowStyle Hidden | Out-Null
|
|||
|
|
```
|
|||
|
|
(Dans le premier `Add-Cmd` du contexte, j'ai abrégé la parenthèse en `...` ; cette ligne n'est pas modifiée.)
|
|||
|
|
|
|||
|
|
```diff
|
|||
|
|
--- a/Tools/anim/RetargetPack.py
|
|||
|
|
+++ b/Tools/anim/RetargetPack.py
|
|||
|
|
@@ -13,6 +13,8 @@
|
|||
|
|
# Methode factice ou copie, ou profil du maillage source different de profil_source : ligne
|
|||
|
|
# "RETARGET echec : <cause>" puis arret.
|
|||
|
|
+# Lot U7b : sous UE >= 5.6, refus de meme forme avant toute suppression ou creation d'asset (API IK Retargeter
|
|||
|
|
+# non portee, U7b-T2-CART ; portage reporte apres V2.0).
|
|||
|
|
@@ -22,6 +24,7 @@
|
|||
|
|
import json
|
|||
|
|
import math
|
|||
|
|
import os
|
|||
|
|
+import re
|
|||
|
|
@@ -57,6 +60,24 @@ class Refusal(Exception):
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
|
|||
|
|
+# Lot U7b (2026-10-09) : l'API Python de l'IK Retargeter a change en UE 5.6-5.8 (U7b-T2-CART : 9e argument de
|
|||
|
|
+# duplicate_and_retarget devenu target_path, reglages de chaine inertes, retargeter neuf sans op). Lance tel quel,
|
|||
|
|
+# le script supprimerait les IK/RTG de reference (make_rig, make_retargeter) et les clips cuits B_/M_
|
|||
|
|
+# (delete_copies) avant de planter. Portage reporte apres V2.0 : refus avant toute suppression ou creation.
|
|||
|
|
+UNPORTED_FROM = (5, 6)
|
|||
|
|
+UNPORTED_MESSAGE = "RetargetPack : API IK Retargeter 5.8 non portee (U7b-T2-CART, reporte apres V2.0) ; aucun asset modifie"
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+def refuse_unported_engine():
|
|||
|
|
+ # GetEngineVersion = FEngineVersion::Current().ToString(), ex. "5.8.3-58210709+++UE5+Release-5.8".
|
|||
|
|
+ # Version illisible : refus aussi (rien ne prouve alors un moteur anterieur a 5.6).
|
|||
|
|
+ text = str(unreal.SystemLibrary.get_engine_version())
|
|||
|
|
+ unreal.log_warning("RETARGET moteur %s" % text)
|
|||
|
|
+ match = re.match(r"\s*(\d+)\.(\d+)", text)
|
|||
|
|
+ if match is None or (int(match.group(1)), int(match.group(2))) >= UNPORTED_FROM:
|
|||
|
|
+ raise Refusal(UNPORTED_MESSAGE)
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
def load_config(saved_dir):
|
|||
|
|
@@ -411,6 +432,8 @@ def bake_named(clips, source_mesh, bodies):
|
|||
|
|
def run():
|
|||
|
|
global CFG
|
|||
|
|
CFG = load_config(unreal.Paths.project_saved_dir())
|
|||
|
|
+ # U7b : avant toute suppression ou creation d'asset ; apres load_config, qui lit le jeton de BuildMod.
|
|||
|
|
+ refuse_unported_engine()
|
|||
|
|
method = load_method(CFG["methode"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```diff
|
|||
|
|
--- a/Tools/debug/LifePlay_interaction_sandbox.bat
|
|||
|
|
+++ b/Tools/debug/LifePlay_interaction_sandbox.bat
|
|||
|
|
@@ -7,4 +7,9 @@
|
|||
|
|
set "PROJ=%GAME%\LifePlay.uproject"
|
|||
|
|
-start "" "%UE%" "%PROJ%" "/Engine/Maps/Entry?game=/Script/LPSandbox.LPPairSandboxGameMode" -game -windowed -ResX=1600 -ResY=900 "-ini:Engine:[/Script/EngineSettings.GameMapsSettings]:GameInstanceClass=/Script/Engine.GameInstance"
|
|||
|
|
+rem Lot U7b : les arguments de l'appelant sont ajoutes en fin de ligne (AnimPipeline.ps1 : -RenderOffScreen pour la
|
|||
|
|
+rem tournee Mesure). Sans argument (double-clic, BuildMod.ps1 -Target sandbox -Open), la ligne de lancement est inchangee,
|
|||
|
|
+rem a l'octet pres : EXTRA n'est defini (espace de tete comprise) que si des arguments sont passes.
|
|||
|
|
+set "EXTRA=%*"
|
|||
|
|
+if defined EXTRA set "EXTRA= %EXTRA%"
|
|||
|
|
+start "" "%UE%" "%PROJ%" "/Engine/Maps/Entry?game=/Script/LPSandbox.LPPairSandboxGameMode" -game -windowed -ResX=1600 -ResY=900 "-ini:Engine:[/Script/EngineSettings.GameMapsSettings]:GameInstanceClass=/Script/Engine.GameInstance"%EXTRA%
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. Chaîne d'appel de `-RenderOffScreen` (lignes après modification)
|
|||
|
|
|
|||
|
|
1. `AnimPipeline.ps1:310` `$sbArgs = '-RenderOffScreen'`. Puis `:339` lance
|
|||
|
|
`Start-Process cmd.exe -ArgumentList '/c ""<addon>\Tools\debug\LifePlay_interaction_sandbox.bat" -RenderOffScreen"'`.
|
|||
|
|
Une chaîne unique passée en `-ArgumentList` est transmise telle quelle comme ligne d'arguments.
|
|||
|
|
2. `cmd /c` : la ligne compte 4 guillemets, donc la règle 2 de `cmd /?` s'applique. cmd retire le premier guillemet et le
|
|||
|
|
dernier, et exécute `"<chemin du .bat>" -RenderOffScreen`. Texte de l'aide (`cmd /?`, poste en français) : « Dans le cas
|
|||
|
|
contraire, l'ancien comportement vérifiera si le premier caractère est un caractère guillemet et si tel est le cas,
|
|||
|
|
enlèvera le premier caractère et le dernier caractère guillemet de la ligne de commande ». Ainsi, le chemin du .bat
|
|||
|
|
reste entre guillemets, même s'il contient une espace (essai § 6.2, dossier `dossier avec espace`).
|
|||
|
|
3. `.bat:13` `set "EXTRA=%*"` donne `EXTRA=-RenderOffScreen`. `.bat:14` ajoute l'espace de tête :
|
|||
|
|
`EXTRA= -RenderOffScreen`. `.bat:15` lance
|
|||
|
|
`start "" "%UE%" "%PROJ%" "/Engine/Maps/Entry?game=…" -game -windowed -ResX=1600 -ResY=900 "-ini:…GameInstance" -RenderOffScreen`.
|
|||
|
|
4. Moteur 5.8 : `FWindowsPlatformApplicationMisc::CreateApplication` teste
|
|||
|
|
`FParse::Param(FCommandLine::Get(), TEXT("RenderOffScreen"))` et renvoie alors l'application nulle
|
|||
|
|
(`D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\ApplicationCore\Private\Windows\WindowsPlatformApplicationMisc.cpp:173-176`).
|
|||
|
|
Il n'y a ni écran de démarrage (`Runtime\Launch\Private\LaunchEngineLoop.cpp:3111`) ni fenêtre système
|
|||
|
|
(`Runtime\ApplicationCore\Private\GenericPlatform\GenericWindow.cpp:29, 113`). La suite de la mécanique (texture
|
|||
|
|
hors écran, pas de back buffer de 8×8) est décrite dans U7b-T1-CART § 4.1.
|
|||
|
|
5. Le pilote attend toujours le processus `UnrealEditor` (`AnimPipeline.ps1:340-345`, inchangé). Le nom du processus ne
|
|||
|
|
change pas avec l'option.
|
|||
|
|
|
|||
|
|
## 4. Preuve que l'usage interactif est inchangé
|
|||
|
|
|
|||
|
|
- **Appelants du .bat (établi)** : `grep -rn interaction_sandbox` sur l'addon (hors `Content`) et sur
|
|||
|
|
`D:\Game\LifePlay-master 5.8\{Tools,README.md,Docs}` :
|
|||
|
|
- `BuildMod.ps1:165` `& (Join-Path $LPSbRoot 'Tools\debug\LifePlay_interaction_sandbox.bat')`, **sans argument** ;
|
|||
|
|
- `AnimPipeline.ps1:306/321/339` (le pilote) ;
|
|||
|
|
- les docs `09_Commandes_Utiles.md:97` et `21_Sandbox_Addon.md:49`, qui décrivent un lancement manuel sans argument.
|
|||
|
|
Aucun autre script n'appelle le .bat. `LifePlay_measure_sandbox.bat` et `LifePlay_pair_sandbox.bat` ne l'appellent pas
|
|||
|
|
et ne sont pas modifiés.
|
|||
|
|
- **Sans argument, `EXTRA` n'est pas défini** : `set "EXTRA="` efface la variable. Dans un .bat, une variable non définie
|
|||
|
|
se développe en chaîne vide, donc `.bat:15` est identique à l'ancienne ligne 9. Une valeur `EXTRA` héritée de
|
|||
|
|
l'environnement est aussi effacée (cas 6 ci-dessous).
|
|||
|
|
- **Essai (établi, § 6.2)** : ligne de commande brute (`Environment.CommandLine`, c'est-à-dire `GetCommandLineW`)
|
|||
|
|
reçue par un faux `UnrealEditor.exe`, en comparant l'ancien .bat (HEAD) et le nouveau :
|
|||
|
|
- cas 1 (ancien, `& bat` comme `BuildMod.ps1:165`) = cas 2 (nouveau, même appel) : **identiques à l'octet** (`-ceq` → True) ;
|
|||
|
|
- cas 5 (nouveau, `cmd /c "<bat>"`, comme un double-clic) = cas 1 : True ;
|
|||
|
|
- cas 6 (nouveau, `EXTRA=-pollution` dans l'environnement, sans argument) = cas 1 : True ;
|
|||
|
|
- cas 3 (ancien appel du pilote sur l'ancien .bat) = cas 1 : True, donc avant U7b le pilote lançait bien la même ligne
|
|||
|
|
que l'usage interactif ;
|
|||
|
|
- cas 4 (nouveau pilote) = cas 1 + ` -RenderOffScreen` : True ;
|
|||
|
|
- cas 7 (deux arguments) = cas 1 + ` -RenderOffScreen -log` : True.
|
|||
|
|
- Une première version (`… GameInstance" %*`) laissait une espace finale dans la ligne interactive : le cas 2 se terminait
|
|||
|
|
par `GameInstance" ]` (écart constaté par le même essai). Je l'ai remplacée par la forme `EXTRA` avant de livrer. Ce
|
|||
|
|
point est noté au § 7.
|
|||
|
|
|
|||
|
|
## 5. Garde-fou de `RetargetPack.py` (b)
|
|||
|
|
|
|||
|
|
### 5.1 Position (lignes après modification, `grep -n`)
|
|||
|
|
- `RP:434` `CFG = load_config(...)` : lecture seule de `Saved\anim_retarget.json` (et de `anim_to_genesis_step.txt`), pour
|
|||
|
|
le jeton (`RP:89`). Aucun appel d'asset dans `load_config` (`RP:81-112`).
|
|||
|
|
- **`RP:436` `refuse_unported_engine()`**, définie en `RP:71-78`.
|
|||
|
|
- Premier appel qui touche un asset après le garde-fou : `RP:451` `make_rig(...)`, qui exécute
|
|||
|
|
**`RP:265` `delete_asset`** (première suppression) puis `RP:270` `create_asset` (première création). Viennent ensuite :
|
|||
|
|
- `make_retargeter`, appelé en `RP:455` (`RP:287` suppression, `RP:288` création) ;
|
|||
|
|
- `delete_copies`, appelé en `RP:461` (`RP:333`) ;
|
|||
|
|
- `bake_named`, appelé en `RP:464`.
|
|||
|
|
- Avant `RP:436`, il n'y a que des définitions et `NONE = unreal.Name()` au niveau du module. Aucun accès à un asset.
|
|||
|
|
- Le garde-fou précède la bifurcation `mode == "rigs"` : il couvre donc les deux modes (`-Retarget bake` et `-Retarget rigs`).
|
|||
|
|
|
|||
|
|
### 5.2 Comment l'échec remonte (établi par lecture du code)
|
|||
|
|
1. `Refusal` est interceptée par `main()` (`RP:476-478`). Le script écrit alors
|
|||
|
|
`RETARGET echec : RetargetPack : API IK Retargeter 5.8 non portee (U7b-T2-CART, reporte apres V2.0) ; aucun asset modifie jeton <j>`,
|
|||
|
|
puis appelle `quit_editor()`. Une ligne `RETARGET moteur <version>` la précède.
|
|||
|
|
2. `BuildMod.ps1:74-76` `Find-RetargetLine` reconnaît la ligne comme un `Failure`. Ensuite, `BuildMod.ps1:139` lève
|
|||
|
|
`throw "Conversion en echec : …"`, et `pwsh -File` se termine en erreur.
|
|||
|
|
3. `AnimPipeline.ps1` : le `.cmd` de l'étape 4 se termine par `@exit /b %ERRORLEVEL%` (`:281`).
|
|||
|
|
- `:284` lit le code de sortie.
|
|||
|
|
- `:288` voit le contrôle « conversion : code 0 » en échec.
|
|||
|
|
- `:287-290` ne trouve pas la ligne `RETARGET bridget n michael n` et lève `throw 'conversion non confirmee'`.
|
|||
|
|
4. API moteur utilisée :
|
|||
|
|
- `UKismetSystemLibrary::GetEngineVersion` : `D:\Game\Launcher\Engine\UE_5.8\Engine\Source\Runtime\Engine\Classes\Kismet\KismetSystemLibrary.h:213-215`
|
|||
|
|
(5.5 : `:170`). Son implémentation est `FEngineVersion::Current().ToString()` (`…\Engine\Private\KismetSystemLibrary.cpp:268-271`).
|
|||
|
|
- `ToString` vaut par défaut `EVersionComponent::Branch` (`Runtime\Core\Public\Misc\EngineVersion.h:34`). Le format
|
|||
|
|
produit est `Major.Minor.Patch-CL+Branch` (`Runtime\Core\Private\Misc\EngineVersion.cpp:140-160`).
|
|||
|
|
- Le nom Python `unreal.SystemLibrary` est celui que le script emploie déjà pour `quit_editor` (`RP:344`, `KismetSystemLibrary.h:656`).
|
|||
|
|
- Version de l'installation : `Build.version`, 5.8.3 (5.5 : 5.5.4).
|
|||
|
|
|
|||
|
|
### 5.3 Correctif de portage non appliqué
|
|||
|
|
Aucune des lignes du diff de U7b-T2-CART § 5 n'est présente :
|
|||
|
|
`grep -c "run_batch_retarget\|add_retarget_op\|set_fk_chains" Tools/anim/RetargetPack.py` = 0.
|
|||
|
|
|
|||
|
|
## 6. Essais statiques (hors moteur, bloc-notes de session)
|
|||
|
|
Dossier : `%USERPROFILE%\AppData\Local\Temp\claude\D--Game-LifePlay-master-5-5\ab8918a1-261f-45b4-904a-678ecfce98f7\scratchpad\u7bt4\`.
|
|||
|
|
|
|||
|
|
1. **Garde-fou** : `python -I -B test_guard.py`, avec le faux module `stub\unreal.py`. Tout appel d'asset y lève une
|
|||
|
|
erreur. Le script importé est le vrai `RetargetPack.py` de l'addon. Résultat : `echecs : 0`, code 0.
|
|||
|
|
- Versions `5.8.3-58210709+++UE5+Release-5.8`, `5.6.0-…`, `6.0.0-…` et `illisible` :
|
|||
|
|
- journal = `RETARGET moteur <v>` puis `RETARGET echec : RetargetPack : API IK Retargeter 5.8 non portee (U7b-T2-CART, reporte apres V2.0) ; aucun asset modifie jeton abc123def456` ;
|
|||
|
|
- appels = `get_engine_version` puis `quit_editor` seulement, soit **0 appel d'asset**.
|
|||
|
|
- Version `5.5.4-40574608+++UE5+Release-5.5` : le garde-fou laisse passer. Le premier appel d'asset est
|
|||
|
|
`load_asset /Game/Quaternius/UAL/UAL1_Standard…`, que le faux module fait échouer volontairement.
|
|||
|
|
- Aucun `__pycache__` n'a été créé dans l'addon (`git status --short --ignored Tools/anim` : seulement les 2 `M`).
|
|||
|
|
2. **Lanceur** : `pwsh -NoProfile -File sim\run_sim.ps1`.
|
|||
|
|
- Faux `UnrealEditor.exe` compilé par `csc.exe` (.NET Framework 4, `/target:winexe`) : il écrit `Environment.CommandLine`.
|
|||
|
|
- Copies de l'ancien et du nouveau .bat, dans `sim\dossier avec espace\`. Leur moteur par défaut est remplacé par un
|
|||
|
|
chemin absent, et `LP_ENGINE_ROOT`/`LP_GAMEROOT` pointent vers des dossiers factices : aucun moteur réel ne pouvait partir.
|
|||
|
|
- Les 7 cas et les 6 comparaisons sont au § 4 : toutes à True.
|
|||
|
|
3. **Regex de BuildMod** : `pwsh -NoProfile -File test_find.ps1`. La fonction `Find-RetargetLine` est extraite de
|
|||
|
|
`BuildMod.ps1` par l'AST (BuildMod n'est pas exécuté). Pour les modes `bake` et `rigs` : `Hit=[]` et
|
|||
|
|
`Failure=[RETARGET echec : RetargetPack : … aucun asset modifie jeton abc123def456]`.
|
|||
|
|
4. **Syntaxe** :
|
|||
|
|
- `ast.parse(RetargetPack.py)` : OK ;
|
|||
|
|
- `[Parser]::ParseFile(AnimPipeline.ps1)` : `erreurs de syntaxe : 0`.
|
|||
|
|
|
|||
|
|
## 7. Écarts à la fiche et à la SPEC
|
|||
|
|
|
|||
|
|
1. Le **.bat est modifié** (cas « si nécessaire » de la fiche). Il ne transmettait pas `%*`. Je l'ai ajouté à l'instantané
|
|||
|
|
avant de le modifier, avec la commande de la fiche.
|
|||
|
|
2. **Forme `EXTRA` au lieu d'un `%*` brut** en fin de ligne. Le `%*` brut ajoutait une espace finale à la ligne
|
|||
|
|
interactive (constaté au § 6.2). La forme retenue donne une ligne identique à l'octet. Elle coûte 2 lignes de plus
|
|||
|
|
que la suggestion de la fiche.
|
|||
|
|
3. Le garde-fou **refuse aussi une version illisible**, par prudence : rien ne prouve alors un moteur antérieur à 5.6.
|
|||
|
|
Il écrit en plus la ligne `RETARGET moteur <version>` avant le refus. Le message de refus est exactement celui de la
|
|||
|
|
fiche, préfixé par `RETARGET echec : ` et suivi de ` jeton <j>` (format existant, `RP:476-478`).
|
|||
|
|
4. « Ne rien lancer » : je n'ai lancé ni jeu, ni éditeur, ni pipeline. J'ai en revanche exécuté des essais statiques
|
|||
|
|
hors moteur (§ 6) : le vrai script Python avec un faux module `unreal`, et les copies du .bat avec un faux exécutable.
|
|||
|
|
C'est une lecture de la consigne, que je signale ici.
|
|||
|
|
5. Erreur de lecture corrigée en cours de travail : un premier `grep -c $'\r$'` sous Git Bash avait donné « CRLF » pour
|
|||
|
|
les 3 fichiers. Le comptage sur les octets montre que `AnimPipeline.ps1` et `RetargetPack.py` sont en **LF** et le .bat
|
|||
|
|
en **CRLF**. Mon premier script de remplacement s'est donc arrêté sur `AnimPipeline.ps1` : 0 occurrence, aucune écriture.
|
|||
|
|
Le .bat, déjà traité à ce moment, était en CRLF et l'est resté. Le second script détecte la fin de ligne de chaque
|
|||
|
|
fichier. État final au § 1.
|
|||
|
|
6. Docs non mises à jour (hors fichiers autorisés) : `D:\Game\LifePlay-master 5.8\Docs\Migration\20_Chaine_Animations.md`
|
|||
|
|
(étape 5) et `21_Sandbox_Addon.md` (lanceurs, report U5 de RetargetPack). Elles relèvent de la phase DOC.
|
|||
|
|
|
|||
|
|
## 8. Incertitudes
|
|||
|
|
|
|||
|
|
- **Comportement réel de `-RenderOffScreen` en 5.8** : taille effective du viewport (avec `r.setres:1280x720` en
|
|||
|
|
config), rythme des images, géométrie. Ce sont les risques (a) et (b) de U7b-T1-CART § 4.1. Ils restent **incertains**
|
|||
|
|
jusqu'à l'essai du § 9.
|
|||
|
|
- **Garde-fou dans l'éditeur 5.8 réel** : il a été essayé avec un faux module seulement. La chaîne `get_engine_version` →
|
|||
|
|
`ToString` est établie par les sources, le comportement Python de bout en bout ne l'est pas. Essai sans risque
|
|||
|
|
proposé pour la VAL :
|
|||
|
|
- commande : `BuildMod.ps1 -GameRoot "D:\Game\LifePlay-master 5.8" -Retarget rigs -RetargetOnly -RetargetConfig <json>`,
|
|||
|
|
avec `{"mode":"rigs","methode":"ue4","dest":"/Game/_TempU7b/Retarget"}` (mode `rigs` sur une destination temporaire :
|
|||
|
|
même si le garde-fou ne jouait pas, ni référence ni clip ne seraient touchés) ;
|
|||
|
|
- attendu : `Conversion en echec : RETARGET echec : RetargetPack : API IK Retargeter 5.8 non portee … jeton <j>`, et
|
|||
|
|
`/Game/_TempU7b` absent.
|
|||
|
|
- **Anomalie hors de mon périmètre (établi, à examiner avant l'essai T1)** : la copie de jeu 5.8 a des modifications qui
|
|||
|
|
ne viennent pas de moi (`git -C "D:\Game\LifePlay-master 5.8" status --short` : `M .gitignore`, `M LifePlay.uproject`).
|
|||
|
|
- `.gitignore` est modifié à 13:31:19, avant le début de cette fiche : bloc `# BEGIN HYPERAISTUDIO MANAGED RUNTIME IGNORE`.
|
|||
|
|
- `LifePlay.uproject` est modifié à 13:36:27, soit 105 lignes : des plugins Éditeur `AIModuleToolset`,
|
|||
|
|
`AnimationAssistantToolset`, `AutomationTestToolset`, `ConfigSettingsToolset`, `DataflowAgent`, etc. ont été activés.
|
|||
|
|
- Aucune de mes commandes n'écrit dans ce dossier. La seule qui s'y place est `Snapshot.ps1` (`Set-Location`), et elle
|
|||
|
|
copie seulement vers `Backup_5.5`.
|
|||
|
|
- L'essai T1 lance ce `.uproject` : l'orchestrateur doit décider s'il garde ou restaure cet état avant l'essai.
|
|||
|
|
Je n'y ai pas touché.
|
|||
|
|
|
|||
|
|
## 9. Essai T1 à confier à lp-builder (une tournée d'un clip, `AS_RightLegKick2`, pack freeanims)
|
|||
|
|
|
|||
|
|
Conditions préalables :
|
|||
|
|
- pwsh 7, éditeur fermé ;
|
|||
|
|
- build 5.8 du jeu à jour (aucun C++ modifié par cette fiche) ;
|
|||
|
|
- DLL de l'addon vérifiées (lp-build § 8) ;
|
|||
|
|
- anomalie du § 8 tranchée.
|
|||
|
|
|
|||
|
|
L'essai ne lance pas AnimPipeline. Il reproduit `Invoke-Sandbox` pour un seul clip, avec le même appel
|
|||
|
|
`cmd /c` que `AnimPipeline.ps1:339`. La sortie va dans un dossier neuf, `Saved\U7b\T1essai_<date>`, pour ne pas écraser
|
|||
|
|
les planches de U4-T6.
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
$G = 'D:\Game\LifePlay-master 5.8'; $S = "$G\Saved"
|
|||
|
|
$bat = 'D:\Game\LifePlay-Sandbox-5.8\Tools\debug\LifePlay_interaction_sandbox.bat'
|
|||
|
|
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'; $rel = "U7b/T1essai_$stamp"; $W = "$S\U7b\T1essai_$stamp"
|
|||
|
|
if (Get-Process UnrealEditor, UnrealEditor-Cmd -ErrorAction SilentlyContinue) { throw 'editeur ouvert' }
|
|||
|
|
New-Item -ItemType Directory -Force $W | Out-Null
|
|||
|
|
$utf8 = New-Object Text.UTF8Encoding $false
|
|||
|
|
$origMode = if (Test-Path "$S\sandbox_mode.txt") { [IO.File]::ReadAllText("$S\sandbox_mode.txt") } else { $null } # 'Pair' le 2026-10-09
|
|||
|
|
foreach ($f in 'sandbox_pack.ini', 'sandbox_tour.txt') { if (Test-Path "$S\$f") { Move-Item "$S\$f" "$W\$f.avant" } }
|
|||
|
|
$ini = [IO.File]::ReadAllText("$S\AnimPipeline\freeanims\sandbox_pack.ini") -replace 'MeasureOutputRoot=.*', "MeasureOutputRoot=$rel/sandbox"
|
|||
|
|
[IO.File]::WriteAllText("$S\sandbox_pack.ini", $ini, $utf8)
|
|||
|
|
[IO.File]::WriteAllText("$S\sandbox_mode.txt", 'Mesure', $utf8)
|
|||
|
|
[IO.File]::WriteAllText("$S\sandbox_tour.txt", 'vignettes planches quitter AS_RightLegKick2', $utf8)
|
|||
|
|
try {
|
|||
|
|
Start-Process -FilePath 'cmd.exe' -ArgumentList ('/c ""{0}" {1}"' -f $bat, '-RenderOffScreen') -WindowStyle Hidden | Out-Null
|
|||
|
|
$d = (Get-Date).AddMinutes(3); while (-not (Get-Process UnrealEditor -ErrorAction SilentlyContinue) -and (Get-Date) -lt $d) { Start-Sleep 3 }
|
|||
|
|
if (-not (Get-Process UnrealEditor -ErrorAction SilentlyContinue)) { throw 'sandbox non lancee (3 min)' }
|
|||
|
|
$d = (Get-Date).AddMinutes(15); while ((Get-Process UnrealEditor -ErrorAction SilentlyContinue) -and (Get-Date) -lt $d) { Start-Sleep 5 }
|
|||
|
|
if (Get-Process UnrealEditor -ErrorAction SilentlyContinue) { throw 'sandbox non fermee en 15 min (laissee ouverte)' }
|
|||
|
|
}
|
|||
|
|
finally {
|
|||
|
|
foreach ($f in 'sandbox_pack.ini', 'sandbox_tour.txt', 'sandbox_mode.txt') { if (Test-Path "$S\$f") { Move-Item "$S\$f" "$W\$f" -Force } }
|
|||
|
|
if ($null -ne $origMode) { [IO.File]::WriteAllText("$S\sandbox_mode.txt", $origMode, $utf8) }
|
|||
|
|
foreach ($f in 'sandbox_pack.ini', 'sandbox_tour.txt') { if (Test-Path "$W\$f.avant") { Move-Item "$W\$f.avant" "$S\$f" } }
|
|||
|
|
}
|
|||
|
|
Copy-Item "$S\Logs\LifePlay.log" "$W\LifePlay.log"
|
|||
|
|
Select-String -Path "$W\LifePlay.log" -Pattern 'Command Line:', 'VIGNETTE .*AS_RightLegKick2', 'PLANCHE .*AS_RightLegKick2', 'Assertion failed', 'out of bounds' | ForEach-Object { $_.Line }
|
|||
|
|
Get-ChildItem "$W\sandbox" -Recurse -File | Select-Object FullName, Length
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Attendus (référence U7b-T1-CART § 6.1, relue dans `D:\Game\LifePlay_Backup_5.5\U4-REF55\E4_freeanims.log:1939, 5460`
|
|||
|
|
et `U4-T6\E4_freeanims.log:2277, 5806`) :
|
|||
|
|
- ligne `LogInit: Command Line:` terminée par ` -RenderOffScreen` ;
|
|||
|
|
- `VIGNETTE …/vignettes/AS_RightLegKick2.png (carre 695 px a 621,173)` ;
|
|||
|
|
- `PLANCHE …/planches/AS_RightLegKick2.jpg 13 images 1.10 s <n> octets (carre 724 px)` (le nombre d'octets varie :
|
|||
|
|
88113 en 5.5, 88496 en 5.8) ;
|
|||
|
|
- 0 `Assertion failed`, 0 `out of bounds` ;
|
|||
|
|
- fichiers `vignettes\AS_RightLegKick2.png` (512×512), `planches\AS_RightLegKick2.jpg` (3328×256 pour 13 images) et
|
|||
|
|
`planches\AS_RightLegKick2.json`.
|
|||
|
|
|
|||
|
|
Le dossier de sortie est créé par la tournée (`MakeDirectory(…, true)`, `LPSandboxMeasureTour.cpp:421, 426, 432`).
|
|||
|
|
Après l'essai, `Saved\sandbox_mode.txt` doit valoir à nouveau `Pair`. Variante pour un essai contraire : réduire une
|
|||
|
|
fenêtre est sans objet, puisqu'il n'y a plus de fenêtre système.
|
|||
|
|
|
|||
|
|
## 10. État final
|
|||
|
|
|
|||
|
|
`git -C D:\Game\LifePlay-Sandbox-5.8 status --short` :
|
|||
|
|
```
|
|||
|
|
M Tools/anim/AnimPipeline.ps1
|
|||
|
|
M Tools/anim/RetargetPack.py
|
|||
|
|
M Tools/debug/LifePlay_interaction_sandbox.bat
|
|||
|
|
```
|
|||
|
|
- `git -C D:\Game\LifePlay-Sandbox status --short` (checkout 5.5) : 0 ligne.
|
|||
|
|
- Fichiers écrits :
|
|||
|
|
- les 3 fichiers ci-dessus ;
|
|||
|
|
- `D:\Game\LifePlay_Backup_5.5\U7b-addon\manifest.csv` (+1 entrée) et `D:\Game\LifePlay_Backup_5.5\U7b-addon\Tools\debug\LifePlay_interaction_sandbox.bat` ;
|
|||
|
|
- ce livrable ;
|
|||
|
|
- les fichiers d'essai du bloc-notes de session (hors projet).
|
|||
|
|
- Retour arrière proposé, non exécuté :
|
|||
|
|
`pwsh -NoProfile -Command "Set-Location 'D:\Game\LifePlay-master 5.8'; .\Tools\Restore.ps1 -Lot U7b-addon -ProjectRoot 'D:\Game\LifePlay-Sandbox-5.8'"`,
|
|||
|
|
ou `git -C D:\Game\LifePlay-Sandbox-5.8 checkout -- <fichier>`.
|