UI14 : menu principal (version 2026.10.4, credits Vinfamy, Donate Patreon edujiro5972, Discord, Commission masque)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
53a5209fdb
commit
3c25b1450b
11 changed files with 377 additions and 2 deletions
|
|
@ -1,7 +1,7 @@
|
|||
[/Script/EngineSettings.GeneralProjectSettings]
|
||||
ProjectID=543F4F9E4DE525696C82F5A52303C15C
|
||||
ProjectName=LifePlay
|
||||
ProjectVersion=2026.9 beta
|
||||
ProjectVersion=2026.10.4
|
||||
Description=Portage UE 5.5 - assets integres depuis LifePlay 5.9 Full Source
|
||||
|
||||
[/Script/MoviePlayer.MoviePlayerSettings]
|
||||
|
|
|
|||
Binary file not shown.
43
Docs/Migration/14_Interface_V1.4.md
Normal file
43
Docs/Migration/14_Interface_V1.4.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 14. Interface du menu principal (lot UI14, avant la V1.4)
|
||||
|
||||
Demande utilisateur (2026-10-02) : numéro de version au format année.mois.publication, liste des crédits vidée avec
|
||||
Vinfamy comme auteur original, lien Donate vers le Patreon de LifePlay Revival, nouveau lien Discord, bouton
|
||||
« Commission Game Content » masqué (il menait à une page de Vinfamy).
|
||||
|
||||
## 1. Où se trouvent ces éléments
|
||||
|
||||
| Élément | Emplacement | Avant |
|
||||
|---|---|---|
|
||||
| Texte de version | `UI/MainMenu`, fonction `Get_Version_Text_0` : `FormatText("LifePlay v{main}.{sub}{text}")` avec `GI.version_main`, `version_sub` (flottants, 5 et 9), `version_text` | « LifePlay v5.9 » |
|
||||
| Titre des crédits | `UI/MainMenu`, `TextBlock_19` | « This project wouldn't be possible without the suppport from my generous patrons: » |
|
||||
| Liste des crédits | `Content/Modules/donors.txt`, lu par `MainMenu` (`LoadTxt`, 4 colonnes) | 319 noms de donateurs de Vinfamy |
|
||||
| Donate | `MainMenu` EventGraph, `K2Node_CallFunction_45` (`LaunchURL`, 3 boutons) | `https://www.patreon.com/vinfamy` |
|
||||
| Discord | `MainMenu` EventGraph, `K2Node_CallFunction_32` (`LaunchURL`) | `https://discord.gg/eUEUhc6` |
|
||||
| Commission Game Content | `MainMenu`, `CommissionButton` (visibilité liée à une fonction de l'écran titre) | visible |
|
||||
|
||||
`GI.version_main` et `version_sub` servent aussi aux sauvegardes et à `GI.ReturnStatIfNeeded` : ils ne sont pas modifiés.
|
||||
|
||||
## 2. Réalisation
|
||||
|
||||
- **Version** : format du menu ramené à `LifePlay {text}` ; nouveau sous-système `Source/LifePlay/LPVersionSubsystem`
|
||||
qui remplit `GI.version_text` au démarrage avec `ProjectVersion` de `Config/DefaultGame.ini`
|
||||
(`[/Script/EngineSettings.GeneralProjectSettings]`). Format : **année.mois.publication**, le dernier nombre étant un
|
||||
compteur de publications (V1.4 = 4) : `ProjectVersion=2026.10.4`. **À chaque publication**, mettre à jour cette ligne
|
||||
(année et mois de la publication, compteur + 1).
|
||||
- **Menu** : nouvelle commandlet `LPEditWidget` (`Source/LifePlayEditorTools`), pilotée par une spécification versionnée
|
||||
`Tools/ui/MainMenu_V1.4.json` ; chaque modification indique la valeur attendue avant (sinon rien n'est écrit), le
|
||||
widget est compilé sans erreur puis sauvegardé. Modifications : format de version, URL Donate
|
||||
(`https://www.patreon.com/cw/edujiro5972`) et Discord (`https://discord.gg/q4689pNSy`), titre des crédits
|
||||
(« Original author: »), infobulle Donate (« Support LifePlay Revival on Patreon »), `CommissionButton` masqué
|
||||
(liaison de visibilité retirée).
|
||||
- **Crédits** : `Content/Modules/donors.txt` réduit à `Vinfamy`.
|
||||
- Liens laissés inchangés (non demandés) : f95zone et bilan 2021 de Vinfamy.
|
||||
|
||||
## 3. Contrôles
|
||||
|
||||
- Essai à blanc : 6 modifications trouvées, toutes conformes aux valeurs attendues.
|
||||
- Comparaison avant/après (`LPDumpFunction`, `LPDumpWidgetTree`) : seuls changent les broches `main`/`sub` du format
|
||||
(retirées), les deux URL, le titre, l'infobulle et la visibilité du bouton.
|
||||
- Build `LifePlay_Build_5.5_UI14` : « Version affichee : LifePlay 2026.10.4 » ; avertissements de script identiques au
|
||||
build précédent (16 « Accessed None », déjà présents).
|
||||
- Sauvegarde : `D:\Game\LifePlay_Backup_5.5\UI14` (`MainMenu.uasset`, `donors.txt`) ; retour : `Tools\Restore.ps1 -Lot UI14`.
|
||||
|
|
@ -938,3 +938,4 @@ Validation L7c/L7d (2026-10-02, parc, même cadrage) : la nuit reste claire (sol
|
|||
| CHG-091 | 2026-10-02 | Doc | nouveaux `Docs/Migration/13_Protocole_Coiffure.md`, `Tools/HairImportFbx.py`, `Tools/HairMaterials.py` ; `README.md` (migration), `08_Guide_Developpeur.md`, `09_Commandes_Utiles.md` | protocole de conversion d'une coiffure (demande utilisateur) ; scripts ponctuels d'O7e rendus paramétrables ; protocole rejoué de bout en bout sur Pocolov 17 sous le nom `Pocolov17P` : bornes identiques au millimètre, dépendances OK ; essai retiré du projet (`D:\Game\LifePlay_Backup_5.5\O7e\proto_essai`) | `git revert` du commit |
|
||||
| CHG-092 | 2026-10-02 | HAIRS1 | nouveaux `Tools/HairPipeline.ps1`, `Tools/FbxMaterialMap.py`, `Tools/hairs/HAIRS1.json` ; `Tools/HairImportFbx.py` (rapport JSON), `Tools/HairMaterials.py` (calotte seulement si utilisée, contrôle des dépendances) ; assets `Content/Heavy/New5/Hairs/Pocolov03/06/11/15/16*` (hors dépôt) ; `Content/Modules/lp_Revival/Hairstyles/pocolov03/06/11/15/16.lphair` ; `Licenses/Free_3D_Models_Credits.txt` ; `13_Protocole_Coiffure.md` §7 | industrialisation de la conversion (demande utilisateur) et test sur 5 coiffures Pocolov (CC BY 4.0, téléchargées avec l'accord de l'utilisateur) ; 5 cas d'archives différents intégrés aux règles ; build `LifePlay_Build_5.5_HAIRS1` : 6 coiffures ajoutées (index 126 à 131) ; contrôle visuel en jeu en attente | retirer les `.lphair` ; assets et sources dans `D:\Game\LifePlay_Backup_5.5\HAIRS1` ; `git checkout HAIRS1-avant -- Tools Licenses Content/Modules` |
|
||||
| CHG-093 | 2026-10-02 | SKIN | `LPHairFromStaticMeshCommandlet` : liaison par transfert de poids depuis le corps (`-Skin=transfer` par défaut, 6 voisins, bras et jambes exclus) et sortie de la peau (`-Gap` 0,3 cm) ; `LifePlayEditorTools.Build.cs` (`SkeletalMeshDescription`, `AnimationCore`) ; `HairPipeline.ps1` (`-Rebuild`, options `skin`, `gap`) ; 6 coiffures Pocolov reconstruites (versions précédentes dans `HAIRS1\<nom>\precedente_*`), Pocolov 17 ajoutée au lot ; `.lphair` et crédits : description des modifications corrigée ; `13_Protocole_Coiffure.md` | vidéo utilisateur : mèches longues liées à la seule tête, qui traversent épaules et poitrine quand la tête tourne ; poids obtenus : tête 47 à 62 %, cou, clavicules, poitrine ; 254 à 950 sommets sortis de la peau par coiffure ; build `LifePlay_Build_5.5_SKIN` ; validé en jeu le 2026-10-02 (les mèches ne traversent plus la peau quand la tête tourne) | `-Skin=rigid` ; `git checkout SKIN-avant -- Source Tools` et remettre les versions précédentes |
|
||||
| CHG-094 | 2026-10-02 | UI14 | nouveaux `Source/LifePlay/LPVersionSubsystem.h/.cpp`, `Source/LifePlayEditorTools/LPEditWidgetCommandlet.h/.cpp` (+ `Json` dans le `.Build.cs`), `Tools/ui/MainMenu_V1.4.json`, `Docs/Migration/14_Interface_V1.4.md` ; `Content/UI/MainMenu.uasset` (6 modifications, diff conforme) ; `Content/Modules/donors.txt` (→ `Vinfamy`) ; `Config/DefaultGame.ini` (`ProjectVersion=2026.10.4`) | demande utilisateur avant la V1.4 : version année.mois.publication, crédits vidés avec Vinfamy auteur original, Donate → Patreon edujiro5972, Discord → discord.gg/q4689pNSy, Commission masqué ; build `LifePlay_Build_5.5_UI14` : « LifePlay 2026.10.4 » ; contrôle en jeu en attente | `Tools\Restore.ps1 -Lot UI14` ; `git checkout UI14-avant -- Config Source Content/Modules/donors.txt` |
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ La migration a été reprise le 2026-09-29, après l'échec d'un premier portage
|
|||
| [11_Audit_Optimisation.md](11_Audit_Optimisation.md) | pilotage | chantier d'optimisation UE5 : audit (lot O0), goulots, leviers, lots O1 à O8, Fab |
|
||||
| [12_Reconciliation_Vinfamy.md](12_Reconciliation_Vinfamy.md) | historique | comparaison avec `vinfamy/LifePlay`, fusion d'historique, rien à récupérer |
|
||||
| [13_Protocole_Coiffure.md](13_Protocole_Coiffure.md) | protocole | ajouter une coiffure (FBX statique, Fab) : import, ajustement sur la tête de Bridget, matériaux, fichier `.lphair`, contrôles |
|
||||
| [14_Interface_V1.4.md](14_Interface_V1.4.md) | lot | menu principal : version année.mois.publication, crédits (Vinfamy, auteur original), liens Donate et Discord, bouton Commission masqué |
|
||||
| [Journal_Modifications.md](Journal_Modifications.md) | traçabilité | `CHG-001` à `CHG-057`, chacune avec son retour arrière |
|
||||
| [Registre_Erreurs.md](Registre_Erreurs.md) | traçabilité | `ERR-001` à `ERR-037`, statut et lot |
|
||||
| `correctifs/` | relecture | écarts de code 4.27 → 5.5 en patchs (`P01` à `P06`) |
|
||||
|
|
|
|||
23
Source/LifePlay/LPVersionSubsystem.cpp
Normal file
23
Source/LifePlay/LPVersionSubsystem.cpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Portage UE 5.5 - voir LPVersionSubsystem.h
|
||||
|
||||
#include "LPVersionSubsystem.h"
|
||||
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "GeneralProjectSettings.h"
|
||||
#include "LifePlay.h"
|
||||
#include "UObject/UnrealType.h"
|
||||
|
||||
void ULPVersionSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
UGameInstance* GI = GetGameInstance();
|
||||
const FStrProperty* Prop = GI ? CastField<FStrProperty>(GI->GetClass()->FindPropertyByName(TEXT("version_text"))) : nullptr;
|
||||
const FString Version = GetDefault<UGeneralProjectSettings>()->ProjectVersion;
|
||||
if (!Prop)
|
||||
{
|
||||
UE_LOG(LogLifePlay, Warning, TEXT("Version : GI.version_text introuvable sur %s, version %s non affichee"), *GetNameSafe(GI), *Version);
|
||||
return;
|
||||
}
|
||||
Prop->SetPropertyValue_InContainer(GI, Version);
|
||||
UE_LOG(LogLifePlay, Display, TEXT("Version affichee : LifePlay %s"), *Version);
|
||||
}
|
||||
21
Source/LifePlay/LPVersionSubsystem.h
Normal file
21
Source/LifePlay/LPVersionSubsystem.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Portage UE 5.5 - lot UI14 (Docs/Migration/14_Interface_V1.4.md).
|
||||
//
|
||||
// Le menu principal affiche "LifePlay {text}" (UI/MainMenu, Get_Version_Text_0) avec text = GI.version_text. Ce
|
||||
// sous-systeme remplit GI.version_text au demarrage avec la version du projet (Config/DefaultGame.ini,
|
||||
// [/Script/EngineSettings.GeneralProjectSettings] ProjectVersion, format annee.mois.publication : 2026.10.4).
|
||||
// GI.version_main et GI.version_sub (5 et 9, utilises par les sauvegardes et ReturnStatIfNeeded) ne sont pas modifies.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "LPVersionSubsystem.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class LIFEPLAY_API ULPVersionSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
};
|
||||
240
Source/LifePlayEditorTools/LPEditWidgetCommandlet.cpp
Normal file
240
Source/LifePlayEditorTools/LPEditWidgetCommandlet.cpp
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
// Portage UE 5.5 - voir LPEditWidgetCommandlet.h
|
||||
|
||||
#include "LPEditWidgetCommandlet.h"
|
||||
|
||||
#include "Blueprint/WidgetTree.h"
|
||||
#include "Components/TextBlock.h"
|
||||
#include "Components/Widget.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "EdGraph/EdGraph.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "K2Node.h"
|
||||
#include "Kismet2/KismetEditorUtilities.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/PackageName.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
#include "UObject/Package.h"
|
||||
#include "UObject/SavePackage.h"
|
||||
#include "WidgetBlueprint.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogLPEditWidget, Log, All);
|
||||
|
||||
namespace
|
||||
{
|
||||
UEdGraphNode* FindNode(UBlueprint* BP, const FString& GraphName, const FString& NodeName)
|
||||
{
|
||||
TArray<UEdGraph*> Graphs;
|
||||
BP->GetAllGraphs(Graphs);
|
||||
for (UEdGraph* Graph : Graphs)
|
||||
{
|
||||
if (Graph && Graph->GetName() == GraphName)
|
||||
{
|
||||
for (UEdGraphNode* Node : Graph->Nodes)
|
||||
{
|
||||
if (Node && Node->GetName() == NodeName)
|
||||
{
|
||||
return Node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** Valeur par defaut d'une broche, texte ou non, telle qu'affichee. */
|
||||
FString PinValue(const UEdGraphPin* Pin)
|
||||
{
|
||||
return Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Text ? Pin->DefaultTextValue.ToString() : Pin->DefaultValue;
|
||||
}
|
||||
|
||||
bool ParseVisibility(const FString& Text, ESlateVisibility& Out)
|
||||
{
|
||||
const UEnum* Enum = StaticEnum<ESlateVisibility>();
|
||||
const int64 Value = Enum->GetValueByNameString(Text);
|
||||
if (Value == INDEX_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Out = static_cast<ESlateVisibility>(Value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ULPEditWidgetCommandlet::ULPEditWidgetCommandlet()
|
||||
{
|
||||
IsClient = false;
|
||||
IsEditor = true;
|
||||
IsServer = false;
|
||||
LogToConsole = true;
|
||||
}
|
||||
|
||||
int32 ULPEditWidgetCommandlet::Main(const FString& Params)
|
||||
{
|
||||
TArray<FString> Tokens, Switches;
|
||||
TMap<FString, FString> P;
|
||||
ParseCommandLine(*Params, Tokens, Switches, P);
|
||||
const bool bDryRun = Switches.Contains(TEXT("DryRun"));
|
||||
FString Json;
|
||||
TSharedPtr<FJsonObject> Spec;
|
||||
if (!FFileHelper::LoadFileToString(Json, *P.FindRef(TEXT("Spec"))) || !FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(Json), Spec) || !Spec.IsValid())
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("Usage : -Spec=<fichier.json> [-DryRun] (fichier illisible : %s)"), *P.FindRef(TEXT("Spec")));
|
||||
return 1;
|
||||
}
|
||||
const FString BPPath = Spec->GetStringField(TEXT("bp"));
|
||||
UWidgetBlueprint* BP = LoadObject<UWidgetBlueprint>(nullptr, *(BPPath + TEXT(".") + FPackageName::GetShortName(BPPath)));
|
||||
if (!BP || !BP->WidgetTree)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("Blueprint de widget introuvable : %s"), *BPPath);
|
||||
return 1;
|
||||
}
|
||||
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
int32 Errors = 0, Changes = 0;
|
||||
|
||||
// 1. Broches.
|
||||
const TArray<TSharedPtr<FJsonValue>>* Pins = nullptr;
|
||||
if (Spec->TryGetArrayField(TEXT("pins"), Pins))
|
||||
{
|
||||
for (const TSharedPtr<FJsonValue>& V : *Pins)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>& O = V->AsObject();
|
||||
const FString Where = O->GetStringField(TEXT("graph")) + TEXT(" / ") + O->GetStringField(TEXT("node")) + TEXT(" . ") + O->GetStringField(TEXT("pin"));
|
||||
UEdGraphNode* Node = FindNode(BP, O->GetStringField(TEXT("graph")), O->GetStringField(TEXT("node")));
|
||||
UEdGraphPin* Pin = Node ? Node->FindPin(*O->GetStringField(TEXT("pin"))) : nullptr;
|
||||
if (!Pin)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("Broche introuvable : %s"), *Where);
|
||||
++Errors;
|
||||
continue;
|
||||
}
|
||||
const FString Before = PinValue(Pin);
|
||||
const FString Expect = O->GetStringField(TEXT("expect"));
|
||||
const FString Value = O->GetStringField(TEXT("value"));
|
||||
if (Before == Value)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT(" %s : deja a la valeur cible"), *Where);
|
||||
continue;
|
||||
}
|
||||
if (Before != Expect)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT(" %s : valeur actuelle '%s', attendue '%s'"), *Where, *Before, *Expect);
|
||||
++Errors;
|
||||
continue;
|
||||
}
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT(" %s : '%s' -> '%s'"), *Where, *Before, *Value);
|
||||
if (!bDryRun)
|
||||
{
|
||||
if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Text)
|
||||
{
|
||||
Schema->TrySetDefaultText(*Pin, FText::FromString(Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
Schema->TrySetDefaultValue(*Pin, Value);
|
||||
}
|
||||
if (PinValue(Pin) != Value)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT(" %s : valeur relue '%s' apres modification"), *Where, *PinValue(Pin));
|
||||
++Errors;
|
||||
}
|
||||
}
|
||||
++Changes;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Elements de l'arbre.
|
||||
const TArray<TSharedPtr<FJsonValue>>* Widgets = nullptr;
|
||||
if (Spec->TryGetArrayField(TEXT("widgets"), Widgets))
|
||||
{
|
||||
for (const TSharedPtr<FJsonValue>& V : *Widgets)
|
||||
{
|
||||
const TSharedPtr<FJsonObject>& O = V->AsObject();
|
||||
const FString Name = O->GetStringField(TEXT("name"));
|
||||
UWidget* Widget = BP->WidgetTree->FindWidget(FName(*Name));
|
||||
if (!Widget)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("Element introuvable : %s"), *Name);
|
||||
++Errors;
|
||||
continue;
|
||||
}
|
||||
FString Text;
|
||||
if (O->TryGetStringField(TEXT("text"), Text))
|
||||
{
|
||||
UTextBlock* TextBlock = Cast<UTextBlock>(Widget);
|
||||
const FString Before = TextBlock ? TextBlock->GetText().ToString() : FString();
|
||||
if (!TextBlock || Before != O->GetStringField(TEXT("expect_text")))
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT(" %s : texte actuel '%s', attendu '%s'"), *Name, *Before, *O->GetStringField(TEXT("expect_text")));
|
||||
++Errors;
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT(" %s.Text : '%s' -> '%s'"), *Name, *Before, *Text);
|
||||
if (!bDryRun) { TextBlock->SetText(FText::FromString(Text)); }
|
||||
++Changes;
|
||||
}
|
||||
}
|
||||
FString Tooltip;
|
||||
if (O->TryGetStringField(TEXT("tooltip"), Tooltip))
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT(" %s.ToolTipText : '%s' -> '%s'"), *Name, *Widget->GetToolTipText().ToString(), *Tooltip);
|
||||
if (!bDryRun) { Widget->SetToolTipText(FText::FromString(Tooltip)); }
|
||||
++Changes;
|
||||
}
|
||||
FString VisibilityText;
|
||||
if (O->TryGetStringField(TEXT("visibility"), VisibilityText))
|
||||
{
|
||||
ESlateVisibility Visibility;
|
||||
if (!ParseVisibility(VisibilityText, Visibility))
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT(" %s : visibilite inconnue '%s'"), *Name, *VisibilityText);
|
||||
++Errors;
|
||||
continue;
|
||||
}
|
||||
const int32 Bound = BP->Bindings.IndexOfByPredicate([&](const FDelegateEditorBinding& B) { return B.ObjectName == Name && B.PropertyName == TEXT("Visibility"); });
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT(" %s.Visibility : %s -> %s%s"), *Name, *StaticEnum<ESlateVisibility>()->GetNameStringByValue(int64(Widget->GetVisibility())),
|
||||
*VisibilityText, Bound != INDEX_NONE ? TEXT(" (liaison de visibilite retiree)") : TEXT(""));
|
||||
if (!bDryRun)
|
||||
{
|
||||
Widget->SetVisibility(Visibility);
|
||||
if (Bound != INDEX_NONE) { BP->Bindings.RemoveAt(Bound); }
|
||||
}
|
||||
++Changes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Errors > 0)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("%d erreur(s) : rien n'est sauvegarde"), Errors);
|
||||
return 1;
|
||||
}
|
||||
if (bDryRun || Changes == 0)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT("%d modification(s) %s"), Changes, bDryRun ? TEXT("(essai a blanc, rien n'est sauvegarde)") : TEXT(": rien a faire"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 3. Compilation et sauvegarde.
|
||||
BP->Modify();
|
||||
FKismetEditorUtilities::CompileBlueprint(BP);
|
||||
if (BP->Status == BS_Error)
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("Compilation en erreur : rien n'est sauvegarde"));
|
||||
return 1;
|
||||
}
|
||||
UPackage* Package = BP->GetOutermost();
|
||||
Package->MarkPackageDirty();
|
||||
const FString Filename = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
|
||||
FSavePackageArgs SaveArgs;
|
||||
SaveArgs.TopLevelFlags = RF_Public | RF_Standalone;
|
||||
SaveArgs.Error = GWarn;
|
||||
if (!UPackage::SavePackage(Package, nullptr, *Filename, SaveArgs))
|
||||
{
|
||||
UE_LOG(LogLPEditWidget, Error, TEXT("Echec de sauvegarde de %s"), *Filename);
|
||||
return 1;
|
||||
}
|
||||
UE_LOG(LogLPEditWidget, Warning, TEXT("%d modification(s), compile sans erreur, sauvegarde : %s"), Changes, *Filename);
|
||||
return 0;
|
||||
}
|
||||
28
Source/LifePlayEditorTools/LPEditWidgetCommandlet.h
Normal file
28
Source/LifePlayEditorTools/LPEditWidgetCommandlet.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Portage UE 5.5 - lot UI14 (interface du menu principal avant la V1.4, Docs/Migration/14_Interface_V1.4.md).
|
||||
//
|
||||
// Applique a un Blueprint de widget les modifications decrites par un fichier JSON (versionne dans Tools/ui/) :
|
||||
// "pins" : valeur par defaut d'une broche d'un noeud ({ "graph", "node", "pin", "expect", "value" }) ; pour une
|
||||
// broche texte (Format d'un FormatText) la valeur est un texte, le noeud reconstruit ses broches ;
|
||||
// "widgets" : proprietes d'un element de l'arbre ({ "name", "expect_text", "text", "tooltip", "visibility" }) ;
|
||||
// "visibility" retire aussi une liaison (binding) de visibilite qui l'ecraserait.
|
||||
// Chaque modification indique la valeur attendue AVANT ("expect", "expect_text") : au moindre ecart, ou element
|
||||
// introuvable, rien n'est sauvegarde. Le Blueprint est ensuite compile (aucune erreur toleree) puis sauvegarde.
|
||||
//
|
||||
// Usage :
|
||||
// UnrealEditor-Cmd.exe <projet> -run=LPEditWidget -Spec=<projet>/Tools/ui/<fichier>.json [-DryRun]
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Commandlets/Commandlet.h"
|
||||
#include "LPEditWidgetCommandlet.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class ULPEditWidgetCommandlet : public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ULPEditWidgetCommandlet();
|
||||
virtual int32 Main(const FString& Params) override;
|
||||
};
|
||||
|
|
@ -45,7 +45,9 @@ public class LifePlayEditorTools : ModuleRules
|
|||
"SkeletalMeshUtilitiesCommon",
|
||||
// Transfert de poids (FSkeletalMeshAttributes, FBoneWeight)
|
||||
"SkeletalMeshDescription",
|
||||
"AnimationCore"
|
||||
"AnimationCore",
|
||||
// UI14 : LPEditWidgetCommandlet lit sa specification JSON
|
||||
"Json"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
Tools/ui/MainMenu_V1.4.json
Normal file
16
Tools/ui/MainMenu_V1.4.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"bp": "/Game/UI/MainMenu",
|
||||
"pins": [
|
||||
{ "graph": "Get_Version_Text_0", "node": "K2Node_FormatText_0", "pin": "Format",
|
||||
"expect": "LifePlay v{main}.{sub}{text}", "value": "LifePlay {text}" },
|
||||
{ "graph": "EventGraph", "node": "K2Node_CallFunction_45", "pin": "URL",
|
||||
"expect": "https://www.patreon.com/vinfamy", "value": "https://www.patreon.com/cw/edujiro5972" },
|
||||
{ "graph": "EventGraph", "node": "K2Node_CallFunction_32", "pin": "URL",
|
||||
"expect": "https://discord.gg/eUEUhc6", "value": "https://discord.gg/q4689pNSy" }
|
||||
],
|
||||
"widgets": [
|
||||
{ "name": "TextBlock_19", "expect_text": "This project wouldn't be possible without the suppport from my generous patrons:", "text": "Original author:" },
|
||||
{ "name": "DonateButton", "tooltip": "Support LifePlay Revival on Patreon" },
|
||||
{ "name": "CommissionButton", "visibility": "Collapsed" }
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue