造个点阵

This commit is contained in:
Sch 2023-07-07 02:51:44 +08:00
parent e0890af948
commit ff430b9e70
20 changed files with 150 additions and 60 deletions

Binary file not shown.

Binary file not shown.

View File

@ -24,4 +24,5 @@ class CUT5_API ICutMainWidgetInterface
public:
virtual void OnUpdateVideo(FGuid UUID, UTexture2D* Texture) {};
};

View File

@ -21,5 +21,7 @@ AMainHUD::AMainHUD()
UWidgetBlueprintLibrary::SetInputMode_UIOnlyEx(UGameplayStatics::GetPlayerController(GWorld, 0), nullptr, EMouseLockMode::DoNotLock);
UGameplayStatics::GetPlayerController(GWorld, 0)->bShowMouseCursor = true;
// UKismetSystemLibrary::ExecuteConsoleCommand(this, "Slate.EnableGlobalInvalidation 1");
}
}

View File

@ -1,6 +1,5 @@
#include "OpencvUtils.h"
#undef check
#include <opencv2/videoio.hpp>
int32 FOpencvUtils::GetVideoFrameCount(FString VideoPath)
@ -11,7 +10,7 @@ int32 FOpencvUtils::GetVideoFrameCount(FString VideoPath)
while (VideoCapture.isOpened())
{
cv::Mat Array;
if (VideoCapture.read(Array))
if (VideoCapture.grab())
{
FrameCount++;
}
@ -20,5 +19,6 @@ int32 FOpencvUtils::GetVideoFrameCount(FString VideoPath)
break;
}
}
VideoCapture.release();
return FrameCount;
}

View File

@ -1,12 +1,15 @@
#pragma once
#include "DragAndDrop/DecoratedDragDropOp.h"
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/mat.hpp>
class CUT5_API FGlobalData
{
public:
inline static int32 DefaultTrackHeight = 50;
inline static int32 TrackLength = 1000;
inline static double DefaultTimeTickSpace = 10.0;
inline static double DefaultTimeTickSpace = 9.0;
inline static int32 LightArrayX = 70;
inline static int32 LightArrayY = 42;
@ -73,6 +76,8 @@ struct CUT5_API FClipData
FString MoviePath;
int32 VideoStartFrame = 0;
int32 VideoEndFrame = 0;
cv::VideoCapture* VideoCapture;
};
struct CUT5_API FTimelinePropertyData
@ -94,13 +99,22 @@ struct CUT5_API FTimelinePropertyData
class CUT5_API FCutDragDropBase : public FDecoratedDragDropOp
{
public:
// TODO: I Decide to use type to Main Widget to handle all drag over event
enum class EType
{
TrackClip,
Clip2Clip,
TickDrag,
};
FCutDragDropBase() {};
FCutDragDropBase(EType InType)
{
Type = InType;
}
TSharedPtr<SWidget> DraggingWidget;
EType Type;
EType Type = EType::TrackClip;
};
@ -108,7 +122,7 @@ class CUT5_API FTrackClipDragOperation final : public FCutDragDropBase
{
public:
FTimelinePropertyData TimelinePropertyData;
cv::VideoCapture* VideoCapture;
};
class CUT5_API FClip2ClipDragDropOperation final : public FCutDragDropBase

View File

