mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Merge branch 'refs/heads/Exter-N/restree-stuff'
This commit is contained in:
commit
96764b34ca
4 changed files with 108 additions and 85 deletions
|
|
@ -17,7 +17,6 @@ public partial class ModEditWindow
|
||||||
private readonly FileDialogService _fileDialog;
|
private readonly FileDialogService _fileDialog;
|
||||||
private readonly ResourceTreeFactory _resourceTreeFactory;
|
private readonly ResourceTreeFactory _resourceTreeFactory;
|
||||||
private readonly ResourceTreeViewer _quickImportViewer;
|
private readonly ResourceTreeViewer _quickImportViewer;
|
||||||
private readonly Dictionary<FullPath, IWritable?> _quickImportWritables = new();
|
|
||||||
private readonly Dictionary<(Utf8GamePath, IWritable?), QuickImportAction> _quickImportActions = new();
|
private readonly Dictionary<(Utf8GamePath, IWritable?), QuickImportAction> _quickImportActions = new();
|
||||||
|
|
||||||
private HashSet<string> GetPlayerResourcesOfType(ResourceType type)
|
private HashSet<string> GetPlayerResourcesOfType(ResourceType type)
|
||||||
|
|
@ -56,52 +55,11 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private void OnQuickImportRefresh()
|
private void OnQuickImportRefresh()
|
||||||
{
|
{
|
||||||
_quickImportWritables.Clear();
|
|
||||||
_quickImportActions.Clear();
|
_quickImportActions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawQuickImportActions(ResourceNode resourceNode, Vector2 buttonSize)
|
private void DrawQuickImportActions(ResourceNode resourceNode, IWritable? writable, Vector2 buttonSize)
|
||||||
{
|
{
|
||||||
if (!_quickImportWritables!.TryGetValue(resourceNode.FullPath, out var writable))
|
|
||||||
{
|
|
||||||
var path = resourceNode.FullPath.ToPath();
|
|
||||||
if (resourceNode.FullPath.IsRooted)
|
|
||||||
{
|
|
||||||
writable = new RawFileWritable(path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var file = _gameData.GetFile(path);
|
|
||||||
writable = file is null ? null : new RawGameFileWritable(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
_quickImportWritables.Add(resourceNode.FullPath, writable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Export this file."u8, buttonSize,
|
|
||||||
resourceNode.FullPath.FullName.Length is 0 || writable is null))
|
|
||||||
{
|
|
||||||
var fullPathStr = resourceNode.FullPath.FullName;
|
|
||||||
var ext = resourceNode.PossibleGamePaths.Length == 1
|
|
||||||
? Path.GetExtension(resourceNode.GamePath.ToString())
|
|
||||||
: Path.GetExtension(fullPathStr);
|
|
||||||
_fileDialog.OpenSavePicker($"Export {Path.GetFileName(fullPathStr)} to...", ext, Path.GetFileNameWithoutExtension(fullPathStr), ext,
|
|
||||||
(success, name) =>
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_editor.Compactor.WriteAllBytes(name, writable!.Write());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Penumbra.Log.Error($"Could not export {fullPathStr}:\n{e}");
|
|
||||||
}
|
|
||||||
}, null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (!_quickImportActions!.TryGetValue((resourceNode.GamePath, writable), out var quickImport))
|
if (!_quickImportActions!.TryGetValue((resourceNode.GamePath, writable), out var quickImport))
|
||||||
{
|
{
|
||||||
|
|
@ -121,24 +79,6 @@ public partial class ModEditWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record RawFileWritable(string Path) : IWritable
|
|
||||||
{
|
|
||||||
public bool Valid
|
|
||||||
=> true;
|
|
||||||
|
|
||||||
public byte[] Write()
|
|
||||||
=> File.ReadAllBytes(Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private record RawGameFileWritable(FileResource FileResource) : IWritable
|
|
||||||
{
|
|
||||||
public bool Valid
|
|
||||||
=> true;
|
|
||||||
|
|
||||||
public byte[] Write()
|
|
||||||
=> FileResource.Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class QuickImportAction
|
public class QuickImportAction
|
||||||
{
|
{
|
||||||
public const string FallbackOptionName = "the current option";
|
public const string FallbackOptionName = "the current option";
|
||||||
|
|
|
||||||
|
|
@ -667,7 +667,7 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
|
||||||
_center = new CombinedTexture(_left, _right);
|
_center = new CombinedTexture(_left, _right);
|
||||||
_textureSelectCombo = new TextureDrawer.PathSelectCombo(textures, editor, () => GetPlayerResourcesOfType(ResourceType.Tex));
|
_textureSelectCombo = new TextureDrawer.PathSelectCombo(textures, editor, () => GetPlayerResourcesOfType(ResourceType.Tex));
|
||||||
_resourceTreeFactory = resourceTreeFactory;
|
_resourceTreeFactory = resourceTreeFactory;
|
||||||
_quickImportViewer = resourceTreeViewerFactory.Create(2, OnQuickImportRefresh, DrawQuickImportActions);
|
_quickImportViewer = resourceTreeViewerFactory.Create(1, OnQuickImportRefresh, DrawQuickImportActions);
|
||||||
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModEditWindow);
|
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModEditWindow);
|
||||||
IsOpen = _config is { OpenWindowAtStart: true, Ephemeral.AdvancedEditingOpen: true };
|
IsOpen = _config is { OpenWindowAtStart: true, Ephemeral.AdvancedEditingOpen: true };
|
||||||
if (IsOpen && selection.Mod != null)
|
if (IsOpen && selection.Mod != null)
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,20 @@ using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using Lumina.Data;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
using OtterGui.Compression;
|
||||||
using OtterGui.Extensions;
|
using OtterGui.Extensions;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui.Text;
|
using OtterGui.Text;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
|
using Penumbra.GameData.Files;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.ResourceTree;
|
using Penumbra.Interop.ResourceTree;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
|
using Penumbra.String.Classes;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow;
|
namespace Penumbra.UI.AdvancedWindow;
|
||||||
|
|
@ -25,17 +29,20 @@ public class ResourceTreeViewer(
|
||||||
IncognitoService incognito,
|
IncognitoService incognito,
|
||||||
int actionCapacity,
|
int actionCapacity,
|
||||||
Action onRefresh,
|
Action onRefresh,
|
||||||
Action<ResourceNode, Vector2> drawActions,
|
Action<ResourceNode, IWritable?, Vector2> drawActions,
|
||||||
CommunicatorService communicator,
|
CommunicatorService communicator,
|
||||||
PcpService pcpService,
|
PcpService pcpService,
|
||||||
IDataManager gameData)
|
IDataManager gameData,
|
||||||
|
FileDialogService fileDialog,
|
||||||
|
FileCompactor compactor)
|
||||||
{
|
{
|
||||||
private const ResourceTreeFactory.Flags ResourceTreeFactoryFlags =
|
private const ResourceTreeFactory.Flags ResourceTreeFactoryFlags =
|
||||||
ResourceTreeFactory.Flags.RedactExternalPaths | ResourceTreeFactory.Flags.WithUiData | ResourceTreeFactory.Flags.WithOwnership;
|
ResourceTreeFactory.Flags.WithUiData | ResourceTreeFactory.Flags.WithOwnership;
|
||||||
|
|
||||||
private readonly HashSet<nint> _unfolded = [];
|
private readonly HashSet<nint> _unfolded = [];
|
||||||
|
|
||||||
private readonly Dictionary<nint, NodeVisibility> _filterCache = [];
|
private readonly Dictionary<nint, NodeVisibility> _filterCache = [];
|
||||||
|
private readonly Dictionary<FullPath, IWritable?> _writableCache = [];
|
||||||
|
|
||||||
private TreeCategory _categoryFilter = AllCategories;
|
private TreeCategory _categoryFilter = AllCategories;
|
||||||
private ChangedItemIconFlag _typeFilter = ChangedItemFlagExtensions.AllFlags;
|
private ChangedItemIconFlag _typeFilter = ChangedItemFlagExtensions.AllFlags;
|
||||||
|
|
@ -115,7 +122,7 @@ public class ResourceTreeViewer(
|
||||||
ImUtf8.InputText("##note"u8, ref _note, "Export note..."u8);
|
ImUtf8.InputText("##note"u8, ref _note, "Export note..."u8);
|
||||||
|
|
||||||
|
|
||||||
using var table = ImRaii.Table("##ResourceTree", actionCapacity > 0 ? 4 : 3,
|
using var table = ImRaii.Table("##ResourceTree", 4,
|
||||||
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
|
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg);
|
||||||
if (!table)
|
if (!table)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -123,9 +130,8 @@ public class ResourceTreeViewer(
|
||||||
ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthStretch, 0.2f);
|
ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthStretch, 0.2f);
|
||||||
ImGui.TableSetupColumn("Game Path", ImGuiTableColumnFlags.WidthStretch, 0.3f);
|
ImGui.TableSetupColumn("Game Path", ImGuiTableColumnFlags.WidthStretch, 0.3f);
|
||||||
ImGui.TableSetupColumn("Actual Path", ImGuiTableColumnFlags.WidthStretch, 0.5f);
|
ImGui.TableSetupColumn("Actual Path", ImGuiTableColumnFlags.WidthStretch, 0.5f);
|
||||||
if (actionCapacity > 0)
|
ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed,
|
||||||
ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed,
|
actionCapacity * 3 * ImGuiHelpers.GlobalScale + (actionCapacity + 1) * ImGui.GetFrameHeight());
|
||||||
(actionCapacity - 1) * 3 * ImGuiHelpers.GlobalScale + actionCapacity * ImGui.GetFrameHeight());
|
|
||||||
ImGui.TableHeadersRow();
|
ImGui.TableHeadersRow();
|
||||||
|
|
||||||
DrawNodes(tree.Nodes, 0, unchecked(tree.DrawObjectAddress * 31), 0);
|
DrawNodes(tree.Nodes, 0, unchecked(tree.DrawObjectAddress * 31), 0);
|
||||||
|
|
@ -211,6 +217,7 @@ public class ResourceTreeViewer(
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
_filterCache.Clear();
|
_filterCache.Clear();
|
||||||
|
_writableCache.Clear();
|
||||||
_unfolded.Clear();
|
_unfolded.Clear();
|
||||||
onRefresh();
|
onRefresh();
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +228,6 @@ public class ResourceTreeViewer(
|
||||||
{
|
{
|
||||||
var debugMode = config.DebugMode;
|
var debugMode = config.DebugMode;
|
||||||
var frameHeight = ImGui.GetFrameHeight();
|
var frameHeight = ImGui.GetFrameHeight();
|
||||||
var cellHeight = actionCapacity > 0 ? frameHeight : 0.0f;
|
|
||||||
|
|
||||||
foreach (var (resourceNode, index) in resourceNodes.WithIndex())
|
foreach (var (resourceNode, index) in resourceNodes.WithIndex())
|
||||||
{
|
{
|
||||||
|
|
@ -291,7 +297,7 @@ public class ResourceTreeViewer(
|
||||||
0 => "(none)",
|
0 => "(none)",
|
||||||
1 => resourceNode.GamePath.ToString(),
|
1 => resourceNode.GamePath.ToString(),
|
||||||
_ => "(multiple)",
|
_ => "(multiple)",
|
||||||
}, false, hasGamePaths ? 0 : ImGuiSelectableFlags.Disabled, new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
}, false, hasGamePaths ? 0 : ImGuiSelectableFlags.Disabled, new Vector2(ImGui.GetContentRegionAvail().X, frameHeight));
|
||||||
if (hasGamePaths)
|
if (hasGamePaths)
|
||||||
{
|
{
|
||||||
var allPaths = string.Join('\n', resourceNode.PossibleGamePaths);
|
var allPaths = string.Join('\n', resourceNode.PossibleGamePaths);
|
||||||
|
|
@ -312,17 +318,29 @@ public class ResourceTreeViewer(
|
||||||
using (var color = ImRaii.PushColor(ImGuiCol.Text, (hasMod ? ColorId.NewMod : ColorId.DisabledMod).Value()))
|
using (var color = ImRaii.PushColor(ImGuiCol.Text, (hasMod ? ColorId.NewMod : ColorId.DisabledMod).Value()))
|
||||||
{
|
{
|
||||||
ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap,
|
ImUtf8.Selectable(modName, false, ImGuiSelectableFlags.AllowItemOverlap,
|
||||||
new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
new Vector2(ImGui.GetContentRegionAvail().X, frameHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.SetCursorPosX(textPos);
|
ImGui.SetCursorPosX(textPos);
|
||||||
ImUtf8.Text(resourceNode.ModRelativePath);
|
ImUtf8.Text(resourceNode.ModRelativePath);
|
||||||
}
|
}
|
||||||
|
else if (resourceNode.FullPath.IsRooted)
|
||||||
|
{
|
||||||
|
var path = resourceNode.FullPath.FullName;
|
||||||
|
var lastDirectorySeparator = path.LastIndexOf('\\');
|
||||||
|
var secondLastDirectorySeparator = lastDirectorySeparator > 0
|
||||||
|
? path.LastIndexOf('\\', lastDirectorySeparator - 1)
|
||||||
|
: -1;
|
||||||
|
if (secondLastDirectorySeparator >= 0)
|
||||||
|
path = $"…{path.AsSpan(secondLastDirectorySeparator)}";
|
||||||
|
ImGui.Selectable(path.AsSpan(), false, ImGuiSelectableFlags.AllowItemOverlap,
|
||||||
|
new Vector2(ImGui.GetContentRegionAvail().X, frameHeight));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImGui.Selectable(resourceNode.FullPath.ToPath(), false, ImGuiSelectableFlags.AllowItemOverlap,
|
ImGui.Selectable(resourceNode.FullPath.ToPath(), false, ImGuiSelectableFlags.AllowItemOverlap,
|
||||||
new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
new Vector2(ImGui.GetContentRegionAvail().X, frameHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.IsItemClicked())
|
if (ImGui.IsItemClicked())
|
||||||
|
|
@ -336,20 +354,17 @@ public class ResourceTreeViewer(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ImUtf8.Selectable(GetPathStatusLabel(resourceNode.FullPathStatus), false, ImGuiSelectableFlags.Disabled,
|
ImUtf8.Selectable(GetPathStatusLabel(resourceNode.FullPathStatus), false, ImGuiSelectableFlags.Disabled,
|
||||||
new Vector2(ImGui.GetContentRegionAvail().X, cellHeight));
|
new Vector2(ImGui.GetContentRegionAvail().X, frameHeight));
|
||||||
ImGuiUtil.HoverTooltip(
|
ImGuiUtil.HoverTooltip(
|
||||||
$"{GetPathStatusDescription(resourceNode.FullPathStatus)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}");
|
$"{GetPathStatusDescription(resourceNode.FullPathStatus)}{GetAdditionalDataSuffix(resourceNode.AdditionalData)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
mutedColor.Dispose();
|
mutedColor.Dispose();
|
||||||
|
|
||||||
if (actionCapacity > 0)
|
ImGui.TableNextColumn();
|
||||||
{
|
using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing,
|
||||||
ImGui.TableNextColumn();
|
ImGui.GetStyle().ItemSpacing with { X = 3 * ImGuiHelpers.GlobalScale });
|
||||||
using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing,
|
DrawActions(resourceNode, new Vector2(frameHeight));
|
||||||
ImGui.GetStyle().ItemSpacing with { X = 3 * ImGuiHelpers.GlobalScale });
|
|
||||||
drawActions(resourceNode, new Vector2(frameHeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unfolded)
|
if (unfolded)
|
||||||
DrawNodes(resourceNode.Children, level + 1, unchecked(nodePathHash * 31), filterIcon);
|
DrawNodes(resourceNode.Children, level + 1, unchecked(nodePathHash * 31), filterIcon);
|
||||||
|
|
@ -402,6 +417,51 @@ public class ResourceTreeViewer(
|
||||||
|| node.FullPath.InternalName.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase)
|
|| node.FullPath.InternalName.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase)
|
||||||
|| Array.Exists(node.PossibleGamePaths, path => path.Path.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase));
|
|| Array.Exists(node.PossibleGamePaths, path => path.Path.ToString().Contains(_nodeFilter, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawActions(ResourceNode resourceNode, Vector2 buttonSize)
|
||||||
|
{
|
||||||
|
if (!_writableCache!.TryGetValue(resourceNode.FullPath, out var writable))
|
||||||
|
{
|
||||||
|
var path = resourceNode.FullPath.ToPath();
|
||||||
|
if (resourceNode.FullPath.IsRooted)
|
||||||
|
{
|
||||||
|
writable = new RawFileWritable(path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var file = gameData.GetFile(path);
|
||||||
|
writable = file is null ? null : new RawGameFileWritable(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
_writableCache.Add(resourceNode.FullPath, writable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImUtf8.IconButton(FontAwesomeIcon.Save, "Export this file."u8, buttonSize,
|
||||||
|
resourceNode.FullPath.FullName.Length is 0 || writable is null))
|
||||||
|
{
|
||||||
|
var fullPathStr = resourceNode.FullPath.FullName;
|
||||||
|
var ext = resourceNode.PossibleGamePaths.Length == 1
|
||||||
|
? Path.GetExtension(resourceNode.GamePath.ToString())
|
||||||
|
: Path.GetExtension(fullPathStr);
|
||||||
|
fileDialog.OpenSavePicker($"Export {Path.GetFileName(fullPathStr)} to...", ext, Path.GetFileNameWithoutExtension(fullPathStr), ext,
|
||||||
|
(success, name) =>
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
compactor.WriteAllBytes(name, writable!.Write());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Penumbra.Log.Error($"Could not export {fullPathStr}:\n{e}");
|
||||||
|
}
|
||||||
|
}, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawActions(resourceNode, writable, new Vector2(frameHeight));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetPathStatusLabel(ResourceNode.PathStatus status)
|
private static ReadOnlySpan<byte> GetPathStatusLabel(ResourceNode.PathStatus status)
|
||||||
|
|
@ -465,4 +525,22 @@ public class ResourceTreeViewer(
|
||||||
Visible = 1,
|
Visible = 1,
|
||||||
DescendentsOnly = 2,
|
DescendentsOnly = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record RawFileWritable(string Path) : IWritable
|
||||||
|
{
|
||||||
|
public bool Valid
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public byte[] Write()
|
||||||
|
=> File.ReadAllBytes(Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private record RawGameFileWritable(FileResource FileResource) : IWritable
|
||||||
|
{
|
||||||
|
public bool Valid
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public byte[] Write()
|
||||||
|
=> FileResource.Data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using OtterGui.Compression;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
|
using Penumbra.GameData.Files;
|
||||||
using Penumbra.Interop.ResourceTree;
|
using Penumbra.Interop.ResourceTree;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
|
|
||||||
|
|
@ -12,8 +14,11 @@ public class ResourceTreeViewerFactory(
|
||||||
IncognitoService incognito,
|
IncognitoService incognito,
|
||||||
CommunicatorService communicator,
|
CommunicatorService communicator,
|
||||||
PcpService pcpService,
|
PcpService pcpService,
|
||||||
IDataManager gameData) : IService
|
IDataManager gameData,
|
||||||
|
FileDialogService fileDialog,
|
||||||
|
FileCompactor compactor) : IService
|
||||||
{
|
{
|
||||||
public ResourceTreeViewer Create(int actionCapacity, Action onRefresh, Action<ResourceNode, Vector2> drawActions)
|
public ResourceTreeViewer Create(int actionCapacity, Action onRefresh, Action<ResourceNode, IWritable?, Vector2> drawActions)
|
||||||
=> new(config, treeFactory, changedItemDrawer, incognito, actionCapacity, onRefresh, drawActions, communicator, pcpService, gameData);
|
=> new(config, treeFactory, changedItemDrawer, incognito, actionCapacity, onRefresh, drawActions, communicator, pcpService, gameData,
|
||||||
|
fileDialog, compactor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue