视频和psaf的导出
This commit is contained in:
parent
88b1288d3c
commit
79887a5dab
@ -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) {};
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user