正常特效数据保存切换

This commit is contained in:
Sch 2023-08-01 08:02:29 +08:00
parent 5fabd46016
commit f859840d7b
25 changed files with 500 additions and 58 deletions

Binary file not shown.

View File

@ -0,0 +1,64 @@
<Project(DefaultProject)>
<Standard>
<File>
<Author>Sch</Author>
</File>
</Standard>
<DeviceList>
<PlayerLightList/>
<DMLightList/>
<GuangZhenList>
<GuangZhen>
<ID>2</ID>
<RoleName>光阵</RoleName>
</GuangZhen>
</GuangZhenList>
<RotationSpeakerList>
<RotationSpeaker>
<ID>0</ID>
<RoleName>音频R</RoleName>
</RotationSpeaker>
</RotationSpeakerList>
<ProjectorList>
<Projector>
<ID>1</ID>
<RoleName>投影仪</RoleName>
</Projector>
</ProjectorList>
</DeviceList>
<CardList>
<Card>
<ID>0</ID>
<Type>0</Type>
<Times/>
<Step/>
<SpecialEffectID/>
<SerialNumberList/>
</Card>
</CardList>
<KeyBoard/>
<ProcessList>
<ProcessA>
<ProcessB>
<ID/>
<AutoNext/>
<TimeLength/>
<SoundList>
<Sound>
<URL/>
<Loop/>
<Mode/>
<Round/>
<Timecode/>
<VolumeEventList>
<VolumeEvent>
<TimeCode/>
<Value/>
</VolumeEvent>
</VolumeEventList>
</Sound>
</SoundList>
</ProcessB>
</ProcessA>
</ProcessList>
</Project(DefaultProject)>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

View File

@ -36,6 +36,10 @@ public:
virtual void OpenTimeline(const FString& TimelineName, bool NeedSaveBefore = false) {};
virtual void OpenProject(const FString& Project) {};
virtual void ExportProject(const FString& ExportPath) {};
virtual void ImportProject(const FString& ImportPath) {};
virtual FString GetGroupName(TSharedPtr<class IWidgetInterface> WidgetInterface) { return FString(); };
virtual FTimelinePropertyData* GetResourcePropertyDataPtr(FGuid GUID) { return nullptr; };
virtual void OnSelectCard(const FGuid& SelectedCard) {};
};

View File

