언리얼로 파일 관리 시스템을 만들었다.
좌측은 폴더 뷰어, 우측은 파일 뷰어다. 하단의 버튼은 좌측부터 폴더 삭제, 폴더 이름변경, 폴더 추가, 파일 복사, 파일 삭제, 파일 이름변경, 파일 업로드이다.
1. 파일 업로드
해당 기능을 위해 winAPI를 사용했다.
이전 포스팅인 CopyFileEx 을 사용해 업로드 진행 상황을 표시한다.
주의할 점은 콜백 함수를 전역함수로 해야한다. 멤버 함수로 만들면 랜더링 쓰레드가 멈춘다.
.hpp
더보기
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/Button.h"
#include "Components/TextBlock.h"
#include "UploadFile.generated.h"
class UFileUpload_Thread;
class ULibraryManager;
UCLASS()
class LOADSCENEPLUGIN_API UUploadFile : public UUserWidget
{
GENERATED_BODY()
public:
UUploadFile(const FObjectInitializer& obj);
virtual void NativeConstruct() override;
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
UFUNCTION()
void OnClicked_Btn_Yes();
UFUNCTION()
void OnClicked_Btn_No();
UFUNCTION()
void OnVisibilityChanged_UploadFile(ESlateVisibility InVisibility);
void FileUploading();
UFUNCTION()
void ReloadFileList();
UPROPERTY(meta = (bindwidget))
UButton* Btn_Yes;
UPROPERTY(meta = (bindwidget))
UButton* Btn_No;
UPROPERTY(meta = (bindwidget))
UTextBlock* Text_doing;
UPROPERTY(meta = (bindwidget))
UTextBlock* Text_finish;
UPROPERTY(meta = (bindwidget))
UTextBlock* Text_Filename;
TArray<FString> FileNames;
UPROPERTY(BlueprintReadWrite)
FString mFilename;
UPROPERTY(BlueprintReadWrite)
float nProgress;
UPROPERTY(BlueprintReadWrite)
int32 TotalFileCount;
UPROPERTY(BlueprintReadWrite)
int32 FileCount;
int32 bCancel;
UFileUpload_Thread* Thread;
ULibraryManager* parent;
};
.cpp
더보기
// Fill out your copyright notice in the Description page of Project Settings.
#include "UploadFile.h"
#include "Windows/AllowWindowsPlatformTypes.h"
#include <windows.h>
#include "Windows/HideWindowsPlatformTypes.h"
#include "FileUpload_Thread.h"
#include "LibraryManager.h"
#include "MyExpandableArea.h"
#include "Kismet/KismetSystemLibrary.h"
DWORD CALLBACK CopyFile_Callback(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize,
LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData);
UUploadFile::UUploadFile(const FObjectInitializer& obj) : Super(obj), bCancel(0)
{
}
void UUploadFile::NativeConstruct()
{
Super::NativeConstruct();
parent = Cast<ULibraryManager>(GetParent()->GetOuter()->GetOuter());
OnVisibilityChanged.AddDynamic(this, &UUploadFile::OnVisibilityChanged_UploadFile);
Btn_Yes->OnClicked.AddDynamic(this, &UUploadFile::OnClicked_Btn_Yes);
Btn_No->OnClicked.AddDynamic(this, &UUploadFile::OnClicked_Btn_No);
Btn_Yes->SetVisibility(ESlateVisibility::Collapsed);
Btn_No->SetVisibility(ESlateVisibility::Collapsed);
Text_doing->SetVisibility(ESlateVisibility::Collapsed);
Text_finish->SetVisibility(ESlateVisibility::Collapsed);
}
void UUploadFile::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
if (nProgress >= 1 && Btn_Yes->GetVisibility() != ESlateVisibility::Visible)
{
Btn_Yes->SetVisibility(ESlateVisibility::Visible);
Btn_No->SetVisibility(ESlateVisibility::Collapsed);
Text_doing->SetVisibility(ESlateVisibility::Collapsed);
Text_finish->SetVisibility(ESlateVisibility::Visible);
}
else if (nProgress < 1 && Btn_No->GetVisibility() != ESlateVisibility::Visible)
{
Btn_Yes->SetVisibility(ESlateVisibility::Collapsed);
Btn_No->SetVisibility(ESlateVisibility::Visible);
Text_doing->SetVisibility(ESlateVisibility::Visible);
Text_finish->SetVisibility(ESlateVisibility::Collapsed);
}
}
void UUploadFile::OnClicked_Btn_Yes()
{
ReloadFileList();
SetVisibility(ESlateVisibility::Collapsed);
}
void UUploadFile::OnClicked_Btn_No()
{
bCancel = 1;
//취소된 파일이 삭제되길 기다림.(임의의 시간동안.)
UKismetSystemLibrary::K2_SetTimer(this, FString(TEXT("ReloadFileList")), 1.0f, false);
SetVisibility(ESlateVisibility::Collapsed);
}
void UUploadFile::OnVisibilityChanged_UploadFile(ESlateVisibility InVisibility)
{
if (InVisibility == ESlateVisibility::Visible)
{
Thread = new UFileUpload_Thread(this);
}
}
void UUploadFile::FileUploading()
{
nProgress = 0.f;
bCancel = 0;
FileCount = 0;
TotalFileCount = FileNames.Num();
for (auto Filename : FileNames)
{
FString src = Filename;
int32 index = 0;
src.FindLastChar('/', index);
FString temp = src.RightChop(index);
FString Dest = parent->ClickedDir->_path + temp;
GEngine->AddOnScreenDebugMessage(-1, 100, FColor::Magenta, Dest);
//'/'제거 후 표시.
mFilename = temp.RightChop(1);
CopyFileEx(*src, *Dest, CopyFile_Callback, this, &bCancel, COPY_FILE_FAIL_IF_EXISTS);
}
}
void UUploadFile::ReloadFileList()
{
//새로고침
FString temp = parent->ClickedDir->_path;
parent->FindFiles(temp);
}
DWORD CALLBACK CopyFile_Callback(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred,
DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData)
{
float pos = (double)TotalBytesTransferred.QuadPart / TotalFileSize.QuadPart;
((UUploadFile*)lpData)->nProgress = pos;
//GEngine->AddOnScreenDebugMessage(-1, 100, FColor::Magenta, FString::Printf(TEXT("TotalFileSize : %lld"), TotalFileSize.QuadPart));
UE_LOG(LogTemp, Log, TEXT("TotalFileSize : %lld"), TotalFileSize.QuadPart);
// 100 퍼센트 전송되지 않을 때
if (pos < 1)
return PROGRESS_CONTINUE;
((UUploadFile*)lpData)->FileCount++;
return PROGRESS_QUIET;
}
끝.
'UnrealEngine' 카테고리의 다른 글
[UE] 외부 라이브러리 사용하기 (0) | 2023.08.20 |
---|---|
[UE] 포커스가 없을 때, 소리 재생 (0) | 2023.08.05 |
UnrealEngine FSocket 통신 (0) | 2023.07.28 |
UnrealEngine Thread 만들기 (0) | 2023.07.15 |
[UE4] 픽셀 스트리밍 ver_4.27(with. Android Build) (0) | 2023.07.08 |
댓글