视频轨道

This commit is contained in:
Sch 2023-07-04 13:57:26 +08:00
parent 440945e67b
commit eb09711d41
24 changed files with 463 additions and 74 deletions

View File

@ -13,7 +13,7 @@ public class Cut5 : ModuleRules
PrivateDependencyModuleNames.AddRange(new string[] { });
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore", "UMG", "OpenCV"});
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore", "UMG", "OpenCV", "DesktopPlatform"});
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");

View File

@ -0,0 +1,7 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "CutMainWidgetInterface.h"
// Add default functionality here for any ICutMainWidgetInterface functions that are not pure virtual.

View File

@ -0,0 +1,27 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "CutMainWidgetInterface.generated.h"
// This class does not need to be modified.
UINTERFACE()
class UCutMainWidgetInterface : public UInterface
{
GENERATED_BODY()
};
/**
*
*/
class CUT5_API ICutMainWidgetInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual void OnUpdateVideo(FGuid UUID, UTexture2D* Texture) {};
};

View File

@ -14,7 +14,7 @@ AMainHUD::AMainHUD()
GEngine->GameViewport->AddViewportWidgetContent(
SNew(SCutMainWindow)
);
GEngine->bUseFixedFrameRate = 1;
GEngine->FixedFrameRate = 60000.0f;

View File

@ -0,0 +1,24 @@
#include "OpencvUtils.h"
#undef check
#include <opencv2/videoio.hpp>
int32 FOpencvUtils::GetVideoFrameCount(FString VideoPath)
{
cv::VideoCapture VideoCapture;
VideoCapture.open(TCHAR_TO_UTF8(*VideoPath));
int32 FrameCount = 0;
while (VideoCapture.isOpened())
{
cv::Mat Array;
if (VideoCapture.read(Array))
{
FrameCount++;
}
if (Array.empty())
{
break;
}
}
return FrameCount;
}

View File

@ -0,0 +1,10 @@
#pragma once
class FOpencvUtils
{
public:
static int32 GetVideoFrameCount(FString VideoPath);
};

View File

@ -37,6 +37,31 @@ struct CUT5_API FClipData
int32 GetClipStartFrame() const { return ClipStartTime / FGlobalData::DefaultTimeTickSpace; };
int32 GetClipEndFrame() const { return ClipEndTime / FGlobalData::DefaultTimeTickSpace; };
enum class ECropMethod
{
FromFront,
FromBack,
};
void CropClip(ECropMethod CropMethod, int32 CropFrame)
{
if (CropMethod == ECropMethod::FromFront)
{
ClipStartTime += CropFrame * FGlobalData::DefaultTimeTickSpace;
if (ClipType == ETrackType::VideoTrack)
{
VideoStartFrame += CropFrame;
}
}
else
{
ClipEndTime -= CropFrame * FGlobalData::DefaultTimeTickSpace;
if (ClipType == ETrackType::VideoTrack)
{
VideoEndFrame -= CropFrame;
}
}
}
// Movies
FString MoviePath;
@ -54,6 +79,10 @@ struct CUT5_API FTimelinePropertyData
}
FString Name = "";
ETrackType Type = ETrackType::VideoTrack;
// Movie Data
FString MoviePath = "";
int32 MovieFrameLength = 0;
};
class CUT5_API FTrackClipDragOperation final : public FDecoratedDragDropOp

View File

