mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Asset browser: Copy, cut, paste
This commit is contained in:
@@ -11,6 +11,7 @@ using GlitchyEngine;
|
||||
using GlitchyEditor.Assets;
|
||||
using System.Diagnostics;
|
||||
using GlitchyEditor.CodeEditors;
|
||||
using GlitchyEditor.Multithreading;
|
||||
|
||||
namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
@@ -196,6 +197,9 @@ namespace GlitchyEditor.EditWindows
|
||||
};
|
||||
|
||||
private append List<String> _selectedFiles = .() ~ ClearAndDeleteItems!(_);
|
||||
|
||||
private append List<String> _filesToCopy = .() ~ ClearAndDeleteItems!(_);
|
||||
private bool _cutFiles = false;
|
||||
|
||||
private append String _assetToRename = .();
|
||||
private char8[128] _renameFileNameBuffer;
|
||||
@@ -591,6 +595,13 @@ namespace GlitchyEditor.EditWindows
|
||||
}
|
||||
|
||||
ImGui.AttachTooltip("Opens the C# Solution of this project.");
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (!_filesToCopy.IsEmpty && ImGui.MenuItem("Paste", "Ctrl+V"))
|
||||
{
|
||||
PasteFiles(CurrentDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows the menu for the given asset creator tree.
|
||||
@@ -767,6 +778,24 @@ namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
NavigateForward();
|
||||
}
|
||||
|
||||
if (Input.IsKeyPressed(.Control))
|
||||
{
|
||||
if (Input.IsKeyPressing(.C))
|
||||
{
|
||||
CopySelectedFiles(cutFiles: false);
|
||||
}
|
||||
|
||||
if (Input.IsKeyPressing(.X))
|
||||
{
|
||||
CopySelectedFiles(cutFiles: true);
|
||||
}
|
||||
|
||||
if (Input.IsKeyPressing(.V))
|
||||
{
|
||||
PasteFiles(CurrentDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<TreeNode<AssetNode>> directoryEntries = scope List<TreeNode<AssetNode>>();
|
||||
@@ -943,7 +972,14 @@ namespace GlitchyEditor.EditWindows
|
||||
// TODO: Special Icon for back-folder?
|
||||
SubTexture2D image = _thumbnailManager.GetThumbnail(entry.Value);
|
||||
|
||||
ImGui.ImageButton("FileImage", image, (.)IconSize);
|
||||
ColorRGBA imageColor = ColorRGBA.White;
|
||||
|
||||
if (_filesToCopy.Contains(entry->Path) && _cutFiles)
|
||||
{
|
||||
imageColor = ColorRGBA(1, 1, 1, 0.5f);
|
||||
}
|
||||
|
||||
ImGui.ImageButton("FileImage", image, (.)IconSize, tint_col: (.)(float4)imageColor);
|
||||
|
||||
if (ImGui.IsRectangleSelecting(ref _rectangleSelection))
|
||||
{
|
||||
@@ -1274,6 +1310,23 @@ namespace GlitchyEditor.EditWindows
|
||||
ImGui.EndMenu();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (ImGui.MenuItem("Cut", "Ctrl+X"))
|
||||
{
|
||||
CopySelectedFiles(cutFiles: true);
|
||||
}
|
||||
|
||||
if (ImGui.MenuItem("Copy", "Ctrl+C"))
|
||||
{
|
||||
CopySelectedFiles(cutFiles: false);
|
||||
}
|
||||
|
||||
if (!_filesToCopy.IsEmpty && singleEntry && parent != null && ImGui.MenuItem("Paste", "Ctrl+V"))
|
||||
{
|
||||
PasteFiles(parent->Path);
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (ImGui.MenuItem("Rename"))
|
||||
@@ -1297,6 +1350,31 @@ namespace GlitchyEditor.EditWindows
|
||||
}
|
||||
}
|
||||
|
||||
private void CopySelectedFiles(bool cutFiles)
|
||||
{
|
||||
_filesToCopy.ClearAndDeleteItems();
|
||||
_selectedFiles.Select((file) => new String(file)).ToList(_filesToCopy);
|
||||
_cutFiles = cutFiles;
|
||||
}
|
||||
|
||||
private void PasteFiles(StringView targetDirectoryPath)
|
||||
{
|
||||
BackgroundTask backgroundTask;
|
||||
if (_cutFiles)
|
||||
{
|
||||
backgroundTask = new MoveFilesBackgroundTask(_filesToCopy, targetDirectoryPath);
|
||||
_filesToCopy.ClearAndDeleteItems();
|
||||
_cutFiles = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundTask = new CopyBackgroundTask(_filesToCopy, targetDirectoryPath);
|
||||
}
|
||||
backgroundTask.DeleteWhenEnded = true;
|
||||
|
||||
EditorApp.Instance.BackgroundTaskManager.StartBackgroundTask(backgroundTask);
|
||||
}
|
||||
|
||||
private void OpenPropertiesWindow(TreeNode<AssetNode> fileOrFolder)
|
||||
{
|
||||
AssetHandle? assetHandle = fileOrFolder->AssetFile?.AssetConfig?.AssetHandle;
|
||||
|
||||
@@ -136,7 +136,7 @@ class CopyBackgroundTask : BackgroundTask
|
||||
|
||||
if (Directory.Exists(targetPath) || _targetPaths.Contains(targetPath))
|
||||
{
|
||||
if (CurrentFileMode.HasFlag(.KeepBoth))
|
||||
if (CurrentFileMode.HasFlag(.KeepBoth) || targetPath == sourcePath)
|
||||
{
|
||||
Path.FindFreePath(_targetDirectoryPath, fileName, "", targetPath, fileName, _targetPaths);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ class CopyBackgroundTask : BackgroundTask
|
||||
|
||||
if (File.Exists(targetPath) || _targetPaths.Contains(targetPath))
|
||||
{
|
||||
if (CurrentFileMode.HasFlag(.KeepBoth))
|
||||
if (CurrentFileMode.HasFlag(.KeepBoth) || targetPath == sourcePath)
|
||||
{
|
||||
let fileExtension = scope String();
|
||||
Path.GetExtension(targetPath, fileExtension);
|
||||
|
||||
@@ -0,0 +1,517 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using ImGui;
|
||||
using System.Threading;
|
||||
|
||||
namespace GlitchyEditor.Multithreading;
|
||||
|
||||
class MoveFilesBackgroundTask : BackgroundTask
|
||||
{
|
||||
private List<String> _sourcePath ~ {ClearAndDeleteItems!(_); delete:append _;};
|
||||
private String _targetDirectoryPath ~ delete:append _;
|
||||
|
||||
private int _totalEntriesToMove;
|
||||
private append Queue<CopyInfo> _pathsToMove = .() ~ ClearAndDeleteItems!(_);
|
||||
private append Queue<CopyInfo> _scanQueue = .() ~ ClearAndDeleteItems!(_);
|
||||
/// Contains the file paths, that will definitely exist after copying. This is used for file renaming during scanning.
|
||||
private append HashSet<StringView> _targetPaths = .();
|
||||
|
||||
private enum ConflictResolutionMode
|
||||
{
|
||||
None,
|
||||
OverwriteFile = 1,
|
||||
KeepBoth = 2,
|
||||
CombineDirectories = 4,
|
||||
SkipFiles = 8,
|
||||
SkipDirectories = 16,
|
||||
SkipNotFound = 32,
|
||||
IgnoreUnexpectedErrors = 64
|
||||
}
|
||||
|
||||
private ConflictResolutionMode _nextFileMode;
|
||||
private ConflictResolutionMode _allFilesMode;
|
||||
|
||||
private ConflictResolutionMode CurrentFileMode => _nextFileMode | _allFilesMode;
|
||||
|
||||
private class CopyInfo
|
||||
{
|
||||
public append String SourcePath = .();
|
||||
// If this entry is actually inside a directory we copy, this contains the path of this entry inside this directory.
|
||||
public append String SubPath = .();
|
||||
public append String TargetPath = .();
|
||||
public ConflictResolutionMode ConflictResolutionMode;
|
||||
|
||||
[AllowAppend]
|
||||
public this(StringView sourcePath, StringView targetPath, ConflictResolutionMode conflictResolutionMode)
|
||||
{
|
||||
SourcePath.Set(sourcePath);
|
||||
TargetPath.Set(targetPath);
|
||||
ConflictResolutionMode = conflictResolutionMode;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ScanningFiles => !_scanQueue.IsEmpty;
|
||||
|
||||
[AllowAppend]
|
||||
public this(List<String> sourcePaths, StringView targetDirectoryPath)
|
||||
{
|
||||
List<String> sourcePathList = append List<String>(sourcePaths.Count);
|
||||
String targetDirectoryPathStr = append String(targetDirectoryPath);
|
||||
|
||||
_sourcePath = sourcePathList;
|
||||
_targetDirectoryPath = targetDirectoryPathStr;
|
||||
|
||||
for (String path in sourcePaths)
|
||||
{
|
||||
_sourcePath.Add(new String(path));
|
||||
_scanQueue.Add(new CopyInfo(path, "", .None));
|
||||
}
|
||||
|
||||
_totalEntriesToMove = sourcePaths.Count;
|
||||
}
|
||||
|
||||
public enum CopyError : IDisposable
|
||||
{
|
||||
case None;
|
||||
case TargetDirectoryIsNotDirectory;
|
||||
case TargetFileExists(String FileName);
|
||||
case TargetDirectoryExists(String DirectoryName);
|
||||
case EntryNotFound(String SourcePath);
|
||||
case UnexpectedError(String Message);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (this)
|
||||
{
|
||||
case .None:
|
||||
case .TargetDirectoryIsNotDirectory:
|
||||
case .TargetFileExists(let FileName):
|
||||
delete FileName;
|
||||
case .TargetDirectoryExists(let DirectoryName):
|
||||
delete DirectoryName;
|
||||
case .EntryNotFound(let SourcePath):
|
||||
delete SourcePath;
|
||||
case .UnexpectedError(let Message):
|
||||
delete Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Result<void, CopyError> CollectFilesToMove()
|
||||
{
|
||||
CopyInfo currentEntry = null;
|
||||
defer
|
||||
{
|
||||
if (currentEntry != null && @return case .Err)
|
||||
{
|
||||
_scanQueue.AddFront(currentEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void AddToMoveQueue(CopyInfo entry, StringView targetPath, ConflictResolutionMode conflictResolutionMode)
|
||||
{
|
||||
entry.TargetPath.Set(targetPath);
|
||||
entry.ConflictResolutionMode = conflictResolutionMode;
|
||||
_pathsToMove.Add(entry);
|
||||
_targetPaths.Add(entry.TargetPath);
|
||||
}
|
||||
|
||||
while (!_scanQueue.IsEmpty && Running)
|
||||
{
|
||||
currentEntry = _scanQueue.PopFront();
|
||||
|
||||
let sourcePath = (StringView)currentEntry.SourcePath;
|
||||
|
||||
let fileName = scope String();
|
||||
Path.GetFileName(sourcePath, fileName);
|
||||
|
||||
let targetPath = scope String();
|
||||
Path.Combine(targetPath, _targetDirectoryPath, currentEntry.SubPath, fileName);
|
||||
|
||||
if (Directory.Exists(sourcePath))
|
||||
{
|
||||
bool skip = false;
|
||||
|
||||
if (Directory.Exists(targetPath) || _targetPaths.Contains(targetPath))
|
||||
{
|
||||
if (CurrentFileMode.HasFlag(.KeepBoth))
|
||||
{
|
||||
Path.FindFreePath(_targetDirectoryPath, fileName, "", targetPath, fileName, _targetPaths);
|
||||
}
|
||||
else if (CurrentFileMode.HasFlag(.SkipDirectories))
|
||||
{
|
||||
skip = true;
|
||||
}
|
||||
else if (Enum.HasAnyFlag(CurrentFileMode, .CombineDirectories))
|
||||
{
|
||||
// Intentionally do nothing.
|
||||
}
|
||||
else
|
||||
{
|
||||
return .Err(.TargetDirectoryExists(new String(fileName)));
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
{
|
||||
delete currentEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current node is ready, add it to move-queue.
|
||||
AddToMoveQueue(currentEntry, targetPath, CurrentFileMode);
|
||||
|
||||
if (Enum.HasAnyFlag(CurrentFileMode, .CombineDirectories))
|
||||
{
|
||||
// Add nested files and directories to the scan-queue.
|
||||
for (FileFindEntry e in Directory.Enumerate(currentEntry.SourcePath))
|
||||
{
|
||||
let entryPath = scope String();
|
||||
e.GetFilePath(entryPath);
|
||||
|
||||
let newEntry = new CopyInfo(entryPath, targetPath, .None);
|
||||
_scanQueue.Add(newEntry);
|
||||
|
||||
Path.Combine(newEntry.SubPath, currentEntry.SubPath, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_nextFileMode = .None;
|
||||
}
|
||||
else if (File.Exists(sourcePath))
|
||||
{
|
||||
bool skip = false;
|
||||
|
||||
if (File.Exists(targetPath) || _targetPaths.Contains(targetPath))
|
||||
{
|
||||
if (CurrentFileMode.HasFlag(.KeepBoth))
|
||||
{
|
||||
let fileExtension = scope String();
|
||||
Path.GetExtension(targetPath, fileExtension);
|
||||
|
||||
StringView fileNameWithoutExtension = fileName.Substring(0..<^fileExtension.Length);
|
||||
|
||||
Path.FindFreePath(_targetDirectoryPath, fileNameWithoutExtension, fileExtension, targetPath, fileName, _targetPaths);
|
||||
}
|
||||
else if (CurrentFileMode.HasFlag(.SkipFiles))
|
||||
{
|
||||
skip = true;
|
||||
}
|
||||
else if (Enum.HasAnyFlag(CurrentFileMode, .OverwriteFile))
|
||||
{
|
||||
// Intentionally do nothing.
|
||||
}
|
||||
else
|
||||
{
|
||||
return .Err(.TargetFileExists(new String(fileName)));
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
{
|
||||
delete currentEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToMoveQueue(currentEntry, targetPath, CurrentFileMode);
|
||||
}
|
||||
|
||||
_nextFileMode = .None;
|
||||
}
|
||||
}
|
||||
|
||||
_totalEntriesToMove = _pathsToMove.Count;
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
private CopyError _currentError = .None ~ _.Dispose();
|
||||
|
||||
public override RunResult Run()
|
||||
{
|
||||
_currentError.Dispose();
|
||||
_currentError = .None;
|
||||
if (CollectFilesToMove() case .Err(out _currentError) || Paused)
|
||||
{
|
||||
return .Pause;
|
||||
}
|
||||
|
||||
while (!_pathsToMove.IsEmpty && Running)
|
||||
{
|
||||
CopyInfo currentPath = _pathsToMove.Peek();
|
||||
|
||||
if (MovePath(currentPath) case .Err(out _currentError) || Paused)
|
||||
{
|
||||
return .Pause;
|
||||
}
|
||||
|
||||
_pathsToMove.PopFront();
|
||||
delete currentPath;
|
||||
}
|
||||
|
||||
return .Finished;
|
||||
}
|
||||
|
||||
private Result<void, CopyError> MovePath(CopyInfo copyInfo)
|
||||
{
|
||||
if (Directory.Exists(copyInfo.SourcePath))
|
||||
{
|
||||
if (Directory.Exists(copyInfo.TargetPath))
|
||||
{
|
||||
if (copyInfo.ConflictResolutionMode.HasFlag(.CombineDirectories))
|
||||
{
|
||||
// We don't have to do anything, because we will be using the target directory.
|
||||
return .Ok;
|
||||
}
|
||||
else if (!CurrentFileMode.HasFlag(.IgnoreUnexpectedErrors))
|
||||
{
|
||||
return .Err(.UnexpectedError(new $"The target directory already exists, but it wasn't properly handled during the scanning phase."));
|
||||
}
|
||||
}
|
||||
|
||||
if (Directory.Move(copyInfo.SourcePath, copyInfo.TargetPath) case .Err(let err) &&
|
||||
!CurrentFileMode.HasFlag(.IgnoreUnexpectedErrors))
|
||||
{
|
||||
return .Err(.UnexpectedError(new $"Failed to move Directory {copyInfo.TargetPath}: {err}"));
|
||||
}
|
||||
}
|
||||
else if (File.Exists(copyInfo.SourcePath))
|
||||
{
|
||||
bool forceOverwrite = false;
|
||||
if (File.Exists(copyInfo.TargetPath))
|
||||
{
|
||||
if (copyInfo.ConflictResolutionMode.HasFlag(.OverwriteFile))
|
||||
{
|
||||
forceOverwrite = true;
|
||||
}
|
||||
else if (!CurrentFileMode.HasFlag(.IgnoreUnexpectedErrors))
|
||||
{
|
||||
return .Err(.UnexpectedError(new $"The target file already exists, but it wasn't properly handled during the scanning phase."));
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Move(copyInfo.SourcePath, copyInfo.TargetPath) case .Err(let err) &&
|
||||
!CurrentFileMode.HasFlag(.IgnoreUnexpectedErrors))
|
||||
{
|
||||
return .Err(.UnexpectedError(new $"Failed to move File {copyInfo.TargetPath}: {err}"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (copyInfo.ConflictResolutionMode.HasFlag(.SkipNotFound))
|
||||
return .Ok;
|
||||
else
|
||||
return .Err(.EntryNotFound(new String(copyInfo.SourcePath)));
|
||||
}
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public override void OnRenderPopup()
|
||||
{
|
||||
String title = scope .("Copying files...");
|
||||
|
||||
if (ImGui.Begin(title, null, .NoDocking | .NoCollapse | .Modal | .NoResize | .AlwaysAutoResize))
|
||||
{
|
||||
if (ScanningFiles)
|
||||
{
|
||||
ImGui.ProgressBar(-1.0f * (float)ImGui.GetTime(), .(-1, 0), scope $"Found {_pathsToMove.Count} files...");
|
||||
}
|
||||
else
|
||||
{
|
||||
int copiedFiles = _totalEntriesToMove - _pathsToMove.Count;
|
||||
|
||||
ImGui.ProgressBar(copiedFiles / _totalEntriesToMove, .(-1, 0), scope $"Copied {copiedFiles} / {_totalEntriesToMove} files.");
|
||||
}
|
||||
|
||||
|
||||
switch (_currentError)
|
||||
{
|
||||
case .TargetFileExists(let fileName):
|
||||
ImGui.PushStyleColor(.Text, 0xFF0000FF);
|
||||
ImGui.TextUnformatted(scope $"A file with the name \"{fileName}\" already exists.");
|
||||
ImGui.PopStyleColor();
|
||||
case .TargetDirectoryExists(let directoryName):
|
||||
ImGui.PushStyleColor(.Text, 0xFF0000FF);
|
||||
ImGui.TextUnformatted(scope $"A directory with the name \"{directoryName}\" already exists.");
|
||||
ImGui.PopStyleColor();
|
||||
case .EntryNotFound(let SourcePath):
|
||||
ImGui.PushStyleColor(.Text, 0xFF0000FF);
|
||||
ImGui.TextUnformatted(scope $"\"{SourcePath}\" doesn't exist.");
|
||||
ImGui.PopStyleColor();
|
||||
case .UnexpectedError(let Message):
|
||||
ImGui.PushStyleColor(.Text, 0xFF0000FF);
|
||||
ImGui.TextUnformatted(scope $"Unexpected error: {Message}");
|
||||
ImGui.PopStyleColor();
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
if (ImGui.BeginTable("buttonTable", 2))
|
||||
{
|
||||
switch (_currentError)
|
||||
{
|
||||
case .None:
|
||||
// Do nothing
|
||||
case .TargetDirectoryIsNotDirectory:
|
||||
// This shouldn't be possible
|
||||
Debug.Break();
|
||||
case .TargetFileExists(let fileName):
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.Button("Overwrite the target file."))
|
||||
{
|
||||
_nextFileMode = .OverwriteFile;
|
||||
Continue();
|
||||
}
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.Button("Overwrite all conflicting target files."))
|
||||
{
|
||||
_allFilesMode |= .OverwriteFile;
|
||||
Continue();
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.Button("Rename copied file."))
|
||||
{
|
||||
_nextFileMode = .KeepBoth;
|
||||
Continue();
|
||||
}
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.Button("Rename all conflicting copied files."))
|
||||
{
|
||||
_allFilesMode |= .KeepBoth;
|
||||
Continue();
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.Button("Skip this file."))
|
||||
{
|
||||
_nextFileMode = .SkipFiles;
|
||||
Continue();
|
||||
}
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.Button("Skip all conflicting files."))
|
||||
{
|
||||
_allFilesMode |= .SkipFiles;
|
||||
Continue();
|
||||
}
|
||||
|
||||
case .TargetDirectoryExists(let directoryName):
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.Button("Combine with target."))
|
||||
{
|
||||
_nextFileMode |= .CombineDirectories;
|
||||
Continue();
|
||||
}
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.Button("Combine all conflicting directories."))
|
||||
{
|
||||
_allFilesMode |= .CombineDirectories;
|
||||
Continue();
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.Button("Rename copied directory."))
|
||||
{
|
||||
_nextFileMode |= .KeepBoth;
|
||||
Continue();
|
||||
}
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.Button("Rename all conflicting directories."))
|
||||
{
|
||||
_allFilesMode |= .KeepBoth;
|
||||
Continue();
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.Button("Skip this directory."))
|
||||
{
|
||||
_nextFileMode |= .SkipDirectories;
|
||||
Continue();
|
||||
}
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.Button("Skip all conflicting directories."))
|
||||
{
|
||||
_allFilesMode |= .SkipFiles;
|
||||
Continue();
|
||||
}
|
||||
case .EntryNotFound(let SourcePath):
|
||||
if (ImGui.Button("Skip"))
|
||||
{
|
||||
_nextFileMode |= .SkipNotFound;
|
||||
Continue();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Skip all"))
|
||||
{
|
||||
_allFilesMode |= .SkipNotFound;
|
||||
Continue();
|
||||
}
|
||||
case .UnexpectedError(let Message):
|
||||
if (ImGui.Button("Retry"))
|
||||
{
|
||||
Continue();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Ignore"))
|
||||
{
|
||||
_nextFileMode |= .IgnoreUnexpectedErrors;
|
||||
Continue();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Ignore all unexpected"))
|
||||
{
|
||||
_allFilesMode |= .IgnoreUnexpectedErrors;
|
||||
Continue();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (_currentError case .None)
|
||||
{
|
||||
if (Paused)
|
||||
{
|
||||
if (ImGui.Button("Continue"))
|
||||
{
|
||||
Continue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui.Button("Pause"))
|
||||
{
|
||||
Pause();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
if (ImGui.Button("Cancel"))
|
||||
{
|
||||
Abort();
|
||||
}
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user