From 0a1e95ef90412fcab1aec951cacc62abca8a516c Mon Sep 17 00:00:00 2001 From: Sch <3516520171@qq.com> Date: Mon, 4 Sep 2023 22:43:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E5=A4=A7=E5=A0=86?= =?UTF-8?q?=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cut5.sln | 60 ++- Cut5.sln.DotSettings.user | 2 + Resources/OutOfFile.png | Bin 0 -> 76459 bytes Source/Cut5/Interface/VideoInterface.cpp | 95 +++-- Source/Cut5/Utils/Utils.cpp | 344 +++++++++++------- Source/Cut5/Widgets/Curtain/SCurtain.cpp | 2 +- Source/Cut5/Widgets/DefineGlobal.h | 23 +- .../DragDropOperator/DragDropOperator.cpp | 20 +- Source/Cut5/Widgets/SCutMainWindow.cpp | 333 ++++++++++++----- Source/Cut5/Widgets/SCutMainWindow.h | 28 ++ Source/Cut5/Widgets/SCutTimeline.cpp | 2 - Source/Cut5/Widgets/STimelineClip.cpp | 17 +- Source/Cut5/Widgets/STrackBody.cpp | 1 - 13 files changed, 612 insertions(+), 315 deletions(-) create mode 100644 Cut5.sln.DotSettings.user create mode 100644 Resources/OutOfFile.png diff --git a/Cut5.sln b/Cut5.sln index 8e330d5..6b74737 100644 --- a/Cut5.sln +++ b/Cut5.sln @@ -7,67 +7,49 @@ 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}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{B95E7D0E-DB45-3765-9058-E00EBBC4B157}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{6EE39883-7339-3FB6-AD82-931FB137D37F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{C48D0E9D-C862-3EA3-96A7-752EE9D06362}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{AF5A253A-0F37-38CE-8998-45CA936C112B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Visualizers", "Visualizers", "{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}" ProjectSection(SolutionItems) = preProject - ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis + D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = D:\UE\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;Android + AvailablePlatforms=Win64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {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 + {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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {C48D0E9D-C862-3EA3-96A7-752EE9D06362} = {233774A8-CC9D-3FA9-86D1-90573E92B704} - {B95E7D0E-DB45-3765-9058-E00EBBC4B157} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6} + {6EE39883-7339-3FB6-AD82-931FB137D37F} = {233774A8-CC9D-3FA9-86D1-90573E92B704} + {AF5A253A-0F37-38CE-8998-45CA936C112B} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6} EndGlobalSection EndGlobal diff --git a/Cut5.sln.DotSettings.user b/Cut5.sln.DotSettings.user new file mode 100644 index 0000000..82c3d3d --- /dev/null +++ b/Cut5.sln.DotSettings.user @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Resources/OutOfFile.png b/Resources/OutOfFile.png new file mode 100644 index 0000000000000000000000000000000000000000..7df42a7e65ce456ecf43712c41c62defde486f97 GIT binary patch literal 76459 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 R{PV4pwidth, AllocatedFrame->height, VideoCodecContext->pix_fmt, - AllocatedFrame->width, AllocatedFrame->height, AV_PIX_FMT_BGRA, - SWS_BILINEAR, nullptr, nullptr, nullptr - ); - if (!SwsCtx) + uint8* RawData = nullptr; + + int32 Width = AllocatedFrame->width; + if (ClipData.ClipType == ETrackType::LightArrayTrack) { - UE_LOG(LogTemp, Error, TEXT("Error creating swsContext")); - CurrentSeekingFrame = -1; - continue;; + RawData = new uint8[FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4]; + Width = FGlobalData::LightArrayX; + } + else if (ClipData.ClipType == ETrackType::VideoTrack) + { + RawData = new uint8[AllocatedFrame->width * AllocatedFrame->height * 4]; + Width = AllocatedFrame->width; } - - - uint8* RawData = new uint8[AllocatedFrame->width * AllocatedFrame->height * 4]; uint8* Dest[4] = {RawData, nullptr, nullptr, nullptr}; - const int32 DestLineSize[4] = {AllocatedFrame->width * 4, 0, 0, 0}; - sws_scale(SwsCtx, AllocatedFrame->data, AllocatedFrame->linesize, 0, AllocatedFrame->height, Dest, DestLineSize); - sws_freeContext(SwsCtx); + int32 DestLineSize[4] = {Width * 4, 0, 0, 0}; - int32 DataSize = AllocatedFrame->width * AllocatedFrame->height * 4; + + if (AllocatedFrame->data[0] == nullptr) { CurrentSeekingFrame = -1; delete RawData; continue;; } + + if (ClipData.ClipType == ETrackType::VideoTrack) + { + + + + + const AVCodecContext* VideoCodecContext = NewPropertyData.VideoCodecContext; + struct SwsContext* SwsCtx = sws_getContext( + AllocatedFrame->width, AllocatedFrame->height, VideoCodecContext->pix_fmt, + AllocatedFrame->width, AllocatedFrame->height, 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); + + } + else if (ClipData.ClipType == ETrackType::LightArrayTrack) + { + + + 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; int32 Y = AllocatedFrame->height; - AsyncTask(ENamedThreads::GameThread, [this, X, Y, RawData]() + + AsyncTask(ENamedThreads::GameThread, [this, X, Y, RawData, AllocatedFrame]() { - MainInterface->OnUpdateVideo(FGuid(), X, Y, RawData); - - + if (ClipData.ClipType == ETrackType::VideoTrack) + { + MainInterface->OnUpdateVideo(FGuid(), X, Y, RawData); + } + if (ClipData.ClipType == ETrackType::LightArrayTrack) + { + TArray ColorArray; + ColorArray.Init(FColor::Black, FGlobalData::LightArrayX * FGlobalData::LightArrayY); + FMemory::Memcpy(ColorArray.GetData(), RawData, FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4); + MainInterface->OnUpdateLightArray(ColorArray); + } }); + + // }); LastFrame = av_frame_alloc(); // av_frame_copy(LastFrame, AllocatedFrame); LastFrame = av_frame_clone(AllocatedFrame); diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index defaaa2..67fac56 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -419,7 +419,7 @@ FString FUtils::GetFfmepg() TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& ExportPath) { - using namespace cv; + using namespace cv; TArray ClipData = TrackData.ClipData; ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; }); TArray EncodeVideoInfos; @@ -429,153 +429,243 @@ TArray FUtils::ExportPsaf(FTrackData TrackData, const FString& FString ExportName = FGuid::NewGuid().ToString();; if (TempClipData.ResourcePropertyDataPtr) { - FTimelinePropertyData PropertyData; - FFFMPEGUtils::LoadContextPure(TempClipData.ResourcePropertyDataPtr->MoviePath, &PropertyData); - const FString PsafSavePath = ExportPath + FString::FromInt(i) + ".psaf"; - - int32 TimeStamp = av_rescale_q(static_cast(TempClipData.VideoStartFrame) / FGlobalData::GlobalFPS * AV_TIME_BASE, AVRational{1, AV_TIME_BASE}, PropertyData.Context->streams[PropertyData.VideoStream]->time_base); - int32 EndTimeStamp = av_rescale_q(static_cast(TempClipData.VideoEndFrame) / FGlobalData::GlobalFPS * AV_TIME_BASE, AVRational{1, AV_TIME_BASE}, PropertyData.Context->streams[PropertyData.VideoStream]->time_base); - av_seek_frame(PropertyData.Context, PropertyData.VideoStream, TimeStamp, AVSEEK_FLAG_BACKWARD); - - - TArray LightArrayResult; - uint8 Width = FGlobalData::LightArrayX; - uint8 Height = FGlobalData::LightArrayY; - uint8 p[128] = "pasf"; - LightArrayResult.Append(p, 128); - + TempClipData.ResourcePropertyDataPtr->MoviePath; + FString TempPath = TempClipData.ResourcePropertyDataPtr->MoviePath; + frames.Empty(); - AVPacket* Packet = av_packet_alloc(); - AVFrame* Frame = av_frame_alloc(); - while (av_read_frame(PropertyData.Context, Packet) >= 0) - { - avcodec_send_packet(PropertyData.VideoCodecContext, Packet); - int32 Response = avcodec_receive_frame(PropertyData.VideoCodecContext, Frame); - if (Response == AVERROR(EAGAIN) || AVERROR_EOF) - { - + VideoCapture capture; + bool ret = capture.open(TCHAR_TO_UTF8(*TempPath)); + + + //setNumThreads(2); + + std::ofstream outfile; + + FString leftStr; + FString rightStr; + + FString SourceLeft; + FString SourceRight; + UKismetStringLibrary::Split(TempPath,".",SourceLeft, SourceRight, ESearchCase::IgnoreCase,ESearchDir::FromEnd); + UKismetStringLibrary::Split(SourceLeft,"/",SourceLeft, SourceRight, ESearchCase::IgnoreCase,ESearchDir::FromEnd); + + + + + FString psafPath = ExportPath + ExportName + FString::FromInt(i) + ".psaf"; + + FString psafPath2 = leftStr + ".psaf2"; + + //outfile.open(TCHAR_TO_UTF8(*leftStr), ios::binary); + outfile.open(*psafPath, std::ios::binary); + // outfile.close(); + UE_LOG(LogTemp, Log, TEXT("open flie -> %s "), *leftStr); + + uint8 width = capture.get(CAP_PROP_FRAME_WIDTH); + uint8 height = capture.get(CAP_PROP_FRAME_HEIGHT); + Size frameSize = Size(width,height ); + + uint8 fps = capture.get(CAP_PROP_FPS); + + float duration = capture.get(CV_CAP_PROP_FRAME_COUNT) / capture.get(CV_CAP_PROP_FPS); + + Size old_size = frameSize; + + capture.set(CAP_PROP_POS_FRAMES, TempClipData.ClipStartFrame); + int32 frameCount = capture.get(CV_CAP_PROP_FRAME_COUNT); + frameCount -= ClipData[i].ClipStartFrame; + UE_LOG(LogTemp, Log, TEXT("frameCount: %s"), *FString::FromInt(frameCount)); + + char p[128] = "pasf"; + outfile.write(reinterpret_cast(p), sizeof(p)); +#if 1 + + Mat frameOrg; + Mat frame; + int frameIndex = 0; + + while (ret && frameIndex < frameCount) { + + if (frameIndex % 2 == 0) { + capture.grab(); + frameIndex++; + continue; } - if (Frame->best_effort_timestamp >= EndTimeStamp) - { - break; - } - if (Frame->best_effort_timestamp >= TimeStamp) - { - - - SwsContext* FormatContext = sws_getContext( - Frame->width, - Frame->height, - PropertyData.VideoCodecContext->pix_fmt, - FGlobalData::LightArrayX, - FGlobalData::LightArrayY, - AVPixelFormat::AV_PIX_FMT_RGB24, - SWS_BILINEAR, - nullptr, - nullptr, - nullptr - ); - - - - - uint8* RawData = static_cast(FMemory::Malloc(FGlobalData::LightArrayX * FGlobalData::LightArrayY * 3)); - uint8* Dest[4] = {RawData, nullptr, nullptr ,nullptr}; - const int32 DestLineSize[4] = {FGlobalData::LightArrayX * 3, 0, 0, 0}; - sws_scale(FormatContext, Frame->data, Frame->linesize, 0, Frame->height, Dest, DestLineSize); - sws_freeContext(FormatContext); - - - LightArrayResult.Add(static_cast(FGlobalData::GlobalFPS)); - LightArrayResult.Add(blockNum); - LightArrayResult.Add(Height); - LightArrayResult.Add(Width); - LightArrayResult.Add(0); - LightArrayResult.Add(0); - LightArrayResult.Add(0); - LightArrayResult.Add(0); - int32 Length = TempClipData.VideoEndFrame - TempClipData.VideoStartFrame; - LightArrayResult.Append(reinterpret_cast(&Length), sizeof(int32)); - - - for (int32 CurrentHeight = Height / 3 - 1; CurrentHeight >= 0; CurrentHeight--) + + /* */ + tempIndex = frameIndex; + + if (capture.read(frameOrg)) { + + if (!capture.isOpened()) { - if (CurrentHeight % 2 == 0) - { - for (int32 CurrentWidth = Width - 1; CurrentWidth >= 0; CurrentWidth--) - { - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 0]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 1]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 2]); - } - } - else - { - for (int32 CurrentWidth = 0; CurrentWidth < Width; CurrentWidth++) - { - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 0]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 1]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 2]); - } - } + UE_LOG(LogTemp, Log, TEXT("cant open video -> %s"), *TempPath); + i++; + continue;; } - - - for (int32 CurrentHeight = Height / 3; CurrentHeight < 2 * Height / 3 ; CurrentHeight++) { - if (CurrentHeight % 2 == 0) - { - for (int32 CurrentWidth = 0; CurrentWidth < Width; CurrentWidth++) - { - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 0]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 1]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 2]); + + if (frameOrg.empty()) + { + UE_LOG(LogTemp, Log, TEXT("no frame")); + i++; + continue;; + } + + UE_LOG(LogTemp, Log, TEXT("frameOrg size - > (%s, %s),frameOrg type -> %s "), + *FString::FromInt(frameOrg.rows),*FString::FromInt(frameOrg.cols), *FString::FromInt(frameOrg.type())); + + resize(frameOrg, frameOrg, Size(70, 42), 0, 0, INTER_LINEAR); + frameOrg.copyTo(frame); + + if (frame.empty()) { + UE_LOG(LogTemp, Log, TEXT(" read none ")); + return EncodeVideoInfos; + } + + /* 每帧标头 */ + outfile.write(reinterpret_cast(&fps), sizeof(uint8)); + outfile.write(reinterpret_cast(&blockNum), sizeof(uint8)); + outfile.write(reinterpret_cast(&height), sizeof(uint8)); + outfile.write(reinterpret_cast(&width), sizeof(uint8)); + outfile.write(reinterpret_cast("00"), sizeof(float)); + outfile.write(reinterpret_cast(&duration), sizeof(float)); + + for (int32 row = frame.rows / 3 - 1; row >= 0; row--) { + if (row % interval == 0) { + + for (int32 col = frame.cols - 1; col >= 0; col--) { + + frame.at(row, col) = frameOrg.at(row, col); + + //outfile.write(reinterpret_cast(&frame.at(row, col)), sizeof(uint8) * 3); + outfile.write(reinterpret_cast(&frame.at(row, col)[2]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[1]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[0]), sizeof(uint8)); + + //UE_LOG(LogTemp, Log, TEXT("row -> %s ,col - > %s "), + // *FString::FromInt(row), *FString::FromInt(col)); } + } - else - { - for (int32 CurrentWidth = Width - 1; CurrentWidth >= 0; CurrentWidth--) - { - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 0]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 1]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 2]); + else { + for (int32 col = 0; col < frame.cols; col++) { + + frame.at(row, col) = frameOrg.at(row, col); + + + outfile.write(reinterpret_cast(&frame.at(row, col)[2]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[1]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[0]), sizeof(uint8)); + + } + + } + + } + + for (int32 row = frame.rows/3; row < 2 * frame.rows / 3 ; row++) { + if (row % interval == 0) { + + for (int32 col = 0; col < frame.cols; col++) { + + frame.at(row, col) = frameOrg.at(row, col); + + outfile.write(reinterpret_cast(&frame.at(row, col)[2]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[1]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[0]), sizeof(uint8)); + + + } + + } + else { + + for (int32 col = frame.cols - 1; col >= 0; col--) { + + frame.at(row, col) = frameOrg.at(row, col); + + outfile.write(reinterpret_cast(&frame.at(row, col)[2]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[1]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[0]), sizeof(uint8)); + + } } } - for (int32 CurrentHeight = 2 * Height / 3; CurrentHeight < Height; CurrentHeight++) { - if (CurrentHeight % 2 == 0) - { - for (int32 CurrentWidth = 0; CurrentWidth < Width; CurrentWidth++) - { - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 0]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 1]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 2]); + for (int32 row = 2 * frame.rows/3; row < frame.rows ; row++) { + if (row % interval == 0) { + for (int32 col = 0; col < frame.cols ; col++) { + + frame.at(row, col) = frameOrg.at(row, col); + + outfile.write(reinterpret_cast(&frame.at(row, col)[2]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[1]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[0]), sizeof(uint8)); + + } + } else { - for (int32 CurrentWidth = Width - 1; CurrentWidth >= 0; CurrentWidth--) - { - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 0]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 1]); - LightArrayResult.Add(RawData[CurrentHeight * FGlobalData::LightArrayX + CurrentWidth + 2]); + for (int32 col = frame.cols - 1; col >= 0 ; col--) { + + frame.at(row, col) = frameOrg.at(row, col); + + outfile.write(reinterpret_cast(&frame.at(row, col)[2]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[1]), sizeof(uint8)); + outfile.write(reinterpret_cast(&frame.at(row, col)[0]), sizeof(uint8)); + + } } } + + +#if EXPORT_PROCESSED_VIDEO + writer.write(frame); +#endif + //frames.Add(MatToTexture2D(frame, width, height, true)); + + frameIndex++; + //UE_LOG(LogTemp, Log, TEXT(" write frame,frameSize( %s, %s )"), *FString::FromInt(frame.rows), *FString::FromInt(frame.cols)); + + } + else + { + frameIndex++; } } - int32 RemainData = 1024 - LightArrayResult.Num() % 1024; - LightArrayResult.AddZeroed(RemainData); - FFileHelper::SaveArrayToFile(LightArrayResult, *PsafSavePath); - FEncodeVideoInfo EncodeVideoInfo; - EncodeVideoInfo.EncodedVideoName = ExportName + FString::FromInt(i) + ".psaf"; - EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.ClipStartFrame); - EncodeVideoInfos.Add(EncodeVideoInfo); +#endif - FFFMPEGUtils::UnLoadContext(&PropertyData); - av_packet_free(&Packet); - av_frame_free(&Frame); + outfile.seekp(0, outfile.end); + size_t fileSize = outfile.tellp(); + UE_LOG(LogTemp, Log, TEXT("fileSize1 -> %s"), *FString::FromInt(fileSize)); + + int32 remains = 1024 - fileSize % (1024); + outfile.write(reinterpret_cast("0x00"), sizeof(uint8)* remains); + fileSize = outfile.tellp(); + UE_LOG(LogTemp, Log, TEXT("fileSize2 -> %s"), *FString::FromInt(fileSize)); + + capture.release(); + +#if EXPORT_PROCESSED_VIDEO + writer.release(); +#endif + + outfile.close(); + + UE_LOG(LogTemp, Log, TEXT("proecess completed , video close")); } + FEncodeVideoInfo EncodeVideoInfo; + FString String = ExportPath + ExportName + 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); i++; } return EncodeVideoInfos; diff --git a/Source/Cut5/Widgets/Curtain/SCurtain.cpp b/Source/Cut5/Widgets/Curtain/SCurtain.cpp index 907c0fb..0cf5d58 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtain.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtain.cpp @@ -81,7 +81,7 @@ void SCurtain::Construct(const FArguments& InArgs) { FSlateApplication::Get().SetKeyboardFocus(InlineEditableTextBlock); } - Curtain->Step = 1 + Offset + (Curtain - CurtainGroup->Curtains.GetData()); + Curtain->Step = Offset + (Curtain - CurtainGroup->Curtains.GetData()); } FReply SCurtain::OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 7cb28b9..6f421fc 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -31,7 +31,7 @@ public: inline static float GlobalFPS = 30.0f; inline static FString CurrentProjectName = "DefaultProject"; inline static FString BasePath = FPaths::ProjectDir(); - inline static FString Version = "1.0.1"; + inline static FString Version = "3.0"; inline static FString ExportPath = ""; inline static TArray Colors = @@ -384,7 +384,7 @@ struct CUT5_API FClipData : public TSharedFromThis if (CropMethod == ECropMethod::FromFront) { ClipStartFrame += CropFrame; - if (ClipType == ETrackType::VideoTrack || ClipType == ETrackType::AudioTrack || ClipType == ETrackType::LightArrayTrack || ClipType == ETrackType::LightBarTrack) + if (ClipType == ETrackType::VideoTrack || ClipType == ETrackType::AudioTrack || ClipType == ETrackType::AudioTrackR || ClipType == ETrackType::LightArrayTrack || ClipType == ETrackType::LightBarTrack) { VideoStartFrame += CropFrame; } @@ -392,11 +392,10 @@ struct CUT5_API FClipData : public TSharedFromThis else { ClipEndFrame -= CropFrame; - if (ClipType == ETrackType::VideoTrack || ClipType == ETrackType::AudioTrack || ClipType == ETrackType::LightArrayTrack || ClipType == ETrackType::LightBarTrack) + if (ClipType == ETrackType::VideoTrack || ClipType == ETrackType::AudioTrack || ClipType == ETrackType::AudioTrackR || ClipType == ETrackType::LightArrayTrack || ClipType == ETrackType::LightBarTrack) { VideoEndFrame -= CropFrame; } - } if (PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None) { @@ -1036,4 +1035,18 @@ enum class ESoundSolveType None, OnlyLeft, OnlyRight, -}; \ No newline at end of file +}; + + +static bool IsVideo(enum ETrackType TrackType) +{ + if ( TrackType == ETrackType::VideoTrack + || TrackType == ETrackType::AudioTrack + || TrackType == ETrackType::AudioTrackR + || TrackType == ETrackType::LightArrayTrack + || TrackType == ETrackType::LightBarTrack) + { + return true; + } + return false; +} diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index fbb895b..31d2c1c 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -770,6 +770,7 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& if (ClipDragOperation.TimelinePropertyData->Type != TrackHead->TrackData.TrackType) { if ((ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::LightArrayTrack) + || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::LightBarTrack) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::PlayerTrack) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::AudioTrack && TrackHead->TrackData.TrackType == ETrackType::AudioTrackR) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::AtomSphereLightTrack)) @@ -797,11 +798,11 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& NewClipData.MovieBrushes = FFFMPEGUtils::GetMovieBrush(&NewClipData); - if (TrackHead->TrackData.TrackType == ETrackType::LightArrayTrack) - { - NewClipData.ClipType = ETrackType::LightArrayTrack; - NewClipData.LightArrayData = FFFMPEGUtils::GetVideoFrameLightArray(ClipDragOperation.TimelinePropertyData->MoviePath, FGlobalData::LightArrayX, FGlobalData::LightArrayY); - } + // if (TrackHead->TrackData.TrackType == ETrackType::LightArrayTrack) + // { + // NewClipData.ClipType = ETrackType::LightArrayTrack; + // NewClipData.LightArrayData = FFFMPEGUtils::GetVideoFrameLightArray(ClipDragOperation.TimelinePropertyData->MoviePath, FGlobalData::LightArrayX, FGlobalData::LightArrayY); + // } if (TrackHead->TrackData.TrackType == ETrackType::PlayerTrack) { NewClipData.ClipType = ETrackType::PlayerTrack; @@ -814,15 +815,6 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& NewClipData.PlayerName = TrackBody->MainWidgetInterface->GetGroupName(TrackHead); NewClipData.PlayerLightData = FOpencvUtils::GetVideoSingleLightColor(ClipDragOperation.TimelinePropertyData->MoviePath); } - if (TrackHead->TrackData.TrackType == ETrackType::VideoTrack) - { - SCutMainWindow* MainWidget = static_cast(TrackHead->MainWidgetInterface); - if (!MainWidget->CutTimeline->GetTrackGroupByName(TEXT("视频附着"))) - { - MainWidget->CutTimeline->AddNewTrackToGroup(TEXT("视频附着"), FTrackData(TEXT("附着音频"), ETrackType::AudioTrack, FDeviceTrack(TEXT("附着音频"), ETrackType::AudioTrack))); - } - - } } else if (ClipDragOperation.TimelinePropertyData->Type == ETrackType::LightArrayTrack) { diff --git a/Source/Cut5/Widgets/SCutMainWindow.cpp b/Source/Cut5/Widgets/SCutMainWindow.cpp index ca29bcf..aa74a1d 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.cpp +++ b/Source/Cut5/Widgets/SCutMainWindow.cpp @@ -854,6 +854,7 @@ void SCutMainWindow::OpenProject(const FString& Project) FFileManagerGeneric::Get().FindFiles(CutlinkName, *FPaths::Combine(Project, TEXT("*.cutlink")), true, false); if (CutlinkName.Num() == 0) { + // GEngine->GameViewport->AddViewportWidgetContent(SNew(SNewProjectTips).Title(FText::FromString(TEXT("存档失效或这不是一个存档"))).OnEnsure_Lambda([])) UE_LOG(LogTemp, Error, TEXT("项目关联文件不存在")); return; } @@ -988,7 +989,7 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) File->InsertNewChildElement("Author")->InsertNewText("Sch"); File->InsertNewChildElement("Date")->InsertNewText("2020-12-12"); File->InsertNewChildElement("Describe")->InsertNewText("描述"); - File->InsertNewChildElement("FileVersion")->InsertNewText("1.0"); + File->InsertNewChildElement("FileVersion")->InsertNewText("3.0"); File->InsertNewChildElement("SoftWareVersion")->InsertNewText(TCHAR_TO_UTF8(*FGlobalData::Version)); // Device List @@ -1034,8 +1035,8 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) tinyxml2::XMLElement* RotationSpeaker = RoundSpeakerList->InsertNewChildElement("RotationSpeaker"); RotationSpeaker->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID))); RotationSpeaker->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName)); - DeviceID++; IDList.Add(TrackData.Guid, DeviceID); + DeviceID++; RotatorSpeakerIndex = DeviceID; } break; @@ -1044,8 +1045,8 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) tinyxml2::XMLElement* LightArray = LightArrayList->InsertNewChildElement("GuangZhen"); LightArray->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID))); LightArray->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName)); - DeviceID++; IDList.Add(TrackData.Guid, DeviceID); + DeviceID++; LightArrayIndex = DeviceID; } break; @@ -1054,6 +1055,7 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) tinyxml2::XMLElement* Projector = ProjectorList->InsertNewChildElement("Projector"); Projector->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID))); Projector->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName)); + IDList.Add(TrackData.Guid, DeviceID); DeviceID++; } break; @@ -1062,8 +1064,8 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) tinyxml2::XMLElement* DMLight = DMLightList->InsertNewChildElement("DMLight"); DMLight->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID))); DMLight->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName)); - DeviceID++; IDList.Add(TrackData.Guid, DeviceID); + DeviceID++; break; } case ETrackType::LightBarTrack: @@ -1075,8 +1077,8 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) tinyxml2::XMLElement* LightArray = LightArrayList->InsertNewChildElement("GuangZhen2"); LightArray->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID))); LightArray->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName)); - DeviceID++; IDList.Add(TrackData.Guid, DeviceID); + DeviceID++; bIsLightBar = true; break; } @@ -1109,13 +1111,13 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) int32 ToStepID = 0; if (TypeID == 1) { - for (int32 k = 0; i < CurtainPanel->Groups.Num(); k++) + for (int32 k = 0; k < CurtainPanel->Groups.Num(); k++) { for (FCurtain& Curtain : CurtainPanel->Groups[k].Curtains) { if (Curtain.CurtainUUID == EffectCardsPanel->EffectCardGroups[i].Cards[j].JumpStepCurtains.Guid) { - ToStepID = Curtain.Step + 1; + ToStepID = Curtain.Step; break; } } @@ -1147,13 +1149,13 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) int32 ToStepID = 0; if (TypeID == 3) { - for (int32 k = 0; i < CurtainPanel->Groups.Num(); k++) + for (int32 k = 0; k < CurtainPanel->Groups.Num(); k++) { for (FCurtain& Curtain : CurtainPanel->Groups[k].Curtains) { if (Curtain.CurtainUUID == EffectCardsPanel->EffectCardGroups[i].JumpStepCurtains.Guid) { - ToStepID = Curtain.Step + 1; + ToStepID = Curtain.Step; break; } } @@ -1482,18 +1484,35 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par const FTrackData& TrackData = StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData; if (TrackData.TrackType == ETrackType::SpotLightTrack) { - + tinyxml2::XMLElement* DMLight = DMLightList->InsertNewChildElement(TCHAR_TO_UTF8(*FString::Printf(TEXT("DMLight")))); DMLight->SetAttribute("ID", TCHAR_TO_UTF8(*FString::FromInt(GetTrackID(TrackData.DeviceTrack.Guid)))); tinyxml2::XMLElement* Event_List = DMLight->InsertNewChildElement("Event_List"); - int32 Count = 0; - for (int32 k = 0; k < TrackData.ClipData.Num(); k++) + + TArray NewClipArrayData = TrackData.ClipData; + Sort(NewClipArrayData.GetData(), NewClipArrayData.Num(), [](const FClipData& A, const FClipData& B) { - const FClipData& TempClipData = TrackData.ClipData[k]; + return A.ClipStartFrame < B.ClipStartFrame; + }); + if (NewClipArrayData.Num() > 0) + { + if (NewClipArrayData[0].ClipStartFrame != 0) + { + tinyxml2::XMLElement* Event1 = Event_List->InsertNewChildElement("Event"); + Event1->InsertNewChildElement("Value")->InsertNewText("0"); + Event1->InsertNewChildElement("TimeCode")->InsertNewText("0"); + } + } + + + int32 Count = 0; + for (int32 k = 0; k < NewClipArrayData.Num(); k++) + { + const FClipData& TempClipData = NewClipArrayData[k]; tinyxml2::XMLElement* Event1 = Event_List->InsertNewChildElement("Event"); - Event1->InsertNewChildElement("Value")->InsertNewText("1"); + Event1->InsertNewChildElement("Value")->InsertNewText("-1"); Event1->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipStartFrame))))); tinyxml2::XMLElement* Event2 = Event_List->InsertNewChildElement("Event"); @@ -1527,16 +1546,37 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par // Default tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); - NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("106090"); + NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000"); NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000"); NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText("-1"); NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText("0"); NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0"); } - for (int32 k = 0; k < TrackData.ClipData.Num(); k++) + + TArray TempClipDataArray = TrackData.ClipData; + Sort(TempClipDataArray.GetData(), TempClipDataArray.Num(), [](const FClipData& A, const FClipData& B) { - - const FClipData& TempClipData = TrackData.ClipData[k]; + return A.ClipStartFrame < B.ClipStartFrame; + }); + if (TempClipDataArray.Num() > 0) + { + if (TempClipDataArray[0].ClipStartFrame != 0) + { + tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); + NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); + NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000"); + NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000"); + NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipDataArray[0].ClipStartFrame))))); + NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText("0"); + NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0"); + } + } + for (int32 k = 0; k < TempClipDataArray.Num(); k++) + { + const FClipData& TempClipData = TempClipDataArray[k]; + + + if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Breathe) { tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); @@ -1549,8 +1589,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par } if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Gradient) { - tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); - GetGradientLight(NewSpeicalEffect, TempClipData); + GetGradientLight(SpeicalEffect, TempClipData); } if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None) { @@ -1564,6 +1603,28 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipStartFrame))))); NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), 1))); } + + if (TempClipDataArray.Num() <= k + 1) + { + tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); + NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); + NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000"); + NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000"); + NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText("-1"); + NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame))))); + NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0"); + } + else if (TempClipDataArray[k + 1].ClipStartFrame - TempClipData.ClipEndFrame != 0) + { + tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); + NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); + NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000"); + NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000"); + NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipDataArray[k + 1].ClipStartFrame - TempClipData.ClipEndFrame))))); + NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame))))); + NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0"); + } + } j++; } @@ -1577,7 +1638,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par for (int32 k = 0; k < CutTimeline->TrackGroupInstances.Num(); k++) { int32 Index = 0; - const FTrackData& TrackData = StaticCastSharedPtr(CutTimeline->TrackGroupInstances[k].Head)->TrackData; + const TSharedPtr CurrentTrackHead = StaticCastSharedPtr(CutTimeline->TrackGroupInstances[k].Head); + const FTrackData& TrackData = CurrentTrackHead->TrackData; + int32 Count = 0; if (TrackData.TrackType == ETrackType::LightArrayTrack || TrackData.TrackType == ETrackType::LightBarTrack) { if (GetTrackID(TrackData.DeviceTrack.Guid) == -1) @@ -1586,50 +1649,61 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par } auto GuangZhen = GuangZhenList->InsertNewChildElement("GuangZhen"); GuangZhen->SetAttribute("ID", TCHAR_TO_UTF8(*FString::FromInt(GetTrackID(TrackData.DeviceTrack.Guid)))); - - int32 Count = 0; auto GuangZhenSpecialEffectList = GuangZhen->InsertNewChildElement("SpecialEffectList"); - for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++) + + TArray TempClipData = TrackData.ClipData; + Sort(TempClipData.GetData(), TempClipData.Num(), [](const FClipData& A, const FClipData& B) { - if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::LightArrayTrack) + return A.ClipStartFrame < B.ClipStartFrame; + }); + if (TempClipData.Num() > 0) + { + if (TempClipData[0].ClipStartFrame != 0) { - FString Filename; - for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpecialEffect"); { - for (const FCurtain& Curtain : CurtainGroup.Curtains) - { - if (Curtain.bIsActive) - { - Filename = Curtain.CurtainName; - } - } - } - TArray EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData, *(FGlobalData::ExportPath / "PSAF" / Filename)); - for (int32 j = 0; j < EncodeVideoInfos.Num(); j++) - { - auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpecialEffect"); - { - auto SpeicalEffectTimeCode = SpeicalEffect->InsertNewChildElement("TimeCode"); - { - SpeicalEffectTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfos[j].EncodedVideoTimeCode))); - } - auto SpeicalEffectURL = SpeicalEffect->InsertNewChildElement("URL"); - { - SpeicalEffectURL->InsertNewText(TCHAR_TO_UTF8(*EncodeVideoInfos[j].EncodedVideoName)); - } - auto SpeicalEffectLoop = SpeicalEffect->InsertNewChildElement("Loop"); - { - SpeicalEffectLoop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(!EncodeVideoInfos[j].ClipData.bIsCycle))); - } - auto SpeicalEffectMode = SpeicalEffect->InsertNewChildElement("Mode"); - { - SpeicalEffectMode->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); - } - } - Count++; + SpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText("0"); + SpeicalEffect->InsertNewChildElement("URL")->InsertNewText(""); + SpeicalEffect->InsertNewChildElement("Loop")->InsertNewText("1"); + SpeicalEffect->InsertNewChildElement("Mode")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); } } } + FString Filename; + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (const FCurtain& Curtain : CurtainGroup.Curtains) + { + if (Curtain.bIsActive) + { + Filename = Curtain.CurtainName; + } + } + } + TArray EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr(CurrentTrackHead)->TrackData, *(FGlobalData::ExportPath / "PSAF" / Filename)); + for (int32 j = 0; j < EncodeVideoInfos.Num(); j++) + { + auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpecialEffect"); + { + auto SpeicalEffectTimeCode = SpeicalEffect->InsertNewChildElement("TimeCode"); + { + SpeicalEffectTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfos[j].EncodedVideoTimeCode))); + } + auto SpeicalEffectURL = SpeicalEffect->InsertNewChildElement("URL"); + { + SpeicalEffectURL->InsertNewText(TCHAR_TO_UTF8(*EncodeVideoInfos[j].EncodedVideoName)); + } + auto SpeicalEffectLoop = SpeicalEffect->InsertNewChildElement("Loop"); + { + SpeicalEffectLoop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(!EncodeVideoInfos[j].ClipData.bIsCycle))); + } + auto SpeicalEffectMode = SpeicalEffect->InsertNewChildElement("Mode"); + { + SpeicalEffectMode->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); + } + } + Count++; + } if (Count == 0) { GuangZhenSpecialEffectList->InsertNewText(""); @@ -1658,6 +1732,19 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo) { int32 TempProjectorID = 0; + for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances) + { + const TSharedPtr TempTrackHead = StaticCastSharedPtr(SingleTrackGroupInstance.Head); + if (TempTrackHead->TrackData.TrackType != ETrackType::ProjectorTrack) + { + continue; + } + if (GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid) != -1) + { + TempProjectorID = GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid); + } + } + tinyxml2::XMLElement* Video = Parent->InsertNewChildElement("Video"); tinyxml2::XMLElement* URL = Video->InsertNewChildElement("URL"); @@ -1703,8 +1790,6 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare VolumeEventTimeCode->InsertNewText("0"); VolumeEventValue->InsertNewText("100"); } - - } } @@ -1724,11 +1809,28 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare int32 Value; }; TArray ProjectorEvents; + + + ProjectorEvents.Add(FProjectorEvent{ FUtils::GetMsFromString(FGlobalData::GetTimeData(EncodeVideoInfo.ClipStartFrame)), 1 }); for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++) { if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::ProjectorTrack) { + + TArray TempClipData = StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.ClipData; + Sort(TempClipData.GetData(), TempClipData.Num(), [](const FClipData& A, const FClipData& B) + { + return A.ClipStartFrame < B.ClipStartFrame; + }); + if (TempClipData.Num() > 0) + { + if (TempClipData[0].ClipStartFrame != 0) + { + ProjectorEvents.Add({"0", 1 }); + } + } + for (FClipData& ClipData : StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.ClipData) { if (ClipData.ClipStartFrame > EncodeVideoInfo.ClipStartFrame - 10 && ClipData.ClipEndFrame < EncodeVideoInfo.ClipEndFrame + 10) @@ -1737,7 +1839,6 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare ClipData.PresetType == EPresetType::EnableProjector ? ShowProjector = 1 : ShowProjector = 0; ProjectorEvents.Add({FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame - EncodeVideoInfo.ClipStartFrame)), ShowProjector}); } - } } } @@ -1771,9 +1872,26 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo) { + + int32 TempSoundID = 0; + for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances) + { + const TSharedPtr TempTrackHead = StaticCastSharedPtr(SingleTrackGroupInstance.Head); + if (TempTrackHead->TrackData.TrackType != ETrackType::AudioTrackR) + { + continue; + } + if (GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid) != -1) + { + TempSoundID = GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid); + } + } + + + tinyxml2::XMLElement* Sound = Parent->InsertNewChildElement("Sound"); { - Sound->InsertNewChildElement("RotationSpeakerID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(RotatorSpeakerIndex))); + Sound->InsertNewChildElement("RotationSpeakerID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TempSoundID))); if (EncodeVideoInfo.EncodedVideoName == "") { Sound->InsertNewChildElement("URL")->InsertNewText(""); @@ -1855,7 +1973,6 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoListElement(tinyxml2::XMLElement* GetVideoElement(VideoList, EncodeVideoInfo); Count++; } - } } if (Count == 0) @@ -1875,16 +1992,16 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrack || StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrackR) { - FString Filename; - for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + FString Filename = GetCurrentSelectFileName(); + + + if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrackR) { - for (const FCurtain& Curtain : CurtainGroup.Curtains) - { - if (Curtain.bIsActive) - { - Filename = Curtain.CurtainName; - } - } + Filename += TEXT("_R"); + } + if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::AudioTrack) + { + Filename += TEXT("_L"); } FString NewExportFilePath = FGlobalData::ExportPath / "Sound" / Filename; TArray EncodeVideoInfos = FUtils::TrackEncodeAudio(StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath); @@ -1957,7 +2074,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, if (!EffectCardsPanel->EffectCardGroups[i].bIsDedicated) { - if (EffectCardsPanel->EffectCardGroups[i].UsedCurtains.Contains(Curtain->CurtainUUID)) + if (EffectCardsPanel->EffectCardGroups[i].UsedCurtains.Contains(Curtain->CurtainUUID) || + EffectCardsPanel->EffectCardGroups[i].UsedCurtains.Contains(FStringWithGUID())) { tinyxml2::XMLElement* SerialNumber = EnableCard->InsertNewChildElement("SerialNumber"); SerialNumber->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID))); @@ -1968,7 +2086,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, for (int32 j = 0 ; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++) { - if (EffectCardsPanel->EffectCardGroups[i].Cards[j].UsedCurtains.Contains(Curtain->CurtainUUID)) + if (EffectCardsPanel->EffectCardGroups[i].Cards[j].UsedCurtains.Contains(Curtain->CurtainUUID) || + EffectCardsPanel->EffectCardGroups[i].Cards[j].UsedCurtains.Contains(FStringWithGUID())) { tinyxml2::XMLElement* SerialNumber = EnableCard->InsertNewChildElement("SerialNumber"); SerialNumber->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID))); @@ -2118,9 +2237,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetFlashLight(tinyxml2::XMLElement* Parent Parent->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[0].ToFColor(false))))); Parent->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(FLinearColor::Black.ToFColor(false))))); float PerLength = (ClipData.PresetsCustomData.Time / ClipData.PresetsCustomData.Times); - Parent->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(PerLength * 1000)))); + Parent->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(ClipData.PresetsCustomData.Time * 1000)))); Parent->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame))))); - Parent->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), static_cast(PerLength * 1000)))); + Parent->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), static_cast(PerLength * 500)))); return nullptr; } @@ -2131,22 +2250,23 @@ tinyxml2::XMLElement* SCutMainWindow::GetGradientLight(tinyxml2::XMLElement* Par if (ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset > 0) { - Parent->InsertNewChildElement("Mode")->InsertNewText("0"); - Parent->InsertNewChildElement("InitialColor") + tinyxml2::XMLElement* NewSpeicalEffect = Parent->InsertNewChildElement("Special_Effect"); + NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); + NewSpeicalEffect->InsertNewChildElement("InitialColor") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[0].Color.ToFColor(false))))); - Parent->InsertNewChildElement("EndColor") + NewSpeicalEffect->InsertNewChildElement("EndColor") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[0].Color.ToFColor(false))))); - Parent->InsertNewChildElement("TimeLength") + NewSpeicalEffect->InsertNewChildElement("TimeLength") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset))))); - Parent->InsertNewChildElement("TimeCode") + NewSpeicalEffect->InsertNewChildElement("TimeCode") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), - *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset))))); + *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame))))); - Parent->InsertNewChildElement("Cycle") + NewSpeicalEffect->InsertNewChildElement("Cycle") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset))))); } @@ -2157,47 +2277,49 @@ tinyxml2::XMLElement* SCutMainWindow::GetGradientLight(tinyxml2::XMLElement* Par { if (Index == CursorNum - 1 && CursorData.CursorFrameOffset <= (ClipData.ClipEndFrame - ClipData.ClipStartFrame)) { - Parent->InsertNewChildElement("Mode")->InsertNewText("0"); - Parent->InsertNewChildElement("InitialColor") + tinyxml2::XMLElement* NewSpeicalEffect = Parent->InsertNewChildElement("Special_Effect"); + NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); + NewSpeicalEffect->InsertNewChildElement("InitialColor") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index].Color.ToFColor(false))))); - Parent->InsertNewChildElement("EndColor") + NewSpeicalEffect->InsertNewChildElement("EndColor") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index].Color.ToFColor(false))))); - Parent->InsertNewChildElement("TimeLength") + NewSpeicalEffect->InsertNewChildElement("TimeLength") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData( (ClipData.ClipEndFrame - ClipData.ClipStartFrame) - ClipData.PresetsCustomData.Cursors[Index].CursorFrameOffset))))); - Parent->InsertNewChildElement("TimeCode") + NewSpeicalEffect->InsertNewChildElement("TimeCode") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + ClipData.PresetsCustomData.Cursors[Index].CursorFrameOffset))))); - Parent->InsertNewChildElement("Cycle") + NewSpeicalEffect->InsertNewChildElement("Cycle") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData( (ClipData.ClipEndFrame - ClipData.ClipStartFrame) - ClipData.PresetsCustomData.Cursors[Index].CursorFrameOffset))))); break; } - Parent->InsertNewChildElement("Mode")->InsertNewText("1"); - Parent->InsertNewChildElement("InitialColor") + tinyxml2::XMLElement* NewSpeicalEffect = Parent->InsertNewChildElement("Special_Effect"); + NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("1"); + NewSpeicalEffect->InsertNewChildElement("InitialColor") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index].Color.ToFColor(false))))); - Parent->InsertNewChildElement("EndColor") + NewSpeicalEffect->InsertNewChildElement("EndColor") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index + 1].Color.ToFColor(false))))); - Parent->InsertNewChildElement("TimeLength") + NewSpeicalEffect->InsertNewChildElement("TimeLength") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData( ClipData.PresetsCustomData.Cursors[Index + 1].CursorFrameOffset - CursorData.CursorFrameOffset))))); - Parent->InsertNewChildElement("TimeCode") + NewSpeicalEffect->InsertNewChildElement("TimeCode") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + CursorData.CursorFrameOffset))))); - Parent->InsertNewChildElement("Cycle") + NewSpeicalEffect->InsertNewChildElement("Cycle") ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString( FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[Index + 1].CursorFrameOffset - CursorData.CursorFrameOffset))))); @@ -2207,6 +2329,27 @@ tinyxml2::XMLElement* SCutMainWindow::GetGradientLight(tinyxml2::XMLElement* Par return nullptr; } +void SCutMainWindow::DeselectAll() +{ + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (FCurtain& Curtain : CurtainGroup.Curtains) + { + Curtain.bIsActive = false; + } + } + for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); ++i) + { + for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); ++j) + { + if (EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive) + { + EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive = false; + } + } + } +} + 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 a34cd66..38edfa3 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.h +++ b/Source/Cut5/Widgets/SCutMainWindow.h @@ -14,6 +14,7 @@ #include "StatePanel/SVideoPlayer.h" #include "Cut5/Interface/CutMainWidgetInterface.h" #include "Cut5/Interface/SoundInterface.h" +#include "FX/SEffectCardsPanel.h" #include "StatePanel/SStatePanel.h" #include "Widgets/SCompoundWidget.h" @@ -120,6 +121,8 @@ public: tinyxml2::XMLElement* GetBreatheLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData); tinyxml2::XMLElement* GetFlashLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData); tinyxml2::XMLElement* GetGradientLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData); + FString GetCurrentSelectFileName(); + void DeselectAll(); int32 RotatorSpeakerIndex = 0; int32 LightArrayIndex = 0; @@ -133,4 +136,29 @@ public: void RemoveThread(const FGuid& Guid); }; +inline FString SCutMainWindow::GetCurrentSelectFileName() +{ + for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) + { + for (const FCurtain& Curtain : CurtainGroup.Curtains) + { + if (Curtain.bIsActive) + { + return Curtain.CurtainName; + } + } + } + for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); ++i) + { + 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 "NULL"; +} + diff --git a/Source/Cut5/Widgets/SCutTimeline.cpp b/Source/Cut5/Widgets/SCutTimeline.cpp index db09aab..c370310 100644 --- a/Source/Cut5/Widgets/SCutTimeline.cpp +++ b/Source/Cut5/Widgets/SCutTimeline.cpp @@ -382,8 +382,6 @@ void SCutTimeline::Construct(const FArguments& InArgs) AddNewDeviceToGroup(TEXT("固定轨道"), LightArrayData); FDeviceTrack LightBarData(TEXT("灯带"), ETrackType::LightBarTrack); AddNewDeviceToGroup(TEXT("固定轨道"), LightBarData); - FDeviceTrack LightBarData2(TEXT("灯带2"), ETrackType::LightBarTrack); - AddNewDeviceToGroup(TEXT("固定轨道"), LightBarData2); FDeviceTrack SpotLightData(TEXT("投射灯一"), ETrackType::SpotLightTrack); AddNewDeviceToGroup(TEXT("固定轨道"), SpotLightData); diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index 9e4f2c8..3321ac7 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -238,7 +238,7 @@ void STimelineClip::Construct(const FArguments& InArgs) // FRunnableThread::Create(Thread, TEXT("VideoThread")); // } } - if (ClipData->ClipType == ETrackType::VideoTrack) + if (ClipData->ClipType == ETrackType::VideoTrack || ClipData->ClipType == ETrackType::LightArrayTrack || ClipData->ClipType == ETrackType::LightBarTrack) { if (!MainWidgetInterface->GetSelf()->GetThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid))) { @@ -246,7 +246,7 @@ void STimelineClip::Construct(const FArguments& InArgs) { MainWidgetInterface->OnUpdateVideo(ClipData->ClipGuid, X, Y, RawData); }, *ClipData, MainWidgetInterface); - FRunnableThread::Create(Thread, TEXT("VideoThread")); + FRunnableThread::Create(Thread, TEXT("VideoThread")); MainWidgetInterface->GetSelf()->AddThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid), Thread); } @@ -346,11 +346,12 @@ void STimelineClip::Seek(int32 Frame) const int32 Offset = Frame - ClipData->ClipStartFrame; const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset; - if (ClipData->LightArrayData.Num() != 0 && SeekMovieFrame < ClipData->LightArrayData.Num()) + + if (MainWidgetInterface->GetSelf()->GetThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid))) { - MainWidgetInterface->OnUpdateLightArray(ClipData->LightArrayData[SeekMovieFrame]); - break; + 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) @@ -446,7 +447,7 @@ void STimelineClip::UpdatePosition(int32 StartFrame) SetRenderTransform(FSlateRenderTransform(FVector2D(NewPosX, 0))); ClipDataBox->SetWidthOverride((ClipData->ClipEndFrame - StartFrame) * FGlobalData::DefaultTimeTickSpace); - if (ClipData->ClipType == ETrackType::VideoTrack) + if (ClipData->ClipType == ETrackType::VideoTrack || ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) { ClipData->VideoStartFrame += StartFrame - ClipData->ClipStartFrame; } @@ -479,7 +480,7 @@ void STimelineClip::UpdateLength(int32 EndFrame) ClipDataBox->SetWidthOverride((EndFrame - ClipData->ClipStartFrame) * FGlobalData::DefaultTimeTickSpace); - if (ClipData->ClipType == ETrackType::VideoTrack) + if (ClipData->ClipType == ETrackType::VideoTrack || ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) { ClipData->VideoEndFrame += EndFrame - ClipData->ClipEndFrame; } @@ -492,10 +493,8 @@ void STimelineClip::UpdateLength(int32 EndFrame) { ClipData->PresetsCustomData.Cursors[i].CursorFrameOffset = ClipData->ClipEndFrame - ClipData->ClipStartFrame; } - } } - } void STimelineClip::UpdateMove(int32 X, int32 DragOffset) diff --git a/Source/Cut5/Widgets/STrackBody.cpp b/Source/Cut5/Widgets/STrackBody.cpp index 8d6d1ff..114d048 100644 --- a/Source/Cut5/Widgets/STrackBody.cpp +++ b/Source/Cut5/Widgets/STrackBody.cpp @@ -283,7 +283,6 @@ void STrackBody::BreakClip(const FGuid& Guid) FFFMPEGUtils::GetAudioBrush(&TrackHead->TrackData.ClipData[i]); FFFMPEGUtils::GetAudioBrush(&NewClipData); } - } }