mirror of
https://github.com/Theaninova/BeatLanguageMapper.git
synced 2026-02-05 00:22:38 +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:
17
Plugins/ZipUtility-ue4/.gitattributes
vendored
Normal file
17
Plugins/ZipUtility-ue4/.gitattributes
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
51
Plugins/ZipUtility-ue4/.gitignore
vendored
Normal file
51
Plugins/ZipUtility-ue4/.gitignore
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
Binaries/*
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
*.pdb
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
Intermediate
|
||||
Binaries/Win64/UE4Editor-ZipUtility.dll
|
||||
BIN
Plugins/ZipUtility-ue4/Docs/event.png
Normal file
BIN
Plugins/ZipUtility-ue4/Docs/event.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 175 KiB |
BIN
Plugins/ZipUtility-ue4/Docs/stopoperation.png
Normal file
BIN
Plugins/ZipUtility-ue4/Docs/stopoperation.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
BIN
Plugins/ZipUtility-ue4/Docs/unzip.png
Normal file
BIN
Plugins/ZipUtility-ue4/Docs/unzip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
BIN
Plugins/ZipUtility-ue4/Docs/zip.png
Normal file
BIN
Plugins/ZipUtility-ue4/Docs/zip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
93
Plugins/ZipUtility-ue4/LICENSE.txt
Normal file
93
Plugins/ZipUtility-ue4/LICENSE.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
ZipUtility and 7z-cpp Modifications placed under MIT
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
(ZipUtility)
|
||||
Copyright (c) Jan Kaniewski (Getnamo) and Contributors (https://github.com/getnamo/ZipUtility-ue4/graphs/contributors)
|
||||
|
||||
(7z-cpp)
|
||||
Copyright (c) Jan Kaniewski (Getnamo), Keith J. Jones (keithjjones), and Contributors (https://github.com/getnamo/7zip-cpp/graphs/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
=============================================================================================
|
||||
|
||||
SevenZip++ (C++ wrapper) by Chadwick McNab is placed in the public domain. [https://bitbucket.org/cmcnab/sevenzip/wiki/Home]
|
||||
|
||||
=============================================================================================
|
||||
|
||||
LZMA SDK (LZMA 7-zip headers) is placed in the public domain. [www.7-zip.org/sdk.html]
|
||||
|
||||
=============================================================================================
|
||||
|
||||
This software uses code of 7z.dll licensed under the LGPL + unrar restriction version 2.1 and its source can be downloaded at www.7-zip.org
|
||||
7-Zip
|
||||
~~~~~
|
||||
License for use and distribution
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
7-Zip Copyright (C) 1999-2015 Igor Pavlov.
|
||||
|
||||
Licenses for files are:
|
||||
|
||||
1) 7z.dll: GNU LGPL + unRAR restriction
|
||||
2) All other files: GNU LGPL
|
||||
|
||||
The GNU LGPL + unRAR restriction means that you must follow both
|
||||
GNU LGPL rules and unRAR restriction rules.
|
||||
|
||||
|
||||
Note:
|
||||
You can use 7-Zip on any computer, including a computer in a commercial
|
||||
organization. You don't need to register or pay for 7-Zip.
|
||||
|
||||
|
||||
GNU LGPL information
|
||||
--------------------
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You can receive a copy of the GNU Lesser General Public License from
|
||||
http://www.gnu.org/
|
||||
|
||||
|
||||
unRAR restriction
|
||||
-----------------
|
||||
|
||||
The decompression engine for RAR archives was developed using source
|
||||
code of unRAR program.
|
||||
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||
|
||||
The license for original unRAR code has the following restriction:
|
||||
|
||||
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||
or as a part of other software is permitted, provided that it is clearly
|
||||
stated in the documentation and source comments that the code may
|
||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||
--
|
||||
Igor Pavlov
|
||||
246
Plugins/ZipUtility-ue4/README.md
Normal file
246
Plugins/ZipUtility-ue4/README.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# ZipUtility Plugin
|
||||
|
||||
[](https://github.com/getnamo/ziputility-ue4/releases)
|
||||
[](https://github.com/getnamo/ziputility-ue4/releases)
|
||||
|
||||
Event driven, blueprint accessible flexible 7zip compression, archiver, and file manipulation plugin for Unreal Engine 4. Built on [7zip-cpp](https://github.com/getnamo/7zip-cpp) modernization of the [SevenZip++](http://bitbucket.org/cmcnab/sevenzip/wiki/Home) C++ wrapper for accessing the 7-zip COM-like API in 7z.dll and 7za.dll.
|
||||
|
||||
Supports the following compression algorithms:
|
||||
7Zip, GZip, BZip2, RAR, TAR, ISO, CAB, LZMA, LZMA86.
|
||||
|
||||
|
||||
Plugin works in Windows only.
|
||||
|
||||
[Main Forum Thread](https://forums.unrealengine.com/showthread.php?95022-Plugin-ZipUtility-(7zip))
|
||||
|
||||
|
||||
## Quick Install & Setup ##
|
||||
|
||||
1. [Download](https://github.com/getnamo/ZipUtility-ue4/releases)
|
||||
2. Create new or choose project.
|
||||
3. Browse to your project folder (typically found at Documents/Unreal Project/{Your Project Root})
|
||||
4. Copy *Plugins* folder into your Project root.
|
||||
5. Restart the Editor and open your project again. Plugin is now ready to use.
|
||||
|
||||
|
||||
## Blueprint Access
|
||||
|
||||
Right click anywhere in a desired blueprint to access the plugin Blueprint Function Library methods. The plugin is completely multi-threaded and will not block your game thread, fire and forget.
|
||||
|
||||

|
||||
|
||||
*Optional but highly recommended:* Add `ZipUtilityInterface` to your blueprint if you wish to be notified of the progress, e.g. when your archive has finished unzipping or if you wish to display a progress bar.
|
||||
|
||||

|
||||
|
||||
After you've added the interface and hit Compile on your blueprint you'll have access to the Progress and List events
|
||||
|
||||

|
||||
|
||||
They're explained in further detail below.
|
||||
|
||||
## Zipping and Compressing Files
|
||||
|
||||
To Zip up a folder or file, right click your event graph and add the `Zip` function.
|
||||
|
||||
Specify a path to a folder or file as a target.
|
||||
|
||||
Leave the Compression format to the default SevenZip or specify a format of choice, the plugin automatically appends the default extension based on the compression format. Note that not all compression formats work for compression (e.g. RAR is extract only).
|
||||
|
||||

|
||||
|
||||
## Unzipping and Extracting Files
|
||||
|
||||
To Unzip up a file, right click your event graph and add the `Unzip` function.
|
||||
|
||||
Specify the full path to a suitable archive file.
|
||||
|
||||
The plugin automatically detects the compression format used in the archive, but you can alternatively specify a specific format using the `UnzipWithFormat` method.
|
||||
|
||||

|
||||
|
||||
## Listing Contents in an Archive
|
||||
|
||||
To list files in your archive, right click your event graph and add the `ListFilesInArchive` function.
|
||||
|
||||
Specify the full path to a suitable archive file. This function requires the use of the `ZipUtilityInterface` callback `OnFileFound`, so ensure you have `ZipUtilityInterface` added to your blueprint.
|
||||
|
||||

|
||||
|
||||
The `OnFileFound` event gets called for every file in the archive with its path and size given in bytes. This function does not extract the contents, but instead allows you to inspect files before committing to extracting their contents.
|
||||
|
||||
## Events & Progress Updates
|
||||
|
||||
By right-clicking in your blueprint and adding various `ZipUtility` events, you can get the status of zip/unzip operations as they occur. All callbacks are received on the game thread. To receive callbacks you must satisfy two requirements:
|
||||
|
||||
1. Implement the `ZipUtilityInterface` interface in your blueprint from the Class Settings menu
|
||||
2. Pass a reference to `self` (or a reference to the class that implements `ZipUtilityInterface`) to all zip/unzip functions
|
||||
|
||||
All events pass along the name of the archive being operated on. Since multiple events can be running in parallel, the archive name is useful to uniquely match events with operations.
|
||||
|
||||
### Event Table
|
||||
|
||||
| Event | Details |
|
||||
| ------------- | ------------- |
|
||||
| `OnStartProcess` | Called when the zip/unzip operation begins |
|
||||
| `OnProgress` | Called periodically while a zip/unzip operation is running to provide the overall status of the operation |
|
||||
| `OnFileDone` | Called for every file that is done being zipped/unzipped |
|
||||
| `OnDone` | Called when the entire zip/unzip operation has completed |
|
||||
| `OnFileFound` | Called for every file that is found as the result of a `ListFilesInArchive` call |
|
||||
|
||||

|
||||
|
||||
## Stopping Operations
|
||||
|
||||
Most of the Zip and Unzip methods return a pointer to a `ZipOperation`. This pointer can be used to terminate an operation that is still running by calling the `StopOperation` function.
|
||||
|
||||
The returned pointer to `ZipOperation` will be Garbage Collected if it is not stored as an Object Reference or in C++ in a `UPROPERTY` declared pointer. So don't store `ZipOperation` as a soft reference/pointer. It is safe to completely ignore the returned `ZipOperation` if you do not care about manually terminating the operation.
|
||||
|
||||

|
||||
|
||||
## Convenience File Functions
|
||||
|
||||
### Move/Rename a File
|
||||
|
||||
Specify full path for the file you wish to move and it's destination
|
||||
|
||||

|
||||
|
||||
To rename it, simply change the destination name
|
||||
|
||||

|
||||
|
||||
|
||||
### Create/Make Directory
|
||||
|
||||

|
||||
|
||||
|
||||
### List Contents of Folder
|
||||
|
||||
Expects self to be a `FileListInterface`
|
||||
|
||||

|
||||
|
||||
## C++
|
||||
|
||||
### Setup
|
||||
|
||||
To use the C++ code from the plugin add it as a dependency module in your project build.cs e.g.
|
||||
|
||||
```c#
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ZipUtility"});
|
||||
```
|
||||
|
||||
then ```#include "ZipFileFunctionLibrary.h"``` in the places where you'd like to use the plugin functionality.
|
||||
|
||||
### [Lambda](http://en.cppreference.com/w/cpp/language/lambda)
|
||||
|
||||
#### [UnzipWithLambda](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/ZipUtility/Public/ZipFileFunctionLibrary.h#L63)
|
||||
|
||||
call the static function with *done* and *progress* callback lambdas e.g. if you're interested in both
|
||||
|
||||
```c++
|
||||
UZipFileFunctionLibrary::UnzipWithLambda(FString("C:/path/to/your/zip.7z"),
|
||||
[]()
|
||||
{
|
||||
//Called when done
|
||||
},
|
||||
[](float Percent)
|
||||
{
|
||||
//called when progress updates with % done
|
||||
});
|
||||
```
|
||||
|
||||
replace either with nullptr if you're not interested in that callback
|
||||
|
||||
#### [ZipWithLambda](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/ZipUtility/Public/ZipFileFunctionLibrary.h#L80)
|
||||
|
||||
call the static function with *done* and *progress* callback lambdas e.g. if you're interested in both
|
||||
|
||||
```c++
|
||||
UZipFileFunctionLibrary::ZipWithLambda(FString("C:/path/to/your/zip.7z"),
|
||||
[]()
|
||||
{
|
||||
//Called when done
|
||||
},
|
||||
[](float Percent)
|
||||
{
|
||||
//called when progress updates with % done
|
||||
});
|
||||
```
|
||||
|
||||
replace either with nullptr if you're not interested in that callback
|
||||
|
||||
### Your own class with [IZipUtilityInterface](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/ZipUtility/Public/ZipUtilityInterface.h)
|
||||
|
||||
Let's say you have a class called `UMyClass`. You then add the `IZipUtilityInterface` to it via multiple inheritance e.g.
|
||||
|
||||
```c++
|
||||
class UMyClass : public UObject, public IZipUtilityInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
Because the events are of the type [BlueprintNativeEvent](https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Functions/Specifiers/BlueprintNativeEvent/) you add the C++ implementation of the events like so
|
||||
|
||||
```c++
|
||||
class UMyClass : public UObject, public IZipUtilityInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
...
|
||||
|
||||
//event 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;
|
||||
virtual void OnFileFound_Implementation(const FString& archive, const FString& file, int32 size) override;
|
||||
};
|
||||
```
|
||||
|
||||
ensure you have at least an empty implementation for each function
|
||||
|
||||
```c++
|
||||
void UMyClass::OnProgress_Implementation(const FString& archive, float percentage, int32 bytes)
|
||||
{
|
||||
//your code here
|
||||
}
|
||||
```
|
||||
|
||||
To call a `ZipUtility` function you first get a valid pointer to your class (I leave that up to you) e.g.
|
||||
|
||||
```c++
|
||||
UMyClass* MyZipClass = NewObject<UMyClass>(); //or you may already have a valid pointer from allocating elsewhere
|
||||
```
|
||||
|
||||
then to e.g. unzip you pass the pointer to your class with the `IZipUtilityInterface` as your second parameter (and if you use them, any other optional parameters such as compression format). If you are calling the zip functions from within the class that implements `IZipUtilityInterface` then you can simply pass `this`:
|
||||
|
||||
```c++
|
||||
UZipFileFunctionLibrary::Unzip(FString("C:/path/to/your/zip.7z"), MyZipClass);
|
||||
```
|
||||
|
||||
See [ZipFileFunctionLibrary.h](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/ZipUtility/Public/ZipFileFunctionLibrary.h) for all the function signatures.
|
||||
|
||||
See [ZULambdaDelegate.h](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/ZipUtility/Private/ZULambdaDelegate.h) for an example class using the above setup to convert `IZipUtilityInterface` interface calls into lambda functions.
|
||||
|
||||
|
||||
### Windows Utility
|
||||
|
||||
For windows utility functions, the callback setup is similar, kindly refer to [WindowsFileUtilityFunctionLibrary.h](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/WindowsUtility/Public/WindowsFileUtilityFunctionLibrary.h) which may use [IWFUFileListInterface](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/WindowsUtility/Public/WFUFileListInterface.h) or [IWFUFolderWatchInterface](https://github.com/getnamo/ZipUtility-ue4/blob/master/Source/WindowsUtility/Public/WFUFolderWatchInterface.h) depending on functions used.
|
||||
|
||||
## License
|
||||
|
||||
MIT for ZipUtility and 7z-cpp
|
||||
|
||||
LGPL for 7za.dll, LGPL + Unrar for 7z.dll
|
||||
|
||||
See license file for details.
|
||||
|
||||
## Help
|
||||
Add any issues you run across to https://github.com/getnamo/ZipUtility-ue4/issues
|
||||
|
||||
or post to the [unreal forum thread](https://forums.unrealengine.com/showthread.php?95022-Plugin-ZipUtility-(7zip)).
|
||||
|
||||
BIN
Plugins/ZipUtility-ue4/Resources/Icon128.png
Normal file
BIN
Plugins/ZipUtility-ue4/Resources/Icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
@@ -0,0 +1,11 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
#include "WFUFileListInterface.h"
|
||||
|
||||
|
||||
UWFUFileListInterface::UWFUFileListInterface(const class FObjectInitializer& PCIP)
|
||||
: Super(PCIP)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
#include "WindowsFileUtilityFunctionLibrary.h"
|
||||
#include "WFUFileListLambdaDelegate.h"
|
||||
|
||||
UWFUFileListLambdaDelegate::UWFUFileListLambdaDelegate()
|
||||
{
|
||||
OnDoneCallback = nullptr;
|
||||
}
|
||||
|
||||
void UWFUFileListLambdaDelegate::SetOnDoneCallback(TFunction<void(const TArray<FString>&, const TArray<FString>&)> InOnDoneCallback)
|
||||
{
|
||||
OnDoneCallback = InOnDoneCallback;
|
||||
}
|
||||
|
||||
void UWFUFileListLambdaDelegate::OnListFileFound_Implementation(const FString& FileName, int32 ByteCount, const FString& FilePath)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UWFUFileListLambdaDelegate::OnListDirectoryFound_Implementation(const FString& DirectoryName, const FString& FilePath)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UWFUFileListLambdaDelegate::OnListDone_Implementation(const FString& DirectoryPath, const TArray<FString>& Files, const TArray<FString>& Folders)
|
||||
{
|
||||
if (OnDoneCallback != nullptr)
|
||||
{
|
||||
OnDoneCallback(Files, Folders);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Object.h"
|
||||
#include "WFUFileListLambdaDelegate.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class WINDOWSFILEUTILITY_API UWFUFileListLambdaDelegate : public UObject, public IWFUFileListInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UWFUFileListLambdaDelegate();
|
||||
public:
|
||||
void SetOnDoneCallback(TFunction<void(const TArray<FString>&, const TArray<FString>&)> InOnDoneCallback);
|
||||
|
||||
protected:
|
||||
//File List Interface
|
||||
|
||||
virtual void OnListFileFound_Implementation(const FString& FileName, int32 ByteCount, const FString& FilePath) override;
|
||||
virtual void OnListDirectoryFound_Implementation(const FString& DirectoryName, const FString& FilePath) override;
|
||||
virtual void OnListDone_Implementation(const FString& DirectoryPath, const TArray<FString>& Files, const TArray<FString>& Folders) override;
|
||||
|
||||
TFunction<void(const TArray<FString>&, const TArray<FString>&)> OnDoneCallback;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
#include "WFUFolderWatchInterface.h"
|
||||
|
||||
|
||||
UWFUFolderWatchInterface::UWFUFolderWatchInterface(const class FObjectInitializer& PCIP)
|
||||
: Super(PCIP)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
#include "WindowsFileUtilityFunctionLibrary.h"
|
||||
#include "WFUFolderWatchLambdaDelegate.h"
|
||||
|
||||
UWFUFolderWatchLambdaDelegate::UWFUFolderWatchLambdaDelegate()
|
||||
{
|
||||
OnFileChangedCallback = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void UWFUFolderWatchLambdaDelegate::SetOnFileChangedCallback(TFunction<void(FString, FString)> InOnFileChangedCallback)
|
||||
{
|
||||
OnFileChangedCallback = InOnFileChangedCallback;
|
||||
}
|
||||
|
||||
|
||||
void UWFUFolderWatchLambdaDelegate::OnFileChanged_Implementation(const FString& FileName, const FString& FilePath)
|
||||
{
|
||||
if (OnFileChangedCallback != nullptr)
|
||||
{
|
||||
OnFileChangedCallback(FileName, FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
void UWFUFolderWatchLambdaDelegate::OnDirectoryChanged_Implementation(const FString& DirectoryName, const FString& DirectoryPath)
|
||||
{
|
||||
if (OnFileChangedCallback != nullptr)
|
||||
{
|
||||
OnFileChangedCallback(DirectoryName, DirectoryPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Object.h"
|
||||
#include "WFUFolderWatchLambdaDelegate.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class WINDOWSFILEUTILITY_API UWFUFolderWatchLambdaDelegate : public UObject, public IWFUFolderWatchInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UWFUFolderWatchLambdaDelegate();
|
||||
public:
|
||||
void SetOnFileChangedCallback(TFunction<void(FString, FString)> InOnFileChangedCallback);
|
||||
|
||||
protected:
|
||||
TFunction<void(FString, FString)> OnFileChangedCallback;
|
||||
|
||||
//IWFUFolderWatchInterface
|
||||
virtual void OnFileChanged_Implementation(const FString& FileName, const FString& FilePath) override;
|
||||
virtual void OnDirectoryChanged_Implementation(const FString& DirectoryName, const FString& DirectoryPath) override;
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
#include "WFULambdaRunnable.h"
|
||||
|
||||
uint64 WFULambdaRunnable::ThreadNumber = 0;
|
||||
|
||||
FQueuedThreadPool* WFULambdaRunnable::ThreadPool = nullptr;
|
||||
|
||||
WFULambdaRunnable::WFULambdaRunnable(TFunction< void()> InFunction)
|
||||
{
|
||||
FunctionPointer = InFunction;
|
||||
|
||||
FString threadStatGroup = FString::Printf(TEXT("FLambdaRunnable%d"), ThreadNumber++);
|
||||
Thread = NULL;
|
||||
Thread = FRunnableThread::Create(this, *threadStatGroup, 0, TPri_BelowNormal); //windows default = 8mb for thread, could specify more
|
||||
}
|
||||
|
||||
WFULambdaRunnable::~WFULambdaRunnable()
|
||||
{
|
||||
if (Thread == NULL)
|
||||
{
|
||||
delete Thread;
|
||||
Thread = NULL;
|
||||
}
|
||||
|
||||
ThreadPool->Destroy();
|
||||
}
|
||||
|
||||
//Run
|
||||
uint32 WFULambdaRunnable::Run()
|
||||
{
|
||||
if (FunctionPointer)
|
||||
FunctionPointer();
|
||||
|
||||
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable %d Run complete"), Number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WFULambdaRunnable::Exit()
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable %d Exit"), Number);
|
||||
|
||||
//delete ourselves when we're done
|
||||
delete this;
|
||||
}
|
||||
|
||||
void WFULambdaRunnable::InitThreadPool(int32 NumberOfThreads)
|
||||
{
|
||||
if (ThreadPool == nullptr)
|
||||
{
|
||||
ThreadPool = FQueuedThreadPool::Allocate();
|
||||
int32 NumThreadsInThreadPool = NumberOfThreads;
|
||||
ThreadPool->Create(NumThreadsInThreadPool, 32 * 1024);
|
||||
}
|
||||
}
|
||||
|
||||
void WFULambdaRunnable::EnsureCompletion()
|
||||
{
|
||||
Thread->WaitForCompletion();
|
||||
}
|
||||
|
||||
WFULambdaRunnable* WFULambdaRunnable::RunLambdaOnBackGroundThread(TFunction< void()> InFunction)
|
||||
{
|
||||
if (FPlatformProcess::SupportsMultithreading())
|
||||
{
|
||||
//UE_LOG(LogClass, Log, TEXT("FLambdaRunnable RunLambdaBackGroundThread"));
|
||||
return new WFULambdaRunnable(InFunction);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IQueuedWork* WFULambdaRunnable::AddLambdaToQueue(TFunction< void()> InFunction)
|
||||
{
|
||||
if (ThreadPool == nullptr)
|
||||
{
|
||||
WFULambdaRunnable::InitThreadPool(FPlatformMisc::NumberOfIOWorkerThreadsToSpawn());
|
||||
}
|
||||
|
||||
if (ThreadPool)
|
||||
{
|
||||
return AsyncLambdaPool(*ThreadPool, InFunction);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool WFULambdaRunnable::RemoveLambdaFromQueue(IQueuedWork* Work)
|
||||
{
|
||||
if (ThreadPool)
|
||||
{
|
||||
return ThreadPool->RetractQueuedWork(Work);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FGraphEventRef WFULambdaRunnable::RunShortLambdaOnGameThread(TFunction< void()> InFunction)
|
||||
{
|
||||
return FFunctionGraphTask::CreateAndDispatchWhenReady(InFunction, TStatId(), nullptr, ENamedThreads::GameThread);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
|
||||
class FWindowsFileUtility : public IWindowsFileUtility
|
||||
{
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void ShutdownModule() override
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_MODULE(IWindowsFileUtility, WindowsFileUtility)
|
||||
@@ -0,0 +1,414 @@
|
||||
#include "WindowsFileUtilityPrivatePCH.h"
|
||||
#include "WFUFolderWatchInterface.h"
|
||||
#include "WFUFileListInterface.h"
|
||||
#include "WindowsFileUtilityFunctionLibrary.h"
|
||||
|
||||
//static TMAP definition
|
||||
TMap<FString, TArray<FWatcher>> UWindowsFileUtilityFunctionLibrary::Watchers = TMap<FString, TArray<FWatcher>>();
|
||||
int TotalWatchers = 0;
|
||||
|
||||
UWindowsFileUtilityFunctionLibrary::UWindowsFileUtilityFunctionLibrary(const class FObjectInitializer& PCIP)
|
||||
: Super(PCIP)
|
||||
{
|
||||
}
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
#include "AllowWindowsPlatformTypes.h"
|
||||
#include <shellapi.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
bool UWindowsFileUtilityFunctionLibrary::DoesFileExist(const FString& FullPath)
|
||||
{
|
||||
return 0 != PathFileExistsW(*FullPath);
|
||||
}
|
||||
|
||||
bool UWindowsFileUtilityFunctionLibrary::MoveFileTo(const FString& From, const FString& To)
|
||||
{
|
||||
//Using windows api
|
||||
return 0 != MoveFileW(*From, *To);
|
||||
}
|
||||
|
||||
|
||||
bool UWindowsFileUtilityFunctionLibrary::CreateDirectoryAt(const FString& FullPath)
|
||||
{
|
||||
//Using windows api
|
||||
return 0 != CreateDirectoryW(*FullPath, NULL);
|
||||
}
|
||||
|
||||
bool UWindowsFileUtilityFunctionLibrary::DeleteFileAt(const FString& FullPath)
|
||||
{
|
||||
//Using windows api
|
||||
return 0 != DeleteFileW(*FullPath);
|
||||
}
|
||||
|
||||
bool UWindowsFileUtilityFunctionLibrary::DeleteEmptyFolder(const FString& FullPath)
|
||||
{
|
||||
//Using windows api
|
||||
return 0 != RemoveDirectoryW(*FullPath);
|
||||
}
|
||||
|
||||
bool IsSubPathOf(const FString& path, const FString& basePath)
|
||||
{
|
||||
return path.Contains(basePath);
|
||||
}
|
||||
|
||||
//Dangerous function not recommended to be exposed to blueprint
|
||||
bool UWindowsFileUtilityFunctionLibrary::DeleteFolderRecursively(const FString& FullPath)
|
||||
{
|
||||
//Only allow user to delete folders sub-class to game folder
|
||||
if (!IsSubPathOf(FullPath, FPaths::ProjectDir()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int len = _tcslen(*FullPath);
|
||||
TCHAR *pszFrom = new TCHAR[len + 2];
|
||||
wcscpy_s(pszFrom, len + 2, *FullPath);
|
||||
pszFrom[len] = 0;
|
||||
pszFrom[len + 1] = 0;
|
||||
|
||||
SHFILEOPSTRUCT fileop;
|
||||
fileop.hwnd = NULL; // no status display
|
||||
fileop.wFunc = FO_DELETE; // delete operation
|
||||
fileop.pFrom = pszFrom; // source file name as double null terminated string
|
||||
fileop.pTo = NULL; // no destination needed
|
||||
fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt the user
|
||||
|
||||
fileop.fAnyOperationsAborted = FALSE;
|
||||
fileop.lpszProgressTitle = NULL;
|
||||
fileop.hNameMappings = NULL;
|
||||
|
||||
int ret = SHFileOperation(&fileop);
|
||||
delete[] pszFrom;
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
void UWindowsFileUtilityFunctionLibrary::WatchFolder(const FString& FullPath, UObject* WatcherDelegate)
|
||||
{
|
||||
//Do we have an entry for this path?
|
||||
if (!Watchers.Contains(FullPath))
|
||||
{
|
||||
//Make an entry
|
||||
TArray<FWatcher> FreshList;
|
||||
Watchers.Add(FullPath, FreshList);
|
||||
Watchers[FullPath] = FreshList;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if we do do we already watch from this object?
|
||||
TArray<FWatcher>& PathWatchers = Watchers[FullPath];
|
||||
|
||||
for (auto Watcher : PathWatchers)
|
||||
{
|
||||
if (Watcher.Delegate == WatcherDelegate)
|
||||
{
|
||||
//Already accounted for
|
||||
UE_LOG(LogTemp, Warning, TEXT("UWindowsFileUtilityFunctionLibrary::WatchFolder Duplicate watcher ignored!"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Add to watchers
|
||||
FWatcher FreshWatcher;
|
||||
FreshWatcher.Delegate = WatcherDelegate;
|
||||
FreshWatcher.Path = FullPath;
|
||||
|
||||
const FWatcher* WatcherPtr = &FreshWatcher;
|
||||
|
||||
//fork this off to another process
|
||||
WFULambdaRunnable* Runnable = WFULambdaRunnable::RunLambdaOnBackGroundThread([FullPath, WatcherDelegate, WatcherPtr]()
|
||||
{
|
||||
UWindowsFileUtilityFunctionLibrary::WatchFolderOnBgThread(FullPath, WatcherPtr);
|
||||
});
|
||||
|
||||
FreshWatcher.Runnable = Runnable;
|
||||
|
||||
TArray<FWatcher>& PathWatchers = Watchers[FullPath];
|
||||
PathWatchers.Add(FreshWatcher);
|
||||
}
|
||||
|
||||
void UWindowsFileUtilityFunctionLibrary::StopWatchingFolder(const FString& FullPath, UObject* WatcherDelegate)
|
||||
{
|
||||
//Do we have an entry?
|
||||
if (!Watchers.Contains(FullPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//We have an entry for this path, remove our watcher
|
||||
TArray<FWatcher> PathWatchers = Watchers[FullPath];
|
||||
for (int i = 0; i < PathWatchers.Num();i++)
|
||||
{
|
||||
FWatcher& PathWatcher = PathWatchers[i];
|
||||
if (PathWatcher.Delegate == WatcherDelegate)
|
||||
{
|
||||
//Stop the runnable
|
||||
PathWatcher.ShouldRun = false;
|
||||
PathWatcher.Runnable->Stop();
|
||||
|
||||
//Remove the watcher and we're done
|
||||
PathWatchers.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UWindowsFileUtilityFunctionLibrary::ListContentsOfFolder(const FString& FullPath, UObject* Delegate)
|
||||
{
|
||||
//Longer than max path? throw error
|
||||
if (FullPath.Len() > MAX_PATH)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("UWindowsFileUtilityFunctionLibrary::ListContentsOfFolder Error, path too long, listing aborted."));
|
||||
return;
|
||||
}
|
||||
|
||||
WFULambdaRunnable* Runnable = WFULambdaRunnable::RunLambdaOnBackGroundThread([&FullPath, Delegate]()
|
||||
{
|
||||
WIN32_FIND_DATA ffd;
|
||||
LARGE_INTEGER filesize;
|
||||
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||||
DWORD dwError = 0;
|
||||
|
||||
FString SearchPath = FullPath + TEXT("\\*");
|
||||
|
||||
hFind = FindFirstFile(*SearchPath, &ffd);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == hFind)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("UWindowsFileUtilityFunctionLibrary::ListContentsOfFolder Error, invalid handle, listing aborted."));
|
||||
return;
|
||||
}
|
||||
|
||||
//Arrays to hold full information on Done
|
||||
TArray<FString> FileNames;
|
||||
TArray<FString> FolderNames;
|
||||
|
||||
//List loop, callback on game thread
|
||||
do
|
||||
{
|
||||
FString Name = FString(ffd.cFileName);
|
||||
FString ItemPath = FullPath + TEXT("\\") + Name;
|
||||
|
||||
//UE_LOG(LogTemp, Log, TEXT("Name: <%s>"), *Name);
|
||||
|
||||
if (Name.Equals(FString(TEXT("."))) ||
|
||||
Name.Equals(FString(TEXT(".."))) )
|
||||
{
|
||||
//ignore these first
|
||||
}
|
||||
//Folder
|
||||
else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
FolderNames.Add(Name);
|
||||
WFULambdaRunnable::RunShortLambdaOnGameThread([Delegate, ItemPath, Name]
|
||||
{
|
||||
((IWFUFileListInterface*)Delegate)->Execute_OnListDirectoryFound((UObject*)Delegate, Name, ItemPath);
|
||||
});
|
||||
}
|
||||
//File
|
||||
else
|
||||
{
|
||||
FileNames.Add(Name);
|
||||
|
||||
filesize.LowPart = ffd.nFileSizeLow;
|
||||
filesize.HighPart = ffd.nFileSizeHigh;
|
||||
int32 TruncatedFileSize = filesize.QuadPart;
|
||||
|
||||
WFULambdaRunnable::RunShortLambdaOnGameThread([Delegate, ItemPath, Name, TruncatedFileSize]
|
||||
{
|
||||
((IWFUFileListInterface*)Delegate)->Execute_OnListFileFound((UObject*)Delegate, Name, TruncatedFileSize, ItemPath);
|
||||
});
|
||||
}
|
||||
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
|
||||
dwError = GetLastError();
|
||||
if (dwError != ERROR_NO_MORE_FILES)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("UWindowsFileUtilityFunctionLibrary::ListContentsOfFolder Error while listing."));
|
||||
return;
|
||||
}
|
||||
|
||||
FindClose(hFind);
|
||||
|
||||
//Done callback with full list of names found
|
||||
WFULambdaRunnable::RunShortLambdaOnGameThread([Delegate, FullPath, FileNames, FolderNames]
|
||||
{
|
||||
((IWFUFileListInterface*)Delegate)->Execute_OnListDone((UObject*)Delegate, FullPath, FileNames, FolderNames);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void UWindowsFileUtilityFunctionLibrary::ListContentsOfFolderToCallback(const FString& FullPath, TFunction<void(const TArray<FString>&, const TArray<FString>&)> OnListCompleteCallback)
|
||||
{
|
||||
UWFUFileListLambdaDelegate* LambdaDelegate = NewObject<UWFUFileListLambdaDelegate>();
|
||||
LambdaDelegate->SetOnDoneCallback(OnListCompleteCallback);
|
||||
|
||||
ListContentsOfFolder(FullPath, LambdaDelegate);
|
||||
}
|
||||
|
||||
void UWindowsFileUtilityFunctionLibrary::WatchFolderOnBgThread(const FString& FullPath, const FWatcher* WatcherPtr)
|
||||
{
|
||||
//mostly from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365261(v=vs.85).aspx
|
||||
//call the delegate when the folder changes
|
||||
|
||||
//TODO: find out which file changed
|
||||
|
||||
DWORD dwWaitStatus;
|
||||
HANDLE dwChangeHandles[2];
|
||||
TCHAR lpDrive[4];
|
||||
TCHAR lpFile[_MAX_FNAME];
|
||||
TCHAR lpExt[_MAX_EXT];
|
||||
|
||||
//finding out about the notification
|
||||
FILE_NOTIFY_INFORMATION strFileNotifyInfo[1024];
|
||||
DWORD dwBytesReturned = 0;
|
||||
|
||||
_tsplitpath_s(*FullPath, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);
|
||||
lpDrive[2] = (TCHAR)'\\';
|
||||
lpDrive[3] = (TCHAR)'\0';
|
||||
|
||||
// Watch the directory for file creation and deletion.
|
||||
|
||||
dwChangeHandles[0] = FindFirstChangeNotification(
|
||||
*FullPath, // directory to watch
|
||||
TRUE, // watch the subtree
|
||||
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE// watch for generic file changes
|
||||
); // watch last write or file size change
|
||||
|
||||
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("\n ERROR: FindFirstChangeNotification function failed.\n"));
|
||||
//ExitProcess(GetLastError());
|
||||
}
|
||||
|
||||
// Watch the subtree for directory creation and deletion.
|
||||
|
||||
dwChangeHandles[1] = FindFirstChangeNotification(
|
||||
lpDrive, // directory to watch
|
||||
TRUE, // watch the subtree
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME); // watch dir name changes
|
||||
|
||||
if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("\n ERROR: FindFirstChangeNotification function failed.\n"));
|
||||
//ExitProcess(GetLastError());
|
||||
}
|
||||
|
||||
// Make a final validation check on our handles.
|
||||
if ((dwChangeHandles[0] == NULL) || (dwChangeHandles[1] == NULL))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("\n ERROR: Unexpected NULL from FindFirstChangeNotification.\n"));
|
||||
//ExitProcess(GetLastError());
|
||||
}
|
||||
const FString DrivePath = FString(lpDrive);
|
||||
FString FileString;
|
||||
FString DirectoryString;
|
||||
const UObject* WatcherDelegate = WatcherPtr->Delegate;
|
||||
|
||||
//Wait while the runnable pointer hasn't been set
|
||||
|
||||
TotalWatchers++;
|
||||
UE_LOG(LogTemp, Log, TEXT("\nStarting Watcher loop %d...\n"), TotalWatchers);
|
||||
|
||||
while (WatcherPtr->ShouldRun) //Watcher.Runnable->Finished == false
|
||||
{
|
||||
// Wait for notification.
|
||||
//UE_LOG(LogTemp, Log, TEXT("\nWaiting for notification...\n"));
|
||||
|
||||
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles,
|
||||
FALSE, INFINITE);
|
||||
|
||||
if (!WatcherPtr->ShouldRun)
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("\nStop called while sleeping\n"));
|
||||
break;
|
||||
}
|
||||
if (!WatcherDelegate->IsValidLowLevel())
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("\nInvalid Watcher Delegate, exiting watch\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dwWaitStatus)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
|
||||
ReadDirectoryChangesW(dwChangeHandles[0], (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytesReturned, NULL, NULL);
|
||||
//UE_LOG(LogTemp, Warning, TEXT("Received info about: %s"), strFileNotifyInfo->FileName);
|
||||
|
||||
FileString = FString(strFileNotifyInfo[0].FileNameLength, strFileNotifyInfo[0].FileName);
|
||||
|
||||
// A file was created, renamed, or deleted in the directory.
|
||||
// Refresh this directory and restart the notification.
|
||||
|
||||
|
||||
|
||||
WFULambdaRunnable::RunShortLambdaOnGameThread([FullPath, FileString, WatcherDelegate]()
|
||||
{
|
||||
if (WatcherDelegate->GetClass()->ImplementsInterface(UWFUFolderWatchInterface::StaticClass()))
|
||||
{
|
||||
FString FilePath = FString::Printf(TEXT("%s\\%s"), *FullPath, *FileString);
|
||||
((IWFUFolderWatchInterface*)WatcherDelegate)->Execute_OnFileChanged((UObject*)WatcherDelegate, FileString, FilePath);
|
||||
}
|
||||
});
|
||||
if (FindNextChangeNotification(dwChangeHandles[0]) == FALSE)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("\n ERROR: FindNextChangeNotification function failed.\n"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
|
||||
// A directory was created, renamed, or deleted.
|
||||
// Refresh the tree and restart the notification.
|
||||
|
||||
ReadDirectoryChangesW(dwChangeHandles[1], (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytesReturned, NULL, NULL);
|
||||
DirectoryString = FString(strFileNotifyInfo[0].FileNameLength, strFileNotifyInfo[0].FileName);
|
||||
|
||||
WFULambdaRunnable::RunShortLambdaOnGameThread([FullPath, WatcherDelegate, DirectoryString]()
|
||||
{
|
||||
if (WatcherDelegate->GetClass()->ImplementsInterface(UWFUFolderWatchInterface::StaticClass()))
|
||||
{
|
||||
FString ChangedDirectoryPath = FString::Printf(TEXT("%s\\%s"), *FullPath, *DirectoryString);
|
||||
((IWFUFolderWatchInterface*)WatcherDelegate)->Execute_OnDirectoryChanged((UObject*)WatcherDelegate, DirectoryString, ChangedDirectoryPath);
|
||||
}
|
||||
});
|
||||
if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("\n ERROR: FindNextChangeNotification function failed.\n"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
|
||||
// A timeout occurred, this would happen if some value other
|
||||
// than INFINITE is used in the Wait call and no changes occur.
|
||||
// In a single-threaded environment you might not want an
|
||||
// INFINITE wait.
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT("\nNo changes in the timeout period.\n"));
|
||||
break;
|
||||
|
||||
default:
|
||||
UE_LOG(LogTemp, Warning, TEXT("\n ERROR: Unhandled dwWaitStatus.\n"));
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TotalWatchers--;
|
||||
UE_LOG(LogTemp, Log, TEXT("\n Watcher loop stopped, total now: %d.\n"), TotalWatchers);
|
||||
}
|
||||
|
||||
#include "HideWindowsPlatformTypes.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CoreUObject.h"
|
||||
#include "EngineMinimal.h"
|
||||
|
||||
#include "IWindowsFileUtility.h"
|
||||
#include "WFULambdaRunnable.h"
|
||||
#include "WFUFileListInterface.h"
|
||||
#include "WFUFolderWatchInterface.h"
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ModuleManager.h"
|
||||
|
||||
|
||||
/**
|
||||
* The public interface to this module. In most cases, this interface is only public to sibling modules
|
||||
* within this plugin.
|
||||
*/
|
||||
class IWindowsFileUtility : public IModuleInterface
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Singleton-like access to this module's interface. This is just for convenience!
|
||||
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
|
||||
*
|
||||
* @return Returns singleton instance, loading the module on demand if needed
|
||||
*/
|
||||
static inline IWindowsFileUtility& Get()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked< IWindowsFileUtility >("WindowsFileUtility");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
|
||||
*
|
||||
* @return True if the module is loaded and ready to use
|
||||
*/
|
||||
static inline bool IsAvailable()
|
||||
{
|
||||
return FModuleManager::Get().IsModuleLoaded("WindowsFileUtility");
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WFUFileListInterface.generated.h"
|
||||
|
||||
UINTERFACE(MinimalAPI)
|
||||
class UWFUFileListInterface : public UInterface
|
||||
{
|
||||
GENERATED_UINTERFACE_BODY()
|
||||
};
|
||||
|
||||
class WINDOWSFILEUTILITY_API IWFUFileListInterface
|
||||
{
|
||||
GENERATED_IINTERFACE_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Called when a file has been found inside the folder of choice
|
||||
* @param FileName of the found file.
|
||||
* @param Size in bytes of the found file.
|
||||
* @param FilePath of the file that was found
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = FolderWatchEvent)
|
||||
void OnListFileFound(const FString& FileName, int32 ByteCount, const FString& FilePath);
|
||||
|
||||
/**
|
||||
* Called when a directory has been found inside the folder of choice
|
||||
* @param DirectoryName of the found directory.
|
||||
* @param FilePath of the file that was found
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = FolderWatchEvent)
|
||||
void OnListDirectoryFound(const FString& DirectoryName, const FString& FilePath);
|
||||
|
||||
/**
|
||||
* Called when the listing operation has completed.
|
||||
* @param DirectoryPath Path of the directory
|
||||
* @param Files array of files found
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = FolderWatchEvent)
|
||||
void OnListDone(const FString& DirectoryPath, const TArray<FString>& Files, const TArray<FString>& Folders);
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WFUFolderWatchInterface.generated.h"
|
||||
|
||||
UINTERFACE(MinimalAPI)
|
||||
class UWFUFolderWatchInterface : public UInterface
|
||||
{
|
||||
GENERATED_UINTERFACE_BODY()
|
||||
};
|
||||
|
||||
class WINDOWSFILEUTILITY_API IWFUFolderWatchInterface
|
||||
{
|
||||
GENERATED_IINTERFACE_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Called when a file inside the folder has changed
|
||||
* @param FilePath Path of the file that has changed
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = FolderWatchEvent)
|
||||
void OnFileChanged(const FString& FileName, const FString& FilePath);
|
||||
|
||||
/**
|
||||
* Called when a directory inside the folder has changed
|
||||
* @param FilePath Path of the file that has changed
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = FolderWatchEvent)
|
||||
void OnDirectoryChanged(const FString& DirectoryName, const FString& DirectoryPath);
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
Long duration lambda wrapper, which are generally not supported by the taskgraph system. New thread per lambda and they will auto-delete upon
|
||||
completion.
|
||||
*/
|
||||
class WINDOWSFILEUTILITY_API WFULambdaRunnable : public FRunnable
|
||||
{
|
||||
private:
|
||||
/** Thread to run the worker FRunnable on */
|
||||
FRunnableThread* Thread;
|
||||
|
||||
// Used to give each thread a unique stat group
|
||||
static uint64 ThreadNumber;
|
||||
|
||||
//Lambda function pointer
|
||||
TFunction< void()> FunctionPointer;
|
||||
|
||||
// A queued threadpool used to run lambda's in the background. This has lazy initialization and is meant to be used with
|
||||
// - AddLambdaToQueue
|
||||
// - RemoveLAmbdaFromQueue
|
||||
static FQueuedThreadPool* ThreadPool;
|
||||
public:
|
||||
//Constructor / Destructor
|
||||
WFULambdaRunnable(TFunction< void()> InFunction);
|
||||
virtual ~WFULambdaRunnable();
|
||||
|
||||
// Begin FRunnable interface.
|
||||
virtual uint32 Run() override;
|
||||
virtual void Exit() override;
|
||||
// End FRunnable interface
|
||||
|
||||
// Initializes the queued thread pool. This is called lazily when the first task is added to the queue
|
||||
// but can also be called by hand to initialize with a specific number of threads. The default number
|
||||
// of threads is FPlatformMisc::NumberOfIOWorkerThreadsToSpawn() which last I checked was hard-coded
|
||||
// at 4. <NOTE> that if you want to call this by hand, you need to do so before ever calling AddLambdaToQueue.
|
||||
static void InitThreadPool(int32 NumberOfThreads);
|
||||
|
||||
/** Makes sure this thread has stopped properly */
|
||||
void EnsureCompletion();
|
||||
|
||||
// Runs the passed lambda on the background thread, new thread per call
|
||||
static WFULambdaRunnable* RunLambdaOnBackGroundThread(TFunction< void()> InFunction);
|
||||
|
||||
// Adds a lambda to be ran on the queued thread pool. Returns a pointer to IQueuedWork which
|
||||
// can be used to later remove the queued job from the pool assuming it hasn't been processed.
|
||||
static IQueuedWork* AddLambdaToQueue(TFunction< void()> InFunction);
|
||||
|
||||
// Removes a lambda from the thread queue
|
||||
static bool RemoveLambdaFromQueue(IQueuedWork* Work);
|
||||
|
||||
// Runs a short lambda on the game thread via task graph system
|
||||
static FGraphEventRef RunShortLambdaOnGameThread(TFunction< void()> InFunction);
|
||||
|
||||
private:
|
||||
// This was yanked from Engine/Source/Runtime/Core/Public/Async/Async.h (originally called AsyncPool(..)). FQueuedThreadPool doesn't have
|
||||
// much documentation, so using the engine code as reference, pretty much everyone seems to use this templated function to queue up work.
|
||||
// It was modified to return an IQueuedWork instead of a TFuture to be more convenient for actually removing items from the queue.
|
||||
template<typename ResultType>
|
||||
static IQueuedWork* AsyncLambdaPool(FQueuedThreadPool& ThreadPool, TFunction<ResultType()> Function, TFunction<void()> CompletionCallback = TFunction<void()>())
|
||||
{
|
||||
TPromise<ResultType> Promise(MoveTemp(CompletionCallback));
|
||||
TFuture<ResultType> Future = Promise.GetFuture();
|
||||
IQueuedWork* Work = new TAsyncQueuedWork<ResultType>(MoveTemp(Function), MoveTemp(Promise));
|
||||
ThreadPool.AddQueuedWork(Work);
|
||||
return Work;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "WFULambdaRunnable.h"
|
||||
#include "WindowsFileUtilityFunctionLibrary.generated.h"
|
||||
|
||||
//Struct to Track which delegate is watching files
|
||||
struct FWatcher
|
||||
{
|
||||
UObject* Delegate;
|
||||
|
||||
FString Path;
|
||||
|
||||
WFULambdaRunnable* Runnable = nullptr;
|
||||
|
||||
FThreadSafeBool ShouldRun = true;
|
||||
|
||||
};
|
||||
|
||||
inline bool operator==(const FWatcher& lhs, const FWatcher& rhs)
|
||||
{
|
||||
return lhs.Delegate == rhs.Delegate;
|
||||
}
|
||||
|
||||
UCLASS(ClassGroup = WindowsFileUtility, Blueprintable)
|
||||
class WINDOWSFILEUTILITY_API UWindowsFileUtilityFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static bool DoesFileExist(const FString& FullPath);
|
||||
|
||||
/*Expects full path including name. you can use this function to rename files.*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static bool MoveFileTo(const FString& From, const FString& To);
|
||||
|
||||
/*Expects full path including folder name.*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static bool CreateDirectoryAt(const FString& FullPath);
|
||||
|
||||
/*Deletes file (not directory). Expects full path.*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static bool DeleteFileAt(const FString& FullPath);
|
||||
|
||||
/*Deletes empty folders only. Expects full path.*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static bool DeleteEmptyFolder(const FString& FullPath);
|
||||
|
||||
/*Dangerous function, not exposed to blueprint. */
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static bool DeleteFolderRecursively(const FString& FullPath);
|
||||
|
||||
/** Watch a folder for change. WatcherDelegate should respond to FolderWatchInterface*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static void WatchFolder(const FString& FullPath, UObject* WatcherDelegate);
|
||||
|
||||
/** Stop watching a folder for change. WatcherDelegate should respond to FolderWatchInterface*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static void StopWatchingFolder(const FString& FullPath, UObject* WatcherDelegate);
|
||||
|
||||
/** List the contents, expects UFileListInterface*/
|
||||
UFUNCTION(BlueprintCallable, Category = WindowsFileUtility)
|
||||
static void ListContentsOfFolder(const FString& FullPath, UObject* ListDelegate);
|
||||
|
||||
//Convenience C++ callback
|
||||
static void ListContentsOfFolderToCallback(const FString& FullPath, TFunction<void(const TArray<FString>&, const TArray<FString>&)> OnListCompleteCallback);
|
||||
|
||||
//Todo: add watch folder with threadsafe boolean passthrough
|
||||
//static void ListContentsOfFolderToCallback(const FString& FullPath, TFunction<void(const TArray<FString>&, const TArray<FString>&)> OnListCompleteCallback);
|
||||
|
||||
private:
|
||||
static void WatchFolderOnBgThread(const FString& FullPath, const FWatcher* Watcher);
|
||||
static TMap<FString, TArray<FWatcher>> Watchers;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class WindowsFileUtility : ModuleRules
|
||||
{
|
||||
public WindowsFileUtility(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"WindowsFileUtility/Public"
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"WindowsFileUtility/Private",
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "7zpp.h"
|
||||
#include "ListCallback.h"
|
||||
#include "ProgressCallback.h"
|
||||
|
||||
using namespace SevenZip;
|
||||
/**
|
||||
* Forwards events from the 7zpp library to the UE4 listener.
|
||||
*/
|
||||
class ZIPUTILITY_API SevenZipCallbackHandler : public ListCallback, public ProgressCallback
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void OnProgress(const TString& archivePath, uint64 bytes) override;
|
||||
virtual void OnDone(const TString& archivePath) override;
|
||||
virtual void OnFileDone(const TString& archivePath, const TString& filePath, uint64 bytes) override;
|
||||
virtual void OnStartWithTotal(const TString& archivePath, unsigned __int64 totalBytes) override;
|
||||
virtual void OnFileFound(const TString& archivePath, const TString& filePath, int size) override;
|
||||
virtual void OnListingDone(const TString& archivePath) override;
|
||||
virtual bool OnCheckBreak() override;
|
||||
|
||||
uint64 BytesLeft = 0;
|
||||
uint64 TotalBytes = 0;
|
||||
UObject* ProgressDelegate = nullptr;
|
||||
FThreadSafeBool bCancelOperation = false;
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include "ZipUtilityInterface.h"
|
||||
#include "ZipOperation.h"
|
||||
#include "ZipFileFunctionLibrary.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum ZipUtilityCompressionFormat
|
||||
{
|
||||
COMPRESSION_FORMAT_UNKNOWN,
|
||||
COMPRESSION_FORMAT_SEVEN_ZIP,
|
||||
COMPRESSION_FORMAT_ZIP,
|
||||
COMPRESSION_FORMAT_GZIP,
|
||||
COMPRESSION_FORMAT_BZIP2,
|
||||
COMPRESSION_FORMAT_RAR,
|
||||
COMPRESSION_FORMAT_TAR,
|
||||
COMPRESSION_FORMAT_ISO,
|
||||
COMPRESSION_FORMAT_CAB,
|
||||
COMPRESSION_FORMAT_LZMA,
|
||||
COMPRESSION_FORMAT_LZMA86
|
||||
};
|
||||
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum ZipUtilityCompressionLevel
|
||||
{
|
||||
COMPRESSION_LEVEL_NONE,
|
||||
COMPRESSION_LEVEL_FAST,
|
||||
COMPRESSION_LEVEL_NORMAL
|
||||
};
|
||||
|
||||
class SevenZipCallbackHandler;
|
||||
class UZipFileFunctionInternalCallback;
|
||||
|
||||
/**
|
||||
A blueprint function library encapsulating all zip operations for both C++ and blueprint use.
|
||||
For some operations a UZipOperation object may be returned, if you're interested in it, ensure
|
||||
you guard it from garbage collection by e.g. storing it as a UProperty, otherwise you may safely
|
||||
ignore it.
|
||||
*/
|
||||
|
||||
UCLASS(ClassGroup = ZipUtility, Blueprintable)
|
||||
class ZIPUTILITY_API UZipFileFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
~UZipFileFunctionLibrary();
|
||||
|
||||
/* Unzips file in archive containing Name via ListFilesInArchive/UnzipFiles. Automatically determines compression if unknown. Calls ZipUtilityInterface progress events. */
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static bool UnzipFileNamed(const FString& archivePath, const FString& Name, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Unzips file in archive containing Name at destination path via ListFilesInArchive/UnzipFilesTo. Automatically determines compression if unknown. Calls ZipUtilityInterface progress events. */
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static bool UnzipFileNamedTo(const FString& archivePath, const FString& Name, const FString& destinationPath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Unzips the given file indexes in archive at destination path. Automatically determines compression if unknown. Calls ZipUtilityInterface progress events. */
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static UZipOperation* UnzipFilesTo(const TArray<int32> fileIndices, const FString& archivePath, const FString& destinationPath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Unzips the given file indexes in archive at current path. Automatically determines compression if unknown. Calls ZipUtilityInterface progress events. */
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static UZipOperation* UnzipFiles(const TArray<int32> fileIndices, const FString& ArchivePath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Unzips archive at current path. Automatically determines compression if unknown. Calls ZipUtilityInterface progress events. */
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static UZipOperation* Unzip(const FString& ArchivePath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat Format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Lambda C++ simple variant*/
|
||||
static UZipOperation* UnzipWithLambda( const FString& ArchivePath,
|
||||
TFunction<void()> OnDoneCallback,
|
||||
TFunction<void(float)> OnProgressCallback = nullptr,
|
||||
ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Unzips archive at destination path. Automatically determines compression if unknown. Calls ZipUtilityInterface progress events. */
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static UZipOperation* UnzipTo(const FString& ArchivePath, const FString& DestinationPath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
/* Compresses the file or folder given at path and places the file in the same root folder. Calls ZipUtilityInterface progress events. Not all formats are supported for compression.*/
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static UZipOperation* Zip( const FString& FileOrFolderPath,
|
||||
UObject* ZipUtilityInterfaceDelegate,
|
||||
ZipUtilityCompressionFormat Format = COMPRESSION_FORMAT_SEVEN_ZIP,
|
||||
TEnumAsByte<ZipUtilityCompressionLevel> Level = COMPRESSION_LEVEL_NORMAL);
|
||||
|
||||
/* Lambda C++ simple variant*/
|
||||
static UZipOperation* ZipWithLambda( const FString& ArchivePath,
|
||||
TFunction<void()> OnDoneCallback,
|
||||
TFunction<void(float)> OnProgressCallback = nullptr,
|
||||
ZipUtilityCompressionFormat Format = COMPRESSION_FORMAT_UNKNOWN,
|
||||
TEnumAsByte<ZipUtilityCompressionLevel> Level = COMPRESSION_LEVEL_NORMAL);
|
||||
|
||||
|
||||
/*Queries Archive content list, calls ZipUtilityInterface list events (OnFileFound)*/
|
||||
UFUNCTION(BlueprintCallable, Category = ZipUtility)
|
||||
static bool ListFilesInArchive(const FString& ArchivePath, UObject* ZipUtilityInterfaceDelegate, ZipUtilityCompressionFormat format = COMPRESSION_FORMAT_UNKNOWN);
|
||||
|
||||
static FGraphEventRef RunLambdaOnGameThread(TFunction< void()> InFunction);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include "Object.h"
|
||||
#include "ZipOperation.generated.h"
|
||||
|
||||
class SevenZipCallbackHandler;
|
||||
/**
|
||||
* Used to track a zip/unzip operation on the WFULambdaRunnable ThreadPool and allows the ability to terminate the
|
||||
* operation early.
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class ZIPUTILITY_API UZipOperation : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UZipOperation();
|
||||
|
||||
// Stops this zip/unzip if it is still valid. This stop event can occur in two places:
|
||||
// 1. The ThreadPool queue, if it can be stopped here then the operation has not yet started.
|
||||
// 2. The SevenZip layer, once the operation has started, it can be canceled while still running.
|
||||
// Note that calling this carries no guarantees of a successful stop, the end result might be one of:
|
||||
// * The file still got extracted (you were too late)
|
||||
// * The file was never extracted (caught it on time)
|
||||
// * The file was created but is of zero size (oops)
|
||||
// * The file was created, is of non-zero size but is not all there (cut off in the middle)
|
||||
// So, it could be a good idea to do some file housekeeping afterward.
|
||||
UFUNCTION(BlueprintCallable, Category = "Zip Operation")
|
||||
void StopOperation();
|
||||
|
||||
// Set the callback handler
|
||||
void SetCallbackHandler(SevenZipCallbackHandler* Handler);
|
||||
|
||||
// Set the queued work
|
||||
void SetThreadPoolWorker(IQueuedWork* Work);
|
||||
|
||||
private:
|
||||
// A pointer to the callback for this operation. Once the operation completes, this
|
||||
// pointer will become invalid.
|
||||
SevenZipCallbackHandler* CallbackHandler;
|
||||
|
||||
// The work that was queued on the async threadpool in WFULambdaRunnable
|
||||
IQueuedWork* ThreadPoolWork;
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ZipUtilityInterface.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum EZipUtilityCompletionState
|
||||
{
|
||||
SUCCESS,
|
||||
FAILURE_NOT_FOUND,
|
||||
FAILURE_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
UINTERFACE(MinimalAPI)
|
||||
class UZipUtilityInterface : public UInterface
|
||||
{
|
||||
GENERATED_UINTERFACE_BODY()
|
||||
};
|
||||
|
||||
class ZIPUTILITY_API IZipUtilityInterface
|
||||
{
|
||||
GENERATED_IINTERFACE_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Called during process as it completes. Currently updates on per file progress.
|
||||
* @param percentage - percentage done
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = ZipUtilityProgressEvents)
|
||||
void OnProgress(const FString& archive, float percentage, int32 bytes);
|
||||
|
||||
/**
|
||||
* Called when whole process is complete (e.g. unzipping completed on archive)
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = ZipUtilityProgressEvents)
|
||||
void OnDone(const FString& archive, EZipUtilityCompletionState CompletionState);
|
||||
|
||||
/**
|
||||
* Called at beginning of process (NB this only supports providing size information for up to 2gb) TODO: fix 32bit BP size issue
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = ZipUtilityProgressEvents)
|
||||
void OnStartProcess(const FString& archive, int32 bytes);
|
||||
|
||||
/**
|
||||
* Called when file process is complete
|
||||
* @param path - path of the file that finished
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = ZipUtilityProgressEvents)
|
||||
void OnFileDone(const FString& archive, const FString& file);
|
||||
|
||||
|
||||
/**
|
||||
* Called when a file is found in the archive (e.g. listing the entries in the archive)
|
||||
* @param path - path of file
|
||||
* @param size - compressed size
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category = ZipUtilityListEvents)
|
||||
void OnFileFound(const FString& archive, const FString& file, int32 size);
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ModuleManager.h"
|
||||
|
||||
class ZIPUTILITY_API FZipUtilityModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
//CHN:
|
||||
//Maybe we need to use a public interface to fetch the module methods for C++? get a reference to zipfile etc
|
||||
|
||||
/**
|
||||
* Singleton-like access to this module's interface. This is just for convenience!
|
||||
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
|
||||
*
|
||||
* @return Returns singleton instance, loading the module on demand if needed
|
||||
*/
|
||||
static inline FZipUtilityModule& Get()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked< FZipUtilityModule >("ZipUtility");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
|
||||
*
|
||||
* @return True if the module is loaded and ready to use
|
||||
*/
|
||||
static inline bool IsAvailable()
|
||||
{
|
||||
return FModuleManager::Get().IsModuleLoaded("ZipUtility");
|
||||
}
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
102
Plugins/ZipUtility-ue4/Source/ZipUtility/ZipUtility.Build.cs
Normal file
102
Plugins/ZipUtility-ue4/Source/ZipUtility/ZipUtility.Build.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class ZipUtility : ModuleRules
|
||||
{
|
||||
private string ThirdPartyPath
|
||||
{
|
||||
get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "../../ThirdParty/")); }
|
||||
}
|
||||
private string SevenZppPath
|
||||
{
|
||||
get { return Path.GetFullPath(Path.Combine(ThirdPartyPath, "7zpp")); }
|
||||
}
|
||||
|
||||
private string ATLPath
|
||||
{
|
||||
get { return "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.13.26128/atlmfc"; }
|
||||
}
|
||||
|
||||
public ZipUtility(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
bEnableExceptions = true;
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"ZipUtility/Public"
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"ZipUtility/Private",
|
||||
Path.Combine(SevenZppPath, "Include"),
|
||||
Path.Combine(ATLPath, "include"),
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"WindowsFileUtility"
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"Projects"
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
|
||||
LoadLib(Target);
|
||||
}
|
||||
public bool LoadLib(ReadOnlyTargetRules Target)
|
||||
{
|
||||
bool isLibrarySupported = false;
|
||||
|
||||
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
|
||||
{
|
||||
isLibrarySupported = true;
|
||||
|
||||
string PlatformSubPath = (Target.Platform == UnrealTargetPlatform.Win64) ? "Win64" : "Win32";
|
||||
string LibrariesPath = Path.Combine(SevenZppPath, "Lib");
|
||||
string DLLPath = Path.Combine(SevenZppPath, "dll");
|
||||
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, PlatformSubPath, "atls.lib"));
|
||||
PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, PlatformSubPath, "7zpp_u.lib"));
|
||||
PublicLibraryPaths.Add(Path.Combine(LibrariesPath, PlatformSubPath));
|
||||
|
||||
PublicDelayLoadDLLs.Add("7z.dll");
|
||||
RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(DLLPath, PlatformSubPath, "7z.dll")));
|
||||
}
|
||||
|
||||
if (isLibrarySupported)
|
||||
{
|
||||
// Include path
|
||||
//PublicIncludePaths.Add(Path.Combine(SevenZppPath, "Include"));
|
||||
}
|
||||
|
||||
return isLibrarySupported;
|
||||
}
|
||||
}
|
||||
46
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/7zpp.h
vendored
Normal file
46
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/7zpp.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "ListCallback.h"
|
||||
#include "ProgressCallback.h"
|
||||
|
||||
#include "PreWindowsApi.h"
|
||||
#include "AllowWindowsPlatformTypes.h"
|
||||
#include "AllowWindowsPlatformAtomics.h"
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4191)
|
||||
#pragma warning(disable: 4996)
|
||||
|
||||
#ifndef DeleteFile
|
||||
#define DeleteFile DeleteFileW
|
||||
#endif
|
||||
#ifndef MoveFile
|
||||
#define MoveFile MoveFileW
|
||||
#endif
|
||||
|
||||
#ifndef LoadString
|
||||
#define LoadString LoadStringW
|
||||
#endif
|
||||
|
||||
#ifndef GetMessage
|
||||
#define GetMessage GetMessageW
|
||||
#endif
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <sphelper.h>
|
||||
|
||||
#undef DeleteFile
|
||||
#undef MoveFile
|
||||
|
||||
#include "SevenZipCompressor.h"
|
||||
#include "SevenZipExtractor.h"
|
||||
#include "SevenZipLister.h"
|
||||
|
||||
#include "HideWindowsPlatformAtomics.h"
|
||||
#include "HideWindowsPlatformTypes.h"
|
||||
#include "PostWindowsApi.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
// Version of this library
|
||||
#define SEVENZIP_VERSION L"0.2.0-20160117.1"
|
||||
#define SEVENZIP_BRANCH L"master"
|
||||
31
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/CompressionFormat.h
vendored
Normal file
31
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/CompressionFormat.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Enum.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
struct CompressionFormat
|
||||
{
|
||||
enum _Enum
|
||||
{
|
||||
Unknown,
|
||||
SevenZip,
|
||||
Zip,
|
||||
GZip,
|
||||
BZip2,
|
||||
Rar,
|
||||
Tar,
|
||||
Iso,
|
||||
Cab,
|
||||
Lzma,
|
||||
Lzma86
|
||||
};
|
||||
|
||||
typedef intl::EnumerationDefinitionNoStrings _Definition;
|
||||
typedef intl::EnumerationValue< _Enum, _Definition, Unknown > _Value;
|
||||
};
|
||||
|
||||
typedef CompressionFormat::_Value CompressionFormatEnum;
|
||||
}
|
||||
23
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/CompressionLevel.h
vendored
Normal file
23
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/CompressionLevel.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Enum.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
struct CompressionLevel
|
||||
{
|
||||
enum _Enum
|
||||
{
|
||||
None,
|
||||
Fast,
|
||||
Normal
|
||||
};
|
||||
|
||||
typedef intl::EnumerationDefinitionNoStrings _Definition;
|
||||
typedef intl::EnumerationValue< _Enum, _Definition, Normal > _Value;
|
||||
};
|
||||
|
||||
typedef CompressionLevel::_Value CompressionLevelEnum;
|
||||
}
|
||||
193
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/Enum.h
vendored
Normal file
193
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/Enum.h
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
//
|
||||
// ###### To create an enum call MyType with string support: ######
|
||||
//
|
||||
//// MyType.h
|
||||
//struct MyType
|
||||
//{
|
||||
// enum _Enum
|
||||
// {
|
||||
// Unknown,
|
||||
// Foo,
|
||||
// Bar
|
||||
// };
|
||||
//
|
||||
// struct _Definition : public EnumerationDefinition< _Enum, _Definition > { static StringValue Strings[]; };
|
||||
// typedef EnumerationValue< _Enum, _Definition, Unknown > _Value;
|
||||
//};
|
||||
//
|
||||
//typedef MyType::_Value MyTypeEnum;
|
||||
//
|
||||
//
|
||||
//// MyType.cpp
|
||||
//#include "MyType.h"
|
||||
//
|
||||
//MyType::_Definition::StringValue MyType::_Definition::Strings[] =
|
||||
//{
|
||||
// { MyType::Foo, _T( "Foo" ) },
|
||||
// { MyType::Bar, _T( "Bar" ) },
|
||||
// { MyType::Unknown, NULL }
|
||||
//};
|
||||
//
|
||||
//
|
||||
// ###### To create an enum call MyType without string support: ######
|
||||
//
|
||||
//// MyType.h
|
||||
//struct MyType
|
||||
//{
|
||||
// enum _Enum
|
||||
// {
|
||||
// Unknown,
|
||||
// Foo,
|
||||
// Bar
|
||||
// };
|
||||
//
|
||||
// typedef EnumerationDefinitionNoStrings _Definition;
|
||||
// typedef EnumerationValue< _Enum, _Definition, Unknown > _Value;
|
||||
//};
|
||||
//
|
||||
//typedef MyType::_Value MyTypeEnum;
|
||||
//
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
namespace intl
|
||||
{
|
||||
template < typename TEnum, class DerivedDef >
|
||||
struct EnumerationDefinition
|
||||
{
|
||||
struct StringValue
|
||||
{
|
||||
TEnum value;
|
||||
const TCHAR* string;
|
||||
};
|
||||
|
||||
static TEnum Parse( const TString& string, const TEnum defaultValue )
|
||||
{
|
||||
const StringValue* it = DerivedDef::Strings;
|
||||
for (; it->string != NULL; ++it )
|
||||
{
|
||||
if ( string.Compare( it->string ) == 0 )
|
||||
{
|
||||
return it->value;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
static TString Format( const TEnum& value )
|
||||
{
|
||||
const StringValue* it = DerivedDef::Strings;
|
||||
for (; it->string != NULL; ++it )
|
||||
{
|
||||
if ( value == it->value )
|
||||
{
|
||||
return it->string;
|
||||
}
|
||||
}
|
||||
return TString();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct EnumerationDefinitionNoStrings {};
|
||||
|
||||
|
||||
template < typename TEnum, class TEnumClass, TEnum DefaultValue >
|
||||
class EnumerationValue
|
||||
{
|
||||
private:
|
||||
|
||||
typedef typename EnumerationValue< TEnum, TEnumClass, DefaultValue > ThisClass;
|
||||
|
||||
TEnum m_value;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename TEnum Enum;
|
||||
|
||||
EnumerationValue():
|
||||
m_value( DefaultValue )
|
||||
{}
|
||||
|
||||
EnumerationValue( const TEnum& value ):
|
||||
m_value( value )
|
||||
{}
|
||||
|
||||
static ThisClass Parse( const TString& string )
|
||||
{
|
||||
return ThisClass( TEnumClass::Parse( string, DefaultValue ) );
|
||||
}
|
||||
|
||||
const TEnum& GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
TString GetString() const
|
||||
{
|
||||
return TEnumClass::Format( m_value );
|
||||
}
|
||||
|
||||
operator TEnum() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
ThisClass& operator=( const TEnum& value )
|
||||
{
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==( const ThisClass& that ) const
|
||||
{
|
||||
return that.m_value == m_value;
|
||||
}
|
||||
|
||||
bool operator!=( const ThisClass& that ) const
|
||||
{
|
||||
return !operator==( that );
|
||||
}
|
||||
|
||||
bool operator==( const TEnum& value ) const
|
||||
{
|
||||
return value == m_value;
|
||||
}
|
||||
|
||||
bool operator!=( const TEnum& value ) const
|
||||
{
|
||||
return !operator==( value );
|
||||
}
|
||||
|
||||
bool operator< ( const ThisClass& that ) const
|
||||
{
|
||||
return m_value < that.m_value;
|
||||
}
|
||||
|
||||
// Bit field members
|
||||
void AddFlag( const TEnum& value )
|
||||
{
|
||||
*reinterpret_cast< int* >( &m_value ) |= static_cast< int >( value );
|
||||
}
|
||||
|
||||
void RemoveFlag( const TEnum& value )
|
||||
{
|
||||
*reinterpret_cast< int* >( &m_value ) &= ~static_cast< int >( value );
|
||||
}
|
||||
|
||||
bool HasFlag( const TEnum& value ) const
|
||||
{
|
||||
return ( m_value & value ) == value;
|
||||
}
|
||||
|
||||
bool HasAnyFlag( const TEnum& valueCombo ) const
|
||||
{
|
||||
return ( m_value & valueCombo ) != 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
24
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/FileInfo.h
vendored
Normal file
24
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/FileInfo.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
namespace intl
|
||||
{
|
||||
struct FileInfo
|
||||
{
|
||||
TString FileName;
|
||||
FILETIME LastWriteTime;
|
||||
FILETIME CreationTime;
|
||||
FILETIME LastAccessTime;
|
||||
ULONGLONG Size;
|
||||
UINT Attributes;
|
||||
bool IsDirectory;
|
||||
};
|
||||
|
||||
struct FilePathInfo : public FileInfo
|
||||
{
|
||||
TString FilePath;
|
||||
};
|
||||
}
|
||||
}
|
||||
23
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/ListCallback.h
vendored
Normal file
23
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/ListCallback.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "SevenZipLibrary.h"
|
||||
#include "CompressionFormat.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class ListCallback
|
||||
{
|
||||
public:
|
||||
/*
|
||||
Called for each file found in the archive. Size in bytes.
|
||||
*/
|
||||
virtual void OnFileFound(const TString& archivePath, const TString& filePath, int size) {}
|
||||
|
||||
/*
|
||||
Called when all the files have been listed
|
||||
*/
|
||||
virtual void OnListingDone(const TString& archivePath) {}
|
||||
};
|
||||
}
|
||||
40
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/ProgressCallback.h
vendored
Normal file
40
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/ProgressCallback.h
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "SevenZipLibrary.h"
|
||||
#include "CompressionFormat.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class ProgressCallback
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
Called at beginning
|
||||
*/
|
||||
virtual void OnStartWithTotal(const TString& archivePath, unsigned __int64 totalBytes) = 0;
|
||||
|
||||
/*
|
||||
Called Whenever progress has updated with a bytes complete
|
||||
*/
|
||||
virtual void OnProgress(const TString& archivePath, unsigned __int64 bytesCompleted) = 0;
|
||||
|
||||
|
||||
/*
|
||||
Called When progress has reached 100%
|
||||
*/
|
||||
virtual void OnDone(const TString& archivePath) = 0;
|
||||
|
||||
/*
|
||||
Called When single file progress has reached 100%, returns the filepath that completed
|
||||
*/
|
||||
virtual void OnFileDone(const TString& archivePath, const TString& filePath, unsigned __int64 bytesCompleted) = 0;
|
||||
|
||||
/*
|
||||
Called to determine if it's time to abort the zip operation. Return true to abort the current operation.
|
||||
*/
|
||||
virtual bool OnCheckBreak() = 0;
|
||||
};
|
||||
}
|
||||
15
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenString.h
vendored
Normal file
15
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenString.h
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <tchar.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
typedef std::wstring TString;
|
||||
#else
|
||||
typedef std::string TString;
|
||||
#endif
|
||||
}
|
||||
48
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipArchive.h
vendored
Normal file
48
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipArchive.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "SevenZipLibrary.h"
|
||||
#include <atlbase.h>
|
||||
#include "FileInfo.h"
|
||||
#include "CompressionFormat.h"
|
||||
#include "CompressionLevel.h"
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class SevenZipArchive
|
||||
{
|
||||
public:
|
||||
SevenZipArchive(const SevenZipLibrary& library, const TString& archivePath);
|
||||
virtual ~SevenZipArchive();
|
||||
|
||||
virtual bool ReadInArchiveMetadata();
|
||||
|
||||
virtual void SetCompressionFormat(const CompressionFormatEnum& format);
|
||||
virtual CompressionFormatEnum GetCompressionFormat();
|
||||
|
||||
virtual void SetCompressionLevel(const CompressionLevelEnum& level);
|
||||
virtual CompressionLevelEnum GetCompressionLevel();
|
||||
|
||||
virtual bool DetectCompressionFormat();
|
||||
|
||||
virtual size_t GetNumberOfItems();
|
||||
virtual std::vector<TString> GetItemsNames();
|
||||
virtual std::vector<size_t> GetOrigSizes();
|
||||
|
||||
protected:
|
||||
bool m_ReadMetadata = false;
|
||||
bool m_OverrideCompressionFormat = false;
|
||||
const SevenZipLibrary& m_library;
|
||||
TString m_archivePath;
|
||||
CompressionFormatEnum m_compressionFormat;
|
||||
CompressionLevelEnum m_compressionLevel;
|
||||
size_t m_numberofitems = 0;
|
||||
std::vector<TString> m_itemnames;
|
||||
std::vector<size_t> m_origsizes;
|
||||
|
||||
private:
|
||||
bool pri_GetNumberOfItems();
|
||||
bool pri_GetItemsNames();
|
||||
bool pri_DetectCompressionFormat(CompressionFormatEnum & format);
|
||||
bool pri_DetectCompressionFormat();
|
||||
};
|
||||
}
|
||||
43
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipCompressor.h
vendored
Normal file
43
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipCompressor.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <atlbase.h>
|
||||
#include "SevenZipLibrary.h"
|
||||
#include "SevenZipArchive.h"
|
||||
#include "FileInfo.h"
|
||||
#include "CompressionFormat.h"
|
||||
#include "CompressionLevel.h"
|
||||
#include "ProgressCallback.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class SevenZipCompressor : public SevenZipArchive
|
||||
{
|
||||
public:
|
||||
|
||||
SevenZipCompressor( const SevenZipLibrary& library, const TString& archivePath );
|
||||
virtual ~SevenZipCompressor();
|
||||
|
||||
// Includes the last directory as the root in the archive, e.g. specifying "C:\Temp\MyFolder"
|
||||
// makes "MyFolder" the single root item in archive with the files within it included.
|
||||
virtual bool CompressDirectory( const TString& directory, ProgressCallback* callback, bool includeSubdirs = true);
|
||||
|
||||
// Excludes the last directory as the root in the archive, its contents are at root instead. E.g.
|
||||
// specifying "C:\Temp\MyFolder" make the files in "MyFolder" the root items in the archive.
|
||||
virtual bool CompressFiles( const TString& directory, const TString& searchFilter, ProgressCallback* callback, bool includeSubdirs = true );
|
||||
virtual bool CompressAllFiles( const TString& directory, ProgressCallback* callback, bool includeSubdirs = true );
|
||||
|
||||
// Compress just this single file as the root item in the archive.
|
||||
virtual bool CompressFile( const TString& filePath, ProgressCallback* callback);
|
||||
|
||||
private:
|
||||
TString m_outputPath; //the final compression result compression path. Used for tracking in callbacks
|
||||
CComPtr< IStream > OpenArchiveStream();
|
||||
bool FindAndCompressFiles( const TString& directory, const TString& searchPattern,
|
||||
const TString& pathPrefix, bool recursion, ProgressCallback* callback);
|
||||
bool CompressFilesToArchive(const TString& pathPrefix, const std::vector< intl::FilePathInfo >& filePaths, ProgressCallback* callback);
|
||||
bool SetCompressionProperties( IUnknown* outArchive );
|
||||
};
|
||||
}
|
||||
30
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipException.h
vendored
Normal file
30
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipException.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <exception>
|
||||
#include "SevenString.h"
|
||||
#include "AllowWindowsPlatformTypes.h"
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
TString StrFmt(const TCHAR* format, ...);
|
||||
TString GetWinErrMsg(const TString& contextMessage, DWORD lastError);
|
||||
TString GetCOMErrMsg(const TString& contextMessage, HRESULT lastError);
|
||||
|
||||
class SevenZipException
|
||||
{
|
||||
protected:
|
||||
|
||||
TString m_message;
|
||||
|
||||
public:
|
||||
|
||||
SevenZipException();
|
||||
SevenZipException(const TString& message);
|
||||
virtual ~SevenZipException();
|
||||
|
||||
const TString& GetMessage() const;
|
||||
};
|
||||
}
|
||||
|
||||
#include "HideWindowsPlatformTypes.h"
|
||||
25
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipExtractor.h
vendored
Normal file
25
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipExtractor.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "SevenZipLibrary.h"
|
||||
#include "SevenZipArchive.h"
|
||||
#include "CompressionFormat.h"
|
||||
#include "ProgressCallback.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class SevenZipExtractor : public SevenZipArchive
|
||||
{
|
||||
public:
|
||||
|
||||
SevenZipExtractor( const SevenZipLibrary& library, const TString& archivePath );
|
||||
virtual ~SevenZipExtractor();
|
||||
|
||||
virtual bool ExtractArchive(const TString& directory, ProgressCallback* callback);
|
||||
virtual bool ExtractFilesFromArchive(const unsigned int* fileIndices, const unsigned int numberFiles, const TString& directory, ProgressCallback* callback);
|
||||
private:
|
||||
|
||||
bool ExtractFilesFromArchive(const CComPtr< IStream >& archiveStream, const unsigned int* fileIndices, const unsigned int numberFiles, const TString& directory, ProgressCallback* callback);
|
||||
};
|
||||
}
|
||||
28
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipLibrary.h
vendored
Normal file
28
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipLibrary.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "SevenZipException.h"
|
||||
#include "CompressionFormat.h"
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class SevenZipLibrary
|
||||
{
|
||||
private:
|
||||
|
||||
typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID* clsID, const GUID* interfaceID, void** outObject );
|
||||
|
||||
HMODULE m_dll;
|
||||
CreateObjectFunc m_func;
|
||||
|
||||
public:
|
||||
|
||||
SevenZipLibrary();
|
||||
~SevenZipLibrary();
|
||||
|
||||
bool Load();
|
||||
bool Load( const TString& libraryPath );
|
||||
void Free();
|
||||
|
||||
bool CreateObject( const GUID& clsID, const GUID& interfaceID, void** outObject ) const;
|
||||
};
|
||||
}
|
||||
24
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipLister.h
vendored
Normal file
24
Plugins/ZipUtility-ue4/ThirdParty/7zpp/Include/SevenZipLister.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "SevenZipLibrary.h"
|
||||
#include "SevenZipArchive.h"
|
||||
#include "CompressionFormat.h"
|
||||
#include "ListCallback.h"
|
||||
|
||||
|
||||
namespace SevenZip
|
||||
{
|
||||
class SevenZipLister : public SevenZipArchive
|
||||
{
|
||||
public:
|
||||
TString m_archivePath;
|
||||
|
||||
SevenZipLister( const SevenZipLibrary& library, const TString& archivePath );
|
||||
virtual ~SevenZipLister();
|
||||
|
||||
virtual bool ListArchive(ListCallback* callback);
|
||||
|
||||
private:
|
||||
bool ListArchive(const CComPtr< IStream >& archiveStream, ListCallback* callback);
|
||||
};
|
||||
}
|
||||
56
Plugins/ZipUtility-ue4/ThirdParty/7zpp/dll/License.txt
vendored
Normal file
56
Plugins/ZipUtility-ue4/ThirdParty/7zpp/dll/License.txt
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
7-Zip
|
||||
~~~~~
|
||||
License for use and distribution
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
7-Zip Copyright (C) 1999-2015 Igor Pavlov.
|
||||
|
||||
Licenses for files are:
|
||||
|
||||
1) 7z.dll: GNU LGPL + unRAR restriction
|
||||
2) 7za.dll: GNU LGPL
|
||||
|
||||
The GNU LGPL + unRAR restriction means that you must follow both
|
||||
GNU LGPL rules and unRAR restriction rules.
|
||||
|
||||
|
||||
Note:
|
||||
You can use 7-Zip on any computer, including a computer in a commercial
|
||||
organization. You don't need to register or pay for 7-Zip.
|
||||
|
||||
|
||||
GNU LGPL information
|
||||
--------------------
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You can receive a copy of the GNU Lesser General Public License from
|
||||
http://www.gnu.org/
|
||||
|
||||
|
||||
unRAR restriction
|
||||
-----------------
|
||||
|
||||
The decompression engine for RAR archives was developed using source
|
||||
code of unRAR program.
|
||||
All copyrights to original unRAR code are owned by Alexander Roshal.
|
||||
|
||||
The license for original unRAR code has the following restriction:
|
||||
|
||||
The unRAR sources cannot be used to re-create the RAR compression algorithm,
|
||||
which is proprietary. Distribution of modified unRAR sources in separate form
|
||||
or as a part of other software is permitted, provided that it is clearly
|
||||
stated in the documentation and source comments that the code may
|
||||
not be used to develop a RAR (WinRAR) compatible archiver.
|
||||
|
||||
|
||||
--
|
||||
Igor Pavlov
|
||||
26
Plugins/ZipUtility-ue4/ZipUtility.uplugin
Normal file
26
Plugins/ZipUtility-ue4/ZipUtility.uplugin
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 2,
|
||||
"VersionName": "0.4.3",
|
||||
"FriendlyName": "ZipUtility",
|
||||
"Description": "",
|
||||
"Category": "Utility",
|
||||
"CreatedBy": "Getnamo",
|
||||
"CreatedByURL": "http://www.getnamo.com",
|
||||
"DocsURL": "https://github.com/getnamo/ZipUtility-ue4",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "",
|
||||
"EnabledByDefault": true,
|
||||
"CanContainContent": false,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "ZipUtility",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"WhitelistPlatforms": [
|
||||
"Win64",
|
||||
"Win32"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user