// 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("NormalText"); MainBarTextStyle.SetFontSize(14); FTextBlockStyle TitleBarTextStyle = FAppStyle::GetWidgetStyle("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 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(); 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(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(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 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 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 TrackBody = StaticCastSharedPtr(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 TrackBody = StaticCastSharedPtr(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(TrackGroupInstance.GetHead())->TrackData.TrackType == ETrackType::AtomSphereLightTrack) { LastGroupName = TrackGroupInstance.GroupName; FString NewName = TrackGroupInstance.GroupName + FString::FromInt(i); TSharedPtr 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 DragDropOperation = DragDropEvent.GetOperationAs(); DragDropOperator::GetDragDropOperator()->CloseCursorDecorator(); if (DragDropOperation->DragDropType == FCutDragDropBase::EType::SelectClips) { DragDropOperator::GetDragDropOperator()->OnDrop(MyGeometry, DragDropEvent, nullptr); } if (DragDropOperation->DragDropType == FCutDragDropBase::EType::Clip2Clip) { TSharedPtr Body = StaticCastSharedPtr(DragDropOperation->OverrideWidget); DragDropOperator::GetDragDropOperator()->OnDrop(MyGeometry, DragDropEvent, Body); Body->CallRender(); } else if (DragDropOperation->DragDropType == FCutDragDropBase::EType::TrackClip) { TSharedPtr Body = StaticCastSharedPtr(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 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& LightArray) { ICutMainWidgetInterface::OnUpdateLightArray(LightArray); StatePanel->LightArray->LightGridColors = LightArray; } void SCutMainWindow::OnUpdatePlayers(TSharedPtr TrackBody, FColor PlayerColor) { ICutMainWidgetInterface::OnUpdatePlayers(TrackBody, PlayerColor); for (int32 i = 0; i < PlayerLightsSlateInstances.Num(); i++) { const FString PlayerLightName = StaticCastSharedPtr(TrackBody)->TrackHead->TrackData.TrackName; if ( StaticCastSharedPtr(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(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 Data; // 找出文件夹内后缀为.cutlink的文件 TArray 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 NewTrackHead = SNew(STrackHead).TrackData(TrackData).CutTimeline(CutTimeline.ToSharedRef()).MainWidgetInterface(this).GroupName(CutTimeline->DeviceTrackGroups[i].GroupName); const TSharedPtr 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 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 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 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 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 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 Widget = CustomInputPanel->GridPanel->GetChildren()->GetChildAt(i); if (StaticCastSharedPtr(Widget)->PropertyData.Guid == GUID) { return &StaticCastSharedPtr(Widget)->PropertyData; } } } return nullptr; } FString SCutMainWindow::GetGroupName(TSharedPtr 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 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 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(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 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(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 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 CurrentTrackHead = StaticCastSharedPtr(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 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 EncodeVideoInfos = FUtils::ExportPsaf(StaticCastSharedPtr(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 TempTrackHead = StaticCastSharedPtr(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 ProjectorEvents; ProjectorEvents.Add(FProjectorEvent{ "0", 1 }); for (int32 i = 0; i < CutTimeline->TrackGroupInstances.Num(); i++) { if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::ProjectorTrack) { for (FClipData& ClipData : StaticCastSharedPtr(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 TempTrackHead = StaticCastSharedPtr(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(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 EncodeVideoInfos = FUtils::TrackEncodeVideo(StaticCastSharedPtr(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 TempTrackHead = StaticCastSharedPtr(SingleTrackGroupInstance.Head); if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrack) LeftTrackData = TempTrackHead->TrackData; if (TempTrackHead->TrackData.TrackType == ETrackType::AudioTrackR) RightTrackData = TempTrackHead->TrackData; } TArray 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(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(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