@ -0,0 +1,98 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "SCustomInputPanel.h"
#include "DesktopPlatformModule.h"
#include "SCustomInputResource.h"
#include "SlateOptMacros.h"
#include "Widgets/Layout/SGridPanel.h"
#include "Widgets/Layout/SScaleBox.h"
#include "Widgets/Layout/SScrollBox.h"
#undef check
#include <opencv2/videoio.hpp>
#include "Cut5/Utils/OpencvUtils.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SCustomInputPanel::Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SScaleBox)
.Stretch(EStretch::ScaleToFit)
[
SNew(SBox)
.WidthOverride(300)
.HeightOverride(300)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.SizeParam(FStretch(0.9))
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SScrollBox)
+ SScrollBox::Slot()
[
SAssignNew(GridPanel, SGridPanel)
]
]
+ SVerticalBox::Slot()
.SizeParam(FStretch(0.1))
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SNew(SButton)
.Text(FText::FromString(TEXT("Open Video")))
.OnClicked_Lambda([this]()
{
IDesktopPlatform* DesktopPlatformModule = FDesktopPlatformModule::Get();
TArray<FString> OpenFileName;
DesktopPlatformModule->OpenFileDialog(nullptr, (TEXT("打开文件")), TEXT(""), TEXT(""), TEXT(""), EFileDialogFlags::None, OpenFileName);
for (int32 i = 0; i < OpenFileName.Num(); i++)
{
Async(EAsyncExecution::Thread, [&, this, OpenFileName, i]
{
const int32 FrameCount = FOpencvUtils::GetVideoFrameCount(OpenFileName[i]);
FGraphEventRef Task = FFunctionGraphTask::CreateAndDispatchWhenReady([&]()
{
FTimelinePropertyData PropertyData;
PropertyData.Name = OpenFileName[i];
PropertyData.Type = ETrackType::VideoTrack;
PropertyData.MoviePath = OpenFileName[i];
PropertyData.MovieFrameLength = FrameCount;
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 3, GridPanel->GetChildren()->Num() / 3)
[
SNew(SCustomInputResource)
.PropertyData(PropertyData)
];
}, TStatId(), nullptr, ENamedThreads::GameThread);
FTaskGraphInterface::Get().WaitUntilTaskCompletes(Task);
});
}
return FReply::Handled();
})
]
]
]
]
];
}
FReply SCustomInputPanel::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
return FReply::Handled().EndDragDrop();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -0,0 +1,27 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/Layout/SGridPanel.h"
/**
*
*/
class CUT5_API SCustomInputPanel : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCustomInputPanel)
{
}
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
TSharedPtr<SGridPanel> GridPanel;
};

View File

@ -0,0 +1,52 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "SCustomInputResource.h"
#include "DefineGlobal.h"
#include "SlateOptMacros.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SCustomInputResource::Construct(const FArguments& InArgs)
{
PropertyData = InArgs._PropertyData;
ChildSlot
[
SNew(SBox)
.WidthOverride(100)
.HeightOverride(100)
[
SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SButton)
]
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SImage)
]
]
];
}
FReply SCustomInputResource::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton);
}
FReply SCustomInputResource::OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
const TSharedPtr<FTrackClipDragOperation> Operation = MakeShared<FTrackClipDragOperation>();
Operation->TimelinePropertyData = PropertyData;
Operation->DraggingWidget = SharedThis(this);
return FReply::Handled().BeginDragDrop(Operation.ToSharedRef());
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "DefineGlobal.h"
#include "Widgets/SCompoundWidget.h"
/**
*
*/
class CUT5_API SCustomInputResource : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SCustomInputResource)
{
}
SLATE_ARGUMENT(FTimelinePropertyData, PropertyData)
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
FTimelinePropertyData PropertyData;
void Construct(const FArguments& InArgs);
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
};

View File