@ -1,5 +1,8 @@
#include "FFMPEGUtils.h"
#include "ImageUtils.h"
#include "Utils.h"
FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* PropertyData)
{
@ -8,6 +11,11 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
{
check(false)
}
if (avformat_find_stream_info(FormatContext, nullptr) < 0)
{
check(false)
}
PropertyData->MovieFrameLength = FormatContext->duration / AV_TIME_BASE * 30;
int32 VideoStream = -1;
int32 AudioStream = -1;
for (unsigned int i = 0; i < FormatContext->nb_streams; i++) {
@ -33,6 +41,57 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
}
PropertyData->VideoCodec = VideoCodec;
PropertyData->VideoCodecContext = VideoCodecContext;
AVPacket* Packet = av_packet_alloc();
AVFrame* Frame = av_frame_alloc();
while (av_read_frame(FormatContext, Packet) >= 0)
{
if (avcodec_send_packet(VideoCodecContext, Packet) < 0)
{
}
if (avcodec_receive_frame(VideoCodecContext, Frame) >= 0)
{
break;
}
};
if (Frame)
{
struct SwsContext* swsCtx = sws_getContext(
Frame->width, Frame->height, VideoCodecContext->pix_fmt,
Frame->width, Frame->height, AV_PIX_FMT_RGBA,
SWS_BILINEAR, NULL, NULL, NULL
);
if (!swsCtx)
{
UE_LOG(LogTemp, Error, TEXT("Error creating swsContext"));
}
uint8* RawData = new uint8[Frame->width * Frame->height * 4];
uint8* dest[4] = {RawData, 0, 0, 0};
int32 dest_linesize[4] = {Frame->width * 4, 0, 0, 0};
sws_scale(swsCtx, Frame->data, Frame->linesize, 0, Frame->height, dest, dest_linesize);
sws_freeContext(swsCtx);
UTexture2D* Texture = UTexture2D::CreateTransient(Frame->width, Frame->height, PF_B8G8R8A8);
if (Texture)
{
void* MipData = Texture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(MipData, RawData, Frame->width * Frame->height * 4);
Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
Texture->UpdateResource();
FGuid Guid = FGuid::NewGuid();
ExportImage(Texture, *FPaths::Combine(FPaths::ProjectSavedDir(), FGlobalData::CurrentProjectName, "Resources", "Thumbnail", Guid.ToString() + ".png"));
PropertyData->IconPath = FPaths::Combine(FPaths::ProjectSavedDir(), FGlobalData::CurrentProjectName, "Resources", "Thumbnail", Guid.ToString() + ".png");
delete RawData;
}
}
av_seek_frame(FormatContext, VideoStream, 0, AVSEEK_FLAG_BACKWARD);
}
@ -47,6 +106,32 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
{
check(false)
}
TArray<uint8> DataResult;
AVPacket Packet = *av_packet_alloc();
AVFrame* Frame = av_frame_alloc();
while (1)
{
if (av_read_frame(FormatContext, &Packet) < 0)
{
if (av_read_frame(FormatContext, &Packet) < 0)
{
break;
}
}
avcodec_send_packet(AudioCodecContext, &Packet);
if (avcodec_receive_frame(AudioCodecContext, Frame) >= 0)
{
const uint8* Result = FUtils::ConvertTwoChannelSound2PortAudioSound(Frame->data[0], Frame->data[1], Frame->nb_samples);
if (Result != nullptr)
{
DataResult.Append(Result, Frame->nb_samples * 4 * 2);
// Pa_WriteStream(Stream, Result, Frame->nb_samples);
}
delete[] Result;
}
}
PropertyData->AudioData = DataResult;
PropertyData->AudioCodecContext = AudioCodecContext;
PropertyData->AudioCodec = AudioCodec;
}
@ -70,7 +155,7 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop
PropertyData->Name = FPaths::GetBaseFilename(Path);
PropertyData->MoviePath = Path;
PropertyData->MovieFrameLength = FormatContext->duration / AV_TIME_BASE * 30;
return {};
}
@ -93,3 +178,56 @@ FString FFFMPEGUtils::ConvertMediaGoPto1(const FString& Path)
}
return {};
}
bool FFFMPEGUtils::ExportImage(UTexture2D* Texture2D, const FString& Path)
{
// setup required parameters
TextureCompressionSettings OldCompressionSettings = Texture2D->CompressionSettings;
TextureMipGenSettings OldMipGenSettings = Texture2D->MipGenSettings;
bool OldSRGB = Texture2D->SRGB;
Texture2D->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
Texture2D->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
Texture2D->SRGB = false;
Texture2D->UpdateResource();
FTexture2DMipMap& mipmap = Texture2D->PlatformData->Mips[0];
uint8* Data = (uint8*)mipmap.BulkData.Lock(LOCK_READ_WRITE);
//FColor* FormatedImageData = static_cast<FColor*>(mipmap.BulkData.Lock(LOCK_READ_WRITE));
if (Data == nullptr)
{
mipmap.BulkData.Unlock(); // 不释放,会卡住
Texture2D->UpdateResource();
return false;
}
int width = Texture2D->PlatformData->SizeX;
int height = Texture2D->PlatformData->SizeY;
TArray<FColor> nColors;
for (int32 y = 0; y < height; y++)
{
for (int32 x = 0; x < width; x++)
{
FColor bColor;
bColor.B = Data[(y * width + x) * 4 + 0];//B 0 - 255
bColor.G = Data[(y * width + x) * 4 + 1];//G
bColor.R = Data[(y * width + x) * 4 + 2];//R
bColor.A = Data[(y * width + x) * 4 + 3];//A
nColors.Add(bColor);
}
}
mipmap.BulkData.Unlock();
// return old parameters
Texture2D->CompressionSettings = OldCompressionSettings;
Texture2D->MipGenSettings = OldMipGenSettings;
Texture2D->SRGB = OldSRGB;
Texture2D->UpdateResource();
//获取 uint8 数据,保存
TArray<uint8> ImgData;
FImageUtils::CompressImageArray(width, height, nColors, ImgData);
return FFileHelper::SaveArrayToFile(ImgData, *Path);
}

View File

