commit 0f9619fef01e90e71278e20e7add915887008b35 Author: zhangmiao <123@123.com> Date: Mon Aug 25 15:12:17 2025 +0800 first commit diff --git a/AdvancedMovieTracks/AdvancedMovieTracks.uplugin b/AdvancedMovieTracks/AdvancedMovieTracks.uplugin new file mode 100644 index 0000000..aa4a916 --- /dev/null +++ b/AdvancedMovieTracks/AdvancedMovieTracks.uplugin @@ -0,0 +1,29 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "0.2", + "FriendlyName": "AdvancedMovieTracks", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "IsExperimentalVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "AdvancedMovieTracks", + "Type": "Runtime", + "LoadingPhase": "Default" + }, + { + "Name": "AdvancedMovieTracksEditor", + "Type": "Editor", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/AdvancedMovieTracks/Config/FilterPlugin.ini b/AdvancedMovieTracks/Config/FilterPlugin.ini new file mode 100644 index 0000000..ccebca2 --- /dev/null +++ b/AdvancedMovieTracks/Config/FilterPlugin.ini @@ -0,0 +1,8 @@ +[FilterPlugin] +; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and +; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. +; +; Examples: +; /README.txt +; /Extras/... +; /Binaries/ThirdParty/*.dll diff --git a/AdvancedMovieTracks/Resources/Icon128.png b/AdvancedMovieTracks/Resources/Icon128.png new file mode 100644 index 0000000..1231d4a Binary files /dev/null and b/AdvancedMovieTracks/Resources/Icon128.png differ diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/AdvancedMovieTracks.Build.cs b/AdvancedMovieTracks/Source/AdvancedMovieTracks/AdvancedMovieTracks.Build.cs new file mode 100644 index 0000000..ac1b9de --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/AdvancedMovieTracks.Build.cs @@ -0,0 +1,53 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class AdvancedMovieTracks : ModuleRules +{ + public AdvancedMovieTracks(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core","MovieSceneTracks","MovieScene","CinematicCamera" + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", "LevelSequence", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/CameraCutCameraCompHook.cpp b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CameraCutCameraCompHook.cpp new file mode 100644 index 0000000..773e588 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CameraCutCameraCompHook.cpp @@ -0,0 +1,107 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CameraCutCameraCompHook.h" + +#include "LevelSequence.h" +#include "LevelSequencePlayer.h" +#include "Camera/CameraComponent.h" +#include "Sections/MovieSceneCameraCutSection.h" +#include "Tracks/MovieSceneCameraCutTrack.h" + + +// Sets default values for this component's properties +UCameraCutCameraCompHook::UCameraCutCameraCompHook() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + // ... +} + + +// Called when the game starts +void UCameraCutCameraCompHook::BeginPlay() +{ + Super::BeginPlay(); + + // ... + +} + + +// Called every frame +void UCameraCutCameraCompHook::TickComponent(float DeltaTime, ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + if (!MyLevelSequencePlayer) return; + + // 获取 CameraCut 轨道 + ULevelSequence* LevelSequence = Cast(MyLevelSequencePlayer->GetSequence()); + if (!LevelSequence) return; + UMovieSceneCameraCutTrack* CameraCutTrack = Cast(LevelSequence->GetMovieScene()->GetCameraCutTrack()); + if (!CameraCutTrack) return; + + + //FQualifiedFrameTime CurrentTime = MyLevelSequencePlayer->GetCurrentTime(); // 获取当前时间 + //auto CurrentFrame = CurrentTime.Time.FrameNumber*800;//不够精确 + + // 获取当前播放帧 + FFrameRate TickResolution = LevelSequence->GetMovieScene() ->GetTickResolution(); + FQualifiedFrameTime QualifiedTime = MyLevelSequencePlayer->GetCurrentTime(); + FFrameTime TimeInTick = ConvertFrameTime(QualifiedTime.Time, QualifiedTime.Rate, TickResolution); + FFrameNumber CurrentTickFrame = TimeInTick.GetFrame(); + // 查找当前激活的 CameraCut 段 + UCameraComponent* ActiveCamComp = nullptr; + for (UMovieSceneSection* Section : CameraCutTrack->GetAllSections()) + { + if (UMovieSceneCameraCutSection* CamSection = Cast(Section)) + { + auto StartFrame = CamSection->GetInclusiveStartFrame(); + auto EndFrame = CamSection->GetExclusiveEndFrame(); + if (CurrentTickFrame >= StartFrame && CurrentTickFrame < EndFrame) + { + // 获取绑定的对象 + TArray BoundObjs = MyLevelSequencePlayer->GetBoundObjects(CamSection->GetCameraBindingID()); + for (UObject* Obj : BoundObjs) + { + if (AActor* Actor = Cast(Obj)) + { + ActiveCamComp = Actor->FindComponentByClass(); + } + else if (UCameraComponent* CamComp = Cast(Obj)) + { + ActiveCamComp = CamComp; + } + if (ActiveCamComp) break; + } + break; + } + } + } + FoundCamera = nullptr; + // 如果找到摄像机组件,就可以获取其位置 + if (ActiveCamComp) + { + FoundCamera = ActiveCamComp; + FVector CamLocation = ActiveCamComp->GetComponentLocation(); + FString CamName = ActiveCamComp->GetOwner()-> GetName(); + if(bNeedDebug) + { + UE_LOG(LogTemp, Log, TEXT("Current Camera position: %s,Name: %s"), *CamLocation.ToString(), *CamName); + GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Orange, FString::Printf(TEXT("Current Camera position: %s,Name: %s"), *CamLocation.ToString(), *CamName)); + DrawDebugSphere(GetOwner()->GetWorld(), CamLocation, 36.f, 12, FColor::Cyan, false, 0.2f, 0, 1.f); + } + // 可以在这里对相机位置进行处理 + } +} + +bool UCameraCutCameraCompHook::FoundCameraComp(UCameraComponent*& FoundCameraComp) +{ + FoundCameraComp = FoundCamera; + return IsValid(FoundCamera); +} + diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/CameraCutCameraCompHook.h b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CameraCutCameraCompHook.h new file mode 100644 index 0000000..23d1bb0 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CameraCutCameraCompHook.h @@ -0,0 +1,44 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "CameraCutCameraCompHook.generated.h" + + +class UCameraComponent; +class ULevelSequencePlayer; + +/** + * This Component Must Tick while you're using FoundCameraComp() + */ +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class ADVANCEDMOVIETRACKS_API UCameraCutCameraCompHook : public UActorComponent +{ + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UCameraCutCameraCompHook(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + + UPROPERTY(BlueprintReadWrite,VisibleAnywhere,meta=(AllowPrivateAccess=true)) + ULevelSequencePlayer* MyLevelSequencePlayer; + UPROPERTY() + UCameraComponent* FoundCamera; +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; + + UPROPERTY(BlueprintReadWrite, VisibleAnywhere, meta = (AllowPrivateAccess = true)) + bool bNeedDebug = false; + + UFUNCTION(BlueprintPure) + bool FoundCameraComp(UCameraComponent*& FoundCameraComp); + +}; diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/CineCustomedCameraActor.cpp b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CineCustomedCameraActor.cpp new file mode 100644 index 0000000..7b5c165 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CineCustomedCameraActor.cpp @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CineCustomedCameraActor.h" +//#include "CineCameraActor.h" + + + +ACineCustomedCameraActor::ACineCustomedCameraActor(const FObjectInitializer& ObjectInitializer) + :Super(ObjectInitializer) +{ + PrimaryActorTick.bCanEverTick = true; +} + +// Called when the game starts or when spawned +void ACineCustomedCameraActor::BeginPlay() +{ + Super::BeginPlay(); + +} + +void ACineCustomedCameraActor::NotifyCameraCut() +{ + FString a(FString::Printf(TEXT("CameraCutIn:%s"),*GetName())); + if (GEngine) + { + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, a); + } + UE_LOG(LogTemp, Warning, TEXT("%s"),*a); + + Super::NotifyCameraCut(); +} + +// Called every frame +void ACineCustomedCameraActor::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/CineCustomedCameraActor.h b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CineCustomedCameraActor.h new file mode 100644 index 0000000..dadf07c --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CineCustomedCameraActor.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "CineCameraActor.h" + +#include "CineCustomedCameraActor.generated.h" + + + +UCLASS() +class ADVANCEDMOVIETRACKS_API ACineCustomedCameraActor : public ACineCameraActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + + ACineCustomedCameraActor(const FObjectInitializer& ObjectInitializer); +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + virtual void NotifyCameraCut() override; +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + +}; diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/CustomAudioTrack.cpp b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CustomAudioTrack.cpp new file mode 100644 index 0000000..4f22a01 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CustomAudioTrack.cpp @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CustomAudioTrack.h" + + + + +void UCustomAudioTrack::Serialize(FArchive& Ar) +{ + Super::Serialize(Ar); +} + +bool UCustomAudioTrack::Rename(const TCHAR* NewName, UObject* NewOuter, ERenameFlags Flags) +{ + RuntimeName = NewName; + return Super::Rename(NewName, NewOuter, Flags); +} + + + +bool UCustomAudioTrack::SupportsType(TSubclassOf SectionClass) const +{ + return Super::SupportsType(SectionClass); +} + +void UCustomAudioTrack::RemoveAllAnimationData() +{ + Super::RemoveAllAnimationData(); +} + +bool UCustomAudioTrack::HasSection(const UMovieSceneSection& Section) const +{ + return Super::HasSection(Section); +} + +void UCustomAudioTrack::AddSection(UMovieSceneSection& Section) +{ + Super::AddSection(Section); +} + +void UCustomAudioTrack::RemoveSection(UMovieSceneSection& Section) +{ + Super::RemoveSection(Section); +} + +void UCustomAudioTrack::RemoveSectionAt(int32 SectionIndex) +{ + Super::RemoveSectionAt(SectionIndex); +} + +bool UCustomAudioTrack::IsEmpty() const +{ + return Super::IsEmpty(); +} + +const TArray& UCustomAudioTrack::GetAllSections() const +{ + return Super::GetAllSections(); +} + +bool UCustomAudioTrack::SupportsMultipleRows() const +{ + return Super::SupportsMultipleRows(); +} + +UMovieSceneSection* UCustomAudioTrack::CreateNewSection() +{ + return Super::CreateNewSection(); +} + diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/CustomAudioTrack.h b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CustomAudioTrack.h new file mode 100644 index 0000000..cb9b0d3 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/CustomAudioTrack.h @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +//"CustomAudioTrack.h" + +#include "CoreMinimal.h" +#include "Evaluation/MovieSceneEvalTemplate.h" + +#include "Tracks/MovieSceneAudioTrack.h" + +#include "CustomAudioTrack.generated.h" + + +/** + * + */ +UCLASS() +class ADVANCEDMOVIETRACKS_API UCustomAudioTrack : public UMovieSceneAudioTrack +{ + GENERATED_BODY() + +public: + // ... 之前的代码 ... + + // 重写显示名称 +#if WITH_EDITOR + virtual FText GetDisplayName() const override + { + if (!RuntimeName.IsNone()) + { + return FText::FromName(RuntimeName); + } + return Super::GetDisplayName(); + } +#endif +#if WITH_EDITORONLY_DATA + virtual FText GetDefaultDisplayName() const override { return FText::FromString(TEXT("CustomAudioTrack")); }; + virtual void SetDisplayName(const FText& NewDisplayName)override { + RuntimeName = *NewDisplayName.ToString(); + Super::SetDisplayName(NewDisplayName); + } +#endif + // UMovieSceneTrack interface + virtual bool SupportsType(TSubclassOf SectionClass) const override; + virtual void RemoveAllAnimationData() override; + virtual bool HasSection(const UMovieSceneSection& Section) const override; + virtual void AddSection(UMovieSceneSection& Section) override; + virtual void RemoveSection(UMovieSceneSection& Section) override; + virtual void RemoveSectionAt(int32 SectionIndex) override; + virtual bool IsEmpty() const override; + virtual const TArray& GetAllSections() const override; + virtual bool SupportsMultipleRows() const override; + virtual UMovieSceneSection* CreateNewSection() override; + // 支持序列化 + virtual void Serialize(FArchive& Ar) override; + + virtual bool Rename(const TCHAR* NewName = nullptr, UObject* NewOuter = nullptr, ERenameFlags Flags = REN_None)override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Identification", meta = (DisplayName = "Track Name")) + FName RuntimeName; + + /*UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Identification", meta = (DisplayName = "Track Name")) + FName RuntimeNameA;*/ +}; diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/Private/AdvancedMovieTracks.cpp b/AdvancedMovieTracks/Source/AdvancedMovieTracks/Private/AdvancedMovieTracks.cpp new file mode 100644 index 0000000..a930cd2 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/Private/AdvancedMovieTracks.cpp @@ -0,0 +1,35 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "AdvancedMovieTracks.h" + + + +#define LOCTEXT_NAMESPACE "FAdvancedMovieTracksModule" + +void FAdvancedMovieTracksModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + //ISequencerModule& SequencerModule = FModuleManager::Get().LoadModuleChecked("Sequencer"); + + //// עԶ༭ + //TrackEditorBindingHandle = SequencerModule.RegisterTrackEditor( + // FOnCreateTrackEditor::CreateStatic(&FCustomAudioTrackEditor::CreateTrackEditor) + //); + +} + +void FAdvancedMovieTracksModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + + /*ISequencerModule* SequencerModule = FModuleManager::Get().GetModulePtr("Sequencer"); + if (SequencerModule) + { + SequencerModule->UnRegisterTrackEditor(TrackEditorBindingHandle); + }*/ +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FAdvancedMovieTracksModule, AdvancedMovieTracks) \ No newline at end of file diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracks/Public/AdvancedMovieTracks.h b/AdvancedMovieTracks/Source/AdvancedMovieTracks/Public/AdvancedMovieTracks.h new file mode 100644 index 0000000..965c74b --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracks/Public/AdvancedMovieTracks.h @@ -0,0 +1,16 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" + +class FAdvancedMovieTracksModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +private: + FDelegateHandle TrackEditorBindingHandle; +}; diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/AdvancedMovieTracksEditor.Build.cs b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/AdvancedMovieTracksEditor.Build.cs new file mode 100644 index 0000000..c921824 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/AdvancedMovieTracksEditor.Build.cs @@ -0,0 +1,64 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class AdvancedMovieTracksEditor : ModuleRules +{ + public AdvancedMovieTracksEditor(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core","MovieSceneTracks","MovieScene","AdvancedMovieTracks" + // ... add other public dependencies that you statically link with here ... + } + ); + if (Target.bBuildWithEditorOnlyData && Target.bBuildEditor) + { + PublicDependencyModuleNames.AddRange(new string[] + { + "UnrealEd" + }); + PrivateDependencyModuleNames.AddRange(new string[] + { + + "UnrealEd", "Sequencer" + }); + } + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/CustomAudioTrackEditor.cpp b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/CustomAudioTrackEditor.cpp new file mode 100644 index 0000000..ce959e6 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/CustomAudioTrackEditor.cpp @@ -0,0 +1,105 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "CustomAudioTrackEditor.h" +#include "AdvancedMovieTracks/CustomAudioTrack.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" + +#if WITH_EDITOR +#include "Sections/MovieSceneAudioSection.h" + + +#define LOCTEXT_NAMESPACE "FAudioTrackEditor" + +FCustomAudioTrackEditor::FCustomAudioTrackEditor(TSharedRef InSequencer) + : FMovieSceneTrackEditor(InSequencer) +{ +} + + + +//UMovieSceneTrack* FCustomAudioTrackEditor::AddTrack(UMovieScene* FocusedMovieScene, const FGuid& ObjectHandle, TSubclassOf TrackClass, FName UniqueTypeName) const +//{ +// //// 确保是自定义轨道类型 +// //if (TrackClass == UCustomAudioTrack::StaticClass()) +// //{ +// // // 创建轨道 +// // UCustomAudioTrack* NewTrack = FocusedMovieScene->AddMasterTrack(); +// // NewTrack->SetDisplayName(FText::FromString("Custom Audio Track")); +// // return NewTrack; +// //} +// //return nullptr; +// return FocusedMovieScene->AddTrack(TrackClass, ObjectHandle); +//} + +void FCustomAudioTrackEditor::BuildAddTrackMenu(FMenuBuilder& MenuBuilder) +{ + MenuBuilder.AddMenuEntry( + FText::FromString("Custom Audio Track"), + FText::FromString("Adds a custom audio track"), + FSlateIcon(), + FUIAction(FExecuteAction::CreateRaw(this, &FCustomAudioTrackEditor::HandleAddAudioTrackMenuEntryExecute)) + ); +} +void FCustomAudioTrackEditor::HandleAddAudioTrackMenuEntryExecute() +{ + UMovieScene* FocusedMovieScene = GetFocusedMovieScene(); + + if (FocusedMovieScene == nullptr) + { + return; + } + + if (FocusedMovieScene->IsReadOnly()) + { + return; + } + + const FScopedTransaction Transaction(NSLOCTEXT("Sequencer", "AddAudioTrack_Transaction", "Add My Audio Track")); + FocusedMovieScene->Modify(); + + auto NewTrack = FocusedMovieScene->AddTrack(); + ensure(NewTrack); + + NewTrack->SetDisplayName(FText::FromString(TEXT("My Audio"))); + + if (GetSequencer().IsValid()) + { + GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::TrackValueChanged); + // 或者 NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemsChanged) 视场景而定 + + GetSequencer()->OnAddTrack(NewTrack, FGuid()); + } +} + + +bool FCustomAudioTrackEditor::SupportsType(TSubclassOf TrackClass) const +{ + return TrackClass == UCustomAudioTrack::StaticClass(); +} + +TSharedRef FCustomAudioTrackEditor::CreateTrackEditor(TSharedRef InSequencer) +{ + return MakeShared(InSequencer); +} +// +//void FCustomAudioTrackEditor::HandleAddTrack() +//{ +// UMovieScene* FocusedMovieScene = GetFocusedMovieScene(); +// if (FocusedMovieScene) +// { +// // 添加轨道 +// UCustomAudioTrack* NewTrack = FocusedMovieScene->AddMasterTrack(); +// if (NewTrack) +// { +// // 添加默认音频片段 +// NewTrack->AddNewSound(nullptr, 0.0f); +// +// // 通知Sequencer刷新 +// GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemAdded); +// } +// } +//} + +#undef LOCTEXT_NAMESPACE + +#endif diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/CustomAudioTrackEditor.h b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/CustomAudioTrackEditor.h new file mode 100644 index 0000000..c8bf992 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/CustomAudioTrackEditor.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +// "CustomAudioTrackEditor.h" + +#include "CoreMinimal.h" + +#if WITH_EDITOR +#include "MovieSceneTrackEditor.h" +class FCustomAudioTrackEditor : public FMovieSceneTrackEditor +{ +public: + FCustomAudioTrackEditor(TSharedRef InSequencer); + + // 创建轨道实例 + //virtual UMovieSceneTrack* AddTrack(UMovieScene* FocusedMovieScene, const FGuid& ObjectHandle, TSubclassOf TrackClass, FName UniqueTypeName) const override; + + + // 在菜单中显示 + virtual void BuildAddTrackMenu(FMenuBuilder& MenuBuilder) override; + + // 检查是否支持添加轨道 + virtual bool SupportsType(TSubclassOf TrackClass) const override; + + // 工厂创建函数 + static TSharedRef CreateTrackEditor(TSharedRef InSequencer); +private: + virtual void HandleAddAudioTrackMenuEntryExecute(); +}; + +#endif diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/Private/AdvancedMovieTracksEditor.cpp b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/Private/AdvancedMovieTracksEditor.cpp new file mode 100644 index 0000000..9561ba7 --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/Private/AdvancedMovieTracksEditor.cpp @@ -0,0 +1,41 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "AdvancedMovieTracksEditor.h" + +#if WITH_EDITOR + +#include "AdvancedMovieTracks.h" +#include "ISequencerModule.h" +#include "AdvancedMovieTracksEditor/CustomAudioTrackEditor.h" + +#define LOCTEXT_NAMESPACE "FAdvancedMovieTracksEditorModule" + +void FAdvancedMovieTracksEditorModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + ISequencerModule& SequencerModule = FModuleManager::Get().LoadModuleChecked("Sequencer"); + + // עԶ༭ + TrackEditorBindingHandle = SequencerModule.RegisterTrackEditor( + FOnCreateTrackEditor::CreateStatic(&FCustomAudioTrackEditor::CreateTrackEditor) + ); + +} + +void FAdvancedMovieTracksEditorModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + + ISequencerModule* SequencerModule = FModuleManager::Get().GetModulePtr("Sequencer"); + if (SequencerModule) + { + SequencerModule->UnRegisterTrackEditor(TrackEditorBindingHandle); + } +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FAdvancedMovieTracksEditorModule, AdvancedMovieTracksEditor) + +#endif diff --git a/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/Public/AdvancedMovieTracksEditor.h b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/Public/AdvancedMovieTracksEditor.h new file mode 100644 index 0000000..b6cb69a --- /dev/null +++ b/AdvancedMovieTracks/Source/AdvancedMovieTracksEditor/Public/AdvancedMovieTracksEditor.h @@ -0,0 +1,16 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" + +class FAdvancedMovieTracksEditorModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +private: + FDelegateHandle TrackEditorBindingHandle; +};