From 1a340b9ef6eb8e82d174c07e0679abde8b9ff662 Mon Sep 17 00:00:00 2001 From: zhangyi Date: Wed, 12 Apr 2023 15:09:29 +0800 Subject: [PATCH 1/4] fullfill path of texture in mat property for ER(FLVER2) --- StudioCore/MsbEditor/ObjectContainer.cs | 5 ++ StudioCore/Resource/FlverResource.cs | 85 +++++++++++++++++-------- 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/StudioCore/MsbEditor/ObjectContainer.cs b/StudioCore/MsbEditor/ObjectContainer.cs index a85230e91..0d0459655 100644 --- a/StudioCore/MsbEditor/ObjectContainer.cs +++ b/StudioCore/MsbEditor/ObjectContainer.cs @@ -18,6 +18,7 @@ using System.Windows.Forms.Design; using static SoulsFormats.MCP; using System.ComponentModel; +using StudioCore.Resource; namespace StudioCore.MsbEditor { @@ -135,6 +136,10 @@ public void LoadFlver(FLVER2 flver, MeshRenderableProxy proxy) for (int i = 0; i < flver.Materials.Count; i++) { var matnode = new Entity(this, flver.Materials[i]); + foreach (var tex in flver.Materials[i].Textures) + { + tex.Path = FlverResource.FindTexturePath(tex.Type, "", flver.Materials[i].MTD); + } Objects.Add(matnode); materialsNode.AddChild(matnode); } diff --git a/StudioCore/Resource/FlverResource.cs b/StudioCore/Resource/FlverResource.cs index 2fccc8a76..87226a47b 100644 --- a/StudioCore/Resource/FlverResource.cs +++ b/StudioCore/Resource/FlverResource.cs @@ -310,7 +310,7 @@ private string TexturePathToVirtual(string texpath) return texpath; } - private void LookupTexture(FlverMaterial.TextureType textureType, FlverMaterial dest, string type, string mpath, string mtd) + public static string FindTexturePath(string type, string mpath, string mtd) { var path = mpath; if (mpath == "") @@ -323,7 +323,7 @@ private void LookupTexture(FlverMaterial.TextureType textureType, FlverMaterial var tex = MtdBank.Matbins[mtdstring].Samplers.Find(x => (x.Type == type)); if (tex == null || tex.Path == "") { - return; + return ""; } path = tex.Path; } @@ -335,12 +335,18 @@ private void LookupTexture(FlverMaterial.TextureType textureType, FlverMaterial var tex = MtdBank.Mtds[mtdstring].Textures.Find(x => (x.Type == type)); if (tex == null || !tex.Extended || tex.Path == "") { - return; + return ""; } path = tex.Path; } } } + return path; + } + + private void LookupTexture(FlverMaterial.TextureType textureType, FlverMaterial dest, string type, string mpath, string mtd) + { + var path = FindTexturePath(type, mpath, mtd); if (!dest.TextureResourceFilled[(int)textureType]) { @@ -350,15 +356,8 @@ private void LookupTexture(FlverMaterial.TextureType textureType, FlverMaterial } } - private void ProcessMaterialTexture(FlverMaterial dest, string type, string mpath, string mtd, - out bool blend, out bool hasNormal2, out bool hasSpec2, out bool hasShininess2, out bool blendMask) + public static FlverMaterial.TextureType GetTextureType(string type) { - blend = false; - blendMask = false; - hasNormal2 = false; - hasSpec2 = false; - hasShininess2 = false; - string paramNameCheck; if (type == null) { @@ -370,48 +369,78 @@ private void ProcessMaterialTexture(FlverMaterial dest, string type, string mpat } if (paramNameCheck == "G_DIFFUSETEXTURE2" || paramNameCheck == "G_DIFFUSE2" || paramNameCheck.Contains("ALBEDO_2")) { - LookupTexture(FlverMaterial.TextureType.AlbedoTextureResource2, dest, type, mpath, mtd); - blend = true; + return FlverMaterial.TextureType.AlbedoTextureResource2; } else if (paramNameCheck == "G_DIFFUSETEXTURE" || paramNameCheck == "G_DIFFUSE" || paramNameCheck.Contains("ALBEDO")) { - LookupTexture(FlverMaterial.TextureType.AlbedoTextureResource, dest, type, mpath, mtd); + return FlverMaterial.TextureType.AlbedoTextureResource; } else if (paramNameCheck == "G_BUMPMAPTEXTURE2" || paramNameCheck == "G_BUMPMAP2" || paramNameCheck.Contains("NORMAL_2")) { - LookupTexture(FlverMaterial.TextureType.NormalTextureResource2, dest, type, mpath, mtd); - blend = true; - hasNormal2 = true; + return FlverMaterial.TextureType.NormalTextureResource2; } else if (paramNameCheck == "G_BUMPMAPTEXTURE" || paramNameCheck == "G_BUMPMAP" || paramNameCheck.Contains("NORMAL")) { - LookupTexture(FlverMaterial.TextureType.NormalTextureResource, dest, type, mpath, mtd); + return FlverMaterial.TextureType.NormalTextureResource; } else if (paramNameCheck == "G_SPECULARTEXTURE2" || paramNameCheck == "G_SPECULAR2" || paramNameCheck.Contains("SPECULAR_2")) { - LookupTexture(FlverMaterial.TextureType.SpecularTextureResource2, dest, type, mpath, mtd); - blend = true; - hasSpec2 = true; + return FlverMaterial.TextureType.SpecularTextureResource2; } else if (paramNameCheck == "G_SPECULARTEXTURE" || paramNameCheck == "G_SPECULAR" || paramNameCheck.Contains("SPECULAR")) { - LookupTexture(FlverMaterial.TextureType.SpecularTextureResource, dest, type, mpath, mtd); + return FlverMaterial.TextureType.SpecularTextureResource; } else if (paramNameCheck == "G_SHININESSTEXTURE2" || paramNameCheck == "G_SHININESS2" || paramNameCheck.Contains("SHININESS2")) { - LookupTexture(FlverMaterial.TextureType.ShininessTextureResource2, dest, type, mpath, mtd); - blend = true; - hasShininess2 = true; + return FlverMaterial.TextureType.ShininessTextureResource2; } else if (paramNameCheck == "G_SHININESSTEXTURE" || paramNameCheck == "G_SHININESS" || paramNameCheck.Contains("SHININESS")) { - LookupTexture(FlverMaterial.TextureType.ShininessTextureResource, dest, type, mpath, mtd); + return FlverMaterial.TextureType.ShininessTextureResource; } else if (paramNameCheck.Contains("BLENDMASK")) { - LookupTexture(FlverMaterial.TextureType.BlendmaskTextureResource, dest, type, mpath, mtd); - blendMask = true; + return FlverMaterial.TextureType.BlendmaskTextureResource; + } + return FlverMaterial.TextureType.AlbedoTextureResource; + } + + private void ProcessMaterialTexture(FlverMaterial dest, string typename, string mpath, string mtd, + out bool blend, out bool hasNormal2, out bool hasSpec2, out bool hasShininess2, out bool blendMask) + { + blend = false; + blendMask = false; + hasNormal2 = false; + hasSpec2 = false; + hasShininess2 = false; + + var type = GetTextureType(typename); + + switch(type) + { + case FlverMaterial.TextureType.AlbedoTextureResource2: + blend = true; + break; + case FlverMaterial.TextureType.NormalTextureResource2: + blend = true; + hasNormal2 = true; + break; + case FlverMaterial.TextureType.SpecularTextureResource2: + blend = true; + hasSpec2 = true; + break; + case FlverMaterial.TextureType.ShininessTextureResource2: + blend = true; + hasShininess2 = true; + break; + case FlverMaterial.TextureType.BlendmaskTextureResource: + blendMask = true; + break; + default: + break; } + LookupTexture(type, dest, typename, mpath, mtd); } unsafe private void ProcessMaterial(IFlverMaterial mat, FlverMaterial dest, GameType type) From 402ceed0bbfc0713cfae4fb5cb028a23427d4a40 Mon Sep 17 00:00:00 2001 From: Trench Zhang Date: Tue, 18 Apr 2023 20:20:37 +0800 Subject: [PATCH 2/4] export map --- StudioCore/MsbEditor/Entity.cs | 30 +++++++++++++++ StudioCore/MsbEditor/ObjectContainer.cs | 51 ++++++++++++++++++++++++- StudioCore/MsbEditor/SceneTree.cs | 13 +++++++ StudioCore/MsbEditor/Universe.cs | 28 ++++++++++++++ StudioCore/Resource/ResourceManager.cs | 12 ++++++ 5 files changed, 132 insertions(+), 2 deletions(-) diff --git a/StudioCore/MsbEditor/Entity.cs b/StudioCore/MsbEditor/Entity.cs index 452217304..9d5b92301 100644 --- a/StudioCore/MsbEditor/Entity.cs +++ b/StudioCore/MsbEditor/Entity.cs @@ -1055,14 +1055,34 @@ public override bool HasTransform } } + public class ModelInfoExport + { + public string Name { get; set; } + public string Type { get; set; } + public string SibPath { get; set; } + public string RealPath { get; set; } + public string DCXPath { get; set; } + + } + + public class MapInfo + { + public string Name { get; set; } + public MapSerializationEntity SerializationEntity { get; set; } = null; + public Dictionary LoadedModels { get; set; } = null; + } + public class MapSerializationEntity { public string Name { get; set; } = null; public int Msbidx { get; set; } = -1; public MapEntity.MapEntityType Type { get; set; } + public string TypeName { get; set; } public Transform Transform { get; set; } + public Vector3 EularRotation { get; set; } public List Children { get; set; } = null; + public bool ShouldSerializeChildren() { return (Children != null && Children.Count > 0); @@ -1446,8 +1466,18 @@ public MapSerializationEntity Serialize(Dictionary idmap) if (HasTransform) { e.Transform = GetLocalTransform(); + + var eularrot = e.Transform.EulerRotation; + + // radians to angles + eularrot.X = eularrot.X * 180 / (float)Math.PI; + eularrot.Y = eularrot.Y * 180 / (float)Math.PI; + eularrot.Z = eularrot.Z * 180 / (float)Math.PI; + + e.EularRotation = eularrot; } e.Type = Type; + e.TypeName = Type.ToString(); e.Children = new List(); if (idmap.ContainsKey(this)) { diff --git a/StudioCore/MsbEditor/ObjectContainer.cs b/StudioCore/MsbEditor/ObjectContainer.cs index 0d0459655..5b344c639 100644 --- a/StudioCore/MsbEditor/ObjectContainer.cs +++ b/StudioCore/MsbEditor/ObjectContainer.cs @@ -19,6 +19,7 @@ using static SoulsFormats.MCP; using System.ComponentModel; using StudioCore.Resource; +using Google.Protobuf.WellKnownTypes; namespace StudioCore.MsbEditor { @@ -929,14 +930,60 @@ public bool SerializeDS2ObjInstances(Param objs) return true; } - public MapSerializationEntity SerializeHierarchy() + public MapInfo SerializeHierarchy() { + MapInfo mapinfo = new MapInfo(); Dictionary idmap = new Dictionary(); for (int i = 0; i < Objects.Count; i++) { idmap.Add(Objects[i], i); } - return ((MapEntity)RootObject).Serialize(idmap); + mapinfo.Name = Name; + mapinfo.LoadedModels = new Dictionary(); + foreach (var lm in LoadedModels) + { + if(lm.Value.GetType().IsSubclassOf(typeof(MSBE.Model))) + { + // handle ER model + ModelInfoExport modelinfo = new ModelInfoExport(); + modelinfo.Name = lm.Key; + string typeandname = ((MSBE.Model)lm.Value).ToString(); + modelinfo.Type = typeandname.Substring(0, typeandname.IndexOf(" ")); + modelinfo.SibPath = ((MSBE.Model)lm.Value).SibPath; + if(modelinfo.Type == "MapPiece") + { + modelinfo.RealPath = ResourceManager.GetModelPath(Name+"_"+ modelinfo.Name.Substring(1)); + } + else + { + modelinfo.RealPath = ResourceManager.GetModelPath(modelinfo.Name); + } + + if(modelinfo.Type == "MapPiece") + { + string mapid_head = Name.Substring(0, 3); + modelinfo.DCXPath = $@"map\{mapid_head}\{Name}\{Name}_{modelinfo.Name.Substring(1)}.mapbnd.dcx"; + } + else if(modelinfo.Type == "Asset") + { + string asset_head = modelinfo.Name.Substring(0, modelinfo.Name.IndexOf('_')); + modelinfo.DCXPath = $@"asset\aeg\{asset_head.ToLower()}\{modelinfo.Name.ToLower()}.geombnd.dcx"; + } + else if (modelinfo.Type == "Enemy" || modelinfo.Type == "Player") + { + modelinfo.DCXPath = $@"chr\{modelinfo.Name.ToLower()}.chrbnd.dcx"; + } + else + { + modelinfo.DCXPath = ""; + } + + + mapinfo.LoadedModels.Add(lm.Key, modelinfo); + } + } + mapinfo.SerializationEntity = ((MapEntity)RootObject).Serialize(idmap); + return mapinfo; } } } diff --git a/StudioCore/MsbEditor/SceneTree.cs b/StudioCore/MsbEditor/SceneTree.cs index 7a0fcae43..fab7db8fc 100644 --- a/StudioCore/MsbEditor/SceneTree.cs +++ b/StudioCore/MsbEditor/SceneTree.cs @@ -737,6 +737,19 @@ public void OnGui() _editorActionManager.Clear(); pendingUnload = m; } + if (ImGui.Selectable("Export Map")) + { + try + { + _universe.ExportMap(m); + } + catch (SavingFailedException e) + { + System.Windows.Forms.MessageBox.Show(e.Wrapped.Message, e.Message, + System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.None); + } + } } ImGui.EndPopup(); } diff --git a/StudioCore/MsbEditor/Universe.cs b/StudioCore/MsbEditor/Universe.cs index e0cebc437..1b193ac9d 100644 --- a/StudioCore/MsbEditor/Universe.cs +++ b/StudioCore/MsbEditor/Universe.cs @@ -13,6 +13,8 @@ using Newtonsoft.Json; using StudioCore.Scene; using StudioCore.Editor; +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json.Linq; namespace StudioCore.MsbEditor { @@ -663,11 +665,13 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false) foreach (var model in msb.Models.GetEntries()) { AssetDescription asset; + // map piece if (model.Name.StartsWith("m")) { asset = _assetLocator.GetMapModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, model.Name)); mappiecesToLoad.Add(asset); } + // character else if (model.Name.StartsWith("c")) { asset = _assetLocator.GetChrModel(model.Name); @@ -678,16 +682,19 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false) chrsToLoad.Add(tasset); } } + // object model else if (model.Name.StartsWith("o") || model.Name.StartsWith("AEG")) { asset = _assetLocator.GetObjModel(model.Name); objsToLoad.Add(asset); } + // collision else if (model.Name.StartsWith("h")) { asset = _assetLocator.GetMapCollisionModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, model.Name), false); colsToLoad.Add(asset); } + // navigation else if (model.Name.StartsWith("n") && _assetLocator.Type != GameType.DarkSoulsIISOTFS && _assetLocator.Type != GameType.Bloodborne) { asset = _assetLocator.GetMapNVMModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, model.Name)); @@ -1476,5 +1483,26 @@ public Type GetPropertyType(string name) } return null; } + + public void ExportMap(Map map) + { + + var browseDlg = new System.Windows.Forms.SaveFileDialog() + { + Title = "Export Map To Json", + FileName = map.Name + ".json", + Filter = "Json file (*.json) |*.JSON", + ValidateNames = true, + }; + + if (browseDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + using (var file = new StreamWriter(browseDlg.FileName)) + { + var json = JsonConvert.SerializeObject(map.SerializeHierarchy()); + file.Write(json); + } + } + } } } diff --git a/StudioCore/Resource/ResourceManager.cs b/StudioCore/Resource/ResourceManager.cs index da047c574..a5a3a6ce5 100644 --- a/StudioCore/Resource/ResourceManager.cs +++ b/StudioCore/Resource/ResourceManager.cs @@ -855,6 +855,18 @@ public static void OnGuiDrawResourceList() ImGui.End(); } + public static string GetModelPath(string modelName) + { + foreach (var item in ResourceDatabase) + { + if(item.Key.ToUpper().IndexOf(modelName.ToUpper()) >= 0) + { + return item.Key; + } + } + return ""; + } + public static void Shutdown() { JobScheduler.Dispose(); From 497f4c3eb847eecfbeae39272d61d8f4809c8507 Mon Sep 17 00:00:00 2001 From: Trench Zhang Date: Fri, 21 Apr 2023 15:36:59 +0800 Subject: [PATCH 3/4] map offset --- StudioCore/MsbEditor/Entity.cs | 1 + StudioCore/MsbEditor/ObjectContainer.cs | 3 +++ StudioCore/MsbEditor/SpecialMapConnections.cs | 18 +++++++++++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/StudioCore/MsbEditor/Entity.cs b/StudioCore/MsbEditor/Entity.cs index 9d5b92301..54675e54a 100644 --- a/StudioCore/MsbEditor/Entity.cs +++ b/StudioCore/MsbEditor/Entity.cs @@ -1070,6 +1070,7 @@ public class MapInfo public string Name { get; set; } public MapSerializationEntity SerializationEntity { get; set; } = null; public Dictionary LoadedModels { get; set; } = null; + public Vector3 MapTransform { get; set; } } public class MapSerializationEntity diff --git a/StudioCore/MsbEditor/ObjectContainer.cs b/StudioCore/MsbEditor/ObjectContainer.cs index 5b344c639..4cc10a8d9 100644 --- a/StudioCore/MsbEditor/ObjectContainer.cs +++ b/StudioCore/MsbEditor/ObjectContainer.cs @@ -982,6 +982,9 @@ public MapInfo SerializeHierarchy() mapinfo.LoadedModels.Add(lm.Key, modelinfo); } } + + mapinfo.MapTransform = SpecialMapConnections.GetEldenMapGlobalTransform(Name); + mapinfo.SerializationEntity = ((MapEntity)RootObject).Serialize(idmap); return mapinfo; } diff --git a/StudioCore/MsbEditor/SpecialMapConnections.cs b/StudioCore/MsbEditor/SpecialMapConnections.cs index 63b22fc18..e6c9536d5 100644 --- a/StudioCore/MsbEditor/SpecialMapConnections.cs +++ b/StudioCore/MsbEditor/SpecialMapConnections.cs @@ -14,6 +14,18 @@ namespace StudioCore.MsbEditor /// internal class SpecialMapConnections { + public static Vector3 GetEldenMapGlobalTransform(string mapid) + { + if (!TryInitializeEldenOffsets()) + { + return new Vector3(0, 0, 0); + } + if (!TryParseMap(mapid, out byte[] target) || !ToEldenGlobalCoords(target, Vector3.Zero, 0, 0, out Vector3 targetGlobal)) + { + return new Vector3(0, 0, 0); + } + return targetGlobal; + } public static Transform? GetEldenMapTransform( string mapid, IReadOnlyDictionary loadedMaps) @@ -26,9 +38,9 @@ internal class SpecialMapConnections { return null; } - (int originX, int originZ) = GetClosestTile(targetGlobal, 0, 0); + (int originTileX, int originTileZ) = GetClosestTile(targetGlobal, 0, 0); // Recenter target in terms of closest tile center, for maximum precision - if (!ToEldenGlobalCoords(target, Vector3.Zero, originX, originZ, out targetGlobal)) + if (!ToEldenGlobalCoords(target, Vector3.Zero, originTileX, originTileZ, out targetGlobal)) { return null; } @@ -41,7 +53,7 @@ internal class SpecialMapConnections if (entry.Value == null || !entry.Value.RootObject.HasTransform || !TryParseMap(entry.Key, out byte[] origin) - || !ToEldenGlobalCoords(origin, Vector3.Zero, originX, originZ, out Vector3 originGlobal)) + || !ToEldenGlobalCoords(origin, Vector3.Zero, originTileX, originTileZ, out Vector3 originGlobal)) { continue; } From 1464d1694c85aebcc19110c0febbe3c6d4aad392 Mon Sep 17 00:00:00 2001 From: Trench Zhang Date: Wed, 27 Sep 2023 16:36:06 +0800 Subject: [PATCH 4/4] fix build error --- DSMapStudio/DSMapStudio.csproj | 4 + StudioCore/Editor/EditorDecorations.cs | 1 - StudioCore/HelpMenu/HelpMenu.cs | 8 +- StudioCore/MapStudioNew.cs | 22 +- StudioCore/MsbEditor/SceneTree.cs | 20 +- StudioCore/MsbEditor/Universe.cs | 41 +-- StudioCore/ParamEditor/MassParamEdit.cs | 1 - StudioCore/ParamEditor/SearchEngine.cs | 323 ++++++++++++++---------- StudioCore/QueuedTaskScheduler.cs | 17 +- StudioCore/Resource/FlverResource.cs | 2 +- StudioCore/Resource/ResourceManager.cs | 1 - StudioCore/StudioCore.csproj | 3 + 12 files changed, 244 insertions(+), 199 deletions(-) diff --git a/DSMapStudio/DSMapStudio.csproj b/DSMapStudio/DSMapStudio.csproj index fe9235eaa..297ce75fd 100644 --- a/DSMapStudio/DSMapStudio.csproj +++ b/DSMapStudio/DSMapStudio.csproj @@ -46,6 +46,10 @@ + + + + diff --git a/StudioCore/Editor/EditorDecorations.cs b/StudioCore/Editor/EditorDecorations.cs index 9af5216e3..ee6da883a 100644 --- a/StudioCore/Editor/EditorDecorations.cs +++ b/StudioCore/Editor/EditorDecorations.cs @@ -12,7 +12,6 @@ using System.Text.RegularExpressions; using FSParam; using StudioCore; -using StudioCore.Editor; using StudioCore.ParamEditor; using StudioCore.TextEditor; diff --git a/StudioCore/HelpMenu/HelpMenu.cs b/StudioCore/HelpMenu/HelpMenu.cs index ff03a846c..6117f09d7 100644 --- a/StudioCore/HelpMenu/HelpMenu.cs +++ b/StudioCore/HelpMenu/HelpMenu.cs @@ -120,10 +120,10 @@ private void DisplayCore() // Content Segments List coreSegments = new List(); - foreach(string segment in contents) + foreach (string segment in contents) { List segmentParts = segment.Split(" ").ToList(); - foreach(string part in segmentParts) + foreach (string part in segmentParts) { coreSegments.Add(part.ToLower()); } @@ -138,7 +138,7 @@ private void DisplayCore() } // Only show if input matches any title or content segments, or if it is blank - if (inputStr.ToLower() == "" || sectionNameSegments.Contains(inputStr) || coreSegments.Contains(inputStr) || tagList.Contains(inputStr) ) + if (inputStr.ToLower() == "" || sectionNameSegments.Contains(inputStr) || coreSegments.Contains(inputStr) || tagList.Contains(inputStr)) { if (ImGui.Selectable(sectionName)) { @@ -486,4 +486,4 @@ private List GetDisplayTextSections(List stringList) return displayTextSegments; } } -} +} \ No newline at end of file diff --git a/StudioCore/MapStudioNew.cs b/StudioCore/MapStudioNew.cs index 64dc20dd0..185151bf1 100644 --- a/StudioCore/MapStudioNew.cs +++ b/StudioCore/MapStudioNew.cs @@ -48,7 +48,7 @@ public class MapStudioNew private static bool _initialLoadComplete = false; private static bool _firstframe = true; public static bool FirstFrame = true; - + // ImGui Debug windows private bool _showImGuiDemoWindow = false; private bool _showImGuiMetricsWindow = false; @@ -59,13 +59,13 @@ public unsafe MapStudioNew(IGraphicsContext context, string version) { _version = version; _programTitle = $"Dark Souls Map Studio version {_version}"; - + // Hack to make sure dialogs work before the main window is created PlatformUtils.InitializeWindows(null); CFG.AttemptLoadOrDefault(); - + Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + Path.PathSeparator + "bin"); - + _context = context; _context.Initialize(); _context.Window.Title = _programTitle; @@ -555,7 +555,7 @@ private bool AttemptLoadProject(Editor.ProjectSettings settings, string filename private bool StealGameDllIfMissing(ProjectSettings settings, string dllName) { - dllName = dllName+".dll"; + dllName = dllName + ".dll"; if (File.Exists(Path.Join(Path.GetFullPath("."), dllName))) return true; if (!File.Exists(Path.Join(settings.GameRoot, dllName))) @@ -594,7 +594,7 @@ public void AttemptSaveOnCrash() CFG.Current.LastProjectFile = ""; CFG.Save(); } - catch(Exception e) + catch (Exception e) { PlatformUtils.Instance.MessageBox($"Unable to save config during crash recovery.\n" + $"If you continue to crash on startup, delete config in AppData\\Local\\DSMapStudio\n\n" + @@ -832,12 +832,12 @@ private unsafe void Update(float deltaseconds) { SaveAll(); } - + if (ImGui.MenuItem("Editor Settings")) { _settingsMenu.MenuOpenState = true; } - + if (Resource.FlverResource.CaptureMaterialLayouts && ImGui.MenuItem("Dump Flver Layouts (Debug)", "")) { DumpFlverLayouts(); @@ -1011,7 +1011,7 @@ private unsafe void Update(float deltaseconds) { _standardProjectUIOpened = false; } - + if (ImGui.BeginTabItem("Advanced")) { NewProject_NameGUI(); @@ -1188,7 +1188,7 @@ private unsafe void Update(float deltaseconds) commands = commandsplit.Skip(1).ToArray(); ImGui.SetNextWindowFocus(); } - + if (_context.Device == null) ImGui.PushStyleColor(ImGuiCol.WindowBg, *ImGui.GetStyleColorVec4(ImGuiCol.WindowBg)); else @@ -1273,4 +1273,4 @@ public static float GetUIScale() return CFG.Current.UIScale; } } -} +} \ No newline at end of file diff --git a/StudioCore/MsbEditor/SceneTree.cs b/StudioCore/MsbEditor/SceneTree.cs index 7daaf7592..1fa2a3ecb 100644 --- a/StudioCore/MsbEditor/SceneTree.cs +++ b/StudioCore/MsbEditor/SceneTree.cs @@ -192,10 +192,10 @@ private void ChaliceDungeonImportButton() } private ulong _mapEnt_ImGuiID = 0; // Needed to avoid issue with identical IDs during keyboard navigation. May be unecessary when ImGUI is updated. - unsafe private void MapObjectSelectable(Entity e, bool visicon, bool hierarchial=false) + unsafe private void MapObjectSelectable(Entity e, bool visicon, bool hierarchial = false) { float scale = MapStudioNew.GetUIScale(); - + // Main selectable if (e is MapEntity me) { @@ -217,7 +217,7 @@ unsafe private void MapObjectSelectable(Entity e, bool visicon, bool hierarchial if (hierarchial && e.Children.Count > 0) { var treeflags = ImGuiTreeNodeFlags.OpenOnArrow | ImGuiTreeNodeFlags.SpanAvailWidth; - if ( _selection.GetSelection().Contains(e)) + if (_selection.GetSelection().Contains(e)) { treeflags |= ImGuiTreeNodeFlags.Selected; } @@ -233,7 +233,7 @@ unsafe private void MapObjectSelectable(Entity e, bool visicon, bool hierarchial else { _mapEnt_ImGuiID++; - if (ImGui.Selectable(padding + e.PrettyName+"##"+ _mapEnt_ImGuiID, _selection.GetSelection().Contains(e), ImGuiSelectableFlags.AllowDoubleClick | ImGuiSelectableFlags.AllowItemOverlap)) + if (ImGui.Selectable(padding + e.PrettyName + "##" + _mapEnt_ImGuiID, _selection.GetSelection().Contains(e), ImGuiSelectableFlags.AllowDoubleClick | ImGuiSelectableFlags.AllowItemOverlap)) { // If double clicked frame the selection in the viewport if (ImGui.IsMouseDoubleClicked(0)) @@ -376,7 +376,7 @@ unsafe private void MapObjectSelectable(Entity e, bool visicon, bool hierarchial _selection.AddSelection(e); } } - else if (_selection.GetSelection().Count > 0 + else if (_selection.GetSelection().Count > 0 && (InputTracker.GetKey(Key.ShiftLeft) || InputTracker.GetKey(Key.ShiftRight))) { // Select Range @@ -727,7 +727,7 @@ public void OnGui() ImGui.SameLine(); ImGui.PushTextWrapPos(); if (metaName.StartsWith("--")) // Marked as normally unused (use red text) - ImGui.TextColored(new Vector4(1.0f, 0.0f, 0.0f, 1.0f), @$"<{metaName.Replace("--","")}>"); + ImGui.TextColored(new Vector4(1.0f, 0.0f, 0.0f, 1.0f), @$"<{metaName.Replace("--", "")}>"); else ImGui.TextColored(new Vector4(1.0f, 1.0f, 0.0f, 1.0f), @$"<{metaName}>"); ImGui.PopTextWrapPos(); @@ -804,9 +804,9 @@ public void OnGui() } catch (SavingFailedException e) { - System.Windows.Forms.MessageBox.Show(e.Wrapped.Message, e.Message, - System.Windows.Forms.MessageBoxButtons.OK, - System.Windows.Forms.MessageBoxIcon.None); + PlatformUtils.Instance.MessageBox(e.Wrapped.Message, e.Message, + MessageBoxButtons.OK, + MessageBoxIcon.None); } } } @@ -960,4 +960,4 @@ public void OnActionEvent(ActionEvent evt) } } } -} +} \ No newline at end of file diff --git a/StudioCore/MsbEditor/Universe.cs b/StudioCore/MsbEditor/Universe.cs index ec3b53d66..a5fc85791 100644 --- a/StudioCore/MsbEditor/Universe.cs +++ b/StudioCore/MsbEditor/Universe.cs @@ -14,18 +14,18 @@ using SoulsFormats; using StudioCore.Scene; using StudioCore.Editor; -using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Linq; +using StudioCore.Platform; namespace StudioCore.MsbEditor { - [JsonSourceGenerationOptions(WriteIndented = true, + [JsonSourceGenerationOptions(WriteIndented = true, GenerationMode = JsonSourceGenerationMode.Metadata, IncludeFields = true)] [JsonSerializable(typeof(List))] internal partial class BtlLightSerializerContext : JsonSerializerContext { } - + /// /// A universe is a collection of loaded maps with methods to load, serialize, /// and unload individual maps. @@ -67,7 +67,7 @@ public int GetLoadedMapCount() { if (map.Value != null) { - i++; + i++; } } return i; @@ -151,7 +151,7 @@ private static ModelMarkerType GetModelMarkerType(string type) public RenderableProxy GetRegionDrawable(Map map, Entity obj) { - if (obj.WrappedObject is IMsbRegion r && r.Shape is MSB.Shape.Box ) + if (obj.WrappedObject is IMsbRegion r && r.Shape is MSB.Shape.Box) { var mesh = DebugPrimitiveRenderableProxy.GetBoxRegionProxy(_renderScene); mesh.World = obj.GetWorldMatrix(); @@ -447,7 +447,7 @@ public void LoadDS2Generators(string mapid, Map map) row.Name = "generator_" + row.ID.ToString(); } - + var mergedRow = new MergedParamRow(); mergedRow.AddRow("generator-loc", row); generatorParams.Add(row.ID, mergedRow); @@ -521,7 +521,7 @@ public void LoadDS2Generators(string mapid, Map map) row.Name = "eventloc_" + row.ID.ToString(); } eventLocationParams.Add(row.ID, row); - + var obj = new MapEntity(map, row, MapEntity.MapEntityType.DS2EventLocation); map.AddObject(obj); map.MapOffsetNode.AddChild(obj); @@ -671,7 +671,7 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false) _dispGroupCount = 8; //? break; case GameType.ArmoredCoreVI: - //TODO AC6 + //TODO AC6 default: throw new Exception($"Error: Did not expect Gametype {_assetLocator.Type}"); //break; @@ -723,13 +723,11 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false) foreach (var model in msb.Models.GetEntries()) { AssetDescription asset; - // map piece if (model.Name.StartsWith("m")) { asset = _assetLocator.GetMapModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, model.Name)); mappiecesToLoad.Add(asset); } - // character else if (model.Name.StartsWith("c")) { asset = _assetLocator.GetChrModel(model.Name); @@ -755,13 +753,11 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false) asset = _assetLocator.GetObjModel(model.Name); objsToLoad.Add(asset); } - // collision else if (model.Name.StartsWith("h")) { asset = _assetLocator.GetMapCollisionModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, model.Name), false); colsToLoad.Add(asset); } - // navigation else if (_assetLocator.Type == GameType.ArmoredCoreVI) { //TODO AC6 @@ -1291,7 +1287,7 @@ public void SaveBTL(Map map) var newLights = map.SerializeBtlLights(BTLs_w[i].AssetName); // Only save BTL if it has been modified - if (JsonSerializer.Serialize(btl.Lights, BtlLightSerializerContext.Default.ListLight) != + if (JsonSerializer.Serialize(btl.Lights, BtlLightSerializerContext.Default.ListLight) != JsonSerializer.Serialize(newLights, BtlLightSerializerContext.Default.ListLight)) { btl.Lights = newLights; @@ -1329,7 +1325,7 @@ public void SaveBTL(Map map) var newLights = map.SerializeBtlLights(BTLs_w[i].AssetName); // Only save BTL if it has been modified - if (JsonSerializer.Serialize(btl.Lights, BtlLightSerializerContext.Default.ListLight) != + if (JsonSerializer.Serialize(btl.Lights, BtlLightSerializerContext.Default.ListLight) != JsonSerializer.Serialize(newLights, BtlLightSerializerContext.Default.ListLight)) { btl.Lights = newLights; @@ -1568,23 +1564,14 @@ public Type GetPropertyType(string name) public void ExportMap(Map map) { - - var browseDlg = new System.Windows.Forms.SaveFileDialog() - { - Title = "Export Map To Json", - FileName = map.Name + ".json", - Filter = "Json file (*.json) |*.JSON", - ValidateNames = true, - }; - - if (browseDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) + if (PlatformUtils.Instance.SaveFileDialog("Export Map To Json", new[] { "json" }, out string path)) { - using (var file = new StreamWriter(browseDlg.FileName)) + using (var file = new StreamWriter(path)) { - var json = JsonConvert.SerializeObject(map.SerializeHierarchy()); + var json = Newtonsoft.Json.JsonConvert.SerializeObject(map.SerializeHierarchy()); file.Write(json); } } } } -} +} \ No newline at end of file diff --git a/StudioCore/ParamEditor/MassParamEdit.cs b/StudioCore/ParamEditor/MassParamEdit.cs index 85f574396..0327093e4 100644 --- a/StudioCore/ParamEditor/MassParamEdit.cs +++ b/StudioCore/ParamEditor/MassParamEdit.cs @@ -8,7 +8,6 @@ using ImGuiNET; using SoulsFormats; using StudioCore.Editor; -using StudioCore.ParamEditor; namespace StudioCore.ParamEditor { diff --git a/StudioCore/ParamEditor/SearchEngine.cs b/StudioCore/ParamEditor/SearchEngine.cs index 05824284c..49d0b10c6 100644 --- a/StudioCore/ParamEditor/SearchEngine.cs +++ b/StudioCore/ParamEditor/SearchEngine.cs @@ -6,37 +6,38 @@ using FSParam; using ImGuiNET; using SoulsFormats; -using StudioCore.ParamEditor; using StudioCore.TextEditor; -namespace StudioCore.Editor +namespace StudioCore.ParamEditor { /* Restricted characters: colon, space, forward slash, ampersand, exclamation mark * */ - class SearchEngine + class SearchEngine { public SearchEngine() { Setup(); } - internal Dictionary> filterList = new Dictionary>(); - internal SearchEngineCommand defaultFilter = null; + internal Dictionary> filterList = new Dictionary>(); + internal SearchEngineCommand defaultFilter = null; internal Func> unpacker; - protected void addExistsFilter() { - filterList.Add("exists", newCmd(new string[0], "Selects all elements", noArgs(noContext((B)=>true)))); + protected void addExistsFilter() + { + filterList.Add("exists", newCmd(new string[0], "Selects all elements", noArgs(noContext((B) => true)))); } protected Func>> noArgs(Func> func) { - return (args, lenient)=>func; + return (args, lenient) => func; } protected Func> noContext(Func func) { - return (context)=>func; + return (context) => func; } - internal virtual void Setup(){ + internal virtual void Setup() + { } internal SearchEngineCommand newCmd(string[] args, string wiki, Func>> func, Func shouldShow = null) { @@ -54,12 +55,12 @@ public List AvailableCommandsForHelpText() List options = new List(); foreach (string op in filterList.Keys) { - SearchEngineCommand cmd = filterList[op]; + SearchEngineCommand cmd = filterList[op]; if (cmd.shouldShow == null || cmd.shouldShow()) - options.Add(op+"("+(filterList[op].args.Length)+" args)"); + options.Add(op + "(" + filterList[op].args.Length + " args)"); } if (defaultFilter != null && (defaultFilter.shouldShow == null || defaultFilter.shouldShow())) - options.Add("or omit specifying and use default ("+defaultFilter.args.Length+"args)"); + options.Add("or omit specifying and use default (" + defaultFilter.args.Length + "args)"); return options; } public List<(string, string[], string)> VisibleCommands() @@ -67,7 +68,7 @@ public List AvailableCommandsForHelpText() List<(string, string[], string)> options = new List<(string, string[], string)>(); foreach (string op in filterList.Keys) { - SearchEngineCommand cmd = filterList[op]; + SearchEngineCommand cmd = filterList[op]; if (cmd.shouldShow == null || cmd.shouldShow()) options.Add((op, cmd.args, cmd.wiki)); } @@ -96,7 +97,8 @@ public virtual List Search(A context, List sourceSet, string command, bool string[] conditions = command.Split("&&", StringSplitOptions.TrimEntries); List liveSet = sourceSet; - try { + try + { foreach (string condition in conditions) { //temp @@ -104,7 +106,7 @@ public virtual List Search(A context, List sourceSet, string command, bool break; string[] cmd = condition.Split(' ', 2); - SearchEngineCommand selectedCommand; + SearchEngineCommand selectedCommand; int argC; string[] args; bool not = false; @@ -117,7 +119,7 @@ public virtual List Search(A context, List sourceSet, string command, bool { selectedCommand = filterList[cmd[0]]; argC = selectedCommand.args.Length; - args = cmd.Length==1?new string[0] : cmd[1].Split(' ', argC, StringSplitOptions.TrimEntries); + args = cmd.Length == 1 ? new string[0] : cmd[1].Split(' ', argC, StringSplitOptions.TrimEntries); } else { @@ -125,7 +127,7 @@ public virtual List Search(A context, List sourceSet, string command, bool argC = selectedCommand.args.Length; args = condition.Split(" ", argC, StringSplitOptions.TrimEntries); } - for (int i=0; i : SearchEngine + class MultiStageSearchEngine : SearchEngine { internal Func contextGetterForMultiStage = null; internal Func sourceListGetterForMultiStage = null; @@ -191,18 +193,19 @@ class ParamAndRowSearchEngine : MultiStageSearchEngine parse = new ParamAndRowSearchEngine(); internal override void Setup() { - unpacker = (selection)=>{ + unpacker = (selection) => + { List<(MassEditRowSource, Param.Row)> list = new List<(MassEditRowSource, Param.Row)>(); list.AddRange(selection.getSelectedRows().Select((x, i) => (MassEditRowSource.Selection, x))); list.AddRange(ParamBank.ClipboardRows.Select((x, i) => (MassEditRowSource.Clipboard, x))); return list; }; - filterList.Add("selection", newCmd(new string[0], "Selects the current param selection and selected rows in that param", noArgs(noContext((row)=>row.Item1 == MassEditRowSource.Selection)))); - filterList.Add("clipboard", newCmd(new string[0], "Selects the param of the clipboard and the rows in the clipboard", noArgs(noContext((row)=>row.Item1 == MassEditRowSource.Clipboard)), ()=>ParamBank.ClipboardRows?.Count > 0)); - contextGetterForMultiStage = (ParamEditorSelectionState state, (MassEditRowSource, Param.Row) exampleItem) => (ParamBank.PrimaryBank, ParamBank.PrimaryBank.Params[exampleItem.Item1 == MassEditRowSource.Selection ? state.getActiveParam() : ParamBank.ClipboardParam]); - sourceListGetterForMultiStage = ((MassEditRowSource, Param.Row) row) => row.Item2; + filterList.Add("selection", newCmd(new string[0], "Selects the current param selection and selected rows in that param", noArgs(noContext((row) => row.Item1 == MassEditRowSource.Selection)))); + filterList.Add("clipboard", newCmd(new string[0], "Selects the param of the clipboard and the rows in the clipboard", noArgs(noContext((row) => row.Item1 == MassEditRowSource.Clipboard)), () => ParamBank.ClipboardRows?.Count > 0)); + contextGetterForMultiStage = (state, exampleItem) => (ParamBank.PrimaryBank, ParamBank.PrimaryBank.Params[exampleItem.Item1 == MassEditRowSource.Selection ? state.getActiveParam() : ParamBank.ClipboardParam]); + sourceListGetterForMultiStage = (row) => row.Item2; searchEngineForMultiStage = RowSearchEngine.rse; - resultRetrieverForMultiStage = (Param.Row row, (MassEditRowSource, Param.Row) exampleItem) => (exampleItem.Item1, row); + resultRetrieverForMultiStage = (row, exampleItem) => (exampleItem.Item1, row); } } enum MassEditRowSource @@ -221,25 +224,29 @@ private ParamSearchEngine(ParamBank bank) ParamBank bank; internal override void Setup() { - unpacker = (dummy)=>ParamBank.AuxBanks.Select((aux, i) => aux.Value.Params.Select((x, i) => (aux.Value, x.Value))).Aggregate(bank.Params.Values.Select((x, i) => (bank, x)), (o, n) => o.Concat(n)).ToList(); - filterList.Add("modified", newCmd(new string[0], "Selects params where any rows do not match the vanilla version, or where any are added. Ignores row names", noArgs(noContext((param)=>{ + unpacker = (dummy) => ParamBank.AuxBanks.Select((aux, i) => aux.Value.Params.Select((x, i) => (aux.Value, x.Value))).Aggregate(bank.Params.Values.Select((x, i) => (bank, x)), (o, n) => o.Concat(n)).ToList(); + filterList.Add("modified", newCmd(new string[0], "Selects params where any rows do not match the vanilla version, or where any are added. Ignores row names", noArgs(noContext((param) => + { if (param.Item1 != bank) return false; HashSet cache = bank.GetVanillaDiffRows(bank.GetKeyForParam(param.Item2)); return cache.Count > 0; })))); - filterList.Add("param", newCmd(new string[]{"param name (regex)"}, "Selects all params whose name matches the given regex", (args, lenient)=>{ + filterList.Add("param", newCmd(new string[] { "param name (regex)" }, "Selects all params whose name matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[0], RegexOptions.IgnoreCase) : new Regex($@"^{args[0]}$"); - return noContext((param)=>param.Item1 != bank ? false : rx.IsMatch(bank.GetKeyForParam(param.Item2) == null ? "" : bank.GetKeyForParam(param.Item2))); + return noContext((param) => param.Item1 != bank ? false : rx.IsMatch(bank.GetKeyForParam(param.Item2) == null ? "" : bank.GetKeyForParam(param.Item2))); })); - filterList.Add("auxparam", newCmd(new string[]{"parambank name", "param name (regex)"}, "Selects params from the specified regulation or parambnd where the param name matches the given regex", (args, lenient)=>{ + filterList.Add("auxparam", newCmd(new string[] { "parambank name", "param name (regex)" }, "Selects params from the specified regulation or parambnd where the param name matches the given regex", (args, lenient) => + { ParamBank auxBank = ParamBank.AuxBanks[args[0]]; Regex rx = lenient ? new Regex(args[1], RegexOptions.IgnoreCase) : new Regex($@"^{args[1]}$"); - return noContext((param)=>param.Item1 != auxBank ? false : rx.IsMatch(auxBank.GetKeyForParam(param.Item2) == null ? "" : auxBank.GetKeyForParam(param.Item2))); - }, ()=>ParamBank.AuxBanks.Count > 0 && CFG.Current.Param_AdvancedMassedit)); - defaultFilter = newCmd(new string[]{"param name (regex)"}, "Selects all params whose name matches the given regex", (args, lenient)=>{ + return noContext((param) => param.Item1 != auxBank ? false : rx.IsMatch(auxBank.GetKeyForParam(param.Item2) == null ? "" : auxBank.GetKeyForParam(param.Item2))); + }, () => ParamBank.AuxBanks.Count > 0 && CFG.Current.Param_AdvancedMassedit)); + defaultFilter = newCmd(new string[] { "param name (regex)" }, "Selects all params whose name matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[0], RegexOptions.IgnoreCase) : new Regex($@"^{args[0]}$"); - return noContext((param)=>param.Item1 != bank ? false : rx.IsMatch(bank.GetKeyForParam(param.Item2) == null ? "" : bank.GetKeyForParam(param.Item2))); + return noContext((param) => param.Item1 != bank ? false : rx.IsMatch(bank.GetKeyForParam(param.Item2) == null ? "" : bank.GetKeyForParam(param.Item2))); }); } } @@ -254,81 +261,93 @@ private RowSearchEngine(ParamBank bank) internal override void Setup() { unpacker = (param) => new List(param.Item2.Rows); - filterList.Add("modified", newCmd(new string[0], "Selects rows which do not match the vanilla version, or are added. Ignores row name", noArgs((context)=>{ - string paramName = context.Item1.GetKeyForParam(context.Item2); - HashSet cache = context.Item1.GetVanillaDiffRows(paramName); - return (row) => cache.Contains(row.ID); - } + filterList.Add("modified", newCmd(new string[0], "Selects rows which do not match the vanilla version, or are added. Ignores row name", noArgs((context) => + { + string paramName = context.Item1.GetKeyForParam(context.Item2); + HashSet cache = context.Item1.GetVanillaDiffRows(paramName); + return (row) => cache.Contains(row.ID); + } ))); - filterList.Add("added", newCmd(new string[0], "Selects rows where the ID is not found in the vanilla param", noArgs((context)=>{ - string paramName = context.Item1.GetKeyForParam(context.Item2); - if (!ParamBank.VanillaBank.Params.ContainsKey(paramName)) - return (row) => true; - Param vanilParam = ParamBank.VanillaBank.Params[paramName]; - return (row) => vanilParam[row.ID] == null; - } + filterList.Add("added", newCmd(new string[0], "Selects rows where the ID is not found in the vanilla param", noArgs((context) => + { + string paramName = context.Item1.GetKeyForParam(context.Item2); + if (!ParamBank.VanillaBank.Params.ContainsKey(paramName)) + return (row) => true; + Param vanilParam = ParamBank.VanillaBank.Params[paramName]; + return (row) => vanilParam[row.ID] == null; + } ))); - filterList.Add("mergeable", newCmd(new string[0], "Selects rows which are not modified in the primary regulation or parambnd and there is exactly one equivalent row in another regulation or parambnd that is modified", noArgs((context)=>{ + filterList.Add("mergeable", newCmd(new string[0], "Selects rows which are not modified in the primary regulation or parambnd and there is exactly one equivalent row in another regulation or parambnd that is modified", noArgs((context) => + { string paramName = context.Item1.GetKeyForParam(context.Item2); if (paramName == null) return (row) => true; HashSet pCache = ParamBank.PrimaryBank.GetVanillaDiffRows(paramName); - var auxCaches = ParamBank.AuxBanks.Select(x=>(x.Value.GetPrimaryDiffRows(paramName), x.Value.GetVanillaDiffRows(paramName))).ToList(); + var auxCaches = ParamBank.AuxBanks.Select(x => (x.Value.GetPrimaryDiffRows(paramName), x.Value.GetVanillaDiffRows(paramName))).ToList(); return (row) => !pCache.Contains(row.ID) && auxCaches.Where((x) => x.Item2.Contains(row.ID) && x.Item1.Contains(row.ID)).Count() == 1; - } - ), ()=>ParamBank.AuxBanks.Count > 0)); - filterList.Add("conflicts", newCmd(new string[0], "Selects rows which, among all equivalents in the primary and additional regulations or parambnds, there is more than row 1 which is modified", noArgs((context)=>{ + } + ), () => ParamBank.AuxBanks.Count > 0)); + filterList.Add("conflicts", newCmd(new string[0], "Selects rows which, among all equivalents in the primary and additional regulations or parambnds, there is more than row 1 which is modified", noArgs((context) => + { string paramName = context.Item1.GetKeyForParam(context.Item2); HashSet pCache = ParamBank.PrimaryBank.GetVanillaDiffRows(paramName); - var auxCaches = ParamBank.AuxBanks.Select(x=>(x.Value.GetPrimaryDiffRows(paramName), x.Value.GetVanillaDiffRows(paramName))).ToList(); - return (row) => (pCache.Contains(row.ID)?1:0) + auxCaches.Where((x) => x.Item2.Contains(row.ID) && x.Item1.Contains(row.ID)).Count() > 1; - } - ), ()=>ParamBank.AuxBanks.Count > 0)); - filterList.Add("id", newCmd(new string[]{"row id (regex)"}, "Selects rows whose ID matches the given regex", (args, lenient)=>{ + var auxCaches = ParamBank.AuxBanks.Select(x => (x.Value.GetPrimaryDiffRows(paramName), x.Value.GetVanillaDiffRows(paramName))).ToList(); + return (row) => (pCache.Contains(row.ID) ? 1 : 0) + auxCaches.Where((x) => x.Item2.Contains(row.ID) && x.Item1.Contains(row.ID)).Count() > 1; + } + ), () => ParamBank.AuxBanks.Count > 0)); + filterList.Add("id", newCmd(new string[] { "row id (regex)" }, "Selects rows whose ID matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[0].ToLower()) : new Regex($@"^{args[0]}$"); - return noContext((row)=>rx.IsMatch(row.ID.ToString())); + return noContext((row) => rx.IsMatch(row.ID.ToString())); })); - filterList.Add("idrange", newCmd(new string[]{"row id minimum (inclusive)", "row id maximum (inclusive)"}, "Selects rows whose ID falls in the given numerical range", (args, lenient)=>{ + filterList.Add("idrange", newCmd(new string[] { "row id minimum (inclusive)", "row id maximum (inclusive)" }, "Selects rows whose ID falls in the given numerical range", (args, lenient) => + { double floor = double.Parse(args[0]); double ceil = double.Parse(args[1]); - return noContext((row)=>row.ID >= floor && row.ID <= ceil); + return noContext((row) => row.ID >= floor && row.ID <= ceil); })); - filterList.Add("name", newCmd(new string[]{"row name (regex)"}, "Selects rows whose Name matches the given regex", (args, lenient)=>{ + filterList.Add("name", newCmd(new string[] { "row name (regex)" }, "Selects rows whose Name matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[0], RegexOptions.IgnoreCase) : new Regex($@"^{args[0]}$"); - return noContext((row)=>rx.IsMatch(row.Name == null ? "" : row.Name)); + return noContext((row) => rx.IsMatch(row.Name == null ? "" : row.Name)); })); - filterList.Add("prop", newCmd(new string[]{"field internalName", "field value (regex)"}, "Selects rows where the specified field has a value that matches the given regex", (args, lenient)=>{ + filterList.Add("prop", newCmd(new string[] { "field internalName", "field value (regex)" }, "Selects rows where the specified field has a value that matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[1], RegexOptions.IgnoreCase) : new Regex($@"^{args[1]}$"); string field = args[0].Replace(@"\s", " "); - return noContext((row)=>{ - Param.Cell? cq = row[field]; - if (cq == null) throw new Exception(); - Param.Cell c = cq.Value; - string term = c.Value.ToParamEditorString(); - return rx.IsMatch(term); + return noContext((row) => + { + Param.Cell? cq = row[field]; + if (cq == null) throw new Exception(); + Param.Cell c = cq.Value; + string term = c.Value.ToParamEditorString(); + return rx.IsMatch(term); }); })); - filterList.Add("proprange", newCmd(new string[]{"field internalName", "field value minimum (inclusive)", "field value maximum (inclusive)"}, "Selects rows where the specified field has a value that falls in the given numerical range", (args, lenient)=>{ + filterList.Add("proprange", newCmd(new string[] { "field internalName", "field value minimum (inclusive)", "field value maximum (inclusive)" }, "Selects rows where the specified field has a value that falls in the given numerical range", (args, lenient) => + { string field = args[0].Replace(@"\s", " "); double floor = double.Parse(args[1]); double ceil = double.Parse(args[2]); - return noContext((row)=> + return noContext((row) => { - Param.Cell? c = row[field]; - if (c == null) throw new Exception(); - return (Convert.ToDouble(c.Value.Value)) >= floor && (Convert.ToDouble(c.Value.Value)) <= ceil; + Param.Cell? c = row[field]; + if (c == null) throw new Exception(); + return Convert.ToDouble(c.Value.Value) >= floor && Convert.ToDouble(c.Value.Value) <= ceil; }); })); - filterList.Add("propref", newCmd(new string[]{"field internalName", "referenced row name (regex)"}, "Selects rows where the specified field that references another param has a value referencing a row whose name matches the given regex", (args, lenient)=>{ + filterList.Add("propref", newCmd(new string[] { "field internalName", "referenced row name (regex)" }, "Selects rows where the specified field that references another param has a value referencing a row whose name matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[1], RegexOptions.IgnoreCase) : new Regex($@"^{args[1]}$"); string field = args[0].Replace(@"\s", " "); - return (context)=>{ - List validFields = FieldMetaData.Get(context.Item2.AppliedParamdef.Fields.Find((f)=>f.InternalName.Equals(field))).RefTypes.FindAll((p)=>bank.Params.ContainsKey(p.param)); - return (row)=> + return (context) => + { + List validFields = FieldMetaData.Get(context.Item2.AppliedParamdef.Fields.Find((f) => f.InternalName.Equals(field))).RefTypes.FindAll((p) => bank.Params.ContainsKey(p.param)); + return (row) => { Param.Cell? c = row[field]; if (c == null) throw new Exception(); - int val = (int) c.Value.Value; + int val = (int)c.Value.Value; foreach (ParamRef rt in validFields) { Param.Row r = bank.Params[rt.param][val]; @@ -338,24 +357,28 @@ internal override void Setup() return false; }; }; - }, ()=>CFG.Current.Param_AdvancedMassedit)); - filterList.Add("propwhere", newCmd(new string[]{"field internalName", "cell/field selector"}, "Selects rows where the specified field appears when the given cell/field search is given", (args, lenient)=>{ + }, () => CFG.Current.Param_AdvancedMassedit)); + filterList.Add("propwhere", newCmd(new string[] { "field internalName", "cell/field selector" }, "Selects rows where the specified field appears when the given cell/field search is given", (args, lenient) => + { string field = args[0].Replace(@"\s", " "); - return (context)=>{ + return (context) => + { string paramName = context.Item1.GetKeyForParam(context.Item2); var cols = context.Item2.Columns; var testCol = context.Item2.GetCol(field); - return (row)=> + return (row) => { var cseSearchContext = (paramName, row); - var res = CellSearchEngine.cse.Search(cseSearchContext, new List<(PseudoColumn, Param.Column)>(){testCol}, args[1], lenient, false); + var res = CellSearchEngine.cse.Search(cseSearchContext, new List<(PseudoColumn, Param.Column)>() { testCol }, args[1], lenient, false); return res.Contains(testCol); }; }; - }, ()=>CFG.Current.Param_AdvancedMassedit)); - filterList.Add("fmg", newCmd(new string[]{"fmg title (regex)"}, "Selects rows which have an attached FMG and that FMG's text matches the given regex", (args, lenient)=>{ + }, () => CFG.Current.Param_AdvancedMassedit)); + filterList.Add("fmg", newCmd(new string[] { "fmg title (regex)" }, "Selects rows which have an attached FMG and that FMG's text matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[0], RegexOptions.IgnoreCase) : new Regex($@"^{args[0]}$"); - return (context)=>{ + return (context) => + { FmgEntryCategory category = FmgEntryCategory.None; string paramName = context.Item1.GetKeyForParam(context.Item2); foreach ((string param, FmgEntryCategory cat) in ParamBank.ParamToFmgCategoryList) @@ -372,20 +395,24 @@ internal override void Setup() { _cache[fmgEntry.ID] = fmgEntry; } - return (row)=>{ + return (row) => + { if (!_cache.ContainsKey(row.ID)) return false; FMG.Entry e = _cache[row.ID]; return e != null && rx.IsMatch(e.Text ?? ""); }; }; - }, ()=>CFG.Current.Param_AdvancedMassedit)); - filterList.Add("vanillaprop", newCmd(new string[]{"field internalName", "field value (regex)"}, "Selects rows where the vanilla equivilent of that row has a value for the given field that matches the given regex", (args, lenient)=>{ + }, () => CFG.Current.Param_AdvancedMassedit)); + filterList.Add("vanillaprop", newCmd(new string[] { "field internalName", "field value (regex)" }, "Selects rows where the vanilla equivilent of that row has a value for the given field that matches the given regex", (args, lenient) => + { Regex rx = lenient ? new Regex(args[1], RegexOptions.IgnoreCase) : new Regex($@"^{args[1]}$"); string field = args[0].Replace(@"\s", " "); - return (param) => { + return (param) => + { Param vparam = ParamBank.VanillaBank.GetParamFromName(param.Item1.GetKeyForParam(param.Item2)); - return (row)=>{ + return (row) => + { Param.Row vrow = vparam[row.ID]; if (vrow == null) return false; @@ -396,32 +423,38 @@ internal override void Setup() return rx.IsMatch(term); }; }; - }, ()=>CFG.Current.Param_AdvancedMassedit)); - filterList.Add("vanillaproprange", newCmd(new string[]{"field internalName", "field value minimum (inclusive)", "field value maximum (inclusive)"}, "Selects rows where the vanilla equivilent of that row has a value for the given field that falls in the given numerical range", (args, lenient)=>{ + }, () => CFG.Current.Param_AdvancedMassedit)); + filterList.Add("vanillaproprange", newCmd(new string[] { "field internalName", "field value minimum (inclusive)", "field value maximum (inclusive)" }, "Selects rows where the vanilla equivilent of that row has a value for the given field that falls in the given numerical range", (args, lenient) => + { string field = args[0].Replace(@"\s", " "); double floor = double.Parse(args[1]); double ceil = double.Parse(args[2]); - return (param) => { + return (param) => + { Param vparam = ParamBank.VanillaBank.GetParamFromName(param.Item1.GetKeyForParam(param.Item2)); - return (row)=>{ + return (row) => + { Param.Row vrow = vparam[row.ID]; if (vrow == null) return false; Param.Cell? c = vrow[field]; if (c == null) throw new Exception(); - return (Convert.ToDouble(c.Value.Value)) >= floor && (Convert.ToDouble(c.Value.Value)) <= ceil; + return Convert.ToDouble(c.Value.Value) >= floor && Convert.ToDouble(c.Value.Value) <= ceil; }; }; - }, ()=>CFG.Current.Param_AdvancedMassedit)); - filterList.Add("auxprop", newCmd(new string[]{"parambank name", "field internalName", "field value (regex)"}, "Selects rows where the equivilent of that row in the given regulation or parambnd has a value for the given field that matches the given regex.\nCan be used to determine if an aux row exists.", (args, lenient)=>{ + }, () => CFG.Current.Param_AdvancedMassedit)); + filterList.Add("auxprop", newCmd(new string[] { "parambank name", "field internalName", "field value (regex)" }, "Selects rows where the equivilent of that row in the given regulation or parambnd has a value for the given field that matches the given regex.\nCan be used to determine if an aux row exists.", (args, lenient) => + { Regex rx = lenient ? new Regex(args[2], RegexOptions.IgnoreCase) : new Regex($@"^{args[2]}$"); string field = args[1].Replace(@"\s", " "); ParamBank bank; if (!ParamBank.AuxBanks.TryGetValue(args[0], out bank)) - throw new Exception("Unable to find auxbank "+args[0]); - return (param) => { + throw new Exception("Unable to find auxbank " + args[0]); + return (param) => + { Param vparam = bank.GetParamFromName(param.Item1.GetKeyForParam(param.Item2)); - return (row)=>{ + return (row) => + { Param.Row vrow = vparam[row.ID]; if (vrow == null) return false; @@ -432,8 +465,9 @@ internal override void Setup() return rx.IsMatch(term); }; }; - }, ()=>ParamBank.AuxBanks.Count > 0 && CFG.Current.Param_AdvancedMassedit)); - filterList.Add("auxproprange", newCmd(new string[]{"parambank name", "field internalName", "field value minimum (inclusive)", "field value maximum (inclusive)"}, "Selects rows where the equivilent of that row in the given regulation or parambnd has a value for the given field that falls in the given range", (args, lenient)=>{ + }, () => ParamBank.AuxBanks.Count > 0 && CFG.Current.Param_AdvancedMassedit)); + filterList.Add("auxproprange", newCmd(new string[] { "parambank name", "field internalName", "field value minimum (inclusive)", "field value maximum (inclusive)" }, "Selects rows where the equivilent of that row in the given regulation or parambnd has a value for the given field that falls in the given range", (args, lenient) => + { string field = args[0].Replace(@"\s", " "); double floor = double.Parse(args[1]); double ceil = double.Parse(args[2]); @@ -448,38 +482,43 @@ internal override void Setup() Param.Row vrow = vparam[row.ID]; Param.Cell? c = vrow[field]; if (c == null) throw new Exception(); - return (Convert.ToDouble(c.Value.Value)) >= floor && (Convert.ToDouble(c.Value.Value)) <= ceil; + return Convert.ToDouble(c.Value.Value) >= floor && Convert.ToDouble(c.Value.Value) <= ceil; }; }; - }, ()=>ParamBank.AuxBanks.Count > 0 && CFG.Current.Param_AdvancedMassedit)); - filterList.Add("semijoin", newCmd(new string[]{"this field internalName", "other param", "other param field internalName", "other param row search"}, "Selects all rows where the value of a given field is any of the values in the second given field found in the given param using the given row selector", (args, lenient)=>{ + }, () => ParamBank.AuxBanks.Count > 0 && CFG.Current.Param_AdvancedMassedit)); + filterList.Add("semijoin", newCmd(new string[] { "this field internalName", "other param", "other param field internalName", "other param row search" }, "Selects all rows where the value of a given field is any of the values in the second given field found in the given param using the given row selector", (args, lenient) => + { string thisField = args[0].Replace(@"\s", " "); string otherParam = args[1]; string otherField = args[2].Replace(@"\s", " "); string otherSearchTerm = args[3]; Param otherParamReal; if (!ParamBank.PrimaryBank.Params.TryGetValue(otherParam, out otherParamReal)) - throw new Exception("Could not find param "+otherParam); - List rows = RowSearchEngine.rse.Search((ParamBank.PrimaryBank, otherParamReal), otherSearchTerm, lenient, false); - (PseudoColumn, Param.Column) otherFieldReal = ParamUtils.GetCol(otherParamReal, otherField); + throw new Exception("Could not find param " + otherParam); + List rows = rse.Search((ParamBank.PrimaryBank, otherParamReal), otherSearchTerm, lenient, false); + (PseudoColumn, Param.Column) otherFieldReal = otherParamReal.GetCol(otherField); if (!otherFieldReal.IsColumnValid()) - throw new Exception("Could not find field "+otherField); + throw new Exception("Could not find field " + otherField); HashSet possibleValues = rows.Select((x) => x.Get(otherFieldReal).ToParamEditorString()).Distinct().ToHashSet(); - return (param) => { - (PseudoColumn, Param.Column) thisFieldReal = ParamUtils.GetCol(param.Item2, thisField); + return (param) => + { + (PseudoColumn, Param.Column) thisFieldReal = param.Item2.GetCol(thisField); if (!thisFieldReal.IsColumnValid()) - throw new Exception("Could not find field "+thisField); - return (row)=>{ + throw new Exception("Could not find field " + thisField); + return (row) => + { string toFind = row.Get(thisFieldReal).ToParamEditorString(); return possibleValues.Contains(toFind); }; }; - }, ()=>CFG.Current.Param_AdvancedMassedit)); - defaultFilter = newCmd(new string[]{"row ID or Name (regex)"}, "Selects rows where either the ID or Name matches the given regex, except in strict/massedit mode", (args, lenient)=>{ + }, () => CFG.Current.Param_AdvancedMassedit)); + defaultFilter = newCmd(new string[] { "row ID or Name (regex)" }, "Selects rows where either the ID or Name matches the given regex, except in strict/massedit mode", (args, lenient) => + { if (!lenient) - return noContext((row)=>false); + return noContext((row) => false); Regex rx = new Regex(args[0], RegexOptions.IgnoreCase); - return (paramContext)=>{ + return (paramContext) => + { FmgEntryCategory category = FmgEntryCategory.None; string paramName = paramContext.Item1.GetKeyForParam(paramContext.Item2); foreach ((string param, FmgEntryCategory cat) in ParamBank.ParamToFmgCategoryList) @@ -489,14 +528,15 @@ internal override void Setup() category = cat; } if (category == FmgEntryCategory.None || !FMGBank.IsLoaded) - return (row)=>rx.IsMatch(row.Name ?? "") || rx.IsMatch(row.ID.ToString()); + return (row) => rx.IsMatch(row.Name ?? "") || rx.IsMatch(row.ID.ToString()); var fmgEntries = FMGBank.GetFmgEntriesByCategory(category, false); Dictionary _cache = new Dictionary(); foreach (var fmgEntry in fmgEntries) { _cache[fmgEntry.ID] = fmgEntry; } - return (row)=>{ + return (row) => + { if (rx.IsMatch(row.Name ?? "") || rx.IsMatch(row.ID.ToString())) return true; if (!_cache.ContainsKey(row.ID)) @@ -514,18 +554,21 @@ class CellSearchEngine : SearchEngine<(string, Param.Row), (PseudoColumn, Param. public static CellSearchEngine cse = new CellSearchEngine(); internal override void Setup() { - unpacker = (row) => { + unpacker = (row) => + { var list = new List<(PseudoColumn, Param.Column)>(); list.Add((PseudoColumn.ID, null)); list.Add((PseudoColumn.Name, null)); list.AddRange(row.Item2.Columns.Select((cell, i) => (PseudoColumn.None, cell))); return list; }; - defaultFilter = newCmd(new string[]{"field internalName (regex)"}, "Selects cells/fields where the internal name of that field matches the given regex", (args, lenient) => { + defaultFilter = newCmd(new string[] { "field internalName (regex)" }, "Selects cells/fields where the internal name of that field matches the given regex", (args, lenient) => + { bool matchID = args[0] == "ID"; bool matchName = args[0] == "Name"; Regex rx = lenient ? new Regex(args[0], RegexOptions.IgnoreCase) : new Regex($@"^{args[0]}$"); - return noContext((cell) => { + return noContext((cell) => + { if (matchID && cell.Item1 == PseudoColumn.ID) return true; if (matchName && cell.Item1 == PseudoColumn.Name) @@ -541,7 +584,8 @@ internal override void Setup() return false; }); }); - filterList.Add("modified", newCmd(new string[0], "Selects cells/fields where the equivalent cell in the vanilla regulation or parambnd has a different value", (args, lenient) => (row) => { + filterList.Add("modified", newCmd(new string[0], "Selects cells/fields where the equivalent cell in the vanilla regulation or parambnd has a different value", (args, lenient) => (row) => + { if (row.Item1 == null) throw new Exception("Can't check if cell is modified - not part of a param"); Param vParam = ParamBank.VanillaBank.Params?[row.Item1]; @@ -551,18 +595,21 @@ internal override void Setup() if (r == null) return (col) => true; else - return (col) => { + return (col) => + { (PseudoColumn, Param.Column) vcol = col.GetAs(vParam); object valA = row.Item2.Get(col); object valB = r.Get(vcol); return ParamUtils.IsValueDiff(ref valA, ref valB, col.GetColumnType()); }; })); - filterList.Add("auxmodified", newCmd(new string[]{"parambank name"}, "Selects cells/fields where the equivalent cell in the specified regulation or parambnd has a different value", (args, lenient) => { + filterList.Add("auxmodified", newCmd(new string[] { "parambank name" }, "Selects cells/fields where the equivalent cell in the specified regulation or parambnd has a different value", (args, lenient) => + { if (!ParamBank.AuxBanks.ContainsKey(args[0])) throw new Exception("Can't check if cell is modified - parambank not found"); ParamBank bank = ParamBank.AuxBanks[args[0]]; - return (row) => { + return (row) => + { if (row.Item1 == null) throw new Exception("Can't check if cell is modified - not part of a param"); Param auxParam = bank.Params?[row.Item1]; @@ -578,7 +625,8 @@ internal override void Setup() else if (r2 == null) return (col) => true; else - return (col) => { + return (col) => + { (PseudoColumn, Param.Column) auxcol = col.GetAs(auxParam); (PseudoColumn, Param.Column) vcol = col.GetAs(vParam); object valA = r.Get(auxcol); @@ -586,31 +634,34 @@ internal override void Setup() return ParamUtils.IsValueDiff(ref valA, ref valB, col.GetColumnType()); }; }; - }, ()=>ParamBank.AuxBanks.Count > 0)); - filterList.Add("sftype", newCmd(new string[]{"paramdef type"}, "Selects cells/fields where the field's data type, as enumerated by soulsformats, matches the given regex", (args, lenient) => { - Regex r = new Regex('^'+args[0]+'$', lenient ? RegexOptions.IgnoreCase : RegexOptions.None); //Leniency rules break from the norm + }, () => ParamBank.AuxBanks.Count > 0)); + filterList.Add("sftype", newCmd(new string[] { "paramdef type" }, "Selects cells/fields where the field's data type, as enumerated by soulsformats, matches the given regex", (args, lenient) => + { + Regex r = new Regex('^' + args[0] + '$', lenient ? RegexOptions.IgnoreCase : RegexOptions.None); //Leniency rules break from the norm return (row) => (col) => r.IsMatch(col.GetColumnSfType()); - }, ()=>CFG.Current.Param_AdvancedMassedit)); + }, () => CFG.Current.Param_AdvancedMassedit)); } } - + class VarSearchEngine : SearchEngine { public static VarSearchEngine vse = new VarSearchEngine(); internal override void Setup() { - unpacker = (dummy) => { + unpacker = (dummy) => + { return MassParamEdit.massEditVars.Keys.ToList(); }; - filterList.Add("vars", newCmd(new string[]{"variable names (regex)"}, "Selects variables whose name matches the given regex", (args, lenient) => { + filterList.Add("vars", newCmd(new string[] { "variable names (regex)" }, "Selects variables whose name matches the given regex", (args, lenient) => + { if (args[0].StartsWith('$')) args[0] = args[0].Substring(1); Regex rx = lenient ? new Regex(args[0], RegexOptions.IgnoreCase) : new Regex($@"^{args[0]}$"); return noContext((name) => rx.IsMatch(name)); })); - + } } } \ No newline at end of file diff --git a/StudioCore/QueuedTaskScheduler.cs b/StudioCore/QueuedTaskScheduler.cs index cc71ca1d6..179a3d54e 100644 --- a/StudioCore/QueuedTaskScheduler.cs +++ b/StudioCore/QueuedTaskScheduler.cs @@ -6,12 +6,15 @@ // //-------------------------------------------------------------------------- +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading; +using System.Threading.Tasks; -namespace System.Threading.Tasks.Schedulers +namespace StudioCore { /// /// Provides a TaskScheduler that provides control over priorities, fairness, and the underlying threads utilized. @@ -39,8 +42,8 @@ public IEnumerable ScheduledTasks { get { - var tasks = (_scheduler._targetScheduler != null) ? - (IEnumerable)_scheduler._nonthreadsafeTaskQueue : + var tasks = _scheduler._targetScheduler != null ? + _scheduler._nonthreadsafeTaskQueue : (IEnumerable)_scheduler._blockingTaskQueue; return tasks.Where(t => t != null).ToList(); } @@ -96,7 +99,7 @@ public IEnumerable Queues // *** /// Initializes the scheduler. - public QueuedTaskScheduler() : this(TaskScheduler.Default, 0) { } + public QueuedTaskScheduler() : this(Default, 0) { } /// Initializes the scheduler. /// The target underlying scheduler onto which this sceduler's work is queued. @@ -121,7 +124,7 @@ public QueuedTaskScheduler( // If 0, use the number of logical processors. But make sure whatever value we pick // is not greater than the degree of parallelism allowed by the underlying scheduler. _concurrencyLevel = maxConcurrencyLevel != 0 ? maxConcurrencyLevel : Environment.ProcessorCount; - if (targetScheduler.MaximumConcurrencyLevel > 0 && + if (targetScheduler.MaximumConcurrencyLevel > 0 && targetScheduler.MaximumConcurrencyLevel < _concurrencyLevel) { _concurrencyLevel = targetScheduler.MaximumConcurrencyLevel; @@ -257,8 +260,8 @@ private int DebugTaskCount { get { - return (_targetScheduler != null ? - (IEnumerable)_nonthreadsafeTaskQueue : (IEnumerable)_blockingTaskQueue) + return (_targetScheduler != null ? + _nonthreadsafeTaskQueue : (IEnumerable)_blockingTaskQueue) .Where(t => t != null).Count(); } } diff --git a/StudioCore/Resource/FlverResource.cs b/StudioCore/Resource/FlverResource.cs index 0601a8284..989be11c4 100644 --- a/StudioCore/Resource/FlverResource.cs +++ b/StudioCore/Resource/FlverResource.cs @@ -373,7 +373,7 @@ private void LookupTexture(FlverMaterial.TextureType textureType, FlverMaterial } } - private void ProcessMaterialTexture(FlverMaterial dest, string typename, string mpath, string mtd, + private void ProcessMaterialTexture(FlverMaterial dest, string texType, string mpath, string mtd, GameType gameType, out bool blend, out bool hasNormal2, out bool hasSpec2, out bool hasShininess2, out bool blendMask) { blend = false; diff --git a/StudioCore/Resource/ResourceManager.cs b/StudioCore/Resource/ResourceManager.cs index 03ff00ccb..8ab54d481 100644 --- a/StudioCore/Resource/ResourceManager.cs +++ b/StudioCore/Resource/ResourceManager.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading.Tasks.Schedulers; using System.Threading; using System.Numerics; using System.IO; diff --git a/StudioCore/StudioCore.csproj b/StudioCore/StudioCore.csproj index 0799de734..ed7526abc 100644 --- a/StudioCore/StudioCore.csproj +++ b/StudioCore/StudioCore.csproj @@ -4,6 +4,7 @@ net7.0-windows 11 + faa5a10d-c786-42f5-bca0-31bc8d975cb9 @@ -425,9 +426,11 @@ + +