@ -61,7 +61,9 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
{
Async(EAsyncExecution::Thread, [&, this, OpenFileName, i]
{
const int32 FrameCount = FOpencvUtils::GetVideoFrameCount(OpenFileName[i]);
cv::VideoCapture NewCapture(TCHAR_TO_UTF8(*OpenFileName[i]));
const int32 FrameCount = NewCapture.get(cv::CAP_PROP_FRAME_COUNT);
FGraphEventRef Task = FFunctionGraphTask::CreateAndDispatchWhenReady([&]()
{
FTimelinePropertyData PropertyData;
@ -73,6 +75,7 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
[
SNew(SCustomInputResource)
.PropertyData(PropertyData)
.VideoCapture(NewCapture)
];
}, TStatId(), nullptr, ENamedThreads::GameThread);

View File

@ -11,6 +11,7 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SCustomInputResource::Construct(const FArguments& InArgs)
{
PropertyData = InArgs._PropertyData;
VideoCapture = InArgs._VideoCapture;
ChildSlot
[
SNew(SBox)
@ -47,6 +48,7 @@ FReply SCustomInputResource::OnDragDetected(const FGeometry& MyGeometry, const F
Operation->TimelinePropertyData = PropertyData;
Operation->DraggingWidget = SharedThis(this);
Operation->Type = FCutDragDropBase::EType::TrackClip;
Operation->VideoCapture = &VideoCapture;
return FReply::Handled().BeginDragDrop(Operation.ToSharedRef());
}

View File

@ -16,6 +16,7 @@ public:
{
}
SLATE_ARGUMENT(FTimelinePropertyData, PropertyData)
SLATE_ARGUMENT(cv::VideoCapture, VideoCapture)
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
@ -24,5 +25,5 @@ public:
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
cv::VideoCapture VideoCapture;
};

View File

@ -109,7 +109,23 @@ void SCutMainWindow::OnUpdateVideo(FGuid UUID, UTexture2D* Texture)
{
ICutMainWidgetInterface::OnUpdateVideo(UUID, Texture);
VideoPlayer->UpdateVideoData(UUID, Texture);
FColor* Colors = static_cast<FColor*>(Texture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE));
for (int32 i = 0; i < FGlobalData::LightArrayX; i++)
{
for (int32 j = 0; j < FGlobalData::LightArrayY; j++)
{
const int32 X = Texture->GetSizeX() / FGlobalData::LightArrayX;
const int32 Y = Texture->GetSizeY() / FGlobalData::LightArrayY;
const int32 ColorIndex = X * i + j * Y * Texture->GetSizeX();
LightArrayPanel->UpdateLightArray(i, j, *(Colors + ColorIndex));
}
}
Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -33,4 +33,5 @@ public:
virtual void OnUpdateVideo(FGuid UUID, UTexture2D* Texture) override;
};

View File

@ -22,7 +22,7 @@ void SCutTimeline::UpdateTimelineLength()
TimelineTick->GenerateTickBox(FGlobalData::TrackLength / FGlobalData::DefaultTimeTickSpace);
}
void SCutTimeline::UpdateCursorPosition(int32 Frame) const
void SCutTimeline::UpdateCursorPosition(int32 Frame)
{
if (TimelineTick.IsValid())
{
@ -34,6 +34,10 @@ void SCutTimeline::UpdateCursorPosition(int32 Frame) const
Interface->Seek(Frame);
}
}
else
{
SetAutoPlay(false);
}
}
}
@ -135,6 +139,17 @@ void SCutTimeline::Construct(const FArguments& InArgs)
TickScrollBox->SetScrollOffset(ChangedValue * TickScrollBox->GetScrollOffsetOfEnd());
})
]
// + SVerticalBox::Slot()
// .SizeParam(FAuto())
// [
// SNew(SSlider)
// .Value(FMath::GetMappedRangeValueClamped(FVector2D(5, 15), FVector2D(0, 1), FGlobalData::DefaultTimeTickSpace))
// .OnValueChanged_Lambda([this](float ChangedValue)
// {
// FGlobalData::DefaultTimeTickSpace = FMath::GetMappedRangeValueClamped(FVector2D(0, 1), FVector2D(5, 15), ChangedValue);
// UpdateTimelineLength();
// })
// ]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
@ -216,7 +231,7 @@ FReply SCutTimeline::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& D
{
// Add new Track
const FTrackClipDragOperation& ClipDragOperation = static_cast<FTrackClipDragOperation&>(DragDropEvent.GetOperation().ToSharedRef().Get());
if (ClipDragOperation.Type != FTrackClipDragOperation::EType::Clip2Clip)
if (ClipDragOperation.Type == FTrackClipDragOperation::EType::TrackClip)
{
FTrackData TrackData;
TrackData.TrackName = ClipDragOperation.TimelinePropertyData.Name;

View File

@ -29,7 +29,7 @@ public:
SLATE_END_ARGS()
void UpdateTimelineLength();
void UpdateCursorPosition(int32 Frame) const;
void UpdateCursorPosition(int32 Frame);
int32 GetCursorPosition() const;
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);

View File

@ -4,6 +4,7 @@
#include "SLightArrayPanel.h"
#include "DefineGlobal.h"
#include "SCutMainWindow.h"
#include "SlateOptMacros.h"
#include "Widgets/Layout/SGridPanel.h"
#include "Widgets/Layout/SScaleBox.h"
@ -12,7 +13,7 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SLightArrayPanel::Construct(const FArguments& InArgs)
{
LightGridColors.Init(FColor(255, 0, 0, 255), FGlobalData::LightArrayX * FGlobalData::LightArrayY);
ChildSlot
[
SNew(SScaleBox)
@ -51,51 +52,36 @@ void SLightArrayPanel::Construct(const FArguments& InArgs)
}
void SLightArrayPanel::GenerateLightArray()
{
}
void SLightArrayPanel::UpdateLightArray(int32 X, int32 Y, FColor Color)
{
LightGridColors[X * FGlobalData::LightArrayY + Y] = Color;
}
int32 SLightArrayPanel::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
for (int32 i = 0; i < FGlobalData::LightArrayX; i++)
{
for (int32 j = 0; j < FGlobalData::LightArrayY; j++)
{
LightGrid->AddSlot(i, j)
[
SNew(SBox)
[
SNew(SBorder)
.ColorAndOpacity(FLinearColor(1, 1, 0, 1))
]
];
const FSlateBrush Brush;
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId,
AllottedGeometry.ToPaintGeometry(FVector2D(600.0 / FGlobalData::LightArrayX - 1.2, 400.0 / FGlobalData::LightArrayY - 1.2), FSlateLayoutTransform(FVector2D(i * 600.0 / FGlobalData::LightArrayX, j * 400.0 / FGlobalData::LightArrayY))),
&Brush,
ESlateDrawEffect::None,
LightGridColors[i * FGlobalData::LightArrayY + j]);
}
}
for (int32 i = 0; i < FGlobalData::LightArrayX; i++)
{
LightBar1->AddSlot()
[
SNew(SBox)
[
SNew(SBorder)
.ColorAndOpacity(FLinearColor(1, 0, 1, 1))
]
];
}
for (int32 i = 0; i < FGlobalData::LightArrayX; i++)
{
LightBar2->AddSlot()
[
SNew(SBox)
[
SNew(SBorder)
.ColorAndOpacity(FLinearColor(1, 0, 1, 1))
]
];
}
}
void SLightArrayPanel::UpdateLightArray(int32 X, int32 Y, FLinearColor Color)
{
return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle,
bParentEnabled);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -21,8 +21,10 @@ public:
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
void GenerateLightArray();
void UpdateLightArray(int32 X, int32 Y, FLinearColor Color);
void UpdateLightArray(int32 X, int32 Y, FColor Color);
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
TSharedPtr<SGridPanel> LightGrid;
TSharedPtr<SHorizontalBox> LightBar1;
TSharedPtr<SHorizontalBox> LightBar2;
TArray<FColor> LightGridColors;
};

