视频和psaf的导出

This commit is contained in:
Sch 2023-08-11 14:24:04 +08:00
parent 88b1288d3c
commit 79887a5dab
10 changed files with 698 additions and 218 deletions

View File

@ -39,7 +39,7 @@ public:
virtual void PreSettingBeforeSeek() {};
virtual void AddNewCard(FEffectCardProperty& CardProperty, FString GroupName) {};
virtual void OpenTimeline(const FString& TimelineName, bool NeedSaveBefore = false) {};
virtual void OpenTimeline(const FString& TimelineName, bool NeedSaveBefore = false, bool ForceOpen = false) {};
virtual void OpenProject(const FString& Project) {};
virtual void PreNewProject() {};
virtual void ExportProject(const FString& ExportPath) {};

View File

@ -1,11 +1,20 @@
#include "Utils.h"
#include "Cut5/Widgets/DefineGlobal.h"
#include "Kismet/KismetStringLibrary.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
#include <fstream>
#define EXPORT_PROCESSED_VIDEO 0
#include <opencv2/videoio/legacy/constants_c.h>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/mat.hpp>
FString FUtils::MakeStringUpright(const FString& String)
{
@ -84,7 +93,7 @@ void FUtils::CreateDefaultTimelineSave(const FString& SavedPath, const FTimeline
FFileHelper::SaveArrayToFile(SavedData, *SavedPath);
}
void FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath)
TArray<FEncodeVideoInfo> FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath)
{
@ -94,21 +103,22 @@ void FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& Export
int32 i = 0;
TArray<FEncodeVideoInfo> EncodeVideoInfos;
for (FClipData& TempClipData : ClipData)
{
if (TempClipData.ResourcePropertyDataPtr->Context)
{
FEncodeVideoInfo EncodeVideoInfo;
FTimespan EndTimespan = FTimespan::FromSeconds(TempClipData.VideoEndFrame / FGlobalData::GlobalFPS);
FTimespan StartTimespan = FTimespan::FromSeconds(TempClipData.VideoStartFrame / FGlobalData::GlobalFPS);
FString StartTime = FString::Printf(TEXT("%02d:%02d:%02d"), StartTimespan.GetHours(), StartTimespan.GetMinutes(), StartTimespan.GetSeconds());
FString EndTime = FString::Printf(TEXT("%02d:%02d:%02d"), EndTimespan.GetHours(), EndTimespan.GetMinutes(), EndTimespan.GetSeconds());
FString InputFile = TempClipData.ResourcePropertyDataPtr->MoviePath;
// 给定一个路径,创建所有不存在的文件夹
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(ExportPath / FString::FromInt(i)));
FString OutputFile = FPaths::ConvertRelativePathToFull(ExportPath / FString::FromInt(i) + TEXT(".mp4"));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, OutputFile);
FString OutputFile = FPaths::ConvertRelativePathToFull(ExportPath + FString::FromInt(i) + TEXT(".mp4"));
int32 StartFrame = (TempClipData.VideoStartFrame) % static_cast<int>(FGlobalData::GlobalFPS);;
int32 EndFrame = (TempClipData.VideoEndFrame) % static_cast<int>(FGlobalData::GlobalFPS);
@ -117,9 +127,15 @@ void FUtils::TrackEncodeVideo(const FTrackData& TrackData, const FString& Export
FPlatformProcess::CreateProc(*GetFfmepg(), *Command, true, false, false, nullptr, 0, nullptr, nullptr);
EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.VideoStartFrame);
EncodeVideoInfo.EncodedVideoName = ExportPath + FString::FromInt(i) + TEXT(".mp4");
EncodeVideoInfos.Add(EncodeVideoInfo);
}
i++;
}
return EncodeVideoInfos;
@ -144,6 +160,276 @@ FString FUtils::GetFfmepg()
return FPaths::ConvertRelativePathToFull(FPaths::ProjectDir() / TEXT("Binaries") / TEXT("Win64") / TEXT("ffmpeg.exe"));
}
TArray<FEncodeVideoInfo> FUtils::ExportPsaf(FTrackData TrackData, const FString& ExportPath)
{
using namespace cv;
TArray<FClipData> ClipData = TrackData.ClipData;
ClipData.Sort([](const FClipData& A, const FClipData& B) {return A.ClipStartFrame < B.ClipStartFrame; });
TArray<FEncodeVideoInfo> EncodeVideoInfos;
int32 i = 0;
for (FClipData& TempClipData : ClipData)
{
FString ExportName = FGuid::NewGuid().ToString();;
if (TempClipData.ResourcePropertyDataPtr)
{
TempClipData.ResourcePropertyDataPtr->MoviePath;
FString TempPath = TempClipData.ResourcePropertyDataPtr->MoviePath;
frames.Empty();
VideoCapture capture;
bool ret = capture.open(TCHAR_TO_UTF8(*TempPath));
UE_LOG(LogTemp, Log, TEXT("cv numThreads -> %s"), *FString::FromInt(getNumThreads()));
//setNumThreads(2);
std::ofstream outfile;
FString leftStr;
FString rightStr;
FString SourceLeft;
FString SourceRight;
UKismetStringLibrary::Split(TempPath,".",SourceLeft, SourceRight, ESearchCase::IgnoreCase,ESearchDir::FromEnd);
UKismetStringLibrary::Split(SourceLeft,"/",SourceLeft, SourceRight, ESearchCase::IgnoreCase,ESearchDir::FromEnd);
FString psafPath = ExportPath / ExportName + FString::FromInt(i) + ".psaf";
FString psafPath2 = leftStr + ".psaf2";
//outfile.open(TCHAR_TO_UTF8(*leftStr), ios::binary);
outfile.open(*psafPath, std::ios::binary);
UE_LOG(LogTemp, Log, TEXT("open flie -> %s "), *leftStr);
uint8 width = capture.get(CAP_PROP_FRAME_WIDTH);
uint8 height = capture.get(CAP_PROP_FRAME_HEIGHT);
Size frameSize = Size(width,height );
uint8 fps = capture.get(CAP_PROP_FPS);
float duration = capture.get(CV_CAP_PROP_FRAME_COUNT) / capture.get(CV_CAP_PROP_FPS);
Size old_size = frameSize;
int32 frameCount = capture.get(CV_CAP_PROP_FRAME_COUNT);
UE_LOG(LogTemp, Log, TEXT("frameCount: %s"), *FString::FromInt(frameCount));
char p[128] = "pasf";
outfile.write(reinterpret_cast<const char*>(p), sizeof(p));
#if 1
Mat frameOrg;
Mat frame;
int frameIndex = 0;
while (ret && frameIndex < frameCount) {
if (frameIndex % 2 == 0) {
capture.grab();
frameIndex++;
continue;
}
/* */
tempIndex = frameIndex;
if (capture.read(frameOrg)) {
if (!capture.isOpened())
{
UE_LOG(LogTemp, Log, TEXT("cant open video -> %s"), *TempPath);
i++;
continue;;
}
if (frameOrg.empty())
{
UE_LOG(LogTemp, Log, TEXT("no frame"));
i++;
continue;;
}
UE_LOG(LogTemp, Log, TEXT("frameOrg size - > (%s, %s),frameOrg type -> %s "),
*FString::FromInt(frameOrg.rows),*FString::FromInt(frameOrg.cols), *FString::FromInt(frameOrg.type()));
resize(frameOrg, frameOrg, Size(70, 42), 0, 0, INTER_LINEAR);
frameOrg.copyTo(frame);
if (frame.empty()) {
UE_LOG(LogTemp, Log, TEXT(" read none "));
return EncodeVideoInfos;
}
/* 每帧标头 */
outfile.write(reinterpret_cast<const char*>(&fps), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&blockNum), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&height), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&width), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>("00"), sizeof(float));
outfile.write(reinterpret_cast<const char*>(&duration), sizeof(float));
for (int32 row = frame.rows / 3 - 1; row >= 0; row--) {
if (row % interval == 0) {
for (int32 col = frame.cols - 1; col >= 0; col--) {
frame.at<Vec3b>(row, col) = frameOrg.at<Vec3b>(row, col);
//outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)), sizeof(uint8) * 3);
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[2]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[1]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[0]), sizeof(uint8));
//UE_LOG(LogTemp, Log, TEXT("row -> %s ,col - > %s "),
// *FString::FromInt(row), *FString::FromInt(col));
}
}
else {
for (int32 col = 0; col < frame.cols; col++) {
frame.at<Vec3b>(row, col) = frameOrg.at<Vec3b>(row, col);
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[2]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[1]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[0]), sizeof(uint8));
}
}
}
for (int32 row = frame.rows/3; row < 2 * frame.rows / 3 ; row++) {
if (row % interval == 0) {
for (int32 col = 0; col < frame.cols; col++) {
frame.at<Vec3b>(row, col) = frameOrg.at<Vec3b>(row, col);
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[2]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[1]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[0]), sizeof(uint8));
}
}
else {
for (int32 col = frame.cols - 1; col >= 0; col--) {
frame.at<Vec3b>(row, col) = frameOrg.at<Vec3b>(row, col);
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[2]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[1]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[0]), sizeof(uint8));
}
}
}
for (int32 row = 2 * frame.rows/3; row < frame.rows ; row++) {
if (row % interval == 0) {
for (int32 col = 0; col < frame.cols ; col++) {
frame.at<Vec3b>(row, col) = frameOrg.at<Vec3b>(row, col);
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[2]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[1]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[0]), sizeof(uint8));
}
}
else {
for (int32 col = frame.cols - 1; col >= 0 ; col--) {
frame.at<Vec3b>(row, col) = frameOrg.at<Vec3b>(row, col);
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[2]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[1]), sizeof(uint8));
outfile.write(reinterpret_cast<const char*>(&frame.at<Vec3b>(row, col)[0]), sizeof(uint8));
}
}
}
#if EXPORT_PROCESSED_VIDEO
writer.write(frame);
#endif
//frames.Add(MatToTexture2D(frame, width, height, true));
frameIndex++;
//UE_LOG(LogTemp, Log, TEXT(" write frame,frameSize( %s, %s )"), *FString::FromInt(frame.rows), *FString::FromInt(frame.cols));
}
else
{
frameIndex++;
}
}
#endif
outfile.seekp(0, outfile.end);
size_t fileSize = outfile.tellp();
UE_LOG(LogTemp, Log, TEXT("fileSize1 -> %s"), *FString::FromInt(fileSize));
int32 remains = 1024 - fileSize % (1024);
outfile.write(reinterpret_cast<const char*>("0x00"), sizeof(uint8)* remains);
fileSize = outfile.tellp();
UE_LOG(LogTemp, Log, TEXT("fileSize2 -> %s"), *FString::FromInt(fileSize));
capture.release();
#if EXPORT_PROCESSED_VIDEO
writer.release();
#endif
outfile.close();
UE_LOG(LogTemp, Log, TEXT("proecess completed , video close"));
}
FEncodeVideoInfo EncodeVideoInfo;
EncodeVideoInfo.EncodedVideoName = ExportName + FString::FromInt(i) + ".psaf";
EncodeVideoInfo.EncodedVideoTimeCode = FGlobalData::GetTimeData(TempClipData.ClipStartFrame);
EncodeVideoInfos.Add(EncodeVideoInfo);
i++;
}
return EncodeVideoInfos;
}
FString FUtils::GetMsFromString(FString TimeString)
{
// 将时间字符串转换为FTimespan对象
FTimespan Timespan;
TArray<FString> TimeParts;
TimeString.ParseIntoArray(TimeParts, TEXT(":"));
if (TimeParts.Num() == 3 || TimeParts.Num() == 4)
{
int32 Hours = FCString::Atoi(*TimeParts[0]);
int32 Minutes = FCString::Atoi(*TimeParts[1]);
int32 Seconds = FCString::Atoi(*TimeParts[2]);
int32 Frames = TimeParts.Num() == 4 ? FCString::Atoi(*TimeParts[3]) : 0;
// Nano -> Milli
Timespan = FTimespan(0, Hours, Minutes, Seconds, Frames * 33 * 1000000); // 假设每帧为33毫秒
}
// 将FTimespan对象转换为毫秒
int64 Milliseconds = Timespan.GetTotalMilliseconds();
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s -> %s"), *TimeString, *FString::FromInt(Milliseconds)));
return FString::FromInt(Milliseconds);
}
FSaveModifier::FSaveModifier(const FString& FullSavedPath)
{

View File

@ -22,7 +22,7 @@ public:
*/
static void CreateDefaultTimelineSave(const FString& SavedPath, const FTimelineInfo::ETimelineType Type);
static void TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath);
static TArray<FEncodeVideoInfo> TrackEncodeVideo(const FTrackData& TrackData, const FString& ExportPath);
static FString CurtainFullPath(const FString& GroupName)
{
@ -60,8 +60,21 @@ public:
static FString GetFfmepg();
static TArray<FEncodeVideoInfo> ExportPsaf(FTrackData TrackData, const FString& ExportPath);
inline static uint8 interval = 2;
inline static uint8 blockNum = 3;
inline static TArray<int32> sequence;
inline static TArray<UTexture2D*> frames;
inline static int32 currentFrameIndex = 0;
inline static int32 FPS = 30;
inline static FTimerDelegate videoDele;
inline static FTimerHandle videoHandle;
inline static FTimerDelegate updateFrameFinishedDele;
inline static int32 tempIndex = 0;
static FString GetMsFromString(FString TimeString);
};
class FSaveModifier

