mirror of
https://github.com/Theaninova/BeatLanguageMapper.git
synced 2026-04-21 11:58:53 +00:00
Mk2Rev1
various bugfixes and such. also bookmarks, temp song loaderm and undo overhaul with near complete multiplayer, but menu items disabled. i really wish i could split this into multiple commits, but i don't know how to work unreal.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
#include "ZipFileFunctionLibrary.h"
|
||||
#include "SevenZipCallbackHandler.h"
|
||||
|
||||
void SevenZipCallbackHandler::OnProgress(const TString& archivePath, uint64 bytes)
|
||||
{
|
||||
const UObject* interfaceDelegate = ProgressDelegate;
|
||||
const uint64 bytesConst = bytes;
|
||||
const FString pathConst = FString(archivePath.c_str());
|
||||
|
||||
if (bytes > 0) {
|
||||
const float ProgressPercentage = ((double)((TotalBytes)-(BytesLeft - bytes)) / (double)TotalBytes) * 100;
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([interfaceDelegate, pathConst, ProgressPercentage, bytesConst]
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("Progress: %d bytes"), progress);
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnProgress((UObject*)interfaceDelegate, pathConst, ProgressPercentage, bytesConst);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void SevenZipCallbackHandler::OnDone(const TString& archivePath)
|
||||
{
|
||||
const UObject* interfaceDelegate = ProgressDelegate;
|
||||
const FString pathConst = FString(archivePath.c_str());
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([pathConst, interfaceDelegate]
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("All Done!"));
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnDone((UObject*)interfaceDelegate, pathConst, EZipUtilityCompletionState::SUCCESS);
|
||||
});
|
||||
}
|
||||
|
||||
void SevenZipCallbackHandler::OnFileDone(const TString& archivePath, const TString& filePath, uint64 bytes)
|
||||
{
|
||||
const UObject* interfaceDelegate = ProgressDelegate;
|
||||
const FString pathConst = FString(archivePath.c_str());
|
||||
const FString filePathConst = FString(filePath.c_str());
|
||||
const uint64 bytesConst = bytes;
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([interfaceDelegate, pathConst, filePathConst, bytesConst]
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("File Done: %s, %d bytes"), filePathConst.c_str(), bytesConst);
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnFileDone((UObject*)interfaceDelegate, pathConst, filePathConst);
|
||||
});
|
||||
|
||||
//Handle byte decrementing
|
||||
if (bytes > 0) {
|
||||
BytesLeft -= bytes;
|
||||
const float ProgressPercentage = ((double)(TotalBytes - BytesLeft) / (double)TotalBytes) * 100;
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([interfaceDelegate, pathConst, ProgressPercentage, bytes]
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("Progress: %d bytes"), progress);
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnProgress((UObject*)interfaceDelegate, pathConst, ProgressPercentage, bytes);
|
||||
});
|
||||
}
|
||||
}
|
||||
void SevenZipCallbackHandler::OnStartWithTotal(const TString& archivePath, unsigned __int64 totalBytes)
|
||||
{
|
||||
TotalBytes = totalBytes;
|
||||
BytesLeft = TotalBytes;
|
||||
|
||||
const UObject* interfaceDelegate = ProgressDelegate;
|
||||
const uint64 bytesConst = TotalBytes;
|
||||
const FString pathConst = FString(archivePath.c_str());
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([interfaceDelegate, pathConst, bytesConst]
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("Starting with %d bytes"), bytesConst);
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnStartProcess((UObject*)interfaceDelegate, pathConst, bytesConst);
|
||||
});
|
||||
}
|
||||
void SevenZipCallbackHandler::OnFileFound(const TString& archivePath, const TString& filePath, int size)
|
||||
{
|
||||
const UObject* interfaceDelegate = ProgressDelegate;
|
||||
const uint64 bytesConst = TotalBytes;
|
||||
const FString pathString = FString(archivePath.c_str());
|
||||
const FString fileString = FString(filePath.c_str());
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([interfaceDelegate, pathString, fileString, bytesConst]
|
||||
{
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnFileFound((UObject*)interfaceDelegate, pathString, fileString, bytesConst);
|
||||
});
|
||||
}
|
||||
void SevenZipCallbackHandler::OnListingDone(const TString& archivePath)
|
||||
{
|
||||
const UObject* interfaceDelegate = ProgressDelegate;
|
||||
const FString pathString = FString(archivePath.c_str());
|
||||
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([interfaceDelegate, pathString]
|
||||
{
|
||||
((IZipUtilityInterface*)interfaceDelegate)->Execute_OnDone((UObject*)interfaceDelegate, pathString, EZipUtilityCompletionState::SUCCESS);
|
||||
});
|
||||
}
|
||||
|
||||
bool SevenZipCallbackHandler::OnCheckBreak()
|
||||
{
|
||||
return bCancelOperation;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
#include "WindowsFileUtilityFunctionLibrary.h"
|
||||
#include "ZipFileFunctionLibrary.h"
|
||||
#include "ZULambdaDelegate.h"
|
||||
|
||||
UZULambdaDelegate::UZULambdaDelegate()
|
||||
{
|
||||
OnDoneCallback = nullptr;
|
||||
OnProgressCallback = nullptr;
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::SetOnDoneCallback(TFunction<void()> InOnDoneCallback)
|
||||
{
|
||||
OnDoneCallback = InOnDoneCallback;
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::SetOnProgessCallback(TFunction<void(float)> InOnProgressCallback)
|
||||
{
|
||||
OnProgressCallback = InOnProgressCallback;
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::OnProgress_Implementation(const FString& archive, float percentage, int32 bytes)
|
||||
{
|
||||
if (OnProgressCallback != nullptr)
|
||||
{
|
||||
OnProgressCallback(percentage);
|
||||
}
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::OnDone_Implementation(const FString& archive, EZipUtilityCompletionState CompletionState)
|
||||
{
|
||||
if (OnDoneCallback != nullptr)
|
||||
{
|
||||
OnDoneCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::OnStartProcess_Implementation(const FString& archive, int32 bytes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::OnFileDone_Implementation(const FString& archive, const FString& file)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UZULambdaDelegate::OnFileFound_Implementation(const FString& archive, const FString& file, int32 size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Object.h"
|
||||
#include "ZULambdaDelegate.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class ZIPUTILITY_API UZULambdaDelegate : public UObject, public IZipUtilityInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UZULambdaDelegate();
|
||||
public:
|
||||
void SetOnDoneCallback(TFunction<void()> InOnDoneCallback);
|
||||
void SetOnProgessCallback(TFunction<void(float)> InOnProgressCallback);
|
||||
|
||||
protected:
|
||||
//Zip utility interface
|
||||
virtual void OnProgress_Implementation(const FString& archive, float percentage, int32 bytes) override;
|
||||
virtual void OnDone_Implementation(const FString& archive, EZipUtilityCompletionState CompletionState) override;
|
||||
virtual void OnStartProcess_Implementation(const FString& archive, int32 bytes) override;
|
||||
virtual void OnFileDone_Implementation(const FString& archive, const FString& file) override;
|
||||
virtual void OnFileFound_Implementation(const FString& archive, const FString& file, int32 size) override;
|
||||
|
||||
TFunction<void()> OnDoneCallback;
|
||||
TFunction<void(float)> OnProgressCallback;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
#include "ZipFileFunctionInternalCallback.h"
|
||||
|
||||
UZipFileFunctionInternalCallback::UZipFileFunctionInternalCallback()
|
||||
{
|
||||
CompressionFormat = ZipUtilityCompressionFormat::COMPRESSION_FORMAT_UNKNOWN;
|
||||
DestinationFolder = FString();
|
||||
File = FString();
|
||||
FileIndex = 0;
|
||||
Callback = NULL;
|
||||
}
|
||||
|
||||
void UZipFileFunctionInternalCallback::OnFileFound_Implementation(const FString& archive, const FString& fileIn, int32 size)
|
||||
{
|
||||
if (!bFileFound && fileIn.ToLower().Contains(File.ToLower()))
|
||||
{
|
||||
TArray<int32> FileIndices = { FileIndex };
|
||||
|
||||
if (bUnzipto)
|
||||
{
|
||||
UZipFileFunctionLibrary::UnzipFilesTo(FileIndices, archive, DestinationFolder, Callback, CompressionFormat);
|
||||
}
|
||||
else
|
||||
{
|
||||
UZipFileFunctionLibrary::UnzipFiles(FileIndices, archive, Callback, CompressionFormat);
|
||||
}
|
||||
|
||||
if (bSingleFile)
|
||||
{
|
||||
bFileFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
FileIndex++;
|
||||
}
|
||||
|
||||
void UZipFileFunctionInternalCallback::SetCallback(const FString& FileName, UObject* CallbackIn, TEnumAsByte<ZipUtilityCompressionFormat> CompressionFormatIn /*= ZipUtilityCompressionFormat::COMPRESSION_FORMAT_UNKNOWN*/)
|
||||
{
|
||||
File = FileName;
|
||||
Callback = CallbackIn;
|
||||
CompressionFormat = CompressionFormatIn;
|
||||
FileIndex = 0;
|
||||
}
|
||||
|
||||
void UZipFileFunctionInternalCallback::SetCallback(const FString& FileName, const FString& DestinationFolderIn, UObject* CallbackIn, TEnumAsByte<ZipUtilityCompressionFormat> CompressionFormatIn /*= ZipUtilityCompressionFormat::COMPRESSION_FORMAT_UNKNOWN*/)
|
||||
{
|
||||
SetCallback(FileName, CallbackIn, CompressionFormatIn);
|
||||
|
||||
bUnzipto = true;
|
||||
DestinationFolder = DestinationFolderIn;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include "ZipUtilityInterface.h"
|
||||
#include "ZipFileFunctionInternalCallback.generated.h"
|
||||
|
||||
/**
|
||||
* This is used to provide a callback for unzipping single files, it ends up getting called from the ListFiles lambda.
|
||||
*/
|
||||
UCLASS(ClassGroup = ZipUtility)
|
||||
class ZIPUTILITY_API UZipFileFunctionInternalCallback : public UObject, public IZipUtilityInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
|
||||
/** Compression format used to unzip */
|
||||
UPROPERTY(Transient)
|
||||
TEnumAsByte<ZipUtilityCompressionFormat> CompressionFormat;
|
||||
|
||||
/** Path of the file */
|
||||
UPROPERTY(Transient)
|
||||
FString File;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FString DestinationFolder;
|
||||
|
||||
/** Current File index parsed */
|
||||
UPROPERTY(Transient)
|
||||
int32 FileIndex = 0;
|
||||
|
||||
/** Callback object */
|
||||
UPROPERTY(Transient)
|
||||
UObject* Callback;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
bool bSingleFile;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
bool bFileFound;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
bool bUnzipto;
|
||||
|
||||
public:
|
||||
UZipFileFunctionInternalCallback();
|
||||
|
||||
//IZipUtilityInterface overrides
|
||||
virtual void OnProgress_Implementation(const FString& archive, float percentage, int32 bytes) override {};
|
||||
|
||||
virtual void OnDone_Implementation(const FString& archive, EZipUtilityCompletionState CompletionState) override {};
|
||||
|
||||
virtual void OnStartProcess_Implementation(const FString& archive, int32 bytes) override {};
|
||||
|
||||
virtual void OnFileDone_Implementation(const FString& archive, const FString& file) override {
|
||||
UE_LOG(LogTemp, Log, TEXT("OnFileDone_Implementation"));
|
||||
};
|
||||
|
||||
virtual void OnFileFound_Implementation(const FString& archive, const FString& fileIn, int32 size) override;
|
||||
|
||||
void SetCallback(const FString& FileName, UObject* CallbackIn, TEnumAsByte<ZipUtilityCompressionFormat> CompressionFormatIn = ZipUtilityCompressionFormat::COMPRESSION_FORMAT_UNKNOWN);
|
||||
void SetCallback(const FString& FileName, const FString& DestinationFolder, UObject* CallbackIn, TEnumAsByte<ZipUtilityCompressionFormat> CompressionFormatIn = ZipUtilityCompressionFormat::COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
FORCEINLINE bool GetSingleFile() const { return bSingleFile; }
|
||||
FORCEINLINE void SetSingleFile(bool val) { bSingleFile = val; }
|
||||
};
|
||||
@@ -0,0 +1,481 @@
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
|
||||
#include "ZipFileFunctionLibrary.h"
|
||||
#include "ZipFileFunctionInternalCallback.h"
|
||||
#include "ListCallback.h"
|
||||
#include "ProgressCallback.h"
|
||||
#include "IPluginManager.h"
|
||||
#include "WFULambdaRunnable.h"
|
||||
#include "ZULambdaDelegate.h"
|
||||
#include "SevenZipCallbackHandler.h"
|
||||
#include "WindowsFileUtilityFunctionLibrary.h"
|
||||
|
||||
#include "7zpp.h"
|
||||
|
||||
using namespace SevenZip;
|
||||
|
||||
//Private Namespace
|
||||
namespace{
|
||||
|
||||
//Threaded Lambda convenience wrappers - Task graph is only suitable for short duration lambdas, but doesn't incur thread overhead
|
||||
FGraphEventRef RunLambdaOnAnyThread(TFunction< void()> InFunction)
|
||||
{
|
||||
return FFunctionGraphTask::CreateAndDispatchWhenReady(InFunction, TStatId(), nullptr, ENamedThreads::AnyThread);
|
||||
}
|
||||
|
||||
//Uses proper threading, for any task that may run longer than about 2 seconds.
|
||||
void RunLongLambdaOnAnyThread(TFunction< void()> InFunction)
|
||||
{
|
||||
WFULambdaRunnable::RunLambdaOnBackGroundThread(InFunction);
|
||||
}
|
||||
|
||||
// Run the lambda on the queued threadpool
|
||||
IQueuedWork* RunLambdaOnThreadPool(TFunction< void()> InFunction)
|
||||
{
|
||||
return WFULambdaRunnable::AddLambdaToQueue(InFunction);
|
||||
}
|
||||
|
||||
//Private static vars
|
||||
SevenZipLibrary SZLib;
|
||||
|
||||
//Utility functions
|
||||
FString PluginRootFolder()
|
||||
{
|
||||
return IPluginManager::Get().FindPlugin("ZipUtility")->GetBaseDir();
|
||||
//return FPaths::ConvertRelativePathToFull(FPaths::GameDir());
|
||||
}
|
||||
|
||||
FString DLLPath()
|
||||
{
|
||||
#if _WIN64
|
||||
|
||||
FString PlatformString = FString(TEXT("Win64"));
|
||||
#else
|
||||
FString PlatformString = FString(TEXT("Win32"));
|
||||
#endif
|
||||
//Swap these to change which license you wish to fall under for zip-utility
|
||||
|
||||
FString DLLString = FString("7z.dll"); //Using 7z.dll: GNU LGPL + unRAR restriction
|
||||
//FString dllString = FString("7za.dll"); //Using 7za.dll: GNU LGPL license, crucially doesn't support .zip out of the box
|
||||
|
||||
return FPaths::ConvertRelativePathToFull(FPaths::Combine(*PluginRootFolder(), TEXT("ThirdParty/7zpp/dll"), *PlatformString, *DLLString));
|
||||
}
|
||||
|
||||
FString ReversePathSlashes(FString forwardPath)
|
||||
{
|
||||
return forwardPath.Replace(TEXT("/"), TEXT("\\"));
|
||||
}
|
||||
|
||||
bool IsValidDirectory(FString& Directory, FString& FileName, const FString& Path)
|
||||
{
|
||||
bool Found = Path.Split(TEXT("/"), &Directory, &FileName, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
|
||||
//try a back split
|
||||
if (!Found)
|
||||
{
|
||||
Found = Path.Split(TEXT("\\"), &Directory, &FileName, ESearchCase::IgnoreCase, ESearchDir::FromEnd);
|
||||
}
|
||||
|
||||
//No valid Directory found
|
||||
if (!Found)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
SevenZip::CompressionLevelEnum libZipLevelFromUELevel(ZipUtilityCompressionLevel ueLevel) {
|
||||
switch (ueLevel)
|
||||
{
|
||||
case COMPRESSION_LEVEL_NONE:
|
||||
return SevenZip::CompressionLevel::None;
|
||||
case COMPRESSION_LEVEL_FAST:
|
||||
return SevenZip::CompressionLevel::Fast;
|
||||
case COMPRESSION_LEVEL_NORMAL:
|
||||
return SevenZip::CompressionLevel::Normal;
|
||||
default:
|
||||
return SevenZip::CompressionLevel::None;
|
||||
}
|
||||
}
|
||||
|
||||
SevenZip::CompressionFormatEnum libZipFormatFromUEFormat(ZipUtilityCompressionFormat UeFormat) {
|
||||
switch (UeFormat)
|
||||
{
|
||||
case COMPRESSION_FORMAT_UNKNOWN:
|
||||
return CompressionFormat::Unknown;
|
||||
case COMPRESSION_FORMAT_SEVEN_ZIP:
|
||||
return CompressionFormat::SevenZip;
|
||||
case COMPRESSION_FORMAT_ZIP:
|
||||
return CompressionFormat::Zip;
|
||||
case COMPRESSION_FORMAT_GZIP:
|
||||
return CompressionFormat::GZip;
|
||||
case COMPRESSION_FORMAT_BZIP2:
|
||||
return CompressionFormat::BZip2;
|
||||
case COMPRESSION_FORMAT_RAR:
|
||||
return CompressionFormat::Rar;
|
||||
case COMPRESSION_FORMAT_TAR:
|
||||
return CompressionFormat::Tar;
|
||||
case COMPRESSION_FORMAT_ISO:
|
||||
return CompressionFormat::Iso;
|
||||
case COMPRESSION_FORMAT_CAB:
|
||||
return CompressionFormat::Cab;
|
||||
case COMPRESSION_FORMAT_LZMA:
|
||||
return CompressionFormat::Lzma;
|
||||
case COMPRESSION_FORMAT_LZMA86:
|
||||
return CompressionFormat::Lzma86;
|
||||
default:
|
||||
return CompressionFormat::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
FString defaultExtensionFromUEFormat(ZipUtilityCompressionFormat ueFormat)
|
||||
{
|
||||
switch (ueFormat)
|
||||
{
|
||||
case COMPRESSION_FORMAT_UNKNOWN:
|
||||
return FString(TEXT(".dat"));
|
||||
case COMPRESSION_FORMAT_SEVEN_ZIP:
|
||||
return FString(TEXT(".7z"));
|
||||
case COMPRESSION_FORMAT_ZIP:
|
||||
return FString(TEXT(".zip"));
|
||||
case COMPRESSION_FORMAT_GZIP:
|
||||
return FString(TEXT(".gz"));
|
||||
case COMPRESSION_FORMAT_BZIP2:
|
||||
return FString(TEXT(".bz2"));
|
||||
case COMPRESSION_FORMAT_RAR:
|
||||
return FString(TEXT(".rar"));
|
||||
case COMPRESSION_FORMAT_TAR:
|
||||
return FString(TEXT(".tar"));
|
||||
case COMPRESSION_FORMAT_ISO:
|
||||
return FString(TEXT(".iso"));
|
||||
case COMPRESSION_FORMAT_CAB:
|
||||
return FString(TEXT(".cab"));
|
||||
case COMPRESSION_FORMAT_LZMA:
|
||||
return FString(TEXT(".lzma"));
|
||||
case COMPRESSION_FORMAT_LZMA86:
|
||||
return FString(TEXT(".lzma86"));
|
||||
default:
|
||||
return FString(TEXT(".dat"));
|
||||
}
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
//Background Thread convenience functions
|
||||
UZipOperation* UnzipFilesOnBGThreadWithFormat(const TArray<int32> FileIndices, const FString& ArchivePath, const FString& DestinationDirectory, const UObject* ProgressDelegate, ZipUtilityCompressionFormat Format)
|
||||
{
|
||||
UZipOperation* ZipOperation = NewObject<UZipOperation>();
|
||||
|
||||
IQueuedWork* Work = RunLambdaOnThreadPool([ProgressDelegate, FileIndices, ArchivePath, DestinationDirectory, Format, ZipOperation]
|
||||
{
|
||||
SevenZipCallbackHandler PrivateCallback;
|
||||
PrivateCallback.ProgressDelegate = (UObject*)ProgressDelegate;
|
||||
ZipOperation->SetCallbackHandler(&PrivateCallback);
|
||||
|
||||
//UE_LOG(LogClass, Log, TEXT("path is: %s"), *path);
|
||||
SevenZipExtractor Extractor(SZLib, *ArchivePath);
|
||||
|
||||
|
||||
if (Format == COMPRESSION_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (!Extractor.DetectCompressionFormat())
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("auto-compression detection did not succeed, passing in unknown format to 7zip library."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Extractor.SetCompressionFormat(libZipFormatFromUEFormat(Format));
|
||||
}
|
||||
|
||||
// Extract indices
|
||||
const int32 NumberFiles = FileIndices.Num();
|
||||
unsigned int* Indices = new unsigned int[NumberFiles];
|
||||
|
||||
for (int32 idx = 0; idx < NumberFiles; idx++)
|
||||
{
|
||||
Indices[idx] = FileIndices[idx];
|
||||
}
|
||||
|
||||
// Perform the extraction
|
||||
Extractor.ExtractFilesFromArchive(Indices, NumberFiles, *DestinationDirectory, &PrivateCallback);
|
||||
|
||||
// Clean up the indices
|
||||
delete Indices;
|
||||
|
||||
// Null out the callback handler now that we're exiting
|
||||
ZipOperation->SetCallbackHandler(nullptr);
|
||||
});
|
||||
|
||||
ZipOperation->SetThreadPoolWorker(Work);
|
||||
return ZipOperation;
|
||||
}
|
||||
|
||||
//Background Thread convenience functions
|
||||
UZipOperation* UnzipOnBGThreadWithFormat(const FString& ArchivePath, const FString& DestinationDirectory, const UObject* ProgressDelegate, ZipUtilityCompressionFormat Format)
|
||||
{
|
||||
UZipOperation* ZipOperation = NewObject<UZipOperation>();
|
||||
|
||||
IQueuedWork* Work = RunLambdaOnThreadPool([ProgressDelegate, ArchivePath, DestinationDirectory, Format, ZipOperation]
|
||||
{
|
||||
SevenZipCallbackHandler PrivateCallback;
|
||||
PrivateCallback.ProgressDelegate = (UObject*)ProgressDelegate;
|
||||
ZipOperation->SetCallbackHandler(&PrivateCallback);
|
||||
|
||||
//UE_LOG(LogClass, Log, TEXT("path is: %s"), *path);
|
||||
SevenZipExtractor Extractor(SZLib, *ArchivePath);
|
||||
|
||||
if (Format == COMPRESSION_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (!Extractor.DetectCompressionFormat())
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("auto-compression detection did not succeed, passing in unknown format to 7zip library."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Extractor.SetCompressionFormat(libZipFormatFromUEFormat(Format));
|
||||
}
|
||||
|
||||
Extractor.ExtractArchive(*DestinationDirectory, &PrivateCallback);
|
||||
|
||||
// Null out the callback handler now that we're exiting
|
||||
ZipOperation->SetCallbackHandler(nullptr);
|
||||
});
|
||||
|
||||
ZipOperation->SetThreadPoolWorker(Work);
|
||||
return ZipOperation;
|
||||
}
|
||||
|
||||
void ListOnBGThread(const FString& Path, const FString& Directory, const UObject* ListDelegate, ZipUtilityCompressionFormat Format)
|
||||
{
|
||||
//RunLongLambdaOnAnyThread - this shouldn't take long, but if it lags, swap the lambda methods
|
||||
RunLambdaOnAnyThread([ListDelegate, Path, Format, Directory] {
|
||||
SevenZipCallbackHandler PrivateCallback;
|
||||
PrivateCallback.ProgressDelegate = (UObject*)ListDelegate;
|
||||
SevenZipLister Lister(SZLib, *Path);
|
||||
|
||||
if (Format == COMPRESSION_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (!Lister.DetectCompressionFormat())
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("auto-compression detection did not succeed, passing in unknown format to 7zip library."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Lister.SetCompressionFormat(libZipFormatFromUEFormat(Format));
|
||||
}
|
||||
|
||||
if (!Lister.ListArchive(&PrivateCallback))
|
||||
{
|
||||
// If ListArchive returned false, it was most likely because the compression format was unsupported
|
||||
// Call OnDone with a failure message, make sure to call this on the game thread.
|
||||
if (IZipUtilityInterface* ZipInterface = Cast<IZipUtilityInterface>((UObject*)ListDelegate))
|
||||
{
|
||||
UE_LOG(LogClass, Warning, TEXT("ZipUtility: Unknown failure for list operation on %s"), *Path);
|
||||
UZipFileFunctionLibrary::RunLambdaOnGameThread([ZipInterface, ListDelegate, Path]
|
||||
{
|
||||
ZipInterface->Execute_OnDone((UObject*)ListDelegate, *Path, EZipUtilityCompletionState::FAILURE_UNKNOWN);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UZipOperation* ZipOnBGThread(const FString& Path, const FString& FileName, const FString& Directory, const UObject* ProgressDelegate, ZipUtilityCompressionFormat UeCompressionformat, ZipUtilityCompressionLevel UeCompressionlevel)
|
||||
{
|
||||
UZipOperation* ZipOperation = NewObject<UZipOperation>();
|
||||
|
||||
IQueuedWork* Work = RunLambdaOnThreadPool([ProgressDelegate, FileName, Path, UeCompressionformat, UeCompressionlevel, Directory, ZipOperation]
|
||||
{
|
||||
SevenZipCallbackHandler PrivateCallback;
|
||||
PrivateCallback.ProgressDelegate = (UObject*)ProgressDelegate;
|
||||
ZipOperation->SetCallbackHandler(&PrivateCallback);
|
||||
|
||||
//Set the zip format
|
||||
ZipUtilityCompressionFormat UeFormat = UeCompressionformat;
|
||||
|
||||
if (UeFormat == COMPRESSION_FORMAT_UNKNOWN)
|
||||
{
|
||||
UeFormat = COMPRESSION_FORMAT_ZIP;
|
||||
}
|
||||
//Disallow creating .rar archives as per unrar restriction, this won't work anyway so redirect to 7z
|
||||
else if (UeFormat == COMPRESSION_FORMAT_RAR)
|
||||
{
|
||||
UE_LOG(LogClass, Warning, TEXT("ZipUtility: Rar compression not supported for creating archives, re-targeting as 7z."));
|
||||
UeFormat = COMPRESSION_FORMAT_SEVEN_ZIP;
|
||||
}
|
||||
|
||||
//concatenate the output filename
|
||||
FString OutputFileName = FString::Printf(TEXT("%s/%s%s"), *Directory, *FileName, *defaultExtensionFromUEFormat(UeFormat));
|
||||
//UE_LOG(LogClass, Log, TEXT("\noutputfile is: <%s>\n path is: <%s>"), *outputFileName, *path);
|
||||
|
||||
SevenZipCompressor compressor(SZLib, *ReversePathSlashes(OutputFileName));
|
||||
compressor.SetCompressionFormat(libZipFormatFromUEFormat(UeFormat));
|
||||
compressor.SetCompressionLevel(libZipLevelFromUELevel(UeCompressionlevel));
|
||||
|
||||
if (PathIsDirectory(*Path))
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("Compressing Folder"));
|
||||
compressor.CompressDirectory(*ReversePathSlashes(Path), &PrivateCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("Compressing File"));
|
||||
compressor.CompressFile(*ReversePathSlashes(Path), &PrivateCallback);
|
||||
}
|
||||
|
||||
// Null out the callback handler
|
||||
ZipOperation->SetCallbackHandler(nullptr);
|
||||
//Todo: expand to support zipping up contents of current folder
|
||||
//compressor.CompressFiles(*ReversePathSlashes(path), TEXT("*"), &PrivateCallback);
|
||||
});
|
||||
ZipOperation->SetThreadPoolWorker(Work);
|
||||
return ZipOperation;
|
||||
}
|
||||
|
||||
}//End private namespace
|
||||
|
||||
UZipFileFunctionLibrary::UZipFileFunctionLibrary(const class FObjectInitializer& PCIP)
|
||||
: Super(PCIP)
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("DLLPath is: %s"), *DLLPath());
|
||||
SZLib.Load(*DLLPath());
|
||||
}
|
||||
|
||||
UZipFileFunctionLibrary::~UZipFileFunctionLibrary()
|
||||
{
|
||||
SZLib.Free();
|
||||
}
|
||||
|
||||
bool UZipFileFunctionLibrary::UnzipFileNamed(const FString& archivePath, const FString& Name, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format /*= COMPRESSION_FORMAT_UNKNOWN*/)
|
||||
{
|
||||
UZipFileFunctionInternalCallback* InternalCallback = NewObject<UZipFileFunctionInternalCallback>();
|
||||
InternalCallback->SetFlags(RF_MarkAsRootSet);
|
||||
InternalCallback->SetCallback(Name, ZipUtilityInterfaceDelegate, format);
|
||||
|
||||
ListFilesInArchive(archivePath, InternalCallback, format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UZipFileFunctionLibrary::UnzipFileNamedTo(const FString& archivePath, const FString& Name, const FString& destinationPath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format /*= COMPRESSION_FORMAT_UNKNOWN*/)
|
||||
{
|
||||
UZipFileFunctionInternalCallback* InternalCallback = NewObject<UZipFileFunctionInternalCallback>();
|
||||
InternalCallback->SetFlags(RF_MarkAsRootSet);
|
||||
InternalCallback->SetCallback(Name, destinationPath, ZipUtilityInterfaceDelegate, format);
|
||||
|
||||
ListFilesInArchive(archivePath, InternalCallback, format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::UnzipFilesTo(const TArray<int32> fileIndices, const FString & archivePath, const FString & destinationPath, UObject * ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format)
|
||||
{
|
||||
return UnzipFilesOnBGThreadWithFormat(fileIndices, archivePath, destinationPath, ZipUtilityInterfaceDelegate, format);
|
||||
}
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::UnzipFiles(const TArray<int32> fileIndices, const FString & ArchivePath, UObject * ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format)
|
||||
{
|
||||
FString Directory;
|
||||
FString FileName;
|
||||
|
||||
//Check Directory validity
|
||||
if (!IsValidDirectory(Directory, FileName, ArchivePath))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (fileIndices.Num() == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return UnzipFilesTo(fileIndices, ArchivePath, Directory, ZipUtilityInterfaceDelegate, format);
|
||||
}
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::Unzip(const FString& ArchivePath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat Format /*= COMPRESSION_FORMAT_UNKNOWN*/)
|
||||
{
|
||||
FString Directory;
|
||||
FString FileName;
|
||||
|
||||
//Check Directory validity
|
||||
if (!IsValidDirectory(Directory, FileName, ArchivePath) || !UWindowsFileUtilityFunctionLibrary::DoesFileExist(ArchivePath))
|
||||
{
|
||||
((IZipUtilityInterface*)ZipUtilityInterfaceDelegate)->Execute_OnDone((UObject*)ZipUtilityInterfaceDelegate, ArchivePath, EZipUtilityCompletionState::FAILURE_NOT_FOUND);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return UnzipTo(ArchivePath, Directory, ZipUtilityInterfaceDelegate, Format);
|
||||
}
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::UnzipWithLambda(const FString& ArchivePath, TFunction<void()> OnDoneCallback, TFunction<void(float)> OnProgressCallback, ZipUtilityCompressionFormat Format)
|
||||
{
|
||||
UZULambdaDelegate* LambdaDelegate = NewObject<UZULambdaDelegate>();
|
||||
LambdaDelegate->AddToRoot();
|
||||
LambdaDelegate->SetOnDoneCallback([LambdaDelegate, OnDoneCallback]()
|
||||
{
|
||||
OnDoneCallback();
|
||||
LambdaDelegate->RemoveFromRoot();
|
||||
});
|
||||
LambdaDelegate->SetOnProgessCallback(OnProgressCallback);
|
||||
|
||||
return Unzip(ArchivePath, LambdaDelegate, Format);
|
||||
}
|
||||
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::UnzipTo(const FString& ArchivePath, const FString& DestinationPath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat Format)
|
||||
{
|
||||
return UnzipOnBGThreadWithFormat(ArchivePath, DestinationPath, ZipUtilityInterfaceDelegate, Format);
|
||||
}
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::Zip(const FString& ArchivePath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat Format, TEnumAsByte<ZipUtilityCompressionLevel> Level)
|
||||
{
|
||||
FString Directory;
|
||||
FString FileName;
|
||||
|
||||
//Check Directory and File validity
|
||||
if (!IsValidDirectory(Directory, FileName, ArchivePath) || !UWindowsFileUtilityFunctionLibrary::DoesFileExist(ArchivePath))
|
||||
{
|
||||
((IZipUtilityInterface*)ZipUtilityInterfaceDelegate)->Execute_OnDone((UObject*)ZipUtilityInterfaceDelegate, ArchivePath, EZipUtilityCompletionState::FAILURE_NOT_FOUND);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ZipOnBGThread(ArchivePath, FileName, Directory, ZipUtilityInterfaceDelegate, Format, Level);
|
||||
}
|
||||
|
||||
UZipOperation* UZipFileFunctionLibrary::ZipWithLambda(const FString& ArchivePath, TFunction<void()> OnDoneCallback, TFunction<void(float)> OnProgressCallback /*= nullptr*/, ZipUtilityCompressionFormat Format /*= COMPRESSION_FORMAT_UNKNOWN*/, TEnumAsByte<ZipUtilityCompressionLevel> Level /*=COMPRESSION_LEVEL_NORMAL*/)
|
||||
{
|
||||
UZULambdaDelegate* LambdaDelegate = NewObject<UZULambdaDelegate>();
|
||||
LambdaDelegate->AddToRoot();
|
||||
LambdaDelegate->SetOnDoneCallback([OnDoneCallback, LambdaDelegate]()
|
||||
{
|
||||
OnDoneCallback();
|
||||
LambdaDelegate->RemoveFromRoot();
|
||||
});
|
||||
LambdaDelegate->SetOnProgessCallback(OnProgressCallback);
|
||||
|
||||
return Zip(ArchivePath, LambdaDelegate, Format);
|
||||
}
|
||||
|
||||
bool UZipFileFunctionLibrary::ListFilesInArchive(const FString& path, UObject* ListDelegate, ZipUtilityCompressionFormat format)
|
||||
{
|
||||
FString Directory;
|
||||
FString FileName;
|
||||
|
||||
//Check Directory validity
|
||||
if (!IsValidDirectory(Directory, FileName, path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ListOnBGThread(path, Directory, ListDelegate, format);
|
||||
return true;
|
||||
}
|
||||
|
||||
FGraphEventRef UZipFileFunctionLibrary::RunLambdaOnGameThread(TFunction< void()> InFunction)
|
||||
{
|
||||
return FFunctionGraphTask::CreateAndDispatchWhenReady(InFunction, TStatId(), nullptr, ENamedThreads::GameThread);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
#include "SevenZipCallbackHandler.h"
|
||||
#include "WFULambdaRunnable.h"
|
||||
#include "ZipOperation.h"
|
||||
|
||||
UZipOperation::UZipOperation()
|
||||
{
|
||||
CallbackHandler = nullptr;
|
||||
}
|
||||
|
||||
void UZipOperation::StopOperation()
|
||||
{
|
||||
if (ThreadPoolWork != nullptr)
|
||||
{
|
||||
WFULambdaRunnable::RemoveLambdaFromQueue(ThreadPoolWork);
|
||||
}
|
||||
|
||||
if (CallbackHandler != nullptr)
|
||||
{
|
||||
CallbackHandler->bCancelOperation = true;
|
||||
CallbackHandler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UZipOperation::SetCallbackHandler(SevenZipCallbackHandler* Handler)
|
||||
{
|
||||
CallbackHandler = Handler;
|
||||
}
|
||||
|
||||
void UZipOperation::SetThreadPoolWorker(IQueuedWork* Work)
|
||||
{
|
||||
ThreadPoolWork = Work;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
#include "ZipUtilityInterface.h"
|
||||
|
||||
UZipUtilityInterface::UZipUtilityInterface(const class FObjectInitializer& PCIP)
|
||||
: Super(PCIP)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "ZipUtilityPrivatePCH.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FZipUtilityModule"
|
||||
|
||||
void FZipUtilityModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
}
|
||||
|
||||
void FZipUtilityModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FZipUtilityModule, ZipUtility)
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "ZipUtilityPlugin.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include "EngineMinimal.h"
|
||||
|
||||
// You should place include statements to your module's private header files here. You only need to
|
||||
// add includes for headers that are used in most of your module's source files though.
|
||||
|
||||
#include "ZipFileFunctionLibrary.h"
|
||||
Reference in New Issue
Block a user