From 1d9620cde472d2ed87fd2ff67bc1fd204da2bdbe Mon Sep 17 00:00:00 2001 From: DurtyFree Date: Sun, 7 Feb 2021 14:07:57 +0100 Subject: [PATCH] Create base class for multiplayer clothes resource builders --- .../Builders/AltvResourceBuilder.cs | 202 +++++++----------- .../Base/MultiplayerResourceBuilderBase.cs | 163 ++++++++++++++ .../{ => Base}/ResourceBuilderBase.cs | 2 +- .../Builders/FivemResourceBuilder.cs | 167 ++++++--------- .../Builders/SingleplayerResourceBuilder.cs | 1 + altClothTool.App/altClothTool.App.csproj | 3 +- 6 files changed, 316 insertions(+), 222 deletions(-) create mode 100644 altClothTool.App/Builders/Base/MultiplayerResourceBuilderBase.cs rename altClothTool.App/Builders/{ => Base}/ResourceBuilderBase.cs (99%) diff --git a/altClothTool.App/Builders/AltvResourceBuilder.cs b/altClothTool.App/Builders/AltvResourceBuilder.cs index 2d75be3..3879119 100644 --- a/altClothTool.App/Builders/AltvResourceBuilder.cs +++ b/altClothTool.App/Builders/AltvResourceBuilder.cs @@ -1,136 +1,100 @@ using System.Collections.Generic; using System.IO; -using RageLib.GTA5.ResourceWrappers.PC.Meta.Structures; -using RageLib.Resources.GTA5.PC.GameFiles; -using RageLib.Resources.GTA5.PC.Meta; +using altClothTool.App.Builders.Base; namespace altClothTool.App.Builders { internal class AltvResourceBuilder - : ResourceBuilderBase + : MultiplayerResourceBuilderBase { - public override void BuildResource(string outputFolder, string collectionName) + private readonly List _streamCfgMetas = new List(); + private readonly List _streamCfgIncludes = new List(); + + #region Resource Props + + protected override void OnFirstPropAddedToResource(string outputFolder, int sexNr, string collectionName) + { + Directory.CreateDirectory($"{outputFolder}\\stream"); + Directory.CreateDirectory($"{outputFolder}\\stream\\{FolderNames[sexNr]}_p.rpf"); + Directory.CreateDirectory($"{outputFolder}\\stream\\{FolderNames[sexNr]}_p.rpf\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}"); + } + + protected override void CopyPropTextureToResource(string propTextureFilePath, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix, char offsetLetter) + { + string targetFilePath = $"{outputFolder}\\stream\\{FolderNames[sexNr]}_p.rpf\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}\\{prefix}_diff_{componentNumerics}_{offsetLetter}.ytd"; + File.Copy(propTextureFilePath, targetFilePath, true); + } + + protected override void CopyPropModelToResource(ClothData propClothData, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix) + { + string targetFilePath = $"{outputFolder}\\stream\\{FolderNames[sexNr]}_p.rpf\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}\\{prefix}_{componentNumerics}.ydd"; + File.Copy(propClothData.MainPath, targetFilePath, true); + } + + #endregion + + #region Resource Clothes + + protected override string GetClothYmtFilePath(string outputFolder, int sexNr, string collectionName) + { + return $"{outputFolder}\\stream\\{FolderNames[sexNr]}.rpf\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}.ymt"; + } + + protected override void OnFirstClothAddedToResource(string outputFolder, int sexNr, string collectionName) + { + Directory.CreateDirectory($"{outputFolder}\\stream"); + Directory.CreateDirectory($"{outputFolder}\\stream\\{FolderNames[sexNr]}.rpf"); + Directory.CreateDirectory($"{outputFolder}\\stream\\{FolderNames[sexNr]}.rpf\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}"); + } + + protected override void CopyClothFirstPersonModelToResource(string clothDataFirstPersonModelPath, int sexNr, string outputFolder, + string collectionName, string componentNumerics, string prefix, string yddPostfix) + { + string targetFilePath = $"{outputFolder}\\stream\\{FolderNames[sexNr]}.rpf\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}\\{prefix}_{componentNumerics}_{yddPostfix}_1.ydd"; + File.Copy(clothDataFirstPersonModelPath, targetFilePath); + } + + protected override void CopyClothTextureToResource(string clothTextureFilePath, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix, string ytdPostfix, char offsetLetter) + { + string targetFilePath = $"{outputFolder}\\stream\\{FolderNames[sexNr]}.rpf\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}\\{prefix}_diff_{componentNumerics}_{offsetLetter}_{ytdPostfix}.ytd"; + File.Copy(clothTextureFilePath, targetFilePath); + } + + protected override void CopyClothModelToResource(ClothData clothData, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix, string yddPostfix) + { + string targetFilePath = $"{outputFolder}\\stream\\{FolderNames[sexNr]}.rpf\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}\\{prefix}_{componentNumerics}_{yddPostfix}.ydd"; + File.Copy(clothData.MainPath, targetFilePath); + } + + #endregion + + protected override void OnResourceClothDataFinished(string outputFolder, int sexNr, string collectionName, bool isAnyClothAdded, bool isAnyPropAdded) { - List streamCfgMetas = new List(); - List streamCfgIncludes = new List(); + if (isAnyPropAdded) + { + _streamCfgIncludes.Add($"stream/{FolderNames[sexNr]}_p.rpf/*"); + } - for(int sexNr = 0; sexNr < 2; ++sexNr) + if (isAnyClothAdded || isAnyPropAdded) { - //Male YMT generating - YmtPedDefinitionFile ymt = new YmtPedDefinitionFile - { - metaYmtName = Prefixes[sexNr] + collectionName, - Unk_376833625 = {DlcName = RageLib.Hash.Jenkins.Hash(Prefixes[sexNr] + collectionName)} - }; - - MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null }; - int[] componentIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int[] propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - //ymt.Unk_376833625.Unk_1235281004 = 0; - //ymt.Unk_376833625.Unk_4086467184 = 0; - //ymt.Unk_376833625.Unk_911147899 = 0; - //ymt.Unk_376833625.Unk_315291935 = 0; - //ymt.Unk_376833625.Unk_2996560424 = ; - - bool isAnyClothAdded = false; - bool isAnyPropAdded = false; - - foreach (ClothData clothData in MainWindow.Clothes) - { - if (clothData.IsComponent()) - { - if (clothData.Textures.Count <= 0 || (int) clothData.TargetSex != sexNr) - continue; - - var componentItemInfo = GenerateYmtPedComponentItem(clothData, ref componentTextureBindings); - ymt.Unk_376833625.CompInfos.Add(componentItemInfo); - - var componentTypeId = componentItemInfo.Unk_3509540765; - GetClothPostfixes(clothData, out var ytdPostfix, out var yddPostfix); - - if (!isAnyClothAdded) - { - isAnyClothAdded = true; - Directory.CreateDirectory(outputFolder + "\\stream"); - Directory.CreateDirectory(outputFolder + "\\stream\\" + FolderNames[sexNr] + ".rpf"); - Directory.CreateDirectory(outputFolder + "\\stream\\" + FolderNames[sexNr] + ".rpf\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName); - } - - int currentComponentIndex = componentIndexes[componentTypeId]++; - string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0'); - string prefix = clothData.GetPrefix(); - - clothData.SetComponentNumerics(componentNumerics, currentComponentIndex); - - File.Copy(clothData.MainPath, outputFolder + "\\stream\\" + FolderNames[sexNr] + ".rpf\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "\\" + prefix + "_" + componentNumerics + "_" + yddPostfix + ".ydd"); - - char offsetLetter = 'a'; - for (int i = 0; i < clothData.Textures.Count; ++i) - File.Copy(clothData.Textures[i], outputFolder + "\\stream\\" + FolderNames[sexNr] + ".rpf\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "\\" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd"); - - if (clothData.FirstPersonModelPath != "") - File.Copy(clothData.FirstPersonModelPath, outputFolder + "\\stream\\" + FolderNames[sexNr] + ".rpf\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "\\" + prefix + "_" + componentNumerics + "_" + yddPostfix + "_1.ydd"); - } - else - { - if (clothData.Textures.Count <= 0 || (int) clothData.TargetSex != sexNr) - continue; - - Unk_2834549053 anchor = (Unk_2834549053)clothData.GetPedPropTypeId(); - var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List(); - var item = GenerateYmtPedPropItem(ymt, anchor, clothData); - defs.Add(item); - - if (!isAnyPropAdded) - { - isAnyPropAdded = true; - Directory.CreateDirectory(outputFolder + "\\stream"); - Directory.CreateDirectory(outputFolder + "\\stream\\" + FolderNames[sexNr] + "_p.rpf"); - Directory.CreateDirectory(outputFolder + "\\stream\\" + FolderNames[sexNr] + "_p.rpf\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName); - } - - int currentPropIndex = propIndexes[(byte)anchor]++; - - string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0'); - string prefix = clothData.GetPrefix(); - - clothData.SetComponentNumerics(componentNumerics, currentPropIndex); - - File.Copy(clothData.MainPath, outputFolder + "\\stream\\" + FolderNames[sexNr] + "_p.rpf\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName + "\\" + prefix + "_" + componentNumerics + ".ydd", true); - - char offsetLetter = 'a'; - for (int i = 0; i < clothData.Textures.Count; ++i) - { - File.Copy(clothData.Textures[i], outputFolder + "\\stream\\" + FolderNames[sexNr] + "_p.rpf\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName + "\\" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd", true); - } - } - } + string shopMetaFilePath = $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}.meta"; + File.WriteAllText(shopMetaFilePath, GenerateShopMetaContent((ClothData.Sex)sexNr, collectionName)); - if (isAnyClothAdded) - { - UpdateYmtComponentTextureBindings(componentTextureBindings, ymt); - ymt.Save(outputFolder + "\\stream\\" + FolderNames[sexNr] + ".rpf\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".ymt"); - } - - if(isAnyPropAdded) - { - streamCfgIncludes.Add("stream/" + FolderNames[sexNr] + "_p.rpf/*"); - } - - if (isAnyClothAdded || isAnyPropAdded) - { - File.WriteAllText(outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".meta", GenerateShopMetaContent((ClothData.Sex)sexNr, collectionName)); - streamCfgMetas.Add("stream/" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".meta: SHOP_PED_APPAREL_META_FILE"); - - streamCfgIncludes.Add("stream/" + FolderNames[sexNr] + ".rpf/*"); - } + _streamCfgMetas.Add($"stream/{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}.meta: SHOP_PED_APPAREL_META_FILE"); + _streamCfgIncludes.Add($"stream/{FolderNames[sexNr]}.rpf/*"); } + } - File.WriteAllText(outputFolder + "\\stream.cfg", GenerateAltvStreamCfgContent(streamCfgIncludes, streamCfgMetas)); - File.WriteAllText(outputFolder + "\\resource.cfg", GenerateAltvResourceCfgContent()); + protected override void OnResourceBuildingFinished(string outputFolder) + { + File.WriteAllText($"{outputFolder}\\stream.cfg", GenerateAltvStreamCfgContent(_streamCfgIncludes, _streamCfgMetas)); + File.WriteAllText($"{outputFolder}\\resource.cfg", GenerateAltvResourceCfgContent()); } - + private string GenerateAltvStreamCfgContent(List files, List metas) { string filesText = ""; diff --git a/altClothTool.App/Builders/Base/MultiplayerResourceBuilderBase.cs b/altClothTool.App/Builders/Base/MultiplayerResourceBuilderBase.cs new file mode 100644 index 0000000..02282ab --- /dev/null +++ b/altClothTool.App/Builders/Base/MultiplayerResourceBuilderBase.cs @@ -0,0 +1,163 @@ +using System.Collections.Generic; +using RageLib.GTA5.ResourceWrappers.PC.Meta.Structures; +using RageLib.Resources.GTA5.PC.GameFiles; +using RageLib.Resources.GTA5.PC.Meta; + +namespace altClothTool.App.Builders.Base +{ + internal abstract class MultiplayerResourceBuilderBase + : ResourceBuilderBase + { + public override void BuildResource(string outputFolder, string collectionName) + { + OnResourceBuildingStarted(outputFolder); + + for(int sexNr = 0; sexNr < 2; ++sexNr) + { + // Male YMT generating + YmtPedDefinitionFile ymt = new YmtPedDefinitionFile + { + metaYmtName = Prefixes[sexNr] + collectionName, + Unk_376833625 = {DlcName = RageLib.Hash.Jenkins.Hash(Prefixes[sexNr] + collectionName)} + }; + + MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null }; + int[] componentIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int[] propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + //ymt.Unk_376833625.Unk_1235281004 = 0; + //ymt.Unk_376833625.Unk_4086467184 = 0; + //ymt.Unk_376833625.Unk_911147899 = 0; + //ymt.Unk_376833625.Unk_315291935 = 0; + //ymt.Unk_376833625.Unk_2996560424 = ; + + bool isAnyClothAdded = false; + bool isAnyPropAdded = false; + + foreach (ClothData clothData in MainWindow.Clothes) + { + if (clothData.IsComponent()) + { + if (clothData.Textures.Count <= 0 || (int) clothData.TargetSex != sexNr) + continue; + + var componentItemInfo = GenerateYmtPedComponentItem(clothData, ref componentTextureBindings); + ymt.Unk_376833625.CompInfos.Add(componentItemInfo); + + var componentTypeId = componentItemInfo.Unk_3509540765; + GetClothPostfixes(clothData, out var ytdPostfix, out var yddPostfix); + + if (!isAnyClothAdded) + { + isAnyClothAdded = true; + OnFirstClothAddedToResource(outputFolder, sexNr, collectionName); + } + + int currentComponentIndex = componentIndexes[componentTypeId]++; + + string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0'); + string prefix = clothData.GetPrefix(); + + clothData.SetComponentNumerics(componentNumerics, currentComponentIndex); + + CopyClothModelToResource(clothData, sexNr, outputFolder, collectionName, componentNumerics, prefix, yddPostfix); + + char offsetLetter = 'a'; + for (int i = 0; i < clothData.Textures.Count; ++i) + { + CopyClothTextureToResource(clothData.Textures[i], sexNr, outputFolder, collectionName, componentNumerics, prefix, ytdPostfix, (char)(offsetLetter + i)); + } + + if (!string.IsNullOrEmpty(clothData.FirstPersonModelPath)) + { + CopyClothFirstPersonModelToResource(clothData.FirstPersonModelPath, sexNr, outputFolder, collectionName, componentNumerics, prefix, yddPostfix); + } + } + else + { + if (clothData.Textures.Count <= 0 || (int) clothData.TargetSex != sexNr) + continue; + + Unk_2834549053 anchor = (Unk_2834549053)clothData.GetPedPropTypeId(); + var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List(); + var item = GenerateYmtPedPropItem(ymt, anchor, clothData); + defs.Add(item); + + if (!isAnyPropAdded) + { + isAnyPropAdded = true; + OnFirstPropAddedToResource(outputFolder, sexNr, collectionName); + } + + int currentPropIndex = propIndexes[(byte)anchor]++; + + string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0'); + string prefix = clothData.GetPrefix(); + clothData.SetComponentNumerics(componentNumerics, currentPropIndex); + + CopyPropModelToResource(clothData, sexNr, outputFolder, collectionName, componentNumerics, prefix); + + char offsetLetter = 'a'; + for (int i = 0; i < clothData.Textures.Count; ++i) + { + CopyPropTextureToResource(clothData.Textures[i], sexNr, outputFolder, collectionName, componentNumerics, prefix, (char)(offsetLetter + i)); + } + } + } + + if (isAnyClothAdded) + { + UpdateYmtComponentTextureBindings(componentTextureBindings, ymt); + var clothYmtFilePath = GetClothYmtFilePath(outputFolder, sexNr, collectionName); + ymt.Save(clothYmtFilePath); + } + + OnResourceClothDataFinished(outputFolder, sexNr, collectionName, isAnyClothAdded, isAnyPropAdded); + } + + OnResourceBuildingFinished(outputFolder); + } + + protected abstract string GetClothYmtFilePath(string outputFolder, int sexNr, string collectionName); + + protected abstract void CopyPropTextureToResource(string propTextureFilePath, int sexNr, string outputFolder, + string collectionName, string componentNumerics, string prefix, char offsetLetter); + + protected abstract void CopyPropModelToResource(ClothData propClothData, int sexNr, string outputFolder, + string collectionName, string componentNumerics, string prefix); + + protected abstract void CopyClothFirstPersonModelToResource(string clothDataFirstPersonModelPath, int sexNr, + string outputFolder, string collectionName, string componentNumerics, string prefix, string yddPostfix); + + protected abstract void CopyClothTextureToResource(string clothTextureFilePath, int sexNr, string outputFolder, + string collectionName, string componentNumerics, string prefix, string ytdPostfix, char offsetLetter); + + protected abstract void CopyClothModelToResource(ClothData clothData, int sexNr, string outputFolder, + string collectionName, string componentNumerics, string prefix, string yddPostfix); + + protected virtual void OnResourceClothDataFinished(string outputFolder, int sexNr, string collectionName, bool isAnyClothAdded, bool isAnyPropAdded) + { + + } + + protected virtual void OnFirstPropAddedToResource(string outputFolder, int sexNr, string collectionName) + { + + } + + protected virtual void OnFirstClothAddedToResource(string outputFolder, int sexNr, string collectionName) + { + + } + + protected virtual void OnResourceBuildingStarted(string outputFolder) + { + + } + + protected virtual void OnResourceBuildingFinished(string outputFolder) + { + + } + } +} diff --git a/altClothTool.App/Builders/ResourceBuilderBase.cs b/altClothTool.App/Builders/Base/ResourceBuilderBase.cs similarity index 99% rename from altClothTool.App/Builders/ResourceBuilderBase.cs rename to altClothTool.App/Builders/Base/ResourceBuilderBase.cs index 6d0b644..f5977d6 100644 --- a/altClothTool.App/Builders/ResourceBuilderBase.cs +++ b/altClothTool.App/Builders/Base/ResourceBuilderBase.cs @@ -3,7 +3,7 @@ using RageLib.Resources.GTA5.PC.GameFiles; using RageLib.Resources.GTA5.PC.Meta; -namespace altClothTool.App.Builders +namespace altClothTool.App.Builders.Base { public abstract class ResourceBuilderBase : IClothesResourceBuilder diff --git a/altClothTool.App/Builders/FivemResourceBuilder.cs b/altClothTool.App/Builders/FivemResourceBuilder.cs index 856baf2..1d6d6f8 100644 --- a/altClothTool.App/Builders/FivemResourceBuilder.cs +++ b/altClothTool.App/Builders/FivemResourceBuilder.cs @@ -1,123 +1,88 @@ using System.Collections.Generic; using System.IO; -using RageLib.GTA5.ResourceWrappers.PC.Meta.Structures; -using RageLib.Resources.GTA5.PC.GameFiles; -using RageLib.Resources.GTA5.PC.Meta; +using altClothTool.App.Builders.Base; namespace altClothTool.App.Builders { internal class FivemResourceBuilder - : ResourceBuilderBase + : MultiplayerResourceBuilderBase { - public override void BuildResource(string outputFolder, string collectionName) + private readonly List _resourceLuaMetas = new List(); + + #region Resource Props + + protected override void OnFirstPropAddedToResource(string outputFolder, int sexNr, string collectionName) { - List resourceLUAMetas = new List(); - - for(int sexNr = 0; sexNr < 2; ++sexNr) - { - //Male YMT generating - YmtPedDefinitionFile ymt = new YmtPedDefinitionFile - { - metaYmtName = Prefixes[sexNr] + collectionName, - Unk_376833625 = {DlcName = RageLib.Hash.Jenkins.Hash(Prefixes[sexNr] + collectionName)} - }; - - MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null }; - int[] componentIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int[] propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - //ymt.Unk_376833625.Unk_1235281004 = 0; - //ymt.Unk_376833625.Unk_4086467184 = 0; - //ymt.Unk_376833625.Unk_911147899 = 0; - //ymt.Unk_376833625.Unk_315291935 = 0; - //ymt.Unk_376833625.Unk_2996560424 = ; - - bool isAnyClothAdded = false; - bool isAnyPropAdded = false; - - foreach (ClothData clothData in MainWindow.Clothes) - { - if (clothData.IsComponent()) - { - if (clothData.Textures.Count <= 0 || (int) clothData.TargetSex != sexNr) - continue; - - var componentItemInfo = GenerateYmtPedComponentItem(clothData, ref componentTextureBindings); - ymt.Unk_376833625.CompInfos.Add(componentItemInfo); - - var componentTypeId = componentItemInfo.Unk_3509540765; - GetClothPostfixes(clothData, out var ytdPostfix, out var yddPostfix); - - if (!isAnyClothAdded) - { - isAnyClothAdded = true; - Directory.CreateDirectory(outputFolder + "\\stream"); - Directory.CreateDirectory(outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName); - } - - int currentComponentIndex = componentIndexes[componentTypeId]++; - - string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0'); - string prefix = clothData.GetPrefix(); - - clothData.SetComponentNumerics(componentNumerics, currentComponentIndex); + Directory.CreateDirectory($"{outputFolder}\\stream"); + Directory.CreateDirectory($"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}"); + } + + protected override void CopyPropTextureToResource(string propTextureFilePath, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix, char offsetLetter) + { + string targetFilePath = $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}^{prefix}_diff_{componentNumerics}_{offsetLetter}.ytd"; + File.Copy(propTextureFilePath, targetFilePath, true); + } - File.Copy(clothData.MainPath, outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "^" + prefix + "_" + componentNumerics + "_" + yddPostfix + ".ydd", true); + protected override void CopyPropModelToResource(ClothData propClothData, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix) + { + string targetFilePath = $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}\\{Prefixes[sexNr]}freemode_01_p_{Prefixes[sexNr]}{collectionName}^{prefix}_{componentNumerics}.ydd"; + File.Copy(propClothData.MainPath, targetFilePath, true); + } - char offsetLetter = 'a'; - for (int i = 0; i < clothData.Textures.Count; ++i) - File.Copy(clothData.Textures[i], outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "^" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd", true); + #endregion - if (clothData.FirstPersonModelPath != "") - File.Copy(clothData.FirstPersonModelPath, outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + "^" + prefix + "_" + componentNumerics + "_" + yddPostfix + "_1.ydd", true); - } - else - { - if (clothData.Textures.Count <= 0 || (int) clothData.TargetSex != sexNr) - continue; + #region Resource Clothes + + protected override string GetClothYmtFilePath(string outputFolder, int sexNr, string collectionName) + { + return $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}.ymt"; + } - Unk_2834549053 anchor = (Unk_2834549053)clothData.GetPedPropTypeId(); - var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List(); - var item = GenerateYmtPedPropItem(ymt, anchor, clothData); - defs.Add(item); + protected override void OnFirstClothAddedToResource(string outputFolder, int sexNr, string collectionName) + { + Directory.CreateDirectory(outputFolder + "\\stream"); + Directory.CreateDirectory(outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName); + } - if (!isAnyPropAdded) - { - isAnyPropAdded = true; - Directory.CreateDirectory(outputFolder + "\\stream"); - Directory.CreateDirectory(outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName); - } + protected override void CopyClothFirstPersonModelToResource(string clothDataFirstPersonModelPath, int sexNr, string outputFolder, + string collectionName, string componentNumerics, string prefix, string yddPostfix) + { + string targetFilePath = $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}^{prefix}_{componentNumerics}_{yddPostfix}_1.ydd"; + File.Copy(clothDataFirstPersonModelPath, targetFilePath, true); + } - int currentPropIndex = propIndexes[(byte)anchor]++; + protected override void CopyClothTextureToResource(string clothTextureFilePath, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix, string ytdPostfix, char offsetLetter) + { + string targetFilePath = $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}^{prefix}_diff_{componentNumerics}_{offsetLetter}_{ytdPostfix}.ytd"; + File.Copy(clothTextureFilePath, targetFilePath, true); + } - string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0'); - string prefix = clothData.GetPrefix(); - clothData.SetComponentNumerics(componentNumerics, currentPropIndex); + protected override void CopyClothModelToResource(ClothData clothData, int sexNr, string outputFolder, string collectionName, + string componentNumerics, string prefix, string yddPostfix) + { + string targetFilePath = $"{outputFolder}\\stream\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}^{prefix}_{componentNumerics}_{yddPostfix}.ydd"; + File.Copy(clothData.MainPath, targetFilePath, true); + } - File.Copy(clothData.MainPath, outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName + "\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName + "^" + prefix + "_" + componentNumerics + ".ydd", true); + #endregion + + protected override void OnResourceBuildingFinished(string outputFolder) + { + File.WriteAllText(outputFolder + "\\fxmanifest.lua", GenerateFiveMResourceLuaContent(_resourceLuaMetas)); + } - char offsetLetter = 'a'; - for (int i = 0; i < clothData.Textures.Count; ++i) - { - File.Copy(clothData.Textures[i], outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName + "\\" + Prefixes[sexNr] + "freemode_01_p_" + Prefixes[sexNr] + collectionName + "^" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd", true); - } - } - } - - if (isAnyClothAdded) - { - UpdateYmtComponentTextureBindings(componentTextureBindings, ymt); - ymt.Save(outputFolder + "\\stream\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".ymt"); - } + protected override void OnResourceClothDataFinished(string outputFolder, int sexNr, string collectionName, bool isAnyPropAdded, bool isAnyClothAdded) + { + if (!isAnyClothAdded && !isAnyPropAdded) + return; - if(isAnyClothAdded || isAnyPropAdded) - { - File.WriteAllText(outputFolder + "\\" + Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".meta", GenerateShopMetaContent((ClothData.Sex)sexNr, collectionName)); - resourceLUAMetas.Add(Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".meta"); - } - } + string shopMetaFilePath = $"{outputFolder}\\{Prefixes[sexNr]}freemode_01_{Prefixes[sexNr]}{collectionName}.meta"; + File.WriteAllText(shopMetaFilePath, GenerateShopMetaContent((ClothData.Sex)sexNr, collectionName)); - File.WriteAllText(outputFolder + "\\fxmanifest.lua", GenerateFiveMResourceLuaContent(resourceLUAMetas)); + _resourceLuaMetas.Add(Prefixes[sexNr] + "freemode_01_" + Prefixes[sexNr] + collectionName + ".meta"); } private string GenerateFiveMResourceLuaContent(List metas) diff --git a/altClothTool.App/Builders/SingleplayerResourceBuilder.cs b/altClothTool.App/Builders/SingleplayerResourceBuilder.cs index 4e7732c..83108f2 100644 --- a/altClothTool.App/Builders/SingleplayerResourceBuilder.cs +++ b/altClothTool.App/Builders/SingleplayerResourceBuilder.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using altClothTool.App.Builders.Base; using RageLib.Archives; using RageLib.GTA5.Archives; using RageLib.GTA5.ArchiveWrappers; diff --git a/altClothTool.App/altClothTool.App.csproj b/altClothTool.App/altClothTool.App.csproj index 9d15eaa..258f0ec 100644 --- a/altClothTool.App/altClothTool.App.csproj +++ b/altClothTool.App/altClothTool.App.csproj @@ -73,7 +73,8 @@ - + + ProjectBuild.xaml