2499 lines
88 KiB
C++
2499 lines
88 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
||
|
||
|
||
#include "SCutMainWindow.h"
|
||
|
||
|
||
#include "DesktopPlatformModule.h"
|
||
#include "IDesktopPlatform.h"
|
||
#include "Curtain/SCurtainPanel.h"
|
||
#include "SCustomInputPanel.h"
|
||
#include "SCustomInputResource.h"
|
||
#include "SCutTimeline.h"
|
||
#include "SlateOptMacros.h"
|
||
#include "SPlayerLight.h"
|
||
#include "STimelinePropertyPanel.h"
|
||
#include "STrackBody.h"
|
||
#include "STrackHead.h"
|
||
#include "Commands/MainMenuCommands.h"
|
||
#include "Commands/ShortcunCommands.h"
|
||
#include "CustomPanel/SCustomPanel.h"
|
||
#include "Cut5/Utils/FFMPEGUtils.h"
|
||
#include "Cut5/Utils/Utils.h"
|
||
#include "Cut5/Xml/tinyxml2.h"
|
||
#include "DragDropOperator/DragDropOperator.h"
|
||
#include "FX/SEffectCardsPanel.h"
|
||
#include "HAL/FileManagerGeneric.h"
|
||
#include "Kismet/KismetSystemLibrary.h"
|
||
#include "MicroWidgets/SColorPanel.h"
|
||
#include "MicroWidgets/SNewProjectTips.h"
|
||
#include "StatePanel/SStatePanel.h"
|
||
#include "TimelineClips/ClipProxy.h"
|
||
#include "Widgets/Layout/SConstraintCanvas.h"
|
||
#include "Widgets/Layout/SScaleBox.h"
|
||
#include "Widgets/Layout/SSpacer.h"
|
||
#include "Widgets/Layout/SWidgetSwitcher.h"
|
||
#include "Widgets/Views/STreeView.h"
|
||
#include "Windows/AllowWindowsPlatformTypes.h"
|
||
|
||
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||
|
||
void SCutMainWindow::Construct(const FArguments& InArgs)
|
||
{
|
||
SAssignNew(CutTimeline, SCutTimeline).MainWidgetInterface(this);
|
||
SAssignNew(StatePanel, SStatePanel);
|
||
SAssignNew(CustomPanel, SCustomPanel);
|
||
|
||
FTextBlockStyle MainBarTextStyle = FAppStyle::GetWidgetStyle<FTextBlockStyle>("NormalText");
|
||
MainBarTextStyle.SetFontSize(14);
|
||
FTextBlockStyle TitleBarTextStyle = FAppStyle::GetWidgetStyle<FTextBlockStyle>("NormalText");
|
||
TitleBarTextStyle.SetFontSize(15);
|
||
|
||
|
||
ChildSlot
|
||
[
|
||
SAssignNew(Overlay, SOverlay)
|
||
+ SOverlay::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SImage)
|
||
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("Black.png"), {}))
|
||
]
|
||
+ SOverlay::Slot()
|
||
.VAlign(VAlign_Top)
|
||
.HAlign(HAlign_Fill)
|
||
[
|
||
SNew(SBox)
|
||
.HeightOverride(47)
|
||
.WidthOverride(47)
|
||
[
|
||
SNew(SHorizontalBox)
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.Padding(16, 0, 0, 0)
|
||
.HAlign(HAlign_Left)
|
||
.VAlign(VAlign_Center)
|
||
[
|
||
SNew(SBox)
|
||
.HeightOverride(28)
|
||
.WidthOverride(28)
|
||
|
||
[
|
||
SNew(SImage)
|
||
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("EngineLogo.png"), {26, 26}))
|
||
]
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.HAlign(HAlign_Left)
|
||
.VAlign(VAlign_Center)
|
||
.SizeParam(FAuto())
|
||
[
|
||
SNew(SOverlay)
|
||
+ SOverlay::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SButton)
|
||
.ButtonStyle(FCoreStyle::Get(), "NoBorder")
|
||
[
|
||
SNew(STextBlock)
|
||
.Text(FText::FromString(TEXT("菜单 v")))
|
||
.Font(MainBarTextStyle.Font)
|
||
]
|
||
.OnClicked_Lambda([this]()
|
||
{
|
||
FMenuBuilder MenuBuilder(true, CommandList);
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().NewProject, NAME_None, FText::FromString(TEXT("新建")));
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().OpenProject, NAME_None, FText::FromString(TEXT("打开")));
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().SaveProject, NAME_None, FText::FromString(TEXT("保存")));
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().SaveProjectAs, NAME_None, FText::FromString(TEXT("保存为")));
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().ExportXML, NAME_None, FText::FromString(TEXT("导出项目到xml")));
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().Setting, NAME_None, FText::FromString(TEXT("设置")));
|
||
MenuBuilder.AddMenuEntry(FMainMenuCommands::Get().Exit, NAME_None, FText::FromString(TEXT("退出")));
|
||
FSlateApplication::Get().PushMenu(AsShared(), FWidgetPath(), MenuBuilder.MakeWidget(), FSlateApplication::Get().GetCursorPos(), FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu));
|
||
|
||
return FReply::Handled();
|
||
})
|
||
]
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FStretch(1.0))
|
||
[
|
||
SNew(SSpacer)
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.VAlign(VAlign_Center)
|
||
.HAlign(HAlign_Right)
|
||
[
|
||
SNew(SBox)
|
||
.WidthOverride(24)
|
||
.HeightOverride(24)
|
||
[
|
||
SNew(SImage)
|
||
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("minus.png"), { 24, 24 }))
|
||
.OnMouseButtonDown_Lambda([](const FGeometry& Geometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
// Maximize
|
||
GEngine->GameViewport->GetWindow()->Minimize();
|
||
return FReply::Handled();
|
||
})
|
||
]
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.VAlign(VAlign_Center)
|
||
.HAlign(HAlign_Right)
|
||
[
|
||
SNew(SBox)
|
||
.WidthOverride(24)
|
||
.HeightOverride(24)
|
||
[
|
||
SNew(SImage)
|
||
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("Max.png"), { 24, 24 }))
|
||
.OnMouseButtonDown_Lambda([](const FGeometry& Geometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
// Maximize
|
||
if (GEngine->GameViewport->GetWindow()->IsWindowMaximized())
|
||
{
|
||
GEngine->GameViewport->GetWindow()->Restore();
|
||
}
|
||
else
|
||
{
|
||
GEngine->GameViewport->GetWindow()->Maximize();
|
||
}
|
||
|
||
return FReply::Handled();
|
||
})
|
||
]
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.VAlign(VAlign_Center)
|
||
.HAlign(HAlign_Right)
|
||
[
|
||
SNew(SBox)
|
||
.WidthOverride(24)
|
||
.HeightOverride(24)
|
||
[
|
||
SNew(SImage)
|
||
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("Close.png"), { 24, 24 }))
|
||
.OnMouseButtonDown_Lambda([](const FGeometry& Geometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
UKismetSystemLibrary::QuitGame(GWorld->GetWorld(), nullptr, EQuitPreference::Quit, false);
|
||
return FReply::Handled();
|
||
})
|
||
]
|
||
]
|
||
]
|
||
]
|
||
|
||
+ SOverlay::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
.Padding(16, 47, 16, 16)
|
||
[
|
||
SNew(SConstraintCanvas)
|
||
+ SConstraintCanvas::Slot()
|
||
.Anchors(FAnchors(0, 0, 1, 1))
|
||
[
|
||
SNew(SVerticalBox)
|
||
+ SVerticalBox::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SHorizontalBox)
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SAssignNew(CurtainPanel, SCurtainPanel)
|
||
.MainInterface(this)
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SVerticalBox)
|
||
+ SVerticalBox::Slot()
|
||
.Padding(2.0)
|
||
[
|
||
SNew(SHorizontalBox)
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SBox)
|
||
.WidthOverride(269)
|
||
.HeightOverride(489)
|
||
.Padding(0, 0, 2, 0)
|
||
[
|
||
SNew(SOverlay)
|
||
+ SOverlay::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SImage)
|
||
.Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("BackGround.png"), {}))
|
||
]
|
||
+ SOverlay::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SVerticalBox)
|
||
+ SVerticalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.Padding(0, 11, 0, 13)
|
||
[
|
||
SNew(SHorizontalBox)
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
[
|
||
SNew(SButton)
|
||
.ButtonStyle(FCoreStyle::Get(), "NoBorder")
|
||
.OnClicked_Lambda([this]()
|
||
{
|
||
PropertiesPanelSwitcher->SetActiveWidgetIndex(0);
|
||
return FReply::Handled();
|
||
})
|
||
[
|
||
SNew(STextBlock)
|
||
.Text(FText::FromString(TEXT("设备列表")))
|
||
.Font(TitleBarTextStyle.Font)
|
||
]
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
[
|
||
SNew(SButton)
|
||
.ButtonStyle(FCoreStyle::Get(), "NoBorder")
|
||
.OnClicked_Lambda([this]()
|
||
{
|
||
PropertiesPanelSwitcher->SetActiveWidgetIndex(1);
|
||
return FReply::Handled();
|
||
})
|
||
[
|
||
SNew(STextBlock)
|
||
.Text(FText::FromString(TEXT("特效卡")))
|
||
.Font(TitleBarTextStyle.Font)
|
||
]
|
||
]
|
||
]
|
||
+ SVerticalBox::Slot()
|
||
.Padding(0, 0, 2, 0)
|
||
[
|
||
SAssignNew(PropertiesPanelSwitcher, SWidgetSwitcher)
|
||
+ SWidgetSwitcher::Slot()
|
||
[
|
||
// Property Panel
|
||
SNew(STimelinePropertyPanel)
|
||
.MainWindow(SharedThis(this))
|
||
.MainInterface(this)
|
||
]
|
||
+ SWidgetSwitcher::Slot()
|
||
[
|
||
SAssignNew(EffectCardsPanel, SEffectCardsPanel)
|
||
.MainInterface(this)
|
||
]
|
||
]
|
||
]
|
||
|
||
]
|
||
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SVerticalBox)
|
||
+ SVerticalBox::Slot()
|
||
[
|
||
StatePanel.ToSharedRef()
|
||
]
|
||
]
|
||
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SVerticalBox)
|
||
+ SVerticalBox::Slot()
|
||
[
|
||
SAssignNew(CustomInputPanel, SCustomInputPanel)
|
||
.MainInterface(this)
|
||
]
|
||
]
|
||
+ SHorizontalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
SNew(SVerticalBox)
|
||
+ SVerticalBox::Slot()
|
||
[
|
||
CustomPanel.ToSharedRef()
|
||
]
|
||
]
|
||
]
|
||
+ SVerticalBox::Slot()
|
||
.SizeParam(FAuto())
|
||
.Padding(2.0)
|
||
.HAlign(HAlign_Fill)
|
||
.VAlign(VAlign_Fill)
|
||
[
|
||
CutTimeline.ToSharedRef()
|
||
]
|
||
|
||
]
|
||
]
|
||
]
|
||
|
||
]
|
||
|
||
|
||
];
|
||
|
||
|
||
|
||
const TSharedPtr<SWidget> NewWidget = SNew(SBox).WidthOverride(48).HeightOverride(48)
|
||
[
|
||
SNew(SImage).Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("MouseCursor.png")), {48, 48}))
|
||
];
|
||
GEngine->GameViewport->AddSoftwareCursorFromSlateWidget(EMouseCursor::Type::Default, NewWidget.ToSharedRef());
|
||
|
||
|
||
|
||
|
||
FShortCutCommands::Register();
|
||
const FName ContextName = FShortCutCommands::Get().GetContextName();
|
||
CommandList = MakeShared<FUICommandList>();
|
||
CommandList->MapAction(FShortCutCommands::Get().MicroLeft, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
CutTimeline->AddSelectedClipsOffset(-1);
|
||
}), EUIActionRepeatMode::RepeatEnabled);
|
||
CommandList->MapAction(FShortCutCommands::Get().MicroRight, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
CutTimeline->AddSelectedClipsOffset(1);
|
||
}), EUIActionRepeatMode::RepeatEnabled);
|
||
|
||
CommandList->MapAction(FShortCutCommands::Get().LeftPerFrame, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
CutTimeline->UpdateCursorPosition(CutTimeline->TimelineTick->GetCursorPosition() - 1);
|
||
}), EUIActionRepeatMode::RepeatEnabled);
|
||
CommandList->MapAction(FShortCutCommands::Get().RightPerFrame, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
CutTimeline->UpdateCursorPosition(CutTimeline->TimelineTick->GetCursorPosition() + 1);
|
||
}), EUIActionRepeatMode::RepeatEnabled);
|
||
CommandList->MapAction(FShortCutCommands::Get().PlayFrame, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
CutTimeline->SetAutoPlay(!CutTimeline->AutoPlaying);
|
||
CutTimeline->PlayImage->SetImage(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(CutTimeline->AutoPlaying ? "ColorSelectCircle.png" : "PlayButton.png"), {24, 24}));
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().Delete, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
for (int32 i = 0; i < CutTimeline->SelectedClips.Num(); i++)
|
||
{
|
||
for (FSingleTrackGroupInstance& TrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
FTrackData& TrackData = StaticCastSharedPtr<STrackHead>(TrackGroupInstance.Head)->TrackData;
|
||
for (int32 j = TrackData.ClipData.Num() - 1; j >= 0; j--)
|
||
{
|
||
if (TrackData.ClipData[j].ClipGuid == CutTimeline->SelectedClips[i])
|
||
{
|
||
TrackData.ClipData.RemoveAt(j);
|
||
UpdateProperties(nullptr);
|
||
}
|
||
}
|
||
StaticCastSharedPtr<STrackBody>(TrackGroupInstance.Body)->CallRender();
|
||
}
|
||
}
|
||
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().ExportXML, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
FString String;
|
||
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
||
DesktopPlatform->OpenDirectoryDialog(nullptr, TEXT("选择导出路径"), String, String);
|
||
if (String.IsEmpty())
|
||
return;
|
||
ExportProject(String);
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().ZoomInTimeline, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
if (CutTimeline->ZoomSlider->GetValue() <= 1.0)
|
||
{
|
||
const float NewValue = CutTimeline->ZoomSlider->GetValue() + 0.1;
|
||
CutTimeline->ZoomSlider->SetValue(NewValue);
|
||
FGlobalData::DefaultTimeTickSpace = FMath::GetMappedRangeValueClamped(FVector2D(0, 1.0), FVector2D(GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength, 14), NewValue);
|
||
CutTimeline->RenderGroup();
|
||
CutTimeline->UpdateCursorPosition(CutTimeline->GetCursorPosition());
|
||
}
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().ZoomOutTimeline, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
if (CutTimeline->ZoomSlider->GetValue() >= 0.1)
|
||
{
|
||
const float NewValue = CutTimeline->ZoomSlider->GetValue() - 0.1;
|
||
CutTimeline->ZoomSlider->SetValue(NewValue);
|
||
FGlobalData::DefaultTimeTickSpace = FMath::GetMappedRangeValueClamped(FVector2D(0, 1.0), FVector2D(GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength, 14), NewValue);
|
||
CutTimeline->RenderGroup();
|
||
CutTimeline->UpdateCursorPosition(CutTimeline->GetCursorPosition());
|
||
}
|
||
}));
|
||
|
||
CommandList->MapAction(FShortCutCommands::Get().SelectMode, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
SelectMode = ESelectMode::SelectMode;
|
||
const TSharedPtr<SWidget> NewWidget = SNew(SBox).WidthOverride(48).HeightOverride(48)
|
||
[
|
||
SNew(SImage).Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("MouseCursor.png")), {48, 48}))
|
||
];
|
||
GEngine->GameViewport->AddSoftwareCursorFromSlateWidget(EMouseCursor::Type::Default, NewWidget.ToSharedRef());
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().CutMode, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
SelectMode = ESelectMode::CutMode;
|
||
|
||
const TSharedPtr<SWidget> NewWidget = SNew(SBox).WidthOverride(19).HeightOverride(19)
|
||
[
|
||
SNew(SImage).Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("BreakClip.png")), {19, 19}))
|
||
];
|
||
GEngine->GameViewport->AddSoftwareCursorFromSlateWidget(EMouseCursor::Type::Default, NewWidget.ToSharedRef());
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().TimelineMoveLeft, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
if (CutTimeline->TrackBodyHScrollBox->GetScrollOffset() < CutTimeline->TrackBodyHScrollBox->GetScrollOffsetOfEnd())
|
||
CutTimeline->TrackBodyHScrollBox->SetScrollOffset(CutTimeline->TrackBodyHScrollBox->GetScrollOffset() - 10);
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().TimelineMoveRight, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
if (CutTimeline->TrackBodyHScrollBox->GetScrollOffset() < CutTimeline->TrackBodyHScrollBox->GetScrollOffsetOfEnd())
|
||
CutTimeline->TrackBodyHScrollBox->SetScrollOffset(CutTimeline->TrackBodyHScrollBox->GetScrollOffset() + 10);
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().Save, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
SaveProject();
|
||
}));
|
||
|
||
CommandList->MapAction(FShortCutCommands::Get().StartCollectGarbage, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
GEngine->SetTimeUntilNextGarbageCollection(1);
|
||
GEngine->ForceGarbageCollection(true);
|
||
}));
|
||
|
||
CommandList->MapAction(FShortCutCommands::Get().Copy, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
CutTimeline->CopyClipData.Empty();
|
||
for (FSingleTrackGroupInstance& Instance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
TSharedPtr<STrackBody> TrackBody = StaticCastSharedPtr<STrackBody>(Instance.Body);
|
||
for (FClipData& ClipData : TrackBody->TrackHead->TrackData.ClipData)
|
||
{
|
||
if (CutTimeline->SelectedClips.Contains(ClipData.ClipGuid))
|
||
{
|
||
CutTimeline->CopyClipData.Add(ClipData);
|
||
break;
|
||
}
|
||
|
||
}
|
||
}
|
||
}));
|
||
CommandList->MapAction(FShortCutCommands::Get().Paste, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
|
||
for (FClipData& ClipData : CutTimeline->CopyClipData)
|
||
{
|
||
for (FSingleTrackGroupInstance& Instance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
TSharedPtr<STrackBody> TrackBody = StaticCastSharedPtr<STrackBody>(Instance.Body);
|
||
FVector2D Pos = TrackBody->GetCachedGeometry().AbsoluteToLocal(NewMouseEvent.GetScreenSpacePosition());
|
||
if (TrackBody->TrackHead->TrackData.DeviceTrack.Guid == ClipData.BindTrackGuid)
|
||
{
|
||
FClipData NewClipData = ClipData;
|
||
NewClipData.ClipGuid = FGuid::NewGuid();
|
||
int32 Length = NewClipData.ClipEndFrame - NewClipData.ClipStartFrame;
|
||
NewClipData.ClipStartFrame = FMath::RoundToInt(Pos.X / FGlobalData::DefaultTimeTickSpace);
|
||
NewClipData.ClipEndFrame = NewClipData.ClipStartFrame + Length;
|
||
DragDropOperator::GetDragDropOperator()->UpdateClipProcess(this, NewClipData);
|
||
TrackBody->TrackHead->TrackData.ClipData.Add(NewClipData);
|
||
TrackBody->CallRender();
|
||
}
|
||
}
|
||
}
|
||
}));
|
||
|
||
FMainMenuCommands::Register();
|
||
CommandList->MapAction(FMainMenuCommands::Get().ExportXML, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
FString String;
|
||
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
||
DesktopPlatform->OpenDirectoryDialog(nullptr, TEXT("选择导出路径"), String, String);
|
||
if (String.IsEmpty())
|
||
return;
|
||
ExportProject(String);
|
||
}));
|
||
|
||
CommandList->MapAction(FMainMenuCommands::Get().NewProject, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
PreNewProject();
|
||
}));
|
||
CommandList->MapAction(FMainMenuCommands::Get().OpenProject, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
FString String;
|
||
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
||
DesktopPlatform->OpenDirectoryDialog(nullptr, TEXT("选择新建路径"), String, String);
|
||
if (String.IsEmpty())
|
||
return;
|
||
OpenProject(String);
|
||
}));
|
||
CommandList->MapAction(FMainMenuCommands::Get().SaveProject, FExecuteAction::CreateLambda([this]()
|
||
{
|
||
SaveProject();
|
||
}));
|
||
|
||
|
||
|
||
FInputBindingManager::Get().RegisterCommandList(FShortCutCommands::Get().GetContextName(), CommandList.ToSharedRef());
|
||
OnUpdateProjector(0, true);
|
||
|
||
DragDropOperator::GetDragDropOperator()->SavedMainInterface = this;
|
||
}
|
||
|
||
|
||
FReply SCutMainWindow::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
if (HasMouseCapture())
|
||
{
|
||
GEngine->GameViewport->GetWindow()->MoveWindowTo(GEngine->GameViewport->GetWindow()->GetPositionInScreen() + MouseEvent.GetCursorDelta());
|
||
}
|
||
|
||
this->NewMouseEvent = MouseEvent;
|
||
return SCompoundWidget::OnMouseMove(MyGeometry, MouseEvent);
|
||
}
|
||
|
||
void SCutMainWindow::Render()
|
||
{
|
||
StatePanel->PlayerList1->ClearChildren();
|
||
StatePanel->PlayerList2->ClearChildren();
|
||
PlayerLightsSlateInstances.Empty();
|
||
bool bSingle = false;
|
||
|
||
int32 i = 0;
|
||
FString LastGroupName;
|
||
for (FSingleTrackGroupInstance& TrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
if (LastGroupName != TrackGroupInstance.GroupName)
|
||
i = 0;
|
||
if (StaticCastSharedPtr<STrackHead>(TrackGroupInstance.GetHead())->TrackData.TrackType == ETrackType::AtomSphereLightTrack)
|
||
{
|
||
LastGroupName = TrackGroupInstance.GroupName;
|
||
FString NewName = TrackGroupInstance.GroupName + FString::FromInt(i);
|
||
TSharedPtr<SPlayerLight> PlayerLight = SNew(SPlayerLight).Name(NewName).TrackHead(TrackGroupInstance.Head);
|
||
(bSingle ? StatePanel->PlayerList1 : StatePanel->PlayerList2)->AddSlot()
|
||
.SizeParam(FAuto())
|
||
[
|
||
PlayerLight.ToSharedRef()
|
||
];
|
||
bSingle = !bSingle;
|
||
PlayerLightsSlateInstances.Add(PlayerLight);
|
||
}
|
||
i++;
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
void SCutMainWindow::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
||
{
|
||
if (TotalTime > 20.0f)
|
||
{
|
||
if (CutTimeline->AutoPlaying == false)
|
||
{
|
||
SaveProject();
|
||
}
|
||
|
||
TotalTime = 0;
|
||
}
|
||
TotalTime += InDeltaTime;
|
||
}
|
||
|
||
int32 SCutMainWindow::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
|
||
const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
|
||
const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
|
||
{
|
||
if (CutTimeline && bRenderLine)
|
||
{
|
||
const FSlateBrush Brush;
|
||
FPaintGeometry PaintGeometry = AllottedGeometry.ToPaintGeometry(
|
||
FVector2f(CutTimeline->TimelineTick->TickCursor->GetCachedGeometry().GetLocalSize().X, 9999),
|
||
FSlateLayoutTransform(FVector2f()));
|
||
|
||
FSlateDrawElement::MakeBox(
|
||
OutDrawElements,
|
||
LayerId + 9,
|
||
AllottedGeometry.ToPaintGeometry(FVector2f(2, CutTimeline->GetCachedGeometry().Size.Y), FSlateLayoutTransform(FVector2f(RenderLineTime, AllottedGeometry.GetLocalSize().Y - CutTimeline->GetCachedGeometry().GetLocalSize().Y))),
|
||
&Brush,
|
||
ESlateDrawEffect::None,
|
||
FColor(255, 255, 255, 255));
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
|
||
}
|
||
|
||
FReply SCutMainWindow::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
|
||
{
|
||
DragDropOperator::GetDragDropOperator()->OnDragOver(MyGeometry, DragDropEvent);
|
||
return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
|
||
}
|
||
|
||
FReply SCutMainWindow::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
|
||
{
|
||
TSharedPtr<FCutDragDropBase> DragDropOperation = DragDropEvent.GetOperationAs<FCutDragDropBase>();
|
||
DragDropOperator::GetDragDropOperator()->CloseCursorDecorator();
|
||
if (DragDropOperation->DragDropType == FCutDragDropBase::EType::SelectClips)
|
||
{
|
||
DragDropOperator::GetDragDropOperator()->OnDrop(MyGeometry, DragDropEvent, nullptr);
|
||
}
|
||
if (DragDropOperation->DragDropType == FCutDragDropBase::EType::Clip2Clip)
|
||
{
|
||
TSharedPtr<STrackBody> Body = StaticCastSharedPtr<STrackBody>(DragDropOperation->OverrideWidget);
|
||
DragDropOperator::GetDragDropOperator()->OnDrop(MyGeometry, DragDropEvent, Body);
|
||
Body->CallRender();
|
||
}
|
||
else if (DragDropOperation->DragDropType == FCutDragDropBase::EType::TrackClip)
|
||
{
|
||
TSharedPtr<STrackBody> Body = StaticCastSharedPtr<STrackBody>(DragDropOperation->MoveAboutWidget);
|
||
if (Body.IsValid())
|
||
{
|
||
DragDropOperator::GetDragDropOperator()->OnDrop(MyGeometry, DragDropEvent, Body);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
return FReply::Handled().EndDragDrop();
|
||
}
|
||
|
||
void SCutMainWindow::CloseAllThreads()
|
||
{
|
||
for (int32 i = 0; i < Threads.Num(); i++)
|
||
{
|
||
TArray<FGuid> Guids;
|
||
Threads.GetKeys(Guids);
|
||
for (int32 j = 0; j < Guids.Num(); j++)
|
||
{
|
||
Threads[Guids[j]]->Stop();
|
||
// delete Threads[Guids[j]];
|
||
Threads.Remove(Guids[j]);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void SCutMainWindow::OnUpdateVideo(FGuid UUID, int32 X, int32 Y, uint8* RawData)
|
||
{
|
||
if (!IsInGameThread())
|
||
{
|
||
|
||
}
|
||
else
|
||
{
|
||
ICutMainWidgetInterface::OnUpdateVideo(UUID, X, Y, RawData);
|
||
StatePanel->VideoPlayer->UpdateVideoData(UUID, X, Y, RawData);
|
||
}
|
||
|
||
}
|
||
|
||
void SCutMainWindow::OnUpdateLightArray(const TArray<FColor>& LightArray)
|
||
{
|
||
ICutMainWidgetInterface::OnUpdateLightArray(LightArray);
|
||
StatePanel->LightArray->LightGridColors = LightArray;
|
||
}
|
||
|
||
void SCutMainWindow::OnUpdatePlayers(TSharedPtr<class IWidgetInterface> TrackBody, FColor PlayerColor)
|
||
{
|
||
ICutMainWidgetInterface::OnUpdatePlayers(TrackBody, PlayerColor);
|
||
|
||
for (int32 i = 0; i < PlayerLightsSlateInstances.Num(); i++)
|
||
{
|
||
const FString PlayerLightName = StaticCastSharedPtr<STrackBody>(TrackBody)->TrackHead->TrackData.TrackName;
|
||
if ( StaticCastSharedPtr<STrackBody>(TrackBody)->TrackHead == PlayerLightsSlateInstances[i]->TrackHead)
|
||
{
|
||
PlayerLightsSlateInstances[i]->SetColor(PlayerColor);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void SCutMainWindow::OnUpdateProjector(int32 Index, bool bEnableProjector)
|
||
{
|
||
if (StatePanel->Projector)
|
||
{
|
||
StatePanel->Projector->SetColorAndOpacity(bEnableProjector ? FLinearColor::White : FLinearColor::Black);
|
||
}
|
||
}
|
||
|
||
void SCutMainWindow::OnUpdateSpotLight(int32 Index, FColor LightColor)
|
||
{
|
||
if (StatePanel->SpotLight)
|
||
{
|
||
StatePanel->SpotLight->SetColorAndOpacity(LightColor.ReinterpretAsLinear());
|
||
}
|
||
|
||
}
|
||
|
||
void SCutMainWindow::OnAddNewTrack(ETrackType Type)
|
||
{
|
||
ICutMainWidgetInterface::OnAddNewTrack(Type);
|
||
switch (Type)
|
||
{
|
||
case ETrackType::PlayerTrack:
|
||
{
|
||
Render();
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
void SCutMainWindow::OnRemoveTrack(FGuid Guid)
|
||
{
|
||
ICutMainWidgetInterface::OnRemoveTrack(Guid);
|
||
Render();
|
||
}
|
||
|
||
void SCutMainWindow::OnUpdateSound(uint8* Data, int32 Size)
|
||
{
|
||
|
||
}
|
||
|
||
void SCutMainWindow::SelectClip(const FGuid& Guid)
|
||
{
|
||
if (CutTimeline->SelectedClipGUID == Guid)
|
||
{
|
||
CutTimeline->SelectedClipGUID.Invalidate();
|
||
}
|
||
else
|
||
{
|
||
CutTimeline->SelectedClipGUID = Guid;
|
||
}
|
||
|
||
for (FSingleTrackGroupInstance Track : CutTimeline->TrackGroupInstances)
|
||
{
|
||
StaticCastSharedPtr<STrackBody>(Track.Body)->CallRender();
|
||
}
|
||
}
|
||
|
||
|
||
void SCutMainWindow::AddNewCard(FEffectCardProperty& CardProperty, FString GroupName)
|
||
{
|
||
EffectCardsPanel->AddNewCard(CardProperty, GroupName);
|
||
}
|
||
|
||
void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefore, bool ForceOpen)
|
||
{
|
||
CutTimeline->bNeedShowPanel = true;
|
||
if (NeedSaveBefore)
|
||
{
|
||
CutTimeline->SaveTimeline(CutTimeline->TimelineInfo.CurrentOpenFullPath, CutTimeline->TimelineInfo);
|
||
CutTimeline->TimelineInfo.CurrentOpenFullPath = TimelineName;
|
||
}
|
||
//
|
||
// if (TimelineName == CutTimeline->TimelineInfo.CurrentOpenFullPath && !ForceOpen)
|
||
// {
|
||
// CloseTimeline();
|
||
// return;
|
||
// }
|
||
FTimelineInfo TimelineInfo;
|
||
// 拿到TimelineName路径中的名字,也就是倒数第四位开始,去掉后缀
|
||
|
||
// GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TimelineName);
|
||
if (CutTimeline->LoadTimeline(TimelineName, TimelineInfo))
|
||
{
|
||
CutTimeline->TimelineInfo = TimelineInfo;
|
||
// CutTimeline->CurrentEditDebug->SetText(FText::FromString(TEXT("当前正在编辑") + TimelineInfo.CurrentOpenFullPath));
|
||
}
|
||
|
||
OnAddNewTrack(ETrackType::PlayerTrack);
|
||
|
||
}
|
||
|
||
void SCutMainWindow::CloseTimeline()
|
||
{
|
||
CutTimeline->bNeedShowPanel = false;
|
||
CutTimeline->SaveTimeline(CutTimeline->TimelineInfo.CurrentOpenFullPath, CutTimeline->TimelineInfo);
|
||
CutTimeline->RenderGroup();
|
||
}
|
||
|
||
void SCutMainWindow::OpenProject(const FString& Project)
|
||
{
|
||
// 得到Project的上一级目录
|
||
|
||
CurtainPanel->Groups.Empty();
|
||
CurtainPanel->CallRender();
|
||
|
||
// 加载项目关联文件 .cutlink
|
||
TArray<uint8> Data;
|
||
// 找出文件夹内后缀为.cutlink的文件
|
||
TArray<FString> CutlinkName;
|
||
FFileManagerGeneric::Get().FindFiles(CutlinkName, *FPaths::Combine(Project, TEXT("*.cutlink")), true, false);
|
||
if (CutlinkName.Num() == 0)
|
||
{
|
||
// GEngine->GameViewport->AddViewportWidgetContent(SNew(SNewProjectTips).Title(FText::FromString(TEXT("存档失效或这不是一个存档"))).OnEnsure_Lambda([]))
|
||
UE_LOG(LogTemp, Error, TEXT("项目关联文件不存在"));
|
||
return;
|
||
}
|
||
|
||
// 去掉.cutlink后缀,得到项目名
|
||
|
||
|
||
FGlobalData::CurrentProjectName = FPaths::GetBaseFilename(FPaths::GetCleanFilename(CutlinkName[0]));
|
||
FGlobalData::BasePath = Project.LeftChop(FGlobalData::CurrentProjectName.Len()) ;
|
||
FFileHelper::LoadFileToArray(Data, *FPaths::Combine(Project, FPaths::GetCleanFilename(CutlinkName[0])));
|
||
FMemoryReader Reader(Data);
|
||
|
||
// 写入版本号
|
||
FString LoadVersion;
|
||
Reader << LoadVersion;
|
||
if (LoadVersion != FGlobalData::Version)
|
||
{
|
||
UE_LOG(LogTemp, Error, TEXT("版本不匹配,无法打开项目,载入版本:%s, 当前版本:%s"), *LoadVersion, *FGlobalData::Version);
|
||
return;
|
||
}
|
||
|
||
// 记录所有导入资产链接
|
||
int32 PropertyDataNum = 0;
|
||
Reader << PropertyDataNum;
|
||
for (int32 i = 0; i < PropertyDataNum; i++)
|
||
{
|
||
FTimelinePropertyData TimelinePropertyData;
|
||
Reader << TimelinePropertyData;
|
||
|
||
FTimelinePropertyData ReloadPropertyData = TimelinePropertyData;
|
||
if (TimelinePropertyData.bIsCustomPresetData == false)
|
||
{
|
||
if (FFFMPEGUtils::LoadMedia(TimelinePropertyData.MoviePath, &ReloadPropertyData) == TEXT("Failed"))
|
||
{
|
||
continue;
|
||
}
|
||
ReloadPropertyData.Guid = TimelinePropertyData.Guid;
|
||
}
|
||
|
||
CustomInputPanel->GridPanel->AddSlot(i % 2, i / 2)
|
||
[
|
||
SNew(SCustomInputResource)
|
||
.CustomInputPanel(CustomInputPanel.Get())
|
||
.PropertyData(ReloadPropertyData)
|
||
];
|
||
CustomInputPanel->PropertyData.Add(ReloadPropertyData);
|
||
}
|
||
|
||
|
||
// 记录所有幕
|
||
int32 CutNum = 0;
|
||
Reader << CutNum;
|
||
for (int32 i = 0; i < CutNum; i++)
|
||
{
|
||
FCurtainGroup NewGroup;
|
||
Reader << NewGroup;
|
||
CurtainPanel->Groups.Add(NewGroup);
|
||
CurtainPanel->CallRender();
|
||
}
|
||
|
||
|
||
|
||
// 记录所有组轨道链接
|
||
CutTimeline->DeviceTrackGroups.Empty();
|
||
CutTimeline->TrackGroupInstances.Empty();
|
||
int32 GroupTrackNum = 0;
|
||
Reader << GroupTrackNum;
|
||
CutTimeline->DeviceTrackGroups.Init(FDeviceTrackGroup(), GroupTrackNum);
|
||
for (int32 i = 0; i < GroupTrackNum; i++)
|
||
{
|
||
Reader << CutTimeline->DeviceTrackGroups[i];
|
||
|
||
for (int32 j = 0; j < CutTimeline->DeviceTrackGroups[i].DeviceTracks.Num(); j++)
|
||
{
|
||
CutTimeline->DeviceTrackGroups[i].DeviceTracks[j].DeviceTrackGroup = &CutTimeline->DeviceTrackGroups[i];
|
||
FTrackData TrackData = FTrackData(CutTimeline->DeviceTrackGroups[i].DeviceTracks[j].DeviceName, CutTimeline->DeviceTrackGroups[i].DeviceTracks[j].DeviceType, CutTimeline->DeviceTrackGroups[i].DeviceTracks[j]);
|
||
const TSharedPtr<STrackHead> NewTrackHead = SNew(STrackHead).TrackData(TrackData).CutTimeline(CutTimeline.ToSharedRef()).MainWidgetInterface(this).GroupName(CutTimeline->DeviceTrackGroups[i].GroupName);
|
||
const TSharedPtr<STrackBody> NewTrackBody = SNew(STrackBody).TrackHead(NewTrackHead).MainWidgetInterface(this);
|
||
NewTrackBody->CallRender();
|
||
CutTimeline->TrackGroupInstances.Add(FSingleTrackGroupInstance(NewTrackHead, NewTrackBody, CutTimeline->DeviceTrackGroups[i].GroupName));
|
||
}
|
||
|
||
|
||
CutTimeline->RenderGroup();
|
||
}
|
||
|
||
EffectCardsPanel->EffectCardGroups.Empty();
|
||
|
||
int32 GroupLength = 0;
|
||
Reader << GroupLength;
|
||
|
||
for (int32 i = 0; i < GroupLength; i++)
|
||
{
|
||
FEffectCardGroup Group;
|
||
Reader << Group;
|
||
EffectCardsPanel->EffectCardGroups.Add(Group);
|
||
EffectCardsPanel->CallRender();
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
void SCutMainWindow::ExportProject(const FString& ExportPath)
|
||
{
|
||
|
||
if (ExportPath.IsEmpty())
|
||
return;
|
||
FGlobalData::ExportPath = ExportPath / FGlobalData::CurrentProjectName;
|
||
|
||
FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*FGlobalData::ExportPath);
|
||
|
||
IDList.Empty();
|
||
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*FGlobalData::ExportPath);
|
||
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(FGlobalData::ExportPath / "Video"));
|
||
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(FGlobalData::ExportPath / "Sound"));
|
||
FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*(FGlobalData::ExportPath / "PSAF"));
|
||
|
||
tinyxml2::XMLDocument Document;
|
||
tinyxml2::XMLElement* RootElement = Document.NewElement("Project");
|
||
|
||
RootElement->SetAttribute("Name", TCHAR_TO_UTF8(*FGlobalData::CurrentProjectName));
|
||
|
||
tinyxml2::XMLDeclaration* decl = Document.NewDeclaration("xml version=\"1.0\"");
|
||
tinyxml2::XMLNode* XMLVersion = Document.InsertFirstChild(decl);
|
||
Document.InsertAfterChild(XMLVersion, 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("描述");
|
||
File->InsertNewChildElement("FileVersion")->InsertNewText("3.0");
|
||
File->InsertNewChildElement("SoftWareVersion")->InsertNewText(TCHAR_TO_UTF8(*FGlobalData::Version));
|
||
|
||
// Device List
|
||
tinyxml2::XMLElement* DeviceList = RootElement->InsertNewChildElement("DeviceList");
|
||
{
|
||
tinyxml2::XMLElement* PlayerLightList = DeviceList->InsertNewChildElement("PlayerLightList");
|
||
tinyxml2::XMLElement* DMLightList = DeviceList->InsertNewChildElement("DMLightList");
|
||
tinyxml2::XMLElement* LightArrayList = DeviceList->InsertNewChildElement("GuangZhenList");
|
||
tinyxml2::XMLElement* RoundSpeakerList = DeviceList->InsertNewChildElement("RotationSpeakerList");
|
||
tinyxml2::XMLElement* ProjectorList = DeviceList->InsertNewChildElement("ProjectorList");
|
||
|
||
int32 DeviceID = 1;
|
||
|
||
for (FDeviceTrackGroup& DeviceTrackGroup : CutTimeline->DeviceTrackGroups)
|
||
{
|
||
for (FDeviceTrack& TrackData : DeviceTrackGroup.DeviceTracks)
|
||
{
|
||
switch (TrackData.DeviceType)
|
||
{
|
||
case ETrackType::AtomSphereLightTrack:
|
||
{
|
||
tinyxml2::XMLElement* PlayerLight = PlayerLightList->InsertNewChildElement("PlayerLight");
|
||
PlayerLight->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID)));
|
||
PlayerLight->InsertNewChildElement("RoleName")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceTrackGroup->GroupName));
|
||
IDList.Add(TrackData.Guid, DeviceID);
|
||
DeviceID++;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
bool bIsLightBar = false;
|
||
for (FDeviceTrackGroup& DeviceTrackGroup : CutTimeline->DeviceTrackGroups)
|
||
{
|
||
for (FDeviceTrack& TrackData : DeviceTrackGroup.DeviceTracks)
|
||
{
|
||
switch (TrackData.DeviceType)
|
||
{
|
||
case ETrackType::AudioTrackR:
|
||
{
|
||
tinyxml2::XMLElement* RotationSpeaker = RoundSpeakerList->InsertNewChildElement("RotationSpeaker");
|
||
RotationSpeaker->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID)));
|
||
RotationSpeaker->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName));
|
||
IDList.Add(TrackData.Guid, DeviceID);
|
||
DeviceID++;
|
||
RotatorSpeakerIndex = DeviceID;
|
||
}
|
||
break;
|
||
case ETrackType::LightArrayTrack:
|
||
{
|
||
tinyxml2::XMLElement* LightArray = LightArrayList->InsertNewChildElement("GuangZhen");
|
||
LightArray->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID)));
|
||
LightArray->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName));
|
||
IDList.Add(TrackData.Guid, DeviceID);
|
||
DeviceID++;
|
||
LightArrayIndex = DeviceID;
|
||
}
|
||
break;
|
||
case ETrackType::ProjectorTrack:
|
||
{
|
||
tinyxml2::XMLElement* Projector = ProjectorList->InsertNewChildElement("Projector");
|
||
Projector->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID)));
|
||
Projector->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName));
|
||
IDList.Add(TrackData.Guid, DeviceID);
|
||
DeviceID++;
|
||
}
|
||
break;
|
||
case ETrackType::SpotLightTrack:
|
||
{
|
||
tinyxml2::XMLElement* DMLight = DMLightList->InsertNewChildElement("DMLight");
|
||
DMLight->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID)));
|
||
DMLight->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName));
|
||
IDList.Add(TrackData.Guid, DeviceID);
|
||
DeviceID++;
|
||
break;
|
||
}
|
||
case ETrackType::LightBarTrack:
|
||
{
|
||
if (bIsLightBar)
|
||
{
|
||
break;
|
||
}
|
||
tinyxml2::XMLElement* LightArray = LightArrayList->InsertNewChildElement("GuangZhen2");
|
||
LightArray->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(DeviceID)));
|
||
LightArray->InsertNewChildElement("Name")->InsertNewText(TCHAR_TO_UTF8(*TrackData.DeviceName));
|
||
IDList.Add(TrackData.Guid, DeviceID);
|
||
DeviceID++;
|
||
bIsLightBar = true;
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
int32 CardType = 0;
|
||
|
||
tinyxml2::XMLElement* CardList = DeviceList->InsertNewChildElement("CardList");
|
||
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i ++)
|
||
{
|
||
if (EffectCardsPanel->EffectCardGroups[i].bIsDedicated)
|
||
{
|
||
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
|
||
{
|
||
tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card");
|
||
Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
|
||
int32 TypeID = 0;
|
||
if (EffectCardsPanel->EffectCardGroups[i].Cards[j].JumpStepCurtains.Guid.IsValid())
|
||
{
|
||
TypeID = 1;
|
||
}
|
||
Card->InsertNewChildElement("Type")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TypeID)));
|
||
Card->InsertNewChildElement("Times")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(-1)));
|
||
|
||
int32 ToStepID = 0;
|
||
if (TypeID == 1)
|
||
{
|
||
for (int32 k = 0; k < CurtainPanel->Groups.Num(); k++)
|
||
{
|
||
for (FCurtain& Curtain : CurtainPanel->Groups[k].Curtains)
|
||
{
|
||
if (Curtain.CurtainUUID == EffectCardsPanel->EffectCardGroups[i].Cards[j].JumpStepCurtains.Guid)
|
||
{
|
||
ToStepID = Curtain.Step;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Card->InsertNewChildElement("Step")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ToStepID)));
|
||
Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
|
||
Card->InsertNewChildElement("SerialNumberList")->InsertNewChildElement("SerialNumber")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
tinyxml2::XMLElement* Card = CardList->InsertNewChildElement("Card");
|
||
|
||
|
||
Card->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID)));
|
||
|
||
int32 TypeID = 2;
|
||
if (EffectCardsPanel->EffectCardGroups[i].JumpStepCurtains.Guid.IsValid())
|
||
{
|
||
TypeID = 3;
|
||
}
|
||
|
||
Card->InsertNewChildElement("Type")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TypeID)));
|
||
Card->InsertNewChildElement("Times")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(-1)));
|
||
|
||
|
||
int32 ToStepID = 0;
|
||
if (TypeID == 3)
|
||
{
|
||
for (int32 k = 0; k < CurtainPanel->Groups.Num(); k++)
|
||
{
|
||
for (FCurtain& Curtain : CurtainPanel->Groups[k].Curtains)
|
||
{
|
||
if (Curtain.CurtainUUID == EffectCardsPanel->EffectCardGroups[i].JumpStepCurtains.Guid)
|
||
{
|
||
ToStepID = Curtain.Step;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
Card->InsertNewChildElement("Step")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(ToStepID)));
|
||
Card->InsertNewChildElement("SpecialEffectID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID)));
|
||
tinyxml2::XMLElement* SerialNumberList = Card->InsertNewChildElement("SerialNumberList");
|
||
for (int32 k = 0; k < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); k++)
|
||
{
|
||
SerialNumberList->InsertNewChildElement("SerialNumber")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[k].ID)));
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// KeyBoard
|
||
tinyxml2::XMLElement* Keyboard = DeviceList->InsertNewChildElement("KeyBoard");
|
||
{
|
||
tinyxml2::XMLElement* KeyCode = Keyboard->InsertNewChildElement("KeyCode");
|
||
KeyCode->InsertNewChildElement("CTRL")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("SHIFT")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("ALT")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("KEY")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("SpecialEffectID")->InsertNewText("");
|
||
}
|
||
}
|
||
// ProcessList
|
||
tinyxml2::XMLElement* ProcessList = RootElement->InsertNewChildElement("ProcessList");
|
||
for (int32 i = 0; i < CurtainPanel->Groups.Num(); i++)
|
||
{
|
||
GetProcessA(ProcessList, &CurtainPanel->Groups[i]);
|
||
}
|
||
GetSpecialEffectList(RootElement);
|
||
|
||
|
||
FString XMLExportPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(ExportPath, FGlobalData::CurrentProjectName, TEXT("Process.xml")));
|
||
TArray<uint8> Data;
|
||
FFileHelper::SaveArrayToFile(Data, *XMLExportPath);
|
||
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, XMLExportPath);
|
||
|
||
FFileHelper::SaveArrayToFile(Data, TEXT("C:\\temp\\Process.xml"));
|
||
tinyxml2::XMLError NewError = Document.SaveFile("C:\\temp\\Process.xml");
|
||
if (NewError)
|
||
{
|
||
check(false)
|
||
}
|
||
|
||
IFileManager::Get().Move(*XMLExportPath, TEXT("C:\\temp\\Process.xml"), true, true, false, false);
|
||
|
||
|
||
}
|
||
|
||
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)
|
||
{
|
||
OpenProject(*(OutFolderNames + "/" + Files[0]));
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
|
||
}
|
||
|
||
void SCutMainWindow::NewProject(const FString& NewPath)
|
||
{
|
||
FGlobalData::BasePath = NewPath;
|
||
CutTimeline->TimelineInfo.CurrentOpenFullPath = FUtils::MainSaveFullPath();
|
||
}
|
||
|
||
void SCutMainWindow::SaveProject()
|
||
{
|
||
// 保存架构
|
||
// 保存只保存项目文件,与导出的xml不相关联。
|
||
|
||
// 根 --- 项目关联文件 项目名.cutlink
|
||
// 根 << 版本号
|
||
// 根 << 记录所有导入资产链接
|
||
// 根 << 记录所有幕
|
||
// 根 << 记录所有组轨道链接
|
||
CutTimeline->SaveTimeline(CutTimeline->TimelineInfo.CurrentOpenFullPath, CutTimeline->TimelineInfo);
|
||
|
||
// 新建项目关联文件.cutlink
|
||
TArray<uint8> ProjectLinkData;
|
||
FMemoryWriter MemoryWriter(ProjectLinkData);
|
||
|
||
// 写入版本号
|
||
MemoryWriter << FGlobalData::Version;
|
||
|
||
// 记录所有导入资产链接
|
||
int32 PropertiesLength = CustomInputPanel->PropertyData.Num();
|
||
MemoryWriter << PropertiesLength;
|
||
for (int32 i = 0; i < PropertiesLength; i++)
|
||
{
|
||
MemoryWriter << CustomInputPanel->PropertyData[i];
|
||
}
|
||
|
||
// 记录所有幕
|
||
int32 CurtainLength = CurtainPanel->Groups.Num();
|
||
MemoryWriter << CurtainLength;
|
||
for (int32 i = 0; i < CurtainPanel->Groups.Num(); i++)
|
||
{
|
||
MemoryWriter << CurtainPanel->Groups[i];
|
||
}
|
||
|
||
int32 DeviceGroupLength = CutTimeline->DeviceTrackGroups.Num();
|
||
MemoryWriter << DeviceGroupLength;
|
||
for (int32 i = 0; i < DeviceGroupLength; i++)
|
||
{
|
||
MemoryWriter << CutTimeline->DeviceTrackGroups[i];
|
||
}
|
||
|
||
|
||
// 记录所有组轨道链接
|
||
int32 GroupLength = EffectCardsPanel->EffectCardGroups.Num();
|
||
MemoryWriter << GroupLength;
|
||
for (FEffectCardGroup& Group : EffectCardsPanel->EffectCardGroups)
|
||
{
|
||
MemoryWriter << Group;
|
||
}
|
||
|
||
const TArray64<uint8> SaveData(ProjectLinkData);
|
||
FFileHelper::SaveArrayToFile(SaveData, *FPaths::Combine(FGlobalData::BasePath, FGlobalData::CurrentProjectName, FGlobalData::CurrentProjectName + TEXT(".cutlink")));
|
||
|
||
}
|
||
|
||
bool SCutMainWindow::PreNewProject()
|
||
{
|
||
FString String;
|
||
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
||
DesktopPlatform->OpenDirectoryDialog(nullptr, TEXT("选择新建路径"), String, String);
|
||
if (String.IsEmpty())
|
||
return false;
|
||
FGlobalData::BasePath = String;
|
||
TSharedPtr<SNewProjectTips> NewProjectTips =
|
||
SNew(SNewProjectTips)
|
||
.Title(TEXT("新建项目名字"));
|
||
|
||
NewProjectTips->OnEnsure.BindLambda([this, NewProjectTips](FString String)
|
||
{
|
||
FGlobalData::CurrentProjectName = String;
|
||
GEngine->GameViewport->RemoveViewportWidgetContent(NewProjectTips.ToSharedRef());
|
||
});
|
||
GEngine->GameViewport->AddViewportWidgetContent(
|
||
NewProjectTips.ToSharedRef(), 2);
|
||
|
||
return true;
|
||
}
|
||
|
||
void SCutMainWindow::OnSelectCard(const FGuid& SelectedCard)
|
||
{
|
||
if (SelectedCard.IsValid())
|
||
{
|
||
EffectCardsPanel->SelectCard(SelectedCard);
|
||
}
|
||
}
|
||
|
||
void SCutMainWindow::OnRemoveCard(const FGuid& SelectedCard)
|
||
{
|
||
if (SelectedCard.IsValid())
|
||
{
|
||
EffectCardsPanel->RemoveCard(SelectedCard);
|
||
}
|
||
}
|
||
|
||
|
||
FTimelinePropertyData* SCutMainWindow::GetResourcePropertyDataPtr(FGuid GUID)
|
||
{
|
||
if (!GUID.IsValid())
|
||
return nullptr;
|
||
if (CustomInputPanel)
|
||
{
|
||
for (int32 i = 0; i < CustomInputPanel->GridPanel->GetChildren()->Num(); i++)
|
||
{
|
||
TSharedPtr<SWidget> Widget = CustomInputPanel->GridPanel->GetChildren()->GetChildAt(i);
|
||
if (StaticCastSharedPtr<SCustomInputResource>(Widget)->PropertyData.Guid == GUID)
|
||
{
|
||
return &StaticCastSharedPtr<SCustomInputResource>(Widget)->PropertyData;
|
||
}
|
||
}
|
||
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
FString SCutMainWindow::GetGroupName(TSharedPtr<IWidgetInterface> WidgetInterface)
|
||
{
|
||
for (FSingleTrackGroupInstance& Instance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
if (Instance.IsThis(WidgetInterface))
|
||
{
|
||
return Instance.GroupName;
|
||
}
|
||
}
|
||
return "";
|
||
|
||
|
||
}
|
||
|
||
void SCutMainWindow::UpdateProperties(IPropertiesInterface* Interface)
|
||
{
|
||
CustomPanel->UpdateProperties(Interface);
|
||
if (Interface)
|
||
{
|
||
CurrentSelectedPropertiesInterfaceGuid = Interface->PropertiesInterfaceGUID;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
void SCutMainWindow::ClearProperties()
|
||
{
|
||
CurrentSelectedPropertiesInterfaceGuid.Invalidate();
|
||
CustomPanel->UpdateProperties(nullptr);
|
||
}
|
||
|
||
void SCutMainWindow::DeleteAllAssetsInTimeline()
|
||
{
|
||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||
{
|
||
CutTimeline->TrackGroupInstances[i].Body->DeleteUseLessClips();
|
||
}
|
||
|
||
}
|
||
|
||
void SCutMainWindow::PreSettingBeforeSeek()
|
||
{
|
||
// OnUpdateProjector(0, true);
|
||
// OnUpdateVideo(FGuid::NewGuid(), 1920, 1080, nullptr);
|
||
OnUpdateSpotLight(0, FColor(255, 255, 255 ,255));
|
||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||
{
|
||
OnUpdatePlayers(CutTimeline->TrackGroupInstances[i].Body, FColor(255, 255, 255, 255));
|
||
}
|
||
}
|
||
|
||
void SCutMainWindow::OpenColorPanel(FLinearColor* ColorPtr)
|
||
{
|
||
TSharedPtr<SColorPanel> ColorPanel = SNew(SColorPanel).ColorPtr(ColorPtr);
|
||
GEngine->GameViewport->AddViewportWidgetContent(
|
||
ColorPanel.ToSharedRef());
|
||
|
||
|
||
}
|
||
|
||
void SCutMainWindow::AddNewCustomPreset(const FString& Name, const FPresetsCustomData CustomData)
|
||
{
|
||
FTimelinePropertyData NewPropertyData;
|
||
NewPropertyData.bIsCustomPresetData = true;
|
||
NewPropertyData.PresetsCustomData = CustomData;
|
||
NewPropertyData.Name = Name;
|
||
|
||
TSharedPtr<SCustomInputResource> CustomInputResource = SNew(SCustomInputResource).PropertyData(NewPropertyData).CustomInputPanel(CustomInputPanel.Get());
|
||
CustomInputPanel->GridPanel->AddSlot(CustomInputPanel->GridPanel->GetChildren()->Num() % 2, CustomInputPanel->GridPanel->GetChildren()->Num() / 2)
|
||
[
|
||
CustomInputResource.ToSharedRef()
|
||
];
|
||
|
||
CustomInputPanel->ResourceInst.Add(CustomInputResource);
|
||
CustomInputPanel->PropertyData.Add(NewPropertyData);
|
||
}
|
||
|
||
ESelectMode SCutMainWindow::GetSelectedMode()
|
||
{
|
||
return SelectMode;
|
||
}
|
||
|
||
SCutMainWindow* SCutMainWindow::GetSelf()
|
||
{
|
||
return this;
|
||
}
|
||
|
||
FReply SCutMainWindow::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
|
||
{
|
||
if (CommandList->ProcessCommandBindings(InKeyEvent))
|
||
{
|
||
return SCompoundWidget::OnKeyDown(MyGeometry, InKeyEvent);
|
||
}
|
||
return SCompoundWidget::OnKeyDown(MyGeometry, InKeyEvent);
|
||
}
|
||
|
||
FReply SCutMainWindow::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
|
||
return FReply::Handled().ReleaseMouseCapture();
|
||
}
|
||
|
||
FReply SCutMainWindow::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
|
||
return FReply::Handled().CaptureMouse(SharedThis(this));
|
||
}
|
||
|
||
FReply SCutMainWindow::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||
{
|
||
|
||
return FReply::Handled();
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Parent)
|
||
{
|
||
tinyxml2::XMLElement* Device = Parent->InsertNewChildElement("Device");
|
||
{
|
||
tinyxml2::XMLElement* Light = Device->InsertNewChildElement("Light");
|
||
{
|
||
// DMLightList
|
||
tinyxml2::XMLElement* DMLightList = Light->InsertNewChildElement("DMLightList");
|
||
{
|
||
|
||
int32 j = 0;
|
||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||
{
|
||
const FTrackData& TrackData = StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData;
|
||
if (TrackData.TrackType == ETrackType::SpotLightTrack)
|
||
{
|
||
|
||
|
||
tinyxml2::XMLElement* DMLight = DMLightList->InsertNewChildElement(TCHAR_TO_UTF8(*FString::Printf(TEXT("DMLight"))));
|
||
DMLight->SetAttribute("ID", TCHAR_TO_UTF8(*FString::FromInt(GetTrackID(TrackData.DeviceTrack.Guid))));
|
||
|
||
tinyxml2::XMLElement* Event_List = DMLight->InsertNewChildElement("Event_List");
|
||
|
||
TArray<FClipData> NewClipArrayData = TrackData.ClipData;
|
||
Sort(NewClipArrayData.GetData(), NewClipArrayData.Num(), [](const FClipData& A, const FClipData& B)
|
||
{
|
||
return A.ClipStartFrame < B.ClipStartFrame;
|
||
});
|
||
if (NewClipArrayData.Num() > 0)
|
||
{
|
||
if (NewClipArrayData[0].ClipStartFrame != 0)
|
||
{
|
||
tinyxml2::XMLElement* Event1 = Event_List->InsertNewChildElement("Event");
|
||
Event1->InsertNewChildElement("Value")->InsertNewText("0");
|
||
Event1->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
}
|
||
}
|
||
|
||
|
||
int32 Count = 0;
|
||
for (int32 k = 0; k < NewClipArrayData.Num(); k++)
|
||
{
|
||
const FClipData& TempClipData = NewClipArrayData[k];
|
||
tinyxml2::XMLElement* Event1 = Event_List->InsertNewChildElement("Event");
|
||
Event1->InsertNewChildElement("Value")->InsertNewText("-1");
|
||
Event1->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipStartFrame)))));
|
||
|
||
tinyxml2::XMLElement* Event2 = Event_List->InsertNewChildElement("Event");
|
||
Event2->InsertNewChildElement("Value")->InsertNewText("0");
|
||
Event2->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame)))));
|
||
Count++;
|
||
}
|
||
if (Count == 0)
|
||
{
|
||
tinyxml2::XMLElement* Event = Event_List->InsertNewChildElement("Event");
|
||
Event->InsertNewChildElement("Value")->InsertNewText("0");
|
||
Event->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
tinyxml2::XMLElement* PlayerLightList = Light->InsertNewChildElement("PlayerLightList");
|
||
{
|
||
int32 j = 0;
|
||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||
{
|
||
const FTrackData& TrackData = StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData;
|
||
if (TrackData.TrackType == ETrackType::AtomSphereLightTrack)
|
||
{
|
||
tinyxml2::XMLElement* PlayerLight = PlayerLightList->InsertNewChildElement(TCHAR_TO_UTF8(*FString::Printf(TEXT("PlayerLight"))));
|
||
PlayerLight->SetAttribute("ID", TCHAR_TO_UTF8(*FString::FromInt(GetTrackID(TrackData.DeviceTrack.Guid))));
|
||
|
||
tinyxml2::XMLElement* SpeicalEffect = PlayerLight->InsertNewChildElement("Special_Effects_List");
|
||
if (TrackData.ClipData.Num() == 0)
|
||
{
|
||
// Default
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText("-1");
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0");
|
||
}
|
||
|
||
TArray<FClipData> TempClipDataArray = TrackData.ClipData;
|
||
Sort(TempClipDataArray.GetData(), TempClipDataArray.Num(), [](const FClipData& A, const FClipData& B)
|
||
{
|
||
return A.ClipStartFrame < B.ClipStartFrame;
|
||
});
|
||
if (TempClipDataArray.Num() > 0)
|
||
{
|
||
if (TempClipDataArray[0].ClipStartFrame != 0)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipDataArray[0].ClipStartFrame)))));
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0");
|
||
}
|
||
}
|
||
for (int32 k = 0; k < TempClipDataArray.Num(); k++)
|
||
{
|
||
const FClipData& TempClipData = TempClipDataArray[k];
|
||
|
||
|
||
|
||
if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Breathe)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
GetBreatheLight(NewSpeicalEffect, TempClipData);
|
||
}
|
||
if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Flash)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
GetFlashLight(NewSpeicalEffect, TempClipData);
|
||
}
|
||
if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::Gradient)
|
||
{
|
||
GetGradientLight(SpeicalEffect, TempClipData);
|
||
}
|
||
if (TempClipData.PresetsCustomData.PresetCustomType == FPresetsCustomData::EPresetCustomType::None)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Colors[0].ToFColor(false)))));
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(TempClipData.PresetsCustomData.Colors[0].ToFColor(false)))));
|
||
|
||
const int32 Frame = TempClipData.ClipEndFrame - TempClipData.ClipStartFrame;
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(Frame)))));
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipStartFrame)))));
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), 1)));
|
||
}
|
||
|
||
if (TempClipDataArray.Num() <= k + 1)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText("-1");
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame)))));
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0");
|
||
}
|
||
else if (TempClipDataArray[k + 1].ClipStartFrame - TempClipData.ClipEndFrame != 0)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = SpeicalEffect->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")->InsertNewText("000000");
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipDataArray[k + 1].ClipStartFrame - TempClipData.ClipEndFrame)))));
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(TempClipData.ClipEndFrame)))));
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")->InsertNewText("0");
|
||
}
|
||
|
||
}
|
||
j++;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
tinyxml2::XMLElement* GuangZhenList = Light->InsertNewChildElement("GuangZhenList");
|
||
{
|
||
|
||
for (int32 k = 0; k < CutTimeline->TrackGroupInstances.Num(); k++)
|
||
{
|
||
int32 Index = 0;
|
||
const TSharedPtr<STrackHead> CurrentTrackHead = StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[k].Head);
|
||
const FTrackData& TrackData = CurrentTrackHead->TrackData;
|
||
int32 Count = 0;
|
||
if (TrackData.TrackType == ETrackType::LightArrayTrack || TrackData.TrackType == ETrackType::LightBarTrack)
|
||
{
|
||
if (GetTrackID(TrackData.DeviceTrack.Guid) == -1)
|
||
{
|
||
continue;
|
||
}
|
||
auto GuangZhen = GuangZhenList->InsertNewChildElement("GuangZhen");
|
||
GuangZhen->SetAttribute("ID", TCHAR_TO_UTF8(*FString::FromInt(GetTrackID(TrackData.DeviceTrack.Guid))));
|
||
auto GuangZhenSpecialEffectList = GuangZhen->InsertNewChildElement("SpecialEffectList");
|
||
|
||
TArray<FClipData> TempClipData = TrackData.ClipData;
|
||
Sort(TempClipData.GetData(), TempClipData.Num(), [](const FClipData& A, const FClipData& B)
|
||
{
|
||
return A.ClipStartFrame < B.ClipStartFrame;
|
||
});
|
||
if (TempClipData.Num() > 0)
|
||
{
|
||
if (TempClipData[0].ClipStartFrame != 0)
|
||
{
|
||
auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpecialEffect");
|
||
{
|
||
SpeicalEffect->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
SpeicalEffect->InsertNewChildElement("URL")->InsertNewText("");
|
||
SpeicalEffect->InsertNewChildElement("Loop")->InsertNewText("1");
|
||
SpeicalEffect->InsertNewChildElement("Mode")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
|
||
}
|
||
}
|
||
}
|
||
FString Filename;
|
||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||
{
|
||
for (const FCurtain& Curtain : CurtainGroup.Curtains)
|
||
{
|
||
if (Curtain.bIsActive)
|
||
{
|
||
Filename = Curtain.CurtainName;
|
||
}
|
||
}
|
||
}
|
||
TArray<FEncodeVideoInfo> EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr<STrackHead>(CurrentTrackHead)->TrackData, *(FGlobalData::ExportPath / "PSAF" / Filename));
|
||
for (int32 j = 0; j < EncodeVideoInfos.Num(); j++)
|
||
{
|
||
auto SpeicalEffect = GuangZhenSpecialEffectList->InsertNewChildElement("SpecialEffect");
|
||
{
|
||
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(!EncodeVideoInfos[j].ClipData.bIsCycle)));
|
||
}
|
||
auto SpeicalEffectMode = SpeicalEffect->InsertNewChildElement("Mode");
|
||
{
|
||
SpeicalEffectMode->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
|
||
}
|
||
}
|
||
Count++;
|
||
}
|
||
if (Count == 0)
|
||
{
|
||
GuangZhenSpecialEffectList->InsertNewText("");
|
||
}
|
||
Index++;
|
||
}
|
||
}
|
||
}
|
||
tinyxml2::XMLElement* RoomLight = Light->InsertNewChildElement("RoomLight");
|
||
{
|
||
RoomLight->InsertNewText("0");
|
||
}
|
||
tinyxml2::XMLElement* JLight = Light->InsertNewChildElement("JLight");
|
||
{
|
||
JLight->InsertNewText("0");
|
||
}
|
||
tinyxml2::XMLElement* Incense_Machine = Light->InsertNewChildElement("Incense_Machine");
|
||
{
|
||
Incense_Machine->InsertNewText("0");
|
||
}
|
||
}
|
||
}
|
||
return Device;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo)
|
||
{
|
||
int32 TempProjectorID = 0;
|
||
for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
const TSharedPtr<STrackHead> TempTrackHead = StaticCastSharedPtr<STrackHead>(SingleTrackGroupInstance.Head);
|
||
if (TempTrackHead->TrackData.TrackType != ETrackType::ProjectorTrack)
|
||
{
|
||
continue;
|
||
}
|
||
if (GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid) != -1)
|
||
{
|
||
TempProjectorID = GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid);
|
||
}
|
||
}
|
||
|
||
|
||
tinyxml2::XMLElement* Video = Parent->InsertNewChildElement("Video");
|
||
tinyxml2::XMLElement* URL = Video->InsertNewChildElement("URL");
|
||
{
|
||
if (EncodeVideoInfo.EncodedVideoName == "")
|
||
{
|
||
URL->InsertNewText("");
|
||
}
|
||
else
|
||
{
|
||
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(!EncodeVideoInfo.ClipData.bIsCycle)));
|
||
}
|
||
tinyxml2::XMLElement* Mode = Video->InsertNewChildElement("Mode");
|
||
{
|
||
Mode->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
|
||
}
|
||
|
||
|
||
tinyxml2::XMLElement* VolumeEventList = Video->InsertNewChildElement("VolumeEventList");
|
||
{
|
||
if (EncodeVideoInfo.TrackData.IsMute)
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
VolumeEvent->InsertNewChildElement("Value")->InsertNewText("0");
|
||
}
|
||
else
|
||
{
|
||
if (EncodeVideoInfo.ClipData.VolumeData.Num() > 0)
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
VolumeEvent->InsertNewChildElement("Value")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EncodeVideoInfo.ClipData.VolumeData[0].Volume)));
|
||
}
|
||
else
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
VolumeEvent->InsertNewChildElement("Value")->InsertNewText("0");
|
||
}
|
||
|
||
}
|
||
for (const FVolumeData& Volume : EncodeVideoInfo.ClipData.VolumeData)
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
{
|
||
tinyxml2::XMLElement* VolumeEventTimeCode = VolumeEvent->InsertNewChildElement("TimeCode");
|
||
tinyxml2::XMLElement* VolumeEventValue = VolumeEvent->InsertNewChildElement("Value");
|
||
|
||
VolumeEventTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(FGlobalData::GetTimeData(Volume.VolumeOffset))));
|
||
VolumeEventValue->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Volume.Volume)));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
tinyxml2::XMLElement* ProjectorID = Video->InsertNewChildElement("ProjectorID");
|
||
{
|
||
ProjectorID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TempProjectorID)));
|
||
}
|
||
|
||
|
||
|
||
tinyxml2::XMLElement* ProjectorEventList = Video->InsertNewChildElement("ProjectorEventList");
|
||
{
|
||
|
||
struct FProjectorEvent
|
||
{
|
||
FString TimeCode;
|
||
int32 Value;
|
||
};
|
||
TArray<FProjectorEvent> ProjectorEvents;
|
||
|
||
|
||
|
||
ProjectorEvents.Add(FProjectorEvent{ "0", 1 });
|
||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||
{
|
||
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::ProjectorTrack)
|
||
{
|
||
for (FClipData& ClipData : StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.ClipData)
|
||
{
|
||
if (ClipData.ClipStartFrame > EncodeVideoInfo.ClipStartFrame - 10 && ClipData.ClipEndFrame < EncodeVideoInfo.ClipEndFrame + 10)
|
||
{
|
||
int32 ShowProjector = 0;
|
||
ClipData.PresetType == EPresetType::EnableProjector ? ShowProjector = 1 : ShowProjector = 0;
|
||
ProjectorEvents.Add({FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame - EncodeVideoInfo.ClipStartFrame)), ShowProjector});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Sort(ProjectorEvents.GetData(), ProjectorEvents.Num(), [](const FProjectorEvent& ProjectorEventA, const FProjectorEvent& ProjectorEventB) {
|
||
return FCString::Atoi(*ProjectorEventA.TimeCode) < FCString::Atoi(*ProjectorEventB.TimeCode);
|
||
});
|
||
|
||
for (const FProjectorEvent& Event : ProjectorEvents)
|
||
{
|
||
tinyxml2::XMLElement* ProjectorEvent1 = ProjectorEventList->InsertNewChildElement("ProjectorEvent");
|
||
{
|
||
tinyxml2::XMLElement* ProjectorTimeCode = ProjectorEvent1->InsertNewChildElement("TimeCode");
|
||
{
|
||
ProjectorTimeCode->InsertNewText(TCHAR_TO_UTF8(*Event.TimeCode));
|
||
}
|
||
tinyxml2::XMLElement* Value = ProjectorEvent1->InsertNewChildElement("Value");
|
||
{
|
||
Value->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Event.Value)));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
return Parent;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo)
|
||
{
|
||
FTrackData LeftTrackData;
|
||
FTrackData RightTrackData;
|
||
int32 TempSoundID = 0;
|
||
for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
const TSharedPtr<STrackHead> TempTrackHead = StaticCastSharedPtr<STrackHead>(SingleTrackGroupInstance.Head);
|
||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrack)
|
||
LeftTrackData = TempTrackHead->TrackData;
|
||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrackR)
|
||
{
|
||
if (GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid) != -1)
|
||
{
|
||
TempSoundID = GetTrackID(TempTrackHead->TrackData.DeviceTrack.Guid);
|
||
}
|
||
RightTrackData = TempTrackHead->TrackData;
|
||
}
|
||
|
||
}
|
||
|
||
tinyxml2::XMLElement* Sound = Parent->InsertNewChildElement("Sound");
|
||
{
|
||
Sound->InsertNewChildElement("RotationSpeakerID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(TempSoundID)));
|
||
if (EncodeVideoInfo.EncodedVideoName == "")
|
||
{
|
||
Sound->InsertNewChildElement("URL")->InsertNewText("");
|
||
}
|
||
else
|
||
{
|
||
Sound->InsertNewChildElement("URL")->InsertNewText(TCHAR_TO_UTF8(*(FPaths::GetBaseFilename(EncodeVideoInfo.EncodedVideoName) + TEXT(".mp3"))));
|
||
}
|
||
|
||
|
||
|
||
tinyxml2::XMLElement* VolumeEventList = Sound->InsertNewChildElement("VolumeEventList");
|
||
{
|
||
if (EncodeVideoInfo.TrackData.IsMute)
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
VolumeEvent->InsertNewChildElement("Value")->InsertNewText("0");
|
||
}
|
||
else
|
||
{
|
||
if (EncodeVideoInfo.ClipData.VolumeData.Num() > 0)
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
VolumeEvent->InsertNewChildElement("Value")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EncodeVideoInfo.ClipData.VolumeData[0].Volume)));
|
||
}
|
||
else
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0");
|
||
VolumeEvent->InsertNewChildElement("Value")->InsertNewText("0");
|
||
}
|
||
|
||
}
|
||
for (const FVolumeData& Volume : EncodeVideoInfo.ClipData.VolumeData)
|
||
{
|
||
tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent");
|
||
{
|
||
tinyxml2::XMLElement* VolumeEventTimeCode = VolumeEvent->InsertNewChildElement("TimeCode");
|
||
tinyxml2::XMLElement* VolumeEventValue = VolumeEvent->InsertNewChildElement("Value");
|
||
|
||
VolumeEventTimeCode->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(FGlobalData::GetTimeData(Volume.VolumeOffset))));
|
||
VolumeEventValue->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Volume.Volume)));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
Sound->InsertNewChildElement("Loop")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(!EncodeVideoInfo.ClipData.bIsCycle)));
|
||
Sound->InsertNewChildElement("Mode")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
|
||
Sound->InsertNewChildElement("Round")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(1)));
|
||
Sound->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FUtils::GetMsFromString(EncodeVideoInfo.EncodedVideoTimeCode)));
|
||
|
||
tinyxml2::XMLElement* RotationSpeakerEventList = Sound->InsertNewChildElement("RotationSpeakerEventList");
|
||
{
|
||
tinyxml2::XMLElement* RotationSpeakerEvent = RotationSpeakerEventList->InsertNewChildElement("RotationSpeakerEvent");
|
||
{
|
||
tinyxml2::XMLElement* RotationSpeakerEventTimeCode = RotationSpeakerEvent->InsertNewChildElement("TimeCode");
|
||
tinyxml2::XMLElement* RotationSpeakerEventValue = RotationSpeakerEvent->InsertNewChildElement("Value");
|
||
|
||
|
||
RotationSpeakerEventTimeCode->InsertNewText("0");
|
||
RotationSpeakerEventValue->InsertNewText("1");
|
||
}
|
||
}
|
||
}
|
||
return Parent;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetVideoListElement(tinyxml2::XMLElement* Parent)
|
||
{
|
||
tinyxml2::XMLElement* VideoList = Parent->InsertNewChildElement("VideoList");
|
||
int32 Count = 0;
|
||
for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++)
|
||
{
|
||
if (StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::VideoTrack)
|
||
{
|
||
FString Filename;
|
||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||
{
|
||
for (const FCurtain& Curtain : CurtainGroup.Curtains)
|
||
{
|
||
if (Curtain.bIsActive)
|
||
{
|
||
Filename = Curtain.CurtainName;
|
||
}
|
||
}
|
||
}
|
||
FString NewExportFilePath = FGlobalData::ExportPath / "Video" / Filename;
|
||
// GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::White, NewExportFilePath);
|
||
TArray<FEncodeVideoInfo> EncodeVideoInfos =
|
||
FUtils::TrackEncodeVideo(StaticCastSharedPtr<STrackHead>(CutTimeline->TrackGroupInstances[i].Head)->TrackData, NewExportFilePath);
|
||
for (const FEncodeVideoInfo EncodeVideoInfo : EncodeVideoInfos)
|
||
{
|
||
GetVideoElement(VideoList, EncodeVideoInfo);
|
||
Count++;
|
||
}
|
||
}
|
||
}
|
||
if (Count == 0)
|
||
{
|
||
VideoList->InsertNewText("");
|
||
}
|
||
return VideoList;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* Parent)
|
||
{
|
||
tinyxml2::XMLElement* AudioList = Parent->InsertNewChildElement("SoundList");
|
||
{
|
||
int32 Count = 0;
|
||
FTrackData LeftTrackData;
|
||
FTrackData RightTrackData;
|
||
for (FSingleTrackGroupInstance& SingleTrackGroupInstance : CutTimeline->TrackGroupInstances)
|
||
{
|
||
const TSharedPtr<STrackHead> TempTrackHead = StaticCastSharedPtr<STrackHead>(SingleTrackGroupInstance.Head);
|
||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrack)
|
||
LeftTrackData = TempTrackHead->TrackData;
|
||
if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrackR)
|
||
RightTrackData = TempTrackHead->TrackData;
|
||
}
|
||
|
||
TArray<FClipData> SavedClipData = LeftTrackData.ClipData;
|
||
if (SavedClipData.Num() > 0)
|
||
{
|
||
Sort(SavedClipData.GetData(), SavedClipData.Num(), [](const FClipData& ClipDataA, const FClipData& ClipDataB)
|
||
{
|
||
return ClipDataA.ClipStartFrame < ClipDataB.ClipStartFrame;
|
||
});
|
||
if (SavedClipData[0].ClipStartFrame != 0 && SavedClipData[0].bIsVirtual == false)
|
||
{
|
||
GetSoundElement(AudioList, {});
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
bool bIsVirtual = false;
|
||
for (FClipData& ClipData : LeftTrackData.ClipData)
|
||
{
|
||
if (ClipData.bIsVirtual)
|
||
{
|
||
bIsVirtual = true;
|
||
const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName;
|
||
FEncodeVideoInfo EncodeVideoInfo;
|
||
EncodeVideoInfo.EncodedVideoName = VirtualFileName;
|
||
GetSoundElement(AudioList, EncodeVideoInfo);
|
||
}
|
||
}
|
||
if (!bIsVirtual)
|
||
{
|
||
for (FClipData& ClipData : RightTrackData.ClipData)
|
||
{
|
||
if (ClipData.bIsVirtual)
|
||
{
|
||
bIsVirtual = true;
|
||
const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName;
|
||
FEncodeVideoInfo EncodeVideoInfo;
|
||
EncodeVideoInfo.EncodedVideoName = VirtualFileName;
|
||
GetSoundElement(AudioList, EncodeVideoInfo);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (!bIsVirtual)
|
||
{
|
||
const FString LeftFilename = GetCurrentSelectFileName() + TEXT("_L");
|
||
const FString RightFilename = GetCurrentSelectFileName() + TEXT("_R");
|
||
const FString LeftNewExportFilePath = FUtils::GetProjectTempPath() / "Sound" / LeftFilename;
|
||
const FString RightNewExportFilePath = FUtils::GetProjectTempPath() / "Sound" / RightFilename;
|
||
const FEncodeVideoInfo LeftEncodeVideoInfos = FUtils::TrackEncodeAudio(LeftTrackData, LeftNewExportFilePath);
|
||
const FEncodeVideoInfo RightEncodeVideoInfos = FUtils::TrackEncodeAudio(RightTrackData, RightNewExportFilePath);
|
||
|
||
const FString ExportFilename = FGlobalData::ExportPath / "Sound" / GetCurrentSelectFileName();
|
||
const FEncodeVideoInfo End = FUtils::CombineAudio(LeftEncodeVideoInfos, RightEncodeVideoInfos, ExportFilename);
|
||
|
||
GetSoundElement(AudioList, End);
|
||
}
|
||
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetProcessA(tinyxml2::XMLElement* Parent, FCurtainGroup* CurtainGroup)
|
||
{
|
||
tinyxml2::XMLElement* ProcessA = Parent->InsertNewChildElement("ProcessA");
|
||
ProcessA->SetAttribute("Name", TCHAR_TO_UTF8(*CurtainGroup->GroupName));
|
||
for (int32 i = 0; i < CurtainGroup->Curtains.Num(); i++)
|
||
{
|
||
CurtainPanel->DeSelectedAll();
|
||
CurtainGroup->Curtains[i].bIsActive = true;
|
||
OpenTimeline(CurtainGroup->Curtains[i].TimelineInfo.CurrentOpenFullPath, true, true);
|
||
GetProcessB(ProcessA, &CurtainGroup->Curtains[i]);
|
||
}
|
||
if (CurtainGroup->Curtains.Num() == 0)
|
||
{
|
||
ProcessA->InsertNewText("");
|
||
}
|
||
return ProcessA;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, FCurtain* Curtain)
|
||
{
|
||
tinyxml2::XMLElement* ProcessB = Parent->InsertNewChildElement("ProcessB");
|
||
ProcessB->SetAttribute("Name", TCHAR_TO_UTF8(*Curtain->CurtainName));
|
||
ProcessB->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Curtain->Step)));
|
||
ProcessB->InsertNewChildElement("AutoNext")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0)));
|
||
ProcessB->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(-1)));
|
||
|
||
GetSoundListElement(ProcessB);
|
||
ProcessB->InsertEndChild(GetDeviceElement(ProcessB));
|
||
GetVideoListElement(ProcessB);
|
||
|
||
// 非必须项
|
||
tinyxml2::XMLElement* Identity_SpecialEffects = ProcessB->InsertNewChildElement("Identity_SpecialEffects");
|
||
{
|
||
tinyxml2::XMLElement* SpecialEffects = Identity_SpecialEffects->InsertNewChildElement("SpecialEffects");
|
||
SpecialEffects->InsertNewChildElement("PlayerID")->InsertNewText("1");
|
||
SpecialEffects->InsertNewChildElement("SpecialEffectID")->InsertNewText("");
|
||
}
|
||
tinyxml2::XMLElement* IsGlobal = ProcessB->InsertNewChildElement("IsGlobal");
|
||
{
|
||
IsGlobal->InsertNewText("1");
|
||
}
|
||
tinyxml2::XMLElement* State = ProcessB->InsertNewChildElement("State");
|
||
{
|
||
State->InsertNewText("0");
|
||
}
|
||
tinyxml2::XMLElement* EnableCard = ProcessB->InsertNewChildElement("EnableCard");
|
||
{
|
||
int32 Count = 0;
|
||
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); i++)
|
||
{
|
||
|
||
if (!EffectCardsPanel->EffectCardGroups[i].bIsDedicated)
|
||
{
|
||
if (EffectCardsPanel->EffectCardGroups[i].UsedCurtains.Contains(Curtain->CurtainUUID) ||
|
||
EffectCardsPanel->EffectCardGroups[i].UsedCurtains.Contains(FStringWithGUID()))
|
||
{
|
||
tinyxml2::XMLElement* SerialNumber = EnableCard->InsertNewChildElement("SerialNumber");
|
||
SerialNumber->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].ID)));
|
||
Count++;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
for (int32 j = 0 ; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++)
|
||
{
|
||
if (EffectCardsPanel->EffectCardGroups[i].Cards[j].UsedCurtains.Contains(Curtain->CurtainUUID) ||
|
||
EffectCardsPanel->EffectCardGroups[i].Cards[j].UsedCurtains.Contains(FStringWithGUID()))
|
||
{
|
||
tinyxml2::XMLElement* SerialNumber = EnableCard->InsertNewChildElement("SerialNumber");
|
||
SerialNumber->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(EffectCardsPanel->EffectCardGroups[i].Cards[j].ID)));
|
||
Count++;
|
||
}
|
||
}
|
||
|
||
}
|
||
if (Count == 0)
|
||
{
|
||
EnableCard->InsertNewText("");
|
||
}
|
||
|
||
}
|
||
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)
|
||
{
|
||
OpenTimeline(FUtils::GroupFullPath(EffectCardsPanel->EffectCardGroups[i].Guid.ToString()), true, true);
|
||
CurrentSelectedPropertiesInterfaceGuid = 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].Guid.ToString()), true, true);
|
||
CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid;
|
||
GetSpecialEffect(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i].Cards[j]);
|
||
SpecialEffectID++;
|
||
}
|
||
|
||
SpecialEffectID++;
|
||
}
|
||
|
||
if (SpecialEffectID == 0)
|
||
{
|
||
SpecialEffectsList->InsertNewText("");
|
||
}
|
||
return SpecialEffectsList;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectGroup(tinyxml2::XMLElement* Parent, FEffectCardGroup* Group)
|
||
{
|
||
tinyxml2::XMLElement* SpecialEffect = Parent->InsertNewChildElement("SpecialEffect");
|
||
tinyxml2::XMLElement* Effect = SpecialEffect->InsertNewChildElement("Effect");
|
||
Effect->SetAttribute("Name", TCHAR_TO_UTF8(*Group->GroupName));
|
||
|
||
tinyxml2::XMLElement* ID = Effect->InsertNewChildElement("ID");
|
||
{
|
||
ID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Group->ID)));
|
||
}
|
||
tinyxml2::XMLElement* AutoNext = Effect->InsertNewChildElement("AutoNext");
|
||
AutoNext->InsertNewText("0");
|
||
|
||
Effect->InsertNewChildElement("TimeLength")->InsertNewText("-1");
|
||
|
||
GetSoundListElement(Effect);
|
||
GetDeviceElement(Effect);
|
||
GetVideoListElement(Effect);
|
||
tinyxml2::XMLElement* IsGlobal = Effect->InsertNewChildElement("IsGlobal");
|
||
{
|
||
int32 bIsGlobal = 0;
|
||
Group->UsedCurtains.Contains(FStringWithGUID(TEXT("全局"), FGuid())) ? bIsGlobal = 1 : bIsGlobal = 0;
|
||
IsGlobal->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(bIsGlobal)));
|
||
}
|
||
tinyxml2::XMLElement* State = Effect->InsertNewChildElement("State");
|
||
{
|
||
State->InsertNewText("0");
|
||
}
|
||
|
||
GetTrigger(SpecialEffect);
|
||
|
||
return Effect;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffect(tinyxml2::XMLElement* Parent, FEffectCardProperty* Effect)
|
||
{
|
||
tinyxml2::XMLElement* SpecialEffect = Parent->InsertNewChildElement("SpecialEffect");
|
||
tinyxml2::XMLElement* Effectxml = SpecialEffect->InsertNewChildElement("Effect");
|
||
Effectxml->SetAttribute("Name", TCHAR_TO_UTF8(*Effect->Name));
|
||
|
||
tinyxml2::XMLElement* ID = Effectxml->InsertNewChildElement("ID");
|
||
{
|
||
ID->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Effect->ID)));
|
||
}
|
||
|
||
tinyxml2::XMLElement* AutoNext = Effectxml->InsertNewChildElement("AutoNext");
|
||
tinyxml2::XMLElement* TimeLength = Effectxml->InsertNewChildElement("TimeLength");
|
||
TimeLength->InsertNewText("-1");
|
||
AutoNext->InsertNewText("0");
|
||
GetSoundListElement(Effectxml);
|
||
GetDeviceElement(Effectxml);
|
||
GetVideoListElement(Effectxml);
|
||
tinyxml2::XMLElement* IsGlobal = Effectxml->InsertNewChildElement("IsGlobal");
|
||
{
|
||
int32 bIsGlobal = 0;
|
||
Effect->UsedCurtains.Contains(FStringWithGUID(TEXT("全局"), FGuid())) ? bIsGlobal = 1 : bIsGlobal = 0;
|
||
IsGlobal->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(bIsGlobal)));
|
||
}
|
||
tinyxml2::XMLElement* State = Effectxml->InsertNewChildElement("State");
|
||
{
|
||
State->InsertNewText("0");
|
||
}
|
||
|
||
GetTrigger(SpecialEffect);
|
||
return Effectxml;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetTrigger(tinyxml2::XMLElement* Parent)
|
||
{
|
||
tinyxml2::XMLElement* Trigger = Parent->InsertNewChildElement("Trigger");
|
||
Trigger->InsertNewChildElement("TriggerMode")->InsertNewText("");
|
||
Trigger->InsertNewChildElement("SerialNumberList")->InsertNewChildElement("SerialNumber")->InsertNewText("");
|
||
Trigger->InsertNewChildElement("SerialNumber")->InsertNewText("");
|
||
tinyxml2::XMLElement* KeyCode = Trigger->InsertNewChildElement("KeyCode");
|
||
KeyCode->InsertNewChildElement("CTRL")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("SHIFT")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("ALT")->InsertNewText("");
|
||
KeyCode->InsertNewChildElement("KEY")->InsertNewText("");
|
||
Trigger->InsertNewChildElement("ActionMode")->InsertNewText("");
|
||
return Trigger;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetBreatheLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData)
|
||
{
|
||
Parent->InsertNewChildElement("Mode")->InsertNewText("3");
|
||
Parent->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[0].ToFColor(false)))));
|
||
Parent->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(FLinearColor::Black.ToFColor(false)))));
|
||
float PerLength = (ClipData.PresetsCustomData.Time / ClipData.PresetsCustomData.Times);
|
||
Parent->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(PerLength * 1000))));
|
||
Parent->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame)))));
|
||
Parent->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), static_cast<int32>(PerLength * 1000))));
|
||
return nullptr;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetFlashLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData)
|
||
{
|
||
Parent->InsertNewChildElement("Mode")->InsertNewText("2");
|
||
Parent->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[0].ToFColor(false)))));
|
||
Parent->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(FLinearColor::Black.ToFColor(false)))));
|
||
float PerLength = (ClipData.PresetsCustomData.Time / ClipData.PresetsCustomData.Times);
|
||
Parent->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(ClipData.PresetsCustomData.Time * 1000))));
|
||
Parent->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame)))));
|
||
Parent->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), static_cast<int32>(PerLength * 500))));
|
||
return nullptr;
|
||
}
|
||
|
||
tinyxml2::XMLElement* SCutMainWindow::GetGradientLight(tinyxml2::XMLElement* Parent, const FClipData& ClipData)
|
||
{
|
||
if (ClipData.PresetsCustomData.Cursors.Num() == 0)
|
||
return nullptr;
|
||
|
||
if (ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset > 0)
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = Parent->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[0].Color.ToFColor(false)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[0].Color.ToFColor(false)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[0].CursorFrameOffset)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")
|
||
->InsertNewText("0");
|
||
}
|
||
|
||
int32 Index = 0;
|
||
const int32 CursorNum = ClipData.PresetsCustomData.Cursors.Num();
|
||
for (const FCursorData& CursorData : ClipData.PresetsCustomData.Cursors)
|
||
{
|
||
if (Index == CursorNum - 1 && CursorData.CursorFrameOffset <= (ClipData.ClipEndFrame - ClipData.ClipStartFrame))
|
||
{
|
||
tinyxml2::XMLElement* NewSpeicalEffect = Parent->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("0");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index].Color.ToFColor(false)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index].Color.ToFColor(false)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(FGlobalData::GetTimeData(
|
||
(ClipData.ClipEndFrame - ClipData.ClipStartFrame) -
|
||
ClipData.PresetsCustomData.Cursors[Index].CursorFrameOffset)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + ClipData.PresetsCustomData.Cursors[Index].CursorFrameOffset)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")
|
||
->InsertNewText("0");
|
||
break;
|
||
}
|
||
tinyxml2::XMLElement* NewSpeicalEffect = Parent->InsertNewChildElement("Special_Effect");
|
||
NewSpeicalEffect->InsertNewChildElement("Mode")->InsertNewText("1");
|
||
NewSpeicalEffect->InsertNewChildElement("InitialColor")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index].Color.ToFColor(false)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("EndColor")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),*FUtils::Color2Hex3(ClipData.PresetsCustomData.Cursors[Index + 1].Color.ToFColor(false)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("TimeLength")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(FGlobalData::GetTimeData(
|
||
ClipData.PresetsCustomData.Cursors[Index + 1].CursorFrameOffset - CursorData.CursorFrameOffset)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("TimeCode")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame + CursorData.CursorFrameOffset)))));
|
||
|
||
NewSpeicalEffect->InsertNewChildElement("Cycle")
|
||
->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"),
|
||
*FUtils::GetMsFromString(
|
||
FGlobalData::GetTimeData(ClipData.PresetsCustomData.Cursors[Index + 1].CursorFrameOffset - CursorData.CursorFrameOffset)))));
|
||
Index++;
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
FGuid SCutMainWindow::GetCurrentSelectCurtain() const
|
||
{
|
||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||
{
|
||
for (const FCurtain& Curtain : CurtainGroup.Curtains)
|
||
{
|
||
if (Curtain.bIsActive)
|
||
{
|
||
return Curtain.CurtainUUID;
|
||
}
|
||
}
|
||
}
|
||
return FGuid();
|
||
}
|
||
|
||
FTimelineInfo SCutMainWindow::GetCurrentSelectCurtainTimelineInfo() const
|
||
{
|
||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||
{
|
||
for (const FCurtain& Curtain : CurtainGroup.Curtains)
|
||
{
|
||
if (Curtain.bIsActive)
|
||
{
|
||
return Curtain.TimelineInfo;
|
||
}
|
||
}
|
||
}
|
||
return FTimelineInfo();
|
||
}
|
||
|
||
bool SCutMainWindow::IsSelectCurtain() const
|
||
{
|
||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||
{
|
||
for (const FCurtain& Curtain : CurtainGroup.Curtains)
|
||
{
|
||
if (Curtain.bIsActive)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void SCutMainWindow::DeselectAll()
|
||
{
|
||
for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups)
|
||
{
|
||
for (FCurtain& Curtain : CurtainGroup.Curtains)
|
||
{
|
||
Curtain.bIsActive = false;
|
||
}
|
||
}
|
||
for (int32 i = 0; i < EffectCardsPanel->EffectCardGroups.Num(); ++i)
|
||
{
|
||
for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); ++j)
|
||
{
|
||
if (EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive)
|
||
{
|
||
EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
CurtainPanel->CallRender();
|
||
EffectCardsPanel->CallRender();
|
||
}
|
||
|
||
int32 SCutMainWindow::GetTrackID(FGuid Guid) const
|
||
{
|
||
const int32* Index = IDList.Find(Guid);
|
||
const int32 NewIndex = Index != nullptr ? *Index : -1;
|
||
return NewIndex;
|
||
}
|
||
|
||
FRunnable* SCutMainWindow::GetThread(const FGuid& Guid)
|
||
{
|
||
if (!Threads.Find(Guid))
|
||
{
|
||
return nullptr;
|
||
}
|
||
return *Threads.Find(Guid);
|
||
}
|
||
|
||
void SCutMainWindow::AddThread(const FGuid& Guid, FRunnable* InSoundThread)
|
||
{
|
||
if (!Threads.Find(Guid))
|
||
{
|
||
Threads.Add(Guid, InSoundThread);
|
||
}
|
||
else
|
||
{
|
||
FRunnable* Thread = *Threads.Find(Guid);
|
||
Thread->Stop();
|
||
delete Thread;
|
||
Threads[Guid] = InSoundThread;
|
||
}
|
||
}
|
||
|
||
void SCutMainWindow::RemoveThread(const FGuid& Guid)
|
||
{
|
||
FRunnable* Thread = *Threads.Find(Guid);
|
||
Thread->Stop();
|
||
delete Thread;
|
||
Threads.Remove(Guid);
|
||
}
|
||
|
||
|
||
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|