@ -1,9 +1,11 @@
#pragma once
#include "ImageUtils.h"
#include "Cut5/Widgets/DefineGlobal.h"
extern "C"{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
struct FFFMPEGUtils
{
@ -13,4 +15,6 @@ struct FFFMPEGUtils
*/
static FString LoadMedia(const FString& Path, FTimelinePropertyData* PropertyData);
static FString ConvertMediaGoPto1(const FString& Path);
static bool ExportImage(UTexture2D* Texture2D, const FString& Path);
};

View File

@ -110,5 +110,10 @@ FSaveModifier::~FSaveModifier()
{
MemoryWriter << TrackData[i];
}
if (bNewSavePath)
{
FFileHelper::SaveArrayToFile(SavedData, *NewSavePath);
return;
}
FFileHelper::SaveArrayToFile(SavedData, *FullSavedPath);
}

View File

@ -47,4 +47,6 @@ public:
int32 GroupLength = 0;
TArray<FString> GroupName;
TArray<FTrackData> TrackData;
bool bNewSavePath = false;
FString NewSavePath = "";
};

View File

@ -76,8 +76,26 @@ void SCurtainPanel::Construct(const FArguments& InArgs)
MainWidgetInterface->ExportProject(String);
return FReply::Handled();
})
.Text(FText::FromString(TEXT("导出")))
]
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SNew(SBox)
.WidthOverride(100)
.HeightOverride(50)
[
SNew(SButton)
.OnClicked_Lambda([this]()
{
MainWidgetInterface->ImportProject("");
return FReply::Handled();
})
.Text(FText::FromString(TEXT("导入")))
]
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())

View File

@ -190,13 +190,26 @@ struct CUT5_API FTimelinePropertyData
int32 VideoStream = -1;
int32 AudioStream = -1;
// Movie Data
// Base Data
FString MoviePath = "";
int32 MovieFrameLength = 0;
TObjectPtr<USoundWave> Sound;
// Audio Data
TArray<uint8> AudioData;
friend FArchive& operator<<(FArchive& Ar, FTimelinePropertyData& PropertyData)
{
Ar << PropertyData.Guid;
Ar << PropertyData.Name;
Ar << PropertyData.Type;
Ar << PropertyData.IconPath;
Ar << PropertyData.MoviePath;
Ar << PropertyData.MovieFrameLength;
Ar << PropertyData.AudioData;
Ar << PropertyData.VideoStream;
Ar << PropertyData.AudioStream;
Ar << PropertyData.MoviePath;
Ar << PropertyData.MovieFrameLength;
return Ar;
}
};
class CUT5_API FCutDragDropBase : public FDecoratedDragDropOp
@ -273,7 +286,7 @@ struct CUT5_API FEffectCardProperty
FGuid Guid = FGuid::NewGuid();
FString Name = "";
FTimelineInfo TimelineInfo;
bool bIsActive = false;
friend FArchive& operator<<(FArchive& Ar, FEffectCardProperty& EffectCardProperty)
{
Ar << EffectCardProperty.Guid;
@ -290,7 +303,9 @@ struct CUT5_API FEffectCardGroup
bool bIsDedicated = false;
bool bCanEditName = false;
bool bIsExpanded = true;
bool bIsActive = false;
FGuid Guid = FGuid::NewGuid();
FTimelineInfo TimelineInfo;
friend FArchive& operator<<(FArchive& Ar, FEffectCardGroup& EffectCard)
{
Ar << EffectCard.GroupName;
@ -298,6 +313,8 @@ struct CUT5_API FEffectCardGroup
Ar << EffectCard.bIsDedicated;
Ar << EffectCard.bCanEditName;
Ar << EffectCard.bIsExpanded;
Ar << EffectCard.Guid;
Ar << EffectCard.TimelineInfo;
return Ar;
};
};

View File