View File

@ -31,6 +31,7 @@ public:
inline static FString CurrentProjectName = "DefaultProject";
inline static FString BasePath = FPaths::ProjectDir();
inline static FString Version = "1.0.0";
inline static FString ExportPath = "";
inline static TArray<FColor> Colors =
{
FColor(175, 93, 81, 255),
@ -160,6 +161,24 @@ struct CUT5_API FPresetsData
return Ar;
}
};
struct CUT5_API FPresetsCustomData
{
TArray<FLinearColor> Colors;
int32 Times;
float Angle;
int32 Time;
friend FArchive& operator<<(FArchive& Ar, FPresetsCustomData& PresetsData)
{
Ar << PresetsData.Colors;
Ar << PresetsData.Times;
Ar << PresetsData.Angle;
Ar << PresetsData.Time;
return Ar;
}
};
struct CUT5_API FClipData
{
@ -705,4 +724,11 @@ struct FProperties
TArray<FGeneralPropertyBase> Properties;
};
struct FEncodeVideoInfo
{
FString EncodedVideoName = ".mp4";
FString EncodedVideoTimeCode = "00:00:00:00";
};

View File

@ -6,7 +6,10 @@
#include "SlateOptMacros.h"
#include "Cut5/Utils/Utils.h"
#include "Cut5/Widgets/Style/CutButtonWidgetStyle.h"
#include "Math/UnitConversion.h"
#include "Widgets/Input/SComboBox.h"
#include "Widgets/Input/SSpinBox.h"
#include "Widgets/Input/NumericTypeInterface.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
@ -72,22 +75,29 @@ void SEffectPreset::Construct(const FArguments& InArgs)
TSharedPtr<SWidget> SEffectPreset::GetPropertiesWidget()
{
FTextBlockStyle NormalText = FAppStyle::GetWidgetStyle<FTextBlockStyle>("NormalText");
NormalText.SetFontSize(13);
PropertiesWidget =
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.Padding(0, 13, 0, 0)
[
SNew(SBox).HeightOverride(32).WidthOverride(214)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(62)
.HeightOverride(32)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("颜色")))
.Font(NormalText.Font)
.Justification(ETextJustify::Center)
]
]
+ SHorizontalBox::Slot()
@ -98,11 +108,9 @@ TSharedPtr<SWidget> SEffectPreset::GetPropertiesWidget()
.HeightOverride(32)
[
SNew(SEditableTextBox)
.OnVerifyTextChanged_Lambda([this](const FText& InText, FText& OutErrorMessage)
{
return true;
})
.OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType)
{
@ -113,60 +121,57 @@ TSharedPtr<SWidget> SEffectPreset::GetPropertiesWidget()
]
]
+ SVerticalBox::Slot()
.Padding(0, 13, 0, 0)
[
SNew(SBox).HeightOverride(32).WidthOverride(214)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(136)
.WidthOverride(62)
.HeightOverride(32)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("动效")))
.Font(NormalText.Font)
.Justification(ETextJustify::Center)
]
]
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
[
SAssignNew(GroupComboBox, SComboBox<TSharedPtr<FString>>)
.OptionsSource(nullptr)
.OnGenerateWidget_Lambda([this](TSharedPtr<FString> InItem)
{
return SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNew(STextBlock).Text(FText::FromString(*InItem))
];
})
SNew(SBox)
.WidthOverride(136)
.HeightOverride(32)
[
SNew(STextBlock).Text_Lambda([this]()
{
return FText::FromString(TEXT(""));
})
SNew(SComboBox<TSharedPtr<FString>>)
]
.OnSelectionChanged_Lambda([this](TSharedPtr<FString> InItem, ESelectInfo::Type SelectInfo)
{
})
]
]
]
+ SVerticalBox::Slot()
.Padding(0, 13, 0, 0)
[
SNew(SBox).HeightOverride(32).WidthOverride(214)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(62)
.HeightOverride(32)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("次数")))
.Font(NormalText.Font)
.Justification(ETextJustify::Center)
]
]
+ SHorizontalBox::Slot()
@ -176,48 +181,31 @@ TSharedPtr<SWidget> SEffectPreset::GetPropertiesWidget()
.WidthOverride(136)
.HeightOverride(32)
[
SNew(SEditableTextBox)
.Text(FText::FromString(FString::FromInt(1)))
.OnVerifyTextChanged_Lambda([this](const FText& InText, FText& OutErrorMessage)
{
if (InText.IsEmpty())
{
OutErrorMessage = FText::FromString(TEXT("ID不能为空"));
return false;
}
// ID必须是数字
for (TCHAR Char : InText.ToString())
{
if (!FChar::IsDigit(Char))
{
OutErrorMessage = FText::FromString(TEXT("ID必须是数字"));
return false;
}
}
return true;
})
.OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType)
{
})
SNew(SSpinBox<int32>)
.MinValue(0)
]
]
]
]
+ SVerticalBox::Slot()
.Padding(0, 13, 0, 0)
[
SNew(SBox).HeightOverride(32).WidthOverride(214)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(62)
.HeightOverride(32)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("角度")))
.Font(NormalText.Font)
.Justification(ETextJustify::Center)
]
]
+ SHorizontalBox::Slot()
@ -227,48 +215,33 @@ TSharedPtr<SWidget> SEffectPreset::GetPropertiesWidget()
.WidthOverride(136)
.HeightOverride(32)
[
SNew(SEditableTextBox)
.Text(FText::FromString(FString::FromInt(1)))
.OnVerifyTextChanged_Lambda([this](const FText& InText, FText& OutErrorMessage)
{
if (InText.IsEmpty())
{
OutErrorMessage = FText::FromString(TEXT("ID不能为空"));
return false;
}
// ID必须是数字
for (TCHAR Char : InText.ToString())
{
if (!FChar::IsDigit(Char))
{
OutErrorMessage = FText::FromString(TEXT("ID必须是数字"));
return false;
}
}
return true;
})
.OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType)
{
})
SNew(SSpinBox<float>)
.MinValue(0.0)
.MaxValue(360.0)
// .TypeInterface(MakeShared<TNumericUnitTypeInterface<float>>(EUnit::Degrees))
]
]
]
]
+ SVerticalBox::Slot()
.Padding(0, 13, 0, 0)
[
SNew(SBox).HeightOverride(32).WidthOverride(214)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.SizeParam(FAuto())
.VAlign(VAlign_Center)
[
SNew(SBox)
.WidthOverride(62)
.HeightOverride(32)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("时间")))
.Font(NormalText.Font)
.Justification(ETextJustify::Center)
]
]
+ SHorizontalBox::Slot()
@ -278,34 +251,14 @@ TSharedPtr<SWidget> SEffectPreset::GetPropertiesWidget()
.WidthOverride(136)
.HeightOverride(32)
[
SNew(SEditableTextBox)
.Text(FText::FromString(FString::FromInt(1)))
.OnVerifyTextChanged_Lambda([this](const FText& InText, FText& OutErrorMessage)
{
if (InText.IsEmpty())
{
OutErrorMessage = FText::FromString(TEXT("ID不能为空"));
return false;
}
// ID必须是数字
for (TCHAR Char : InText.ToString())
{
if (!FChar::IsDigit(Char))
{
OutErrorMessage = FText::FromString(TEXT("ID必须是数字"));
return false;
}
}
return true;
})
.OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType)
{
})
SNew(SSpinBox<int32>)
.MinValue(0.0)
// .TypeInterface(MakeShared<TNumericUnitTypeInterface<int32>>(EUnit::Seconds))
]
]
]
];
return PropertiesWidget;
}

