轨道移动

This commit is contained in:
Sch 2023-08-17 03:31:22 +08:00
parent 7990dd0d94
commit 84feb73412
10 changed files with 165 additions and 62 deletions

View File

@ -9,11 +9,11 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
AVFormatContext* FormatContext = nullptr;
if (avformat_open_input(&FormatContext, TCHAR_TO_UTF8(*Path), nullptr, nullptr) != 0)
{
check(false)
return TEXT("Failed");
}
if (avformat_find_stream_info(FormatContext, nullptr) < 0)
{
check(false)
return TEXT("Failed");
}
PropertyData->MovieFrameLength = FormatContext->duration / AV_TIME_BASE * 30;
int32 VideoStream = -1;
@ -37,7 +37,7 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
if (avcodec_open2(VideoCodecContext, VideoCodec, nullptr) < 0)
{
check(false)
return TEXT("Failed");
}
PropertyData->VideoCodec = VideoCodec;
PropertyData->VideoCodecContext = VideoCodecContext;
@ -104,7 +104,7 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
AVCodec* AudioCodec = avcodec_find_decoder(AudioCodecContext->codec_id);
if (avcodec_open2(AudioCodecContext, AudioCodec, nullptr) < 0)
{
check(false)
return TEXT("Failed");
}
TArray<uint8> DataResult;
@ -167,7 +167,7 @@ FString FFFMPEGUtils::ConvertMediaGoPto1(const FString& Path)
AVFormatContext* FormatContext = nullptr;
if (avformat_open_input(&FormatContext, TCHAR_TO_UTF8(*Path), nullptr, nullptr) != 0)
{
check(false)
return TEXT("Failed");
}
int32 VideoStream = -1;
int32 AudioStream = -1;

View File

@ -86,6 +86,27 @@ FSlateDynamicImageBrush* FUtils::GetBrushFromImage(const FString& ImageName, con
return Brush;
}
bool FUtils::DetectDragTypeCanDrop(const FClipData& DraggingType, const ETrackType& DropTrackType)
{
if (DropTrackType == ETrackType::LightArrayTrack || DropTrackType == ETrackType::LightBarTrack || DropTrackType == ETrackType::SpotLightTrack || DropTrackType == ETrackType::AtomSphereLightTrack)
{
ETrackType DraggingTrackType = DraggingType.ClipType;
// 支持预设灯光
if (DraggingTrackType == ETrackType::LightArrayTrack || DraggingTrackType == ETrackType::LightBarTrack || DraggingTrackType == ETrackType::SpotLightTrack || DraggingTrackType == ETrackType::AtomSphereLightTrack)
{
return true;
}
}
return false;
}
void FUtils::CreateDefaultTimelineSave(const FString& SavedPath, const FTimelineInfo::ETimelineType Type)
{
TArray<uint8> SavedData;
@ -519,3 +540,4 @@ FSaveModifier::~FSaveModifier()
}
FFileHelper::SaveArrayToFile(SavedData, *FullSavedPath);
}

View File

