Skip to content

Commit

Permalink
Instanced Projects, AssetLocator, ParamBank, FMGBank (#895)
Browse files Browse the repository at this point in the history
* Create project replacing assetlocator, rework functions to use common utilities

* Move statics usages

* Remove passing of AssetLocator - Make it (temporarily) static

* Turn Assetlocator into a static dummy

* Move static hack to AssetLocator

* Rename project to projectassetlocator, introduce owning project object

* Clean some imports

* END SUPPORT of ER PartialParams, ParamBank to use new assetlocator.

* Stop reusing parambank instances, make them part of Project. Also keep settings in project because looseparams option. Also also it's still used all over and is good for serialization.

* Change comparison menus to select project/mod folder

* Allow to still select json from compare, including loading settings from json

* Defs loaded on a per-project/bank basis

* Repair from merge

* Move parammeta to be part of parambank

* deduplicate project gametype (again)

* undo privacy because we are setting it outside and I don't want to fix it right now

* Scuffed start on instanced FMGBank

* Use own assetlocator in fmgbank, fix writemode

* fmg loading with fromOptions

* Move FMG enums to their own class

* Move big switches

* move post-load fmginfo edits

* Renamed UICategories to FileCategories so that we're not putting UI state in the fmgbank

* Move data into dictionary rather than list

* rename fmginfo uicategory, filecategory.text

* Move the game-based hacks to generateInfo

* naming and insertion consistency

* Loaded categories is now backed by the fmgbank itself

* Patching is on lookup instead of modifying data

* Move sorting logic to lookup stuff

* Split up Exporter, EntryGroup and FMGInfo

* no more partial class

* Move reloading of FMGs to bank and outside of screen.

* Move most of FMGBank into FMGLang

* Introduce FMGFileSet, finally some semblence of functioning again.

* Fix Errors when no project loaded, assetbrowser ordering

* GetProjectFileAllPaths util

* merge compile fixes
  • Loading branch information
Philiquaz authored Jun 29, 2024
1 parent 3fb60ab commit dba491f
Show file tree
Hide file tree
Showing 30 changed files with 4,544 additions and 4,933 deletions.
2,223 changes: 70 additions & 2,153 deletions src/StudioCore/AssetLocator.cs

Large diffs are not rendered by default.

216 changes: 216 additions & 0 deletions src/StudioCore/AssetUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
using SoulsFormats;
using StudioCore.Editor;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace StudioCore;

/// <summary>
/// Helper functions and statics for Project/Assetlocator
/// </summary>
public class AssetUtils
{
public static readonly string GameExecutableFilter;
public static readonly string ProjectJsonFilter;
public static readonly string RegulationBinFilter;
public static readonly string Data0Filter;
public static readonly string ParamBndDcxFilter;
public static readonly string ParamBndFilter;
public static readonly string EncRegulationFilter;
public static readonly string ParamLooseFilter;
public static readonly string CsvFilter;
public static readonly string TxtFilter;
public static readonly string FmgJsonFilter;

static AssetUtils()
{
// These patterns are meant to be passed directly into PlatformUtils.
// Everything about their handling should be done there.

// Game Executable (.EXE, EBOOT.BIN)|*.EXE*;*EBOOT.BIN*
// Windows executable (*.EXE)|*.EXE*
// Playstation executable (*.BIN)|*.BIN*
GameExecutableFilter = "exe,bin";
// Project file (project.json)|PROJECT.JSON
ProjectJsonFilter = "json";
// Regulation file (regulation.bin)|REGULATION.BIN
RegulationBinFilter = "bin";
// Data file (Data0.bdt)|DATA0.BDT
Data0Filter = "bdt";
// ParamBndDcx (gameparam.parambnd.dcx)|GAMEPARAM.PARAMBND.DCX
ParamBndDcxFilter = "parambnd.dcx";
// ParamBnd (gameparam.parambnd)|GAMEPARAM.PARAMBND
ParamBndFilter = "parambnd";
// Enc_RegBndDcx (enc_regulation.bnd.dcx)|ENC_REGULATION.BND.DCX
EncRegulationFilter = "bnd.dcx";
// Loose Param file (*.Param)|*.Param
ParamLooseFilter = "param";
// CSV file (*.csv)|*.csv
CsvFilter = "csv";
// Text file (*.txt)|*.txt
TxtFilter = "txt";
// Exported FMGs (*.fmg.json)|*.fmg.json
FmgJsonFilter = "fmg.json";
// All file filter is implicitly added by NFD. Ideally this is used explicitly.
// All files|*.*
}
public static GameType GetGameTypeForExePath(string exePath)
{
var type = GameType.Undefined;
if (exePath.ToLower().Contains("darksouls.exe"))
{
type = GameType.DarkSoulsPTDE;
}
else if (exePath.ToLower().Contains("darksoulsremastered.exe"))
{
type = GameType.DarkSoulsRemastered;
}
else if (exePath.ToLower().Contains("darksoulsii.exe"))
{
type = GameType.DarkSoulsIISOTFS;
}
else if (exePath.ToLower().Contains("darksoulsiii.exe"))
{
type = GameType.DarkSoulsIII;
}
else if (exePath.ToLower().Contains("eboot.bin"))
{
var path = Path.GetDirectoryName(exePath);
if (Directory.Exists($@"{path}\dvdroot_ps4"))
{
type = GameType.Bloodborne;
}
else
{
type = GameType.DemonsSouls;
}
}
else if (exePath.ToLower().Contains("sekiro.exe"))
{
type = GameType.Sekiro;
}
else if (exePath.ToLower().Contains("eldenring.exe"))
{
type = GameType.EldenRing;
}
else if (exePath.ToLower().Contains("armoredcore6.exe"))
{
type = GameType.ArmoredCoreVI;
}

return type;
}

public static bool CheckFilesExpanded(string gamepath, GameType game)
{
if (game == GameType.EldenRing)
{
if (!Directory.Exists($@"{gamepath}\map"))
{
return false;
}

if (!Directory.Exists($@"{gamepath}\asset"))
{
return false;
}
}

if (game is GameType.DarkSoulsPTDE or GameType.DarkSoulsIII or GameType.Sekiro)
{
if (!Directory.Exists($@"{gamepath}\map"))
{
return false;
}

if (!Directory.Exists($@"{gamepath}\obj"))
{
return false;
}
}

if (game == GameType.DarkSoulsIISOTFS)
{
if (!Directory.Exists($@"{gamepath}\map"))
{
return false;
}

if (!Directory.Exists($@"{gamepath}\model\obj"))
{
return false;
}
}

if (game == GameType.ArmoredCoreVI)
{
if (!Directory.Exists($@"{gamepath}\map"))
{
return false;
}

if (!Directory.Exists($@"{gamepath}\asset"))
{
return false;
}
}

return true;
}

public static string GetGameIDForDir(GameType Type)
{
switch (Type)
{
case GameType.DemonsSouls:
return "DES";
case GameType.DarkSoulsPTDE:
return "DS1";
case GameType.DarkSoulsRemastered:
return "DS1R";
case GameType.DarkSoulsIISOTFS:
return "DS2S";
case GameType.Bloodborne:
return "BB";
case GameType.DarkSoulsIII:
return "DS3";
case GameType.Sekiro:
return "SDT";
case GameType.EldenRing:
return "ER";
case GameType.ArmoredCoreVI:
return "AC6";
default:
throw new Exception("Game type not set");
}
}

public static AssetDescription GetNullAsset()
{
AssetDescription ret = new();
ret.AssetPath = "null";
ret.AssetName = "null";
ret.AssetArchiveVirtualPath = "null";
ret.AssetVirtualPath = "null";
return ret;
}

public static string GetBinderVirtualPath(string virtualPathToBinder, string binderFilePath)
{
var filename = Path.GetFileNameWithoutExtension($@"{binderFilePath}.blah");
if (filename.Length > 0)
{
filename = $@"{virtualPathToBinder}/{filename}";
}
else
{
filename = virtualPathToBinder;
}

return filename;
}
}
12 changes: 6 additions & 6 deletions src/StudioCore/Editor/Action.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,10 @@ public override ActionEvent Undo()

public class DuplicateFMGEntryAction : EditorAction
{
private readonly FMGBank.EntryGroup EntryGroup;
private FMGBank.EntryGroup NewEntryGroup;
private readonly FMGEntryGroup EntryGroup;
private FMGEntryGroup NewEntryGroup;

public DuplicateFMGEntryAction(FMGBank.EntryGroup entryGroup)
public DuplicateFMGEntryAction(FMGEntryGroup entryGroup)
{
EntryGroup = entryGroup;
}
Expand All @@ -333,10 +333,10 @@ public override ActionEvent Undo()

public class DeleteFMGEntryAction : EditorAction
{
private FMGBank.EntryGroup BackupEntryGroup = new();
private FMGBank.EntryGroup EntryGroup;
private FMGEntryGroup BackupEntryGroup = new();
private FMGEntryGroup EntryGroup;

public DeleteFMGEntryAction(FMGBank.EntryGroup entryGroup)
public DeleteFMGEntryAction(FMGEntryGroup entryGroup)
{
EntryGroup = entryGroup;
}
Expand Down
22 changes: 11 additions & 11 deletions src/StudioCore/Editor/EditorDecorations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,21 +259,21 @@ public static void ParamRefsSelectables(ParamBank bank, List<ParamRef> paramRefs
return rows;
}

private static List<(string, FMGBank.EntryGroup)> resolveFMGRefs(List<FMGRef> fmgRefs, Param.Row context,
private static List<(string, FMGEntryGroup)> resolveFMGRefs(List<FMGRef> fmgRefs, Param.Row context,
dynamic oldval)
{
if (!FMGBank.IsLoaded)
if (!Locator.ActiveProject.FMGBank.IsLoaded)
{
return new List<(string, FMGBank.EntryGroup)>();
return new List<(string, FMGEntryGroup)>();
}

return fmgRefs.Where(rf =>
{
Param.Cell? c = context?[rf.conditionField];
return context == null || c == null || Convert.ToInt32(c.Value.Value) == rf.conditionValue;
}).Select(rf => FMGBank.FmgInfoBank.Find(x => x.Name == rf.fmg))
}).Select(rf => Locator.ActiveProject.FMGBank.FmgInfoBank.FirstOrDefault(x => x.Name == rf.fmg))
.Where(fmgi => fmgi != null)
.Select(fmgi => (fmgi.Name, FMGBank.GenerateEntryGroup((int)oldval, fmgi)))
.Select(fmgi => (fmgi.Name, Locator.ActiveProject.FMGBank.GenerateEntryGroup((int)oldval, fmgi)))
.ToList();
}

Expand All @@ -282,11 +282,11 @@ public static void FmgRefSelectable(EditorScreen ownerScreen, List<FMGRef> fmgNa
{
List<string> textsToPrint = UICache.GetCached(ownerScreen, (int)oldval, "PARAM META FMGREF", () =>
{
List<(string, FMGBank.EntryGroup)> refs = resolveFMGRefs(fmgNames, context, oldval);
List<(string, FMGEntryGroup)> refs = resolveFMGRefs(fmgNames, context, oldval);
return refs.Where(x => x.Item2 != null)
.Select(x =>
{
FMGBank.EntryGroup group = x.Item2;
FMGEntryGroup group = x.Item2;
var toPrint = "";
if (!string.IsNullOrWhiteSpace(group.Title?.Text))
{
Expand Down Expand Up @@ -379,7 +379,7 @@ public static void VirtualParamRefSelectables(ParamBank bank, string virtualRefN
{
List<string> matchedExtRefPath =
currentRef.paths.Select(x => string.Format(x, searchValue)).ToList();
AssetLocator al = ParamBank.PrimaryBank.AssetLocator;
AssetLocator al = Locator.AssetLocator;
ExtRefItem(context, fieldName, $"modded {currentRef.name}", matchedExtRefPath, al.GameModDirectory,
cacheOwner);
ExtRefItem(context, fieldName, $"vanilla {currentRef.name}", matchedExtRefPath,
Expand Down Expand Up @@ -464,7 +464,7 @@ public static void ParamRefEnumQuickLink(ParamBank bank, object oldval, List<Par
}
else if (fmgRefs != null)
{
(string, FMGBank.EntryGroup)? primaryRef =
(string, FMGEntryGroup)? primaryRef =
resolveFMGRefs(fmgRefs, context, oldval)?.FirstOrDefault();
if (primaryRef?.Item2 != null)
{
Expand Down Expand Up @@ -599,9 +599,9 @@ public static void PropertyRowFMGRefsContextItems(List<FMGRef> reftypes, Param.R
ActionManager executor)
{
// Add Goto statements
List<(string, FMGBank.EntryGroup)> refs = resolveFMGRefs(reftypes, context, oldval);
List<(string, FMGEntryGroup)> refs = resolveFMGRefs(reftypes, context, oldval);
var ctrlDown = InputTracker.GetKey(Key.ControlLeft) || InputTracker.GetKey(Key.ControlRight);
foreach ((var name, FMGBank.EntryGroup group) in refs)
foreach ((var name, FMGEntryGroup group) in refs)
{
if (ImGui.Selectable($@"Goto {name} Text"))
{
Expand Down
23 changes: 20 additions & 3 deletions src/StudioCore/Editor/ProjectSettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using StudioCore.Platform;
using Silk.NET.Core;
using StudioCore.Platform;
using System;
using System.Collections.Generic;
using System.IO;
Expand Down Expand Up @@ -39,8 +40,6 @@ public class ProjectSettings
/// </summary>
public bool UseLooseParams { get; set; } = false;

public bool PartialParams { get; set; } = false;

// FMG editor
public string LastFmgLanguageUsed { get; set; } = "";

Expand Down Expand Up @@ -79,6 +78,24 @@ public static ProjectSettings Deserialize(string path)
return null;
}
}

internal ProjectSettings CopyAndAssumeFromModDir(string moddir)
{
ProjectSettings newProj = new();
newProj.ProjectName = Path.GetFileName(Path.GetDirectoryName(moddir));
newProj.GameRoot = GameRoot;
newProj.GameType = GameType;
switch (newProj.GameType)
{
case GameType.DarkSoulsIISOTFS:
newProj.UseLooseParams = File.Exists($@"{moddir}\Param\AreaParam.param");
break;
case GameType.DarkSoulsIII:
newProj.UseLooseParams = File.Exists($@"{moddir}\param\gameparam\gameparam_dlc2.parambnd.dcx");
break;
}
return newProj;
}
}

public class NewProjectOptions
Expand Down
4 changes: 2 additions & 2 deletions src/StudioCore/Interface/AliasUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ public static string FindPlayerCharacterName(Entity e, string modelName)
var term = c.Value.ToParamEditorString();
var result = term;

if (FMGBank.IsLoaded)
if (Locator.ActiveProject.FMGBank.IsLoaded)
{
var matchingFmgInfo = FMGBank.FmgInfoBank.Find(x => x.Name.Contains("Character"));
var matchingFmgInfo = Locator.ActiveProject.FMGBank.FmgInfoBank.First(x => x.Name.Contains("Character"));

if (matchingFmgInfo != null)
{
Expand Down
Loading

0 comments on commit dba491f

Please sign in to comment.