View File

@ -288,7 +288,7 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
{
FTimelinePropertyData Data;
FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data);
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("GUID %s"), *Data.Guid.ToString()));
TSharedPtr<SCustomInputResource> Resource = SNew(SCustomInputResource)
.PropertyData(Data).OnCheckBoxChecked_Lambda([this](FTimelinePropertyData& ClickedData, bool bIsChecked)
{
@ -306,7 +306,7 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
break;
}
}
GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, FString::Printf(TEXT("Num %d"), SelectedProperties.Num()));
}
});
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2)

View File

@ -14,7 +14,7 @@ void SCustomInputResource::Construct(const FArguments& InArgs)
PropertyData = InArgs._PropertyData;
VideoCapture = InArgs._VideoCapture;
OnCheckBoxChecked = InArgs._OnCheckBoxChecked;
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Orange, FString::Printf(TEXT("GUID %s"), *PropertyData.Guid.ToString()));
ChildSlot
[
SNew(SBox)

View File

@ -539,7 +539,7 @@ void SCutMainWindow::AddNewCard(FEffectCardProperty& CardProperty, FString Group
EffectCardsPanel->AddNewCard(CardProperty, GroupName);
}
void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefore)
void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefore, bool ForceOpen)
{
if (NeedSaveBefore)
{
@ -556,8 +556,12 @@ void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefo
CutTimeline->SaveTimeline(CutTimeline->TimelineInfo.CurrentOpenFullPath, CutTimeline->TimelineInfo);
else
{
CutTimeline->SaveTimeline(FUtils::MainSaveFullPath(), CutTimeline->TimelineInfo);
CutTimeline->TimelineInfo.CurrentOpenFullPath = FUtils::MainSaveFullPath();
if (!ForceOpen)
{
CutTimeline->SaveTimeline(FUtils::MainSaveFullPath(), CutTimeline->TimelineInfo);
CutTimeline->TimelineInfo.CurrentOpenFullPath = FUtils::MainSaveFullPath();
}
}
}
}
@ -659,29 +663,27 @@ void SCutMainWindow::OpenProject(const FString& Project)
void SCutMainWindow::ExportProject(const FString& ExportPath)
{
// 先读取所有保存下来的轨道
for (FTrackGroup& TrackGroup : CutTimeline->TrackGroups)
{
for (FTrackData& TrackData : TrackGroup.TrackDataArray)
{
// FUtils::TrackEncodeVideo(TrackData, FPaths::Combine(ExportPath, TEXT("Video")));
}
}
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
{
FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, FPaths::Combine(ExportPath, TEXT("Video")));
}
if (ExportPath.IsEmpty())
return;
FGlobalData::ExportPath = ExportPath / FGlobalData::CurrentProjectName;
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*FGlobalData::ExportPath);
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(FGlobalData::ExportPath / "video"));
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(FGlobalData::ExportPath / "audio"));
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(FGlobalData::ExportPath / "psaf"));
tinyxml2::XMLDocument Document;
tinyxml2::XMLElement* RootElement = Document.NewElement(TCHAR_TO_UTF8(*FString::Printf(TEXT("Project(%s)"), *FGlobalData::CurrentProjectName)));
tinyxml2::XMLElement* RootElement = Document.NewElement(TCHAR_TO_UTF8(*FString::Printf(TEXT("%s"), *FGlobalData::CurrentProjectName)));
Document.InsertFirstChild(RootElement);
tinyxml2::XMLElement* Standard = RootElement->InsertNewChildElement("Standard");
tinyxml2::XMLElement* File = Standard->InsertNewChildElement("File");
File->InsertNewChildElement("Author")->InsertNewText("Sch");
File->InsertNewChildElement("Date")->InsertNewText("2020-12-12");
File->InsertNewChildElement("Describe")->InsertNewText("1.0");
File->InsertNewChildElement("FileVersion")->InsertNewText("1.0");
File->InsertNewChildElement("SoftWareVersion")->InsertNewText(TCHAR_TO_UTF8(*FGlobalData::Version));
// Device List
tinyxml2::XMLElement* DeviceList = RootElement->InsertNewChildElement("DeviceList");
{
@ -691,7 +693,11 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
tinyxml2::XMLElement* RoundSpeakerList = DeviceList->InsertNewChildElement("RotationSpeakerList");
tinyxml2::XMLElement* ProjectorList = DeviceList->InsertNewChildElement("ProjectorList");
int32 ID = 0;
int32 PlayerTrackID = 0;
int32 DMLightID = 0;
int32 GuangZhenID = 0;
int32 RoundSpeakerID = 0;
int32 ProjectorID = 0;
for (int32 i = 0; i < CutTimeline->TrackGroups.Num(); i++)
{
for (FTrackData& TrackData : CutTimeline->TrackGroups[i].TrackDataArray)
@ -701,42 +707,48 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
case ETrackType::PlayerTrack:
{
tinyxml2::XMLElement* PlayerLight = PlayerLightList->InsertNewChildElement("PlayerLight");
PlayerLight->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ID)));
PlayerLight->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(PlayerTrackID)));
PlayerLight->InsertNewChildElement("RoleName")->InsertNewText(TCHAR_TO_UTF8(*TrackData.TrackName));
ID++;
PlayerTrackID++;
}
break;
case ETrackType::AudioTrackR:
{
tinyxml2::XMLElement* RotationSpeaker = RoundSpeakerList->InsertNewChildElement("RotationSpeaker");
RotationSpeaker->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ID)));
RotationSpeaker->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(RoundSpeakerID)));
RotationSpeaker->InsertNewChildElement("RoleName")->InsertNewText(TCHAR_TO_UTF8(*TrackData.TrackName));
ID++;
RoundSpeakerID++;
}
break;
case ETrackType::LightArrayTrack:
{
tinyxml2::XMLElement* LightArray = LightArrayList->InsertNewChildElement("GuangZhen");
LightArray->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ID)));
LightArray->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(GuangZhenID)));
LightArray->InsertNewChildElement("RoleName")->InsertNewText(TCHAR_TO_UTF8(*TrackData.TrackName));
ID++;
GuangZhenID++;
}
break;
case ETrackType::ProjectorTrack:
{
tinyxml2::XMLElement* Projector = ProjectorList->InsertNewChildElement("Projector");
Projector->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ID)));
Projector->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ProjectorID)));
Projector->InsertNewChildElement("RoleName")->InsertNewText(TCHAR_TO_UTF8(*TrackData.TrackName));
ID++;
ProjectorID++;
}
break;
case ETrackType::SpotLightTrack:
{
tinyxml2::XMLElement* DMLight = DMLightList->InsertNewChildElement("DMLight");
DMLight->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DMLightID)));
DMLight->InsertNewChildElement("RoleName")->InsertNewText(TCHAR_TO_UTF8(*TrackData.TrackName));
DMLightID++;
}
}
}
}
// Card List
ID = 0;
tinyxml2::XMLElement* CardList = RootElement->InsertNewChildElement("CardList");
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i ++)
{
@ -746,10 +758,10 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
{
tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card");
Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
Card->InsertNewChildElement("Type")->InsertNewText(EffectCardsPanel->EffectCardGroups[0].bIsDedicated ? "0" : "2");
Card->InsertNewChildElement("Type")->InsertNewText(EffectCardsPanel->EffectCardGroups[i].bIsDedicated ? "0" : "2");
Card->InsertNewChildElement("Times");
Card->InsertNewChildElement("Step");
Card->InsertNewChildElement("SpecialEffectID");
Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
Card->InsertNewChildElement("SerialNumberList");
}
@ -761,7 +773,7 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
Card->InsertNewChildElement("Type")->InsertNewText(EffectCardsPanel->EffectCardGroups[0].bIsDedicated ? "0" : "2");
Card->InsertNewChildElement("Times");
Card->InsertNewChildElement("Step");
Card->InsertNewChildElement("SpecialEffectID");
Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID)));
Card->InsertNewChildElement("SerialNumberList");
}
@ -770,78 +782,18 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
// KeyBoard
tinyxml2::XMLElement* Keyboard = RootElement->InsertNewChildElement("KeyBoard");
}
// ProcessList
for (int32 i = 0; i < CurtainPanel->Groups.Num(); i++)
{
tinyxml2::XMLElement* ProcessList = RootElement->InsertNewChildElement("ProcessList");
tinyxml2::XMLElement* ProcessA = ProcessList->InsertNewChildElement("ProcessA");
tinyxml2::XMLElement* ProcessB = ProcessA->InsertNewChildElement("ProcessB");
{
tinyxml2::XMLElement* ProcessID = ProcessB->InsertNewChildElement("ID");
tinyxml2::XMLElement* AutoNext = ProcessB->InsertNewChildElement("AutoNext");
tinyxml2::XMLElement* TimeLength = ProcessB->InsertNewChildElement("TimeLength");
tinyxml2::XMLElement* SoundList = ProcessB->InsertNewChildElement("SoundList");
{
GetSoundElement(SoundList);
}
ProcessB->InsertEndChild(GetDeviceElement(ProcessB));
tinyxml2::XMLElement* VideoList = ProcessB->InsertNewChildElement("VideoList");
{
// for video
GetVideoElement(VideoList);
}
// 非必须项
tinyxml2::XMLElement* Identity_SpecialEffects = ProcessB->InsertNewChildElement("Identity_SpecialEffects");
{
}
tinyxml2::XMLElement* IsGlobal = ProcessB->InsertNewChildElement("IsGlobal");
{
}
tinyxml2::XMLElement* State = ProcessB->InsertNewChildElement("State");
{
}
}
GetProcessA(RootElement, &CurtainPanel->Groups[i]);
}
GetSpecialEffectList(RootElement);
// Effect Lists
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i++)
{
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
{
}
}
tinyxml2::XMLElement* SpecialEffect = RootElement->InsertNewChildElement("SpecialEffect");
{
tinyxml2::XMLElement* Test = SpecialEffect->InsertNewChildElement("Test");
{
Test->InsertNewChildElement("ID");
Test->InsertNewChildElement("AutoNext");
Test->InsertNewChildElement("TimeLength");
GetSoundElement(Test);
GetDeviceElement(Test);
GetVideoElement(Test);
Test->InsertNewChildElement("IsGlobal");
Test->InsertNewChildElement("State");
}
}
FString XMLExportPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(ExportPath, FGlobalData::CurrentProjectName, FGlobalData::CurrentProjectName + TEXT(".xml")));
TArray<uint8> Data;
FFileHelper::SaveArrayToFile(Data, *XMLExportPath);
// FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*XMLExportPath);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, XMLExportPath);
Document.SaveFile(TCHAR_TO_UTF8(*XMLExportPath));
}
@ -1044,7 +996,36 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par
}
tinyxml2::XMLElement* GuangZhenList = Light->InsertNewChildElement("GuangZhenList");
{
auto GuangZhenSpecialEffectList = GuangZhenList->InsertNewChildElement("SpecialEffectList");
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
{
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::LightArrayTrack)
{
TArray<FEncodeVideoInfo> EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, *(FGlobalData::ExportPath / "psaf"));
for (int32 j = 0; j < EncodeVideoInfos.Num(); j++)
{
auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpeicalEffect");
{
auto SpeicalEffectTimeCode = SpeicalEffect->InsertNewChildElement("TimeCode");
{
SpeicalEffectTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfos[j].EncodedVideoTimeCode)));
}
auto SpeicalEffectURL = SpeicalEffect->InsertNewChildElement("URL");
{
SpeicalEffectURL->InsertNewText(TCHAR_TO_UTF8(*EncodeVideoInfos[j].EncodedVideoName));
}
auto SpeicalEffectLoop = SpeicalEffect->InsertNewChildElement("Loop");
{
SpeicalEffectLoop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
}
auto SpeicalEffectMode = SpeicalEffect->InsertNewChildElement("Mode");
{
SpeicalEffectMode->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
}
}
}
}
}
}
tinyxml2::XMLElement* RoomLight = Light->InsertNewChildElement("RoomLight");
{
@ -1063,22 +1044,68 @@ tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Par
return Device;
}
tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Parent)
tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo)
{
int32 TempProjectorID = 0;
tinyxml2::XMLElement* Video = Parent->InsertNewChildElement("Video");
tinyxml2::XMLElement* URL = Video->InsertNewChildElement("URL");
{
URL->InsertNewText(TCHAR_TO_UTF8(*(FPaths::GetBaseFilename(EncodeVideoInfo.EncodedVideoName) + TEXT(".mp4"))));
}
tinyxml2::XMLElement* Timecode = Video->InsertNewChildElement("Timecode");
{
Timecode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfo.EncodedVideoTimeCode)));
}
tinyxml2::XMLElement* Loop = Video->InsertNewChildElement("Loop");
{
Loop->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
}
tinyxml2::XMLElement* Mode = Video->InsertNewChildElement("Mode");
{
Mode->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
}
tinyxml2::XMLElement* ProjectorID = Video->InsertNewChildElement("ProjectorID");
{
ProjectorID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TempProjectorID)));
}
tinyxml2::XMLElement* ProjectorEventList = Video->InsertNewChildElement("ProjectorEventList");
{
tinyxml2::XMLElement* ProjectorEvent = ProjectorEventList->InsertNewChildElement("ProjectorEvent");
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
{
tinyxml2::XMLElement* TimeCode = ProjectorEvent->InsertNewChildElement("TimeCode");
tinyxml2::XMLElement* Value = ProjectorEvent->InsertNewChildElement("Value");
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::ProjectorTrack)
{
for (FClipData& ClipData : StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.ClipData)
{
tinyxml2::XMLElement* ProjectorEvent = ProjectorEventList->InsertNewChildElement("ProjectorEvent");
{
tinyxml2::XMLElement* ProjectorTimeCode = ProjectorEvent->InsertNewChildElement("TimeCode");
{
ProjectorTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame))));
}
tinyxml2::XMLElement* Value = ProjectorEvent->InsertNewChildElement("Value");
{
Value->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
}
}
tinyxml2::XMLElement* ProjectorEvent2 = ProjectorEventList->InsertNewChildElement("ProjectorEvent");
{
tinyxml2::XMLElement* ProjectorTimeCode = ProjectorEvent2->InsertNewChildElement("TimeCode");
{
ProjectorTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipEndFrame))));
}
tinyxml2::XMLElement* Value = ProjectorEvent2->InsertNewChildElement("Value");
{
Value->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(1)));
}
}
}
}
}
}
return Parent;
}
@ -1103,5 +1130,155 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Pare
return Parent;
}
tinyxml2::XMLElement* SCutMainWindow::GetVideoListElement(tinyxml2::XMLElement* Parent)
{
tinyxml2::XMLElement* VideoList = Parent->InsertNewChildElement("VideoList");
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
{
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::VideoTrack)
{
FString Filename = FGuid::NewGuid().ToString();
FString NewExportFilePath = FGlobalData::ExportPath / "Video" / Filename;
TArray<FEncodeVideoInfo> EncodeVideoInfos = FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath);
for (FEncodeVideoInfo EncodeVideoInfo : EncodeVideoInfos)
{
GetVideoElement(VideoList, EncodeVideoInfo);
}
}
}
return VideoList;
}
tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* Parent)
{
return nullptr;
}
tinyxml2::XMLElement* SCutMainWindow::GetProcessA(tinyxml2::XMLElement* Parent, FCurtainGroup* CurtainGroup)
{
tinyxml2::XMLElement* ProcessA = Parent->InsertNewChildElement(TCHAR_TO_UTF8(*CurtainGroup->GroupName));
for (int32 i = 0; i < CurtainGroup->Curtains.Num(); i++)
{
GetProcessB(ProcessA, &CurtainGroup->Curtains[i]);
}
return ProcessA;
}
tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, FCurtain* Curtain)
{
tinyxml2::XMLElement* ProcessB = Parent->InsertNewChildElement(TCHAR_TO_UTF8(*Curtain->CurtainName));
tinyxml2::XMLElement* ProcessID = ProcessB->InsertNewChildElement("ID");
tinyxml2::XMLElement* AutoNext = ProcessB->InsertNewChildElement("AutoNext");
tinyxml2::XMLElement* TimeLength = ProcessB->InsertNewChildElement("TimeLength");
tinyxml2::XMLElement* SoundList = ProcessB->InsertNewChildElement("SoundList");
{
GetSoundElement(SoundList);
}
ProcessB->InsertEndChild(GetDeviceElement(ProcessB));
GetVideoListElement(ProcessB);
// 非必须项
tinyxml2::XMLElement* Identity_SpecialEffects = ProcessB->InsertNewChildElement("Identity_SpecialEffects");
{
}
tinyxml2::XMLElement* IsGlobal = ProcessB->InsertNewChildElement("IsGlobal");
{
}
tinyxml2::XMLElement* State = ProcessB->InsertNewChildElement("State");
{
}
return ProcessB;
}
tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectList(tinyxml2::XMLElement* Parent)
{
tinyxml2::XMLElement* SpecialEffectsList = Parent->InsertNewChildElement("SpecialEffectsList");
int32 SpecialEffectID = 0;
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i++)
{
if (!EffectCardsPanel->EffectCardGroups[i].bIsDedicated)
{
if (EffectCardsPanel->EffectCardGroups[i].bIsDedicated == false)
{
const FString Name = FPaths::Combine(FGlobalData::BasePath, FGlobalData::CurrentProjectName, TEXT("FX"), EffectCardsPanel->EffectCardGroups[i].GroupName + TEXT(".bin"));
OpenTimeline(Name, true, true);
CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Guid;
// OnSelectCard(EffectCardsPanel->EffectCardGroups[i].Guid);
}
GetSpecialEffectGroup(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i]);
SpecialEffectID++;
continue;
}
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
{
OpenTimeline(FUtils::SingleCardFullPath(EffectCardsPanel->EffectCardGroups[i].Cards[j].Name), true, true);
CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid;
// OnSelectCard(EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid);
GetSpecialEffect(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i].Cards[j]);
SpecialEffectID++;
}
SpecialEffectID++;
}
return SpecialEffectsList;
}
tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectGroup(tinyxml2::XMLElement* Parent, FEffectCardGroup* Group)
{
tinyxml2::XMLElement* SpecialEffect = Parent->InsertNewChildElement(TCHAR_TO_UTF8(*Group->GroupName));
tinyxml2::XMLElement* ID = SpecialEffect->InsertNewChildElement("ID");
{
ID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Group->ID)));
}
tinyxml2::XMLElement* AutoNext = SpecialEffect->InsertNewChildElement("AutoNext");
GetSoundElement(SpecialEffect);
GetDeviceElement(SpecialEffect);
GetVideoListElement(SpecialEffect);
tinyxml2::XMLElement* IsGlobal = SpecialEffect->InsertNewChildElement("IsGlobal");
{
int32 bIsGlobal = 0;
Group->UsedCurtains.Contains(TEXT("全局")) ? bIsGlobal = 1 : bIsGlobal = 0;
IsGlobal->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(bIsGlobal)));
}
tinyxml2::XMLElement* State = SpecialEffect->InsertNewChildElement("State");
{
}
return SpecialEffect;
}
tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffect(tinyxml2::XMLElement* Parent, FEffectCardProperty* Effect)
{
tinyxml2::XMLElement* SpecialEffect = Parent->InsertNewChildElement(TCHAR_TO_UTF8(*Effect->Name));
tinyxml2::XMLElement* ID = SpecialEffect->InsertNewChildElement("ID");
{
ID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Effect->ID)));
}
tinyxml2::XMLElement* AutoNext = SpecialEffect->InsertNewChildElement("AutoNext");
GetSoundElement(SpecialEffect);
GetDeviceElement(SpecialEffect);
GetVideoListElement(SpecialEffect);
tinyxml2::XMLElement* IsGlobal = SpecialEffect->InsertNewChildElement("IsGlobal");
{
int32 bIsGlobal = 0;
Effect->UsedCurtains.Contains(TEXT("全局")) ? bIsGlobal = 1 : bIsGlobal = 0;
IsGlobal->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(bIsGlobal)));
}
tinyxml2::XMLElement* State = SpecialEffect->InsertNewChildElement("State");
{
}
return SpecialEffect;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -61,7 +61,7 @@ public:
virtual void SelectClip(const FGuid& Guid) override;
// 不好 到时候改成 Group Widget 内部操作
virtual void AddNewCard(FEffectCardProperty& CardProperty, FString GroupName) override;
virtual void OpenTimeline(const FString& TimelineName, bool NeedSaveBefore) override;
virtual void OpenTimeline(const FString& TimelineName, bool NeedSaveBefore, bool ForceOpen = false) override;
virtual void OpenProject(const FString& Project) override;
virtual void ExportProject(const FString& ExportPath) override;
virtual void ImportProject(const FString& ImportPath) override;
@ -78,7 +78,15 @@ public:
virtual SCutTimeline* GetCutTimeline() override { return CutTimeline.Get(); };
virtual void PreSettingBeforeSeek() override;
static tinyxml2::XMLElement* GetDeviceElement(tinyxml2::XMLElement* Parent);
static tinyxml2::XMLElement* GetVideoElement(tinyxml2::XMLElement* Parent);
static tinyxml2::XMLElement* GetSoundElement(tinyxml2::XMLElement* Parent);
tinyxml2::XMLElement* GetDeviceElement(tinyxml2::XMLElement* Parent);
tinyxml2::XMLElement* GetVideoElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo);
tinyxml2::XMLElement* GetSoundElement(tinyxml2::XMLElement* Parent);
tinyxml2::XMLElement* GetVideoListElement(tinyxml2::XMLElement* Parent);
tinyxml2::XMLElement* GetSoundListElement(tinyxml2::XMLElement* Parent);
tinyxml2::XMLElement* GetProcessA(tinyxml2::XMLElement* Parent, FCurtainGroup* CurtainGroup);
tinyxml2::XMLElement* GetProcessB(tinyxml2::XMLElement* Parent, FCurtain* Curtain);
tinyxml2::XMLElement* GetSpecialEffectList(tinyxml2::XMLElement* Parent);
tinyxml2::XMLElement* GetSpecialEffectGroup(tinyxml2::XMLElement* Parent, FEffectCardGroup* Group);
tinyxml2::XMLElement* GetSpecialEffect(tinyxml2::XMLElement* Parent, FEffectCardProperty* Effect);
};

