diff --git a/Source/Cut5/Interface/SoundInterface.cpp b/Source/Cut5/Interface/SoundInterface.cpp index c81454b..c006544 100644 --- a/Source/Cut5/Interface/SoundInterface.cpp +++ b/Source/Cut5/Interface/SoundInterface.cpp @@ -62,7 +62,7 @@ uint32 FSoundThread::Run() if (Pa_WriteStream(Stream, Audio.GetData() + Offset, Size) == paOutputUnderflowed) { - GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Underflowed")); + }; SeekedFrame = 0; } diff --git a/Source/Cut5/Interface/SoundWaveformThread.cpp b/Source/Cut5/Interface/SoundWaveformThread.cpp new file mode 100644 index 0000000..00667e1 --- /dev/null +++ b/Source/Cut5/Interface/SoundWaveformThread.cpp @@ -0,0 +1 @@ +#include "SoundWaveformThread.h" diff --git a/Source/Cut5/Interface/SoundWaveformThread.h b/Source/Cut5/Interface/SoundWaveformThread.h new file mode 100644 index 0000000..e9b128f --- /dev/null +++ b/Source/Cut5/Interface/SoundWaveformThread.h @@ -0,0 +1,7 @@ +#pragma once + +class FSoundWaveformThread : public FRunnable +{ +public: + FSoundWaveformThread(); +}; diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index cb9d9b9..ec2461d 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -252,9 +252,9 @@ bool FUtils::DetectDragTypeCanDrop(const FClipData& DraggingType, const ETrackTy } } - if (DropTrackType == ETrackType::VideoTrack) + if (DropTrackType == ETrackType::VideoTrack || DropTrackType == ETrackType::LightArrayTrack || DropTrackType == ETrackType::LightBarTrack) { - if (DraggingType.ClipType == ETrackType::VideoTrack) + if (DraggingType.ClipType == ETrackType::VideoTrack || DraggingType.ClipType == ETrackType::LightArrayTrack || DraggingType.ClipType == ETrackType::LightBarTrack) { return true; } @@ -342,7 +342,7 @@ TArray FUtils::TrackEncodeVideo(const FTrackData& TrackData, c FString OutputFile = "\"" + FPaths::ConvertRelativePathToFull(ExportPath + FString::FromInt(i) + TEXT(".mp4")) + "\""; - GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("OutputFile %s"), *OutputFile)); + // 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); diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 6220cde..74fda7a 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -370,10 +370,7 @@ struct CUT5_API FClipData : public TSharedFromThis TArray ClipColors; TArray AudioCurtains; - UE_DEPRECATED(0.0, "Use int32 instead of float, Please just use ClipStartFrame and ClipEndFrame") - int32 GetClipStartFrame() const { return ClipStartTime / FGlobalData::DefaultTimeTickSpace; }; - UE_DEPRECATED(0.0, "Use int32 instead of float, Please just use ClipStartFrame and ClipEndFrame") - int32 GetClipEndFrame() const { return ClipEndTime / FGlobalData::DefaultTimeTickSpace; }; + int32 GetLength() const { return ClipEndFrame - ClipStartFrame; } int32 GetClipRelativeEndFrame() const { return ClipEndFrame - ClipStartFrame; } FPresetsCustomData PresetsCustomData; diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index eaaf2aa..d6ce57c 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -138,25 +138,6 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv FSlateApplication::Get().AddWindowAsNativeChild(CurrentShowDragDropWindow.ToSharedRef(), FSlateApplication::Get().GetActiveTopLevelWindow().ToSharedRef(), true); } CurrentShowDragDropWindow->MoveWindowTo(FSlateApplication::Get().GetCursorPos()); - // CurrentShowDragDropWidget = DragDropBase->VirtualDraggingShow.ToSharedRef(); - // SCutMainWindow* MainWindow = static_cast(SavedMainInterface); - // if (MainWindow) - // { - // MainWindow->Overlay->AddSlot() - // .HAlign(HAlign_Left) - // .VAlign(VAlign_Top) - // [ - // SNew(SBox) - // .WidthOverride(80) - // .HeightOverride(80) - // .HAlign(HAlign_Fill) - // .VAlign(VAlign_Fill) - // [ - // CurrentShowDragDropWidget.ToSharedRef() - // ] - // ]; - // } - } TSharedPtr ClipsMoveDragDropBase = StaticCastSharedPtr(DragDropBase); if (DragDropBase->DragDropType == FCutDragDropBase::EType::ClipsMove) @@ -227,7 +208,7 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv - GEngine->AddOnScreenDebugMessage(-1, 0.1f, FColor::Red, FString::Printf(TEXT("StartPosition:%s"), *ScrollStartPosition.ToString())); + // GEngine->AddOnScreenDebugMessage(-1, 0.1f, FColor::Red, FString::Printf(TEXT("StartPosition:%s"), *ScrollStartPosition.ToString())); if (StartPosition.X < CurrentPosition.X && StartPosition.Y < CurrentPosition.Y) { @@ -298,10 +279,15 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv if (TickTimeline->CutTimeline->AutoPlaying == false) { int32 NewFrame = (TickTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X) / FGlobalData::DefaultTimeTickSpace; - for (FSingleTrackGroupInstance& Instance : TickTimeline->CutTimeline->TrackGroupInstances) + if (LastFrame != NewFrame) { - Instance.Body->Seek(NewFrame); + for (FSingleTrackGroupInstance& Instance : TickTimeline->CutTimeline->TrackGroupInstances) + { + Instance.Body->Seek(NewFrame); + } + LastFrame = NewFrame; } + TickTimeline->CutTimeline->CurrentTimeData->SetText(FText::FromString(FGlobalData::GetTimeData(NewFrame) + " / ")); } @@ -846,9 +832,41 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& if (FUtils::DetectDragTypeCanDrop(NewClipData, TrackHead->TrackData.TrackType)) { TrackHead->TrackData.ClipData.Add(NewClipData); + + + UpdateClipProcess(TrackHead->MainWidgetInterface, NewClipData); + + if (NewClipData.ClipType == ETrackType::AudioTrack) + { + if (TrackHead->TrackData.TrackType == ETrackType::AudioTrack) + { + FTrackData* TrackData = SavedMainInterface->GetCutTimeline()->GetTrackDataByType(ETrackType::AudioTrackR); + if (TrackData) + { + NewClipData.ClipType = ETrackType::AudioTrackR; + NewClipData.ClipGuid = FGuid::NewGuid(); + TrackData->ClipData.Add(NewClipData); + UpdateClipProcess(SavedMainInterface, NewClipData); + } + } + else if (TrackHead->TrackData.TrackType == ETrackType::AudioTrackR) + { + FTrackData* TrackData = SavedMainInterface->GetCutTimeline()->GetTrackDataByType(ETrackType::AudioTrack); + if (TrackData) + { + NewClipData.ClipType = ETrackType::AudioTrack; + NewClipData.ClipGuid = FGuid::NewGuid(); + TrackData->ClipData.Add(NewClipData); + UpdateClipProcess(SavedMainInterface, NewClipData); + } + } + } + + } - TrackBody->CallRender(); + SavedMainInterface->GetCutTimeline()->RenderGroup(); + } diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h index 31a0225..6d76651 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h @@ -17,6 +17,7 @@ public: ICutMainWidgetInterface* SavedMainInterface; TSharedPtr CurrentShowDragDropWidget; TSharedPtr CurrentShowDragDropWindow; + int32 LastFrame = 0; }; diff --git a/Source/Cut5/Widgets/SCutTimeline.cpp b/Source/Cut5/Widgets/SCutTimeline.cpp index 7a6c78b..59c5b3d 100644 --- a/Source/Cut5/Widgets/SCutTimeline.cpp +++ b/Source/Cut5/Widgets/SCutTimeline.cpp @@ -66,17 +66,21 @@ void SCutTimeline::UpdateTimelineLength() TimelineTick->TickLengthBox->SetWidthOverride(FGlobalData::TrackLength * FGlobalData::DefaultTimeTickSpace); } -void SCutTimeline::UpdateCursorPosition(int32 Frame) +void SCutTimeline::UpdateCursorPosition(int32 Frame, bool NeedSeek) { if (TimelineTick.IsValid()) { if (Frame >= 0 && Frame <= FGlobalData::TrackLength) { MainWidgetInterface->PreSettingBeforeSeek(); - for (const FSingleTrackGroupInstance& Interface : TrackGroupInstances) + if (NeedSeek) { - Interface.Body->Seek(Frame); + for (const FSingleTrackGroupInstance& Interface : TrackGroupInstances) + { + Interface.Body->Seek(Frame); + } } + CurrentTimeData->SetText(FText::FromString(FGlobalData::GetTimeData(Frame) + " / ")); MaxTimeData->SetText(FText::FromString(FGlobalData::GetTimeData(FGlobalData::TrackLength))); } @@ -212,9 +216,13 @@ void SCutTimeline::Construct(const FArguments& InArgs) .OnValueChanged_Lambda([this](float ChangedValue) { FGlobalData::DefaultTimeTickSpace = FMath::GetMappedRangeValueClamped(FVector2D(0, 1.0), FVector2D(30.0, GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength), ChangedValue); - UpdateCursorPosition(GetCursorPosition()); - // TickScrollBox->SetScrollOffset(TrackBodyHScrollBox->GetScrollOffset()); - + UpdateCursorPosition(GetCursorPosition(), false); + + // TrackBodyHScrollBox->SetScrollOffset(TimelineTick->GetCursorPosition() * FGlobalData::DefaultTimeTickSpace); + + TrackBodyHScrollBox->SetScrollOffset(0.0); + TickScrollBox->SetScrollOffset(TrackBodyHScrollBox->GetScrollOffset()); + RenderGroup(); }) ] @@ -313,6 +321,9 @@ void SCutTimeline::Construct(const FArguments& InArgs) [ SAssignNew(TrackBodyHScrollBox, SScrollBox) .Orientation(EOrientation::Orient_Horizontal) + .NavigationScrollPadding(100) + .BackPadScrolling(false) + .FrontPadScrolling(false) .Visibility(EVisibility::SelfHitTestInvisible) .ScrollBarVisibility(EVisibility::Hidden) .WheelScrollMultiplier(0) @@ -522,7 +533,7 @@ int32 SCutTimeline::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeo { FSlateDrawElement::MakeBox( OutDrawElements, - LayerId + 1, + LayerId + 99, AllottedGeometry.ToPaintGeometry(FVector2f(2, GetCachedGeometry().Size.Y), FSlateLayoutTransform(FVector2f(GetCachedGeometry().AbsoluteToLocal(TimelineTick->TickCursor->GetCachedGeometry().GetAbsolutePosition()).X, AllottedGeometry.GetLocalSize().Y - GetCachedGeometry().GetLocalSize().Y))), &Brush, ESlateDrawEffect::None, diff --git a/Source/Cut5/Widgets/SCutTimeline.h b/Source/Cut5/Widgets/SCutTimeline.h index 74559be..8cc6696 100644 --- a/Source/Cut5/Widgets/SCutTimeline.h +++ b/Source/Cut5/Widgets/SCutTimeline.h @@ -66,7 +66,7 @@ public: virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override; void UpdateTimelineLength(); - void UpdateCursorPosition(int32 Frame); + void UpdateCursorPosition(int32 Frame, bool NeedSeek = true); int32 GetCursorPosition() const; /** Constructs this widget with InArgs */ void Construct(const FArguments& InArgs); diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index 7dd82b6..6d6e4fa 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -607,8 +607,69 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (ClipData->ClipType == ETrackType::AudioTrack || ClipData->ClipType == ETrackType::AudioTrackR) { const FSlateBrush Brush; + + + + float DownSample = 4; + // Draw Audio Waveform + + + const float RangeStart = MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().LocalToAbsolute(FVector2D(0, 0)).X; + const float RangeEnd = MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().LocalToAbsolute(FVector2D(MainWidgetInterface->GetCutTimeline()->TrackBodyHScrollBox->GetCachedGeometry().GetLocalSize().X, 0)).X; + const float CurrentStartRange = AllottedGeometry.LocalToAbsolute(FVector2D(0, 0)).X; + const float CurrentEndRange = AllottedGeometry.LocalToAbsolute(FVector2D(AllottedGeometry.GetLocalSize().X, 0)).X; + + + + const int32 CropStartFrameOffset = ((CurrentStartRange * -1) + RangeStart > 0 ? (CurrentStartRange * -1) + RangeStart : 0) / FGlobalData::DefaultTimeTickSpace; + const int32 CropEndFrameOffset = (RangeEnd - CurrentEndRange > 0 ? + (RangeEnd - RangeStart) + CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace : CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + (RangeEnd - RangeStart)) + / FGlobalData::DefaultTimeTickSpace; + + int32 NeedDrawCount = (CropEndFrameOffset - CropStartFrameOffset) * FGlobalData::DefaultTimeTickSpace; + + + + + const int32 StartOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + * ClipData->VideoStartFrame + * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; + + const int32 EndOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + * ClipData->VideoEndFrame + * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; + + const int32 CropStartDataOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + * CropStartFrameOffset * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; + + const int32 CropEndDataOffset = (ClipData->ResourcePropertyDataPtr->AudioSample / FGlobalData::GlobalFPS) + * CropEndFrameOffset * FUtils::GetFormatSampleBytesNum(ClipData->ResourcePropertyDataPtr->SampleFormat) * 2 / DownSample; + + const int32 Interval = ((EndOffset + CropEndDataOffset) - (StartOffset + CropStartDataOffset)) / NeedDrawCount; + + + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Red, FString::FromInt(NeedDrawCount)); + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green, FString::FromInt(Interval)); + + + for (int32 i = 0; i < NeedDrawCount / DownSample; i++) + { + const int32 CurrentIndex = (StartOffset * DownSample) + (i * (Interval * DownSample * 4)); + if (CurrentIndex >= ClipData->ResourcePropertyDataPtr->AudioData.Num()) + continue; + + float NewFloat = *reinterpret_cast(&ClipData->ResourcePropertyDataPtr->AudioData[CurrentIndex]); + float Y = FMath::GetMappedRangeValueClamped(FVector2D(1.0, 0.0), FVector2D(0.0, AllottedGeometry.GetLocalSize().Y), + FMath::Abs(NewFloat)); + TArray NewLoc; + NewLoc.Add(FVector2D((CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + i) * DownSample, AllottedGeometry.GetLocalSize().Y)); + NewLoc.Add(FVector2D((CropStartFrameOffset * FGlobalData::DefaultTimeTickSpace + i) * DownSample, Y)); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 6, AllottedGeometry.ToPaintGeometry(), NewLoc, ESlateDrawEffect::None, + FColor(45, 214, 153, 255), true, DownSample * 1.2); + } + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 5, AllottedGeometry.ToPaintGeometry(), - &Brush, ESlateDrawEffect::None, FLinearColor(1.0, 0.0, 1.0, 1.0)); + &Brush, ESlateDrawEffect::None, FColor(22, 105, 78, 255)); } diff --git a/Source/Cut5/Widgets/STrackBody.cpp b/Source/Cut5/Widgets/STrackBody.cpp index 8239c3f..d22df45 100644 --- a/Source/Cut5/Widgets/STrackBody.cpp +++ b/Source/Cut5/Widgets/STrackBody.cpp @@ -171,7 +171,7 @@ FReply STrackBody::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointer + Y ); - GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("X:%f,Y:%f"), Y, DragDropOperator->ScrollStartPosition.Y)); + // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("X:%f,Y:%f"), Y, DragDropOperator->ScrollStartPosition.Y)); DragDropOperator->DraggingWidget = TrackHead->CutTimeline; return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton).BeginDragDrop(DragDropOperator.ToSharedRef()); }