diff --git a/Plugins/SchUtils/Resources/Icon128.png b/Plugins/SchUtils/Resources/Icon128.png new file mode 100644 index 0000000..1231d4a Binary files /dev/null and b/Plugins/SchUtils/Resources/Icon128.png differ diff --git a/Plugins/SchUtils/SchUtils.uplugin b/Plugins/SchUtils/SchUtils.uplugin new file mode 100644 index 0000000..2e14fb4 --- /dev/null +++ b/Plugins/SchUtils/SchUtils.uplugin @@ -0,0 +1,24 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "SchUtils", + "Description": "https://space.bilibili.com/234305886", + "Category": "Other", + "CreatedBy": "Sch", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "IsExperimentalVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "SchUtils", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/Plugins/SchUtils/Source/SchUtils/Private/SchUtils.cpp b/Plugins/SchUtils/Source/SchUtils/Private/SchUtils.cpp new file mode 100644 index 0000000..545fc16 --- /dev/null +++ b/Plugins/SchUtils/Source/SchUtils/Private/SchUtils.cpp @@ -0,0 +1,121 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "SchUtils.h" + +#define LOCTEXT_NAMESPACE "FSchUtilsModule" + +void FSchUtilsModule::OnSchDebugCommand(const TArray& Strings) +{ + if (Strings.Num() == 0) + { + UE_LOG(LogTemp, Warning, TEXT("SchDebug: No Args")); + return; + } + if (Strings.Num() == 1) + { + LogValue(Strings[0]); + } + if (Strings.Num() == 2) + { + SetDebugValue(Strings[0], Strings[1]); + } +} + +void FSchUtilsModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + + // Register Debug Console Commands + IConsoleManager::Get().RegisterConsoleCommand(TEXT("SchDebugMode"), TEXT("Set Debug Mode, 1 for Draw Screen, 2 for UE LOG, UE LOG Default!") + , FConsoleCommandWithArgsDelegate::CreateLambda([](const TArray& Args) + { + + })); + + IConsoleManager::Get().RegisterConsoleCommand( + TEXT("SchDebug"), TEXT("Debug Tool for Debug Marco"), + FConsoleCommandWithArgsDelegate::CreateRaw(this, &FSchUtilsModule::OnSchDebugCommand), ECVF_Default); +} + +void FSchUtilsModule::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. + + TArray Keys; + DebugOffsetMap.GetKeys(Keys); + for (FString Str : Keys) + { + delete[] DebugOffsetMap[Str].Data; + } +} + +void FSchUtilsModule::LogValue(const FString& Name) +{ + switch (DebugOffsetMap[Name].Type) + { + case EDebugToolDataType::Float: + { + UE_LOG(LogTemp, Warning, TEXT("SchDebug: %s = %f"), *Name, *reinterpret_cast(DebugOffsetMap[Name].Data)); + break; + } + case EDebugToolDataType::Int32: + { + UE_LOG(LogTemp, Warning, TEXT("SchDebug: %s = %d"), *Name, *reinterpret_cast(DebugOffsetMap[Name].Data)); + break; + } + case EDebugToolDataType::Vector: + { + UE_LOG(LogTemp, Warning, TEXT("SchDebug: %s = %s"), *Name, *reinterpret_cast(DebugOffsetMap[Name].Data)->ToString()) + + + + break; + } + default: + { + // UE_LOG(LogTemp, Warning, TEXT("SchDebug: %s = %s"), *Name, *reinterpret_cast(DebugOffsetMap[Name].Data)); + + break; + } + } +} + +void FSchUtilsModule::SetDebugValue(const FString& Name, const FString& Value) +{ + switch (DebugOffsetMap[Name].Type) + { + case EDebugToolDataType::Float: + { + *reinterpret_cast(DebugOffsetMap[Name].Data) = FCString::Atof(*Value); + break; + } + case EDebugToolDataType::Int32: + { + *reinterpret_cast(DebugOffsetMap[Name].Data) = FCString::Atoi(*Value); + break; + } + case EDebugToolDataType::Vector: + { + *reinterpret_cast(DebugOffsetMap[Name].Data) = FVector::ZeroVector; + break; + } + default: + { + *reinterpret_cast(DebugOffsetMap[Name].Data) = Value; + break; + } + } +} + +void FSchUtilsModule::LogOpts(const FString& Name) +{ + if (Name == "1" || Name == "2") + { + CurrentLogOpts = FCString::Atoi(*Name); + } +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FSchUtilsModule, SchUtils) \ No newline at end of file diff --git a/Plugins/SchUtils/Source/SchUtils/Public/SchUtils.h b/Plugins/SchUtils/Source/SchUtils/Public/SchUtils.h new file mode 100644 index 0000000..ee41490 --- /dev/null +++ b/Plugins/SchUtils/Source/SchUtils/Public/SchUtils.h @@ -0,0 +1,75 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +#ifdef UE_BUILD_SHIPPING +#define SCH_DEBUG_FLOAT(x, Name) x +#define SCH_DEBUG_INT32(x, Name) x +#define SCH_DEBUG_Vector(x, Name) x +#elif +#define SCH_DEBUG_FLOAT(x, Name) FSchUtilsModule::DebugValue(x, L##Name, EDebugToolDataType::Float) +#define SCH_DEBUG_INT32(x, Name) FSchUtilsModule::DebugValue(x, L##Name, EDebugToolDataType::Int32) +#define SCH_DEBUG_Vector(x, Name) FSchUtilsModule::DebugValue(x, L##Name, EDebugToolDataType::Vector) +#endif + +#define SCH_LOG_OPTS(x) FSchUtilsModule::LogOpts(x) + +enum class EDebugToolDataType +{ + Float, + Int32, + Vector, +}; + +struct FDebugToolsByteOffsetStruct +{ + FDebugToolsByteOffsetStruct(uint8* Data, EDebugToolDataType Type) + : Type(Type) + , Data(Data) + { + } + EDebugToolDataType Type; + uint8* Data; + +}; + +class FSchUtilsModule : public IModuleInterface +{ +public: + void OnSchDebugCommand(const TArray& Strings); + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + + template + inline static Type DebugValue(Type Value, const FString& Name, EDebugToolDataType TypeEnum); + inline static void LogValue(const FString& Name); + inline static void SetDebugValue(const FString& Name, const FString& Value); + inline static void LogOpts(const FString& Name); + + + inline static TMap DebugOffsetMap; + + inline static int32 CurrentLogOpts = 2; +}; + + + +template +Type FSchUtilsModule::DebugValue(Type Value, const FString& Name, EDebugToolDataType TypeEnum) +{ + if (DebugOffsetMap.Contains(Name)) + { + return *reinterpret_cast(DebugOffsetMap[Name].Data); + } + else + { + uint8* NewValue = new uint8[sizeof(Type)]; + *reinterpret_cast(NewValue) = Value; + DebugOffsetMap[Name] = FDebugToolsByteOffsetStruct(NewValue, TypeEnum); + } + return Type(); +} diff --git a/Plugins/SchUtils/Source/SchUtils/SchUtils.Build.cs b/Plugins/SchUtils/Source/SchUtils/SchUtils.Build.cs new file mode 100644 index 0000000..dfd8b4c --- /dev/null +++ b/Plugins/SchUtils/Source/SchUtils/SchUtils.Build.cs @@ -0,0 +1,53 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class SchUtils : ModuleRules +{ + public SchUtils(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... 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", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Source/Cut5/Cut5.Build.cs b/Source/Cut5/Cut5.Build.cs index 22b593a..da892b3 100644 --- a/Source/Cut5/Cut5.Build.cs +++ b/Source/Cut5/Cut5.Build.cs @@ -12,9 +12,9 @@ public class Cut5 : ModuleRules { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "FFMPEGMedia", "FFMPEGMediaFactory"}); + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "FFMPEGMedia", "FFMPEGMediaFactory", "SchUtils"}); PrivateDependencyModuleNames.AddRange(new string[] {"ApplicationCore", "FFMPEGMedia", "FFMPEGMediaFactory", - "Slate", "SlateCore", "UMG", "OpenCV", "DesktopPlatform", "PortAudioPlugin"}); + "Slate", "SlateCore", "UMG", "OpenCV", "DesktopPlatform", "PortAudioPlugin", "SchUtils"}); } } diff --git a/Source/Cut5/Interface/CutMainWidgetInterface.h b/Source/Cut5/Interface/CutMainWidgetInterface.h index a7fc78c..f404153 100644 --- a/Source/Cut5/Interface/CutMainWidgetInterface.h +++ b/Source/Cut5/Interface/CutMainWidgetInterface.h @@ -30,6 +30,7 @@ public: virtual void OnUpdateLightArray(const TArray& LightArray) {}; virtual void OnUpdateSpotLight(int32 Index, FColor LightColor) {}; virtual void OnUpdateProjector(int32 Index, bool bEnableProjector) {}; + virtual void OnUpdateLightBar(const TArray& LightArray) {}; virtual void OnUpdatePlayers(TSharedPtr TrackBody, FColor PlayerColor) {}; virtual void OnAddNewTrack(ETrackType Type) {}; diff --git a/Source/Cut5/Interface/ExportThread.cpp b/Source/Cut5/Interface/ExportThread.cpp new file mode 100644 index 0000000..8edb7d9 --- /dev/null +++ b/Source/Cut5/Interface/ExportThread.cpp @@ -0,0 +1,85 @@ +#include "ExportThread.h" + +#include + +void FExportThread::Stop() +{ + bNeedClose = true; + FRunnable::Stop(); +} + +bool FExportThread::Init() +{ + ProcessWindow = ::CreateWindowExW(WS_EX_TOPMOST, WC_DIALOG, L"进度...", 0, CW_USEDEFAULT, CW_USEDEFAULT, 300, 100, + NULL, NULL, NULL, NULL); + if (ProcessWindow) + { + RECT rcClient; + GetClientRect(ProcessWindow, &rcClient); + + + + ProcessBar = ::CreateWindowExW(0, PROGRESS_CLASS, NULL, + WS_CHILD | WS_VISIBLE, 0, 0, rcClient.right, rcClient.bottom, ProcessWindow, NULL, NULL, NULL); + + ProcessText = ::CreateWindowExW(0, WC_STATIC, NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, rcClient.right, rcClient.bottom, ProcessBar, NULL, NULL, NULL); + SubProcessText = ::CreateWindowExW(0, WC_STATIC, NULL, WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 50, rcClient.right, rcClient.bottom, ProcessBar, NULL, NULL, NULL); + + ::ShowWindow(ProcessWindow, SW_SHOW); + + } + return FRunnable::Init(); +} + +uint32 FExportThread::Run() +{ + int32 LastPercent = 0; + int32 LastMaxPercent = 0; + ::SendMessageW(ProcessBar, PBM_SETRANGE, 0, MAKELPARAM(0, MaxPercent)); + ::SendMessageW(ProcessBar, PBM_SETPOS, 3, 0); + while (!bNeedClose) + { + + + if (LastPercent != CurrentPercent || LastMaxPercent != MaxPercent) + { + LastPercent = CurrentPercent; + LastMaxPercent = MaxPercent; + ::SetWindowTextW(ProcessText, *FString::Printf(TEXT("进度:%d/%d"), int32(CurrentPercent), int32(MaxPercent))); + ::SetWindowTextW(SubProcessText, *FString::Printf(TEXT("子进度:%d/%d"), int32(SubCurrentPercent), int32(SubMaxPercent))); + } + + const LPMSG MSG = {nullptr}; + while (PeekMessageW(MSG, ProcessWindow, 0, 0, PM_REMOVE)) + { + TranslateMessage(MSG); + DispatchMessageW(MSG); + + switch (MSG->message) + { + case WM_CLOSE: + { + bNeedClose = true; + PostQuitMessage(0); + break; + } + case WM_DESTROY: + bNeedClose = true; + DestroyWindow(0); + default: + break; + + } + } + // ::UpdateWindow(ProcessWindow); + + ::BringWindowToTop(ProcessWindow); + } + return 0; +} + +void FExportThread::Exit() +{ + ::DestroyWindow(ProcessWindow); + FRunnable::Exit(); +} diff --git a/Source/Cut5/Interface/ExportThread.h b/Source/Cut5/Interface/ExportThread.h new file mode 100644 index 0000000..f0eaeda --- /dev/null +++ b/Source/Cut5/Interface/ExportThread.h @@ -0,0 +1,27 @@ +#pragma once +#include "Windows/AllowWindowsPlatformTypes.h" +#include "Windows/PreWindowsApi.h" +#include "Windows/MinWindows.h" +#include "Windows/PostWindowsApi.h" +#include "Windows/HideWindowsPlatformTypes.h" +class FExportThread : public FRunnable +{ +public: + virtual void Stop() override; + virtual bool Init() override; + virtual uint32 Run() override; + virtual void Exit() override; + + bool bNeedClose = false; + std::atomic MaxPercent = 100.0f; + std::atomic CurrentPercent = 0.0f; + std::atomic Message = nullptr; + + std::atomic SubMaxPercent = 100.0f; + std::atomic SubCurrentPercent = 0.0f; + + HWND ProcessWindow = nullptr; + HWND ProcessBar = nullptr; + HWND ProcessText = nullptr; + HWND SubProcessText = nullptr; +}; diff --git a/Source/Cut5/Interface/VideoInterface.cpp b/Source/Cut5/Interface/VideoInterface.cpp index a88088f..58c8d22 100644 --- a/Source/Cut5/Interface/VideoInterface.cpp +++ b/Source/Cut5/Interface/VideoInterface.cpp @@ -107,6 +107,11 @@ uint32 FVideoThread::Run() uint8* RawData = nullptr; int32 Width = AllocatedFrame->width; + if (ClipData.ClipType == ETrackType::LightBarTrack) + { + RawData = new uint8[FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4]; + Width = FGlobalData::LightArrayX; + } if (ClipData.ClipType == ETrackType::LightArrayTrack) { RawData = new uint8[FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4]; @@ -172,6 +177,26 @@ uint32 FVideoThread::Run() sws_scale(SwsCtx, AllocatedFrame->data, AllocatedFrame->linesize, 0, AllocatedFrame->height, Dest, DestLineSize); sws_freeContext(SwsCtx); } + else if (ClipData.ClipType == ETrackType::LightBarTrack) + { + + + const AVCodecContext* VideoCodecContext = NewPropertyData.VideoCodecContext; + struct SwsContext* SwsCtx = sws_getContext( + AllocatedFrame->width, AllocatedFrame->height, VideoCodecContext->pix_fmt, + FGlobalData::LightArrayX, FGlobalData::LightArrayY, AV_PIX_FMT_BGRA, + SWS_BILINEAR, nullptr, nullptr, nullptr + ); + if (!SwsCtx) + { + UE_LOG(LogTemp, Error, TEXT("Error creating swsContext")); + CurrentSeekingFrame = -1; + continue;; + } + + sws_scale(SwsCtx, AllocatedFrame->data, AllocatedFrame->linesize, 0, AllocatedFrame->height, Dest, DestLineSize); + sws_freeContext(SwsCtx); + } int32 X = AllocatedFrame->width; @@ -190,6 +215,13 @@ uint32 FVideoThread::Run() FMemory::Memcpy(ColorArray.GetData(), RawData, FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4); MainInterface->OnUpdateLightArray(ColorArray); } + if (ClipData.ClipType == ETrackType::LightBarTrack) + { + TArray ColorArray; + ColorArray.Init(FColor::Black, FGlobalData::LightArrayX * FGlobalData::LightArrayY); + FMemory::Memcpy(ColorArray.GetData(), RawData, FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4); + MainInterface->OnUpdateLightBar(ColorArray); + } }); // }); diff --git a/Source/Cut5/Utils/CutPlatformUtils.cpp b/Source/Cut5/Utils/CutPlatformUtils.cpp index a7be6bd..44449be 100644 --- a/Source/Cut5/Utils/CutPlatformUtils.cpp +++ b/Source/Cut5/Utils/CutPlatformUtils.cpp @@ -4,19 +4,8 @@ HWND FCutPlatformUtils::CreateProcessWindow() { - HWND Process = ::FindWindowW(nullptr, *FApp::GetName()); - if (Process) - { - HWND ProcessBar = ::CreateWindowExW(0, PROGRESS_CLASS, NULL, - WS_CHILD | WS_VISIBLE, 0, 0, 200, 20, - Process, (HMENU) 0, NULL, NULL); - - ::SendMessageW(ProcessBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); - return ProcessBar; - } + return nullptr; - - } void FCutPlatformUtils::UpdateProcess(HWND hwnd, float Progress, FString Message) diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index ec2461d..df1cbd1 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -317,6 +317,33 @@ TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, c { TArray ClipData = TrackData.ClipData; ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; }); + + + if (FGlobalData::Export_OnlyXML) + { + int32 i = 0; + TArray EncodeVideoInfos; + for (FClipData& TempClipData : ClipData) + { + if (!TempClipData.ResourcePropertyDataPtr) + continue; + if (TempClipData.ResourcePropertyDataPtr->Context) + { + FEncodeVideoInfo EncodeVideoInfo; + EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.ClipStartFrame); + EncodeVideoInfo.EncodedVideoName = ExportPath + FString::FromInt(i) + TEXT(".mp4"); + EncodeVideoInfo.ClipStartFrame = TempClipData.ClipStartFrame; + EncodeVideoInfo.ClipEndFrame = TempClipData.ClipEndFrame; + + EncodeVideoInfo.TrackData = TrackData; + EncodeVideoInfo.ClipData = TempClipData; + + EncodeVideoInfos.Add(EncodeVideoInfo); + } + i++; + } + return EncodeVideoInfos; + } int32 i = 0; TArray EncodeVideoInfos; @@ -333,8 +360,6 @@ TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, c int32 EndMilli = TempClipData.VideoEndFrame % static_cast(FGlobalData::GlobalFPS); FString NewStartMilli = FUtils::GetMsFromString(FGlobalData::GetTimeData(StartMilli)); FString NewEndMilli = FUtils::GetMsFromString(FGlobalData::GetTimeData(EndMilli)); - NewStartMilli = FString::Printf(TEXT("%04d"), FCString::Atoi(*NewStartMilli)); - NewEndMilli = FString::Printf(TEXT("%04d"), FCString::Atoi(*NewEndMilli)); FString StartTime = FString::Printf(TEXT("%02d:%02d:%02d.%s"), StartTimespan.GetHours(), StartTimespan.GetMinutes(), StartTimespan.GetSeconds(), *NewStartMilli); FString EndTime = FString::Printf(TEXT("%02d:%02d:%02d.%s"), EndTimespan.GetHours(), EndTimespan.GetMinutes(), EndTimespan.GetSeconds(), *NewEndMilli); @@ -398,6 +423,8 @@ FEncodeVideoInfo FUtils::TrackEncodeAudio(const FTrackData& TrackData, const FSt int32 i = 0; for (FClipData& TempClipData : ClipData) { + if (!TempClipData.ResourcePropertyDataPtr) + continue; if (TempClipData.ResourcePropertyDataPtr->Context) { SavedClipData = TempClipData; @@ -565,6 +592,29 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& using namespace cv; TArray ClipData = TrackData.ClipData; ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; }); + + if (FGlobalData::Export_OnlyXML) + { + TArray EncodeVideoInfos; + int32 i = 0; + for (FClipData& TempClipData : ClipData) + { + FString ExportName = FGuid::NewGuid().ToString();; + if (TempClipData.ResourcePropertyDataPtr) + { + FEncodeVideoInfo EncodeVideoInfo; + FString String = ExportPath + FString::FromInt(i) + ".psaf"; + EncodeVideoInfo.EncodedVideoName = FPaths::GetBaseFilename(String) + ".psaf"; + EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.ClipStartFrame); + + EncodeVideoInfo.TrackData = TrackData; + EncodeVideoInfo.ClipData = TempClipData; + EncodeVideoInfos.Add(EncodeVideoInfo); + } + } + return EncodeVideoInfos; + } + TArray EncodeVideoInfos; int32 i = 0; for (FClipData& TempClipData : ClipData) @@ -625,9 +675,9 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& Size old_size = frameSize; - capture.set(CAP_PROP_POS_FRAMES, TempClipData.ClipStartFrame); + capture.set(CAP_PROP_POS_FRAMES, TempClipData.VideoStartFrame); int32 frameCount = capture.get(CV_CAP_PROP_FRAME_COUNT); - frameCount -= ClipData[i].ClipStartFrame; + frameCount -= ClipData[i].VideoStartFrame; UE_LOG(LogTemp, Log, TEXT("frameCount: %s"), *FString::FromInt(frameCount)); char p[128] = "pasf"; @@ -695,17 +745,17 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& int8 g = frame.at(row, col)[1]; int8 b = frame.at(row, col)[0]; - if (r == 1) + if (r == 1 || r == 2) { - r -= 1; + r = 0; } - if (g == 1) + if (g == 1 || g == 2) { - g -= 1; + g = 0; } - if (b == 1) + if (b == 1 || b == 2) { - b -= 1; + b = 0; } outfile.write(reinterpret_cast(&r), sizeof(uint8)); @@ -725,17 +775,17 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& int8 g = frame.at(row, col)[1]; int8 b = frame.at(row, col)[0]; - if (r == 1) + if (r == 1 || r == 2) { - r -= 1; + r = 0; } - if (g == 1) + if (g == 1 || g == 2) { - g -= 1; + g = 0; } - if (b == 1) + if (b == 1 || b == 2) { - b -= 1; + b = 0; } outfile.write(reinterpret_cast(&r), sizeof(uint8)); @@ -758,17 +808,17 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& int8 g = frame.at(row, col)[1]; int8 b = frame.at(row, col)[0]; - if (r == 1) + if (r == 1 || r == 2) { - r -= 1; + r = 0; } - if (g == 1) + if (g == 1 || g == 2) { - g -= 1; + g = 0; } - if (b == 1) + if (b == 1 || b == 2) { - b -= 1; + b = 0; } outfile.write(reinterpret_cast(&r), sizeof(uint8)); @@ -787,17 +837,17 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& int8 g = frame.at(row, col)[1]; int8 b = frame.at(row, col)[0]; - if (r == 1) + if (r == 1 || r == 2) { - r -= 1; + r = 0; } - if (g == 1) + if (g == 1 || g == 2) { - g -= 1; + g = 0; } - if (b == 1) + if (b == 1 || b == 2) { - b -= 1; + b = 0; } outfile.write(reinterpret_cast(&r), sizeof(uint8)); @@ -818,17 +868,17 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& int8 g = frame.at(row, col)[1]; int8 b = frame.at(row, col)[0]; - if (r == 1) + if (r == 1 || r == 2) { - r -= 1; + r = 0; } - if (g == 1) + if (g == 1 || g == 2) { - g -= 1; + g = 0; } - if (b == 1) + if (b == 1 || b == 2) { - b -= 1; + b = 0; } outfile.write(reinterpret_cast(&r), sizeof(uint8)); @@ -846,17 +896,17 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& int8 g = frame.at(row, col)[1]; int8 b = frame.at(row, col)[0]; - if (r == 1) + if (r == 1 || r == 2) { - r -= 1; + r = 0; } - if (g == 1) + if (g == 1 || g == 2) { - g -= 1; + g = 0; } - if (b == 1) + if (b == 1 || b == 2) { - b -= 1; + b = 0; } outfile.write(reinterpret_cast(&r), sizeof(uint8)); @@ -960,9 +1010,9 @@ FString FUtils::GetMsNumberFromStringWithZFill(FString TimeString) FString FUtils::Color2Hex3(FColor Color) { - Color.R = FMath::GetMappedRangeValueClamped(FVector2D(0, 0xFF), FVector2D(0, 0x64), Color.R); - Color.G = FMath::GetMappedRangeValueClamped(FVector2D(0, 0xFF), FVector2D(0, 0x64), Color.G); - Color.B = FMath::GetMappedRangeValueClamped(FVector2D(0, 0xFF), FVector2D(0, 0x64), Color.B); + Color.R = FMath::GetMappedRangeValueClamped(FVector2D(0, 0xFF), FVector2D(0, 0x32), Color.R); + Color.G = FMath::GetMappedRangeValueClamped(FVector2D(0, 0xFF), FVector2D(0, 0x32), Color.G); + Color.B = FMath::GetMappedRangeValueClamped(FVector2D(0, 0xFF), FVector2D(0, 0x32), Color.B); return FString::Printf(TEXT("%02X%02X%02X"), Color.R, Color.G, Color.B); } diff --git a/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp b/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp index feadc63..1ba5d6c 100644 --- a/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp +++ b/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp @@ -8,6 +8,7 @@ void FTimelineClipCommands::RegisterCommands() UI_COMMAND(Fill2Start, "填充到开头", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(Fill2End, "填充到结尾", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(Cycle, "循环", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); + UI_COMMAND(FillPlayers, "填充至所有玩家轨道", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(CancelCycle, "取消循环", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(AddCursorHere, "在此处添加渐变点", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(AddVolumeHere, "在此处添加音量点", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); diff --git a/Source/Cut5/Widgets/Commands/TimelineClipCommands.h b/Source/Cut5/Widgets/Commands/TimelineClipCommands.h index e235c00..fff4767 100644 --- a/Source/Cut5/Widgets/Commands/TimelineClipCommands.h +++ b/Source/Cut5/Widgets/Commands/TimelineClipCommands.h @@ -21,6 +21,7 @@ public: TSharedPtr Break; TSharedPtr Fill2Start; TSharedPtr Fill2End; + TSharedPtr FillPlayers; TSharedPtr CancelCycle; TSharedPtr Cycle; TSharedPtr AddCursorHere; diff --git a/Source/Cut5/Widgets/Curtain/SCurtain.cpp b/Source/Cut5/Widgets/Curtain/SCurtain.cpp index f7a5544..64fd0e9 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtain.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtain.cpp @@ -91,6 +91,7 @@ void SCurtain::Construct(const FArguments& InArgs) if (!Curtain->bIsActive) { OpenThis(); + } }) .Text(FText::FromString(Curtain->CurtainName)) @@ -160,6 +161,7 @@ TSharedPtr SCurtain::OpenThis() CurtainPanel->CallRender(); + // 没有Curtain就Create一个 if (!FPaths::FileExists(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()))) { @@ -182,7 +184,71 @@ TSharedPtr SCurtain::OpenThis() CurtainDragDrop->DragDropType = FCutDragDropBase::EType::CurtainDrag; CurtainDragDrop->DraggingWidget = SharedThis(this); + + CurtainPanel->MainWidgetInterface->UpdateProperties(nullptr); + CurtainPanel->MainWidgetInterface->UpdateProperties(this); + return CurtainDragDrop; } +FProperties* SCurtain::GetProperties() +{ + return IPropertiesInterface::GetProperties(); +} + +TSharedPtr SCurtain::GetPropertiesWidget() +{ + FTextBlockStyle NormalText = FAppStyle::GetWidgetStyle("NormalText"); + NormalText.SetFontSize(13); + + FCurtain& CurtainRef = *Curtain; + + PropertiesWidget = + SNew(SVerticalBox) + + SVerticalBox::Slot() + .SizeParam(FAuto()) + .Padding(0, 13, 0, 0) + [ + SNew(SBox).HeightOverride(32).WidthOverride(214) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .VAlign(VAlign_Center) + [ + SNew(SBox) + .WidthOverride(62) + .HeightOverride(32) + .VAlign(VAlign_Center) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("全局"))) + .Font(NormalText.Font) + .Justification(ETextJustify::Center) + ] + ] + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .HAlign(HAlign_Right) + [ + SNew(SBox) + .WidthOverride(136) + .HeightOverride(32) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this, &CurtainRef]() + { + return CurtainRef.IsGlobal ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this, &CurtainRef](const ECheckBoxState State) + { + CurtainRef.IsGlobal = State == ECheckBoxState::Checked; + }) + ] + ] + ] + ]; + return PropertiesWidget; +} + END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/Curtain/SCurtain.h b/Source/Cut5/Widgets/Curtain/SCurtain.h index b547643..5d4cfc4 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtain.h +++ b/Source/Cut5/Widgets/Curtain/SCurtain.h @@ -3,13 +3,14 @@ #pragma once #include "CoreMinimal.h" +#include "Cut5/Interface/PropertiesInterface.h" #include "Cut5/Widgets/DefineGlobal.h" #include "Widgets/SCompoundWidget.h" /** * */ -class CUT5_API SCurtain : public SCompoundWidget +class CUT5_API SCurtain : public SCompoundWidget, public IPropertiesInterface { public: SLATE_BEGIN_ARGS(SCurtain) @@ -36,6 +37,9 @@ public: // FButtonStyle UnSelectedButtonStyle; FButtonStyle SelectedButtonStyle = FButtonStyle::GetDefault(); + + virtual FProperties* GetProperties() override; + virtual TSharedPtr GetPropertiesWidget() override; }; diff --git a/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp b/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp index 4d037b3..b04e1ee 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp @@ -294,6 +294,7 @@ void SCurtainPanel::UnSelectAllCurtain() void SCurtainPanel::CallRender() { + // MainWidgetInterface->UpdateProperties(nullptr); ScrollBox->ClearChildren(); GroupWidgets.Empty(); for (FCurtainGroup& Group : Groups) diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 74fda7a..26b25e9 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -34,6 +34,8 @@ public: inline static FString Version = "3.0"; inline static FString CutVersion = "1.1"; inline static FString ExportPath = ""; + + inline static bool Export_OnlyXML = false; inline static TArray ExportErrorString; @@ -345,7 +347,7 @@ struct CUT5_API FClipData : public TSharedFromThis Ar << ClipData.bIsCycle; Ar << ClipData.AudioCurtains; Ar << ClipData.bIsVirtual; - Ar << ClipData.VirtualCurtainName; + Ar << ClipData.VirtualCurtainGuid; return Ar; }; @@ -455,7 +457,7 @@ struct CUT5_API FClipData : public TSharedFromThis TArray PlayerLightData; EPresetType PresetType = EPresetType::NotAPresets; bool bIsVirtual = false; - FString VirtualCurtainName = ""; + FGuid VirtualCurtainGuid = FGuid(); // Placeholder @@ -843,11 +845,13 @@ public: FTimelineInfo TimelineInfo; bool bIsActive = false; int32 Step = 0; + bool IsGlobal = true; friend FArchive& operator<< (FArchive& Ar, FCurtain& Curtain) { Ar << Curtain.CurtainName; Ar << Curtain.CurtainUUID; Ar << Curtain.TimelineInfo; + Ar << Curtain.IsGlobal; return Ar; } }; diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index d6ce57c..664b936 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -556,16 +556,11 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& FVector2D StartPos = ClipSelectDragDrop->ScrollResultStartPosition; FVector2D EndPos = ClipSelectDragDrop->ScrollResultEndPosition; - // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("StartPos : %f, %f"), StartPos.X, StartPos.Y)); - // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("EndPos : %f, %f"), EndPos.X, EndPos.Y)); - auto IsInRange = [this, StartPos, EndPos](FClipData& ClipData) { const float ClipStartTime = ClipData.ClipStartFrame * FGlobalData::DefaultTimeTickSpace; const float ClipEndTime = ClipData.ClipEndFrame * FGlobalData::DefaultTimeTickSpace; - // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("ClipStartTime : %f"), ClipStartTime)); - // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("ClipEndTime : %f"), ClipEndTime)); - + if (StartPos.X < ClipStartTime && EndPos.X > ClipStartTime) { return true; @@ -846,6 +841,7 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& { NewClipData.ClipType = ETrackType::AudioTrackR; NewClipData.ClipGuid = FGuid::NewGuid(); + NewClipData.BindTrackGuid = TrackData->DeviceTrack.Guid; TrackData->ClipData.Add(NewClipData); UpdateClipProcess(SavedMainInterface, NewClipData); } @@ -857,6 +853,7 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& { NewClipData.ClipType = ETrackType::AudioTrack; NewClipData.ClipGuid = FGuid::NewGuid(); + NewClipData.BindTrackGuid = TrackData->DeviceTrack.Guid; TrackData->ClipData.Add(NewClipData); UpdateClipProcess(SavedMainInterface, NewClipData); } diff --git a/Source/Cut5/Widgets/FX/SEffectCard.cpp b/Source/Cut5/Widgets/FX/SEffectCard.cpp index 57db788..90d79ae 100644 --- a/Source/Cut5/Widgets/FX/SEffectCard.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCard.cpp @@ -395,6 +395,7 @@ TSharedPtr SEffectCard::GetPropertiesWidget() return false; } } + return true; }) .OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType) @@ -567,6 +568,46 @@ TSharedPtr SEffectCard::GetPropertiesWidget() ] ] ] + ] + + SVerticalBox::Slot() + .Padding(0, 16, 0 ,0) + [ + SNew(SBox).HeightOverride(32).WidthOverride(214) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .VAlign(VAlign_Center) + [ + SNew(SBox) + .WidthOverride(62) + .HeightOverride(32) + .VAlign(VAlign_Center) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("恢复默认"))) + .Font(NormalText.Font) + .Justification(ETextJustify::Center) + ] + ] + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + [ + SNew(SBox) + .WidthOverride(136) + .HeightOverride(32) + [ + SNew(SButton) + .Text(FText::FromString(TEXT("恢复默认"))) + .OnClicked_Lambda([this]() + { + CardProperty->UsedCurtains.Empty(); + CardProperty->JumpStepCurtains = FStringWithGUID(); + return FReply::Handled(); + }) + ] + ] + ] ]; return PropertiesWidget; diff --git a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp index 0149293..c6c4591 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp @@ -213,6 +213,9 @@ void SEffectCardGroup::Construct(const FArguments& InArgs) return false; } } + // ID不能重复 + + return true; }) .OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType) @@ -377,7 +380,48 @@ void SEffectCardGroup::Construct(const FArguments& InArgs) ] ] + ] + + SVerticalBox::Slot() + .Padding(0, 16, 0 ,0) + [ + SNew(SBox).HeightOverride(32).WidthOverride(214) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .VAlign(VAlign_Center) + [ + SNew(SBox) + .WidthOverride(62) + .HeightOverride(32) + .VAlign(VAlign_Center) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("恢复默认"))) + .Font(NormalText.Font) + .Justification(ETextJustify::Center) + ] + ] + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + [ + SNew(SBox) + .WidthOverride(136) + .HeightOverride(32) + [ + SNew(SButton) + .Text(FText::FromString(TEXT("恢复默认"))) + .OnClicked_Lambda([this]() + { + EffectCardGroup->UsedCurtains.Empty(); + EffectCardGroup->JumpStepCurtains = FStringWithGUID(); + return FReply::Handled(); + }) + ] + ] + ] ]; + PropertiesInterfaceGUID = EffectCardGroup->Guid; CallRender(); } @@ -419,24 +463,8 @@ void SEffectCardGroup::CallRender() .OnClicked_Lambda([this]() { - - - - - int32 ID = 0; - for (int32 i = 0; i < EffectCardPanel->EffectCardGroups.Num(); i++) - { - if (EffectCardPanel->EffectCardGroups[i].bIsDedicated) - { - for (int32 j = 0; j < EffectCardPanel->EffectCardGroups[i].Cards.Num(); j++) - { - ID++; - } - } - ID++; - } - // 新建卡牌后 对卡牌进行个体保存。 + int32 ID = EffectCardPanel->GetCurrentID(true); FEffectCardProperty NewCard; NewCard.Name = TEXT("未命名") + FString::FromInt(ID); NewCard.ID = ID; diff --git a/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp b/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp index 968394a..87dce3d 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp @@ -107,15 +107,7 @@ void SEffectCardsPanel::CallRender() const FGuid NewGuid = FGuid::NewGuid(); FEffectCardGroup* Group = AddNewGroup(TEXT("新建组") + NewGuid.ToString()); Group->Guid = NewGuid; - int32 ID = 0; - for (int32 i = 0; i < EffectCardGroups.Num(); i++) - { - for (int32 j = 0; j < EffectCardGroups[i].Cards.Num(); j++) - { - ID++; - } - ID++; - } + int32 ID = GetCurrentID(true); Group->ID = ID; const FString NewPath = FPaths::Combine(FGlobalData::BasePath, FGlobalData::CurrentProjectName, TEXT("FX"), NewGuid.ToString() + TEXT(".bin")); @@ -256,10 +248,10 @@ void SEffectCardsPanel::DuplicateCard(const FGuid& Guid, const FGuid& ToGroupGui { if (EffectCardGroups[k].Guid == ToGroupGuid) { - if (EffectCardGroups[k].Cards.Contains(NewEffectCardProperty)) - { - return; - } + // if (EffectCardGroups[k].Cards.Contains(NewEffectCardProperty)) + // { + // return; + // } EffectCardGroups[k].Cards.Add(NewEffectCardProperty); break; } @@ -399,4 +391,53 @@ void SEffectCardsPanel::LoadPanel(const FString& Path) CallRender(); } +bool SEffectCardsPanel::IsIdExists(int32 ID) +{ + for (FEffectCardGroup& Group : EffectCardGroups) + { + if (Group.ID == ID) + { + return true; + } + for (const FEffectCardProperty& Property : Group.Cards) + { + if (Property.ID == ID) + { + return true; + } + } + } + return false; +} + +int32 SEffectCardsPanel::GetCurrentID(bool Iterate) +{ + if (FPaths::FileExists(FGlobalData::BasePath / FGlobalData::CurrentProjectName / "ID.bin")) + { + FString IDData; + FFileHelper::LoadFileToString(IDData, *(FGlobalData::BasePath / FGlobalData::CurrentProjectName / "ID.bin")); + + if (Iterate) + { + int32 ID = FCString::Atoi(*IDData); + ID++; + const FString NewIDData = FString::FromInt(ID); + FFileHelper::SaveStringToFile(NewIDData, *(FGlobalData::BasePath / FGlobalData::CurrentProjectName / "ID.bin")); + return ID; + } + + return FCString::Atoi(*IDData); + } + else + { + const FString IDData = "1"; + FFileHelper::SaveStringToFile(IDData, *(FGlobalData::BasePath / FGlobalData::CurrentProjectName / "ID.bin")); + + return 1; + } + + return -1; + +} + END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/FX/SEffectCardsPanel.h b/Source/Cut5/Widgets/FX/SEffectCardsPanel.h index 07aa9c3..d367e99 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardsPanel.h +++ b/Source/Cut5/Widgets/FX/SEffectCardsPanel.h @@ -97,5 +97,9 @@ public: void SavePanel(const FString& Path); void LoadPanel(const FString& Path); + + bool IsIdExists(int32 ID); + + int32 GetCurrentID(bool Iterate = true); }; diff --git a/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp b/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp index 8723363..adf5294 100644 --- a/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp +++ b/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp @@ -15,6 +15,7 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SColorPanel::Construct(const FArguments& InArgs) { + OnColorCommit = InArgs._OnColorCommit; ColorPtr = InArgs._ColorPtr; CurrentSelectColor = ColorPtr->LinearRGBToHSV(); ColorS = ColorPtr->LinearRGBToHSV().G; @@ -149,6 +150,7 @@ void SColorPanel::Construct(const FArguments& InArgs) .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ColorPanelClose.png"), {})) .OnMouseButtonDown_Lambda([this](const FGeometry&, const FPointerEvent&) { + OnColorCommit.ExecuteIfBound(CurrentSelectColor); GEngine->GameViewport->RemoveViewportWidgetContent(SharedThis(this)); return FReply::Handled(); }) diff --git a/Source/Cut5/Widgets/MicroWidgets/SColorPanel.h b/Source/Cut5/Widgets/MicroWidgets/SColorPanel.h index 48fed8f..d6d4d07 100644 --- a/Source/Cut5/Widgets/MicroWidgets/SColorPanel.h +++ b/Source/Cut5/Widgets/MicroWidgets/SColorPanel.h @@ -11,10 +11,12 @@ class CUT5_API SColorPanel : public SCompoundWidget { public: + DECLARE_DELEGATE_OneParam(FOnColorCommit, FLinearColor) SLATE_BEGIN_ARGS(SColorPanel) { } SLATE_ARGUMENT(FLinearColor*, ColorPtr) + SLATE_EVENT(FOnColorCommit, OnColorCommit) SLATE_END_ARGS() /** Constructs this widget with InArgs */ @@ -29,6 +31,7 @@ public: TSharedPtr SBar; TSharedPtr ColorBox; TSharedPtr ColorImage; + FOnColorCommit OnColorCommit; FLinearColor CurrentSelectColor = FLinearColor(1, 1, 0, 1); float ColorS = 0; diff --git a/Source/Cut5/Widgets/SCustomInputPanel.cpp b/Source/Cut5/Widgets/SCustomInputPanel.cpp index 3457c5d..5fb3158 100644 --- a/Source/Cut5/Widgets/SCustomInputPanel.cpp +++ b/Source/Cut5/Widgets/SCustomInputPanel.cpp @@ -310,16 +310,12 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) .Justification(ETextJustify::Center) ] ] - ] ] ] ] - ] - ] - ]; @@ -337,7 +333,7 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) AddPreset(TEXT("橘色"), TEXT("橘色.dat"), EPresetType::Custom); AddPreset(TEXT("青柠"), TEXT("青柠.dat"), EPresetType::Custom); AddPreset(TEXT("音量\n玩家谈话"), TEXT("10"), EPresetType::Volume); - AddPreset(TEXT("音量\n视频底音"), TEXT("35"), EPresetType::Volume); + AddPreset(TEXT("音量\n视频底音"), TEXT("25"), EPresetType::Volume); AddPreset(TEXT("音量\n静音"), TEXT("0"), EPresetType::Volume); AddPreset(TEXT("启动投影"), TEXT(""), EPresetType::EnableProjector); AddPreset(TEXT("屏蔽投影"), TEXT(""), EPresetType::DisableProjector); diff --git a/Source/Cut5/Widgets/SCutMainWindow.cpp b/Source/Cut5/Widgets/SCutMainWindow.cpp index bd1edf4..3a9f6ab 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.cpp +++ b/Source/Cut5/Widgets/SCutMainWindow.cpp @@ -18,6 +18,7 @@ #include "Commands/MainMenuCommands.h" #include "Commands/ShortcunCommands.h" #include "CustomPanel/SCustomPanel.h" +#include "Cut5/Interface/ExportThread.h" #include "Cut5/Utils/CutPlatformUtils.h" #include "Cut5/Utils/FFMPEGUtils.h" #include "Cut5/Utils/Utils.h" @@ -39,6 +40,8 @@ #include "Windows/AllowWindowsPlatformTypes.h" #include "Windows/WindowsPlatformApplicationMisc.h" #include "GenericPlatform/GenericPlatformApplicationMisc.h" +#include "SaveConverter/Timeline/TimelineLoader.h" +#include "SchUtils.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION @@ -129,20 +132,9 @@ void SCutMainWindow::Construct(const FArguments& InArgs) .Justification(ETextJustify::Center) .OnDoubleClicked_Lambda([this](const FGeometry&, const FPointerEvent&) { - for (int32 i = CutTimeline->DeviceTrackGroups.Num() - 1; i >= 0; i--) - { - if (CutTimeline->DeviceTrackGroups[i].GroupType == ETrackType::AtomSphereLightTrack) - { - CutTimeline->DeviceTrackGroups.RemoveAt(i); - } - // for (int32 j = CutTimeline->DeviceTrackGroups[i].DeviceTracks.Num() - 1; j >= 0; j--) - // { - // if (CutTimeline->DeviceTrackGroups[i].DeviceTracks[j].DeviceType == ETrackType::AtomSphereLightTrack) - // { - // CutTimeline->DeviceTrackGroups[i].DeviceTracks.RemoveAt(j); - // } - // } - } + FRunnable* Runnable = new FExportThread(); + FRunnableThread* RunnableThread = FRunnableThread::Create(Runnable, TEXT("ExportThread")); + return FReply::Handled(); }) ] @@ -726,6 +718,10 @@ void SCutMainWindow::Tick(const FGeometry& AllottedGeometry, const double InCurr TotalTime = 0; } TotalTime += InDeltaTime; + + + SCH_DEBUG_INT32(114514, "TestVar"); + // GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("TestVar: %d"), SCH_DEBUG_INT32(114514, "TestVar"))); } int32 SCutMainWindow::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, @@ -858,6 +854,12 @@ void SCutMainWindow::OnUpdateSpotLight(int32 Index, FColor LightColor) } +void SCutMainWindow::OnUpdateLightBar(const TArray& LightArray) +{ + ICutMainWidgetInterface::OnUpdateLightBar(LightArray); + StatePanel->LightArray->LightBarColors = LightArray; +} + void SCutMainWindow::OnAddNewTrack(ETrackType Type) { ICutMainWidgetInterface::OnAddNewTrack(Type); @@ -978,12 +980,20 @@ bool SCutMainWindow::OpenProject(const FString& Project) FUtils::AddTips(SNew(STips).Title(TEXT("打开失败")).SubTitle(FString::Printf(TEXT("版本不匹配,无法打开项目,载入版本:%s, 当前版本:%s"), *LoadVersion, *FGlobalData::Version)).OnEnsure_Lambda([](const FString& String){})); return false; } + + + FExportThread* Thread = new FExportThread(); + FRunnableThread* RunnableThread = FRunnableThread::Create(Thread, TEXT("ImportThread")); // 记录所有导入资产链接 int32 PropertyDataNum = 0; Reader << PropertyDataNum; + + Thread->MaxPercent = PropertyDataNum; + Thread->CurrentPercent = 0; for (int32 i = 0; i < PropertyDataNum; i++) { + Thread->CurrentPercent = Thread->CurrentPercent + 1; FTimelinePropertyData TimelinePropertyData; Reader << TimelinePropertyData; @@ -1058,7 +1068,7 @@ bool SCutMainWindow::OpenProject(const FString& Project) } - + Thread->Stop(); return true; } @@ -1068,9 +1078,14 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) if (ExportPath.IsEmpty()) return; - - HWND hwnd = FCutPlatformUtils::CreateProcessWindow(); - FCutPlatformUtils::UpdateProcess(hwnd, 50, TEXT("")); + ExportCards.Empty(); + TotalExported = 0; + int32 ExportCount = CalculateExportCount(); + Runnable = new FExportThread(); + FRunnableThread* RunnableThread = FRunnableThread::Create(Runnable, TEXT("ExportThread")); + Runnable->MaxPercent = ExportCount; + Runnable->CurrentPercent = TotalExported; + FGlobalData::ExportPath = ExportPath / FGlobalData::CurrentProjectName + TEXT("_XML"); @@ -1208,16 +1223,17 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) { for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++) { - tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card"); - Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID))); + FExportCard ExportCard; int32 TypeID = 0; if (EffectCardsPanel->EffectCardGroups[i].Cards[j].JumpStepCurtains.Guid.IsValid()) { TypeID = 1; } - Card->InsertNewChildElement("Type")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TypeID))); - Card->InsertNewChildElement("Times")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(-1))); - + ExportCard.CardName = EffectCardsPanel->EffectCardGroups[i].Cards[j].Name; + ExportCard.CardID = EffectCardsPanel->EffectCardGroups[i].Cards[j].ID; + ExportCard.CardType = TypeID; + ExportCard.Times = -1; + int32 ToStepID = 0; if (TypeID == 1) { @@ -1233,29 +1249,28 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) } } } + ExportCard.Step = ToStepID; + ExportCard.SerialID.Add(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID); - Card->InsertNewChildElement("Step")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ToStepID))); - Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID - 1))); - Card->InsertNewChildElement("SerialNumberList")->InsertNewChildElement("SerialNumber")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID))); + + ExportCard.TimelinePath = FUtils::SingleCardFullPath(EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid.ToString()); + ExportCard.CardGuid = EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid; + ExportCards.Add(ExportCard); + UE_LOG(LogTemp, Log, TEXT("ExportCard.TimelinePath = %s"), *ExportCard.TimelinePath); } } else { - tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card"); - - - Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID))); - + FExportCard ExportCard; + ExportCard.CardName = EffectCardsPanel->EffectCardGroups[i].GroupName; + ExportCard.CardID = EffectCardsPanel->EffectCardGroups[i].ID; int32 TypeID = 2; if (EffectCardsPanel->EffectCardGroups[i].JumpStepCurtains.Guid.IsValid()) { TypeID = 3; } - - Card->InsertNewChildElement("Type")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TypeID))); - Card->InsertNewChildElement("Times")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(-1))); - - + ExportCard.CardType = TypeID; + ExportCard.Times = -1; int32 ToStepID = 0; if (TypeID == 3) { @@ -1271,16 +1286,48 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) } } } - Card->InsertNewChildElement("Step")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ToStepID))); - Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID))); - tinyxml2::XMLElement* SerialNumberList = Card->InsertNewChildElement("SerialNumberList"); + ExportCard.Step = ToStepID; for (int32 k = 0; k < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); k++) { - SerialNumberList->InsertNewChildElement("SerialNumber")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[k].ID))); + ExportCard.SerialID.Add(EffectCardsPanel->EffectCardGroups[i].Cards[k].ID); } + + + ExportCard.TimelinePath = FUtils::GroupFullPath(EffectCardsPanel->EffectCardGroups[i].Guid.ToString()); + ExportCard.CardGuid = EffectCardsPanel->EffectCardGroups[i].Guid; + ExportCards.Add(ExportCard); } - } + + Sort(ExportCards.GetData(), ExportCards.Num(), [](const FExportCard& A, const FExportCard& B) { return A.CardID < B.CardID; }); + int32 Count = 0; + for (int32 i = 0; i < ExportCards.Num(); i++) + { + if (ExportCards[i].CardType == 0 || ExportCards[i].CardType == 2) + { + ExportCards[i].SpecialEffectID = Count; + } + else + { + ExportCards[i].SpecialEffectID = -1; + } + Count++; + } + for (int32 i = 0; i < ExportCards.Num(); i++) + { + tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card"); + Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCards[i].CardID))); + Card->InsertNewChildElement("Type")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCards[i].CardType))); + Card->InsertNewChildElement("Times")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCards[i].Times))); + Card->InsertNewChildElement("Step")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCards[i].Step))); + Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCards[i].SpecialEffectID))); + tinyxml2::XMLElement* SerialNumberList = Card->InsertNewChildElement("SerialNumberList"); + for (int32 k = 0; k < ExportCards[i].SerialID.Num(); k++) + { + SerialNumberList->InsertNewChildElement("SerialNumber")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCards[i].SerialID[k]))); + } + } + // KeyBoard tinyxml2::XMLElement* Keyboard = DeviceList->InsertNewChildElement("KeyBoard"); @@ -1323,6 +1370,8 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) } FFileHelper::SaveStringToFile(Ended, *FUtils::GetProjectTempPath()); + + Runnable->Stop(); } @@ -1652,6 +1701,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par Event1->InsertNewChildElement("TimeCode")->InsertNewText("0"); } } + + int32 Count = 0; @@ -1670,6 +1721,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par } Count++; + + TotalExported++; + Runnable->CurrentPercent = Runnable->CurrentPercent + 1; } if (Count == 0) { @@ -1791,6 +1845,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par } } + TotalExported++; + Runnable->CurrentPercent = Runnable->CurrentPercent + 1; j++; } } @@ -1834,17 +1890,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par } } } - FString Filename; - for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) - { - for (const FCurtain& Curtain : CurtainGroup.Curtains) - { - if (Curtain.bIsActive) - { - Filename = Curtain.CurtainName + (CurrentTrackHead->TrackData.TrackType == ETrackType::LightArrayTrack ? TEXT("光阵") : TEXT("光条")); - } - } - } + FString Filename = GetCurrentSelectFileName() + (CurrentTrackHead->TrackData.TrackType == ETrackType::LightArrayTrack ? TEXT("光阵") : TEXT("光条")); + TArray EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr(CurrentTrackHead)->TrackData, *(FGlobalData::ExportPath / "PSAF" / Filename)); for (int32 j = 0; j < EncodeVideoInfos.Num(); j++) { @@ -2133,7 +2180,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Pare tinyxml2::XMLElement* VolumeEventValue = VolumeEvent->InsertNewChildElement("Value"); VolumeEventTimeCode->InsertNewText("0"); - VolumeEventValue->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ClipData.CurrentVolume))); + VolumeEventValue->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(100))); } } @@ -2265,11 +2312,14 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* if (ClipData.bIsVirtual) { bIsVirtual = true; - const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName; + FString GetSelectionName = GetSelectNameByGuid(ClipData.VirtualCurtainGuid); + const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / GetSelectionName; FEncodeVideoInfo EncodeVideoInfo; EncodeVideoInfo.EncodedVideoName = VirtualFileName; EncodeVideoInfo.ClipData = ClipData; GetSoundElement(AudioList, EncodeVideoInfo); + TotalExported++; + Runnable->CurrentPercent = Runnable->CurrentPercent + 1; } } if (!bIsVirtual) @@ -2279,11 +2329,14 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* if (ClipData.bIsVirtual) { bIsVirtual = true; - const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName; + FString GetSelectionName = GetSelectNameByGuid(ClipData.VirtualCurtainGuid); + const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / GetSelectionName; FEncodeVideoInfo EncodeVideoInfo; EncodeVideoInfo.EncodedVideoName = VirtualFileName; EncodeVideoInfo.ClipData = ClipData; GetSoundElement(AudioList, EncodeVideoInfo); + TotalExported++; + Runnable->CurrentPercent = Runnable->CurrentPercent + 1; } } } @@ -2298,6 +2351,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* const FEncodeVideoInfo LeftEncodeVideoInfos = FUtils::TrackEncodeAudio(LeftTrackData, LeftNewExportFilePath); const FEncodeVideoInfo RightEncodeVideoInfos = FUtils::TrackEncodeAudio(RightTrackData, RightNewExportFilePath); + TotalExported++; + Runnable->CurrentPercent = Runnable->CurrentPercent + 1; + const FString ExportFilename = FGlobalData::ExportPath / "Sound" / GetCurrentSelectFileName(); const FEncodeVideoInfo End = FUtils::CombineAudio(LeftEncodeVideoInfos, RightEncodeVideoInfos, ExportFilename); @@ -2343,6 +2399,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, { AutoNext = 1; AutoNextTimeLength = FUtils::GetMsFromString(FGlobalData::GetTimeData(AutoNextClipData[0].ClipStartFrame)); + + TotalExported++; + Runnable->CurrentPercent = Runnable->CurrentPercent + 1; } ProcessB->InsertNewChildElement("AutoNext")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(AutoNext))); @@ -2361,7 +2420,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, } tinyxml2::XMLElement* IsGlobal = ProcessB->InsertNewChildElement("IsGlobal"); { - IsGlobal->InsertNewText("1"); + IsGlobal->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Curtain->IsGlobal))); } tinyxml2::XMLElement* State = ProcessB->InsertNewChildElement("State"); { @@ -2410,31 +2469,49 @@ tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectList(tinyxml2::XMLElement* { tinyxml2::XMLElement* SpecialEffectsList = Parent->InsertNewChildElement("SpecialEffectsList"); int32 SpecialEffectID = 0; - for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i++) + for (FExportCard& ExportCard : ExportCards) { - if (!EffectCardsPanel->EffectCardGroups[i].bIsDedicated) - { - DeselectAll(); - EffectCardsPanel->EffectCardGroups[i].bIsActive = true; - OpenTimeline(FUtils::GroupFullPath(EffectCardsPanel->EffectCardGroups[i].Guid.ToString()), true, true); - CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Guid; - GetSpecialEffectGroup(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i]); - SpecialEffectID++; - continue; - } - for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++) - { - DeselectAll(); - EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive = true; - OpenTimeline(FUtils::SingleCardFullPath(EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid.ToString()), true, true); - CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid; - GetSpecialEffect(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i].Cards[j]); - SpecialEffectID++; - } - - SpecialEffectID++; - } + DeselectAll(); + SetActive(ExportCard.CardGuid); + OpenTimeline(ExportCard.TimelinePath, true, true); + tinyxml2::XMLElement* SpecialEffect = SpecialEffectsList->InsertNewChildElement("SpecialEffect"); + tinyxml2::XMLElement* Effect = SpecialEffect->InsertNewChildElement("Effect"); + Effect->SetAttribute("Name", TCHAR_TO_UTF8(*ExportCard.CardName)); + + tinyxml2::XMLElement* ID = Effect->InsertNewChildElement("ID"); + { + ID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ExportCard.SpecialEffectID))); + } + + FString AutoNextTimeLength = "-1"; + int32 AutoNext = 0; + TArray AutoNextClipData = CutTimeline->GetClipDataByType(ETrackType::AutoNext); + if (AutoNextClipData.Num() > 0) + { + AutoNext = 1; + AutoNextTimeLength = FUtils::GetMsFromString(FGlobalData::GetTimeData(AutoNextClipData[0].ClipStartFrame)); + } + + Effect->InsertNewChildElement("AutoNext")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(AutoNext))); + Effect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*AutoNextTimeLength)); + GetSoundListElement(Effect); + GetDeviceElement(Effect); + GetVideoListElement(Effect); + tinyxml2::XMLElement* IsGlobal = Effect->InsertNewChildElement("IsGlobal"); + { + int32 bIsGlobal = 0; + IsGlobal->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(bIsGlobal))); + } + tinyxml2::XMLElement* State = Effect->InsertNewChildElement("State"); + { + State->InsertNewText("0"); + } + + GetTrigger(SpecialEffect); + } + + if (SpecialEffectID == 0) { SpecialEffectsList->InsertNewText(""); @@ -2677,6 +2754,70 @@ tinyxml2::XMLElement* SCutMainWindow::GetGradientLight(tinyxml2::XMLElement* Par return nullptr; } +FTimelineInfo SCutMainWindow::GetSelectTimelineInfoByGuid(const FGuid& Guid) const +{ + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (const FCurtain& Curtain : CurtainGroup.Curtains) + { + if (Curtain.CurtainUUID == Guid) + { + return Curtain.TimelineInfo; + } + } + } + for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups) + { + if (!Group.bIsDedicated) + { + if (Group.Guid == Guid) + { + return Group.TimelineInfo; + } + } + for (FEffectCardProperty& Property : Group.Cards) + { + if (Property.Guid == Guid) + { + return Property.TimelineInfo; + } + } + } + return FTimelineInfo(); +} + +FString SCutMainWindow::GetSelectNameByGuid(const FGuid& Guid) const +{ + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (const FCurtain& Curtain : CurtainGroup.Curtains) + { + if (Curtain.CurtainUUID == Guid) + { + return TEXT("幕_") + Curtain.CurtainName; + } + } + } + for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups) + { + if (!Group.bIsDedicated) + { + if (Group.Guid == Guid) + { + return TEXT("特效组_") + Group.GroupName; + } + } + for (FEffectCardProperty& Property : Group.Cards) + { + if (Property.Guid == Guid) + { + return TEXT("特效卡_") + Property.Name; + } + } + } + return ""; +} + FGuid SCutMainWindow::GetCurrentSelectCurtain() const { for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) @@ -2689,9 +2830,57 @@ FGuid SCutMainWindow::GetCurrentSelectCurtain() const } } } + for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups) + { + if (!Group.bIsDedicated) + { + if (Group.bIsActive == true) + { + return Group.Guid; + } + } + for (FEffectCardProperty& Property : Group.Cards) + { + if (Property.bIsActive) + { + return Property.Guid; + } + } + } return FGuid(); } +void SCutMainWindow::SetActive(FGuid& Guid) const +{ + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (FCurtain& Curtain : CurtainGroup.Curtains) + { + if (Curtain.CurtainUUID == Guid) + { + Curtain.bIsActive = true; + } + } + } + for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups) + { + if (!Group.bIsDedicated) + { + if (Group.Guid == Guid) + { + Group.bIsActive = true; + } + } + for (FEffectCardProperty& Property : Group.Cards) + { + if (Property.Guid == Guid) + { + Property.bIsActive = true; + } + } + } +} + FTimelineInfo SCutMainWindow::GetCurrentSelectCurtainTimelineInfo() const { for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) @@ -2704,6 +2893,23 @@ FTimelineInfo SCutMainWindow::GetCurrentSelectCurtainTimelineInfo() const } } } + for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups) + { + if (!Group.bIsDedicated) + { + if (Group.bIsActive) + { + return Group.TimelineInfo; + } + } + for (FEffectCardProperty& Property : Group.Cards) + { + if (Property.bIsActive) + { + return Property.TimelineInfo; + } + } + } return FTimelineInfo(); } @@ -2733,6 +2939,7 @@ void SCutMainWindow::DeselectAll() } for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); ++i) { + EffectCardsPanel->EffectCardGroups[i].bIsActive = false; for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); ++j) { if (EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive) @@ -2746,6 +2953,37 @@ void SCutMainWindow::DeselectAll() EffectCardsPanel->CallRender(); } +int32 SCutMainWindow::CalculateExportCount() +{ + int32 Count = 0; + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (FCurtain& Curtain : CurtainGroup.Curtains) + { + FTimelineLoader TimelineLoader(Curtain.TimelineInfo.CurrentOpenFullPath); + Count += TimelineLoader.GetClipData().Num(); + } + } + for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups) + { + if (!Group.bIsDedicated) + { + for (FEffectCardProperty& Property : Group.Cards) + { + FTimelineLoader TimelineLoader(Property.TimelineInfo.CurrentOpenFullPath); + Count += TimelineLoader.GetClipData().Num(); + } + } + for (FEffectCardProperty& Property : Group.Cards) + { + FTimelineLoader TimelineLoader(Property.TimelineInfo.CurrentOpenFullPath); + Count += TimelineLoader.GetClipData().Num(); + } + } + return Count; + +} + int32 SCutMainWindow::GetTrackID(FGuid Guid) const { const int32* Index = IDList.Find(Guid); diff --git a/Source/Cut5/Widgets/SCutMainWindow.h b/Source/Cut5/Widgets/SCutMainWindow.h index 2cd1214..dff3b57 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.h +++ b/Source/Cut5/Widgets/SCutMainWindow.h @@ -13,6 +13,7 @@ #include "CustomPanel/SCustomPanel.h" #include "StatePanel/SVideoPlayer.h" #include "Cut5/Interface/CutMainWidgetInterface.h" +#include "Cut5/Interface/ExportThread.h" #include "Cut5/Interface/SoundInterface.h" #include "FX/SEffectCardsPanel.h" #include "StatePanel/SStatePanel.h" @@ -21,6 +22,23 @@ /** * */ + +struct FExportCard +{ + + FString CardName; + int32 CardID; + int32 CardType; + int32 SpecialEffectID; + int32 Times; + int32 Step; + TArray SerialID; + + FString TimelinePath; + FGuid CardGuid; + +}; + class CUT5_API SCutMainWindow : public SCompoundWidget, public ICutMainWidgetInterface { public: @@ -54,7 +72,7 @@ public: - + TArray ExportCards; void CloseAllThreads(); FSoundThread* SoundThread; @@ -69,6 +87,7 @@ public: virtual void OnUpdatePlayers(TSharedPtr TrackBody, FColor PlayerColor) override; virtual void OnUpdateProjector(int32 Index, bool bEnableProjector) override; virtual void OnUpdateSpotLight(int32 Index, FColor LightColor) override; + virtual void OnUpdateLightBar(const TArray& LightArray) override; virtual void OnAddNewTrack(ETrackType Type) override; virtual void OnRemoveTrack(FGuid Guid) override; virtual void OnUpdateSound(uint8* Data, int32 Size) override; @@ -97,6 +116,8 @@ public: virtual ESelectMode GetSelectedMode() override; virtual SCutMainWindow* GetSelf() override; + FExportThread* Runnable; + FPointerEvent NewMouseEvent; virtual bool SupportsKeyboardFocus() const override { return true; }; virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override; @@ -125,12 +146,17 @@ public: tinyxml2::XMLElement* GetFlashLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData); tinyxml2::XMLElement* GetGradientLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData); FString GetCurrentSelectFileName() const; - - + FTimelineInfo GetSelectTimelineInfoByGuid(const FGuid& Guid) const; + FString GetSelectNameByGuid(const FGuid& Guid) const; FGuid GetCurrentSelectCurtain() const; + void SetActive(FGuid& Guid) const; FTimelineInfo GetCurrentSelectCurtainTimelineInfo() const; bool IsSelectCurtain() const; void DeselectAll(); + + int32 TotalExported = 0; + + int32 CalculateExportCount(); int32 RotatorSpeakerIndex = 0; int32 LightArrayIndex = 0; @@ -152,17 +178,24 @@ inline FString SCutMainWindow::GetCurrentSelectFileName() const { if (Curtain.bIsActive) { - return Curtain.CurtainName; + return TEXT("幕_") + Curtain.CurtainName; } } } for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); ++i) { + if (!EffectCardsPanel->EffectCardGroups[i].bIsDedicated) + { + if (EffectCardsPanel->EffectCardGroups[i].bIsActive) + { + return TEXT("特效组_") + EffectCardsPanel->EffectCardGroups[i].GroupName; + } + } for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); ++j) { if (EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive) { - return EffectCardsPanel->EffectCardGroups[i].Cards[j].Name; + return TEXT("特效卡_") + EffectCardsPanel->EffectCardGroups[i].Cards[j].Name; } } } diff --git a/Source/Cut5/Widgets/SCutTimeline.cpp b/Source/Cut5/Widgets/SCutTimeline.cpp index 59c5b3d..f50ba22 100644 --- a/Source/Cut5/Widgets/SCutTimeline.cpp +++ b/Source/Cut5/Widgets/SCutTimeline.cpp @@ -297,7 +297,7 @@ void SCutTimeline::Construct(const FArguments& InArgs) + SHorizontalBox::Slot() .SizeParam(FStretch(0.93f)) [ - SNew(SVerticalBox) + SAssignNew(TimelineMainContentVerticalBox, SVerticalBox) + SVerticalBox::Slot() .SizeParam(FAuto()) [ @@ -518,6 +518,13 @@ TArray SCutTimeline::GetClipData() return ResultClipData; } +FReply SCutTimeline::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + FVector2D Vector = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, FString::Printf(TEXT("X:%f,Y:%f"), Vector.X, Vector.Y)); + return SCompoundWidget::OnMouseMove(MyGeometry, MouseEvent); +} + int32 SCutTimeline::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const diff --git a/Source/Cut5/Widgets/SCutTimeline.h b/Source/Cut5/Widgets/SCutTimeline.h index 8cc6696..bcd6c9e 100644 --- a/Source/Cut5/Widgets/SCutTimeline.h +++ b/Source/Cut5/Widgets/SCutTimeline.h @@ -77,10 +77,12 @@ public: void SetAutoPlay(bool bStart); void IterateCursor(); FTickCursorTimeThread* TickCursorTimeThread = nullptr; + TSharedPtr TimelineMainContentVerticalBox; TSharedPtr CommandList; TArray GetClipData(); + virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; FTimerHandle TimerHandle; bool AutoPlaying = false; virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; @@ -171,6 +173,7 @@ public: int32 FPS = 0; TFunction BindFunction; bool bIsDead = false; + FString Guid = FGuid::NewGuid().ToString(); virtual uint32 Run() override { while (!bIsDead) @@ -179,7 +182,8 @@ public: { FPlatformProcess::Sleep(1.0f / FPS); FFunctionGraphTask::CreateAndDispatchWhenReady([this]() - { + { + UE_LOG(LogTemp, Warning, TEXT("%s Tick"), *Guid); if (BindFunction) BindFunction(); }, TStatId(), nullptr, ENamedThreads::GameThread); diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index 6d6e4fa..11e1e7c 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -79,6 +79,11 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().AddCursorHere); } + if (ClipData->ClipType == ETrackType::AtomSphereLightTrack) + { + MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().FillPlayers); + } + MenuContent = MenuBuilder.MakeWidget(); FSlateApplication::Get().PushMenu(AsShared(), FWidgetPath(), MenuContent.ToSharedRef(), FSlateApplication::Get().GetCursorPos(), FPopupTransitionEffect::ContextMenu); @@ -385,6 +390,41 @@ void STimelineClip::Seek(int32 Frame) const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset; + if (MainWidgetInterface->GetSelf()->GetThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid))) + { + static_cast(MainWidgetInterface->GetSelf()->GetThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid)))->SeekFrame(SeekMovieFrame); + } + + if (ClipData->PresetsCustomData.PresetCustomType != FPresetsCustomData::EPresetCustomType::None) + { + if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Breathe) + { + MainWidgetInterface->OnUpdateLightArray(FUtils::SingleColor2ColorArray(ClipData->GetBreathColor(SeekMovieFrame))); + } + else if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Flash) + { + MainWidgetInterface->OnUpdateLightArray(FUtils::SingleColor2ColorArray(ClipData->GetFlashColor(SeekMovieFrame))); + } + else if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Gradient) + { + MainWidgetInterface->OnUpdateLightArray(FUtils::SingleColor2ColorArray(ClipData->GetGradientColor(SeekMovieFrame))); + } + break; + } + else if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None + && !ClipData->ResourcePropertyDataPtr) + { + MainWidgetInterface->OnUpdateLightArray(FUtils::SingleColor2ColorArray(ClipData->ClipColors[0].ToFColor(false))); + } + break; + + } + case ETrackType::LightBarTrack: + { + const int32 Offset = Frame - ClipData->ClipStartFrame; + const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset; + + if (MainWidgetInterface->GetSelf()->GetThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid))) { static_cast(MainWidgetInterface->GetSelf()->GetThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid)))->SeekFrame(SeekMovieFrame); @@ -454,7 +494,7 @@ void STimelineClip::Seek(int32 Frame) } else if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None) { - MainWidgetInterface->OnUpdatePlayers(Body, ClipData->ClipColors[0].ToFColor(false)); + MainWidgetInterface->OnUpdatePlayers(Body, ClipData->PresetsCustomData.Colors[0].ToFColor(false)); } break; } @@ -607,67 +647,117 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) { const FSlateBrush Brush; - - float DownSample = 4; + // Draw Audio Waveform - - - const float RangeStart = MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().LocalToAbsolute(FVector2D(0, 0)).X; - const float RangeEnd = MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().LocalToAbsolute(FVector2D(MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().GetLocalSize().X, 0)).X; + const float RangeStart = // MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2D(0, 0)).X; + // MainWidgetInterface->GetSelf()->GetCachedGeometry().GetLocalPositionAtCoordinates(MainWidgetInterface->GetCutTimeline()->TimelineMainContentVerticalBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2D(0, 0))).X; + MainWidgetInterface->GetCutTimeline()->TimelineMainContentVerticalBox->GetCachedGeometry().Position.X; + const float RangeEnd = // MainWidgetInterface->GetCutTimeline()->TrackBodyScrollBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2D(MainWidgetInterface->GetCutTimeline()->TrackBodyScrollBox->GetCachedGeometry().GetLocalSize().X, 0)).X; + MainWidgetInterface->GetCutTimeline()->TimelineMainContentVerticalBox->GetCachedGeometry().GetLocalSize().X; const float CurrentStartRange = AllottedGeometry.LocalToAbsolute(FVector2D(0, 0)).X; const float CurrentEndRange = AllottedGeometry.LocalToAbsolute(FVector2D(AllottedGeometry.GetLocalSize().X, 0)).X; + + + int32 CropStartFrameOffset = ((CurrentStartRange * -1) + RangeStart > 0 ? (CurrentStartRange * -1) + RangeStart : 0) / FGlobalData::DefaultTimeTickSpace; + if (CurrentEndRange < RangeStart) + { + CropStartFrameOffset = -1; + } - const int32 CropStartFrameOffset = ((CurrentStartRange * -1) + RangeStart > 0 ? (CurrentStartRange * -1) + RangeStart : 0) / FGlobalData::DefaultTimeTickSpace; const int32 CropEndFrameOffset = (RangeEnd - CurrentEndRange > 0 ? - (RangeEnd - RangeStart) + CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace : CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + (RangeEnd - RangeStart)) + (CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace) + (RangeEnd - RangeStart) - (RangeEnd - CurrentEndRange) : CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + (RangeEnd - RangeStart)) / FGlobalData::DefaultTimeTickSpace; - + int32 NeedDrawCount = (CropEndFrameOffset - CropStartFrameOffset) * FGlobalData::DefaultTimeTickSpace; - - - + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, FString::Printf(TEXT("CropStartFrameOffset : %d"), CropStartFrameOffset)); + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, FString::Printf(TEXT("CropEndFrameOffset : %d"), CropEndFrameOffset)); + + const int32 StartOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) * ClipData->VideoStartFrame * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; - - const int32 EndOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + const int32 EndOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) * ClipData->VideoEndFrame * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; - + const int32 CropStartDataOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) * CropStartFrameOffset * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; - + const int32 CropEndDataOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) * CropEndFrameOffset * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; - - const int32 Interval = ((EndOffset + CropEndDataOffset) - (StartOffset + CropStartDataOffset)) / NeedDrawCount; - - GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, FString::FromInt(NeedDrawCount)); - GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green, FString::FromInt(Interval)); - - - for (int32 i = 0; i < NeedDrawCount / DownSample; i++) + if (NeedDrawCount == 0) { - const int32 CurrentIndex = (StartOffset * DownSample) + (i * (Interval * DownSample * 4)); - if (CurrentIndex >= ClipData->ResourcePropertyDataPtr->AudioData.Num()) - continue; - - float NewFloat = *reinterpret_cast(&ClipData->ResourcePropertyDataPtr->AudioData[CurrentIndex]); - float Y = FMath::GetMappedRangeValueClamped(FVector2D(1.0, 0.0), FVector2D(0.0, AllottedGeometry.GetLocalSize().Y), - FMath::Abs(NewFloat)); - TArray NewLoc; - NewLoc.Add(FVector2D((CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + i) * DownSample, AllottedGeometry.GetLocalSize().Y)); - NewLoc.Add(FVector2D((CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + i) * DownSample, Y)); - FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 6, AllottedGeometry.ToPaintGeometry(), NewLoc, ESlateDrawEffect::None, - FColor(45, 214, 153, 255), true, DownSample * 1.2); + NeedDrawCount = -1; } + const int32 Interval = (CropEndDataOffset - CropStartDataOffset) / NeedDrawCount; + + + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, FString::FromInt(NeedDrawCount)); + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green, FString::FromInt(Interval)); + + if (CropStartFrameOffset != -1 || NeedDrawCount != -1) + { + for (int32 i = 0; i < NeedDrawCount / DownSample; i++) + { + const int32 CurrentIndex = (CropStartDataOffset * DownSample) + (i * (Interval * DownSample * 4)); + if (CurrentIndex >= ClipData->ResourcePropertyDataPtr->AudioData.Num()) + continue; + + float NewFloat = *reinterpret_cast(&ClipData->ResourcePropertyDataPtr->AudioData[CurrentIndex]); + float Y = FMath::GetMappedRangeValueClamped(FVector2D(1.0, 0.0), FVector2D(0.0, AllottedGeometry.GetLocalSize().Y), + FMath::Abs(NewFloat)); + TArray NewLoc; + NewLoc.Add(FVector2D((CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + i * DownSample) , AllottedGeometry.GetLocalSize().Y)); + NewLoc.Add(FVector2D((CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + i * DownSample) , Y)); + // GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, NewLoc[0].ToString()); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 6, AllottedGeometry.ToPaintGeometry(), NewLoc, ESlateDrawEffect::None, + FColor(45, 214, 153, 255), true, DownSample * 1.2); + } + } + + + // + // int32 NeedDrawCount = ClipData->GetLength() * FGlobalData::DefaultTimeTickSpace; + // float DownSample = 4; + // // Draw Audio Waveform + // + // + // const float RangeStart = MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().LocalToAbsolute(FVector2D(0, 0)).X; + // const float RangeEnd = MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().LocalToAbsolute(FVector2D(MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().GetLocalSize().X, 0)).X; + // const float CurrentStartRange = AllottedGeometry.LocalToAbsolute(FVector2D(0, 0)).X; + // const float CurrentEndRange = AllottedGeometry.LocalToAbsolute(FVector2D(AllottedGeometry.GetLocalSize().X, 0)).X; + // + // const int32 StartOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + // * ClipData->VideoStartFrame + // * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; + // + // const int32 EndOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + // * ClipData->VideoEndFrame + // * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; + // + // const int32 Interval = (EndOffset - StartOffset) / NeedDrawCount; + // for (int32 i = 0; i < NeedDrawCount / DownSample; i++) + // { + // const int32 CurrentIndex = (StartOffset * DownSample) + (i * (Interval * DownSample * 4)); + // if (CurrentIndex >= ClipData->ResourcePropertyDataPtr->AudioData.Num()) + // continue; + // + // float NewFloat = *reinterpret_cast(&ClipData->ResourcePropertyDataPtr->AudioData[CurrentIndex]); + // float Y = FMath::GetMappedRangeValueClamped(FVector2D(1.0, 0.0), FVector2D(0.0, AllottedGeometry.GetLocalSize().Y), + // FMath::Abs(NewFloat)); + // TArray NewLoc; + // NewLoc.Add(FVector2D(i * DownSample, AllottedGeometry.GetLocalSize().Y)); + // NewLoc.Add(FVector2D(i * DownSample, Y)); + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 6, AllottedGeometry.ToPaintGeometry(), NewLoc, ESlateDrawEffect::None, + // FColor(45, 214, 153, 255), true, DownSample * 1.2); + // } FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 5, AllottedGeometry.ToPaintGeometry(), &Brush, ESlateDrawEffect::None, FColor(22, 105, 78, 255)); } @@ -690,7 +780,8 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe } - if (ClipData->MovieBrushNum > 0) + if (ClipData->MovieBrushNum > 0 && (ClipData->ClipType == ETrackType::VideoTrack || ClipData->ClipType == ETrackType::LightArrayTrack || + ClipData->ClipType == ETrackType::LightBarTrack)) { int32 Step = ClipData->MovieBrushNum; @@ -726,11 +817,11 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (ClipData->PresetType == EPresetType::EnableProjector) { - FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("开启投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("开启\n投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } if (ClipData->PresetType == EPresetType::DisableProjector) { - FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("关闭投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("关闭\n投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } if (ClipData->bIsCycle == true) { @@ -782,7 +873,8 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe } - if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None) + if (ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None +&& ClipData->ClipType != ETrackType::AudioTrackR && ClipData->ClipType != ETrackType::AudioTrack) { const FSlateBrush Brush; FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 4, AllottedGeometry.ToPaintGeometry(), diff --git a/Source/Cut5/Widgets/STrackBody.cpp b/Source/Cut5/Widgets/STrackBody.cpp index d22df45..af6fb78 100644 --- a/Source/Cut5/Widgets/STrackBody.cpp +++ b/Source/Cut5/Widgets/STrackBody.cpp @@ -53,6 +53,11 @@ void STrackBody::Construct(const FArguments& InArgs) { AddVolume(SelectedClipGUID); }), FCanExecuteAction()); + CommandList->MapAction(FTimelineClipCommands::Get().FillPlayers, FExecuteAction::CreateLambda([this]() + { + FillPlayers(SelectedClipGUID); + }), FCanExecuteAction()); + MainWidgetInterface = InArgs._MainWidgetInterface; TrackHead = InArgs._TrackHead; ChildSlot @@ -136,6 +141,7 @@ FReply STrackBody::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent); } + void STrackBody::OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { @@ -274,6 +280,33 @@ void STrackBody::Fill2End(const FGuid& Guid) } } +void STrackBody::FillPlayers(const FGuid& Guid) +{ + FClipData NewClipData; + for (int32 i = 0; i < SlateClips.Num(); i++) + { + if (TrackHead->TrackData.ClipData[i].ClipGuid == Guid) + { + NewClipData = TrackHead->TrackData.ClipData[i]; + } + } + for (FSingleTrackGroupInstance& Instance : MainWidgetInterface->GetCutTimeline()->TrackGroupInstances) + { + TSharedPtr TrackBody = StaticCastSharedPtr(Instance.Body); + if (TrackBody->TrackHead != TrackHead) + { + if (TrackBody->TrackHead->TrackData.TrackType == ETrackType::AtomSphereLightTrack) + { + NewClipData.ClipGuid = FGuid::NewGuid(); + NewClipData.BindTrackGuid = TrackBody->TrackHead->TrackData.DeviceTrack.Guid; + DragDropOperator::GetDragDropOperator()->UpdateClipProcess(MainWidgetInterface, NewClipData); + TrackBody->TrackHead->TrackData.ClipData.Add(NewClipData); + TrackBody->CallRender(); + } + } + } +} + void STrackBody::SetCycle(const FGuid& Guid, bool Cycle) { for (int32 i = 0; i < SlateClips.Num(); i++) diff --git a/Source/Cut5/Widgets/STrackBody.h b/Source/Cut5/Widgets/STrackBody.h index 825d3f9..c3c5442 100644 --- a/Source/Cut5/Widgets/STrackBody.h +++ b/Source/Cut5/Widgets/STrackBody.h @@ -36,6 +36,7 @@ public: virtual void BreakClip(const FGuid& Guid) override; void Fill2Start(const FGuid& Guid); void Fill2End(const FGuid& Guid); + void FillPlayers(const FGuid& Guid); void SetCycle(const FGuid& Guid, bool Cycle); void AddCursor(const FGuid& Guid); void AddVolume(const FGuid& Guid); @@ -59,3 +60,4 @@ public: }; + diff --git a/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.cpp b/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.cpp index cd1288a..20a7b80 100644 --- a/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.cpp +++ b/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.cpp @@ -15,6 +15,7 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SLightArrayPanel::Construct(const FArguments& InArgs) { LightGridColors.Init(FColor(255, 0, 0, 255), FGlobalData::LightArrayX * FGlobalData::LightArrayY); + LightBarColors.Init(FColor(0, 0, 0, 255), FGlobalData::LightArrayX * FGlobalData::LightArrayY); ChildSlot [ @@ -95,6 +96,31 @@ int32 SLightArrayPanel::OnPaint(const FPaintArgs& Args, const FGeometry& Allotte } } + for (int32 i = 0; i < FGlobalData::LightArrayX; i++) + { + const FSlateBrush Brush; + FSlateDrawElement::MakeBox( + OutDrawElements, + LayerId + 100000, + LightBar1->GetPaintSpaceGeometry().ToPaintGeometry(SingleLocalSize, FSlateLayoutTransform(FVector2D(i * OriginLocalSize.X, OriginLocalSize.Y))), + &Brush, + ESlateDrawEffect::None, + LightBarColors[i] + ); + } + + for (int32 i = 0; i < FGlobalData::LightArrayX; i++) + { + const FSlateBrush Brush; + FSlateDrawElement::MakeBox( + OutDrawElements, + LayerId + 100000, + LightBar2->GetPaintSpaceGeometry().ToPaintGeometry(SingleLocalSize, FSlateLayoutTransform(FVector2D(i * OriginLocalSize.X, OriginLocalSize.Y))), + &Brush, + ESlateDrawEffect::None, + LightBarColors[i] + ); + } return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled); } diff --git a/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.h b/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.h index 0814d52..c3c19b6 100644 --- a/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.h +++ b/Source/Cut5/Widgets/StatePanel/SLightArrayPanel.h @@ -27,4 +27,5 @@ public: TSharedPtr LightBar1; TSharedPtr LightBar2; TArray LightGridColors; + TArray LightBarColors; }; diff --git a/Source/Cut5/Widgets/StaticProperties/ClipProperties.cpp b/Source/Cut5/Widgets/StaticProperties/ClipProperties.cpp new file mode 100644 index 0000000..09e0da1 --- /dev/null +++ b/Source/Cut5/Widgets/StaticProperties/ClipProperties.cpp @@ -0,0 +1,674 @@ +// #include "ClipProperties.h" +// +// #include "Cut5/Utils/Utils.h" +// #include "Cut5/Widgets/SCutTimeline.h" +// #include "Cut5/Widgets/STrackHead.h" +// +// +// FClipProperties* FClipProperties::GetProperties() +// { +// static FClipProperties* Properties = new FClipProperties(); +// return Properties; +// } +// +// TSharedPtr FClipProperties::GetProperties(ICutMainWidgetInterface* MainInterface) +// { +// Selectable.Empty(); +// Selectable.Add(MakeShared(TEXT("无"))); +// Selectable.Add(MakeShared(TEXT("呼吸"))); +// Selectable.Add(MakeShared(TEXT("闪烁"))); +// Selectable.Add(MakeShared(TEXT("渐变"))); +// +// +// FTextBlockStyle NormalText = FAppStyle::GetWidgetStyle("NormalText"); +// NormalText.SetFontSize(13); +// +// TSharedPtr VerticalBox; +// +// PropertiesWidget = SAssignNew(VerticalBox, SVerticalBox); +// +// +// +// if (!IsEqualPresetType(GetClips(MainInterface), EPresetType::NotAPresets) +// && !IsEqualTrackType(GetClips(MainInterface), ETrackType::VolumeTrack)) +// { // 颜色 +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("颜色"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// SNew(SImage) +// .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("Color.png"), {})) +// .ColorAndOpacity_Lambda([this, MainInterface]() +// { +// if (GetClips(MainInterface).Num() > 0) +// { +// return GetClips(MainInterface)[0]->PresetsCustomData.Colors[0]; +// } +// else +// { +// return FLinearColor::White; +// } +// }) +// .OnMouseButtonDown_Lambda([this, MainInterface](const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +// { +// MainInterface->OpenColorPanel(&ClipData->PresetsCustomData.Colors[0]); +// return FReply::Handled(); +// }) +// ] +// ] +// ] +// ]; +// +// +// // 动效 +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("动效"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// SNew(SComboBox>) +// .OptionsSource(&Selectable) +// .OnGenerateWidget_Lambda([this](TSharedPtr InItem) +// { +// return SNew(STextBlock).Text(FText::FromString(*InItem)); +// }) +// .OnSelectionChanged_Lambda([this](TSharedPtr InItem, ESelectInfo::Type SelectInfo) +// { +// switch (Selectable.Find(InItem)) +// { +// case 0: +// ClipData->PresetsCustomData.PresetCustomType = FPresetsCustomData::EPresetCustomType::None; +// break; +// case 1: +// ClipData->PresetsCustomData.PresetCustomType = FPresetsCustomData::EPresetCustomType::Breathe; +// break; +// case 2: +// ClipData->PresetsCustomData.PresetCustomType = FPresetsCustomData::EPresetCustomType::Flash; +// break; +// case 3: +// { +// +// ClipData->PresetsCustomData.PresetCustomType = FPresetsCustomData::EPresetCustomType::Gradient; +// if (ClipData->PresetsCustomData.Cursors.Num() < 2) +// { +// ClipData->PresetsCustomData.Cursors.Empty(); +// ClipData->PresetsCustomData.Cursors.Add(FCursorData(0, FLinearColor::Red)); +// ClipData->PresetsCustomData.Cursors.Add(FCursorData(10, FLinearColor::Green)); +// } +// } +// +// default: +// break; +// } +// MainInterface->GetCutTimeline()->RenderGroup(); +// }) +// [ +// SNew(STextBlock) +// .Text_Lambda([this]() +// { +// if (!ClipData) +// return FText(); +// return FText::FromString( ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None ? TEXT("无") : ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Breathe ? TEXT("呼吸") : ClipData->PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Gradient ? TEXT("渐变") : TEXT("闪烁")); +// }) +// ] +// ] +// ] +// ] +// ]; +// +// // 次数 +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("次数"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// +// SNew(SSpinBox) +// .Value_Lambda([this]() +// { +// if (!ClipData) +// return 0; +// return ClipData->PresetsCustomData.Times; +// }) +// .MinValue(1) +// .MaxValue(200) +// .OnValueChanged_Lambda([this](const int32& Value) +// { +// if (!ClipData) +// return; +// ClipData->PresetsCustomData.Times = Value; +// }) +// ] +// ] +// ] +// ]; +// +// +// // 时间 +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("时间"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// SNew(SSpinBox) +// .Value(0.3) +// .MinValue(0.3) +// .OnValueChanged_Lambda([this](const float& Value) +// { +// if (!ClipData) +// return; +// ClipData->ClipEndFrame = ClipData->ClipStartFrame + Value * FGlobalData::GlobalFPS; +// ClipData->PresetsCustomData.Time = (ClipData->ClipEndFrame - ClipData->ClipStartFrame) / FGlobalData::GlobalFPS; +// MainInterface->GetCutTimeline()->RenderGroup(); +// +// }) +// .Value_Lambda([this]() +// { +// if (!ClipData) +// return 0.0f; +// return (ClipData->ClipEndFrame - ClipData->ClipStartFrame) / FGlobalData::GlobalFPS; +// }) +// // .TypeInterface(MakeShared>(EUnit::Seconds)) +// ] +// ] +// ] +// ]; +// +// // 保存自定义效果 +// VerticalBox->AddSlot() +// .SizeParam(FStretch(1.0)) +// [ +// SNew(SSpacer) +// ]; +// VerticalBox->AddSlot() +// .HAlign(HAlign_Center) +// .VAlign(VAlign_Bottom) +// .Padding(0, 0, 0, 24) +// [ +// SNew(SBox).HeightOverride(40).WidthOverride(144) +// [ +// SNew(SOverlay) +// + SOverlay::Slot() +// .HAlign(HAlign_Fill) +// .VAlign(VAlign_Fill) +// [ +// SNew(SImage) +// .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("SaveCustomPreset.png"), {144, 40})) +// .OnMouseButtonDown_Lambda([this](const FGeometry&, const FPointerEvent&) +// { +// TSharedPtr NewProjectTips = SNew(SNewProjectTips).Title(TEXT("保存自定义效果名称")); +// NewProjectTips->OnEnsure.BindLambda([this, NewProjectTips](const FString& String) +// { +// TimelineClip->MainWidgetInterface->AddNewCustomPreset(String, ClipData->PresetsCustomData); +// GEngine->GameViewport->RemoveViewportWidgetContent(NewProjectTips.ToSharedRef()); +// }); +// GEngine->GameViewport->AddViewportWidgetContent(NewProjectTips.ToSharedRef() +// , 1); +// return FReply::Handled(); +// }) +// ] +// + SOverlay::Slot() +// [ +// SNew(STextBlock) +// .Visibility(EVisibility::HitTestInvisible) +// .Text(FText::FromString((TEXT("保存自定义效果")))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// ]; +// } +// +// if ((ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) && MainInterface->GetSelf()->GetCurrentSelectCurtain() != FGuid()) +// { +// +// AudiosCurtainOptions.Empty(); +// TArray& Groups = MainInterface->GetSelf()->CurtainPanel->Groups; +// for (FCurtainGroup& Group : Groups) +// { +// for (FCurtain& Curtain : Group.Curtains) +// { +// if (Curtain.CurtainUUID != MainInterface->GetSelf()->GetCurrentSelectCurtain()) +// { +// AudiosCurtainOptions.Add(MakeShared(Curtain.CurtainName, Curtain.CurtainUUID)); +// } +// } +// } +// +// for (FEffectCardGroup& CardGroup : MainInterface->GetSelf()->EffectCardsPanel->EffectCardGroups) +// { +// if (!CardGroup.bIsDedicated) +// { +// AudiosCurtainOptions.Add(MakeShared(CardGroup.GroupName, CardGroup.Guid)); +// } +// +// +// for (FEffectCardProperty& CardProperty : CardGroup.Cards) +// { +// if (!CardProperty.IsClone) +// { +// AudiosCurtainOptions.Add(MakeShared(CardProperty.Name, CardProperty.Guid)); +// } +// } +// } +// +// VerticalBox->AddSlot() +// .Padding(0, 16, 0 ,0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .VAlign(VAlign_Center) +// .WidthOverride(62) +// .HeightOverride(32) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("有效幕"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// SAssignNew(AudiosCurtainComboBox, SComboBox>) +// .OptionsSource(&AudiosCurtainOptions) +// .OnGenerateWidget_Lambda([this](TSharedPtr InItem) +// { +// return SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// [ +// SNew(STextBlock).Text(FText::FromString(*InItem->String)) +// ] +// + SHorizontalBox::Slot() +// .HAlign(HAlign_Right) +// [ +// SNew(SCheckBox) +// .IsChecked(ClipData->AudioCurtains.Contains(*InItem.Get()) ? ECheckBoxState::Checked : ECheckBoxState::Unchecked) +// .OnCheckStateChanged_Lambda([this, InItem](const ECheckBoxState& State) +// { +// const FGuid& Guid = InItem.Get()->Guid; +// FCurtainGroup* Group = nullptr; +// const FString CurrentPath = // MainInterface->GetSelf()->CurtainPanel->FindCurtain(Guid,Group)->TimelineInfo.CurrentOpenFullPath; +// MainInterface->GetSelf()->GetSelectTimelineInfoByGuid(Guid).CurrentOpenFullPath; +// FTimelineLoader TimelineLoader(CurrentPath, true); +// if (TimelineLoader.GetSpecifyClipData(ClipData->ClipType).Num() > 0 && State == ECheckBoxState::Checked) +// { +// FUtils::AddTips( +// SNew(STips) +// .Title(TEXT("警告")) +// .SubTitle(TEXT("选中的幕中的音频轨道已经存在音频片段\n如果继续添加,将会覆盖原有的音频片段\n是否继续?")) +// .OnEnsure_Lambda([this, State, InItem, CurrentPath](const FString& String) +// { +// // 先清空 +// FTimelineLoader ModifyTimelineLoader(CurrentPath, true); +// TArray Clips = ModifyTimelineLoader.GetSpecifyClipData(ClipData->ClipType); +// for (int32 i = Clips.Num() - 1; i >= 0; i--) +// { +// ModifyTimelineLoader.RemoveClipData(Clips[i]); +// } +// +// FClipData NewClip = *ClipData; +// NewClip.Move(0); +// NewClip.bIsVirtual = true; +// NewClip.VirtualCurtainGuid = MainInterface->GetSelf()->GetCurrentSelectCurtain(); +// NewClip.ClipGuid = FGuid::NewGuid(); +// ModifyTimelineLoader.GetClipData().Add(NewClip); +// +// if (State == ECheckBoxState::Checked) +// { +// ClipData->AudioCurtains.Add(*InItem.Get()); +// MainInterface->UpdateProperties(this); +// } +// else +// { +// ClipData->AudioCurtains.Remove(*InItem.Get()); +// MainInterface->UpdateProperties(this); +// } +// }) +// ); +// } +// else +// { +// if (State == ECheckBoxState::Checked) +// { +// FClipData NewClip = *ClipData; +// NewClip.Move(0); +// NewClip.bIsVirtual = true; +// NewClip.VirtualCurtainGuid = MainInterface->GetSelf()->GetCurrentSelectCurtain(); +// NewClip.ClipGuid = FGuid::NewGuid(); +// TimelineLoader.GetClipData().Add(NewClip); +// +// +// ClipData->AudioCurtains.Add(*InItem.Get()); +// MainInterface->UpdateProperties(this); +// +// +// } +// else +// { +// if (TimelineLoader.GetSpecifyClipData(ClipData->ClipType).Num() > 0) +// { +// TArray Clips = TimelineLoader.GetSpecifyClipData(ClipData->ClipType); +// for (int32 i = Clips.Num() - 1; i >= 0; i--) +// { +// TimelineLoader.RemoveClipData(Clips[i]); +// } +// } +// +// +// ClipData->AudioCurtains.Remove(*InItem.Get()); +// MainInterface->UpdateProperties(this); +// } +// } +// +// +// +// +// +// }) +// ]; +// +// }) +// [ +// SNew(STextBlock).Text_Lambda([this]() +// { +// if (ClipData->AudioCurtains.Num() == 1) +// { +// return FText::FromString(ClipData->AudioCurtains[0].String); +// } +// else if (ClipData->AudioCurtains.Num() > 1) +// { +// return FText::FromString(TEXT("多个")); +// } +// else +// { +// return FText::FromString(TEXT("无")); +// } +// }) +// ] +// ] +// ] +// ] +// ]; +// } +// +// if (ClipData->ClipType == ETrackType::VolumeTrack) +// { +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("音频"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .HAlign(HAlign_Right) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// SNew(SCheckBox) +// .IsChecked_Lambda([this]() +// { +// return ClipData->Work4Audio ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; +// }) +// .OnCheckStateChanged_Lambda([this](const ECheckBoxState State) +// { +// ClipData->Work4Audio = State == ECheckBoxState::Checked; +// }) +// ] +// ] +// ] +// ]; +// +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("视频"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .HAlign(HAlign_Right) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// SNew(SCheckBox) +// .IsChecked_Lambda([this]() +// { +// return ClipData->Work4Video ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; +// }) +// .OnCheckStateChanged_Lambda([this](const ECheckBoxState State) +// { +// ClipData->Work4Video = State == ECheckBoxState::Checked; +// }) +// ] +// ] +// ] +// ]; +// +// VerticalBox->AddSlot() +// .Padding(0, 13, 0, 0) +// [ +// SNew(SBox).HeightOverride(32).WidthOverride(214) +// [ +// SNew(SHorizontalBox) +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// .VAlign(VAlign_Center) +// [ +// SNew(SBox) +// .WidthOverride(62) +// .HeightOverride(32) +// .VAlign(VAlign_Center) +// [ +// SNew(STextBlock) +// .Text(FText::FromString(TEXT("音量"))) +// .Font(NormalText.Font) +// .Justification(ETextJustify::Center) +// ] +// ] +// + SHorizontalBox::Slot() +// .SizeParam(FAuto()) +// [ +// SNew(SBox) +// .WidthOverride(136) +// .HeightOverride(32) +// [ +// +// SNew(SSpinBox) +// .Value_Lambda([this]() +// { +// if (!ClipData) +// return 0; +// return ClipData->CurrentVolume; +// }) +// .MinValue(1) +// .MaxValue(100) +// .OnValueChanged_Lambda([this](const int32& Value) +// { +// if (!ClipData) +// return; +// ClipData->CurrentVolume = Value; +// }) +// ] +// ] +// ] +// ]; +// } +// +// +// +// return PropertiesWidget; +// } +// +// TArray FClipProperties::GetClips(ICutMainWidgetInterface* MainInterface) +// { +// TArray Clips; +// for (FSingleTrackGroupInstance& Instance : MainInterface->GetCutTimeline()->TrackGroupInstances) +// { +// for (FClipData& ClipData: StaticCastSharedPtr(Instance.Head)->TrackData.ClipData) +// { +// if (MainInterface->GetCutTimeline()->SelectedClips.Contains(ClipData.ClipGuid)) +// { +// Clips.Add(&ClipData); +// } +// } +// } +// return Clips; +// } +// +// bool FClipProperties::IsEqualTrackType(TArray ClipData, ETrackType Type) +// { +// for (FClipData* Data : ClipData) +// { +// if (Data->ClipType != Type) +// return false; +// } +// return true; +// } +// bool FClipProperties::IsEqualPresetType(TArray ClipData, EPresetType Type) +// { +// for (FClipData* Data : ClipData) +// { +// if (Data->PresetType != Type) +// return false; +// } +// return true; +// } diff --git a/Source/Cut5/Widgets/StaticProperties/ClipProperties.h b/Source/Cut5/Widgets/StaticProperties/ClipProperties.h new file mode 100644 index 0000000..df6792e --- /dev/null +++ b/Source/Cut5/Widgets/StaticProperties/ClipProperties.h @@ -0,0 +1,16 @@ +// #pragma once +// #include "Cut5/Interface/CutMainWidgetInterface.h" +// +// class FClipProperties +// { +// public: +// static FClipProperties* GetProperties(); +// TSharedPtr GetProperties(ICutMainWidgetInterface* MainInterface); +// TArray GetClips(ICutMainWidgetInterface* MainInterface); +// bool IsEqualTrackType(TArray ClipData, ETrackType Type); +// bool IsEqualPresetType(TArray ClipData, EPresetType Type); +// TArray> Selectable; +// +// TSharedPtr PropertiesWidget; +// }; +// diff --git a/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp b/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp index 3220299..85ded73 100644 --- a/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp +++ b/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp @@ -349,6 +349,23 @@ TSharedPtr FClipProxy::GetPropertiesWidget() } } + for (FEffectCardGroup& CardGroup : MainInterface->GetSelf()->EffectCardsPanel->EffectCardGroups) + { + if (!CardGroup.bIsDedicated) + { + AudiosCurtainOptions.Add(MakeShared(CardGroup.GroupName, CardGroup.Guid)); + } + + + for (FEffectCardProperty& CardProperty : CardGroup.Cards) + { + if (!CardProperty.IsClone) + { + AudiosCurtainOptions.Add(MakeShared(CardProperty.Name, CardProperty.Guid)); + } + } + } + VerticalBox->AddSlot() .Padding(0, 16, 0 ,0) [ @@ -395,7 +412,8 @@ TSharedPtr FClipProxy::GetPropertiesWidget() { const FGuid& Guid = InItem.Get()->Guid; FCurtainGroup* Group = nullptr; - const FString CurrentPath = MainInterface->GetSelf()->CurtainPanel->FindCurtain(Guid,Group)->TimelineInfo.CurrentOpenFullPath; + const FString CurrentPath = // MainInterface->GetSelf()->CurtainPanel->FindCurtain(Guid,Group)->TimelineInfo.CurrentOpenFullPath; + MainInterface->GetSelf()->GetSelectTimelineInfoByGuid(Guid).CurrentOpenFullPath; FTimelineLoader TimelineLoader(CurrentPath, true); if (TimelineLoader.GetSpecifyClipData(ClipData->ClipType).Num() > 0 && State == ECheckBoxState::Checked) { @@ -416,7 +434,7 @@ TSharedPtr FClipProxy::GetPropertiesWidget() FClipData NewClip = *ClipData; NewClip.Move(0); NewClip.bIsVirtual = true; - NewClip.VirtualCurtainName = MainInterface->GetSelf()->GetCurrentSelectFileName(); + NewClip.VirtualCurtainGuid = MainInterface->GetSelf()->GetCurrentSelectCurtain(); NewClip.ClipGuid = FGuid::NewGuid(); ModifyTimelineLoader.GetClipData().Add(NewClip); @@ -440,7 +458,7 @@ TSharedPtr FClipProxy::GetPropertiesWidget() FClipData NewClip = *ClipData; NewClip.Move(0); NewClip.bIsVirtual = true; - NewClip.VirtualCurtainName = MainInterface->GetSelf()->GetCurrentSelectFileName(); + NewClip.VirtualCurtainGuid = MainInterface->GetSelf()->GetCurrentSelectCurtain(); NewClip.ClipGuid = FGuid::NewGuid(); TimelineLoader.GetClipData().Add(NewClip);