View File

@ -53,14 +53,31 @@ int32 STimelineTick::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe
for (int32 j = 0; j < TickCount; j++)
{
const FSlateBrush Brush;
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(2, TickBox->GetCachedGeometry().GetLocalSize().Y), FSlateLayoutTransform(FVector2f(TickBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2f(0.0, 0.0)).X + j * FGlobalData::DefaultTimeTickSpace, 0.0))),
&Brush,
ESlateDrawEffect::None,
FColor(255, 255, 255, 255));
if (j % 2 == 0)
{
const FSlateBrush Brush;
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(2, TickBox->GetCachedGeometry().GetLocalSize().Y - 2), FSlateLayoutTransform(FVector2f(TickBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2f(0.0, 0.0)).X + j * FGlobalData::DefaultTimeTickSpace, 0.0))),
&Brush,
ESlateDrawEffect::None,
FColor(55, 55, 55, 255));
}
if (j % 10 == 0)
{
const FSlateBrush Brush;
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId,
AllottedGeometry.ToPaintGeometry(FVector2f(2, TickBox->GetCachedGeometry().GetLocalSize().Y + 2), FSlateLayoutTransform(FVector2f(TickBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2f(0.0, 0.0)).X + j * FGlobalData::DefaultTimeTickSpace, 0.0))),
&Brush,
ESlateDrawEffect::None,
FColor(95, 95, 95, 255));
}
}