@ -7,23 +7,27 @@
#include "Cut5/Utils/Utils.h"
#include "Cut5/Widgets/MicroWidgets/SClickEditableText.h"
#include "Widgets/Text/SInlineEditableTextBlock.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SEffectCard::OnNameEdited(FString New, FString Old)
{
CardProperty->Name = New;
SetSavePath({TEXT("FX"), TEXT("SingleCard"), New + TEXT(".bin")});
if (!IFileManager::Get().FileExists(*GetSavePath()))
if (!IFileManager::Get().FileExists(*FUtils::SingleCardFullPath(CardProperty->Name)))
{
TArray<uint8> BinaryData;
FFileHelper::LoadFileToArray(BinaryData, *CardProperty->TimelineInfo.CurrentOpenFullPath);
CardProperty->TimelineInfo.CurrentOpenFullPath = FUtils::SingleCardFullPath(CardProperty->Name);
FFileHelper::SaveArrayToFile(BinaryData, *CardProperty->TimelineInfo.CurrentOpenFullPath);
{
FSaveModifier SaveModifier(CardProperty->TimelineInfo.CurrentOpenFullPath);
SaveModifier.TimelineInfo.CurrentOpenFullPath = FUtils::SingleCardFullPath(CardProperty->Name);
SaveModifier.bNewSavePath = true;
SaveModifier.NewSavePath = FUtils::SingleCardFullPath(CardProperty->Name);
}
}
else
{
}
}
@ -32,7 +36,6 @@ void SEffectCard::Construct(const FArguments& InArgs)
CardProperty = InArgs._CardProperty;
GroupName = InArgs._GroupName;
MainInterface = InArgs._MainInterface;
SetSavePath({TEXT("FX"), TEXT("SingleCard"), CardProperty->Name + TEXT(".bin")});
ChildSlot
[
SNew(SBox)
@ -40,31 +43,38 @@ void SEffectCard::Construct(const FArguments& InArgs)
.HeightOverride(125.0f)
[
SNew(SOverlay)
// + SOverlay::Slot()
// [
// SNew(SButton)
// ]
+ SOverlay::Slot()
[
SNew(SButton)
]
+ SOverlay::Slot()
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
[
SNew(SImage)
.Visibility(EVisibility::HitTestInvisible)
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("EffectCard.png"), FVector2D(125.0, 125.0)))
.Image(CardProperty->bIsActive ? FUtils::GetBrushFromImage(FUtils::GetResourcesPath("EffectCard.png"), FVector2D(125.0, 125.0)) :
FUtils::GetBrushFromImage(FUtils::GetResourcesPath("EffectCardUnSelected.png"), FVector2D(125.0, 125.0)))
.OnMouseButtonDown_Lambda([this](const FGeometry&, const FPointerEvent& PointerEvent)
{
MainInterface->OpenTimeline(FUtils::SingleCardFullPath(CardProperty->TimelineInfo.CurrentOpenFullPath), true);
MainInterface->OpenTimeline(FUtils::SingleCardFullPath(CardProperty->Name), true);
MainInterface->OnSelectCard(CardProperty->Guid);
return FReply::Handled();
})
]
+ SOverlay::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
[
SNew(SClickEditableText)
.InitTextPtr(&CardProperty->Name)
.OnEdited_Raw(this, &SEffectCard::OnNameEdited)
.CanEdit(true)
.CanEdit(!CardProperty->bIsActive)
.OnSingleClick_Lambda([this]()
{
MainInterface->OpenTimeline(FUtils::SingleCardFullPath(CardProperty->Name), true);
})
]
]

View File

