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/Source/Cut5/Utils/FFMPEGUtils.cpp b/Source/Cut5/Utils/FFMPEGUtils.cpp index 9a1f7c1..ffca877 100644 --- a/Source/Cut5/Utils/FFMPEGUtils.cpp +++ b/Source/Cut5/Utils/FFMPEGUtils.cpp @@ -13,10 +13,22 @@ #include "Serialization/BufferArchive.h" +// Use Relative Path FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* PropertyData) { + + FString NewPath; + if (FPaths::IsRelative(Path)) + { + NewPath = FGlobalData::BasePath / FGlobalData::CurrentProjectName / Path; + } + else + { + NewPath = Path; + } + AVFormatContext* FormatContext = nullptr; - if (avformat_open_input(&FormatContext, TCHAR_TO_UTF8(*Path), nullptr, nullptr) != 0) + if (avformat_open_input(&FormatContext, TCHAR_TO_UTF8(*NewPath), nullptr, nullptr) != 0) { return TEXT("Failed"); } @@ -185,7 +197,7 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop } PropertyData->Name = FPaths::GetBaseFilename(Path); - PropertyData->MoviePath = Path; + PropertyData->MoviePath = NewPath; return {}; diff --git a/Source/Cut5/Widgets/DefineGlobal.h b/Source/Cut5/Widgets/DefineGlobal.h index 26b25e9..a303974 100644 --- a/Source/Cut5/Widgets/DefineGlobal.h +++ b/Source/Cut5/Widgets/DefineGlobal.h @@ -788,6 +788,7 @@ struct CUT5_API FEffectCardProperty int32 ID = 0; TArray UsedCurtains; FStringWithGUID JumpStepCurtains; + bool IsGlobal = true; bool IsClone = false; friend FArchive& operator<<(FArchive& Ar, FEffectCardProperty& EffectCardProperty) @@ -799,6 +800,7 @@ struct CUT5_API FEffectCardProperty Ar << EffectCardProperty.UsedCurtains; Ar << EffectCardProperty.JumpStepCurtains; Ar << EffectCardProperty.IsClone; + Ar << EffectCardProperty.IsGlobal; return Ar; }; @@ -821,6 +823,8 @@ struct CUT5_API FEffectCardGroup int32 ID = 0; TArray UsedCurtains; FStringWithGUID JumpStepCurtains; + bool IsGlobal = true; + friend FArchive& operator<<(FArchive& Ar, FEffectCardGroup& EffectCard) { Ar << EffectCard.GroupName; @@ -833,6 +837,7 @@ struct CUT5_API FEffectCardGroup Ar << EffectCard.ID; Ar << EffectCard.UsedCurtains; Ar << EffectCard.JumpStepCurtains; + Ar << EffectCard.IsGlobal; return Ar; }; }; diff --git a/Source/Cut5/Widgets/FX/SEffectCard.cpp b/Source/Cut5/Widgets/FX/SEffectCard.cpp index 560c82c..450cc91 100644 --- a/Source/Cut5/Widgets/FX/SEffectCard.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCard.cpp @@ -294,7 +294,7 @@ TSharedPtr SEffectCard::GetPropertiesWidget() FTextBlockStyle NormalText = FAppStyle::GetWidgetStyle("NormalText"); NormalText.SetFontSize(13); - + PropertiesWidget = SNew(SVerticalBox) + SVerticalBox::Slot() @@ -618,6 +618,49 @@ TSharedPtr SEffectCard::GetPropertiesWidget() ] ] ] + ] + + SVerticalBox::Slot() + .SizeParam(FAuto()) + .Padding(0, 13, 0, 0) + [ + SNew(SBox).HeightOverride(32).WidthOverride(214) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .VAlign(VAlign_Center) + [ + SNew(SBox) + .WidthOverride(62) + .HeightOverride(32) + .VAlign(VAlign_Center) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("全局"))) + .Font(NormalText.Font) + .Justification(ETextJustify::Center) + ] + ] + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .HAlign(HAlign_Right) + [ + SNew(SBox) + .WidthOverride(136) + .HeightOverride(32) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() + { + return this->CardProperty->IsGlobal ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](const ECheckBoxState State) + { + this->CardProperty->IsGlobal = State == ECheckBoxState::Checked; + }) + ] + ] + ] ]; return PropertiesWidget; diff --git a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp index c6c4591..ea16acb 100644 --- a/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp +++ b/Source/Cut5/Widgets/FX/SEffectCardGroup.cpp @@ -420,8 +420,52 @@ void SEffectCardGroup::Construct(const FArguments& InArgs) ] ] ] + ] + + SVerticalBox::Slot() + .SizeParam(FAuto()) + .Padding(0, 13, 0, 0) + [ + SNew(SBox).HeightOverride(32).WidthOverride(214) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .VAlign(VAlign_Center) + [ + SNew(SBox) + .WidthOverride(62) + .HeightOverride(32) + .VAlign(VAlign_Center) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("全局"))) + .Font(NormalText.Font) + .Justification(ETextJustify::Center) + ] + ] + + SHorizontalBox::Slot() + .SizeParam(FAuto()) + .HAlign(HAlign_Right) + [ + SNew(SBox) + .WidthOverride(136) + .HeightOverride(32) + [ + SNew(SCheckBox) + .IsChecked_Lambda([this]() + { + return this->EffectCardGroup->IsGlobal ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; + }) + .OnCheckStateChanged_Lambda([this](const ECheckBoxState State) + { + this->EffectCardGroup->IsGlobal = State == ECheckBoxState::Checked; + }) + ] + ] + ] ]; + PropertiesInterfaceGUID = EffectCardGroup->Guid; CallRender(); } diff --git a/Source/Cut5/Widgets/SCustomInputPanel.cpp b/Source/Cut5/Widgets/SCustomInputPanel.cpp index 5fb3158..1cf481d 100644 --- a/Source/Cut5/Widgets/SCustomInputPanel.cpp +++ b/Source/Cut5/Widgets/SCustomInputPanel.cpp @@ -254,12 +254,31 @@ void SCustomInputPanel::Construct(const FArguments& InArgs) DesktopPlatformModule->OpenFileDialog(nullptr, (TEXT("打开文件")), TEXT(""), TEXT(""), TEXT(""), EFileDialogFlags::Multiple, OpenFileName); for (int32 i = 0; i < OpenFileName.Num(); i++) { + AVFormatContext* Context = nullptr; + if (avformat_open_input(&Context, TCHAR_TO_UTF8(*OpenFileName[i]), nullptr, nullptr) != 0) + { + continue; + } + + // Move Video To Save + FString MediaSavePath = FGlobalData::BasePath / FGlobalData::CurrentProjectName / TEXT("MediaFolder"); + if (!FPaths::DirectoryExists(MediaSavePath)) + { + FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*MediaSavePath); + } + FString MediaBaseName = FPaths::GetBaseFilename(OpenFileName[i]) + TEXT(".") + FPaths::GetExtension(OpenFileName[i]); + MediaSavePath = MediaSavePath / MediaBaseName; + IFileManager::Get().Copy(*MediaSavePath, *OpenFileName[i], true, true); + + FString RelativePath = TEXT("MediaFolder") / MediaBaseName; + FTimelinePropertyData Data; - if (FFFMPEGUtils::LoadMedia(OpenFileName[i], &Data) == TEXT("Failed")) + if (FFFMPEGUtils::LoadMedia(RelativePath, &Data) == TEXT("Failed")) { continue; }; + TSharedPtr Resource = SNew(SCustomInputResource).MainInterface(MainWidgetInterface).CustomInputPanel(this) .PropertyData(Data).OnCheckBoxChecked_Lambda([this](FTimelinePropertyData& ClickedData, bool bIsChecked) { diff --git a/Source/Cut5/Widgets/SCutTimeline.cpp b/Source/Cut5/Widgets/SCutTimeline.cpp index f50ba22..dd8c58f 100644 --- a/Source/Cut5/Widgets/SCutTimeline.cpp +++ b/Source/Cut5/Widgets/SCutTimeline.cpp @@ -211,17 +211,38 @@ void SCutTimeline::Construct(const FArguments& InArgs) .MinValue(0.0) .Value_Lambda([this]() { - return FMath::GetMappedRangeValueClamped(FVector2D(30.0, GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength), FVector2D(0, 1.0), FGlobalData::DefaultTimeTickSpace); + return FMath::GetMappedRangeValueClamped(FVector2D(GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength, 15.0), FVector2D(0, 1.0), FGlobalData::DefaultTimeTickSpace); }) .OnValueChanged_Lambda([this](float ChangedValue) { - FGlobalData::DefaultTimeTickSpace = FMath::GetMappedRangeValueClamped(FVector2D(0, 1.0), FVector2D(30.0, GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength), ChangedValue); + FGlobalData::DefaultTimeTickSpace = FMath::GetMappedRangeValueClamped(FVector2D(0, 1.0), FVector2D(GetCachedGeometry().GetLocalSize().X / FGlobalData::TrackLength, 15.0), ChangedValue); UpdateCursorPosition(GetCursorPosition(), false); - // TrackBodyHScrollBox->SetScrollOffset(TimelineTick->GetCursorPosition() * FGlobalData::DefaultTimeTickSpace); - TrackBodyHScrollBox->SetScrollOffset(0.0); - TickScrollBox->SetScrollOffset(TrackBodyHScrollBox->GetScrollOffset()); + + int32 Frame = GetCursorPosition(); + + float Offset = TrackBodyHScrollBox->GetScrollOffset(); + float MaxOffset = TrackBodyHScrollBox->GetScrollOffsetOfEnd(); + float TickOffset = TickScrollBox->GetScrollOffset(); + float TickMaxOffset = TickScrollBox->GetScrollOffsetOfEnd(); + + // GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, FString::Printf(TEXT("Offset: %f, MaxOffset: %f, TickOffset: %f, TickMaxOffset: %f"), Offset, MaxOffset, TickOffset, TickMaxOffset)); + + + + + + TrackBodyHScrollBox->SetScrollOffset(Frame * FGlobalData::DefaultTimeTickSpace); + if (TickScrollBox->GetScrollOffset() > TickScrollBox->GetScrollOffsetOfEnd()) + { + TickScrollBox->SetScrollOffset(TickScrollBox->GetScrollOffsetOfEnd()); + } + else + { + TickScrollBox->SetScrollOffset(TrackBodyHScrollBox->GetScrollOffset()); + } + RenderGroup(); }) diff --git a/Source/Cut5/Widgets/STimelineTick.cpp b/Source/Cut5/Widgets/STimelineTick.cpp index 0e2f94c..b781f5a 100644 --- a/Source/Cut5/Widgets/STimelineTick.cpp +++ b/Source/Cut5/Widgets/STimelineTick.cpp @@ -53,6 +53,8 @@ int32 STimelineTick::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe { int32 TickCount = //(FGlobalData::TrackLength * FGlobalData::CurrentTimeScroll) / FGlobalData::DefaultTimeTickSpace; FGlobalData::TrackLength; + + int32 LastRenderedText = 0; for (int32 j = 0; j < TickCount; j++) { @@ -73,8 +75,8 @@ int32 STimelineTick::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe const int32 Multiplier = FMath::GetMappedRangeValueClamped(FVector2D(500, 1), FVector2D(1, 6), Space); - - if (j % (Multiplier * int32(FGlobalData::GlobalFPS)) == 0) + int32 Result = int32(j * FGlobalData::DefaultTimeTickSpace); + if (FMath::Abs(Result - 100 * (LastRenderedText)) < 14) { const FSlateBrush Brush; FSlateDrawElement::MakeBox( @@ -88,8 +90,9 @@ int32 STimelineTick::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGe , 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)); - + LastRenderedText++; } + } const FSlateBrush Brush;