@ -3,6 +3,7 @@
#include "SCutMainWindow.h"
#include "SCustomInputPanel.h"
#include "SCutTimeline.h"
#include "SlateOptMacros.h"
#include "STimelinePropertyPanel.h"
@ -14,7 +15,7 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SCutMainWindow::Construct(const FArguments& InArgs)
{
SAssignNew(CutTimeline, SCutTimeline);
SAssignNew(CutTimeline, SCutTimeline).MainWidgetInterface(this);
SAssignNew(LightArrayPanel, SLightArrayPanel);
SAssignNew(VideoPlayer, SVideoPlayer);
ChildSlot
@ -66,6 +67,16 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
LightArrayPanel.ToSharedRef()
]
]
+ SHorizontalBox::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SNew(SCustomInputPanel)
]
]
]
+ SVerticalBox::Slot()
@ -78,31 +89,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs)
]
];
FTrackData NewTrack;
NewTrack.TrackName = "Track 1";
NewTrack.TrackType = ETrackType::VideoTrack;
CutTimeline->AddNewTrack(NewTrack, 0);
FTrackData NewTrack2;
NewTrack2.TrackName = "Track 2";
NewTrack2.TrackType = ETrackType::VideoTrack;
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
CutTimeline->AddNewTrack(NewTrack2, 0);
}
FReply SCutMainWindow::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
@ -117,4 +104,12 @@ FReply SCutMainWindow::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent&
}
void SCutMainWindow::OnUpdateVideo(FGuid UUID, UTexture2D* Texture)
{
ICutMainWidgetInterface::OnUpdateVideo(UUID, Texture);
VideoPlayer->UpdateVideoData(UUID, Texture);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -6,12 +6,13 @@
#include "SCutTimeline.h"
#include "SLightArrayPanel.h"
#include "SVideoPlayer.h"
#include "Cut5/Interface/CutMainWidgetInterface.h"
#include "Widgets/SCompoundWidget.h"
/**
*
*/
class CUT5_API SCutMainWindow : public SCompoundWidget
class CUT5_API SCutMainWindow : public SCompoundWidget, public ICutMainWidgetInterface
{
public:
SLATE_BEGIN_ARGS(SCutMainWindow)
@ -31,4 +32,5 @@ public:
virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
virtual void OnUpdateVideo(FGuid UUID, UTexture2D* Texture) override;
};

View File

@ -49,7 +49,7 @@ int32 SCutTimeline::GetCursorPosition() const
void SCutTimeline::Construct(const FArguments& InArgs)
{
MainWidgetInterface = InArgs._MainWidgetInterface;
ChildSlot
[
SNew(SVerticalBox)
@ -175,8 +175,8 @@ void SCutTimeline::Construct(const FArguments& InArgs)
void SCutTimeline::AddNewTrack(FTrackData TrackData, int32 TrackIndex)
{
TrackDataArray.Insert(TrackData, TrackIndex);
const TSharedPtr<STrackHead> NewTrackHead = SNew(STrackHead).TrackData(TrackData).CutTimeline(SharedThis(this));
const TSharedPtr<STrackBody> NewTrackBody = SNew(STrackBody).TrackHead(NewTrackHead);
const TSharedPtr<STrackHead> NewTrackHead = SNew(STrackHead).TrackData(TrackData).CutTimeline(SharedThis(this)).MainWidgetInterface(MainWidgetInterface);
const TSharedPtr<STrackBody> NewTrackBody = SNew(STrackBody).TrackHead(NewTrackHead).MainWidgetInterface(MainWidgetInterface);
TrackHeadScrollBox->AddSlot()
[
NewTrackHead.ToSharedRef()
@ -188,9 +188,16 @@ void SCutTimeline::AddNewTrack(FTrackData TrackData, int32 TrackIndex)
AllWidgets.Add(NewTrackBody.Get());
}
FReply SCutTimeline::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
FReply SCutTimeline::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
// Add new Track
const FTrackClipDragOperation& ClipDragOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
FTrackData TrackData;
TrackData.TrackName = ClipDragOperation.TimelinePropertyData.Name;
TrackData.TrackType = ClipDragOperation.TimelinePropertyData.Type;
AddNewTrack(TrackData, 0);
return SCompoundWidget::OnDrop(MyGeometry, DragDropEvent);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -7,6 +7,7 @@
#include "STimelineTick.h"
#include "Cut5/WidgetInterface.h"
#include "Cut5/Interface/CutMainWidgetInterface.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/Layout/SScrollBox.h"
@ -24,6 +25,7 @@ public:
SLATE_BEGIN_ARGS(SCutTimeline)
{
}
SLATE_ARGUMENT(ICutMainWidgetInterface*, MainWidgetInterface)
SLATE_END_ARGS()
void UpdateTimelineLength();
@ -33,7 +35,7 @@ public:
void Construct(const FArguments& InArgs);
void AddNewTrack(FTrackData TrackData, int32 TrackIndex);
ICutMainWidgetInterface* MainWidgetInterface;
TArray<FTrackData> TrackDataArray;
TArray<IWidgetInterface*> AllWidgets;
TSharedPtr<STimelineTick> TimelineTick;
@ -43,5 +45,6 @@ public:
TSharedPtr<SBox> TimelineTickBox;
TSharedPtr<SScrollBox> TickScrollBox;
virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
};

View File

@ -4,12 +4,17 @@
#include "STimelineClip.h"
#include "SlateOptMacros.h"
#undef check
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/mat.hpp>
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void STimelineClip::Construct(const FArguments& InArgs)
{
ClipData = InArgs._InClipData;
MainWidgetInterface = InArgs._MainWidgetInterface;
ChildSlot
[
SNew(SBox)
@ -25,12 +30,60 @@ void STimelineClip::Construct(const FArguments& InArgs)
}
void STimelineClip::Seek()
void STimelineClip::Seek(int32 Frame)
{
switch (ClipData.ClipType)
{
case ETrackType::VideoTrack:
{
FDateTime A = FDateTime::Now();
cv::VideoCapture Capture;
Capture.open(TCHAR_TO_UTF8(*ClipData.MoviePath));
GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::Red, FString::Printf(TEXT("Read Time: %f"), (FDateTime::Now() - A).GetTotalMilliseconds()));
const int32 Offset = Frame - (ClipData.ClipStartTime / FGlobalData::TrackLength);
Capture.set(cv::CAP_PROP_POS_FRAMES, ClipData.VideoStartFrame + Offset);
cv::Mat Read;
Capture.read(Read);
UTexture2D* Texture = UTexture2D::CreateTransient(Read.cols, Read.rows, PF_B8G8R8A8);
if (Texture)
{
A = FDateTime::Now();
uint8* RGBAData = new uint8[Read.cols * Read.rows * 4];
for (int i = 0; i < Read.cols * Read.rows; i++)
{
RGBAData[i * 4 + 0] = Read.data[i * 3 + 0];
RGBAData[i * 4 + 1] = Read.data[i * 3 + 1];
RGBAData[i * 4 + 2] = Read.data[i * 3 + 2];
RGBAData[i * 4 + 3] = 255;
}
GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::Red, FString::Printf(TEXT("RGBA Time: %f"), (FDateTime::Now() - A).GetTotalMilliseconds()));
void* MipData = Texture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(MipData, RGBAData, Read.cols * Read.rows * 4);
Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
Texture->UpdateResource();
MainWidgetInterface->OnUpdateVideo(FGuid::NewGuid(), Texture);
}
// Async(EAsyncExecution::Thread, [this, Frame]()
// {
// cv::VideoCapture Capture;
// Capture.open(TCHAR_TO_UTF8(*ClipData.MoviePath), cv::CAP_FFMPEG);
// const int32 Offset = Frame - (ClipData.ClipStartTime / FGlobalData::TrackLength);
// Capture.set(cv::CAP_PROP_POS_FRAMES, ClipData.VideoStartFrame + Offset);
// cv::Mat Read;
// Capture.read(Read);
// FGraphEventRef Task = FFunctionGraphTask::CreateAndDispatchWhenReady([&]()
// {
//
//
// }, TStatId(), nullptr, ENamedThreads::GameThread);
// FTaskGraphInterface::Get().WaitUntilTaskCompletes(Task);
// });
}
break;
default:
break;

View File

@ -4,6 +4,7 @@
#include "CoreMinimal.h"
#include "DefineGlobal.h"
#include "Cut5/Interface/CutMainWidgetInterface.h"
#include "Widgets/SCompoundWidget.h"
/**
@ -16,11 +17,13 @@ public:
{
}
SLATE_ARGUMENT(FClipData, InClipData)
SLATE_ARGUMENT(ICutMainWidgetInterface*, MainWidgetInterface)
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
FClipData ClipData;
virtual void Seek();
ICutMainWidgetInterface* MainWidgetInterface;
virtual void Seek(int32 Frame);
};

View File

@ -24,16 +24,9 @@ void STimelinePropertyPanel::Construct(const FArguments& InArgs)
]
]
];
AddNewSelection(FTimelinePropertyData("Test", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test1", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test2", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test3", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test4", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test5", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test6", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test7", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test8", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData("Test9", ETrackType::VideoTrack));
AddNewSelection(FTimelinePropertyData(TEXT("玩家"), ETrackType::PlayerTrack));
AddNewSelection(FTimelinePropertyData(TEXT("聚光灯"), ETrackType::SpotLightTrack));
AddNewSelection(FTimelinePropertyData(TEXT("氛围灯"), ETrackType::AtomSphereLightTrack));
}

View File

@ -10,6 +10,7 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void STrackBody::Construct(const FArguments& InArgs)
{
MainWidgetInterface = InArgs._MainWidgetInterface;
TrackHead = InArgs._TrackHead;
ChildSlot
[
@ -48,7 +49,7 @@ void STrackBody::CallRender()
TrackHead->CutTimeline->UpdateTimelineLength();
}
TSharedPtr<STimelineClip> TimelineClip;
TimelineClip = SNew(STimelineClip).InClipData(TempClipData);
TimelineClip = SNew(STimelineClip).InClipData(TempClipData).MainWidgetInterface(MainWidgetInterface);
Overlay->AddSlot()
.HAlign(HAlign_Left)
@ -66,44 +67,68 @@ FReply STrackBody::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& Dra
const FTrackClipDragOperation& ClipDragOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
if (ClipDragOperation.TimelinePropertyData.Type == TrackHead->TrackData.TrackType)
{
FClipData NewClipData;
NewClipData.ClipGuid = FGuid::NewGuid();
NewClipData.ClipType = ClipDragOperation.TimelinePropertyData.Type;
NewClipData.ClipStartTime = FMath::TruncToInt(MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X / FGlobalData::DefaultTimeTickSpace) * FGlobalData::DefaultTimeTickSpace;
NewClipData.ClipColors.Add(FLinearColor(1, 1, 1, 1));;
NewClipData.ClipEndTime = NewClipData.ClipStartTime + 200;
NewClipData.ClipColors.Add(FLinearColor(1, 1, 1, 1));
if (ClipDragOperation.TimelinePropertyData.Type == ETrackType::VideoTrack)
{
NewClipData.MoviePath = ClipDragOperation.TimelinePropertyData.MoviePath;
NewClipData.ClipEndTime = NewClipData.ClipStartTime + ClipDragOperation.TimelinePropertyData.MovieFrameLength * FGlobalData::DefaultTimeTickSpace;
}
else
{
NewClipData.ClipEndTime = NewClipData.ClipStartTime + 200;
}
//Overwrite the clip if it is in the same position
TArray<int32, TInlineAllocator<2>> Indexes = {-1, -1};
for (int32 i = TrackHead->TrackData.ClipData.Num() - 1; i >= 0; i--)
{
const double ClipStartTime = TrackHead->TrackData.ClipData[i].ClipStartTime;
const double ClipEndTime = TrackHead->TrackData.ClipData[i].ClipEndTime;
if (NewClipData.ClipEndTime < ClipEndTime && NewClipData.ClipEndTime > ClipStartTime)
if (NewClipData.ClipStartTime >= ClipStartTime && NewClipData.ClipEndTime <= ClipEndTime)
{
Indexes[0] = i;
// 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.ClipEndTime = NewClipData.ClipStartTime;
TrackHead->TrackData.ClipData.Add(LeftClipData);
FClipData RightClipData = SaveClipData;
RightClipData.ClipStartTime = NewClipData.ClipEndTime;
TrackHead->TrackData.ClipData.Add(RightClipData);
continue;
}
if (NewClipData.ClipStartTime > ClipStartTime && NewClipData.ClipStartTime < ClipEndTime)
if (NewClipData.ClipStartTime <= ClipEndTime && NewClipData.ClipEndTime >= ClipEndTime)
{
Indexes[1] = i;
// It mean the new clip start point is in the old clip
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromBack, (ClipEndTime - NewClipData.ClipStartTime) / FGlobalData::DefaultTimeTickSpace);
continue;
}
if (NewClipData.ClipEndTime > ClipStartTime && NewClipData.ClipStartTime < ClipStartTime)
{
// It mean the new clip end point is in the old clip
TrackHead->TrackData.ClipData[i].CropClip(FClipData::ECropMethod::FromFront, (NewClipData.ClipEndTime - ClipStartTime) / FGlobalData::DefaultTimeTickSpace);
continue;
}
if (NewClipData.ClipStartTime <= ClipStartTime && NewClipData.ClipEndTime >= ClipEndTime)
{
// It mean the new clip is out of the old clip
TrackHead->TrackData.ClipData.RemoveAt(i);
continue;
}
}
if (Indexes[0] != -1 && Indexes[1] == -1)
{
TrackHead->TrackData.ClipData[Indexes[0]].ClipStartTime = NewClipData.ClipEndTime;
}
if (Indexes[1] != -1 && Indexes[0] == -1)
{
TrackHead->TrackData.ClipData[Indexes[1]].ClipEndTime = NewClipData.ClipStartTime;
}
else
{
}
TrackHead->TrackData.ClipData.Add(NewClipData);
GEngine->AddOnScreenDebugMessage(-1, 10.0, FColor::Green, FString::Printf(TEXT("Track %d"), TrackHead->TrackData.ClipData.Num()));
CallRender();
}
@ -132,7 +157,7 @@ void STrackBody::Seek(int32 Frame)
{
if (SlateClips[i]->ClipData.GetClipStartFrame() <= Frame && SlateClips[i]->ClipData.GetClipEndFrame() > Frame)
{
SlateClips[i]->Seek();
SlateClips[i]->Seek(Frame);
break;
}
}

View File

@ -17,6 +17,7 @@ public:
{
}
SLATE_ARGUMENT(TSharedPtr<STrackHead>, TrackHead)
SLATE_ARGUMENT(ICutMainWidgetInterface*, MainWidgetInterface)
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
@ -27,6 +28,7 @@ public:
virtual void OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
virtual void OnDragLeave(const FDragDropEvent& DragDropEvent) override;
TSharedPtr<STrackHead> TrackHead;
ICutMainWidgetInterface* MainWidgetInterface;
TSharedPtr<SOverlay> Overlay;
TSharedPtr<SBox> TrackBodyBox;
TArray<TSharedPtr<STimelineClip>> SlateClips;

View File

@ -11,6 +11,7 @@ void STrackHead::Construct(const FArguments& InArgs)
{
TrackData = InArgs._TrackData;
CutTimeline = InArgs._CutTimeline;
MainWidgetInterface = InArgs._MainWidgetInterface;
ChildSlot
[
SNew(SBox)

View File

@ -4,6 +4,7 @@
#include "CoreMinimal.h"
#include "SCutTimeline.h"
#include "Cut5/Interface/CutMainWidgetInterface.h"
#include "Widgets/SCompoundWidget.h"
/**
@ -17,6 +18,7 @@ public:
}
SLATE_ARGUMENT(FTrackData, TrackData);
SLATE_ARGUMENT(TSharedPtr<SCutTimeline>, CutTimeline);
SLATE_ARGUMENT(ICutMainWidgetInterface*, MainWidgetInterface);
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
@ -24,4 +26,5 @@ public:
FTrackData TrackData;
TSharedPtr<SCutTimeline> CutTimeline;
ICutMainWidgetInterface* MainWidgetInterface;
};

View File

@ -26,9 +26,11 @@ void SVideoPlayer::Construct(const FArguments& InArgs)
];
}
void SVideoPlayer::UpdateVideoData(FGuid UUID, FLinearColor Color)
void SVideoPlayer::UpdateVideoData(FGuid UUID, UTexture2D* Texture)
{
FSlateBrush* Brush = new FSlateBrush();
Brush->SetResourceObject(Texture);
VideoImage->SetImage(Brush);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -19,6 +19,6 @@ public:
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
void UpdateVideoData(FGuid UUID, FLinearColor Color);
void UpdateVideoData(FGuid UUID, UTexture2D* Texture);
TSharedPtr<SImage> VideoImage;
};