@ -13,6 +13,27 @@
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SEffectCardGroup::OnNameEdited(FString New, FString Old)
{
EffectCardGroup->GroupName = New;
if (!IFileManager::Get().FileExists(*FUtils::GroupFullPath(EffectCardGroup->GroupName)))
{
TArray<uint8> BinaryData;
FFileHelper::LoadFileToArray(BinaryData, *EffectCardGroup->TimelineInfo.CurrentOpenFullPath);
{
FSaveModifier SaveModifier(EffectCardGroup->TimelineInfo.CurrentOpenFullPath);
SaveModifier.TimelineInfo.CurrentOpenFullPath = FUtils::GroupFullPath(EffectCardGroup->GroupName);
SaveModifier.bNewSavePath = true;
SaveModifier.NewSavePath = FUtils::GroupFullPath(EffectCardGroup->GroupName);
}
}
else
{
}
}
void SEffectCardGroup::Construct(const FArguments& InArgs)
{
EffectCardGroup = InArgs._EffectCardGroup;
@ -38,12 +59,15 @@ void SEffectCardGroup::Construct(const FArguments& InArgs)
.InitTextPtr(&EffectCardGroup->GroupName)
.CanEdit(EffectCardGroup->bCanEditName)
.IsNeedUpright(false)
.OnEdited_Raw(this, &SEffectCardGroup::OnNameEdited)
]
.BodyContent()
[
SNew(SBorder)
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
// .ColorAndOpacity(EffectCardGroup->bIsDedicated ? FLinearColor(0.5, 0.5, 0.5, 1) :
// EffectCardGroup->bIsActive ? FLinearColor(1, 0, 0, 1) : FLinearColor(0.5, 0.5, 0.5, 1))
[
SNew(SOverlay)
+ SOverlay::Slot()

View File

@ -23,6 +23,7 @@ public:
SLATE_ARGUMENT(ICutMainWidgetInterface*, MainInterface)
SLATE_END_ARGS()
void OnNameEdited(FString New, FString Old);
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);

View File

@ -45,9 +45,7 @@ void SEffectCardsPanel::Construct(const FArguments& InArgs)
DedicatedGroup.GroupName = TEXT("独立特效卡");
EffectCardGroups.Add(DedicatedGroup);
FEffectCardProperty CardProperty;
CardProperty.Name = TEXT("鲨鱼卡");
AddNewCard(CardProperty, "");
CallRender();
}
void SEffectCardsPanel::CallRender()
@ -82,6 +80,8 @@ void SEffectCardsPanel::CallRender()
FSaveModifier SaveModifier(NewPath);
SaveModifier.TimelineInfo.CurrentOpenFullPath = NewPath;
}
Group->TimelineInfo.CurrentOpenFullPath = NewPath;
CallRender();
return FReply::Handled();
})
]
@ -193,4 +193,54 @@ FEffectCardGroup* SEffectCardsPanel::GetDedicatedGroupFromName()
return nullptr;
}
void SEffectCardsPanel::SelectCard(const FGuid& Guid)
{
if (Guid == CurrentSelectedCardGuid)
{
MainInterface->OpenTimeline(FUtils::MainSaveFullPath());
CurrentSelectedCardGuid.Invalidate();
CallRender();
}
else
{
for (FEffectCardGroup& EffectCardGroup : EffectCardGroups)
{
if (EffectCardGroup.bIsDedicated)
{
for (FEffectCardProperty& Property : EffectCardGroup.Cards)
{
Property.bIsActive = false;
}
}
else
{
EffectCardGroup.bIsActive = false;
}
}
CurrentSelectedCardGuid = Guid;
}
for (FEffectCardGroup& EffectCardGroup : EffectCardGroups)
{
if (EffectCardGroup.bIsDedicated)
{
for (FEffectCardProperty& Property : EffectCardGroup.Cards)
{
if (Guid == Property.Guid)
{
Property.bIsActive = true;
}
}
}
else
{
if (EffectCardGroup.Guid == Guid)
{
EffectCardGroup.bIsActive = true;
}
}
}
CallRender();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -83,5 +83,9 @@ public:
* @return Dedicated Group Ptr.
*/
FEffectCardGroup* GetDedicatedGroupFromName();
void SelectCard(const FGuid& Guid);
FGuid CurrentSelectedCardGuid;
};

View File

@ -154,17 +154,24 @@ void SCustomInputPanel::Construct(const FArguments& InArgs)
{
FTimelinePropertyData Data;
FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data);
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2)
[
SNew(SCustomInputResource)
.PropertyData(Data)
];
PropertyData.Add(Data);
return FReply::Handled();
}
else
{
FTimelinePropertyData Data;
FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data);
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 3, GridPanel->GetChildren()->Num() / 3)
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2)
[
SNew(SCustomInputResource)
.PropertyData(Data)
];
PropertyData.Add(Data);
}
}
return FReply::Handled();
@ -317,5 +324,50 @@ int SCustomInputPanel::AudioCallback(const void* input, void* output, unsigned l
return 0;
}
void SCustomInputPanel::SavePanel(const FString& SavePlace)
{
TArray<uint8> NewData;
FMemoryWriter Writer(NewData);
int32 PropertyDataNum = PropertyData.Num();
Writer << PropertyDataNum;
for (FTimelinePropertyData& Data : PropertyData)
{
Writer << Data;
}
FFileHelper::SaveArrayToFile(NewData, *SavePlace);
}
void SCustomInputPanel::LoadPanel(const FString& LoadPlace)
{
ClearPanel();
TArray<uint8> LoadData;
FFileHelper::LoadFileToArray(LoadData, *LoadPlace);
FMemoryReader Reader(LoadData);
int32 PropertyDataNum = 0;
Reader << PropertyDataNum;
for (int32 i = 0; i < PropertyDataNum; i++)
{
FTimelinePropertyData Data;
Reader << Data;
FTimelinePropertyData ReloadPropertyData;
FFFMPEGUtils::LoadMedia(Data.MoviePath, &ReloadPropertyData);
ReloadPropertyData.Guid = Data.Guid;
GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2)
[
SNew(SCustomInputResource)
.PropertyData(ReloadPropertyData)
];
PropertyData.Add(ReloadPropertyData);
}
}
void SCustomInputPanel::ClearPanel()
{
GridPanel->ClearChildren();
PropertyData.Empty();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

View File

@ -47,7 +47,8 @@ public:
void *userData );
TSharedPtr<SWidgetSwitcher> Switcher;
TArray<FTimelinePropertyData> PropertyData;
void SavePanel(const FString& SavePlace);
void LoadPanel(const FString& LoadPlace);
void ClearPanel();
};