View File

@ -4,10 +4,7 @@
#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
@ -61,17 +58,42 @@ void STimelineClip::Seek(int32 Frame)
{
case ETrackType::VideoTrack:
{
if (!ClipData->VideoCapture || Frame > ClipData->ClipEndTime / FGlobalData::DefaultTimeTickSpace || Frame < 0)
{
return;
}
FDateTime A = FDateTime::Now();
cv::VideoCapture Capture;
Capture.open(TCHAR_TO_UTF8(*ClipData->MoviePath));
const int32 Offset = Frame - (ClipData->ClipStartTime / FGlobalData::DefaultTimeTickSpace);
const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset;
if (SeekMovieFrame > LastSeekFrame)
{
const int32 SeekOffset = SeekMovieFrame - LastSeekFrame;
for (int32 i = 0; i < SeekOffset; i++)
{
ClipData->VideoCapture->grab();
}
}
else if (SeekMovieFrame < LastSeekFrame)
{
ClipData->VideoCapture->set(cv::CAP_PROP_POS_FRAMES, 0);
for (int32 i = 0; i < SeekMovieFrame; i++)
{
ClipData->VideoCapture->grab();
}
}
LastSeekFrame = SeekMovieFrame;
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);
ClipData->VideoCapture->retrieve(Read);
// ClipData->VideoCapture->read(Read);
UTexture2D* Texture = UTexture2D::CreateTransient(Read.cols, Read.rows, PF_B8G8R8A8);
if (Texture)
{
A = FDateTime::Now();

View File

@ -6,6 +6,10 @@
#include "DefineGlobal.h"
#include "Cut5/Interface/CutMainWidgetInterface.h"
#include "Widgets/SCompoundWidget.h"
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/mat.hpp>
/**
*
@ -30,5 +34,7 @@ public:
void UpdatePosition(double StartTime);
void UpdateLength(double X);
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
int32 LastSeekFrame = 0;
};

View File

@ -56,4 +56,19 @@ void STimelineTick::GenerateTickBox(int32 TickCount)
}
FReply STimelineTick::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
const int32 NewFrame = FMath::TruncToInt(MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()).X / FGlobalData::DefaultTimeTickSpace) * FGlobalData::DefaultTimeTickSpace;
UpdateNewCursorPosition(NewFrame);
return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton).BeginDragDrop(MakeShared<FCutDragDropBase>(FCutDragDropBase::EType::TickDrag));
}
FReply STimelineTick::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
UpdateNewCursorPosition((MyGeometry.AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X));
return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -27,4 +27,7 @@ public:
TSharedPtr<SOverlay> TickBox;
TSharedPtr<SBox> TickLengthBox;
TSharedPtr<SImage> TickCursor;
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
};

View File

@ -82,6 +82,7 @@ FReply STrackBody::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& Dra
{
NewClipData.MoviePath = ClipDragOperation.TimelinePropertyData.MoviePath;
NewClipData.ClipEndTime = NewClipData.ClipStartTime + ClipDragOperation.TimelinePropertyData.MovieFrameLength * FGlobalData::DefaultTimeTickSpace;
NewClipData.VideoCapture = ClipDragOperation.VideoCapture;
}
else
{