diff --git a/Asset/1.wav b/Asset/1.wav new file mode 100644 index 0000000..93c6ae4 Binary files /dev/null and b/Asset/1.wav differ diff --git a/Asset/A.mp3 b/Asset/A.mp3 new file mode 100644 index 0000000..752ad20 Binary files /dev/null and b/Asset/A.mp3 differ diff --git a/Asset/Start.bat b/Asset/Start.bat new file mode 100644 index 0000000..1f9b30d --- /dev/null +++ b/Asset/Start.bat @@ -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 \ No newline at end of file diff --git a/Asset/output.mp3 b/Asset/output.mp3 new file mode 100644 index 0000000..9429ae2 Binary files /dev/null and b/Asset/output.mp3 differ diff --git a/Cut5.sln b/Cut5.sln index 6b74737..8e330d5 100644 --- a/Cut5.sln +++ b/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 diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index 1c9dc02..b8a986b 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -368,12 +368,14 @@ TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, c } -TArray 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 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 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 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(FGlobalData::GlobalFPS);; int32 EndFrame = (TempClipData.VideoEndFrame) % static_cast(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 EncodeVideoInfos; + // TArray EncodeVideoInfos; // for (FClipData& TempClipData : ClipData) // { // if (TempClipData.ResourcePropertyDataPtr->Context) @@ -450,8 +455,9 @@ TArray 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 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 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 Widget) +{ + GEngine->GameViewport->AddViewportWidgetContent(Widget.ToSharedRef()); +} FSaveModifier::FSaveModifier(const FString& FullSavedPath) diff --git a/Source/Cut5/Utils/Utils.h b/Source/Cut5/Utils/Utils.h index 14a4349..c4c7a66 100644 --- a/Source/Cut5/Utils/Utils.h +++ b/Source/Cut5/Utils/Utils.h @@ -33,8 +33,8 @@ public: static void CreateDefaultTimelineSave(const FString& SavedPath, const FTimelineInfo::ETimelineType Type); static TArray TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath); - static TArray TrackEncodeAudio(const FTrackData& TrackDataLeft, const FString& ExportPath); - static TArray 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 Widget); }; template @@ -140,7 +144,6 @@ T* FUtils::CastTypeByFormat(U* InValue, AVSampleFormat* Format) } - class FSaveModifier { public: diff --git a/Source/Cut5/Widgets/Curtain/SCurtain.cpp b/Source/Cut5/Widgets/Curtain/SCurtain.cpp index 0cf5d58..98bf1d0 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtain.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtain.cpp @@ -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 SCurtain::OpenThis() { + + CurtainPanel->MainWidgetInterface->GetSelf()->DeselectAll(); CurtainPanel->DeSelectedAll(); Curtain->bIsActive = true; CurtainPanel->CallRender(); diff --git a/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp b/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp index 6e65830..e2e0b89 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp @@ -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(); } } diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 6a08379..1dc29e8 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -335,6 +335,8 @@ struct CUT5_API FClipData : public TSharedFromThis 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 } } } + 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 FTimelinePropertyData* ResourcePropertyDataPtr = nullptr; FGuid ResourcePropertyGuid; AVSampleFormat SampleFormat; - // Movies FString MoviePath; int32 VideoStartFrame = 0; int32 VideoEndFrame = 0; - cv::VideoCapture* VideoCapture; - - // Light Array TArray> LightArrayData; - - // Player FString PlayerName; TArray 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; diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index deffcb9..5288eda 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -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 TrackHead = StaticCastSharedPtr(ClipDragOperation.OverrideWidget)->TrackHead; static_cast(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; diff --git a/Source/Cut5/Widgets/FX/SEffectCard.cpp b/Source/Cut5/Widgets/FX/SEffectCard.cpp index 92bb7fc..e9a2242 100644 --- a/Source/Cut5/Widgets/FX/SEffectCard.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCard.cpp @@ -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 EffectCardDragDrop = MakeShared(); diff --git a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp index 48f173e..5212bd7 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp @@ -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); } } diff --git a/Source/Cut5/Widgets/MicroWidgets/STips.cpp b/Source/Cut5/Widgets/MicroWidgets/STips.cpp index 9631e7c..4483045 100644 --- a/Source/Cut5/Widgets/MicroWidgets/STips.cpp +++ b/Source/Cut5/Widgets/MicroWidgets/STips.cpp @@ -12,7 +12,7 @@ void STips::Construct(const FArguments& InArgs) { OnEnsure = InArgs._OnEnsure; FTextBlockStyle NormalText = FAppStyle::GetWidgetStyle("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))) ] ] ] diff --git a/Source/Cut5/Widgets/SCutMainWindow.cpp b/Source/Cut5/Widgets/SCutMainWindow.cpp index 9d08029..fc78bca 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.cpp +++ b/Source/Cut5/Widgets/SCutMainWindow.cpp @@ -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 TempTrackHead = StaticCastSharedPtr(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 EncodeVideoInfos = FUtils::TrackEncodeVideo(StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath); + // GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::White, NewExportFilePath); + TArray EncodeVideoInfos = + FUtils::TrackEncodeVideo(StaticCastSharedPtr(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(CutTimeline->TrackGroupInstances[i].Head)->TrackData; - if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrack || - StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrackR) + const TSharedPtr TempTrackHead = StaticCastSharedPtr(SingleTrackGroupInstance.Head); + if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrack) + LeftTrackData = TempTrackHead->TrackData; + if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrackR) + RightTrackData = TempTrackHead->TrackData; + } + + TArray SavedClipData = LeftTrackData.ClipData; + if (SavedClipData.Num() > 0) + { + Sort(SavedClipData.GetData(), SavedClipData.Num(), [](const FClipData& ClipDataA, const FClipData& ClipDataB) { - FString Filename = GetCurrentSelectFileName(); - - if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrackR) - { - Filename += TEXT("_R"); - } - if (StaticCastSharedPtr(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 EncodeVideoInfos = FUtils::TrackEncodeAudio(StaticCastSharedPtr(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 diff --git a/Source/Cut5/Widgets/SCutMainWindow.h b/Source/Cut5/Widgets/SCutMainWindow.h index 9d6310d..1884dec 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.h +++ b/Source/Cut5/Widgets/SCutMainWindow.h @@ -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(); diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index d0ccd50..f3f8a65 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -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 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("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } + if (ClipData->bIsVirtual == true) + { + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("虚拟轨道(不可编辑)")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + } if (MainWidgetInterface->GetCutTimeline()->SelectedClips.Contains(ClipData->ClipGuid)) diff --git a/Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.cpp b/Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.cpp new file mode 100644 index 0000000..ce4b612 --- /dev/null +++ b/Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.cpp @@ -0,0 +1,71 @@ +#include "TimelineLoader.h" + +FTimelineLoader::FTimelineLoader(const FString& LoadPath, bool bNeedSaveWhenExit) +{ + this->bNeedSaveWhenExit = bNeedSaveWhenExit; + this->LoadPath = FPaths::ConvertRelativePathToFull(LoadPath); + + TArray 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 SaveData; + FMemoryWriter MemoryWriter(SaveData, false); + int32 ClipCount = ClipData.Num(); + MemoryWriter << TimelineInfo; + MemoryWriter << ClipCount; + MemoryWriter << ClipData; + FFileHelper::SaveArrayToFile(SaveData, *LoadPath); + } +} + + +TArray FTimelineLoader::GetSpecifyClipData(const FTrackData& TrackData) const +{ + TArray ResultClipData; + for (const FClipData& Clip : ClipData) + { + if (Clip.BindTrackGuid == TrackData.DeviceTrack.Guid) + { + ResultClipData.Add(Clip); + } + } + return ResultClipData; +} + +TArray FTimelineLoader::GetSpecifyClipData(const ETrackType TrackType) const +{ + TArray 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); +} diff --git a/Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.h b/Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.h new file mode 100644 index 0000000..0cc9cc0 --- /dev/null +++ b/Source/Cut5/Widgets/SaveConverter/Timeline/TimelineLoader.h @@ -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 ClipData; + + +public: + explicit FTimelineLoader(const FString& LoadPath, bool bNeedSaveWhenExit = false); + ~FTimelineLoader(); + + TArray GetSpecifyClipData(const FTrackData& TrackData) const; + TArray GetSpecifyClipData(const ETrackType TrackType) const; + TArray& GetClipData() { return ClipData; } + void RemoveClipData(int32 Index = 0); + void RemoveClipData(const FClipData& RemoveClipData); + FTimelineInfo& GetTimelineInfo() { return TimelineInfo; } +}; diff --git a/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp b/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp index 04c2afb..6e18046 100644 --- a/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp +++ b/Source/Cut5/Widgets/TimelineClips/ClipProxy.cpp @@ -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 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& Groups = MainInterface->GetSelf()->CurtainPanel->Groups; for (FCurtainGroup& Group : Groups) { for (FCurtain& Curtain : Group.Curtains) { - AudiosCurtainOptions.Add(MakeShared(Curtain.CurtainName, Curtain.CurtainUUID)); + if (Curtain.CurtainUUID != MainInterface->GetSelf()->GetCurrentSelectCurtain()) + { + AudiosCurtainOptions.Add(MakeShared(Curtain.CurtainName, Curtain.CurtainUUID)); + } } } @@ -387,18 +393,84 @@ TSharedPtr 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 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 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); + } } - - + + + + + }) ]; diff --git a/Subproject/新建项目名字/Curtain/44F39C3D4878F8AFAA8DC69BF0102AEB.bin b/Subproject/新建项目名字/Curtain/44F39C3D4878F8AFAA8DC69BF0102AEB.bin new file mode 100644 index 0000000..a3d8091 Binary files /dev/null and b/Subproject/新建项目名字/Curtain/44F39C3D4878F8AFAA8DC69BF0102AEB.bin differ diff --git a/Subproject/新建项目名字/Curtain/4CD7D4EC429C032451CD4292ECD15AEF.bin b/Subproject/新建项目名字/Curtain/4CD7D4EC429C032451CD4292ECD15AEF.bin new file mode 100644 index 0000000..feb4e14 Binary files /dev/null and b/Subproject/新建项目名字/Curtain/4CD7D4EC429C032451CD4292ECD15AEF.bin differ diff --git a/Subproject/新建项目名字/Resources/Thumbnail/804D18794F966498A7E2C4A9677282C2.png b/Subproject/新建项目名字/Resources/Thumbnail/804D18794F966498A7E2C4A9677282C2.png new file mode 100644 index 0000000..5a9a50b Binary files /dev/null and b/Subproject/新建项目名字/Resources/Thumbnail/804D18794F966498A7E2C4A9677282C2.png differ diff --git a/Subproject/新建项目名字/新建项目名字.bin b/Subproject/新建项目名字/新建项目名字.bin new file mode 100644 index 0000000..8a55263 Binary files /dev/null and b/Subproject/新建项目名字/新建项目名字.bin differ diff --git a/Subproject/新建项目名字/新建项目名字.cutlink b/Subproject/新建项目名字/新建项目名字.cutlink new file mode 100644 index 0000000..11245d5 Binary files /dev/null and b/Subproject/新建项目名字/新建项目名字.cutlink differ diff --git a/Temp/973F81CF4C990C5F6172D19562DC4CE2.png b/Temp/973F81CF4C990C5F6172D19562DC4CE2.png deleted file mode 100644 index a0c0302..0000000 Binary files a/Temp/973F81CF4C990C5F6172D19562DC4CE2.png and /dev/null differ diff --git a/Temp/A7F104E44C6D332967FCF59024DA15D0.png b/Temp/A7F104E44C6D332967FCF59024DA15D0.png deleted file mode 100644 index a0c0302..0000000 Binary files a/Temp/A7F104E44C6D332967FCF59024DA15D0.png and /dev/null differ diff --git a/Temp/B1F5BF2148B5A9FE7CB82BAE711CC5CB b/Temp/B1F5BF2148B5A9FE7CB82BAE711CC5CB deleted file mode 100644 index ea4a4a1..0000000 Binary files a/Temp/B1F5BF2148B5A9FE7CB82BAE711CC5CB and /dev/null differ diff --git a/Temp/DDB7B76E4E3D9044E0FDB4A5788982F7.png b/Temp/DDB7B76E4E3D9044E0FDB4A5788982F7.png deleted file mode 100644 index d38a8d2..0000000 Binary files a/Temp/DDB7B76E4E3D9044E0FDB4A5788982F7.png and /dev/null differ diff --git a/Temp/DEBFE51B416C3ACB99F045876844E347.png b/Temp/DEBFE51B416C3ACB99F045876844E347.png deleted file mode 100644 index ff10f6a..0000000 Binary files a/Temp/DEBFE51B416C3ACB99F045876844E347.png and /dev/null differ