View File

@ -5,6 +5,7 @@
#include "DefineGlobal.h"
#include "SlateOptMacros.h"
#include "Cut5/Utils/Utils.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
@ -15,8 +16,8 @@ void SCustomInputResource::Construct(const FArguments& InArgs)
ChildSlot
[
SNew(SBox)
.WidthOverride(100)
.HeightOverride(100)
.WidthOverride(173.5)
.HeightOverride(97.5)
[
SNew(SOverlay)
+ SOverlay::Slot()
@ -30,6 +31,7 @@ void SCustomInputResource::Construct(const FArguments& InArgs)
.VAlign(VAlign_Fill)
[
SNew(SImage)
.Image(FUtils::GetBrushFromImage(PropertyData.IconPath, {}))
]
]

View File

@ -290,6 +290,8 @@ void SCutMainWindow::OnUpdateSound(uint8* Data, int32 Size)
SoundThread->QueueAudio(Data, Size);
}
void SCutMainWindow::AddNewCard(FEffectCardProperty& CardProperty, FString GroupName)
{
EffectCardsPanel->AddNewCard(CardProperty, GroupName);
@ -320,6 +322,7 @@ void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefo
if (CutTimeline->LoadTimeline(TimelineName, TimelineInfo))
{
CutTimeline->TimelineInfo = TimelineInfo;
CutTimeline->CurrentEditDebug->SetText(FText::FromString(TEXT("当前正在编辑") + TimelineInfo.CurrentOpenFullPath));
}
}
@ -332,6 +335,17 @@ void SCutMainWindow::OpenProject(const FString& Project)
void SCutMainWindow::ExportProject(const FString& ExportPath)
{
// Save Project Link
TArray<uint8> Data {0};
FMemoryWriter MemoryWriter(Data);
FString CustomInputPanelSavePath = ExportPath + "/" + FGlobalData::CurrentProjectName + "/Dataset/" + TEXT("CustomInputPanel.bin");
MemoryWriter << CustomInputPanelSavePath;
CustomInputPanel->SavePanel(CustomInputPanelSavePath);
FFileHelper::SaveArrayToFile(Data, *(ExportPath + "/" + FGlobalData::CurrentProjectName + "/" + FGlobalData::CurrentProjectName + TEXT("_Link.cutlink")));
if (ExportPath.IsEmpty())
return;
tinyxml2::XMLDocument Document;
@ -449,14 +463,46 @@ void SCutMainWindow::ExportProject(const FString& ExportPath)
TArray<uint8> Data {0};
FFileHelper::SaveArrayToFile(Data, *(ExportPath + "/" + FGlobalData::CurrentProjectName + "/" + FGlobalData::CurrentProjectName + TEXT(".bin")));
Document.SaveFile(TCHAR_TO_UTF8(*(ExportPath + "/" + FGlobalData::CurrentProjectName + "/" + FGlobalData::CurrentProjectName + TEXT(".xml"))));
}
void SCutMainWindow::ImportProject(const FString& ImportPath)
{
FString Path = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir());
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
if (DesktopPlatform)
{
const void* ParentWindowWindowHandle = FSlateApplication::Get().FindBestParentWindowHandleForDialogs(nullptr);
FString OutFolderNames;
bool bFolderSelected = DesktopPlatform->OpenDirectoryDialog(ParentWindowWindowHandle, TEXT("选择项目文件夹"), Path, OutFolderNames);
if (bFolderSelected)
{
// 检查有没有后缀为 cutlink 的文件
TArray<FString> Files;
IFileManager::Get().FindFiles(Files, *OutFolderNames, TEXT("cutlink"));
if (Files.Num() != 0)
{
TArray<uint8> Data;
FFileHelper::LoadFileToArray(Data, *(OutFolderNames + "/" + Files[0]));
FMemoryReader Reader(Data);
FString CustomPanelInputPath = "";
Reader << CustomPanelInputPath;
CustomInputPanel->LoadPanel(CustomPanelInputPath);
}
}
}
return;
}
void SCutMainWindow::OnSelectCard(const FGuid& SelectedCard)
{
if (SelectedCard.IsValid())
{
EffectCardsPanel->SelectCard(SelectedCard);
}
}
FTimelinePropertyData* SCutMainWindow::GetResourcePropertyDataPtr(FGuid GUID)
{

View File

@ -56,7 +56,10 @@ public:
virtual void OpenTimeline(const FString& TimelineName, bool NeedSaveBefore) override;
virtual void OpenProject(const FString& Project) override;
virtual void ExportProject(const FString& ExportPath) override;
virtual void ImportProject(const FString& ImportPath) override;
virtual void OnSelectCard(const FGuid& SelectedCard) override;
virtual FTimelinePropertyData* GetResourcePropertyDataPtr(FGuid GUID) override;
virtual FString GetGroupName(TSharedPtr<IWidgetInterface> WidgetInterface) override;
};

