diff --git a/Source/Cut5/Interface/SoundInterface.cpp b/Source/Cut5/Interface/SoundInterface.cpp index 3f01287..7c8194c 100644 --- a/Source/Cut5/Interface/SoundInterface.cpp +++ b/Source/Cut5/Interface/SoundInterface.cpp @@ -69,18 +69,7 @@ void FSoundThread::Stop() int FSoundThread::PaStreamCallback(const void* input, void* output, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData) { - // FSoundThread* This = static_cast(userData); - // - // TArray> ResultData; - // const int32 FrameLength = This->Audio.Num(); - // for (int32 i = This->SeekedFrame * (This->SampleRate / FGlobalData::GlobalFPS) * This->ByteNum * 2; i < This->SeekedFrame * (This->SampleRate / FGlobalData::GlobalFPS) * This->ByteNum * 2 + frameCount && i < FrameLength; ++i) - // { - // if (ResultData.Num() < i && i > 0) - // { - // ResultData.Add(This->Audio[i]); - // } - // } - // output = ResultData.GetData(); + return paContinue; } diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index 88445b5..6c8b131 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -265,6 +265,16 @@ bool FUtils::DetectDragTypeCanDrop(const FClipData& DraggingType, const ETrackTy return true; } } + + if (DropTrackType == ETrackType::ProjectorTrack) + { + if (DraggingType.ClipType == ETrackType::ProjectorTrack) + { + return true; + } + } + + return false; @@ -293,13 +303,9 @@ void FUtils::CreateDefaultTimelineSave(const FString& SavedPath, const FTimeline TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath) { - - TArray ClipData = TrackData.ClipData; ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; }); - - - + int32 i = 0; TArray EncodeVideoInfos; for (FClipData& TempClipData : ClipData) @@ -314,9 +320,10 @@ TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, c FString StartTime = FString::Printf(TEXT("%02d:%02d:%02d"), StartTimespan.GetHours(), StartTimespan.GetMinutes(), StartTimespan.GetSeconds()); FString EndTime = FString::Printf(TEXT("%02d:%02d:%02d"), EndTimespan.GetHours(), EndTimespan.GetMinutes(), EndTimespan.GetSeconds()); FString InputFile = "\"" + TempClipData.ResourcePropertyDataPtr->MoviePath + "\""; - - FString OutputFile = "\"" + FPaths::ConvertRelativePathToFull(ExportPath + FString::FromInt(i) + TEXT(".mp4")) + "\""; + + FString OutputFile = "\"" + FPaths::ConvertRelativePathToFull(ExportPath / FPaths::GetBaseFilename(TempClipData.MoviePath, true) + FString::FromInt(i) + TEXT(".mp4")) + "\""; + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("OutputFile %s"), *OutputFile)); int32 StartFrame = (TempClipData.VideoStartFrame) % static_cast(FGlobalData::GlobalFPS);; int32 EndFrame = (TempClipData.VideoEndFrame) % static_cast(FGlobalData::GlobalFPS); @@ -327,7 +334,7 @@ TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, c FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr); EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.ClipStartFrame); - EncodeVideoInfo.EncodedVideoName = ExportPath + FString::FromInt(i) + TEXT(".mp4"); + EncodeVideoInfo.EncodedVideoName = ExportPath / FPaths::GetBaseFilename(TempClipData.MoviePath, true) + FString::FromInt(i) + TEXT(".mp4"); EncodeVideoInfo.ClipStartFrame = TempClipData.ClipStartFrame; EncodeVideoInfo.ClipEndFrame = TempClipData.ClipEndFrame; diff --git a/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp b/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp index 612474f..5b32339 100644 --- a/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp +++ b/Source/Cut5/Widgets/Commands/TimelineClipCommands.cpp @@ -7,5 +7,7 @@ void FTimelineClipCommands::RegisterCommands() UI_COMMAND(Break, "分割", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(Fill2Start, "填充到开头", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); UI_COMMAND(Fill2End, "填充到结尾", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); + UI_COMMAND(Cycle, "循环", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); + UI_COMMAND(CancelCycle, "取消循环", "Executes My TimelineClipCommands", EUserInterfaceActionType::Button, FInputChord()); } #undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/Cut5/Widgets/Commands/TimelineClipCommands.h b/Source/Cut5/Widgets/Commands/TimelineClipCommands.h index 276d322..be032a7 100644 --- a/Source/Cut5/Widgets/Commands/TimelineClipCommands.h +++ b/Source/Cut5/Widgets/Commands/TimelineClipCommands.h @@ -21,4 +21,6 @@ public: TSharedPtr Break; TSharedPtr Fill2Start; TSharedPtr Fill2End; + TSharedPtr CancelCycle; + TSharedPtr Cycle; }; \ No newline at end of file diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 2eac0f4..e53dfcc 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -279,6 +279,18 @@ struct CUT5_API FPresetsCustomData } }; +struct CUT5_API FVolumeData +{ + int32 VolumeOffset = 0; + int32 Volume = 100; + + friend FArchive& operator<<(FArchive& Ar, FVolumeData& VolumeData) + { + Ar << VolumeData.VolumeOffset; + Ar << VolumeData.Volume; + return Ar; + } +}; struct CUT5_API FClipData { @@ -308,6 +320,8 @@ struct CUT5_API FClipData Ar << ClipData.bCanDrag; Ar << ClipData.PresetsCustomData; Ar << ClipData.MovieBrushesPath; + Ar << ClipData.VolumeData; + Ar << ClipData.bIsCycle; return Ar; }; @@ -323,6 +337,8 @@ struct CUT5_API FClipData int32 ClipStartFrame = 0; int32 ClipEndFrame = 10; + TArray VolumeData; + bool bIsCycle = false; TArray ClipColors; @@ -338,9 +354,6 @@ struct CUT5_API FClipData TArray MovieBrushes; TArray MovieBrushesPath; - - - TArray AudioBrushes; TArray AudioBrushLength; int32 AudioBrushNum = 0; diff --git a/Source/Cut5/Widgets/SCutMainWindow.cpp b/Source/Cut5/Widgets/SCutMainWindow.cpp index 75f5695..0bd8b85 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.cpp +++ b/Source/Cut5/Widgets/SCutMainWindow.cpp @@ -637,7 +637,7 @@ int32 SCutMainWindow::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedG FSlateDrawElement::MakeBox( OutDrawElements, - LayerId + 4, + LayerId + 9, AllottedGeometry.ToPaintGeometry(FVector2f(2, CutTimeline->GetCachedGeometry().Size.Y), FSlateLayoutTransform(FVector2f(RenderLineTime, AllottedGeometry.GetLocalSize().Y - CutTimeline->GetCachedGeometry().GetLocalSize().Y))), &Brush, ESlateDrawEffect::None, @@ -1490,11 +1490,11 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par const FClipData& TempClipData = TrackData.ClipData[k]; tinyxml2::XMLElement* Event1 = Event_List->InsertNewChildElement("Event"); Event1->InsertNewChildElement("Value")->InsertNewText("1"); - Event1->InsertNewChildElement("Timecode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipStartFrame))))); + Event1->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipStartFrame))))); tinyxml2::XMLElement* Event2 = Event_List->InsertNewChildElement("Event"); Event2->InsertNewChildElement("Value")->InsertNewText("0"); - Event2->InsertNewChildElement("Timecode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame))))); + Event2->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame))))); Count++; } if (Count == 0) @@ -1536,13 +1536,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Breathe) { tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); - NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); - NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Colors[0].ToFColor(false))))); - NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(FLinearColor::Black.ToFColor(false))))); - float PerLength = (TempClipData.PresetsCustomData.Time / TempClipData.PresetsCustomData.Times); - NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(PerLength * 1000)))); - 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"), TempClipData.PresetsCustomData.Times))); + GetBreatheLight(NewSpeicalEffect, TempClipData); } if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Flash) { @@ -1558,13 +1552,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Gradient) { tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect"); - NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); - NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Cursors[0].Color.ToFColor(false))))); - NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Cursors[1].Color.ToFColor(false))))); - float PerLength = (TempClipData.PresetsCustomData.Time / TempClipData.PresetsCustomData.Times) / 2; - NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(PerLength * 1000)))); - 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"), TempClipData.PresetsCustomData.Times))); + GetGradientLight(NewSpeicalEffect, TempClipData); } if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None) { @@ -1572,7 +1560,9 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0"); NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Colors[0].ToFColor(false))))); NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Colors[0].ToFColor(false))))); - NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), -1))); + + const int32 Frame = TempClipData.ClipEndFrame - TempClipData.ClipStartFrame; + NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(Frame))))); 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))); } @@ -1604,7 +1594,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par TArray EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData, *(FGlobalData::ExportPath / "PSAF")); for (int32 j = 0; j < EncodeVideoInfos.Num(); j++) { - auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpeicalEffect"); + auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpecialEffect"); { auto SpeicalEffectTimeCode = SpeicalEffect->InsertNewChildElement("TimeCode"); { @@ -1616,7 +1606,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par } auto SpeicalEffectLoop = SpeicalEffect->InsertNewChildElement("Loop"); { - SpeicalEffectLoop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); + SpeicalEffectLoop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(1))); } auto SpeicalEffectMode = SpeicalEffect->InsertNewChildElement("Mode"); { @@ -1669,13 +1659,13 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare } } - tinyxml2::XMLElement* Timecode = Video->InsertNewChildElement("Timecode"); + tinyxml2::XMLElement* Timecode = Video->InsertNewChildElement("TimeCode"); { Timecode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfo.EncodedVideoTimeCode))); } tinyxml2::XMLElement* Loop = Video->InsertNewChildElement("Loop"); { - Loop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); + Loop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(1))); } tinyxml2::XMLElement* Mode = Video->InsertNewChildElement("Mode"); { @@ -1799,10 +1789,10 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Pare } } - Sound->InsertNewChildElement("Loop")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); + Sound->InsertNewChildElement("Loop")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(1))); Sound->InsertNewChildElement("Mode")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); Sound->InsertNewChildElement("Round")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(1))); - Sound->InsertNewChildElement("Timecode")->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfo.EncodedVideoTimeCode))); + Sound->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfo.EncodedVideoTimeCode))); tinyxml2::XMLElement* RotationSpeakerEventList = Sound->InsertNewChildElement("RotationSpeakerEventList"); { @@ -1828,8 +1818,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoListElement(tinyxml2::XMLElement* { if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::VideoTrack) { - FString Filename = FGuid::NewGuid().ToString(); - FString NewExportFilePath = FGlobalData::ExportPath / "Video" / Filename; + FString NewExportFilePath = FGlobalData::ExportPath / "Video/"; + GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::White, NewExportFilePath); TArray EncodeVideoInfos = FUtils::TrackEncodeVideo(StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath); for (FEncodeVideoInfo EncodeVideoInfo : EncodeVideoInfos) { @@ -2033,7 +2023,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffect(tinyxml2::XMLElement* Par } tinyxml2::XMLElement* AutoNext = Effectxml->InsertNewChildElement("AutoNext"); - Effectxml->InsertNewChildElement("TimeLength")->InsertNewText("-1"); + tinyxml2::XMLElement* TimeLength = Effectxml->InsertNewChildElement("TimeLength"); + TimeLength->InsertNewText("-1"); AutoNext->InsertNewText("0"); GetSoundListElement(Effectxml); GetDeviceElement(Effectxml); @@ -2068,6 +2059,113 @@ tinyxml2::XMLElement* SCutMainWindow::GetTrigger(tinyxml2::XMLElement* Parent) return Trigger; } +tinyxml2::XMLElement* SCutMainWindow::GetBreatheLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData) +{ + Parent->InsertNewChildElement("Mode")->InsertNewText("3"); + 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("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)))); + return nullptr; +} + +tinyxml2::XMLElement* SCutMainWindow::GetFlashLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData) +{ + Parent->InsertNewChildElement("Mode")->InsertNewText("2"); + 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("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)))); + return nullptr; +} + +tinyxml2::XMLElement* SCutMainWindow::GetGradientLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData) +{ + if (ClipData.PresetsCustomData.Cursors.Num() == 0) + return nullptr; + + if (ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset > 0) + { + Parent->InsertNewChildElement("Mode")->InsertNewText("0"); + 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(ClipData.PresetsCustomData.Colors[0].ToFColor(false))))); + + Parent->InsertNewChildElement("TimeLength") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), + *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset))))); + + Parent->InsertNewChildElement("TimeCode") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), + *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset))))); + + Parent->InsertNewChildElement("Cycle") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), + *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset))))); + } + + int32 Index = 0; + const int32 CursorNum = ClipData.PresetsCustomData.Cursors.Num(); + for (const FCursorData& CursorData : ClipData.PresetsCustomData.Cursors) + { + if (Index == CursorNum - 1 && CursorData.CursorFrameOffset < (ClipData.ClipEndFrame - ClipData.ClipStartFrame)) + { + Parent->InsertNewChildElement("Mode")->InsertNewText("0"); + Parent->InsertNewChildElement("InitialColor") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[Index].ToFColor(false))))); + + Parent->InsertNewChildElement("EndColor") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[Index].ToFColor(false))))); + + Parent->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") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), + *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + ClipData.PresetsCustomData.Cursors[Index].CursorFrameOffset))))); + + Parent->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") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(CursorData.Color.ToFColor(false))))); + + Parent->InsertNewChildElement("EndColor") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[Index + 1].ToFColor(false))))); + + Parent->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") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), + *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + CursorData.CursorFrameOffset))))); + + Parent->InsertNewChildElement("Cycle") + ->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), + *FUtils::GetMsFromString( + FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[Index + 1].CursorFrameOffset - CursorData.CursorFrameOffset))))); + Index++; + } + + return nullptr; +} + int32 SCutMainWindow::GetTrackID(FGuid Guid) const { const int32* Index = IDList.Find(Guid); @@ -2099,5 +2197,13 @@ void SCutMainWindow::AddThread(const FGuid& Guid, FRunnable* InSoundThread) } } +void SCutMainWindow::RemoveThread(const FGuid& Guid) +{ + FRunnable* Thread = *Threads.Find(Guid); + Thread->Stop(); + delete Thread; + Threads.Remove(Guid); +} + END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/SCutMainWindow.h b/Source/Cut5/Widgets/SCutMainWindow.h index cd69e07..a34cd66 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.h +++ b/Source/Cut5/Widgets/SCutMainWindow.h @@ -116,6 +116,10 @@ public: tinyxml2::XMLElement* GetSpecialEffectGroup(tinyxml2::XMLElement* Parent, FEffectCardGroup* Group); tinyxml2::XMLElement* GetSpecialEffect(tinyxml2::XMLElement* Parent, FEffectCardProperty* Effect); tinyxml2::XMLElement* GetTrigger(tinyxml2::XMLElement* Parent); + + 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); int32 RotatorSpeakerIndex = 0; int32 LightArrayIndex = 0; @@ -126,6 +130,7 @@ public: TMap Threads; FRunnable* GetThread(const FGuid& Guid); void AddThread(const FGuid& Guid, FRunnable* InSoundThread); + void RemoveThread(const FGuid& Guid); }; diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index aac6808..3cd956e 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -51,8 +51,24 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F FMenuBuilder MenuBuilder(true, CommandList); MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Remove); MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Break); - MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Fill2Start); - MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Fill2End); + if (ClipData->ClipType != ETrackType::VideoTrack && ClipData->ClipType != ETrackType::AudioTrack && ClipData->ClipType != ETrackType::AudioTrackR) + { + MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Fill2Start); + MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Fill2End); + } + if (ClipData->ClipType != ETrackType::ProjectorTrack) + { + if (ClipData->bIsCycle) + { + MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().CancelCycle); + } + else + { + MenuBuilder.AddMenuEntry(FTimelineClipCommands::Get().Cycle); + } + } + + MenuContent = MenuBuilder.MakeWidget(); FSlateApplication::Get().PushMenu(AsShared(), FWidgetPath(), MenuContent.ToSharedRef(), FSlateApplication::Get().GetCursorPos(), FPopupTransitionEffect::ContextMenu); return FReply::Handled(); @@ -136,7 +152,7 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F const TSharedPtr Clip2ClipDragDropOperation = MakeShared(); Clip2ClipDragDropOperation->MainInterface = MainWidgetInterface; Clip2ClipDragDropOperation->DragOffset = MainWidgetInterface->GetCutTimeline()->GetCachedGeometry().AbsoluteToLocal(PointerEvent.GetScreenSpacePosition()).X; - float X = StaticCastSharedPtr(Body)->GetCachedGeometry().AbsoluteToLocal(PointerEvent.GetScreenSpacePosition()).X / FGlobalData::DefaultTimeTickSpace; + const float X = StaticCastSharedPtr(Body)->GetCachedGeometry().AbsoluteToLocal(PointerEvent.GetScreenSpacePosition()).X / FGlobalData::DefaultTimeTickSpace; Clip2ClipDragDropOperation->OriginOffset = ClipData->ClipStartFrame - X / FGlobalData::DefaultTimeTickSpace; for (FSingleTrackGroupInstance& TrackGroupInstance : MainWidgetInterface->GetCutTimeline()->TrackGroupInstances) @@ -229,6 +245,8 @@ void STimelineClip::Construct(const FArguments& InArgs) FRunnableThread::Create(Thread, TEXT("VideoThread")); MainWidgetInterface->GetSelf()->AddThread(FUtils::GetVideoThreadGuid(ClipData->ClipGuid), Thread); } + + } if (MainWidgetInterface->GetCutTimeline()->SelectedClipGUID == ClipData->ClipGuid) { @@ -410,7 +428,7 @@ void STimelineClip::UpdatePosition(int32 StartFrame) } const int32 NewPosX = StartFrame * FGlobalData::DefaultTimeTickSpace; - if (StartFrame > 0) + if (ClipData->ClipType == ETrackType::VideoTrack || ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) { if (ClipData->VideoStartFrame + StartFrame - ClipData->ClipStartFrame < 0) { @@ -418,6 +436,8 @@ void STimelineClip::UpdatePosition(int32 StartFrame) } } + + SetRenderTransform(FSlateRenderTransform(FVector2D(NewPosX, 0))); @@ -576,11 +596,15 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (ClipData->PresetType == EPresetType::EnableProjector) { - FSlateDrawElement::MakeText(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("开启投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("开启投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } if (ClipData->PresetType == EPresetType::DisableProjector) { - FSlateDrawElement::MakeText(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("关闭投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("关闭投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + } + if (ClipData->bIsCycle == true) + { + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 9, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("循环播放")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } @@ -649,19 +673,19 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (PaintDragType == 0) { const FSlateBrush Brush; - FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(10, AllottedGeometry.Size.Y), FSlateLayoutTransform(FVector2f(0, 0))), + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 5, AllottedGeometry.ToPaintGeometry(FVector2f(10, AllottedGeometry.Size.Y), FSlateLayoutTransform(FVector2f(0, 0))), &Brush, ESlateDrawEffect::None, FLinearColor(1.0, 0.0, 1.0, 1.0)); } else if (PaintDragType == 1) { const FSlateBrush Brush; - FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(10, AllottedGeometry.Size.Y), FSlateLayoutTransform(FVector2f(AllottedGeometry.Size.X - 10, 0))), + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 5, AllottedGeometry.ToPaintGeometry(FVector2f(10, AllottedGeometry.Size.Y), FSlateLayoutTransform(FVector2f(AllottedGeometry.Size.X - 10, 0))), &Brush, ESlateDrawEffect::None, FLinearColor(1.0, 0.0, 1.0, 1.0)); } else if (PaintDragType == 2) { const FSlateBrush Brush; - FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(FGlobalData::DefaultTimeTickSpace, FGlobalData::DefaultTrackHeight), FSlateLayoutTransform(FVector2f(LocalPos.X, 0))), + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 5, AllottedGeometry.ToPaintGeometry(FVector2f(FGlobalData::DefaultTimeTickSpace, FGlobalData::DefaultTrackHeight), FSlateLayoutTransform(FVector2f(LocalPos.X, 0))), &Brush, ESlateDrawEffect::None, FLinearColor(1.0, 0.0, 1.0, 1.0)); } diff --git a/Source/Cut5/Widgets/STimelinePropertyPanel.cpp b/Source/Cut5/Widgets/STimelinePropertyPanel.cpp index 9ddcdeb..0870520 100644 --- a/Source/Cut5/Widgets/STimelinePropertyPanel.cpp +++ b/Source/Cut5/Widgets/STimelinePropertyPanel.cpp @@ -37,6 +37,8 @@ void STimelinePropertyPanel::Construct(const FArguments& InArgs) [ SNew(SBox) .Padding(0, 0 , 0, 14) + .HeightOverride(76) + .WidthOverride(236) [ SNew(SOverlay) + SOverlay::Slot() diff --git a/Source/Cut5/Widgets/STrackBody.cpp b/Source/Cut5/Widgets/STrackBody.cpp index 03027b8..16cb16f 100644 --- a/Source/Cut5/Widgets/STrackBody.cpp +++ b/Source/Cut5/Widgets/STrackBody.cpp @@ -35,6 +35,14 @@ void STrackBody::Construct(const FArguments& InArgs) { Fill2End(SelectedClipGUID); }), FCanExecuteAction()); + CommandList->MapAction(FTimelineClipCommands::Get().Cycle, FExecuteAction::CreateLambda([this]() + { + SetCycle(SelectedClipGUID, true); + }), FCanExecuteAction()); + CommandList->MapAction(FTimelineClipCommands::Get().CancelCycle, FExecuteAction::CreateLambda([this]() + { + SetCycle(SelectedClipGUID, false); + }), FCanExecuteAction()); MainWidgetInterface = InArgs._MainWidgetInterface; TrackHead = InArgs._TrackHead; @@ -200,6 +208,18 @@ void STrackBody::Fill2End(const FGuid& Guid) } } +void STrackBody::SetCycle(const FGuid& Guid, bool Cycle) +{ + for (int32 i = 0; i < SlateClips.Num(); i++) + { + if (TrackHead->TrackData.ClipData[i].ClipGuid == Guid) + { + TrackHead->TrackData.ClipData[i].bIsCycle = Cycle; + break; + } + } +} + void STrackBody::BreakClip(const FGuid& Guid) { for (int32 i = 0; i < SlateClips.Num(); i++) diff --git a/Source/Cut5/Widgets/STrackBody.h b/Source/Cut5/Widgets/STrackBody.h index 48f05e8..53fa9a6 100644 --- a/Source/Cut5/Widgets/STrackBody.h +++ b/Source/Cut5/Widgets/STrackBody.h @@ -36,6 +36,7 @@ public: virtual void BreakClip(const FGuid& Guid) override; void Fill2Start(const FGuid& Guid); void Fill2End(const FGuid& Guid); + void SetCycle(const FGuid& Guid, bool Cycle); // virtual bool CanDragOver() override;