diff --git a/GameRes/FileSystem.cs b/GameRes/FileSystem.cs index eb4f26c9..abe22b55 100644 --- a/GameRes/FileSystem.cs +++ b/GameRes/FileSystem.cs @@ -458,7 +458,7 @@ namespace GameRes m_arc_name_stack.Push (path); } - private void Pop () + internal void Pop () { if (m_fs_stack.Count > 1) { @@ -500,10 +500,26 @@ namespace GameRes { private static FileSystemStack m_vfs = new FileSystemStack(); + /// + /// Top, or "current" filesystem in VFS hierarchy. + /// public static IFileSystem Top { get { return m_vfs.Top; } } + + /// + /// Whether top filesystem is virtual (i.e. represents an archive). + /// public static bool IsVirtual { get { return m_vfs.Count > 1; } } + + /// + /// Number of filesystems in hierarchy. ==1 when only physical file system is represented. + /// Always >= 1 + /// public static int Count { get { return m_vfs.Count; } } + /// + /// Archive corresponding to the top filesystem, or null if file system doesn't have underlying + /// archive file. + /// public static ArcFile CurrentArchive { get { return m_vfs.CurrentArchive; } } private static string[] m_top_path = new string[1]; @@ -522,12 +538,31 @@ namespace GameRes { if (!value.Any()) return; - var new_vfs = new FileSystemStack(); var desired = value.ToArray(); - for (int i = 0; i < desired.Length-1; ++i) - new_vfs.ChDir (new_vfs.Top.FindFile (desired[i])); - new_vfs.Top.CurrentDirectory = desired.Last(); - m_vfs.Dispose(); + if (desired.Length == Count) + { + var cur_stack = m_vfs.ArcStack.Reverse(); + if (1 == Count || cur_stack.SequenceEqual (desired.Take (desired.Length-1))) + { + // desired path is identical to current, adjust final component only + m_vfs.Top.CurrentDirectory = desired.Last(); + return; + } + } + // desired path is different, rebuild filesystem hierarchy from scratch + var new_vfs = new FileSystemStack(); + try + { + for (int i = 0; i < desired.Length-1; ++i) + new_vfs.ChDir (new_vfs.Top.FindFile (desired[i])); + new_vfs.Top.CurrentDirectory = desired.Last(); + m_vfs.Dispose(); + } + catch + { + new_vfs.Dispose(); + throw; + } m_vfs = new_vfs; } }