视频轨道
This commit is contained in:
parent
440945e67b
commit
eb09711d41
@ -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");
|
||||
|
7
Source/Cut5/Interface/CutMainWidgetInterface.cpp
Normal file
7
Source/Cut5/Interface/CutMainWidgetInterface.cpp
Normal 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.
|
27
Source/Cut5/Interface/CutMainWidgetInterface.h
Normal file
27
Source/Cut5/Interface/CutMainWidgetInterface.h
Normal 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) {};
|
||||
};
|
@ -14,7 +14,7 @@ AMainHUD::AMainHUD()
|
||||
GEngine->GameViewport->AddViewportWidgetContent(
|
||||
SNew(SCutMainWindow)
|
||||
);
|
||||
|
||||
|
||||
GEngine->bUseFixedFrameRate = 1;
|
||||
GEngine->FixedFrameRate = 60000.0f;
|
||||
|
||||
|
24
Source/Cut5/Utils/OpencvUtils.cpp
Normal file
24
Source/Cut5/Utils/OpencvUtils.cpp
Normal 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;
|
||||
}
|
10
Source/Cut5/Utils/OpencvUtils.h
Normal file
10
Source/Cut5/Utils/OpencvUtils.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
class FOpencvUtils
|
||||
{
|
||||
public:
|
||||
static int32 GetVideoFrameCount(FString VideoPath);
|
||||
};
|
||||
|
@ -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
|
||||
|
98
Source/Cut5/Widgets/SCustomInputPanel.cpp
Normal file
98
Source/Cut5/Widgets/SCustomInputPanel.cpp
Normal 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
|
27
Source/Cut5/Widgets/SCustomInputPanel.h
Normal file
27
Source/Cut5/Widgets/SCustomInputPanel.h
Normal 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;
|
||||
};
|
52
Source/Cut5/Widgets/SCustomInputResource.cpp
Normal file
52
Source/Cut5/Widgets/SCustomInputResource.cpp
Normal 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
|
26
Source/Cut5/Widgets/SCustomInputResource.h
Normal file
26
Source/Cut5/Widgets/SCustomInputResource.h
Normal 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;
|
||||
};
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -11,6 +11,7 @@ void STrackHead::Construct(const FArguments& InArgs)
|
||||
{
|
||||
TrackData = InArgs._TrackData;
|
||||
CutTimeline = InArgs._CutTimeline;
|
||||
MainWidgetInterface = InArgs._MainWidgetInterface;
|
||||
ChildSlot
|
||||
[
|
||||
SNew(SBox)
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user