View File

@ -84,6 +84,13 @@ void SCutTimeline::Construct(const FArguments& InArgs)
SNew(SHorizontalBox)
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SAssignNew(CurrentEditDebug, STextBlock)
.Text(FText::FromString(TEXT("当前正在编辑主面板")))
]
+ SVerticalBox::Slot()
[
// Timeline
SNew(SHorizontalBox)

View File

@ -96,6 +96,7 @@ public:
TSharedPtr<SScrollBox> TrackBodyHScrollBox;
TSharedPtr<SBox> TimelineTickBox;
TSharedPtr<SScrollBox> TickScrollBox;
TSharedPtr<STextBlock> CurrentEditDebug;
TArray<FSingleTrackGroupInstance> TrackGroupInstances;
TArray<FTrackGroup> TrackGroups;

View File

@ -195,28 +195,10 @@ void STimelineClip::Seek(int32 Frame)
FMemory::Memcpy(MipData, RawData, AllocatedFrame->width * AllocatedFrame->height * 4);
Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
Texture->UpdateResource();
MainWidgetInterface->OnUpdateVideo(FGuid::NewGuid(), Texture);
delete RawData;
}
av_frame_free(&AllocatedFrame);
// AVFrame* frameRGBA = av_frame_alloc();
// int numBytes = avpicture_get_size(AV_PIX_FMT_RGBA, VideoCodecContext->width, VideoCodecContext->height);
// uint8_t* buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
// avpicture_fill((AVPicture*)frameRGBA, buffer, AV_PIX_FMT_RGBA, VideoCodecContext->width, VideoCodecContext->height);
// sws_scale(swsCtx, AllocatedFrame->data, AllocatedFrame->linesize, 0, VideoCodecContext->height, frameRGBA->data, frameRGBA->linesize);
//
// UTexture2D* texture = UTexture2D::CreateTransient(VideoCodecContext->width, VideoCodecContext->height);
// FUpdateTextureRegion2D region(0, 0, 0, 0, VideoCodecContext->width, VideoCodecContext->height);
// texture->UpdateTextureRegions(0, 1, &region, VideoCodecContext->width * 4, 4, frameRGBA->data[0]);
// MainWidgetInterface->OnUpdateVideo(FGuid::NewGuid(), texture);
}
break;
@ -243,8 +225,6 @@ void STimelineClip::Seek(int32 Frame)
break;
case ETrackType::AudioTrack:
{
if (Stream == nullptr)
{
Pa_Initialize();

View File

@ -95,7 +95,7 @@ void SStatePanel::Construct(const FArguments& InArgs)
]
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
SNew(SBox)
@ -107,7 +107,7 @@ void SStatePanel::Construct(const FArguments& InArgs)
]
]
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
[
SNew(SBox)
@ -127,6 +127,15 @@ void SStatePanel::Construct(const FArguments& InArgs)
]
]
+ SVerticalBox::Slot()
.SizeParam(FAuto())
[
SNew(SBox)
.HeightOverride(125.0)
[
SAssignNew(PlayerList2, SHorizontalBox)
]
]
]
]