音频导出
This commit is contained in:
parent
8005d78372
commit
7613ea06cd
BIN
Asset/1.wav
Normal file
BIN
Asset/1.wav
Normal file
Binary file not shown.
BIN
Asset/A.mp3
Normal file
BIN
Asset/A.mp3
Normal file
Binary file not shown.
3
Asset/Start.bat
Normal file
3
Asset/Start.bat
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
D:\Project\Cut5\Binaries\Win64\ffmpeg.exe -i 1.wav -i A.mp3 -filter_complex "[0:a]pan=1c|c0=c0[a];[1:a]pan=1c|c0=c1[b];[a][b]amerge=inputs=2[aout]" -map "[aout]" -t 1000000 output.mp3
|
||||
pause
|
BIN
Asset/output.mp3
Normal file
BIN
Asset/output.mp3
Normal file
Binary file not shown.
60
Cut5.sln
60
Cut5.sln
@ -7,49 +7,67 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{233774
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Games", "Games", "{DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{6EE39883-7339-3FB6-AD82-931FB137D37F}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{B95E7D0E-DB45-3765-9058-E00EBBC4B157}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{AF5A253A-0F37-38CE-8998-45CA936C112B}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{C48D0E9D-C862-3EA3-96A7-752EE9D06362}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Visualizers", "Visualizers", "{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis
|
||||
..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
DebugGame Editor|Android = DebugGame Editor|Android
|
||||
DebugGame Editor|Win64 = DebugGame Editor|Win64
|
||||
DebugGame|Android = DebugGame|Android
|
||||
DebugGame|Win64 = DebugGame|Win64
|
||||
Development Editor|Android = Development Editor|Android
|
||||
Development Editor|Win64 = Development Editor|Win64
|
||||
Development|Android = Development|Android
|
||||
Development|Win64 = Development|Win64
|
||||
Shipping|Android = Shipping|Android
|
||||
Shipping|Win64 = Shipping|Win64
|
||||
EndGlobalSection
|
||||
# UnrealVS Section
|
||||
GlobalSection(ddbf523f-7eb6-4887-bd51-85a714ff87eb) = preSolution
|
||||
AvailablePlatforms=Win64
|
||||
AvailablePlatforms=Win64;Android
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6EE39883-7339-3FB6-AD82-931FB137D37F}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{6EE39883-7339-3FB6-AD82-931FB137D37F}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{6EE39883-7339-3FB6-AD82-931FB137D37F}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{6EE39883-7339-3FB6-AD82-931FB137D37F}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{6EE39883-7339-3FB6-AD82-931FB137D37F}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame|Win64.ActiveCfg = DebugGame|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame|Win64.Build.0 = DebugGame|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.Development Editor|Win64.ActiveCfg = Development_Editor|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.Development Editor|Win64.Build.0 = Development_Editor|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.Development|Win64.ActiveCfg = Development|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.Development|Win64.Build.0 = Development|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.Shipping|Win64.ActiveCfg = Shipping|x64
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B}.Shipping|Win64.Build.0 = Shipping|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Android.ActiveCfg = Invalid|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Android.ActiveCfg = Android_DebugGame|Win64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Android.Build.0 = Android_DebugGame|Win64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Win64.ActiveCfg = DebugGame|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Win64.Build.0 = DebugGame|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Android.ActiveCfg = Invalid|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Win64.ActiveCfg = Development_Editor|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Win64.Build.0 = Development_Editor|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Android.ActiveCfg = Android_Development|Win64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Android.Build.0 = Android_Development|Win64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Win64.ActiveCfg = Development|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Win64.Build.0 = Development|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Android.ActiveCfg = Android_Shipping|Win64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Android.Build.0 = Android_Shipping|Win64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Win64.ActiveCfg = Shipping|x64
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Win64.Build.0 = Shipping|x64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{6EE39883-7339-3FB6-AD82-931FB137D37F} = {233774A8-CC9D-3FA9-86D1-90573E92B704}
|
||||
{AF5A253A-0F37-38CE-8998-45CA936C112B} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6}
|
||||
{C48D0E9D-C862-3EA3-96A7-752EE9D06362} = {233774A8-CC9D-3FA9-86D1-90573E92B704}
|
||||
{B95E7D0E-DB45-3765-9058-E00EBBC4B157} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -368,12 +368,14 @@ TArray<FEncodeVideoInfo> FUtils::TrackEncodeVideo(const FTrackData& TrackData, c
|
||||
|
||||
}
|
||||
|
||||
TArray<FEncodeVideoInfo> FUtils::TrackEncodeAudio(const FTrackData& TrackData, const FString& ExportPath)
|
||||
FEncodeVideoInfo FUtils::TrackEncodeAudio(const FTrackData& TrackData, const FString& ExportPath)
|
||||
{
|
||||
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*FPaths::GetPath(ExportPath));
|
||||
TArray<FClipData> ClipData = TrackData.ClipData;
|
||||
ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; });
|
||||
|
||||
// 先拆出所有音频
|
||||
FEncodeVideoInfo EncodeVideoInfo;
|
||||
FClipData SavedClipData;
|
||||
int32 AudioCount = 0;
|
||||
{
|
||||
int32 i = 0;
|
||||
@ -381,7 +383,7 @@ TArray<FEncodeVideoInfo> FUtils::TrackEncodeAudio(const FTrackData& TrackData, c
|
||||
{
|
||||
if (TempClipData.ResourcePropertyDataPtr->Context)
|
||||
{
|
||||
FEncodeVideoInfo EncodeVideoInfo;
|
||||
SavedClipData = TempClipData;
|
||||
FTimespan EndTimespan = FTimespan::FromSeconds(TempClipData.VideoEndFrame / FGlobalData::GlobalFPS);
|
||||
FTimespan StartTimespan = FTimespan::FromSeconds(TempClipData.VideoStartFrame / FGlobalData::GlobalFPS);
|
||||
|
||||
@ -389,47 +391,50 @@ TArray<FEncodeVideoInfo> FUtils::TrackEncodeAudio(const FTrackData& TrackData, c
|
||||
FString EndTime = FString::Printf(TEXT("%02d:%02d:%02d"), EndTimespan.GetHours(), EndTimespan.GetMinutes(), EndTimespan.GetSeconds());
|
||||
FString InputFile = TempClipData.ResourcePropertyDataPtr->MoviePath;
|
||||
|
||||
FString OutputFile = FPaths::ConvertRelativePathToFull(GetProjectTempPath() / FString::FromInt(i) + TEXT(".mp3"));
|
||||
|
||||
FString OutputFile = ExportPath + TEXT(".mp3");
|
||||
|
||||
int32 StartFrame = (TempClipData.VideoStartFrame) % static_cast<int>(FGlobalData::GlobalFPS);;
|
||||
int32 EndFrame = (TempClipData.VideoEndFrame) % static_cast<int>(FGlobalData::GlobalFPS);
|
||||
|
||||
FString Command = FString::Printf(TEXT("-y -i \"%s\" -ss %s -to %s -c copy \"%s\""),
|
||||
|
||||
FString Command = FString::Printf(TEXT("-y -i \"%s\" -ss %s -to %s \"%s\""),
|
||||
*InputFile, *StartTime, *EndTime, *OutputFile);
|
||||
|
||||
|
||||
FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
FProcHandle ProcHandle = FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
while (FPlatformProcess::IsProcRunning(ProcHandle)){ FPlatformProcess::Sleep(0.1);};
|
||||
i++;
|
||||
AudioCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FString Header = GetFfmepg();
|
||||
for (int32 i = 0; i < ClipData.Num(); i++)
|
||||
if (AudioCount > 1)
|
||||
{
|
||||
Header += " -i ";
|
||||
Header += "\"" + GetProjectTempPath() / FString::FromInt(i) + ".mp3" + "\"";
|
||||
FString Header = GetFfmepg();
|
||||
for (int32 i = 0; i < ClipData.Num(); i++)
|
||||
{
|
||||
Header += " -i ";
|
||||
Header += "\"" + GetProjectTempPath() / FString::FromInt(i) + ".mp3" + "\"";
|
||||
}
|
||||
|
||||
Header += " -filter_complex";
|
||||
|
||||
// [0:0][1:0]...[n:0]concat=n=n=2:v=0:a=1[out]
|
||||
for (int32 i = 0; i < ClipData.Num(); i++)
|
||||
{
|
||||
Header += "[" + FString::FromInt(i) + ":0]";
|
||||
}
|
||||
|
||||
Header += "concat=n=" + FString::FromInt(ClipData.Num()) + ":v=0:a=1[out]";
|
||||
Header += " -map [out] -y " + ExportPath + ".mp3";
|
||||
FProcHandle ProcHandle = FPlatformProcess::CreateProc(*GetFfmepg(), *Header, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
while (FPlatformProcess::IsProcRunning(ProcHandle)){ FPlatformProcess::Sleep(0.1);};
|
||||
}
|
||||
|
||||
Header += " -filter_complex";
|
||||
|
||||
// [0:0][1:0]...[n:0]concat=n=n=2:v=0:a=1[out]
|
||||
for (int32 i = 0; i < ClipData.Num(); i++)
|
||||
{
|
||||
Header += "[" + FString::FromInt(i) + ":0]";
|
||||
}
|
||||
|
||||
Header += "concat=n=" + FString::FromInt(ClipData.Num()) + ":v=0:a=1[out]";
|
||||
Header += " -map [out] -y " + ExportPath + ".mp3";
|
||||
FPlatformProcess::CreateProc(*GetFfmepg(), *Header, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// int32 i = 0;
|
||||
TArray<FEncodeVideoInfo> EncodeVideoInfos;
|
||||
// TArray<FEncodeVideoInfo> EncodeVideoInfos;
|
||||
// for (FClipData& TempClipData : ClipData)
|
||||
// {
|
||||
// if (TempClipData.ResourcePropertyDataPtr->Context)
|
||||
@ -450,8 +455,9 @@ TArray<FEncodeVideoInfo> FUtils::TrackEncodeAudio(const FTrackData& TrackData, c
|
||||
// FString Command = FString::Printf(TEXT("-y -i \"%s\" -ss %s -to %s -c copy \"%s\""),
|
||||
// *InputFile, *StartTime, *EndTime, *OutputFile);
|
||||
//
|
||||
// FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
//
|
||||
// FProcHandle ProcHandle = FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
// while (FPlatformProcess::IsProcRunning(ProcHandle)){ FPlatformProcess::Sleep(0.1);};
|
||||
//
|
||||
// EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.ClipStartFrame);
|
||||
// EncodeVideoInfo.EncodedVideoName = ExportPath + FString::FromInt(i) + TEXT(".mp3");
|
||||
// EncodeVideoInfo.ClipStartFrame = TempClipData.ClipStartFrame;
|
||||
@ -463,14 +469,65 @@ TArray<FEncodeVideoInfo> FUtils::TrackEncodeAudio(const FTrackData& TrackData, c
|
||||
// }
|
||||
// i++;
|
||||
// }
|
||||
return EncodeVideoInfos;
|
||||
|
||||
EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(SavedClipData.ClipStartFrame);
|
||||
EncodeVideoInfo.EncodedVideoName = ExportPath + TEXT(".mp3");
|
||||
EncodeVideoInfo.ClipStartFrame = SavedClipData.ClipStartFrame;
|
||||
EncodeVideoInfo.ClipEndFrame = SavedClipData.ClipEndFrame;
|
||||
|
||||
EncodeVideoInfo.TrackData = TrackData;
|
||||
EncodeVideoInfo.ClipData = SavedClipData;
|
||||
return EncodeVideoInfo;
|
||||
|
||||
}
|
||||
|
||||
TArray<FEncodeVideoInfo> FUtils::CombineAudio(const FEncodeVideoInfo& EncodeVideoInfo,
|
||||
const FEncodeVideoInfo& EncodeAudioInfo, const FString& ExportPath)
|
||||
FEncodeVideoInfo FUtils::CombineAudio(const FEncodeVideoInfo& LeftEncodeData,
|
||||
const FEncodeVideoInfo& RightEncodeData, const FString& ExportPath)
|
||||
{
|
||||
return {};
|
||||
FString LeftPathName = "";
|
||||
FString RightPathName = "";
|
||||
if (FPaths::FileExists(LeftEncodeData.EncodedVideoName))
|
||||
{
|
||||
LeftPathName = LeftEncodeData.EncodedVideoName;
|
||||
}
|
||||
if (FPaths::FileExists(RightEncodeData.EncodedVideoName))
|
||||
{
|
||||
RightPathName = RightEncodeData.EncodedVideoName;
|
||||
}
|
||||
|
||||
FString Command = "";
|
||||
|
||||
if (LeftPathName == "")
|
||||
{
|
||||
Command = FString() + " -i " + "\"" +
|
||||
RightPathName + "\"" + " -y -af \"pan=stereo|c0=0|c1=0\" " + "\"" +
|
||||
ExportPath + ".mp3"+ "\"";
|
||||
}
|
||||
else if (RightPathName == "")
|
||||
{
|
||||
Command = FString() + " -i " + "\"" +
|
||||
LeftPathName + "\"" + " -y -af \"pan=stereo|c0=c0\" " + "\"" +
|
||||
ExportPath + ".mp3"+ "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
Command = FString() + " -i " + "\"" +
|
||||
LeftPathName + "\"" + " -i " + "\"" +
|
||||
RightPathName + "\"" +
|
||||
" -y -filter_complex \"[0:a]pan=1c|c0=c0[a];[1:a]pan=1c|c0=c1[b];[a][b]amerge=inputs=2[aout]\" " +
|
||||
"-map \"[aout]\" " +
|
||||
ExportPath+ ".mp3" + "\"";
|
||||
}
|
||||
|
||||
FProcHandle ProcHandle = FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
|
||||
while (FPlatformProcess::IsProcRunning(ProcHandle)){ FPlatformProcess::Sleep(0.1);};
|
||||
|
||||
FEncodeVideoInfo VideoInfo;
|
||||
VideoInfo.EncodedVideoName = ExportPath + TEXT(".mp3");
|
||||
VideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(LeftEncodeData.ClipStartFrame);
|
||||
VideoInfo.ClipStartFrame = LeftEncodeData.ClipStartFrame;
|
||||
VideoInfo.ClipData = LeftEncodeData.ClipData;
|
||||
return VideoInfo;
|
||||
}
|
||||
|
||||
FString FUtils::GetFfmepg()
|
||||
@ -759,6 +816,10 @@ FString FUtils::Color2Hex3(FColor Color)
|
||||
return FString::Printf(TEXT("%02X%02X%02X"), Color.R, Color.G, Color.B);
|
||||
}
|
||||
|
||||
void FUtils::AddTips(TSharedPtr<SWidget> Widget)
|
||||
{
|
||||
GEngine->GameViewport->AddViewportWidgetContent(Widget.ToSharedRef());
|
||||
}
|
||||
|
||||
|
||||
FSaveModifier::FSaveModifier(const FString& FullSavedPath)
|
||||
|
@ -33,8 +33,8 @@ public:
|
||||
static void CreateDefaultTimelineSave(const FString& SavedPath, const FTimelineInfo::ETimelineType Type);
|
||||
|
||||
static TArray<FEncodeVideoInfo> TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath);
|
||||
static TArray<FEncodeVideoInfo> TrackEncodeAudio(const FTrackData& TrackDataLeft, const FString& ExportPath);
|
||||
static TArray<FEncodeVideoInfo> CombineAudio(const FEncodeVideoInfo& EncodeVideoInfo, const FEncodeVideoInfo& EncodeAudioInfo, const FString& ExportPath);
|
||||
static FEncodeVideoInfo TrackEncodeAudio(const FTrackData& TrackDataLeft, const FString& ExportPath);
|
||||
static FEncodeVideoInfo CombineAudio(const FEncodeVideoInfo& LeftEncodeData, const FEncodeVideoInfo& RightEncodeData, const FString& ExportPath);
|
||||
static FString CurtainFullPath(const FString& GroupName)
|
||||
{
|
||||
// GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FGlobalData::BasePath);
|
||||
@ -88,6 +88,10 @@ public:
|
||||
|
||||
static FString GetMsFromString(FString TimeString);
|
||||
static FString Color2Hex3(FColor Color);
|
||||
|
||||
|
||||
|
||||
static void AddTips(TSharedPtr<SWidget> Widget);
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
@ -140,7 +144,6 @@ T* FUtils::CastTypeByFormat(U* InValue, AVSampleFormat* Format)
|
||||
}
|
||||
|
||||
|
||||
|
||||
class FSaveModifier
|
||||
{
|
||||
public:
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Brushes/SlateBoxBrush.h"
|
||||
#include "Brushes/SlateImageBrush.h"
|
||||
#include "Cut5/Utils/Utils.h"
|
||||
#include "Cut5/Widgets/SCutMainWindow.h"
|
||||
#include "Cut5/Widgets/Style/CutButtonWidgetStyle.h"
|
||||
#include "Widgets/Text/SInlineEditableTextBlock.h"
|
||||
|
||||
@ -124,6 +125,8 @@ FReply SCurtain::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEv
|
||||
|
||||
TSharedPtr<FCurtainDragDrop> SCurtain::OpenThis()
|
||||
{
|
||||
|
||||
CurtainPanel->MainWidgetInterface->GetSelf()->DeselectAll();
|
||||
CurtainPanel->DeSelectedAll();
|
||||
Curtain->bIsActive = true;
|
||||
CurtainPanel->CallRender();
|
||||
|
@ -263,7 +263,16 @@ void SCurtainPanel::AddNewCurtain(int32 Index)
|
||||
{
|
||||
if (Index < Groups.Num())
|
||||
{
|
||||
Groups[Index].Curtains.Add(FCurtain());
|
||||
FCurtain Curtain;
|
||||
FUtils::CreateDefaultTimelineSave(FUtils::CurtainFullPath(Curtain.CurtainUUID.ToString()), FTimelineInfo::ETimelineType::FX);
|
||||
{
|
||||
FSaveModifier SaveModifier(FUtils::CurtainFullPath(Curtain.CurtainUUID.ToString()));
|
||||
SaveModifier.TimelineInfo.CurrentOpenFullPath = FUtils::CurtainFullPath(Curtain.CurtainUUID.ToString());
|
||||
SaveModifier.TimelineInfo.CurrentOpenType = FTimelineInfo::ETimelineType::FX;
|
||||
Curtain.TimelineInfo = SaveModifier.TimelineInfo;
|
||||
}
|
||||
Groups[Index].Curtains.Add(Curtain);
|
||||
|
||||
CallRender();
|
||||
}
|
||||
}
|
||||
|
@ -335,6 +335,8 @@ struct CUT5_API FClipData : public TSharedFromThis<FClipData>
|
||||
Ar << ClipData.VolumeData;
|
||||
Ar << ClipData.bIsCycle;
|
||||
Ar << ClipData.AudioCurtains;
|
||||
Ar << ClipData.bIsVirtual;
|
||||
Ar << ClipData.VirtualCurtainName;
|
||||
return Ar;
|
||||
};
|
||||
|
||||
@ -393,6 +395,12 @@ struct CUT5_API FClipData : public TSharedFromThis<FClipData>
|
||||
}
|
||||
}
|
||||
}
|
||||
void Move(int32 StartFrame)
|
||||
{
|
||||
const int32 OriginStartFrame = ClipStartFrame;
|
||||
ClipStartFrame = StartFrame;
|
||||
ClipEndFrame = ClipEndFrame + (OriginStartFrame - StartFrame);
|
||||
}
|
||||
void CropClip(ECropMethod CropMethod, int32 CropFrame)
|
||||
{
|
||||
if (CropMethod == ECropMethod::FromFront)
|
||||
@ -427,27 +435,35 @@ struct CUT5_API FClipData : public TSharedFromThis<FClipData>
|
||||
FTimelinePropertyData* ResourcePropertyDataPtr = nullptr;
|
||||
FGuid ResourcePropertyGuid;
|
||||
AVSampleFormat SampleFormat;
|
||||
|
||||
// Movies
|
||||
FString MoviePath;
|
||||
int32 VideoStartFrame = 0;
|
||||
int32 VideoEndFrame = 0;
|
||||
cv::VideoCapture* VideoCapture;
|
||||
|
||||
|
||||
// Light Array
|
||||
TArray<TArray<FColor>> LightArrayData;
|
||||
|
||||
|
||||
// Player
|
||||
FString PlayerName;
|
||||
TArray<FColor> PlayerLightData;
|
||||
|
||||
|
||||
|
||||
EPresetType PresetType = EPresetType::NotAPresets;
|
||||
bool bIsVirtual = false;
|
||||
FString VirtualCurtainName = "";
|
||||
|
||||
|
||||
// Placeholder
|
||||
int32 PlaceHolder1 = 0;
|
||||
int32 PlaceHolder2 = 0;
|
||||
int32 PlaceHolder3 = 0;
|
||||
int32 PlaceHolder4 = 0;
|
||||
|
||||
float PlaceHolder5 = 0;
|
||||
float PlaceHolder6 = 0;
|
||||
float PlaceHolder7 = 0;
|
||||
float PlaceHolder8 = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool operator == (const FClipData& Other) const
|
||||
{
|
||||
return ClipGuid == Other.ClipGuid;
|
||||
|
@ -805,8 +805,6 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent&
|
||||
NewClipData.MoviePath = ClipDragOperation.TimelinePropertyData->MoviePath;
|
||||
NewClipData.ClipEndFrame = NewClipData.ClipStartFrame + ClipDragOperation.TimelinePropertyData->MovieFrameLength;
|
||||
NewClipData.VideoEndFrame = ClipDragOperation.TimelinePropertyData->MovieFrameLength;
|
||||
NewClipData.VideoCapture = ClipDragOperation.VideoCapture;
|
||||
|
||||
|
||||
NewClipData.MovieBrushes = FFFMPEGUtils::GetMovieBrush(&NewClipData);
|
||||
|
||||
@ -861,6 +859,7 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent&
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TSharedPtr<STrackHead> TrackHead = StaticCastSharedPtr<STrackBody>(ClipDragOperation.OverrideWidget)->TrackHead;
|
||||
static_cast<SCutMainWindow*>(TrackHead->MainWidgetInterface)->bRenderLine = false;
|
||||
|
||||
@ -912,6 +911,7 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent&
|
||||
TrackHead->TrackData.ClipData.Add(NewClipData);
|
||||
|
||||
UpdateClipProcess(TrackBody->MainWidgetInterface, NewClipData);
|
||||
SavedMainInterface->UpdateProperties(nullptr);
|
||||
TrackBody->CallRender();
|
||||
|
||||
return;
|
||||
|
@ -81,6 +81,8 @@ void SEffectCard::Construct(const FArguments& InArgs)
|
||||
PropertiesInterfaceGUID = CardProperty->Guid;
|
||||
MainInterface->CurrentSelectedPropertiesInterfaceGuid = CardProperty->Guid;
|
||||
MainInterface->UpdateProperties(this);
|
||||
|
||||
MainInterface->GetSelf()->DeselectAll();
|
||||
MainInterface->OnSelectCard(CardProperty->Guid);
|
||||
|
||||
TSharedPtr<FEffectCardDragDrop> EffectCardDragDrop = MakeShared<FEffectCardDragDrop>();
|
||||
|
@ -390,6 +390,7 @@ void SEffectCardGroup::OnSelect()
|
||||
MainInterface->OpenTimeline(Name, true);
|
||||
MainInterface->CurrentSelectedPropertiesInterfaceGuid = EffectCardGroup->Guid;
|
||||
MainInterface->UpdateProperties(this);
|
||||
MainInterface->GetSelf()->DeselectAll();
|
||||
MainInterface->OnSelectCard(EffectCardGroup->Guid);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ void STips::Construct(const FArguments& InArgs)
|
||||
{
|
||||
OnEnsure = InArgs._OnEnsure;
|
||||
FTextBlockStyle NormalText = FAppStyle::GetWidgetStyle<FTextBlockStyle>("NormalText");
|
||||
NormalText.SetFontSize(20);
|
||||
NormalText.SetFontSize(18);
|
||||
ChildSlot
|
||||
[
|
||||
SNew(SOverlay)
|
||||
@ -38,7 +38,7 @@ void STips::Construct(const FArguments& InArgs)
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding(0, 30, 0, 0)
|
||||
.Padding(0, 20, 0, 0)
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Top)
|
||||
[
|
||||
@ -47,7 +47,7 @@ void STips::Construct(const FArguments& InArgs)
|
||||
.TextStyle(&NormalText)
|
||||
]
|
||||
+ SVerticalBox::Slot()
|
||||
.Padding(0, 16, 0, 0)
|
||||
.Padding(0, 5, 0, 0)
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Top)
|
||||
[
|
||||
@ -109,7 +109,7 @@ void STips::Construct(const FArguments& InArgs)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString(TEXT("确定")))
|
||||
.ColorAndOpacity(FSlateColor(FLinearColor(1.0f, 1.0f, 1.0f, 1.0f)))
|
||||
.ColorAndOpacity(FSlateColor(FLinearColor(0.6f, 0.6f, 0.7f, 1.0f)))
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@ -964,7 +964,7 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
|
||||
return;
|
||||
FGlobalData::ExportPath = ExportPath / FGlobalData::CurrentProjectName;
|
||||
|
||||
FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*ExportPath);
|
||||
FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*FGlobalData::ExportPath);
|
||||
|
||||
IDList.Empty();
|
||||
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*FGlobalData::ExportPath);
|
||||
@ -1874,22 +1874,24 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare
|
||||
|
||||
tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo)
|
||||
{
|
||||
|
||||
FTrackData LeftTrackData;
|
||||
FTrackData RightTrackData;
|
||||
int32 TempSoundID = 0;
|
||||
for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||||
{
|
||||
const TSharedPtr<STrackHead> TempTrackHead = StaticCastSharedPtr<STrackHead>(SingleTrackGroupInstance.Head);
|
||||
if (TempTrackHead->TrackData.TrackType != ETrackType::AudioTrackR)
|
||||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrack)
|
||||
LeftTrackData = TempTrackHead->TrackData;
|
||||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrackR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid) != -1)
|
||||
{
|
||||
TempSoundID = GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid);
|
||||
if (GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid) != -1)
|
||||
{
|
||||
TempSoundID = GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid);
|
||||
}
|
||||
RightTrackData = TempTrackHead->TrackData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
tinyxml2::XMLElement* Sound = Parent->InsertNewChildElement("Sound");
|
||||
{
|
||||
@ -1984,8 +1986,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoListElement(tinyxml2::XMLElement*
|
||||
}
|
||||
}
|
||||
FString NewExportFilePath = FGlobalData::ExportPath / "Video" / Filename;
|
||||
GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::White, NewExportFilePath);
|
||||
TArray<FEncodeVideoInfo> EncodeVideoInfos = FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath);
|
||||
// GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::White, NewExportFilePath);
|
||||
TArray<FEncodeVideoInfo> EncodeVideoInfos =
|
||||
FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath);
|
||||
for (const FEncodeVideoInfo EncodeVideoInfo : EncodeVideoInfos)
|
||||
{
|
||||
GetVideoElement(VideoList, EncodeVideoInfo);
|
||||
@ -2005,69 +2008,76 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement*
|
||||
tinyxml2::XMLElement* AudioList = Parent->InsertNewChildElement("SoundList");
|
||||
{
|
||||
int32 Count = 0;
|
||||
bool bGlobalAudio = false;
|
||||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||||
FTrackData LeftTrackData;
|
||||
FTrackData RightTrackData;
|
||||
for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||||
{
|
||||
const FTrackData& TrackData = StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData;
|
||||
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrack ||
|
||||
StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrackR)
|
||||
const TSharedPtr<STrackHead> TempTrackHead = StaticCastSharedPtr<STrackHead>(SingleTrackGroupInstance.Head);
|
||||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrack)
|
||||
LeftTrackData = TempTrackHead->TrackData;
|
||||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrackR)
|
||||
RightTrackData = TempTrackHead->TrackData;
|
||||
}
|
||||
|
||||
TArray<FClipData> SavedClipData = LeftTrackData.ClipData;
|
||||
if (SavedClipData.Num() > 0)
|
||||
{
|
||||
Sort(SavedClipData.GetData(), SavedClipData.Num(), [](const FClipData& ClipDataA, const FClipData& ClipDataB)
|
||||
{
|
||||
FString Filename = GetCurrentSelectFileName();
|
||||
|
||||
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrackR)
|
||||
{
|
||||
Filename += TEXT("_R");
|
||||
}
|
||||
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrack)
|
||||
{
|
||||
Filename += TEXT("_L");
|
||||
}
|
||||
FString NewExportFilePath = FGlobalData::ExportPath / "Sound" / Filename;
|
||||
return ClipDataA.ClipStartFrame < ClipDataB.ClipStartFrame;
|
||||
});
|
||||
if (SavedClipData[0].ClipStartFrame != 0 && SavedClipData[0].bIsVirtual == false)
|
||||
{
|
||||
GetSoundElement(AudioList, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bGlobalAudio = false;
|
||||
FEncodeVideoInfo GlobalAudioEncodeVideoInfo = {};
|
||||
for (const FEncodeVideoInfo& EncodeVideoInfo : AllGlobalSounds)
|
||||
|
||||
bool bIsVirtual = false;
|
||||
for (FClipData& ClipData : LeftTrackData.ClipData)
|
||||
{
|
||||
if (ClipData.bIsVirtual)
|
||||
{
|
||||
bIsVirtual = true;
|
||||
const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName;
|
||||
FEncodeVideoInfo EncodeVideoInfo;
|
||||
EncodeVideoInfo.EncodedVideoName = VirtualFileName;
|
||||
GetSoundElement(AudioList, EncodeVideoInfo);
|
||||
}
|
||||
}
|
||||
if (!bIsVirtual)
|
||||
{
|
||||
for (FClipData& ClipData : RightTrackData.ClipData)
|
||||
{
|
||||
if (ClipData.bIsVirtual)
|
||||
{
|
||||
if (EncodeVideoInfo.ClipData.AudioCurtains.Contains(GetCurrentSelectCurtain()))
|
||||
{
|
||||
bGlobalAudio = true;
|
||||
GlobalAudioEncodeVideoInfo = EncodeVideoInfo;
|
||||
Count++;
|
||||
};
|
||||
}
|
||||
|
||||
if (bGlobalAudio == false)
|
||||
{
|
||||
TArray<FEncodeVideoInfo> EncodeVideoInfos = FUtils::TrackEncodeAudio(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath);
|
||||
|
||||
for (const FEncodeVideoInfo EncodeVideoInfo : EncodeVideoInfos)
|
||||
{
|
||||
if (EncodeVideoInfo.ClipData.AudioCurtains.Num() > 0)
|
||||
{
|
||||
AllGlobalSounds.Add(EncodeVideoInfo);
|
||||
}
|
||||
}
|
||||
for (const FEncodeVideoInfo EncodeVideoInfo : EncodeVideoInfos)
|
||||
{
|
||||
GetSoundElement(AudioList, EncodeVideoInfo);
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetSoundElement(AudioList, GlobalAudioEncodeVideoInfo);
|
||||
bIsVirtual = true;
|
||||
const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName;
|
||||
FEncodeVideoInfo EncodeVideoInfo;
|
||||
EncodeVideoInfo.EncodedVideoName = VirtualFileName;
|
||||
GetSoundElement(AudioList, EncodeVideoInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (Count == 0 && !bGlobalAudio)
|
||||
if (!bIsVirtual)
|
||||
{
|
||||
GetSoundElement(AudioList, FEncodeVideoInfo());
|
||||
const FString LeftFilename = GetCurrentSelectFileName() + TEXT("_L");
|
||||
const FString RightFilename = GetCurrentSelectFileName() + TEXT("_R");
|
||||
const FString LeftNewExportFilePath = FUtils::GetProjectTempPath() / "Sound" / LeftFilename;
|
||||
const FString RightNewExportFilePath = FUtils::GetProjectTempPath() / "Sound" / RightFilename;
|
||||
const FEncodeVideoInfo LeftEncodeVideoInfos = FUtils::TrackEncodeAudio(LeftTrackData, LeftNewExportFilePath);
|
||||
const FEncodeVideoInfo RightEncodeVideoInfos = FUtils::TrackEncodeAudio(RightTrackData, RightNewExportFilePath);
|
||||
|
||||
const FString ExportFilename = FGlobalData::ExportPath / "Sound" / GetCurrentSelectFileName();
|
||||
const FEncodeVideoInfo End = FUtils::CombineAudio(LeftEncodeVideoInfos, RightEncodeVideoInfos, ExportFilename);
|
||||
|
||||
GetSoundElement(AudioList, End);
|
||||
}
|
||||
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -2391,6 +2401,21 @@ FGuid SCutMainWindow::GetCurrentSelectCurtain() const
|
||||
return FGuid();
|
||||
}
|
||||
|
||||
FTimelineInfo SCutMainWindow::GetCurrentSelectCurtainTimelineInfo() const
|
||||
{
|
||||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||||
{
|
||||
for (const FCurtain& Curtain : CurtainGroup.Curtains)
|
||||
{
|
||||
if (Curtain.bIsActive)
|
||||
{
|
||||
return Curtain.TimelineInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FTimelineInfo();
|
||||
}
|
||||
|
||||
bool SCutMainWindow::IsSelectCurtain() const
|
||||
{
|
||||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||||
@ -2425,6 +2450,9 @@ void SCutMainWindow::DeselectAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CurtainPanel->CallRender();
|
||||
EffectCardsPanel->CallRender();
|
||||
}
|
||||
|
||||
int32 SCutMainWindow::GetTrackID(FGuid Guid) const
|
||||
|
@ -125,7 +125,10 @@ public:
|
||||
tinyxml2::XMLElement* GetFlashLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData);
|
||||
tinyxml2::XMLElement* GetGradientLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData);
|
||||
FString GetCurrentSelectFileName() const;
|
||||
|
||||
|
||||
FGuid GetCurrentSelectCurtain() const;
|
||||
FTimelineInfo GetCurrentSelectCurtainTimelineInfo() const;
|
||||
bool IsSelectCurtain() const;
|
||||
void DeselectAll();
|
||||
|
||||
|
@ -62,6 +62,7 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F
|
||||
MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().AddVolumeHere);
|
||||
}
|
||||
|
||||
|
||||
if (ClipData->ClipType != ETrackType::ProjectorTrack)
|
||||
{
|
||||
if (ClipData->bIsCycle)
|
||||
@ -84,6 +85,11 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
|
||||
if (ClipData->bIsVirtual)
|
||||
return FReply::Handled();
|
||||
|
||||
|
||||
TSharedPtr<FClipProxy> ClipProxy = FClipProxy::GetProxy();
|
||||
ClipProxy->UpdateInterface(SharedThis(this));
|
||||
|
||||
@ -645,6 +651,10 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe
|
||||
{
|
||||
FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("循环播放")), FAppStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White);
|
||||
}
|
||||
if (ClipData->bIsVirtual == true)
|
||||
{
|
||||
FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("虚拟轨道(不可编辑)")), FAppStyle::Get().GetWidgetStyle<FTextBlockStyle>("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White);
|
||||
}
|
||||
|
||||
|
||||
if (MainWidgetInterface->GetCutTimeline()->SelectedClips.Contains(ClipData->ClipGuid))
|
||||
|
@ -0,0 +1,71 @@
|
||||
#include "TimelineLoader.h"
|
||||
|
||||
FTimelineLoader::FTimelineLoader(const FString& LoadPath, bool bNeedSaveWhenExit)
|
||||
{
|
||||
this->bNeedSaveWhenExit = bNeedSaveWhenExit;
|
||||
this->LoadPath = FPaths::ConvertRelativePathToFull(LoadPath);
|
||||
|
||||
TArray<uint8> LoadData;
|
||||
const bool Response = FFileHelper::LoadFileToArray(LoadData, *this->LoadPath);
|
||||
|
||||
if (LoadData.Num() == 0 || !Response)
|
||||
{
|
||||
return;
|
||||
}
|
||||
FMemoryReader MemoryReader(LoadData, false);
|
||||
MemoryReader << TimelineInfo;
|
||||
int32 ClipCount = 0;
|
||||
MemoryReader << ClipCount;
|
||||
MemoryReader << ClipData;
|
||||
}
|
||||
|
||||
FTimelineLoader::~FTimelineLoader()
|
||||
{
|
||||
if (bNeedSaveWhenExit)
|
||||
{
|
||||
TArray<uint8> SaveData;
|
||||
FMemoryWriter MemoryWriter(SaveData, false);
|
||||
int32 ClipCount = ClipData.Num();
|
||||
MemoryWriter << TimelineInfo;
|
||||
MemoryWriter << ClipCount;
|
||||
MemoryWriter << ClipData;
|
||||
FFileHelper::SaveArrayToFile(SaveData, *LoadPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TArray<FClipData> FTimelineLoader::GetSpecifyClipData(const FTrackData& TrackData) const
|
||||
{
|
||||
TArray<FClipData> ResultClipData;
|
||||
for (const FClipData& Clip : ClipData)
|
||||
{
|
||||
if (Clip.BindTrackGuid == TrackData.DeviceTrack.Guid)
|
||||
{
|
||||
ResultClipData.Add(Clip);
|
||||
}
|
||||
}
|
||||
return ResultClipData;
|
||||
}
|
||||
|
||||
TArray<FClipData> FTimelineLoader::GetSpecifyClipData(const ETrackType TrackType) const
|
||||
{
|
||||
TArray<FClipData> ResultClipData;
|
||||
for (const FClipData& Clip : ClipData)
|
||||
{
|
||||
if (Clip.ClipType == TrackType)
|
||||
{
|
||||
ResultClipData.Add(Clip);
|
||||
}
|
||||
}
|
||||
return ResultClipData;
|
||||
}
|
||||
|
||||
void FTimelineLoader::RemoveClipData(int32 Index)
|
||||
{
|
||||
ClipData.RemoveAt(Index);
|
||||
}
|
||||
|
||||
void FTimelineLoader::RemoveClipData(const FClipData& RemoveClipData)
|
||||
{
|
||||
ClipData.Remove(RemoveClipData);
|
||||
}
|
25
Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.h
Normal file
25
Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "Cut5/Widgets/DefineGlobal.h"
|
||||
|
||||
class FTimelineLoader
|
||||
{
|
||||
private:
|
||||
FString Version = "1.0.1";
|
||||
bool bNeedSaveWhenExit = false;
|
||||
FString LoadPath = "";
|
||||
|
||||
FTimelineInfo TimelineInfo;
|
||||
TArray<FClipData> ClipData;
|
||||
|
||||
|
||||
public:
|
||||
explicit FTimelineLoader(const FString& LoadPath, bool bNeedSaveWhenExit = false);
|
||||
~FTimelineLoader();
|
||||
|
||||
TArray<FClipData> GetSpecifyClipData(const FTrackData& TrackData) const;
|
||||
TArray<FClipData> GetSpecifyClipData(const ETrackType TrackType) const;
|
||||
TArray<FClipData>& GetClipData() { return ClipData; }
|
||||
void RemoveClipData(int32 Index = 0);
|
||||
void RemoveClipData(const FClipData& RemoveClipData);
|
||||
FTimelineInfo& GetTimelineInfo() { return TimelineInfo; }
|
||||
};
|
@ -5,6 +5,8 @@
|
||||
#include "Cut5/Widgets/SCutTimeline.h"
|
||||
#include "Cut5/Widgets/STimelineClip.h"
|
||||
#include "Cut5/Widgets/MicroWidgets/SNewProjectTips.h"
|
||||
#include "Cut5/Widgets/MicroWidgets/STips.h"
|
||||
#include "Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.h"
|
||||
#include "Widgets/Input/SSpinBox.h"
|
||||
#include "Widgets/Layout/SSpacer.h"
|
||||
|
||||
@ -331,15 +333,19 @@ TSharedPtr<SWidget> FClipProxy::GetPropertiesWidget()
|
||||
];
|
||||
}
|
||||
|
||||
if (ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR)
|
||||
if ((ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) && MainInterface->GetSelf()->GetCurrentSelectCurtain() != FGuid())
|
||||
{
|
||||
|
||||
AudiosCurtainOptions.Empty();
|
||||
TArray<FCurtainGroup>& Groups = MainInterface->GetSelf()->CurtainPanel->Groups;
|
||||
for (FCurtainGroup& Group : Groups)
|
||||
{
|
||||
for (FCurtain& Curtain : Group.Curtains)
|
||||
{
|
||||
AudiosCurtainOptions.Add(MakeShared<FStringWithGUID>(Curtain.CurtainName, Curtain.CurtainUUID));
|
||||
if (Curtain.CurtainUUID != MainInterface->GetSelf()->GetCurrentSelectCurtain())
|
||||
{
|
||||
AudiosCurtainOptions.Add(MakeShared<FStringWithGUID>(Curtain.CurtainName, Curtain.CurtainUUID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,18 +393,84 @@ TSharedPtr<SWidget> FClipProxy::GetPropertiesWidget()
|
||||
.IsChecked(ClipData->AudioCurtains.Contains(*InItem.Get()) ? ECheckBoxState::Checked : ECheckBoxState::Unchecked)
|
||||
.OnCheckStateChanged_Lambda([this, InItem](const ECheckBoxState& State)
|
||||
{
|
||||
if (State == ECheckBoxState::Checked)
|
||||
const FGuid& Guid = InItem.Get()->Guid;
|
||||
FCurtainGroup* Group = nullptr;
|
||||
const FString CurrentPath = MainInterface->GetSelf()->CurtainPanel->FindCurtain(Guid,Group)->TimelineInfo.CurrentOpenFullPath;
|
||||
FTimelineLoader TimelineLoader(CurrentPath, true);
|
||||
if (TimelineLoader.GetSpecifyClipData(ClipData->ClipType).Num() > 0 && State == ECheckBoxState::Checked)
|
||||
{
|
||||
ClipData->AudioCurtains.Add(*InItem.Get());
|
||||
MainInterface->UpdateProperties(this);
|
||||
FUtils::AddTips(
|
||||
SNew(STips)
|
||||
.Title(TEXT("警告"))
|
||||
.SubTitle(TEXT("选中的幕中的音频轨道已经存在音频片段\n如果继续添加,将会覆盖原有的音频片段\n是否继续?"))
|
||||
.OnEnsure_Lambda([this, State, InItem, CurrentPath](const FString& String)
|
||||
{
|
||||
// 先清空
|
||||
FTimelineLoader ModifyTimelineLoader(CurrentPath, true);
|
||||
TArray<FClipData> 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.VirtualCurtainName = MainInterface->GetSelf()->GetCurrentSelectFileName();
|
||||
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
|
||||
{
|
||||
ClipData->AudioCurtains.Remove(*InItem.Get());
|
||||
MainInterface->UpdateProperties(this);
|
||||
if (State == ECheckBoxState::Checked)
|
||||
{
|
||||
FClipData NewClip = *ClipData;
|
||||
NewClip.Move(0);
|
||||
NewClip.bIsVirtual = true;
|
||||
NewClip.VirtualCurtainName = MainInterface->GetSelf()->GetCurrentSelectFileName();
|
||||
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<FClipData> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
];
|
||||
|
||||
|
BIN
Subproject/新建项目名字/Curtain/44F39C3D4878F8AFAA8DC69BF0102AEB.bin
Normal file
BIN
Subproject/新建项目名字/Curtain/44F39C3D4878F8AFAA8DC69BF0102AEB.bin
Normal file
Binary file not shown.
BIN
Subproject/新建项目名字/Curtain/4CD7D4EC429C032451CD4292ECD15AEF.bin
Normal file
BIN
Subproject/新建项目名字/Curtain/4CD7D4EC429C032451CD4292ECD15AEF.bin
Normal file
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
BIN
Subproject/新建项目名字/新建项目名字.bin
Normal file
BIN
Subproject/新建项目名字/新建项目名字.bin
Normal file
Binary file not shown.
BIN
Subproject/新建项目名字/新建项目名字.cutlink
Normal file
BIN
Subproject/新建项目名字/新建项目名字.cutlink
Normal file
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 114 KiB |
Binary file not shown.
Before Width: | Height: | Size: 114 KiB |
Binary file not shown.
Before Width: | Height: | Size: 195 KiB |
Binary file not shown.
Before Width: | Height: | Size: 297 KiB |
Binary file not shown.
Before Width: | Height: | Size: 189 KiB |
Loading…
Reference in New Issue
Block a user