From 5953ee70dc8193374d14bc6dffc2034465e9b802 Mon Sep 17 00:00:00 2001 From: Sch <3516520171@qq.com> Date: Wed, 23 Aug 2023 09:07:11 +0800 Subject: [PATCH] 8.23 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 右上角菜单 O 2. 新建项目窗口会关闭 O 3. 左上角项目名同步 O 4. 添加角色组氛围灯同步显示 O 5. 时间轴没办法往下滚动 O 6. 拖拽时候要有拖拽效果 7. 太长的话底下播放条消失了 O 8. 默认情况下不是显示默认设备面板 O 9. 点击到文字的时候也要能选中幕 O 10. 显示轨道时间码 O 11. 特效卡选中后并没有切换幕 O 12. 切换按键上显示光阵和视频 O 13. 删除左上角debug信息 O 14. 修改片段层级显示颜色 O 15. 显示边缘拖拽效果 O 16. 优化颜色面板ui O 17. 删除特效组 O 18. 对着时间轴滑动可以左右移动 O 19. 导入音频崩溃 20.从文件夹里拖拽文件今日会崩溃 O 21. 导入时多选素材 O 22. 时间轴每一秒设置一个大帧 O 23. 自动保存 O --- Cut5.sln | 60 ++++--- Resources/Music.png | Bin 0 -> 29788 bytes Source/Cut5/Interface/SoundInterface.cpp | 13 +- Source/Cut5/MainHUD.cpp | 2 +- Source/Cut5/Utils/FFMPEGUtils.cpp | 29 +++- Source/Cut5/Utils/Utils.cpp | 2 +- .../Cut5/Widgets/Commands/ShortcunCommands.h | 5 +- .../Widgets/Commands/ShortcutCommands.cpp | 20 ++- Source/Cut5/Widgets/Curtain/SCurtain.cpp | 69 +++++--- Source/Cut5/Widgets/Curtain/SCurtain.h | 3 + Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp | 2 +- Source/Cut5/Widgets/DefineGlobal.h | 8 +- .../DragDropOperator/DragDropOperator.cpp | 65 ++++++- .../DragDropOperator/DragDropOperator.h | 4 + Source/Cut5/Widgets/FX/SEffectCard.cpp | 2 +- Source/Cut5/Widgets/FX/SEffectCardGroup.cpp | 76 +++++++- Source/Cut5/Widgets/FX/SEffectCardGroup.h | 6 + Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp | 23 ++- .../Cut5/Widgets/MicroWidgets/SColorPanel.cpp | 15 +- .../Widgets/MicroWidgets/SNewProjectTips.cpp | 6 +- Source/Cut5/Widgets/SCustomInputPanel.cpp | 120 ++++++------- Source/Cut5/Widgets/SCustomInputResource.cpp | 21 ++- Source/Cut5/Widgets/SCustomInputResource.h | 5 +- Source/Cut5/Widgets/SCutMainWindow.cpp | 164 ++++++++++++++---- Source/Cut5/Widgets/SCutMainWindow.h | 10 +- Source/Cut5/Widgets/SCutTimeline.cpp | 22 ++- Source/Cut5/Widgets/SCutTimeline.h | 2 + Source/Cut5/Widgets/SStartMenu.cpp | 4 + Source/Cut5/Widgets/STimelineClip.cpp | 110 ++++++++---- Source/Cut5/Widgets/STimelineClip.h | 6 + .../Cut5/Widgets/STimelinePropertyPanel.cpp | 2 +- Source/Cut5/Widgets/STimelineTick.cpp | 9 +- .../Cut5/Widgets/StatePanel/SStatePanel.cpp | 13 +- Source/Cut5/Widgets/StatePanel/SStatePanel.h | 2 +- 34 files changed, 669 insertions(+), 231 deletions(-) create mode 100644 Resources/Music.png diff --git a/Cut5.sln b/Cut5.sln index 6b74737..8e330d5 100644 --- a/Cut5.sln +++ b/Cut5.sln @@ -7,49 +7,67 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{233774 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Games", "Games", "{DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{6EE39883-7339-3FB6-AD82-931FB137D37F}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{B95E7D0E-DB45-3765-9058-E00EBBC4B157}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{AF5A253A-0F37-38CE-8998-45CA936C112B}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{C48D0E9D-C862-3EA3-96A7-752EE9D06362}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Visualizers", "Visualizers", "{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}" ProjectSection(SolutionItems) = preProject - D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis + ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugGame Editor|Android = DebugGame Editor|Android DebugGame Editor|Win64 = DebugGame Editor|Win64 + DebugGame|Android = DebugGame|Android DebugGame|Win64 = DebugGame|Win64 + Development Editor|Android = Development Editor|Android Development Editor|Win64 = Development Editor|Win64 + Development|Android = Development|Android Development|Win64 = Development|Win64 + Shipping|Android = Shipping|Android Shipping|Win64 = Shipping|Win64 EndGlobalSection # UnrealVS Section GlobalSection(ddbf523f-7eb6-4887-bd51-85a714ff87eb) = preSolution - AvailablePlatforms=Win64 + AvailablePlatforms=Win64;Android EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6EE39883-7339-3FB6-AD82-931FB137D37F}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame|Win64.ActiveCfg = DebugGame|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame|Win64.Build.0 = DebugGame|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development Editor|Win64.ActiveCfg = Development_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development Editor|Win64.Build.0 = Development_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development|Win64.ActiveCfg = Development|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development|Win64.Build.0 = Development|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Shipping|Win64.ActiveCfg = Shipping|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Shipping|Win64.Build.0 = Shipping|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Android.ActiveCfg = Invalid|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Android.ActiveCfg = Android_DebugGame|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Android.Build.0 = Android_DebugGame|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Win64.ActiveCfg = DebugGame|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Win64.Build.0 = DebugGame|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Android.ActiveCfg = Invalid|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Win64.ActiveCfg = Development_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Win64.Build.0 = Development_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Android.ActiveCfg = Android_Development|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Android.Build.0 = Android_Development|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Win64.ActiveCfg = Development|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Win64.Build.0 = Development|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Android.ActiveCfg = Android_Shipping|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Android.Build.0 = Android_Shipping|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Win64.ActiveCfg = Shipping|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Win64.Build.0 = Shipping|x64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {6EE39883-7339-3FB6-AD82-931FB137D37F} = {233774A8-CC9D-3FA9-86D1-90573E92B704} - {AF5A253A-0F37-38CE-8998-45CA936C112B} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6} + {C48D0E9D-C862-3EA3-96A7-752EE9D06362} = {233774A8-CC9D-3FA9-86D1-90573E92B704} + {B95E7D0E-DB45-3765-9058-E00EBBC4B157} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6} EndGlobalSection EndGlobal diff --git a/Resources/Music.png b/Resources/Music.png new file mode 100644 index 0000000000000000000000000000000000000000..8c591dac824843d6d1922602c29f625ca04c872a GIT binary patch literal 29788 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�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 EAIZ@=3jhEB literal 0 HcmV?d00001 diff --git a/Source/Cut5/Interface/SoundInterface.cpp b/Source/Cut5/Interface/SoundInterface.cpp index 8fff424..a442645 100644 --- a/Source/Cut5/Interface/SoundInterface.cpp +++ b/Source/Cut5/Interface/SoundInterface.cpp @@ -8,6 +8,7 @@ FCriticalSection Mutex; FSoundThread::FSoundThread(int32 OutputChannel, int32 SampleRate) : FRunnable() { + Stream = nullptr; Pa_Initialize(); Pa_OpenDefaultStream(&Stream, 0, OutputChannel, paFloat32, SampleRate, 0, nullptr, nullptr); Pa_StartStream(Stream); @@ -23,7 +24,12 @@ bool FSoundThread::Init() void FSoundThread::Exit() { - Pa_Terminate(); + if (Stream != nullptr && Pa_IsStreamActive(Stream)) + { + Pa_StopStream(Stream); + // Pa_Terminate(); + } + FRunnable::Exit(); } @@ -37,7 +43,10 @@ uint32 FSoundThread::Run() const int32 FrameLength = Audio.Num(); for (int32 i = SeekedFrame * (SampleRate / 26) * 4 * 2; i < (SeekedFrame + 1) * (SampleRate / 26) * 4 * 2 && i < FrameLength; ++i) { - ResultData.Add(Audio[i]); + if (ResultData.Num() < i && i > 0) + { + ResultData.Add(Audio[i]); + } } Pa_WriteStream(Stream, ResultData.GetData(), ResultData.Num() / 4 / 2); SeekedFrame = 0; diff --git a/Source/Cut5/MainHUD.cpp b/Source/Cut5/MainHUD.cpp index 9e1da34..d87f547 100644 --- a/Source/Cut5/MainHUD.cpp +++ b/Source/Cut5/MainHUD.cpp @@ -23,7 +23,7 @@ AMainHUD::AMainHUD() ); GEngine->bUseFixedFrameRate = 1; - GEngine->FixedFrameRate = 60000.0f; + GEngine->FixedFrameRate = 120.0f; UWidgetBlueprintLibrary::SetInputMode_UIOnlyEx(UGameplayStatics::GetPlayerController(GWorld, 0), nullptr, EMouseLockMode::DoNotLock); diff --git a/Source/Cut5/Utils/FFMPEGUtils.cpp b/Source/Cut5/Utils/FFMPEGUtils.cpp index 81ab348..82d9f90 100644 --- a/Source/Cut5/Utils/FFMPEGUtils.cpp +++ b/Source/Cut5/Utils/FFMPEGUtils.cpp @@ -269,6 +269,10 @@ TArray FFFMPEGUtils::GetMovieBrush(FClipData* ClipData, bool Regene if (ClipData->ResourcePropertyDataPtr) { + if (ClipData->ResourcePropertyDataPtr->VideoCodecContext == nullptr) + { + return {}; + } const float ClipLength = (ClipData->VideoEndFrame - ClipData->VideoStartFrame) * FGlobalData::DefaultTimeTickSpace; const float FrameNum = ClipLength / 128.0; const float TotalFrame = ClipData->ResourcePropertyDataPtr->VideoCodecContext->framerate.num * ( ClipData->ResourcePropertyDataPtr->Context->duration / AV_TIME_BASE); @@ -329,11 +333,9 @@ TArray FFFMPEGUtils::GetMovieBrush(FClipData* ClipData, bool Regene FGuid Guid = FGuid::NewGuid(); ExportImage(Texture, *FPaths::Combine(FUtils::GetTempPath() / ClipData->ClipGuid.ToString() / Guid.ToString() + ".png")); ClipData->MovieBrushesPath.Add(FPaths::Combine(FUtils::GetTempPath() / ClipData->ClipGuid.ToString() / Guid.ToString() + ".png")); - + FSlateDynamicImageBrush Brush = FSlateDynamicImageBrush(*ClipData->MovieBrushesPath[i], FVector2f(0, 0)); + Result.Add(Brush); - FSlateBrush NewBrush; - NewBrush.SetResourceObject(Texture); - Result.Add(NewBrush); delete RawData; } @@ -351,6 +353,25 @@ TArray FFFMPEGUtils::GetAudioBrush(FClipData* ClipData) const int32 PicLength = TimeLength / 8.0; + if (ClipData->ResourcePropertyDataPtr) + { + if (ClipData->ResourcePropertyDataPtr->AudioData.Num() == 0) + { + return {}; + } + if (ClipData->ResourcePropertyDataPtr->AudioStream == -1) + { + return {}; + } + if (ClipData->ResourcePropertyDataPtr->VideoStream != -1) + { + return {}; + } + } + else + { + return {}; + } int32 DownSampleSpace = 128; TArray DownSampledData; diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index fef5d24..159eb71 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -139,7 +139,7 @@ void FUtils::CreateDefaultTimelineSave(const FString& SavedPath, const FTimeline MemoryWriter << ClipLength; MemoryWriter << AllClips; FFileHelper::SaveArrayToFile(SavedData, *SavedPath); - + // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("CreateDefaultTimelineSave %s"), *SavedPath)); // FFileHelper::LoadFileToArray(SavedData, *FPaths::Combine(FPaths::ProjectSavedDir(), Type == FTimelineInfo::ETimelineType::Main ? TEXT("Default.sav") : TEXT("DefaultFX.sav"))); } diff --git a/Source/Cut5/Widgets/Commands/ShortcunCommands.h b/Source/Cut5/Widgets/Commands/ShortcunCommands.h index 14e96e0..8a35fe0 100644 --- a/Source/Cut5/Widgets/Commands/ShortcunCommands.h +++ b/Source/Cut5/Widgets/Commands/ShortcunCommands.h @@ -14,13 +14,14 @@ public: TSharedPtr CutMode; TSharedPtr SelectMode; TSharedPtr AutoMagnet; - - TSharedPtr LeftPerFrame; TSharedPtr RightPerFrame; TSharedPtr PlayFrame; TSharedPtr Delete; + TSharedPtr TimelineMoveLeft; + TSharedPtr TimelineMoveRight; + }; diff --git a/Source/Cut5/Widgets/Commands/ShortcutCommands.cpp b/Source/Cut5/Widgets/Commands/ShortcutCommands.cpp index b7f0b6a..7c14387 100644 --- a/Source/Cut5/Widgets/Commands/ShortcutCommands.cpp +++ b/Source/Cut5/Widgets/Commands/ShortcutCommands.cpp @@ -3,15 +3,17 @@ #define LOCTEXT_NAMESPACE "FShortCutCommands" void FShortCutCommands::RegisterCommands() { - UI_COMMAND(CutMode, "剪刀模式", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::B)); - UI_COMMAND(SelectMode, "选择模式", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::A)); - UI_COMMAND(ZoomInTimeline, "放大时间线", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::Equals, EModifierKey::Alt)); - UI_COMMAND(ZoomOutTimeline, "缩小时间线", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::Hyphen, EModifierKey::Alt)); - UI_COMMAND(ExportXML, "导出XML", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::E, EModifierKey::Alt)); - UI_COMMAND(PlayFrame, "播放", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::SpaceBar)); - UI_COMMAND(LeftPerFrame, "左移一帧", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::LeftBracket)); - UI_COMMAND(Delete, "删除", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::Delete)); - UI_COMMAND(RightPerFrame, "右移一帧", "Executes My FCurtainCommands", EUserInterfaceActionType::Button, FInputChord(EKeys::RightBracket)); + UI_COMMAND(CutMode, "剪刀模式", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::B)); + UI_COMMAND(SelectMode, "选择模式", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::A)); + UI_COMMAND(ZoomInTimeline, "放大时间线", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::Equals, EModifierKey::Alt)); + UI_COMMAND(ZoomOutTimeline, "缩小时间线", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::Hyphen, EModifierKey::Alt)); + UI_COMMAND(ExportXML, "导出XML", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::E, EModifierKey::Alt)); + UI_COMMAND(PlayFrame, "播放", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::SpaceBar)); + UI_COMMAND(LeftPerFrame, "左移一帧", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::LeftBracket)); + UI_COMMAND(Delete, "删除", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::Delete)); + UI_COMMAND(RightPerFrame, "右移一帧", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::RightBracket)); + UI_COMMAND(TimelineMoveLeft, "左侧移动时间轴", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::MouseScrollDown, EModifierKey::Shift)); + UI_COMMAND(TimelineMoveRight, "右侧移动时间轴", "Executes My FCurtainCommands", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::MouseScrollUp, EModifierKey::Shift)); } #undef LOCTEXT_NAMESPACE diff --git a/Source/Cut5/Widgets/Curtain/SCurtain.cpp b/Source/Cut5/Widgets/Curtain/SCurtain.cpp index 919d0ba..4087cec 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtain.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtain.cpp @@ -46,32 +46,7 @@ void SCurtain::Construct(const FArguments& InArgs) .ButtonStyle(FCutButtonStyle::Get(), Curtain->bIsActive ? "Curtain.CurtainButtonSelected" : "Curtain.CurtainButton") .OnClicked_Lambda([this]() { - CurtainPanel->DeSelectedAll(); - Curtain->bIsActive = true; - CurtainPanel->CallRender(); - - - // 没有Curtain就Create一个 - if (!FPaths::FileExists(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()))) - { - FUtils::CreateDefaultTimelineSave(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()), FTimelineInfo::ETimelineType::FX); - { - FSaveModifier SaveModifier(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString())); - SaveModifier.TimelineInfo.CurrentOpenFullPath = FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()); - SaveModifier.TimelineInfo.CurrentOpenType = FTimelineInfo::ETimelineType::FX; - Curtain->TimelineInfo = SaveModifier.TimelineInfo; - } - } - CurtainPanel->MainWidgetInterface->OpenTimeline(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()), true); - - - - - TSharedPtr CurtainDragDrop = MakeShared(); - CurtainDragDrop->CurtainIndex = CurtainIndex; - CurtainDragDrop->GroupIndex = CurtainGroup - &CurtainPanel->Groups[0]; - CurtainDragDrop->DragDropType = FCutDragDropBase::EType::CurtainDrag; - CurtainDragDrop->DraggingWidget = SharedThis(this); + TSharedPtr CurtainDragDrop = OpenThis(); return FReply::Handled().DetectDrag(SharedThis(this), EKeys::LeftMouseButton).BeginDragDrop(CurtainDragDrop.ToSharedRef()); }) ] @@ -101,6 +76,11 @@ void SCurtain::Construct(const FArguments& InArgs) ] ] ]; + + if (Curtain->bIsActive) + { + FSlateApplication::Get().SetKeyboardFocus(InlineEditableTextBlock); + } } FReply SCurtain::OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) @@ -132,8 +112,45 @@ FReply SCurtain::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEv CurtainPanel->ShowCurtainCommand(Curtain->CurtainUUID); return FReply::Handled(); } + if (!Curtain->bIsActive) + { + OpenThis(); + } return SCompoundWidget::OnMouseButtonDown(MyGeometry, MouseEvent); } + +TSharedPtr SCurtain::OpenThis() +{ + CurtainPanel->DeSelectedAll(); + Curtain->bIsActive = true; + CurtainPanel->CallRender(); + + + // 没有Curtain就Create一个 + if (!FPaths::FileExists(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()))) + { + FUtils::CreateDefaultTimelineSave(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()), FTimelineInfo::ETimelineType::FX); + { + FSaveModifier SaveModifier(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString())); + SaveModifier.TimelineInfo.CurrentOpenFullPath = FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()); + SaveModifier.TimelineInfo.CurrentOpenType = FTimelineInfo::ETimelineType::FX; + Curtain->TimelineInfo = SaveModifier.TimelineInfo; + } + } + CurtainPanel->MainWidgetInterface->OpenTimeline(FUtils::CurtainFullPath(Curtain->CurtainUUID.ToString()), true); + + + + + TSharedPtr CurtainDragDrop = MakeShared(); + CurtainDragDrop->CurtainIndex = CurtainIndex; + CurtainDragDrop->GroupIndex = CurtainGroup - &CurtainPanel->Groups[0]; + CurtainDragDrop->DragDropType = FCutDragDropBase::EType::CurtainDrag; + CurtainDragDrop->DraggingWidget = SharedThis(this); + + return CurtainDragDrop; +} + END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/Curtain/SCurtain.h b/Source/Cut5/Widgets/Curtain/SCurtain.h index b386c08..b547643 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtain.h +++ b/Source/Cut5/Widgets/Curtain/SCurtain.h @@ -32,7 +32,10 @@ public: int32 CurtainIndex; TSharedPtr InlineEditableTextBlock; TSharedPtr CurtainButton; + TSharedPtr OpenThis(); // FButtonStyle UnSelectedButtonStyle; FButtonStyle SelectedButtonStyle = FButtonStyle::GetDefault(); }; + + diff --git a/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp b/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp index 19dccfd..74500a9 100644 --- a/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp +++ b/Source/Cut5/Widgets/Curtain/SCurtainPanel.cpp @@ -127,7 +127,7 @@ void SCurtainPanel::Construct(const FArguments& InArgs) .Padding(10.0) [ SAssignNew(Title, STextBlock) - .Text(FText::FromString(FGlobalData::CurrentProjectName)) + .Text_Lambda([](){ return FText::FromString(FGlobalData::CurrentProjectName); }) .Justification(ETextJustify::Left) ] + SVerticalBox::Slot() diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 83a7339..bc4cbd3 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -4,6 +4,7 @@ #include "Cut5/WidgetInterface.h" + #include "Widgets/Input/SEditableTextBox.h" extern "C"{ @@ -508,6 +509,7 @@ public: DragDropType = InType; } TSharedPtr DraggingWidget; + TSharedPtr VirtualDraggingShow; TSharedPtr OverrideWidget; TSharedPtr MoveAboutWidget; class ICutMainWidgetInterface* MainInterface; @@ -515,7 +517,11 @@ public: float OriginOffset = 0.0f; EType DragDropType = EType::TrackClip; ETrackType ManualClipType = ETrackType::None; - + + virtual TSharedPtr GetDefaultDecorator() const override + { + return DraggingWidget.ToSharedRef(); + }; }; class CUT5_API FTrackClipDragOperation final : public FCutDragDropBase diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index 0810073..1fff968 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -105,14 +105,53 @@ void DragDropOperator::UpdateClipProcess(ICutMainWidgetInterface* MainInterface, return; } - - +void DragDropOperator::CloseCursorDecorator() +{ + if (CurrentShowDragDropWindow) + { + CurrentShowDragDropWindow->DestroyWindowImmediately(); + CurrentShowDragDropWindow.Reset(); + } +} void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { + if (TSharedPtr DragDropBase = DragDropEvent.GetOperationAs()) + { + return; + } if (TSharedPtr DragDropBase = DragDropEvent.GetOperationAs()) { + // if (DragDropBase->VirtualDraggingShow && DragDropBase->MainInterface) + // { + // if (!CurrentShowDragDropWindow) + // { + // CurrentShowDragDropWindow = SWindow::MakeCursorDecorator(); + // CurrentShowDragDropWindow->SetContent(DragDropBase->VirtualDraggingShow.ToSharedRef()); + // FSlateApplication::Get().AddWindowAsNativeChild(CurrentShowDragDropWindow.ToSharedRef(), FSlateApplication::Get().GetActiveTopLevelWindow().ToSharedRef(), true); + // } + // CurrentShowDragDropWindow->MoveWindowTo(FSlateApplication::Get().GetCursorPos()); + // // CurrentShowDragDropWidget = DragDropBase->VirtualDraggingShow.ToSharedRef(); + // // SCutMainWindow* MainWindow = static_cast(SavedMainInterface); + // // if (MainWindow) + // // { + // // MainWindow->Overlay->AddSlot() + // // .HAlign(HAlign_Left) + // // .VAlign(VAlign_Top) + // // [ + // // SNew(SBox) + // // .WidthOverride(80) + // // .HeightOverride(80) + // // .HAlign(HAlign_Fill) + // // .VAlign(VAlign_Fill) + // // [ + // // CurrentShowDragDropWidget.ToSharedRef() + // // ] + // // ]; + // // } + // + // } TSharedPtr ClipsMoveDragDropBase = StaticCastSharedPtr(DragDropBase); if (DragDropBase->DragDropType == FCutDragDropBase::EType::ClipsMove) { @@ -251,7 +290,16 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv return; } TickTimeline->UpdateNewCursorPosition((TickTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X) / FGlobalData::DefaultTimeTickSpace); - + if (TickTimeline->CutTimeline->AutoPlaying == false) + { + int32 NewFrame = (TickTimeline->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X) / FGlobalData::DefaultTimeTickSpace; + for (FSingleTrackGroupInstance& Instance : TickTimeline->CutTimeline->TrackGroupInstances) + { + Instance.Body->Seek(NewFrame); + } + TickTimeline->CutTimeline->CurrentTimeData->SetText(FText::FromString(FGlobalData::GetTimeData(NewFrame) + " / ")); + } + return; } @@ -368,6 +416,12 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv const auto& DragDropOperation = static_cast(DragDropEvent.GetOperation().ToSharedRef().Get()); TSharedPtr Body = StaticCastSharedPtr(DragDropOperation.OverrideWidget); + + if (DragDropOperation.DragDropType == FCutDragDropBase::EType::Device) + { + + } + if (DragDropOperation.DragDropType == FCutDragDropBase::EType::Clip2Clip) { const int32 NewPos = (Body->MainWidgetInterface->GetCutTimeline()->GetCachedGeometry().AbsoluteToLocal(DragDropEvent.GetScreenSpacePosition()).X - DragDropOperation.DragOffset) / FGlobalData::DefaultTimeTickSpace; @@ -421,7 +475,7 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv if (TimelineClip == Clip) continue;; - GEngine->AddOnScreenDebugMessage(-1, 0.1f, FColor::Red, FString::Printf(TEXT("ClipStartFrame:%d, LoopClipFrame:%d"), TimelineClip->ClipData->ClipStartFrame + NewPos, Clip->ClipData->ClipStartFrame)); + // GEngine->AddOnScreenDebugMessage(-1, 0.1f, FColor::Red, FString::Printf(TEXT("ClipStartFrame:%d, LoopClipFrame:%d"), TimelineClip->ClipData->ClipStartFrame + NewPos, Clip->ClipData->ClipStartFrame)); if ((TimelineClip->ClipData->ClipStartFrame + NewPos) == Clip->ClipData->ClipEndFrame) { @@ -450,10 +504,13 @@ void DragDropOperator::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv { } + return; } void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, TSharedPtr DropWidget) { + + const auto& DragDropOperation = static_cast(DragDropEvent.GetOperation().ToSharedRef().Get()); if (DragDropOperation.DragDropType == FCutDragDropBase::EType::ClipsMove) diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h index dfd3873..31a0225 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.h @@ -13,6 +13,10 @@ public: void OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, TSharedPtr DropWidget); void OnDropAddNewTrack(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, TSharedPtr DropWidget); void UpdateClipProcess(ICutMainWidgetInterface* MainInterface, FClipData& TimelineClip); + void CloseCursorDecorator(); + ICutMainWidgetInterface* SavedMainInterface; + TSharedPtr CurrentShowDragDropWidget; + TSharedPtr CurrentShowDragDropWindow; }; diff --git a/Source/Cut5/Widgets/FX/SEffectCard.cpp b/Source/Cut5/Widgets/FX/SEffectCard.cpp index d914eb3..5a98b59 100644 --- a/Source/Cut5/Widgets/FX/SEffectCard.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCard.cpp @@ -58,7 +58,7 @@ void SEffectCard::Construct(const FArguments& InArgs) .OnClicked_Lambda([this]() { - MainInterface->OpenTimeline(FUtils::SingleCardFullPath(CardProperty->Name), true); + MainInterface->OpenTimeline(FUtils::SingleCardFullPath(CardProperty->Guid.ToString()), true); PropertiesInterfaceGUID = CardProperty->Guid; MainInterface->CurrentSelectedPropertiesInterfaceGuid = CardProperty->Guid; MainInterface->UpdateProperties(this); diff --git a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp index 20090a2..cb63881 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp @@ -15,6 +15,7 @@ #include "Widgets/Layout/SScrollBox.h" #include "Widgets/Text/SInlineEditableTextBlock.h" #include "Cut5/Widgets/FX/SEffectCardsPanel.h" +#include "Cut5/Widgets/MicroWidgets/STips.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION @@ -414,7 +415,7 @@ void SEffectCardGroup::CallRender() .WidthOverride(76) .HeightOverride(76) [ - SNew(SOverlay) + SAssignNew(Overlay, SOverlay) + SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) @@ -428,6 +429,17 @@ void SEffectCardGroup::CallRender() FEffectCardProperty NewCard; NewCard.Name = TEXT("未命名") + NewCard.Guid.ToString(); + int32 ID = 0; + for (int32 i = 0; i < EffectCardPanel->EffectCardGroups.Num(); i++) + { + for (int32 j = 0; j < EffectCardPanel->EffectCardGroups[i].Cards.Num(); j++) + { + ID++; + } + ID++; + } + NewCard.ID = ID; + FUtils::CreateDefaultTimelineSave(FUtils::SingleCardFullPath(NewCard.Guid.ToString()), FTimelineInfo::ETimelineType::FX); { FSaveModifier SaveModifier(FUtils::SingleCardFullPath(NewCard.Guid.ToString())); @@ -486,6 +498,56 @@ TSharedPtr SEffectCardGroup::GetPropertiesWidget() return PropertiesWidget; } + +void SEffectCardGroup::ShowClosedButton(bool bShow) +{ + if (bShow) + { + ClosedButton = SNew(SButton) + .ButtonStyle(FCoreStyle::Get(), "NoBorder") + .Content() + [ + SNew(SImage) + .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("close-circle-fill.png"), {16, 16})) + ] + .OnClicked_Lambda([this]() + { + GEngine->GameViewport->AddViewportWidgetContent( + SNew(STips) + .Title(TEXT("确定删除特效卡吗?")) + .SubTitle(TEXT("特效卡删除后不可恢复")) + .OnEnsure_Lambda([this](const FString& String) + { + if (EffectCardGroup->bIsActive) + { + MainInterface->OnSelectCard(EffectCardGroup->Guid); + } + EffectCardPanel->RemoveCard(EffectCardGroup->Guid); + }), 1 + ); + + + return FReply::Handled(); + }); + Overlay->AddSlot() + .VAlign(VAlign_Top) + .HAlign(HAlign_Right) + [ + ClosedButton.ToSharedRef() + ]; + } + else + { + if (ClosedButton) + { + Overlay->RemoveSlot(ClosedButton.ToSharedRef()); + ClosedButton.Reset(); + } + + } + +} + FReply SEffectCardGroup::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { TSharedPtr EffectCardDragDrop = DragDropEvent.GetOperationAs(); @@ -500,4 +562,16 @@ FReply SEffectCardGroup::OnDrop(const FGeometry& MyGeometry, const FDragDropEven return SCompoundWidget::OnDrop(MyGeometry, DragDropEvent); } +void SEffectCardGroup::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + ShowClosedButton(true); + +} + +void SEffectCardGroup::OnMouseLeave(const FPointerEvent& MouseEvent) +{ + ShowClosedButton(false); + +} + END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/FX/SEffectCardGroup.h b/Source/Cut5/Widgets/FX/SEffectCardGroup.h index 51f7b4d..f1b3712 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardGroup.h +++ b/Source/Cut5/Widgets/FX/SEffectCardGroup.h @@ -56,6 +56,9 @@ public: virtual TSharedPtr GetPropertiesWidget() override; + void ShowClosedButton(bool bShow); + TSharedPtr ClosedButton; + TSharedPtr Overlay; TSharedPtr PropertiesWidget; @@ -65,4 +68,7 @@ public: TSharedPtr>> GroupComboBox; TSharedPtr>> JumpStepComboBox; + virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; + virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override; + }; diff --git a/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp b/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp index d25af07..153e9ad 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCardsPanel.cpp @@ -104,7 +104,16 @@ void SEffectCardsPanel::CallRender() .OnClicked_Lambda([this]() { FEffectCardGroup* Group = AddNewGroup(TEXT("新建组") + FGuid::NewGuid().ToString()); - + int32 ID = 0; + for (int32 i = 0; i < EffectCardGroups.Num(); i++) + { + for (int32 j = 0; j < EffectCardGroups[i].Cards.Num(); j++) + { + ID++; + } + ID++; + } + Group->ID = ID; const FString NewPath = FPaths::Combine(FGlobalData::BasePath, FGlobalData::CurrentProjectName, TEXT("FX"), FGuid::NewGuid().ToString() + TEXT(".bin")); FUtils::CreateDefaultTimelineSave(NewPath, FTimelineInfo::ETimelineType::FX); { @@ -144,8 +153,19 @@ void SEffectCardsPanel::AddNewCard(FEffectCardProperty CardProperty, const FStri void SEffectCardsPanel::RemoveCard(const FGuid& GUID) { // Search in all group to find GUID equal to the GUID. + int32 j = 0; for (FEffectCardGroup& Group : EffectCardGroups) { + if (!Group.bIsDedicated && Group.Guid == GUID) + { + if (Group.bIsActive == true) + { + MainInterface->OpenTimeline(FUtils::MainSaveFullPath()); + } + EffectCardGroups.RemoveAt(j); + break; + } + int32 i = 0; for (FEffectCardProperty& Property : Group.Cards) { @@ -160,6 +180,7 @@ void SEffectCardsPanel::RemoveCard(const FGuid& GUID) } i++; } + j++; } CallRender(); } diff --git a/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp b/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp index 9dd7702..2547972 100644 --- a/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp +++ b/Source/Cut5/Widgets/MicroWidgets/SColorPanel.cpp @@ -136,17 +136,17 @@ void SColorPanel::Construct(const FArguments& InArgs) + SOverlay::Slot() .HAlign(HAlign_Right) .VAlign(VAlign_Top) + .Padding(0, 0, 16, 16) [ SNew(SBox) .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) - .Padding(0, 0, 16, 16) + .Padding(0, 0, 0, 0) .WidthOverride(24) .HeightOverride(24) [ SNew(SImage) - .DesiredSizeOverride(FVector2D(24, 24)) - .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ColorPanelClose.png"), {24, 24})) + .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ColorPanelClose.png"), {})) .OnMouseButtonDown_Lambda([this](const FGeometry&, const FPointerEvent&) { GEngine->GameViewport->RemoveViewportWidgetContent(SharedThis(this)); @@ -163,6 +163,7 @@ void SColorPanel::Construct(const FArguments& InArgs) .HeightOverride(12) [ SAssignNew(ColorBarHCircle, SImage) + .Visibility(EVisibility::HitTestInvisible) .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ColorSelectCircle.png"), {16, 16})) ] @@ -176,6 +177,7 @@ void SColorPanel::Construct(const FArguments& InArgs) .HeightOverride(12) [ SAssignNew(ColorBarVCircle, SImage) + .Visibility(EVisibility::HitTestInvisible) .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ColorSelectCircle.png"), {16, 16})) ] ] @@ -188,6 +190,7 @@ void SColorPanel::Construct(const FArguments& InArgs) .HeightOverride(12) [ SAssignNew(ColorBarSCircle, SImage) + .Visibility(EVisibility::HitTestInvisible) .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ColorSelectCircle.png"), {16, 16})) ] ] @@ -220,9 +223,9 @@ FReply SColorPanel::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent void SColorPanel::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) { - ColorBarHCircle->SetRenderTransform(FVector2D(18 + (CurrentSelectColor.R / 360.0f * 286), 242)); - ColorBarSCircle->SetRenderTransform(FVector2D(18 + (ColorS * 286), ColorSHeight + 56)); - ColorBarVCircle->SetRenderTransform(FVector2D(18 + (CurrentSelectColor.B * 286), 268)); + ColorBarHCircle->SetRenderTransform(FVector2D(12 + (CurrentSelectColor.R / 360.0f * 288), 242)); + ColorBarSCircle->SetRenderTransform(FVector2D(12 + (ColorS * 286), ColorSHeight + 56 - 6)); + ColorBarVCircle->SetRenderTransform(FVector2D(12 + (CurrentSelectColor.B * 288), 268)); ColorImage->SetColorAndOpacity(GetColor()); *ColorPtr = GetColor(); diff --git a/Source/Cut5/Widgets/MicroWidgets/SNewProjectTips.cpp b/Source/Cut5/Widgets/MicroWidgets/SNewProjectTips.cpp index 36aa5db..831902a 100644 --- a/Source/Cut5/Widgets/MicroWidgets/SNewProjectTips.cpp +++ b/Source/Cut5/Widgets/MicroWidgets/SNewProjectTips.cpp @@ -64,10 +64,14 @@ void SNewProjectTips::Construct(const FArguments& InArgs) .OnTextCommitted_Lambda([this](const FText& InText, ETextCommit::Type InCommitType) { - if (OnEnsure.ExecuteIfBound(InText.ToString())) + if (InCommitType == ETextCommit::Type::OnEnter) { + if (OnEnsure.ExecuteIfBound(InText.ToString())) + { + } } + }) diff --git a/Source/Cut5/Widgets/SCustomInputPanel.cpp b/Source/Cut5/Widgets/SCustomInputPanel.cpp index 6fecbe3..3cc6887 100644 --- a/Source/Cut5/Widgets/SCustomInputPanel.cpp +++ b/Source/Cut5/Widgets/SCustomInputPanel.cpp @@ -141,7 +141,7 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) { bIsEditMode = false; ImportImage->SetImage(FUtils::GetBrushFromImage(FUtils::GetResourcesPath("ImportVideo.png"), {})); - ImportText->SetText(FText::FromString(TEXT("导入视频"))); + ImportText->SetText(FText::FromString(TEXT("导入资产"))); for (int32 i = 0; i < ResourceInst.Num(); i++) { ResourceInst[i]->ShowCheckBox(false); @@ -250,78 +250,44 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) } IDesktopPlatform* DesktopPlatformModule = FDesktopPlatformModule::Get(); TArray OpenFileName; - DesktopPlatformModule->OpenFileDialog(nullptr, (TEXT("打开文件")), TEXT(""), TEXT(""), TEXT(""), EFileDialogFlags::None, OpenFileName); - + DesktopPlatformModule->OpenFileDialog(nullptr, (TEXT("打开文件")), TEXT(""), TEXT(""), TEXT(""), EFileDialogFlags::Multiple, OpenFileName); for (int32 i = 0; i < OpenFileName.Num(); i++) { - if (FPaths::GetExtension(OpenFileName[i]) == "mp3") + FTimelinePropertyData Data; + if (FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data) == TEXT("Failed")) { - FTimelinePropertyData Data; - FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data); + continue; + }; - TSharedPtr Resource = SNew(SCustomInputResource) - .PropertyData(Data).OnCheckBoxChecked_Lambda([this](FTimelinePropertyData& Data, bool bIsChecked) - { - if (bIsChecked == true) - { - SelectedProperties.Add(Data); - } - else - { - SelectedProperties.Remove(Data); - } - - }); - GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2) - [ - Resource.ToSharedRef() - ]; - PropertyData.Add(Data); - ResourceInst.Add(Resource.ToSharedRef()); - if (bIsEditMode) - { - Resource->ShowCheckBox(true); - } - return FReply::Handled(); - } - else + TSharedPtr Resource = SNew(SCustomInputResource).MainInterface(MainWidgetInterface) + .PropertyData(Data).OnCheckBoxChecked_Lambda([this](FTimelinePropertyData& ClickedData, bool bIsChecked) { - FTimelinePropertyData Data; - if (FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data) == TEXT("Failed")) + if (bIsChecked == true) { - return FReply::Handled(); - }; - - TSharedPtr Resource = SNew(SCustomInputResource) - .PropertyData(Data).OnCheckBoxChecked_Lambda([this](FTimelinePropertyData& ClickedData, bool bIsChecked) - { - if (bIsChecked == true) - { - SelectedProperties.Add(ClickedData); - } - else - { - for (int32 i = 0; i < SelectedProperties.Num(); i++) - { - if (SelectedProperties[i].Guid == ClickedData.Guid) - { - SelectedProperties.RemoveAt(i); - break; - } - } - - } - }); - GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2) - [ - Resource.ToSharedRef() - ]; - PropertyData.Add(Data); - ResourceInst.Add(Resource.ToSharedRef()); - if (bIsEditMode) - { - Resource->ShowCheckBox(true); + SelectedProperties.Add(ClickedData); } + else + { + for (int32 i = 0; i < SelectedProperties.Num(); i++) + { + if (SelectedProperties[i].Guid == ClickedData.Guid) + { + SelectedProperties.RemoveAt(i); + break; + } + } + + } + }); + GridPanel->AddSlot(GridPanel->GetChildren()->Num() % 2, GridPanel->GetChildren()->Num() / 2) + [ + Resource.ToSharedRef() + ]; + PropertyData.Add(Data); + ResourceInst.Add(Resource.ToSharedRef()); + if (bIsEditMode) + { + Resource->ShowCheckBox(true); } } @@ -339,7 +305,7 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) .VAlign(VAlign_Center) [ SAssignNew(ImportText, STextBlock) - .Text(FText::FromString(TEXT("导入视频"))) + .Text(FText::FromString(TEXT("导入资产"))) .Justification(ETextJustify::Center) ] ] @@ -385,6 +351,25 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) FReply SCustomInputPanel::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) { + if (TSharedPtr DragOperation = DragDropEvent.GetOperationAs()) + { + for (const FString& NewFile : DragOperation->GetFiles()) + { + FTimelinePropertyData Data; + if (FFFMPEGUtils::LoadMedia(NewFile, &Data) != TEXT("Failed")) + { + EffectGridPanel->AddSlot(EffectGridPanel->GetChildren()->Num() % 4, EffectGridPanel->GetChildren()->Num() / 4) + [ + SNew(SCustomInputResource) + .PropertyData(Data) + .MainInterface(MainWidgetInterface) + ]; + PropertyData.Add(Data); + } + + } + return FReply::Handled().EndDragDrop(); + } return FReply::Handled().EndDragDrop(); } @@ -551,6 +536,7 @@ void SCustomInputPanel::LoadPanel(const FString& LoadPlace) [ SNew(SCustomInputResource) .PropertyData(ReloadPropertyData) + .MainInterface(MainWidgetInterface) ]; PropertyData.Add(ReloadPropertyData); } diff --git a/Source/Cut5/Widgets/SCustomInputResource.cpp b/Source/Cut5/Widgets/SCustomInputResource.cpp index daa34f5..2c550fa 100644 --- a/Source/Cut5/Widgets/SCustomInputResource.cpp +++ b/Source/Cut5/Widgets/SCustomInputResource.cpp @@ -14,7 +14,7 @@ void SCustomInputResource::Construct(const FArguments& InArgs) PropertyData = InArgs._PropertyData; VideoCapture = InArgs._VideoCapture; OnCheckBoxChecked = InArgs._OnCheckBoxChecked; - CustomPresetName = InArgs._CustomPresetName; + MainInterface = InArgs._MainInterface; ChildSlot [ SNew(SBox) @@ -39,15 +39,17 @@ void SCustomInputResource::Construct(const FArguments& InArgs) .Padding(10.0) [ SNew(SImage) - .Image(PropertyData.bIsCustomPresetData == false ? FUtils::GetBrushFromImage(PropertyData.IconPath, {}) : FUtils::GetBrushFromImage(FUtils::GetResourcesPath("CustomPreset.png"), {})) + .Image( (PropertyData.VideoStream == -1 && PropertyData.AudioStream != -1) ? FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("Music.png")), {}) : + PropertyData.bIsCustomPresetData == false ? FUtils::GetBrushFromImage(PropertyData.IconPath, {}) : FUtils::GetBrushFromImage(FUtils::GetResourcesPath("CustomPreset.png"), {})) ] + SOverlay::Slot() .HAlign(HAlign_Center) .VAlign(VAlign_Center) [ SNew(STextBlock) - .Text(FText::FromString(CustomPresetName)) - .Visibility(PropertyData.bIsCustomPresetData == true ? EVisibility::Visible : EVisibility::Collapsed) + .Text(FText::FromString(PropertyData.Name)) + .Font(FAppStyle::GetWidgetStyle("NormalText").Font) + // .Visibility(PropertyData.bIsCustomPresetData == true ? EVisibility::Visible : EVisibility::Collapsed) ] ] @@ -67,6 +69,17 @@ FReply SCustomInputResource::OnDragDetected(const FGeometry& MyGeometry, const F Operation->DraggingWidget = SharedThis(this); Operation->DragDropType = FCutDragDropBase::EType::TrackClip; Operation->VideoCapture = &VideoCapture; + Operation->MainInterface = MainInterface; + + Operation->VirtualDraggingShow = SNew(SBox) + .WidthOverride(80) + .HeightOverride(80) + .HAlign(HAlign_Fill) + .VAlign(VAlign_Fill) + [ + SNew(SImage).Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(PropertyData.IconPath), {})) + ]; + return FReply::Handled().BeginDragDrop(Operation.ToSharedRef()); } diff --git a/Source/Cut5/Widgets/SCustomInputResource.h b/Source/Cut5/Widgets/SCustomInputResource.h index 2177f40..854d18e 100644 --- a/Source/Cut5/Widgets/SCustomInputResource.h +++ b/Source/Cut5/Widgets/SCustomInputResource.h @@ -18,7 +18,7 @@ public: } SLATE_ARGUMENT(FTimelinePropertyData, PropertyData) SLATE_ARGUMENT(cv::VideoCapture, VideoCapture) - SLATE_ARGUMENT(FString, CustomPresetName) + SLATE_ARGUMENT(ICutMainWidgetInterface*, MainInterface) SLATE_EVENT(FOnCheckBoxChecked, OnCheckBoxChecked) SLATE_END_ARGS() @@ -27,7 +27,7 @@ public: void Construct(const FArguments& InArgs); virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; - + ICutMainWidgetInterface* MainInterface; void ShowCheckBox(bool bShow); FOnCheckBoxChecked OnCheckBoxChecked; TSharedPtr ImageOverlay; @@ -35,5 +35,4 @@ public: TSharedPtr CheckBox; TSharedPtr Box; - FString CustomPresetName; }; diff --git a/Source/Cut5/Widgets/SCutMainWindow.cpp b/Source/Cut5/Widgets/SCutMainWindow.cpp index d020b99..7099684 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.cpp +++ b/Source/Cut5/Widgets/SCutMainWindow.cpp @@ -24,7 +24,7 @@ #include "DragDropOperator/DragDropOperator.h" #include "FX/SEffectCardsPanel.h" #include "HAL/FileManagerGeneric.h" -#include "Interfaces/IMainFrameModule.h" +#include "Kismet/KismetSystemLibrary.h" #include "MicroWidgets/SColorPanel.h" #include "MicroWidgets/SNewProjectTips.h" #include "StatePanel/SStatePanel.h" @@ -49,11 +49,11 @@ void SCutMainWindow::Construct(const FArguments& InArgs) MainBarTextStyle.SetFontSize(14); FTextBlockStyle TitleBarTextStyle = FAppStyle::GetWidgetStyle("NormalText"); TitleBarTextStyle.SetFontSize(15); - - + + ChildSlot [ - SNew(SOverlay) + SAssignNew(Overlay, SOverlay) + SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) @@ -134,6 +134,12 @@ void SCutMainWindow::Construct(const FArguments& InArgs) [ 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() @@ -147,6 +153,20 @@ void SCutMainWindow::Construct(const FArguments& InArgs) [ 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() @@ -160,6 +180,11 @@ void SCutMainWindow::Construct(const FArguments& InArgs) [ 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(); + }) ] ] ] @@ -332,30 +357,36 @@ void SCutMainWindow::Construct(const FArguments& InArgs) ]; + + + 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(); - IMainFrameModule& MainFrame = FModuleManager::GetModuleChecked("MainFrame"); - FInputBindingManager::Get().RegisterCommandList(ContextName, MainFrame.GetMainFrameCommandBindings()); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().LeftPerFrame, FExecuteAction::CreateLambda([this]() + + CommandList->MapAction(FShortCutCommands::Get().LeftPerFrame, FExecuteAction::CreateLambda([this]() { CutTimeline->UpdateCursorPosition(CutTimeline->TimelineTick->GetCursorPosition() - 1); - })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().RightPerFrame, FExecuteAction::CreateLambda([this]() + }), EUIActionRepeatMode::RepeatEnabled); + CommandList->MapAction(FShortCutCommands::Get().RightPerFrame, FExecuteAction::CreateLambda([this]() { CutTimeline->UpdateCursorPosition(CutTimeline->TimelineTick->GetCursorPosition() + 1); - })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().PlayFrame, FExecuteAction::CreateLambda([this]() + }), EUIActionRepeatMode::RepeatEnabled); + CommandList->MapAction(FShortCutCommands::Get().PlayFrame, FExecuteAction::CreateLambda([this]() { CutTimeline->SetAutoPlay(!CutTimeline->AutoPlaying); })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().Delete, FExecuteAction::CreateLambda([this]() + CommandList->MapAction(FShortCutCommands::Get().Delete, FExecuteAction::CreateLambda([this]() { for (int32 i = 0; i < CutTimeline->SelectedClips.Num(); i++) { @@ -374,7 +405,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs) } })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().ExportXML, FExecuteAction::CreateLambda([this]() + CommandList->MapAction(FShortCutCommands::Get().ExportXML, FExecuteAction::CreateLambda([this]() { FString String; IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); @@ -383,14 +414,14 @@ void SCutMainWindow::Construct(const FArguments& InArgs) return; ExportProject(String); })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().ZoomInTimeline, FExecuteAction::CreateLambda([this]() + CommandList->MapAction(FShortCutCommands::Get().ZoomInTimeline, FExecuteAction::CreateLambda([this]() { 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(); })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().ZoomOutTimeline, FExecuteAction::CreateLambda([this]() + CommandList->MapAction(FShortCutCommands::Get().ZoomOutTimeline, FExecuteAction::CreateLambda([this]() { const float NewValue = CutTimeline->ZoomSlider->GetValue() - 0.1; CutTimeline->ZoomSlider->SetValue(NewValue); @@ -398,7 +429,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs) CutTimeline->RenderGroup(); })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().SelectMode, FExecuteAction::CreateLambda([this]() + CommandList->MapAction(FShortCutCommands::Get().SelectMode, FExecuteAction::CreateLambda([this]() { SelectMode = ESelectMode::SelectMode; const TSharedPtr NewWidget = SNew(SBox).WidthOverride(48).HeightOverride(48) @@ -407,7 +438,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs) ]; GEngine->GameViewport->AddSoftwareCursorFromSlateWidget(EMouseCursor::Type::Default, NewWidget.ToSharedRef()); })); - MainFrame.GetMainFrameCommandBindings()->MapAction(FShortCutCommands::Get().CutMode, FExecuteAction::CreateLambda([this]() + CommandList->MapAction(FShortCutCommands::Get().CutMode, FExecuteAction::CreateLambda([this]() { SelectMode = ESelectMode::CutMode; @@ -424,7 +455,6 @@ void SCutMainWindow::Construct(const FArguments& InArgs) FMainMenuCommands::Register(); - CommandList = MakeShareable(new FUICommandList); CommandList->MapAction(FMainMenuCommands::Get().ExportXML, FExecuteAction::CreateLambda([this]() { FString String; @@ -452,14 +482,21 @@ void SCutMainWindow::Construct(const FArguments& InArgs) { SaveProject(); })); - - - // CommandList->MapAction(FMainMenuCommands::Get().Exit, FExecuteAction::CreateLambda([this]() - // { - // FPlatformMisc::RequestExit(true); - // })); - + + 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); + })); + FInputBindingManager::Get().RegisterCommandList(FShortCutCommands::Get().GetContextName(), CommandList.ToSharedRef()); OnUpdateProjector(0, true); + + DragDropOperator::GetDragDropOperator()->SavedMainInterface = this; } void SCutMainWindow::Render() @@ -494,11 +531,25 @@ void SCutMainWindow::Render() +} + +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 + const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, + const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const { if (CutTimeline && bRenderLine) { @@ -534,6 +585,7 @@ FReply SCutMainWindow::OnDragOver(const FGeometry& MyGeometry, const FDragDropEv 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); @@ -656,6 +708,7 @@ void SCutMainWindow::AddNewCard(FEffectCardProperty& CardProperty, FString Group void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefore, bool ForceOpen) { + if (NeedSaveBefore) { if (TimelineName != "") @@ -664,17 +717,23 @@ void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefo { CutTimeline->SaveTimeline(FUtils::MainSaveFullPath(), CutTimeline->TimelineInfo); CutTimeline->TimelineInfo.CurrentOpenFullPath = FUtils::MainSaveFullPath(); + CutTimeline->bNeedShowPanel = false; } else { if (CutTimeline->TimelineInfo.CurrentOpenFullPath != FUtils::MainSaveFullPath()) + { CutTimeline->SaveTimeline(CutTimeline->TimelineInfo.CurrentOpenFullPath, CutTimeline->TimelineInfo); + CutTimeline->bNeedShowPanel = true; + } + else { if (!ForceOpen) { CutTimeline->SaveTimeline(FUtils::MainSaveFullPath(), CutTimeline->TimelineInfo); CutTimeline->TimelineInfo.CurrentOpenFullPath = FUtils::MainSaveFullPath(); + CutTimeline->bNeedShowPanel = false; } } @@ -684,7 +743,7 @@ void SCutMainWindow::OpenTimeline(const FString& TimelineName, bool NeedSaveBefo FTimelineInfo TimelineInfo; // 拿到TimelineName路径中的名字,也就是倒数第四位开始,去掉后缀 - + // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TimelineName); if (CutTimeline->LoadTimeline(TimelineName, TimelineInfo)) { CutTimeline->TimelineInfo = TimelineInfo; @@ -736,11 +795,18 @@ void SCutMainWindow::OpenProject(const FString& Project) { FTimelinePropertyData TimelinePropertyData; Reader << TimelinePropertyData; - FTimelinePropertyData ReloadPropertyData; - FFFMPEGUtils::LoadMedia(TimelinePropertyData.MoviePath, &ReloadPropertyData); - ReloadPropertyData.Guid = TimelinePropertyData.Guid; + + FTimelinePropertyData ReloadPropertyData = TimelinePropertyData; + if (TimelinePropertyData.bIsCustomPresetData == false) + { + if (FFFMPEGUtils::LoadMedia(TimelinePropertyData.MoviePath, &ReloadPropertyData) == TEXT("Failed")) + { + continue; + } + ReloadPropertyData.Guid = TimelinePropertyData.Guid; + } - CustomInputPanel->GridPanel->AddSlot(CustomInputPanel->GetChildren()->Num() % 2, CustomInputPanel->GetChildren()->Num() / 2) + CustomInputPanel->GridPanel->AddSlot(i % 2, i / 2) [ SNew(SCustomInputResource) .PropertyData(ReloadPropertyData) @@ -1161,8 +1227,9 @@ void SCutMainWindow::AddNewCustomPreset(const FString& Name, const FPresetsCusto FTimelinePropertyData NewPropertyData; NewPropertyData.bIsCustomPresetData = true; NewPropertyData.PresetsCustomData = CustomData; - - TSharedPtr CustomInputResource = SNew(SCustomInputResource).PropertyData(NewPropertyData).CustomPresetName(Name); + NewPropertyData.Name = Name; + + TSharedPtr CustomInputResource = SNew(SCustomInputResource).PropertyData(NewPropertyData); CustomInputPanel->GridPanel->AddSlot(CustomInputPanel->GridPanel->GetChildren()->Num() % 2, CustomInputPanel->GridPanel->GetChildren()->Num() / 2) [ CustomInputResource.ToSharedRef() @@ -1177,6 +1244,33 @@ ESelectMode SCutMainWindow::GetSelectedMode() return SelectMode; } +FReply SCutMainWindow::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) +{ + if (CommandList->ProcessCommandBindings(InKeyEvent)) + { + return FReply::Handled(); + } + return FReply::Handled(); +} + +FReply SCutMainWindow::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + if (CommandList->ProcessCommandBindings(MouseEvent)) + { + return FReply::Handled(); + } + return FReply::Handled(); +} + +FReply SCutMainWindow::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + if (CommandList->ProcessCommandBindings(MouseEvent)) + { + return FReply::Handled(); + } + return FReply::Handled(); +} + tinyxml2::XMLElement* SCutMainWindow::GetDeviceElement(tinyxml2::XMLElement* Parent) { tinyxml2::XMLElement* Device = Parent->InsertNewChildElement("Device"); @@ -1498,7 +1592,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectList(tinyxml2::XMLElement* } for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++) { - OpenTimeline(FUtils::SingleCardFullPath(EffectCardsPanel->EffectCardGroups[i].Cards[j].Name), true, true); + OpenTimeline(FUtils::SingleCardFullPath(EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid.ToString()), true, true); CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid; // OnSelectCard(EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid); GetSpecialEffect(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i].Cards[j]); diff --git a/Source/Cut5/Widgets/SCutMainWindow.h b/Source/Cut5/Widgets/SCutMainWindow.h index 9c7da14..4b50215 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.h +++ b/Source/Cut5/Widgets/SCutMainWindow.h @@ -41,15 +41,18 @@ public: TSharedPtr EffectCardsPanel; TArray> PlayerLightsSlateInstances; TSharedPtr DefaultCursorWidget; + TSharedPtr Overlay; TSharedPtr CommandList; void Render(); - + virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override; virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override; FSoundThread* SoundThread; + + float TotalTime; bool bRenderLine = false; float RenderLineTime = 0; @@ -85,6 +88,11 @@ public: virtual void OpenColorPanel(FLinearColor* ColorPtr); virtual void AddNewCustomPreset(const FString& Name, const FPresetsCustomData CustomData) override; virtual ESelectMode GetSelectedMode() override; + + virtual bool SupportsKeyboardFocus() const override { return true; }; + virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override; + virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; + virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; tinyxml2::XMLElement* GetDeviceElement(tinyxml2::XMLElement* Parent); tinyxml2::XMLElement* GetVideoElement(tinyxml2::XMLElement* Parent, FEncodeVideoInfo EncodeVideoInfo); diff --git a/Source/Cut5/Widgets/SCutTimeline.cpp b/Source/Cut5/Widgets/SCutTimeline.cpp index 7b68513..22c3679 100644 --- a/Source/Cut5/Widgets/SCutTimeline.cpp +++ b/Source/Cut5/Widgets/SCutTimeline.cpp @@ -106,7 +106,7 @@ void SCutTimeline::Construct(const FArguments& InArgs) ] + SOverlay::Slot() .HAlign(HAlign_Fill) - .VAlign(VAlign_Fill) + .VAlign(VAlign_Top) [ SNew(SVerticalBox) + SVerticalBox::Slot() @@ -115,7 +115,7 @@ void SCutTimeline::Construct(const FArguments& InArgs) // Tool bar SNew(SHorizontalBox) + SHorizontalBox::Slot() - + .SizeParam(FAuto()) .Padding(8, 0, 0, 0) .HAlign(HAlign_Left) .VAlign(VAlign_Center) @@ -205,6 +205,7 @@ void SCutTimeline::Construct(const FArguments& InArgs) ] + SVerticalBox::Slot() + .SizeParam(FStretch(1.0)) [ // Timeline SNew(SHorizontalBox) @@ -265,7 +266,7 @@ void SCutTimeline::Construct(const FArguments& InArgs) [ SAssignNew(TimelineTickBox, SBox) .WidthOverride(FGlobalData::TrackLength * FGlobalData::DefaultTimeTickSpace) - .HeightOverride(25) + .MaxDesiredHeight(60) [ SAssignNew(TickScrollBox, SScrollBox) .ScrollBarVisibility(EVisibility::Hidden) @@ -514,7 +515,10 @@ void SCutTimeline::RenderGroup() FTextBlockStyle BlackHugeText = FAppStyle::GetWidgetStyle("NormalText"); BlackHugeText.SetFontSize(16); - + if (!bNeedShowPanel) + { + return; + } for (int32 i = 0; i < DeviceTrackGroups.Num(); i++) { @@ -668,7 +672,9 @@ bool SCutTimeline::LoadTimeline(const FString& LoadPath, FTimelineInfo& Info) { if (StaticCastSharedPtr(TrackGroupInstances[l].Head)->TrackData.DeviceTrack.Guid == DeviceTrackGroups[j].DeviceTracks[k].Guid) { + AllClips[i].MovieBrushes = FFFMPEGUtils::GetMovieBrush(&AllClips[i], false); + AllClips[i].AudioBrushes = FFFMPEGUtils::GetAudioBrush(&AllClips[i]); StaticCastSharedPtr(TrackGroupInstances[l].Head)->TrackData.ClipData.Add(AllClips[i]); } } @@ -773,8 +779,16 @@ void SCutTimeline::AddNewDeviceToGroup(FString GroupName, FDeviceTrack DeviceTra TrackData.TrackName = DeviceTrack.DeviceName; TrackData.TrackType = DeviceTrack.DeviceType; TrackData.DeviceTrack = DeviceTrack; + + + AddNewTrack(TrackData, 0, GroupName); RenderGroup(); + + if (DeviceTrack.DeviceType == ETrackType::AtomSphereLightTrack) + { + MainWidgetInterface->OnAddNewTrack(ETrackType::PlayerTrack); + } } END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/SCutTimeline.h b/Source/Cut5/Widgets/SCutTimeline.h index 179efd0..582f82e 100644 --- a/Source/Cut5/Widgets/SCutTimeline.h +++ b/Source/Cut5/Widgets/SCutTimeline.h @@ -131,6 +131,8 @@ public: bool bRenderBox = false; TArray RenderBoxPos {{}, {}}; + + bool bNeedShowPanel = false; }; diff --git a/Source/Cut5/Widgets/SStartMenu.cpp b/Source/Cut5/Widgets/SStartMenu.cpp index 8265261..0637ca1 100644 --- a/Source/Cut5/Widgets/SStartMenu.cpp +++ b/Source/Cut5/Widgets/SStartMenu.cpp @@ -20,11 +20,15 @@ void SStartMenu::Construct(const FArguments& InArgs) + SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) + .Padding(16, 47, 16, 16) [ SNew(SImage) .Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("BackGround.png")), {})) ] + SOverlay::Slot() + .HAlign(HAlign_Fill) + .VAlign(VAlign_Fill) + .Padding(16, 47, 16, 16) [ SNew(SVerticalBox) + SVerticalBox::Slot() diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index 9a3faad..b5557d3 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -55,25 +55,12 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F return FReply::Handled(); } - // if (ClipData->PresetType != EPresetType::NotAPresets) - // { - // for (int32 i = 0; i < ClipData->Cursors.Num(); i++) - // { - // TSharedPtr ClipCursor = SNew(SClipCursor).CursorData(&ClipData->Cursors[i]); // .RenderTransform(FSlateRenderTransform(FVector2D(0, 0))); - // ClipOverlay->AddSlot() - // .HAlign(HAlign_Left) - // .VAlign(VAlign_Center) - // [ - // ClipCursor.ToSharedRef() - // ]; - // } - // } const FVector2D LocalPos = Geometry.AbsoluteToLocal(PointerEvent.GetScreenSpacePosition()); const float DragOffset = MainWidgetInterface->GetCutTimeline()->GetCachedGeometry().AbsoluteToLocal(PointerEvent.GetScreenSpacePosition()).X; if (LocalPos.X <= 10) { - if (ClipData->bCanDrag) + if (ClipData->bCanDrag && !MainWidgetInterface->GetCutTimeline()->SelectedClips.Contains(ClipData->ClipGuid)) { const TSharedPtr Clip2ClipDragDropOperation = MakeShared(); Clip2ClipDragDropOperation->TrackBody = StaticCastSharedPtr(Body); @@ -88,7 +75,7 @@ FReply STimelineClip::OnBorderMouseButtonDown(const FGeometry& Geometry, const F } if (LocalPos.X >= Geometry.GetLocalSize().X - 10) { - if (ClipData->bCanDrag) + if (ClipData->bCanDrag && !MainWidgetInterface->GetCutTimeline()->SelectedClips.Contains(ClipData->ClipGuid)) { const TSharedPtr Clip2ClipDragDropOperation = MakeShared(); Clip2ClipDragDropOperation->TrackBody = StaticCastSharedPtr(Body); @@ -690,7 +677,17 @@ void STimelineClip::UpdateMove(int32 X, int32 DragOffset) FReply STimelineClip::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { const FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); - + bNeedPaintDrag = false; + if (LocalPos.X <= 10) + { + bNeedPaintDrag = true; + PaintDragType = 0; + } + if (LocalPos.X >= MyGeometry.GetLocalSize().X - 10) + { + bNeedPaintDrag = true; + PaintDragType = 1; + } return FReply::Handled(); } @@ -700,28 +697,50 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe { const float XLength = AllottedGeometry.GetLocalSize().X; + const float TotalLength = ((ClipData->ClipEndFrame - ClipData->ClipStartFrame) * FGlobalData::DefaultTimeTickSpace); { - - const float TotalLength = ((ClipData->ClipEndFrame - ClipData->ClipStartFrame) * FGlobalData::DefaultTimeTickSpace); + if (ClipData->AudioBrushes.Num() > 0) { int32 i = 0; const int32 PicLength = TotalLength / ClipData->AudioBrushes.Num(); for (FSlateBrush& SlateBrush : ClipData->AudioBrushes) { - FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 2, AllottedGeometry.ToPaintGeometry(FVector2f(PicLength, AllottedGeometry.GetLocalSize().Y), FSlateLayoutTransform(FVector2f(i * PicLength, 0))), &SlateBrush); + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(PicLength, AllottedGeometry.GetLocalSize().Y), FSlateLayoutTransform(FVector2f(i * PicLength, 0))), &SlateBrush); i++; } } } - + if (ClipData->MovieBrushes.Num() > 0) { - int32 i = 0; - for (FSlateBrush& SlateBrush : ClipData->MovieBrushes) + + int32 Step = ClipData->MovieBrushes.Num(); + const int32 PerImageLength = TotalLength / ClipData->MovieBrushesPath.Num(); + const int32 ShouldPerImageLength = TotalLength / 128; + if (ShouldPerImageLength != 0) { - FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(XLength / ClipData->MovieBrushes.Num(), AllottedGeometry.GetLocalSize().Y), FSlateLayoutTransform(FVector2f(i * (XLength / ClipData->MovieBrushes.Num()), 0))), &SlateBrush); + Step = ClipData->MovieBrushes.Num() / ShouldPerImageLength; + } + + + TArray NewBrushes; + int32 Current = 0; + for (int32 j = 0; j < ShouldPerImageLength; j++) + { + if (ClipData->MovieBrushes.Num() > 0) + NewBrushes.Add(ClipData->MovieBrushes[Current]); + Current += Step; + } + int32 i = 0; + if (NewBrushes.Num() == 0) + { + NewBrushes.Add(ClipData->MovieBrushes[0]); + } + for (FSlateBrush& SlateBrush : NewBrushes) + { + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(XLength / NewBrushes.Num(), AllottedGeometry.GetLocalSize().Y), FSlateLayoutTransform(FVector2f(i * (XLength / NewBrushes.Num()), 0))), &SlateBrush); i++; } } @@ -730,11 +749,11 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (ClipData->PresetType == EPresetType::EnableProjector) { - FSlateDrawElement::MakeText(OutDrawElements, LayerId + 2, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("开启投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("开启投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } if (ClipData->PresetType == EPresetType::DisableProjector) { - FSlateDrawElement::MakeText(OutDrawElements, LayerId + 2, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("关闭投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); + FSlateDrawElement::MakeText(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(), FText::FromString(TEXT("关闭投影仪")), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor::White); } @@ -746,7 +765,7 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe Vectors.Add(FVector2f(0, AllottedGeometry.Size.Y)); Vectors.Add(FVector2f(AllottedGeometry.Size.X, AllottedGeometry.Size.Y)); Vectors.Add(FVector2f(AllottedGeometry.Size.X, 0)); - FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 2, AllottedGeometry.ToPaintGeometry(), Vectors, ESlateDrawEffect::None, FLinearColor::White, true, 2.0f); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(), Vectors, ESlateDrawEffect::None, FLinearColor::White, true, 2.0f); return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId + 1, InWidgetStyle, bParentEnabled); } @@ -782,7 +801,7 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe if (ClipData->PresetType == EPresetType::Color) { const FSlateBrush Brush; - FSlateDrawElement::MakeBox(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(), &Brush, ESlateDrawEffect::None, ClipData->ClipColors[0]); } if (ClipData->PresetType == EPresetType::Gradient) @@ -799,6 +818,22 @@ int32 STimelineClip::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe EOrientation::Orient_Vertical, ESlateDrawEffect::None); } + if (bNeedPaintDrag) + { + if (PaintDragType == 0) + { + const FSlateBrush Brush; + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(10, AllottedGeometry.Size.Y), FSlateLayoutTransform(FVector2f(0, 0))), + &Brush, ESlateDrawEffect::None, FLinearColor(1.0, 0.0, 1.0, 1.0)); + } + else if (PaintDragType == 1) + { + const FSlateBrush Brush; + FSlateDrawElement::MakeBox(OutDrawElements, LayerId + 3, AllottedGeometry.ToPaintGeometry(FVector2f(10, AllottedGeometry.Size.Y), FSlateLayoutTransform(FVector2f(AllottedGeometry.Size.X - 10, 0))), + &Brush, ESlateDrawEffect::None, FLinearColor(1.0, 0.0, 1.0, 1.0)); + } + + } return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId + 1, InWidgetStyle, @@ -817,9 +852,12 @@ void STimelineClip::DoSound(ESoundSolveType SolveType, int32 InFrame) { if (SoundThread == nullptr) { - SoundThread = new FSoundThread(2, ClipData->ResourcePropertyDataPtr->AudioSample); - FRunnableThread* Thread = FRunnableThread::Create(SoundThread, TEXT("SoundThread")); - SoundThread->CopyAudio(ClipData->ResourcePropertyDataPtr->AudioData.GetData(), ClipData->ResourcePropertyDataPtr->AudioData.Num(), SolveType); + if (ClipData->ResourcePropertyDataPtr->AudioStream != -1) + { + SoundThread = new FSoundThread(2, ClipData->ResourcePropertyDataPtr->AudioSample); + FRunnableThread* Thread = FRunnableThread::Create(SoundThread, TEXT("SoundThread")); + SoundThread->CopyAudio(ClipData->ResourcePropertyDataPtr->AudioData.GetData(), ClipData->ResourcePropertyDataPtr->AudioData.Num(), SolveType); + } } const int32 Offset = InFrame - ClipData->ClipStartFrame; const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset; @@ -840,5 +878,17 @@ void STimelineClip::OnDragLeave(const FDragDropEvent& DragDropEvent) bIsDragOver = false; } +void STimelineClip::OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) +{ + SCompoundWidget::OnMouseEnter(MyGeometry, MouseEvent); + +} + +void STimelineClip::OnMouseLeave(const FPointerEvent& MouseEvent) +{ + SCompoundWidget::OnMouseLeave(MouseEvent); + bNeedPaintDrag = false; +} + END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/Cut5/Widgets/STimelineClip.h b/Source/Cut5/Widgets/STimelineClip.h index 2ae6366..0a20dc7 100644 --- a/Source/Cut5/Widgets/STimelineClip.h +++ b/Source/Cut5/Widgets/STimelineClip.h @@ -63,6 +63,12 @@ public: virtual void OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override; virtual void OnDragLeave(const FDragDropEvent& DragDropEvent) override; + virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; + virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override; + + bool bNeedPaintDrag = false; + int32 PaintDragType = 0; + bool bIsDragOver = false; }; diff --git a/Source/Cut5/Widgets/STimelinePropertyPanel.cpp b/Source/Cut5/Widgets/STimelinePropertyPanel.cpp index d0d7646..9b5024a 100644 --- a/Source/Cut5/Widgets/STimelinePropertyPanel.cpp +++ b/Source/Cut5/Widgets/STimelinePropertyPanel.cpp @@ -73,7 +73,7 @@ void STimelinePropertyPanel::Construct(const FArguments& InArgs) } } FDeviceTrack DeviceTrack(TEXT("玩家"), ETrackType::AtomSphereLightTrack); - MainWindow->CutTimeline->AddNewDeviceToGroup(TEXT("角色组") + FString::FromInt(Index), DeviceTrack, ETrackType::PlayerTrack); + MainWindow->CutTimeline->AddNewDeviceToGroup(TEXT("角色组") + FString::FromInt(Index), DeviceTrack, ETrackType::AtomSphereLightTrack); return FReply::Handled(); }) ] diff --git a/Source/Cut5/Widgets/STimelineTick.cpp b/Source/Cut5/Widgets/STimelineTick.cpp index fe4587b..fa57bd7 100644 --- a/Source/Cut5/Widgets/STimelineTick.cpp +++ b/Source/Cut5/Widgets/STimelineTick.cpp @@ -6,6 +6,8 @@ #include "AudioDevice.h" #include "DefineGlobal.h" #include "SlateOptMacros.h" +#include "Cut5/Utils/Utils.h" +#include "Rendering/SlateDrawBuffer.h" BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION @@ -65,7 +67,7 @@ int32 STimelineTick::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe ESlateDrawEffect::None, FColor(55, 55, 55, 255)); } - if (j % 10 == 0) + if (j % 30 == 0) { const FSlateBrush Brush; FSlateDrawElement::MakeBox( @@ -75,6 +77,11 @@ int32 STimelineTick::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe &Brush, ESlateDrawEffect::None, FColor(95, 95, 95, 255)); + const FPaintGeometry NewTextLoc = AllottedGeometry.ToPaintGeometry(FVector2f(2, TickBox->GetCachedGeometry().GetLocalSize().Y + 2) + , FSlateLayoutTransform(FVector2f(TickBox->GetCachedGeometry().GetLocalPositionAtCoordinates(FVector2f(0.0, 0.0)).X + j * FGlobalData::DefaultTimeTickSpace, 5))); + FSlateDrawElement::MakeText( + OutDrawElements, LayerId, NewTextLoc, FGlobalData::GetTimeData(j), FAppStyle::Get().GetWidgetStyle("NormalText").Font, ESlateDrawEffect::None, FLinearColor(1.0, 1.0, 1.0, 0.5)); + } } diff --git a/Source/Cut5/Widgets/StatePanel/SStatePanel.cpp b/Source/Cut5/Widgets/StatePanel/SStatePanel.cpp index f803cf1..6a3aef1 100644 --- a/Source/Cut5/Widgets/StatePanel/SStatePanel.cpp +++ b/Source/Cut5/Widgets/StatePanel/SStatePanel.cpp @@ -189,13 +189,22 @@ void SStatePanel::Construct(const FArguments& InArgs) .WidthOverride(100) .HeightOverride(60) [ - SNew(SButton) + SAssignNew(SwitchButton, SButton) .OnClicked_Lambda([this]() { ShowSwitcher->SetActiveWidgetIndex(!bIsVideo); bIsVideo = !bIsVideo; + if (bIsVideo) + { + SwitchButton->SetContent(VideoPlayer.ToSharedRef()); + } + else + { + SwitchButton->SetContent(LightArray.ToSharedRef()); + } return FReply::Handled(); }) + ] ] @@ -226,7 +235,7 @@ void SStatePanel::Construct(const FArguments& InArgs) ] ]; - + SwitchButton->SetContent(LightArray.ToSharedRef()); } diff --git a/Source/Cut5/Widgets/StatePanel/SStatePanel.h b/Source/Cut5/Widgets/StatePanel/SStatePanel.h index 64e581d..1fef961 100644 --- a/Source/Cut5/Widgets/StatePanel/SStatePanel.h +++ b/Source/Cut5/Widgets/StatePanel/SStatePanel.h @@ -30,6 +30,6 @@ public: TSharedPtr MainShow; TSharedPtr Projector; TSharedPtr SpotLight; - + TSharedPtr SwitchButton; bool bIsVideo = false; };