@ -15,6 +15,8 @@ public:
static FSlateDynamicImageBrush* GetBrushFromImage(const FString& ImageName, const FVector2D Size);
static TArray<FSlateDynamicImageBrush*> BrushPtr;
static bool DetectDragTypeCanDrop(const FClipData& DraggingType, const ETrackType& DropTrackType);
/**
* @brief Create a default timeline save file.
* @param SavedPath Where to save.

View File

@ -361,6 +361,12 @@ struct CUT5_API FClipData
// Cursor
TArray<FCursorData> Cursors;
EPresetType PresetType = EPresetType::NotAPresets;
bool operator == (const FClipData& Other) const
{
return ClipGuid == Other.ClipGuid;
}
};
struct CUT5_API FTimelinePropertyData
{
@ -494,6 +500,7 @@ public:
Move,
};
EDragType DragType;
TSharedPtr<SWidget> TrackBody;
};
@ -821,4 +828,5 @@ struct FEncodeVideoInfo
FString EncodedVideoTimeCode = "00:00:00:00";
int32 ClipStartFrame = 0;
int32 ClipEndFrame = 0;
};
};

View File

@ -1,6 +1,7 @@
#include "DragDropOperator.h"
#include "Cut5/Utils/OpencvUtils.h"
#include "Cut5/Utils/Utils.h"
#include "Cut5/Widgets/DefineGlobal.h"
#include "Cut5/Widgets/SCutMainWindow.h"
#include "Cut5/Widgets/STimelineClip.h"
@ -18,6 +19,79 @@ DragDropOperator* DragDropOperator::GetDragDropOperator()
}
return DragDropOperator::Operator;
}
void DragDropOperator::UpdateClipProcess(ICutMainWidgetInterface* MainInterface, FClipData& TimelineClip)
{
if (!MainInterface)
return;
for (FSingleTrackGroupInstance& SingleTrackGroupInstance : MainInterface->GetCutTimeline()->TrackGroupInstances)
{
TSharedPtr<STrackHead> TrackHead = StaticCastSharedPtr<STrackHead>(SingleTrackGroupInstance.Head);
for (int32 i = TrackHead->TrackData.ClipData.Num() - 1; i >= 0; i--)
{
if (TimelineClip.ClipStartFrame == TrackHead->TrackData.ClipData[i].ClipStartFrame || TimelineClip.ClipEndFrame == TrackHead->TrackData.ClipData[i].ClipEndFrame)
{
continue;
}
const double ClipStartFrame = TrackHead->TrackData.ClipData[i].ClipStartFrame;
const double ClipEndFrame = TrackHead->TrackData.ClipData[i].ClipEndFrame;
if (TimelineClip.ClipStartFrame >= ClipStartFrame && TimelineClip.ClipEndFrame <= ClipEndFrame)
{
// It mean the new clip is in the old clip
FClipData SaveClipData = TrackHead->TrackData.ClipData[i];
TrackHead->TrackData.ClipData.RemoveAt(i);
// Left
FClipData LeftClipData = SaveClipData;
LeftClipData.ClipEndFrame = TimelineClip.ClipStartFrame;
TrackHead->TrackData.ClipData.Add(LeftClipData);
FClipData RightClipData = SaveClipData;
RightClipData.ClipStartFrame = TimelineClip.ClipEndFrame;
TrackHead->TrackData.ClipData.Add(RightClipData);
continue;
}
if (TimelineClip.ClipStartFrame <= ClipEndFrame && TimelineClip.ClipEndFrame >= ClipEndFrame)
{
// It mean the new clip start point is in the old clip
int32 NewStartFrame = TimelineClip.ClipStartFrame;
int32 LeftCropFrame = TrackHead->TrackData.ClipData[i].ClipEndFrame - NewStartFrame;
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromBack, LeftCropFrame);
continue;
}
if (TimelineClip.ClipEndFrame > ClipStartFrame && TimelineClip.ClipStartFrame < ClipStartFrame)
{
// It mean the new clip end point is in the old clip
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromFront, (TimelineClip.ClipEndFrame - ClipStartFrame));
continue;
}
if (TimelineClip.ClipStartFrame <= ClipStartFrame && TimelineClip.ClipEndFrame >= ClipEndFrame)
{
// It mean the new clip is out of the old clip
TrackHead->TrackData.ClipData.RemoveAt(i);
continue;
}
// const int32 CropFrameRight = TrackHead->TrackData.ClipData[i].GetClipRelativeEndFrame() - SelectedClipFrame - 1;
// TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromBack, CropFrameRight);
//
// NewClipData.CropClip(FClipData::ECropMethod::FromFront, SelectedClipFrame + 1);
// TrackHead->TrackData.ClipData.Add(NewClipData);
}
}
return;
}
void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
@ -26,18 +100,28 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv
if (DragDropBase->DragDropType == FCutDragDropBase::EType::MovePanel)
{
TSharedPtr<SCutTimeline> CutTimeline = StaticCastSharedPtr<SCutTimeline>(DragDropBase->DraggingWidget);
float ChangedValue = (CutTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X - DragDropEvent.GetOperationAs<FCutDragDropBase>()->DragOffset); // / TrackBodyHScrollBox->GetScrollOffsetOfEnd();
float Current = CutTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X;
float DragOffset = DragDropEvent.GetOperationAs<FCutDragDropBase>()->DragOffset;
float ChangedValue = (Current - DragOffset);
if (CutTimeline->TrackBodyHScrollBox->GetScrollOffset() < 0)
{
CutTimeline->TrackBodyHScrollBox->SetScrollOffset(0);
CutTimeline->TickScrollBox->SetScrollOffset(0);
DragDropEvent.GetOperationAs<FCutDragDropBase>()->DragOffset = 0;
}
if (CutTimeline->TrackBodyHScrollBox->GetScrollOffset() <= CutTimeline->TrackBodyHScrollBox->GetScrollOffsetOfEnd() - 10.0)
{
CutTimeline->TrackBodyHScrollBox->SetScrollOffset(CutTimeline->TrackBodyHScrollBox->GetScrollOffset() - ChangedValue);
CutTimeline->TickScrollBox->SetScrollOffset(CutTimeline->TrackBodyHScrollBox->GetScrollOffset());
DragDropEvent.GetOperationAs<FCutDragDropBase>()->DragOffset = (CutTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("ChangedValue: %f"), CutTimeline->TrackBodyHScrollBox->GetScrollOffset()));
}
else
{
CutTimeline->TickScrollBox->SetScrollOffset(CutTimeline->TrackBodyHScrollBox->GetScrollOffsetOfEnd() - 11.0);
CutTimeline->TrackBodyHScrollBox->SetScrollOffset(CutTimeline->TrackBodyHScrollBox->GetScrollOffsetOfEnd() - 10.0);
CutTimeline->TickScrollBox->SetScrollOffset(CutTimeline->TickScrollBox->GetScrollOffsetOfEnd() - 10.0);
DragDropEvent.GetOperationAs<FCutDragDropBase>()->DragOffset = (CutTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X);
}
return;
@ -428,59 +512,30 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent&
TSharedPtr<STimelineClip> TimelineClip = StaticCastSharedPtr<STimelineClip>(ClipDragOperation.DraggingWidget);
TSharedPtr<STrackHead> TrackHead = StaticCastSharedPtr<STrackBody>(ClipDragOperation.OverrideWidget)->TrackHead;
static_cast<SCutMainWindow*>(TrackHead->MainWidgetInterface)->bRenderLine = false;
for (int32 i = TrackHead->TrackData.ClipData.Num() - 1; i >= 0; i--)
TSharedPtr<STrackBody> TrackBody = StaticCastSharedPtr<STrackBody>(ClipDragOperation.TrackBody);
if (TrackBody != DropWidget)
{
if (TimelineClip->ClipData->ClipStartFrame == TrackHead->TrackData.ClipData[i].ClipStartFrame || TimelineClip->ClipData->ClipEndFrame == TrackHead->TrackData.ClipData[i].ClipEndFrame)
// It mean the clip is not in the same track
FClipData NewClipData = *TimelineClip->ClipData;
if (FUtils::DetectDragTypeCanDrop(NewClipData, TrackHead->TrackData.TrackType) == false)
{
continue;
return;
}
const double ClipStartFrame = TrackHead->TrackData.ClipData[i].ClipStartFrame;
const double ClipEndFrame = TrackHead->TrackData.ClipData[i].ClipEndFrame;
if (TimelineClip->ClipData->ClipStartFrame >= ClipStartFrame && TimelineClip->ClipData->ClipEndFrame <= ClipEndFrame)
{
// It mean the new clip is in the old clip
FClipData SaveClipData = TrackHead->TrackData.ClipData[i];
TrackHead->TrackData.ClipData.RemoveAt(i);
// Left
FClipData LeftClipData = SaveClipData;
LeftClipData.ClipEndFrame = TimelineClip->ClipData->ClipStartFrame;
TrackHead->TrackData.ClipData.Add(LeftClipData);
FClipData RightClipData = SaveClipData;
RightClipData.ClipStartFrame = TimelineClip->ClipData->ClipEndFrame;
TrackHead->TrackData.ClipData.Add(RightClipData);
continue;
}
if (TimelineClip->ClipData->ClipStartFrame <= ClipEndFrame && TimelineClip->ClipData->ClipEndFrame >= ClipEndFrame)
{
// It mean the new clip start point is in the old clip
int32 NewStartFrame = TimelineClip->ClipData->ClipStartFrame;
int32 LeftCropFrame = TrackHead->TrackData.ClipData[i].ClipEndFrame - NewStartFrame;
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromBack, LeftCropFrame);
continue;
}
if (TimelineClip->ClipData->ClipEndFrame > ClipStartFrame && TimelineClip->ClipData->ClipStartFrame < ClipStartFrame)
{
// It mean the new clip end point is in the old clip
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromFront, (TimelineClip->ClipData->ClipEndFrame - ClipStartFrame));
continue;
}
if (TimelineClip->ClipData->ClipStartFrame <= ClipStartFrame && TimelineClip->ClipData->ClipEndFrame >= ClipEndFrame)
{
// It mean the new clip is out of the old clip
TrackHead->TrackData.ClipData.RemoveAt(i);
continue;
}
// const int32 CropFrameRight = TrackHead->TrackData.ClipData[i].GetClipRelativeEndFrame() - SelectedClipFrame - 1;
// TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromBack, CropFrameRight);
//
// NewClipData.CropClip(FClipData::ECropMethod::FromFront, SelectedClipFrame + 1);
// TrackHead->TrackData.ClipData.Add(NewClipData);
TSharedPtr<STrackBody> OriginTrackBody = StaticCastSharedPtr<STrackBody>(TimelineClip->Body);
OriginTrackBody->TrackHead->TrackData.ClipData.Remove(NewClipData);
TrackHead->TrackData.ClipData.Add(NewClipData);
UpdateClipProcess(TrackBody->MainWidgetInterface, NewClipData);
TrackBody->CallRender();
return;
}
UpdateClipProcess(TrackBody->MainWidgetInterface, *TimelineClip->ClipData);
}
}

View File

@ -1,4 +1,6 @@
#pragma once
#include "Cut5/Interface/CutMainWidgetInterface.h"
class DragDropOperator
{
@ -10,4 +12,7 @@ public:
void OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent);
void OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, TSharedPtr<SWidget> DropWidget);
void OnDropAddNewTrack(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, TSharedPtr<SWidget> DropWidget);
void UpdateClipProcess(ICutMainWidgetInterface* MainInterface, FClipData& TimelineClip);
};

View File

@ -287,7 +287,10 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
else
{
FTimelinePropertyData Data;
FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data);
if (FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data) == TEXT("Failed"))
{
return FReply::Handled();
};
TSharedPtr<SCustomInputResource> Resource = SNew(SCustomInputResource)
.PropertyData(Data).OnCheckBoxChecked_Lambda([this](FTimelinePropertyData& ClickedData, bool bIsChecked)

View File

@ -1069,11 +1069,15 @@ void SCutMainWindow::AddNewCustomPreset(const FString& Name, const FPresetsCusto
FTimelinePropertyData NewPropertyData;
NewPropertyData.bIsCustomPresetData = true;
NewPropertyData.PresetsCustomData = CustomData;
TSharedPtr<SCustomInputResource> CustomInputResource = SNew(SCustomInputResource).PropertyData(NewPropertyData).CustomPresetName(Name);
CustomInputPanel->GridPanel->AddSlot(CustomInputPanel->GridPanel->GetChildren()->Num() % 2, CustomInputPanel->GridPanel->GetChildren()->Num() / 2)
[
SNew(SCustomInputResource).PropertyData(NewPropertyData).CustomPresetName(Name)
CustomInputResource.ToSharedRef()
];
CustomInputPanel->ResourceInst.Add(CustomInputResource);
CustomInputPanel->PropertyData.Add(NewPropertyData);
}
tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Parent)

View File

@ -9,6 +9,7 @@
#include "AudioDevice.h"
#include "SCutTimeline.h"
#include "SlateOptMacros.h"
#include "STrackBody.h"
#include "Commands/TimelineClipCommands.h"
#include "Cut5/WidgetInterface.h"
#include "Cut5/Interface/SoundInterface.h"
@ -67,6 +68,7 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F
if (ClipData->bCanDrag)
{
const TSharedPtr<FClip2ClipDragDropOperation> Clip2ClipDragDropOperation = MakeShared<FClip2ClipDragDropOperation>();
Clip2ClipDragDropOperation->TrackBody = StaticCastSharedPtr<STrackBody>(Body);
Clip2ClipDragDropOperation->DraggingWidget = SharedThis(this);
Clip2ClipDragDropOperation->DragDropType = FCutDragDropBase::EType::Clip2Clip;
Clip2ClipDragDropOperation->DragType = FClip2ClipDragDropOperation::EDragType::DragLeft;
@ -81,6 +83,7 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F
if (ClipData->bCanDrag)
{
const TSharedPtr<FClip2ClipDragDropOperation> Clip2ClipDragDropOperation = MakeShared<FClip2ClipDragDropOperation>();
Clip2ClipDragDropOperation->TrackBody = StaticCastSharedPtr<STrackBody>(Body);
Clip2ClipDragDropOperation->DraggingWidget = SharedThis(this);
Clip2ClipDragDropOperation->DragDropType = FCutDragDropBase::EType::Clip2Clip;
Clip2ClipDragDropOperation->DragType = FClip2ClipDragDropOperation::EDragType::DragRight;
@ -92,6 +95,7 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F
else
{
const TSharedPtr<FClip2ClipDragDropOperation> Clip2ClipDragDropOperation = MakeShared<FClip2ClipDragDropOperation>();
Clip2ClipDragDropOperation->TrackBody = StaticCastSharedPtr<STrackBody>(Body);
Clip2ClipDragDropOperation->DraggingWidget = SharedThis(this);
Clip2ClipDragDropOperation->DragDropType = FCutDragDropBase::EType::Clip2Clip;
Clip2ClipDragDropOperation->DragType = FClip2ClipDragDropOperation::EDragType::Move;

View File

@ -124,7 +124,7 @@ FReply STrackBody::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointer
{
TSharedPtr<FCutDragDropBase> DragDropOperator = MakeShared<FCutDragDropBase>();
DragDropOperator->DragDropType = FCutDragDropBase::EType::MovePanel;
DragDropOperator->DragOffset = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()).X;
DragDropOperator->DragOffset = MainWidgetInterface->GetCutTimeline()->GetCachedGeometry().AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()).X;
DragDropOperator->DraggingWidget = TrackHead->CutTimeline;
return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton).BeginDragDrop(DragDropOperator.ToSharedRef());
}