Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions DSMapStudio/DSMapStudio.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\StudioCore\StudioCore.csproj" />
<ProjectReference Include="..\Veldrid.SDL2\Veldrid.SDL2.csproj" />
Expand Down
1 change: 0 additions & 1 deletion StudioCore/Editor/EditorDecorations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using System.Text.RegularExpressions;
using FSParam;
using StudioCore;
using StudioCore.Editor;
using StudioCore.ParamEditor;
using StudioCore.TextEditor;

Expand Down
8 changes: 4 additions & 4 deletions StudioCore/HelpMenu/HelpMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ private void DisplayCore()
// Content Segments
List<string> coreSegments = new List<string>();

foreach(string segment in contents)
foreach (string segment in contents)
{
List<string> segmentParts = segment.Split(" ").ToList();
foreach(string part in segmentParts)
foreach (string part in segmentParts)
{
coreSegments.Add(part.ToLower());
}
Expand All @@ -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))
{
Expand Down Expand Up @@ -486,4 +486,4 @@ private List<string> GetDisplayTextSections(List<string> stringList)
return displayTextSegments;
}
}
}
}
22 changes: 11 additions & 11 deletions StudioCore/MapStudioNew.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)))
Expand Down Expand Up @@ -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" +
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -1011,7 +1011,7 @@ private unsafe void Update(float deltaseconds)
{
_standardProjectUIOpened = false;
}

if (ImGui.BeginTabItem("Advanced"))
{
NewProject_NameGUI();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1273,4 +1273,4 @@ public static float GetUIScale()
return CFG.Current.UIScale;
}
}
}
}
31 changes: 31 additions & 0 deletions StudioCore/MsbEditor/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,14 +1056,35 @@ 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<string, ModelInfoExport> LoadedModels { get; set; } = null;
public Vector3 MapTransform { get; set; }
}

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<MapSerializationEntity> Children { get; set; } = null;


public bool ShouldSerializeChildren()
{
return (Children != null && Children.Count > 0);
Expand Down Expand Up @@ -1399,8 +1420,18 @@ public MapSerializationEntity Serialize(Dictionary<Entity, int> 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<MapSerializationEntity>();
if (idmap.ContainsKey(this))
{
Expand Down
59 changes: 57 additions & 2 deletions StudioCore/MsbEditor/ObjectContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
using SoulsFormats.KF4;
using static SoulsFormats.MCP;
using System.ComponentModel;
using StudioCore.Resource;
using Google.Protobuf.WellKnownTypes;
using StudioCore.Platform;

namespace StudioCore.MsbEditor
Expand Down Expand Up @@ -134,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);
}
Expand Down Expand Up @@ -928,14 +934,63 @@ public bool SerializeDS2ObjInstances(Param objs)
return true;
}

public MapSerializationEntity SerializeHierarchy()
public MapInfo SerializeHierarchy()
{
MapInfo mapinfo = new MapInfo();
Dictionary<Entity, int> idmap = new Dictionary<Entity, int>();
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<string, ModelInfoExport>();
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.MapTransform = SpecialMapConnections.GetEldenMapGlobalTransform(Name);

mapinfo.SerializationEntity = ((MapEntity)RootObject).Serialize(idmap);
return mapinfo;
}
}
}
27 changes: 20 additions & 7 deletions StudioCore/MsbEditor/SceneTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
Expand All @@ -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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -796,6 +796,19 @@ public void OnGui()
GC.WaitForPendingFinalizers();
GC.Collect();
}
if (ImGui.Selectable("Export Map"))
{
try
{
_universe.ExportMap(m);
}
catch (SavingFailedException e)
{
PlatformUtils.Instance.MessageBox(e.Wrapped.Message, e.Message,
MessageBoxButtons.OK,
MessageBoxIcon.None);
}
}
}
if (_universe.GetLoadedMapCount() > 1)
{
Expand Down Expand Up @@ -947,4 +960,4 @@ public void OnActionEvent(ActionEvent evt)
}
}
}
}
}
18 changes: 15 additions & 3 deletions StudioCore/MsbEditor/SpecialMapConnections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ namespace StudioCore.MsbEditor
/// </summary>
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<string, ObjectContainer> loadedMaps)
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
Loading