├── .gitignore ├── Config ├── BaseMDViewModel.ini ├── DefaultMDViewModel.ini └── FilterPlugin.ini ├── LICENSE ├── MDViewModel.uplugin ├── README.md ├── Resources └── Icon128.png └── Source ├── MDViewModel ├── MDViewModel.Build.cs ├── Private │ ├── Bindings │ │ ├── MDVMBlueprintBindingBase.cpp │ │ ├── MDViewModelChangedBinding.cpp │ │ ├── MDViewModelDelegateBinding.cpp │ │ └── MDViewModelFieldNotifyBinding.cpp │ ├── Components │ │ ├── MDVMPCDynamicDelegateIntermediate.cpp │ │ ├── MDVMPCUpdatePollingComponent.cpp │ │ ├── MDVMPSDynamicDelegateIntermediate.cpp │ │ ├── MDVMPawnUpdatePollingComponent.cpp │ │ ├── MDViewModelAssignmentComponent.cpp │ │ └── MDViewModelCacheComponent.cpp │ ├── Interfaces │ │ ├── MDVMCompiledAssignmentsInterface.cpp │ │ ├── MDViewModelCacheInterface.cpp │ │ ├── MDViewModelRuntimeInterface.cpp │ │ └── MDViewModelSupportedInterface.cpp │ ├── MDViewModelModule.cpp │ ├── Subsystems │ │ ├── MDGlobalViewModelCache.cpp │ │ ├── MDLocalPlayerViewModelCache.cpp │ │ ├── MDObjectViewModelCache.cpp │ │ └── MDWorldViewModelCache.cpp │ ├── Util │ │ ├── MDVMAssignmentObjectKey.cpp │ │ ├── MDViewModelAssignment.cpp │ │ ├── MDViewModelAssignmentData.cpp │ │ ├── MDViewModelAssignmentReference.cpp │ │ ├── MDViewModelConfig.cpp │ │ ├── MDViewModelFunctionLibrary.cpp │ │ ├── MDViewModelInstanceKey.cpp │ │ ├── MDViewModelLog.cpp │ │ └── MDViewModelUtils.cpp │ ├── ViewModel │ │ ├── MDViewModelBase.cpp │ │ └── MDViewModelBlueprintBase.cpp │ ├── ViewModelProviders │ │ ├── MDViewModelProviderBase.cpp │ │ ├── MDViewModelProvider_Cached.cpp │ │ ├── MDViewModelProvider_Manual.cpp │ │ └── MDViewModelProvider_Unique.cpp │ ├── WidgetExtensions │ │ ├── MDViewModelWidgetClassExtension.cpp │ │ └── MDViewModelWidgetExtension.cpp │ └── Widgets │ │ ├── MDVMDynamicEntryBox.cpp │ │ ├── MDViewModelComboBox.cpp │ │ ├── MDViewModelSwitcher.cpp │ │ └── MDViewModelSwitcherSlot.cpp └── Public │ ├── Bindings │ ├── MDVMBlueprintBindingBase.h │ ├── MDViewModelChangedBinding.h │ ├── MDViewModelDelegateBinding.h │ └── MDViewModelFieldNotifyBinding.h │ ├── Components │ ├── MDVMPCDynamicDelegateIntermediate.h │ ├── MDVMPCUpdatePollingComponent.h │ ├── MDVMPSDynamicDelegateIntermediate.h │ ├── MDVMPawnUpdatePollingComponent.h │ ├── MDViewModelAssignmentComponent.h │ └── MDViewModelCacheComponent.h │ ├── Interfaces │ ├── MDVMCompiledAssignmentsInterface.h │ ├── MDViewModelCacheInterface.h │ ├── MDViewModelRuntimeInterface.h │ └── MDViewModelSupportedInterface.h │ ├── Subsystems │ ├── MDGlobalViewModelCache.h │ ├── MDLocalPlayerViewModelCache.h │ ├── MDObjectViewModelCache.h │ └── MDWorldViewModelCache.h │ ├── Util │ ├── MDVMAssignmentObjectKey.h │ ├── MDViewModelAssignment.h │ ├── MDViewModelAssignmentData.h │ ├── MDViewModelAssignmentReference.h │ ├── MDViewModelConfig.h │ ├── MDViewModelFunctionLibrary.h │ ├── MDViewModelInstanceKey.h │ ├── MDViewModelLog.h │ ├── MDViewModelMetaUtils.h │ └── MDViewModelUtils.h │ ├── ViewModel │ ├── MDViewModelBase.h │ └── MDViewModelBlueprintBase.h │ ├── ViewModelProviders │ ├── MDViewModelProviderBase.h │ ├── MDViewModelProvider_Cached.h │ ├── MDViewModelProvider_Manual.h │ └── MDViewModelProvider_Unique.h │ ├── WidgetExtensions │ ├── MDViewModelWidgetClassExtension.h │ └── MDViewModelWidgetExtension.h │ └── Widgets │ ├── MDVMDynamicEntryBox.h │ ├── MDViewModelComboBox.h │ ├── MDViewModelSwitcher.h │ └── MDViewModelSwitcherSlot.h ├── MDViewModelEditor ├── MDViewModelEditor.Build.cs ├── Private │ ├── Customizations │ │ ├── MDViewModelAssignmentComponentCustomization.cpp │ │ ├── MDViewModelAssignmentEditorObjectCustomization.cpp │ │ └── MDViewModelAssignmentReferenceCustomization.cpp │ ├── MDViewModelEditorConfig.cpp │ ├── MDViewModelEditorConfig.h │ ├── MDViewModelEditorModule.cpp │ ├── Util │ │ ├── MDVMEditorUtils.cpp │ │ └── MDViewModelClassFilter.cpp │ ├── ViewModelTab │ │ ├── FieldInspector │ │ │ ├── DragAndDrop │ │ │ │ ├── MDVMDragAndDropWrapperButton.cpp │ │ │ │ ├── MDVMInspectorDragAndDropActionBase.cpp │ │ │ │ ├── MDVMInspectorDragAndDropChanged.cpp │ │ │ │ ├── MDVMInspectorDragAndDropCommand.cpp │ │ │ │ ├── MDVMInspectorDragAndDropEvent.cpp │ │ │ │ ├── MDVMInspectorDragAndDropFieldNotify.cpp │ │ │ │ ├── MDVMInspectorDragAndDropFunctionBase.cpp │ │ │ │ ├── MDVMInspectorDragAndDropGetter.cpp │ │ │ │ ├── MDVMInspectorDragAndDropHelper.cpp │ │ │ │ └── MDVMInspectorDragAndDropProperty.cpp │ │ │ ├── MDViewModelChangedDebugLineItem.cpp │ │ │ ├── MDViewModelDebugLineItemBase.cpp │ │ │ ├── MDViewModelEventDebugLineItem.cpp │ │ │ ├── MDViewModelFieldDebugLineItem.cpp │ │ │ ├── MDViewModelFieldInspector.cpp │ │ │ └── MDViewModelFunctionDebugLineItem.cpp │ │ ├── MDViewModelAssignmentDialog.cpp │ │ ├── MDViewModelAssignmentEditorObject.cpp │ │ ├── MDViewModelDetails.cpp │ │ ├── MDViewModelEditor.cpp │ │ ├── MDViewModelEditorCommands.cpp │ │ ├── MDViewModelList.cpp │ │ ├── MDViewModelListItem.cpp │ │ └── MDViewModelTab.cpp │ └── Widgets │ │ └── SMDVMConfigEditor.cpp └── Public │ ├── Customizations │ ├── MDViewModelAssignmentComponentCustomization.h │ ├── MDViewModelAssignmentEditorObjectCustomization.h │ └── MDViewModelAssignmentReferenceCustomization.h │ ├── MDViewModelEditorModule.h │ ├── Util │ ├── MDVMEditorUtils.h │ └── MDViewModelClassFilter.h │ ├── ViewModelTab │ ├── FieldInspector │ │ ├── DragAndDrop │ │ │ ├── MDVMDragAndDropWrapperButton.h │ │ │ ├── MDVMInspectorDragAndDropActionBase.h │ │ │ ├── MDVMInspectorDragAndDropChanged.h │ │ │ ├── MDVMInspectorDragAndDropCommand.h │ │ │ ├── MDVMInspectorDragAndDropEvent.h │ │ │ ├── MDVMInspectorDragAndDropFieldNotify.h │ │ │ ├── MDVMInspectorDragAndDropFunctionBase.h │ │ │ ├── MDVMInspectorDragAndDropGetter.h │ │ │ ├── MDVMInspectorDragAndDropHelper.h │ │ │ └── MDVMInspectorDragAndDropProperty.h │ │ ├── MDViewModelChangedDebugLineItem.h │ │ ├── MDViewModelDebugLineItemBase.h │ │ ├── MDViewModelEventDebugLineItem.h │ │ ├── MDViewModelFieldDebugLineItem.h │ │ ├── MDViewModelFieldInspector.h │ │ └── MDViewModelFunctionDebugLineItem.h │ ├── MDViewModelAssignmentDialog.h │ ├── MDViewModelAssignmentEditorObject.h │ ├── MDViewModelDetails.h │ ├── MDViewModelEditor.h │ ├── MDViewModelEditorCommands.h │ ├── MDViewModelList.h │ ├── MDViewModelListItem.h │ └── MDViewModelTab.h │ └── Widgets │ └── SMDVMConfigEditor.h └── MDViewModelGraph ├── MDViewModelGraph.Build.cs ├── Private ├── BlueprintExtensions │ ├── MDViewModelAssignableInterface.cpp │ ├── MDViewModelBlueprintCompilerExtension.cpp │ ├── MDViewModelSupportedBlueprintExtension.cpp │ └── MDViewModelWidgetBlueprintExtension.cpp ├── MDViewModelGraph.cpp ├── Nodes │ ├── MDVMNode_CallCommand.cpp │ ├── MDVMNode_CallFunctionBase.cpp │ ├── MDVMNode_CallGetter.cpp │ ├── MDVMNode_CallHelper.cpp │ ├── MDVMNode_DynamicBindingBase.cpp │ ├── MDVMNode_GetProperty.cpp │ ├── MDVMNode_GetViewModel.cpp │ ├── MDVMNode_SetProperty.cpp │ ├── MDVMNode_SetViewModel.cpp │ ├── MDVMNode_SetViewModelOfClass.cpp │ ├── MDVMNode_ViewModelChanged.cpp │ ├── MDVMNode_ViewModelEvent.cpp │ ├── MDVMNode_ViewModelFieldNotify.cpp │ └── MDViewModelNodeSpawner.cpp ├── Subsystems │ └── MDViewModelGraphSubsystem.cpp └── Util │ ├── MDViewModelEditorAssignment.cpp │ └── MDViewModelGraphStatics.cpp └── Public ├── BlueprintExtensions ├── MDViewModelAssignableInterface.h ├── MDViewModelBlueprintCompilerExtension.h ├── MDViewModelSupportedBlueprintExtension.h └── MDViewModelWidgetBlueprintExtension.h ├── Nodes ├── MDVMNode_CallCommand.h ├── MDVMNode_CallFunctionBase.h ├── MDVMNode_CallGetter.h ├── MDVMNode_CallHelper.h ├── MDVMNode_DynamicBindingBase.h ├── MDVMNode_GetProperty.h ├── MDVMNode_GetViewModel.h ├── MDVMNode_SetProperty.h ├── MDVMNode_SetViewModel.h ├── MDVMNode_SetViewModelOfClass.h ├── MDVMNode_ViewModelChanged.h ├── MDVMNode_ViewModelEvent.h ├── MDVMNode_ViewModelFieldNotify.h └── MDViewModelNodeSpawner.h ├── Subsystems └── MDViewModelGraphSubsystem.h └── Util ├── MDViewModelEditorAssignment.h └── MDViewModelGraphStatics.h /Config/BaseMDViewModel.ini: -------------------------------------------------------------------------------- 1 | [CoreRedirects] 2 | +ClassRedirects=(OldName="/Script/MDViewModelEditor.MDViewModelWidgetBlueprintExtension",NewName="/Script/MDViewModelGraph.MDViewModelWidgetBlueprintExtension") 3 | +ClassRedirects=(OldName="/Script/MDViewModelGraph.MDViewModelActorBlueprintExtension",NewName="/Script/MDViewModelGraph.MDViewModelSupportedBlueprintExtension") 4 | 5 | [Staging] 6 | +AllowedConfigFiles=DefaultViewModel.ini 7 | -------------------------------------------------------------------------------- /Config/DefaultMDViewModel.ini: -------------------------------------------------------------------------------- 1 | [CoreRedirects] 2 | +ClassRedirects=(OldName="/Script/MDViewModelEditor.MDViewModelWidgetBlueprintExtension",NewName="/Script/MDViewModelGraph.MDViewModelWidgetBlueprintExtension") 3 | +ClassRedirects=(OldName="/Script/MDViewModelGraph.MDViewModelActorBlueprintExtension",NewName="/Script/MDViewModelGraph.MDViewModelSupportedBlueprintExtension") 4 | 5 | [Staging] 6 | +AllowedConfigFiles=DefaultViewModel.ini 7 | -------------------------------------------------------------------------------- /Config/FilterPlugin.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dylan Dumesnil 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MDViewModel.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "MDViewModel", 6 | "Description": "An Unreal Engine 5 Model-View-ViewModel Plugin with automatic data binding to use in UMG Widget and Actor Blueprints", 7 | "Category": "UI", 8 | "CreatedBy": "DoubleDeez", 9 | "CreatedByURL": "https://github.com/DoubleDeez", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "CanContainContent": false, 13 | "IsBetaVersion": false, 14 | "IsExperimentalVersion": false, 15 | "Installed": false, 16 | "Modules": [ 17 | { 18 | "Name": "MDViewModel", 19 | "Type": "Runtime", 20 | "LoadingPhase": "Default" 21 | }, 22 | { 23 | "Name": "MDViewModelEditor", 24 | "Type": "Editor", 25 | "LoadingPhase": "PostEngineInit" 26 | }, 27 | { 28 | "Name": "MDViewModelGraph", 29 | "Type": "UncookedOnly", 30 | "LoadingPhase": "Default" 31 | } 32 | ], 33 | "Plugins": [ 34 | { 35 | "Name": "StructUtils", 36 | "Enabled": true 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MDViewModel 2 | 3 | The MDViewModel plugin is an Unreal-ified implementation of the [Model-View-ViewModel pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel), supporting UMG Widgets and Actor Blueprints as Views with the goal of automating the most common binding patterns. 4 | 5 | - Bind UMG Widget, Actor and Object Blueprints to View Models 6 | - Caches View Model objects for the lifetime of their model data source 7 | - Automatically fetch/create View Models and bind them to Views based on tuning set in each View 8 | - Generates Blueprint events automatically for binding view model data to Blueprint logic, facilitating event-based updates to your Views 9 | - Custom editor extensions to improve view model workflows and debugging 10 | - FieldNotify properties and functions on view models are automatically exposed as Blueprint Events 11 | - Integrates with the Blueprint Editor Debugger to display the values of properties on view models that are set on the instance being debugged 12 | - Create View Models as C++ classes or Blueprints 13 | 14 | ## Compatibility 15 | 16 | MDViewModel supports C++ projects using Unreal Engine 5.1 or greater. Features may vary depending on the engine version. 17 | 18 | ## Philosophy 19 | 20 | This plugin is written with the assumption that you follow certain methodologies when using view models. 21 | 22 | - Visual properties and logic are set within the View's Blueprint. 23 | - A view never communicates directly with the model object. 24 | - Everything goes through view models. 25 | - Model objects (gameplay objects, online backend systems, etc) are not aware of view models. 26 | - Instead, view models reach into the external systems to grab the data they need, bind delegates and send out commands. 27 | - A view model will only represent a single model object (a view model can hold sub-view models though) and will only ever represent that 1 object. 28 | - Each model object should have a unique view model. 29 | - For a view to display data from a different object, it should bind to a that object's view model. 30 | 31 | MDViewModel does what it can to streamline the most common workflows and patterns for binding to model data, but some more complex patterns will require more manual work. 32 | 33 | While this is how MDViewModel is intended to be used, it's powerful enough to be used (or abused) for other patterns as well. 34 | 35 | ## Getting Started 36 | 37 | Check out the [Getting Started page](https://github.com/DoubleDeez/MDViewModel/wiki/Getting-Started) to get set up and learn how to create and bind to a view model. 38 | 39 | https://github.com/DoubleDeez/MDViewModel/assets/1893819/59474726-c86b-42c8-8fce-4a7af77a8931 40 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoubleDeez/MDViewModel/c7649b6bd52659260e09c236c4db5e4cae7b3a7c/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/MDViewModel/MDViewModel.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class MDViewModel : ModuleRules 6 | { 7 | public MDViewModel(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange( 12 | new string[] 13 | { 14 | "Core", 15 | "DeveloperSettings", 16 | "GameplayTags", 17 | "StructUtils", 18 | "UMG" 19 | } 20 | ); 21 | 22 | #if UE_5_3_OR_LATER 23 | PublicDependencyModuleNames.Add("FieldNotification"); 24 | PublicDefinitions.Add("MDVM_WITH_BLUEPRINT_FIELD_NOTIFY=1"); 25 | #else 26 | PublicDefinitions.Add("MDVM_WITH_BLUEPRINT_FIELD_NOTIFY=0"); 27 | #endif 28 | 29 | PrivateDependencyModuleNames.AddRange( 30 | new string[] 31 | { 32 | "CoreUObject", 33 | "Engine", 34 | "InputCore", 35 | "Slate", 36 | "SlateCore" 37 | } 38 | ); 39 | 40 | if (Target.Type == TargetType.Editor) 41 | { 42 | PublicDependencyModuleNames.AddRange( 43 | new string[] 44 | { 45 | "UMGEditor", 46 | "UnrealEd" 47 | } 48 | ); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Bindings/MDVMBlueprintBindingBase.cpp: -------------------------------------------------------------------------------- 1 | #include "Bindings/MDVMBlueprintBindingBase.h" 2 | 3 | #include "GameFramework/Actor.h" 4 | #include "Interfaces/MDViewModelRuntimeInterface.h" 5 | #include "Util/MDViewModelUtils.h" 6 | 7 | void UMDVMBlueprintBindingBase::BindViewModelDelegates(IMDViewModelRuntimeInterface& Object) const 8 | { 9 | Object.StopListeningForAllNativeViewModelsChanged(this); 10 | 11 | TWeakObjectPtr WeakObject = Object.GetOwningObject(); 12 | for (int32 i = 0; i < GetNumEntries(); ++i) 13 | { 14 | if (const FMDViewModeBindingEntryBase* Entry = GetEntry(i)) 15 | { 16 | auto Delegate = FMDVMOnViewModelSet::FDelegate::CreateUObject(this, &UMDVMBlueprintBindingBase::OnViewModelChanged, i, WeakObject); 17 | Object.ListenForChanges(MoveTemp(Delegate), { Entry->ViewModelClass, Entry->ViewModelName }); 18 | } 19 | } 20 | } 21 | 22 | void UMDVMBlueprintBindingBase::UnbindViewModelDelegates(IMDViewModelRuntimeInterface& Object) const 23 | { 24 | Object.StopListeningForAllNativeViewModelsChanged(this); 25 | } 26 | 27 | void UMDVMBlueprintBindingBase::BindDynamicDelegates(UObject* InInstance) const 28 | { 29 | // Only Widgets and other objects bind here, actors will bind from UMDViewModelAssignmentComponent::BeginPlay 30 | if (IsValid(InInstance) && !InInstance->IsA()) 31 | { 32 | if (IMDViewModelRuntimeInterface* Object = MDViewModelUtils::GetOrCreateViewModelRuntimeInterface(InInstance)) 33 | { 34 | BindViewModelDelegates(*Object); 35 | } 36 | } 37 | } 38 | 39 | void UMDVMBlueprintBindingBase::UnbindDynamicDelegates(UObject* InInstance) const 40 | { 41 | // Only Widgets and other objects unbind here, actors will unbind from UMDViewModelAssignmentComponent::EndPlay 42 | if (IsValid(InInstance) && !InInstance->IsA()) 43 | { 44 | if (IMDViewModelRuntimeInterface* Object = MDViewModelUtils::GetOrCreateViewModelRuntimeInterface(InInstance)) 45 | { 46 | UnbindViewModelDelegates(*Object); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Bindings/MDViewModelChangedBinding.cpp: -------------------------------------------------------------------------------- 1 | #include "Bindings/MDViewModelChangedBinding.h" 2 | 3 | #include "ViewModel/MDViewModelBase.h" 4 | 5 | void UMDViewModelChangedBinding::OnViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel, int32 EntryIndex, TWeakObjectPtr BoundObject) const 6 | { 7 | if (!ensure(ViewModelChangedBindings.IsValidIndex(EntryIndex)) || !BoundObject.IsValid()) 8 | { 9 | return; 10 | } 11 | 12 | const FMDViewModelChangedBindingEntry& Entry = ViewModelChangedBindings[EntryIndex]; 13 | if (UFunction* Func = BoundObject->FindFunction(Entry.FunctionNameToBind)) 14 | { 15 | struct 16 | { 17 | UMDViewModelBase* OldViewModel = nullptr; 18 | UMDViewModelBase* NewViewModel = nullptr; 19 | } Params = { OldViewModel, NewViewModel }; 20 | 21 | BoundObject->ProcessEvent(Func, &Params); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Bindings/MDViewModelDelegateBinding.cpp: -------------------------------------------------------------------------------- 1 | #include "Bindings/MDViewModelDelegateBinding.h" 2 | 3 | #include "ViewModel/MDViewModelBase.h" 4 | 5 | void UMDViewModelDelegateBinding::OnViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel, int32 EntryIndex, TWeakObjectPtr BoundObject) const 6 | { 7 | if (!ensure(ViewModelDelegateBindings.IsValidIndex(EntryIndex)) || !BoundObject.IsValid()) 8 | { 9 | return; 10 | } 11 | 12 | const FMDViewModelDelegateBindingEntry& Entry = ViewModelDelegateBindings[EntryIndex]; 13 | 14 | if (const FMulticastDelegateProperty* MulticastDelegateProp = FindFProperty(Entry.ViewModelClass, Entry.DelegatePropertyName)) 15 | { 16 | FScriptDelegate Delegate; 17 | Delegate.BindUFunction(BoundObject.Get(), Entry.FunctionNameToBind); 18 | 19 | if (IsValid(OldViewModel)) 20 | { 21 | MulticastDelegateProp->RemoveDelegate(Delegate, OldViewModel); 22 | } 23 | 24 | if (IsValid(NewViewModel)) 25 | { 26 | MulticastDelegateProp->AddDelegate(MoveTemp(Delegate), NewViewModel); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Components/MDVMPCDynamicDelegateIntermediate.cpp: -------------------------------------------------------------------------------- 1 | #include "Components/MDVMPCDynamicDelegateIntermediate.h" 2 | 3 | #include "GameFramework/PlayerController.h" 4 | 5 | 6 | UMDVMPCDynamicDelegateIntermediate* UMDVMPCDynamicDelegateIntermediate::FindOrAddListener(APlayerController* Owner) 7 | { 8 | if (IsValid(Owner)) 9 | { 10 | UMDVMPCDynamicDelegateIntermediate* Result = Owner->FindComponentByClass(); 11 | if (IsValid(Result)) 12 | { 13 | return Result; 14 | } 15 | 16 | constexpr bool bManualAttachment = false; 17 | constexpr bool bDeferredFinish = false; 18 | return Cast(Owner->AddComponentByClass(StaticClass(), bManualAttachment, FTransform::Identity, bDeferredFinish)); 19 | } 20 | 21 | return nullptr; 22 | } 23 | 24 | void UMDVMPCDynamicDelegateIntermediate::BeginPlay() 25 | { 26 | Super::BeginPlay(); 27 | 28 | if (APlayerController* PC = Cast(GetOwner())) 29 | { 30 | PC->OnPossessedPawnChanged.AddUniqueDynamic(this, &UMDVMPCDynamicDelegateIntermediate::OnPCPawnChanged); 31 | } 32 | } 33 | 34 | void UMDVMPCDynamicDelegateIntermediate::EndPlay(const EEndPlayReason::Type EndPlayReason) 35 | { 36 | if (APlayerController* PC = Cast(GetOwner())) 37 | { 38 | PC->OnPossessedPawnChanged.RemoveAll(this); 39 | } 40 | 41 | Super::EndPlay(EndPlayReason); 42 | } 43 | 44 | void UMDVMPCDynamicDelegateIntermediate::OnPCPawnChanged(APawn* OldPawn, APawn* NewPawn) 45 | { 46 | OnPawnChanged.Broadcast(); 47 | } 48 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Components/MDVMPCUpdatePollingComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "Components/MDVMPCUpdatePollingComponent.h" 2 | #include "GameFramework/HUD.h" 3 | #include "GameFramework/PlayerController.h" 4 | #include "GameFramework/PlayerState.h" 5 | 6 | 7 | UMDVMPCUpdatePollingComponent* UMDVMPCUpdatePollingComponent::FindOrAddPollingComponent(APlayerController* Owner) 8 | { 9 | if (IsValid(Owner)) 10 | { 11 | UMDVMPCUpdatePollingComponent* Result = Owner->FindComponentByClass(); 12 | if (IsValid(Result)) 13 | { 14 | return Result; 15 | } 16 | 17 | constexpr bool bManualAttachment = false; 18 | constexpr bool bDeferredFinish = false; 19 | return Cast(Owner->AddComponentByClass(StaticClass(), bManualAttachment, FTransform::Identity, bDeferredFinish)); 20 | } 21 | 22 | return nullptr; 23 | } 24 | 25 | UMDVMPCUpdatePollingComponent::UMDVMPCUpdatePollingComponent() 26 | { 27 | PrimaryComponentTick.bCanEverTick = true; 28 | PrimaryComponentTick.bStartWithTickEnabled = false; 29 | } 30 | 31 | void UMDVMPCUpdatePollingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) 32 | { 33 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 34 | 35 | const APlayerController* PC = CastChecked(GetOwner()); 36 | if (OnHUDChanged.IsBound()) 37 | { 38 | AHUD* HUD = PC->GetHUD(); 39 | if (CachedHUDObject != HUD) 40 | { 41 | CachedHUDObject = HUD; 42 | OnHUDChanged.Broadcast(); 43 | } 44 | } 45 | 46 | if (OnPlayerStateChanged.IsBound()) 47 | { 48 | APlayerState* PlayerState = PC->GetPlayerState(); 49 | if (CachedPlayerStateObject != PlayerState) 50 | { 51 | CachedPlayerStateObject = PlayerState; 52 | OnPlayerStateChanged.Broadcast(); 53 | } 54 | } 55 | } 56 | 57 | FDelegateHandle UMDVMPCUpdatePollingComponent::BindOnHUDChanged(FSimpleDelegate&& Delegate) 58 | { 59 | check(Delegate.IsBound()); 60 | 61 | const FDelegateHandle Handle = OnHUDChanged.Add(MoveTemp(Delegate)); 62 | 63 | UpdateShouldTick(); 64 | 65 | return Handle; 66 | } 67 | 68 | void UMDVMPCUpdatePollingComponent::UnbindOnHUDChanged(const FDelegateHandle& Handle) 69 | { 70 | OnHUDChanged.Remove(Handle); 71 | 72 | UpdateShouldTick(); 73 | } 74 | 75 | FDelegateHandle UMDVMPCUpdatePollingComponent::BindOnPlayerStateChanged(FSimpleDelegate&& Delegate) 76 | { 77 | check(Delegate.IsBound()); 78 | 79 | const FDelegateHandle Handle = OnPlayerStateChanged.Add(MoveTemp(Delegate)); 80 | 81 | UpdateShouldTick(); 82 | 83 | return Handle; 84 | } 85 | 86 | void UMDVMPCUpdatePollingComponent::UnbindOnPlayerStateChanged(const FDelegateHandle& Handle) 87 | { 88 | OnPlayerStateChanged.Remove(Handle); 89 | 90 | UpdateShouldTick(); 91 | } 92 | 93 | void UMDVMPCUpdatePollingComponent::UpdateShouldTick() 94 | { 95 | const bool bShouldTick = OnHUDChanged.IsBound() || OnPlayerStateChanged.IsBound(); 96 | SetComponentTickEnabled(bShouldTick); 97 | } 98 | 99 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Components/MDVMPSDynamicDelegateIntermediate.cpp: -------------------------------------------------------------------------------- 1 | #include "Components/MDVMPSDynamicDelegateIntermediate.h" 2 | 3 | #include "GameFramework/PlayerState.h" 4 | 5 | UMDVMPSDynamicDelegateIntermediate* UMDVMPSDynamicDelegateIntermediate::FindOrAddListener(APlayerState* Owner) 6 | { 7 | if (IsValid(Owner)) 8 | { 9 | UMDVMPSDynamicDelegateIntermediate* Result = Owner->FindComponentByClass(); 10 | if (IsValid(Result)) 11 | { 12 | return Result; 13 | } 14 | 15 | constexpr bool bManualAttachment = false; 16 | constexpr bool bDeferredFinish = false; 17 | return Cast(Owner->AddComponentByClass(StaticClass(), bManualAttachment, FTransform::Identity, bDeferredFinish)); 18 | } 19 | 20 | return nullptr; 21 | } 22 | 23 | void UMDVMPSDynamicDelegateIntermediate::BeginPlay() 24 | { 25 | Super::BeginPlay(); 26 | 27 | if (APlayerState* PlayerState = Cast(GetOwner())) 28 | { 29 | PlayerState->OnPawnSet.AddDynamic(this, &UMDVMPSDynamicDelegateIntermediate::OnPSPawnChanged); 30 | } 31 | } 32 | 33 | void UMDVMPSDynamicDelegateIntermediate::EndPlay(const EEndPlayReason::Type EndPlayReason) 34 | { 35 | if (APlayerState* PlayerState = Cast(GetOwner())) 36 | { 37 | PlayerState->OnPawnSet.RemoveAll(this); 38 | } 39 | 40 | Super::EndPlay(EndPlayReason); 41 | } 42 | 43 | void UMDVMPSDynamicDelegateIntermediate::OnPSPawnChanged(APlayerState* Player, APawn* NewPawn, APawn* OldPawn) 44 | { 45 | OnPawnChanged.Broadcast(); 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Components/MDVMPawnUpdatePollingComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "Components/MDVMPawnUpdatePollingComponent.h" 2 | #include "GameFramework/Pawn.h" 3 | #include "GameFramework/PlayerState.h" 4 | 5 | 6 | UMDVMPawnUpdatePollingComponent* UMDVMPawnUpdatePollingComponent::FindOrAddPollingComponent(APawn* Owner) 7 | { 8 | if (IsValid(Owner)) 9 | { 10 | UMDVMPawnUpdatePollingComponent* Result = Owner->FindComponentByClass(); 11 | if (IsValid(Result)) 12 | { 13 | return Result; 14 | } 15 | 16 | constexpr bool bManualAttachment = false; 17 | constexpr bool bDeferredFinish = false; 18 | return Cast(Owner->AddComponentByClass(StaticClass(), bManualAttachment, FTransform::Identity, bDeferredFinish)); 19 | } 20 | 21 | return nullptr; 22 | } 23 | 24 | UMDVMPawnUpdatePollingComponent::UMDVMPawnUpdatePollingComponent() 25 | { 26 | PrimaryComponentTick.bCanEverTick = true; 27 | PrimaryComponentTick.bStartWithTickEnabled = false; 28 | } 29 | 30 | void UMDVMPawnUpdatePollingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) 31 | { 32 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 33 | 34 | const APawn* Pawn = CastChecked(GetOwner()); 35 | if (OnPlayerStateChanged.IsBound()) 36 | { 37 | APlayerState* PlayerState = Pawn->GetPlayerState(); 38 | if (CachedPlayerStateObject != PlayerState) 39 | { 40 | CachedPlayerStateObject = PlayerState; 41 | OnPlayerStateChanged.Broadcast(); 42 | } 43 | } 44 | } 45 | 46 | FDelegateHandle UMDVMPawnUpdatePollingComponent::BindOnPlayerStateChanged(FSimpleDelegate&& Delegate) 47 | { 48 | check(Delegate.IsBound()); 49 | 50 | const FDelegateHandle Handle = OnPlayerStateChanged.Add(MoveTemp(Delegate)); 51 | 52 | UpdateShouldTick(); 53 | 54 | return Handle; 55 | } 56 | 57 | void UMDVMPawnUpdatePollingComponent::UnbindOnPlayerStateChanged(const FDelegateHandle& Handle) 58 | { 59 | OnPlayerStateChanged.Remove(Handle); 60 | 61 | UpdateShouldTick(); 62 | } 63 | 64 | void UMDVMPawnUpdatePollingComponent::UpdateShouldTick() 65 | { 66 | const bool bShouldTick = OnPlayerStateChanged.IsBound(); 67 | SetComponentTickEnabled(bShouldTick); 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Components/MDViewModelCacheComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "Components/MDViewModelCacheComponent.h" 2 | 3 | #include "GameFramework/Actor.h" 4 | #include "Util/MDViewModelInstanceKey.h" 5 | #include "Util/MDViewModelUtils.h" 6 | #include "ViewModel/MDViewModelBase.h" 7 | 8 | 9 | UMDViewModelCacheComponent* UMDViewModelCacheComponent::FindOrAddCache(AActor* Owner) 10 | { 11 | if (IsValid(Owner)) 12 | { 13 | UMDViewModelCacheComponent* Result = Owner->FindComponentByClass(); 14 | if (IsValid(Result)) 15 | { 16 | return Result; 17 | } 18 | 19 | constexpr bool bManualAttachment = false; 20 | constexpr bool bDeferredFinish = false; 21 | return Cast(Owner->AddComponentByClass(UMDViewModelCacheComponent::StaticClass(), bManualAttachment, FTransform::Identity, bDeferredFinish)); 22 | } 23 | 24 | return nullptr; 25 | } 26 | 27 | void UMDViewModelCacheComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) 28 | { 29 | BroadcastShutdown(); 30 | 31 | Super::EndPlay(EndPlayReason); 32 | } 33 | 34 | UObject* UMDViewModelCacheComponent::GetViewModelOwner() const 35 | { 36 | return GetOwner(); 37 | } 38 | 39 | FString UMDViewModelCacheComponent::GetCacheDebugName() const 40 | { 41 | return FString::Printf(TEXT("Actor Cache (%s)"), *GetNameSafe(GetOwner())); 42 | } 43 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Interfaces/MDVMCompiledAssignmentsInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "Interfaces/MDVMCompiledAssignmentsInterface.h" 2 | 3 | #include "Util/MDViewModelAssignment.h" 4 | #include "Util/MDViewModelAssignmentData.h" 5 | #include "ViewModel/MDViewModelBase.h" 6 | 7 | bool IMDVMCompiledAssignmentsInterface::HasAssignments() const 8 | { 9 | return !GetAssignments().IsEmpty(); 10 | } 11 | 12 | void IMDVMCompiledAssignmentsInterface::SearchAssignments(TMap& OutViewModelAssignments, TSubclassOf ViewModelClass, const FGameplayTag& ProviderTag, const FName& ViewModelName) const 13 | { 14 | OutViewModelAssignments = GetAssignments(); 15 | 16 | if (ProviderTag.IsValid() || ViewModelName != NAME_None || ViewModelClass != nullptr) 17 | { 18 | // Remove assignments that don't match the filter 19 | for (auto It = OutViewModelAssignments.CreateIterator(); It; ++It) 20 | { 21 | if (ProviderTag.IsValid() && !ProviderTag.MatchesTagExact(It.Key().ProviderTag)) 22 | { 23 | It.RemoveCurrent(); 24 | continue; 25 | } 26 | 27 | if (ViewModelName != NAME_None && ViewModelName != It.Key().ViewModelName) 28 | { 29 | It.RemoveCurrent(); 30 | continue; 31 | } 32 | 33 | if (ViewModelClass != nullptr && ViewModelClass != It.Key().ViewModelClass) 34 | { 35 | It.RemoveCurrent(); 36 | continue; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Interfaces/MDViewModelSupportedInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "Interfaces/MDViewModelSupportedInterface.h" 2 | 3 | #include "Engine/BlueprintGeneratedClass.h" 4 | #include "Engine/GameInstance.h" 5 | #include "Engine/LocalPlayer.h" 6 | #include "Engine/World.h" 7 | #include "GameFramework/Pawn.h" 8 | #include "GameFramework/PlayerController.h" 9 | #include "GameFramework/PlayerState.h" 10 | 11 | void IMDViewModelSupportedInterface::InitializeViewModelSupport() 12 | { 13 | UBlueprintGeneratedClass::BindDynamicDelegates(GetOwningObjectClass(), GetOwningObject()); 14 | } 15 | 16 | UObject* IMDViewModelSupportedInterface::GetOwningObject() const 17 | { 18 | return Cast(const_cast(this)); 19 | } 20 | 21 | UGameInstance* IMDViewModelSupportedInterface::ResolveGameInstance() const 22 | { 23 | if (const UWorld* World = ResolveWorld()) 24 | { 25 | return World->GetGameInstance(); 26 | } 27 | 28 | return nullptr; 29 | } 30 | 31 | UWorld* IMDViewModelSupportedInterface::ResolveWorld() const 32 | { 33 | return GetOwningObject()->GetWorld(); 34 | } 35 | 36 | ULocalPlayer* IMDViewModelSupportedInterface::ResolveOwningLocalPlayer() const 37 | { 38 | if (ULocalPlayer* LocalPlayer = Cast(GetOwningObject())) 39 | { 40 | return LocalPlayer; 41 | } 42 | 43 | if (const APlayerController* PC = ResolveOwningPlayer()) 44 | { 45 | return PC->GetLocalPlayer(); 46 | } 47 | 48 | return nullptr; 49 | } 50 | 51 | APlayerController* IMDViewModelSupportedInterface::ResolveOwningPlayer() const 52 | { 53 | if (APlayerController* PC = Cast(GetOwningObject())) 54 | { 55 | return PC; 56 | } 57 | 58 | if (const ULocalPlayer* LocalPlayer = Cast(GetOwningObject())) 59 | { 60 | return LocalPlayer->GetPlayerController(ResolveWorld()); 61 | } 62 | 63 | if (const APlayerState* PS = Cast(GetOwningObject())) 64 | { 65 | return PS->GetPlayerController(); 66 | } 67 | 68 | if (const APawn* Pawn = Cast(GetOwningObject())) 69 | { 70 | return Pawn->GetController(); 71 | } 72 | 73 | return nullptr; 74 | } 75 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/MDViewModelModule.cpp: -------------------------------------------------------------------------------- 1 | #include "Modules/ModuleManager.h" 2 | 3 | class FMDViewModelModule : public IModuleInterface 4 | { 5 | }; 6 | 7 | IMPLEMENT_MODULE(FMDViewModelModule, MDViewModel) -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Subsystems/MDGlobalViewModelCache.cpp: -------------------------------------------------------------------------------- 1 | #include "Subsystems/MDGlobalViewModelCache.h" 2 | #include "Engine/GameInstance.h" 3 | #include "Util/MDViewModelUtils.h" 4 | #include "ViewModel/MDViewModelBase.h" 5 | 6 | bool UMDGlobalViewModelCache::ShouldCreateSubsystem(UObject* Outer) const 7 | { 8 | TArray ChildClasses; 9 | GetDerivedClasses(GetClass(), ChildClasses, false); 10 | 11 | // Only create an instance if there is no override implementation defined elsewhere 12 | return ChildClasses.Num() == 0; 13 | } 14 | 15 | void UMDGlobalViewModelCache::Deinitialize() 16 | { 17 | BroadcastShutdown(); 18 | 19 | Super::Deinitialize(); 20 | } 21 | 22 | UObject* UMDGlobalViewModelCache::GetViewModelOwner() const 23 | { 24 | return GetGameInstance(); 25 | } 26 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Subsystems/MDLocalPlayerViewModelCache.cpp: -------------------------------------------------------------------------------- 1 | #include "Subsystems/MDLocalPlayerViewModelCache.h" 2 | #include "Engine/LocalPlayer.h" 3 | #include "Util/MDViewModelUtils.h" 4 | #include "ViewModel/MDViewModelBase.h" 5 | 6 | bool UMDLocalPlayerViewModelCache::ShouldCreateSubsystem(UObject* Outer) const 7 | { 8 | TArray ChildClasses; 9 | GetDerivedClasses(GetClass(), ChildClasses, false); 10 | 11 | // Only create an instance if there is no override implementation defined elsewhere 12 | return ChildClasses.Num() == 0; 13 | } 14 | 15 | void UMDLocalPlayerViewModelCache::Deinitialize() 16 | { 17 | BroadcastShutdown(); 18 | 19 | Super::Deinitialize(); 20 | } 21 | 22 | UObject* UMDLocalPlayerViewModelCache::GetViewModelOwner() const 23 | { 24 | return GetLocalPlayer(); 25 | } 26 | 27 | FString UMDLocalPlayerViewModelCache::GetCacheDebugName() const 28 | { 29 | return FString::Printf(TEXT("Local Player Cached: (%s)"), *GetLocalPlayer()->GetNickname()); 30 | } 31 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Subsystems/MDWorldViewModelCache.cpp: -------------------------------------------------------------------------------- 1 | #include "Subsystems/MDWorldViewModelCache.h" 2 | #include "Engine/World.h" 3 | #include "Util/MDViewModelUtils.h" 4 | #include "ViewModel/MDViewModelBase.h" 5 | 6 | bool UMDWorldViewModelCache::ShouldCreateSubsystem(UObject* Outer) const 7 | { 8 | TArray ChildClasses; 9 | GetDerivedClasses(GetClass(), ChildClasses, false); 10 | 11 | // Only create an instance if there is no override implementation defined elsewhere 12 | return ChildClasses.Num() == 0; 13 | } 14 | 15 | void UMDWorldViewModelCache::Deinitialize() 16 | { 17 | BroadcastShutdown(); 18 | 19 | Super::Deinitialize(); 20 | } 21 | 22 | UObject* UMDWorldViewModelCache::GetViewModelOwner() const 23 | { 24 | return GetWorld(); 25 | } 26 | 27 | FString UMDWorldViewModelCache::GetCacheDebugName() const 28 | { 29 | return FString::Printf(TEXT("World Cache (%s)"), *GetWorld()->GetMapName()); 30 | } 31 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDVMAssignmentObjectKey.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDVMAssignmentObjectKey.h" 2 | 3 | #include "Serialization/CompactBinaryWriter.h" 4 | 5 | 6 | bool FMDVMAssignmentObjectKey::operator==(const FMDVMAssignmentObjectKey& Other) const 7 | { 8 | return Other.Assignment == Assignment && Other.ObjectPtr == ObjectPtr; 9 | } 10 | 11 | FCbWriter& operator<<(FCbWriter& Writer, const FMDVMAssignmentObjectKey& Key) 12 | { 13 | Writer.BeginObject(); 14 | Writer << "Assignment" << Key.Assignment; 15 | Writer << "Object" << GetNameSafe(Key.ObjectPtr.GetObject()); 16 | Writer.EndObject(); 17 | return Writer; 18 | } 19 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDViewModelAssignment.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelAssignment.h" 2 | 3 | #include "Serialization/CompactBinaryWriter.h" 4 | #include "ViewModel/MDViewModelBase.h" 5 | 6 | 7 | #if WITH_EDITORONLY_DATA 8 | void FMDViewModelAssignment::UpdateViewModelClassName() 9 | { 10 | if (::IsValid(ViewModelClass)) 11 | { 12 | ViewModelClassName = ViewModelClass->GetFName(); 13 | } 14 | } 15 | #endif 16 | 17 | bool FMDViewModelAssignment::IsValid() const 18 | { 19 | return ::IsValid(ViewModelClass) && ProviderTag.IsValid() && ViewModelName.IsValid(); 20 | } 21 | 22 | void FMDViewModelAssignment::PostSerialize(const FArchive& Ar) 23 | { 24 | if (Ar.IsSaving() && IsValid()) 25 | { 26 | // Save broad and specific references 27 | Ar.MarkSearchableName(StaticStruct(), ViewModelClass->GetFName()); 28 | Ar.MarkSearchableName(StaticStruct(), *FString::Printf(TEXT("%s.%s"), *ViewModelClass->GetFName().ToString(), *ViewModelName.ToString())); 29 | Ar.MarkSearchableName(StaticStruct(), *FString::Printf(TEXT("%s.%s.%s"), *ViewModelClass->GetFName().ToString(), *ViewModelName.ToString(), *ProviderTag.ToString())); 30 | } 31 | } 32 | 33 | bool FMDViewModelAssignment::operator==(const FMDViewModelAssignment& Other) const 34 | { 35 | #if WITH_EDITORONLY_DATA 36 | if (ViewModelClassName != Other.ViewModelClassName) 37 | { 38 | return false; 39 | } 40 | #endif 41 | 42 | return ViewModelClass == Other.ViewModelClass && ProviderTag == Other.ProviderTag && ViewModelName == Other.ViewModelName; 43 | } 44 | 45 | FCbWriter& operator<<(FCbWriter& Writer, const FMDViewModelAssignment& Assignment) 46 | { 47 | Writer.BeginObject(); 48 | Writer << "Class" << GetNameSafe(Assignment.ViewModelClass); 49 | Writer << "Provider" << Assignment.ProviderTag.GetTagName(); 50 | Writer << "Name" << Assignment.ViewModelName; 51 | #if WITH_EDITORONLY_DATA 52 | Writer << "ClassPath" << Assignment.ViewModelClassName; 53 | #endif 54 | Writer.EndObject(); 55 | return Writer; 56 | } 57 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDViewModelAssignmentData.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelAssignmentData.h" 2 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDViewModelAssignmentReference.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelAssignmentReference.h" 2 | 3 | #include "Serialization/CompactBinaryWriter.h" 4 | #include "Util/MDViewModelAssignment.h" 5 | #include "ViewModel/MDViewModelBase.h" 6 | 7 | FMDViewModelAssignmentReference::FMDViewModelAssignmentReference(const FMDViewModelAssignment& Assignment) 8 | : ViewModelClass(Assignment.ViewModelClass) 9 | , ViewModelName(Assignment.ViewModelName) 10 | { 11 | } 12 | 13 | FMDViewModelAssignmentReference::FMDViewModelAssignmentReference(TSubclassOf ViewModelClass, const FName& ViewModelName) 14 | : ViewModelClass(ViewModelClass) 15 | , ViewModelName(ViewModelName) 16 | { 17 | } 18 | 19 | bool FMDViewModelAssignmentReference::IsAssignmentValid() const 20 | { 21 | return !ViewModelClass.IsNull() && ViewModelName != NAME_None; 22 | } 23 | 24 | void FMDViewModelAssignmentReference::PostSerialize(const FArchive& Ar) 25 | { 26 | if (Ar.IsSaving() && IsAssignmentValid()) 27 | { 28 | // Save broad and specific references 29 | Ar.MarkSearchableName(FMDViewModelAssignment::StaticStruct(), *ViewModelClass.GetAssetName()); 30 | Ar.MarkSearchableName(FMDViewModelAssignment::StaticStruct(), *FString::Printf(TEXT("%s.%s"), *ViewModelClass.GetAssetName(), *ViewModelName.ToString())); 31 | } 32 | } 33 | 34 | #if WITH_EDITOR 35 | FText FMDViewModelAssignmentReference::GetDisplayText() const 36 | { 37 | if (IsAssignmentValid()) 38 | { 39 | return FText::Format(INVTEXT("{0} ({1})"), ViewModelClass.LoadSynchronous()->GetDisplayNameText(), FText::FromName(ViewModelName)); 40 | } 41 | 42 | return INVTEXT("Invalid Assignment"); 43 | } 44 | #endif 45 | 46 | FMDViewModelAssignmentReference& FMDViewModelAssignmentReference::operator=(const FMDViewModelAssignmentReference& Other) 47 | { 48 | ViewModelClass = Other.ViewModelClass; 49 | ViewModelName = Other.ViewModelName; 50 | 51 | #if WITH_EDITOR 52 | PRAGMA_DISABLE_DEPRECATION_WARNINGS 53 | OnGetWidgetClass = Other.OnGetWidgetClass; 54 | PRAGMA_ENABLE_DEPRECATION_WARNINGS 55 | OnGetBoundObjectClass = Other.OnGetBoundObjectClass; 56 | #endif 57 | 58 | return *this; 59 | } 60 | 61 | bool FMDViewModelAssignmentReference::operator==(const FMDViewModelAssignmentReference& Other) const 62 | { 63 | return ViewModelClass == Other.ViewModelClass && ViewModelName == Other.ViewModelName; 64 | } 65 | 66 | FCbWriter& operator<<(FCbWriter& Writer, const FMDViewModelAssignmentReference& Assignment) 67 | { 68 | Writer.BeginObject(); 69 | Writer << "Class" << Assignment.ViewModelClass.ToString(); 70 | Writer << "Name" << Assignment.ViewModelName; 71 | Writer.EndObject(); 72 | return Writer; 73 | } 74 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDViewModelConfig.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelConfig.h" 2 | 3 | #include "GameplayTagsManager.h" 4 | #include "ViewModelProviders/MDViewModelProvider_Cached.h" 5 | 6 | UMDViewModelConfig::UMDViewModelConfig() 7 | : DefaultViewModelLifetime(TAG_MDVMProvider_Cached_Lifetimes_Global) 8 | { 9 | CategoryName = TEXT("Plugins"); 10 | SectionName = TEXT("MD View Model"); 11 | } 12 | 13 | void UMDViewModelConfig::PostInitProperties() 14 | { 15 | Super::PostInitProperties(); 16 | 17 | UGameplayTagsManager::Get().CallOrRegister_OnDoneAddingNativeTagsDelegate( 18 | FSimpleMulticastDelegate::FDelegate::CreateWeakLambda(this, [this]() { ReloadConfig(); })); 19 | } 20 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDViewModelInstanceKey.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelInstanceKey.h" 2 | 3 | #include "Serialization/CompactBinaryWriter.h" 4 | #include "ViewModel/MDViewModelBase.h" 5 | 6 | bool FMDViewModelInstanceKey::IsValid() const 7 | { 8 | return ViewModelName != NAME_None && ViewModelClass != nullptr; 9 | } 10 | 11 | bool FMDViewModelInstanceKey::operator==(const FMDViewModelInstanceKey& Other) const 12 | { 13 | return Other.ViewModelName == ViewModelName && Other.ViewModelClass == ViewModelClass; 14 | } 15 | 16 | FCbWriter& operator<<(FCbWriter& Writer, const FMDViewModelInstanceKey& Key) 17 | { 18 | Writer.BeginObject(); 19 | Writer << "Name" << Key.ViewModelName; 20 | Writer << "Class" << GetNameSafe(Key.ViewModelClass.Get()); 21 | Writer.EndObject(); 22 | return Writer; 23 | } 24 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Util/MDViewModelLog.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelLog.h" 2 | 3 | DEFINE_LOG_CATEGORY(LogMDViewModel); 4 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/ViewModelProviders/MDViewModelProviderBase.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelProviders/MDViewModelProviderBase.h" 2 | 3 | #include "ViewModel/MDViewModelBase.h" 4 | 5 | 6 | bool UMDViewModelProviderBase::ShouldCreateSubsystem(UObject* Outer) const 7 | { 8 | // by default, all providers can be overidden 9 | 10 | TArray ChildClasses; 11 | GetDerivedClasses(GetClass(), ChildClasses, false); 12 | 13 | // Only create an instance if there is no override implementation defined elsewhere 14 | return ChildClasses.Num() == 0; 15 | } 16 | 17 | #if WITH_EDITOR 18 | void UMDViewModelProviderBase::GetSupportedViewModelClasses(TArray& OutViewModelClasses) 19 | { 20 | // By default, providers support all view model classes 21 | OutViewModelClasses.Add({ UMDViewModelBase::StaticClass() }); 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/ViewModelProviders/MDViewModelProvider_Manual.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelProviders/MDViewModelProvider_Manual.h" 2 | 3 | #include "Interfaces/MDViewModelRuntimeInterface.h" 4 | 5 | UE_DEFINE_GAMEPLAY_TAG(TAG_MDVMProvider_Manual, "MDVM.Provider.Manual"); 6 | 7 | UMDViewModelBase* UMDViewModelProvider_Manual::SetViewModel(IMDViewModelRuntimeInterface& Object, const FMDViewModelAssignment& Assignment, const FMDViewModelAssignmentData& Data) 8 | { 9 | // Get the existing view model if there is one, since it would have been manually set 10 | return Object.GetViewModel(FMDViewModelAssignmentReference(Assignment)); 11 | } 12 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/ViewModelProviders/MDViewModelProvider_Unique.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelProviders/MDViewModelProvider_Unique.h" 2 | 3 | #include "Engine/Blueprint.h" 4 | #include "Runtime/Launch/Resources/Version.h" 5 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 2 6 | #include "Logging/StructuredLog.h" 7 | #endif 8 | #include "Util/MDViewModelAssignment.h" 9 | #include "Util/MDViewModelAssignmentData.h" 10 | #include "Util/MDViewModelFunctionLibrary.h" 11 | #include "Util/MDViewModelLog.h" 12 | #include "ViewModel/MDViewModelBase.h" 13 | 14 | UE_DEFINE_GAMEPLAY_TAG(TAG_MDVMProvider_Unique, "MDVM.Provider.Unique"); 15 | 16 | 17 | UMDViewModelBase* UMDViewModelProvider_Unique::SetViewModel(IMDViewModelRuntimeInterface& Object, const FMDViewModelAssignment& Assignment, const FMDViewModelAssignmentData& Data) 18 | { 19 | if (IsValid(Assignment.ViewModelClass)) 20 | { 21 | UObject* OwningObject = Object.GetOwningObject(); 22 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 2 23 | UE_LOGFMT(LogMDViewModel, Verbose, "Creating Unique View Model with Assignment [{Assignment}] for Object [{ObjectName}]", 24 | ("ObjectName", GetPathNameSafe(OwningObject)), 25 | ("Assignment", Assignment)); 26 | #else 27 | UE_LOG(LogMDViewModel, Verbose, TEXT("Creating Unique View Model with Assignment [%s (%s)] for Object [%s]"), 28 | *GetNameSafe(Assignment.ViewModelClass.Get()), 29 | *Assignment.ViewModelName.ToString(), 30 | *GetPathNameSafe(OwningObject) 31 | ); 32 | #endif 33 | 34 | const FMDViewModelAssignmentReference AssignmentReference(Assignment); 35 | if (!Object.IsListeningForChanges(this, AssignmentReference)) 36 | { 37 | auto Delegate = FMDVMOnViewModelSet::FDelegate::CreateUObject(this, &UMDViewModelProvider_Unique::OnBoundObjectViewModelChanged); 38 | Object.ListenForChanges(MoveTemp(Delegate), AssignmentReference); 39 | } 40 | 41 | UMDViewModelBase* ViewModel = Object.SetViewModelOfClass(OwningObject, OwningObject, AssignmentReference, Data.ViewModelSettings); 42 | UniqueVMs.Add(ViewModel); 43 | return ViewModel; 44 | } 45 | 46 | return nullptr; 47 | } 48 | 49 | #if WITH_EDITOR 50 | void UMDViewModelProvider_Unique::GetExpectedContextObjectTypes(const FInstancedStruct& ProviderSettings, const FInstancedStruct& ViewModelSettings, UBlueprint* Blueprint, TArray>& OutContextObjectClasses) const 51 | { 52 | if (IsValid(Blueprint)) 53 | { 54 | OutContextObjectClasses.Add(Blueprint->GeneratedClass); 55 | } 56 | } 57 | #endif 58 | 59 | void UMDViewModelProvider_Unique::OnBoundObjectViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel) 60 | { 61 | if (IsValid(OldViewModel) && UniqueVMs.Remove(OldViewModel) > 0) 62 | { 63 | OldViewModel->ShutdownViewModelFromProvider(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/WidgetExtensions/MDViewModelWidgetClassExtension.cpp: -------------------------------------------------------------------------------- 1 | #include "WidgetExtensions/MDViewModelWidgetClassExtension.h" 2 | 3 | #include "Blueprint/UserWidget.h" 4 | #include "Runtime/Launch/Resources/Version.h" 5 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 2 6 | #include "Logging/StructuredLog.h" 7 | #endif 8 | #include "Util/MDViewModelLog.h" 9 | #include "WidgetExtensions/MDViewModelWidgetExtension.h" 10 | 11 | void UMDViewModelWidgetClassExtension::BeginDestroy() 12 | { 13 | Super::BeginDestroy(); 14 | 15 | // Work around issue where ~FInstancedStruct would crash when calling DestroyStruct on partially destroyed UserDefinedStructs 16 | Assignments.Empty(); 17 | } 18 | 19 | void UMDViewModelWidgetClassExtension::Initialize(UUserWidget* UserWidget) 20 | { 21 | Super::Initialize(UserWidget); 22 | 23 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 2 24 | UE_LOGFMT(LogMDViewModel, Verbose, "Initializing View Model Extension for Widget [{WidgetName}]", UserWidget->GetPathName()); 25 | #else 26 | UE_LOG(LogMDViewModel, Verbose, TEXT("Initializing View Model Extension for Widget [%s]"), *UserWidget->GetPathName()); 27 | #endif 28 | 29 | // ensure that we add the extension to the widget 30 | UMDViewModelWidgetExtension* Extension = UMDViewModelWidgetExtension::GetOrCreate(UserWidget); 31 | ensure(Extension); 32 | 33 | if (TArray* QueuedListenerDatas = QueuedDelegates.Find(UserWidget)) 34 | { 35 | for (QueuedListenerData& Data : *QueuedListenerDatas) 36 | { 37 | Extension->ListenForChanges(MoveTemp(Data.Delegate), Data.Assignment); 38 | } 39 | 40 | QueuedDelegates.Remove(UserWidget); 41 | } 42 | } 43 | 44 | #if WITH_EDITOR 45 | void UMDViewModelWidgetClassExtension::Construct(UUserWidget* UserWidget) 46 | { 47 | Super::Construct(UserWidget); 48 | 49 | #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 2 50 | // Initialize isn't called in editor Debug mode so we force it here 51 | if (IsValid(UserWidget) && UserWidget->IsPreviewTime()) 52 | { 53 | Initialize(UserWidget); 54 | } 55 | #endif 56 | } 57 | #endif 58 | 59 | void UMDViewModelWidgetClassExtension::SetAssignments(const TMap& InAssignments) 60 | { 61 | Assignments = InAssignments; 62 | } 63 | 64 | void UMDViewModelWidgetClassExtension::QueueListenForChanges(UUserWidget* Widget, FMDVMOnViewModelSet::FDelegate&& Delegate, const FMDViewModelAssignmentReference& Assignment) 65 | { 66 | if (IsValid(Widget)) 67 | { 68 | if (UMDViewModelWidgetExtension* Extension = Widget->GetExtension()) 69 | { 70 | Extension->ListenForChanges(MoveTemp(Delegate), Assignment); 71 | } 72 | else 73 | { 74 | QueuedDelegates.FindOrAdd(Widget).Emplace(QueuedListenerData{ MoveTemp(Delegate), Assignment }); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/WidgetExtensions/MDViewModelWidgetExtension.cpp: -------------------------------------------------------------------------------- 1 | #include "WidgetExtensions/MDViewModelWidgetExtension.h" 2 | 3 | #include "Runtime/Launch/Resources/Version.h" 4 | #include "Blueprint/UserWidget.h" 5 | #include "UObject/Package.h" 6 | 7 | void UMDViewModelWidgetExtension::Construct() 8 | { 9 | Super::Construct(); 10 | 11 | const UUserWidget* Widget = GetUserWidget(); 12 | if (!IsValid(Widget)) 13 | { 14 | return; 15 | } 16 | 17 | #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 2 18 | // TODO - Support DebugMode with editable debug view models 19 | if (Widget->IsPreviewTime()) 20 | { 21 | return; 22 | } 23 | #endif 24 | 25 | PopulateViewModels(); 26 | } 27 | 28 | void UMDViewModelWidgetExtension::Destruct() 29 | { 30 | CleanUpViewModels(); 31 | 32 | Super::Destruct(); 33 | } 34 | 35 | void UMDViewModelWidgetExtension::BeginDestroy() 36 | { 37 | if (!HasAnyFlags(RF_ClassDefaultObject)) 38 | { 39 | OnBeginDestroy.Broadcast(); 40 | } 41 | 42 | Super::BeginDestroy(); 43 | } 44 | 45 | UMDViewModelWidgetExtension* UMDViewModelWidgetExtension::GetOrCreate(UUserWidget* Widget) 46 | { 47 | if (IsValid(Widget)) 48 | { 49 | UMDViewModelWidgetExtension* Extension = Widget->GetExtension(); 50 | if (IsValid(Extension)) 51 | { 52 | return Extension; 53 | } 54 | 55 | return Widget->AddExtension(); 56 | } 57 | 58 | return nullptr; 59 | } 60 | 61 | UObject* UMDViewModelWidgetExtension::GetOwningObject() const 62 | { 63 | return GetUserWidget(); 64 | } 65 | 66 | UGameInstance* UMDViewModelWidgetExtension::ResolveGameInstance() const 67 | { 68 | if (const UUserWidget* Widget = GetUserWidget()) 69 | { 70 | return Widget->GetGameInstance(); 71 | } 72 | 73 | return nullptr; 74 | } 75 | 76 | UWorld* UMDViewModelWidgetExtension::ResolveWorld() const 77 | { 78 | if (const UUserWidget* Widget = GetUserWidget()) 79 | { 80 | return Widget->GetWorld(); 81 | } 82 | 83 | return nullptr; 84 | } 85 | 86 | ULocalPlayer* UMDViewModelWidgetExtension::ResolveOwningLocalPlayer() const 87 | { 88 | if (const UUserWidget* Widget = GetUserWidget()) 89 | { 90 | return Widget->GetOwningLocalPlayer(); 91 | } 92 | 93 | return nullptr; 94 | } 95 | 96 | APlayerController* UMDViewModelWidgetExtension::ResolveOwningPlayer() const 97 | { 98 | if (const UUserWidget* Widget = GetUserWidget()) 99 | { 100 | return Widget->GetOwningPlayer(); 101 | } 102 | 103 | return nullptr; 104 | } 105 | 106 | TMap>& UMDViewModelWidgetExtension::GetViewModels() 107 | { 108 | return ViewModels; 109 | } 110 | -------------------------------------------------------------------------------- /Source/MDViewModel/Private/Widgets/MDViewModelSwitcherSlot.cpp: -------------------------------------------------------------------------------- 1 | #include "Widgets/MDViewModelSwitcherSlot.h" 2 | 3 | #include "Components/Widget.h" 4 | 5 | void UMDViewModelSwitcherSlot::PostInitProperties() 6 | { 7 | Super::PostInitProperties(); 8 | 9 | #if WITH_EDITOR 10 | ViewModelAssignment.OnGetBoundObjectClass.BindUObject(this, &UMDViewModelSwitcherSlot::GetContentWidgetClass); 11 | #endif 12 | } 13 | 14 | #if WITH_EDITOR 15 | UClass* UMDViewModelSwitcherSlot::GetContentWidgetClass() const 16 | { 17 | return IsValid(Content) ? Content->GetClass() : nullptr; 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Bindings/MDVMBlueprintBindingBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Engine/DynamicBlueprintBinding.h" 4 | #include "Templates/SubclassOf.h" 5 | #include "MDVMBlueprintBindingBase.generated.h" 6 | 7 | class UMDViewModelBase; 8 | class IMDViewModelRuntimeInterface; 9 | 10 | USTRUCT() 11 | struct MDVIEWMODEL_API FMDViewModeBindingEntryBase 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | // Class of the view model we're binding to 17 | UPROPERTY() 18 | TSubclassOf ViewModelClass; 19 | 20 | // Name of the view model we're binding to 21 | UPROPERTY() 22 | FName ViewModelName = NAME_None; 23 | }; 24 | 25 | UCLASS() 26 | class MDVIEWMODEL_API UMDVMBlueprintBindingBase : public UDynamicBlueprintBinding 27 | { 28 | GENERATED_BODY() 29 | 30 | friend class UMDViewModelAssignmentComponent; 31 | 32 | protected: 33 | virtual void BindViewModelDelegates(IMDViewModelRuntimeInterface& Object) const; 34 | virtual void UnbindViewModelDelegates(IMDViewModelRuntimeInterface& Object) const; 35 | 36 | virtual void OnViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel, int32 EntryIndex, TWeakObjectPtr BoundObject) const {} 37 | 38 | virtual const FMDViewModeBindingEntryBase* GetEntry(int32 Index) const { return nullptr; } 39 | virtual int32 GetNumEntries() const { return 0; } 40 | 41 | private: 42 | virtual void BindDynamicDelegates(UObject* InInstance) const override final; 43 | virtual void UnbindDynamicDelegates(UObject* InInstance) const override final; 44 | }; 45 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Bindings/MDViewModelChangedBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMBlueprintBindingBase.h" 4 | #include "MDViewModelChangedBinding.generated.h" 5 | 6 | class UMDViewModelBase; 7 | 8 | /** Entry for a delegate to assign after a blueprint has been instanced */ 9 | USTRUCT() 10 | struct MDVIEWMODEL_API FMDViewModelChangedBindingEntry : public FMDViewModeBindingEntryBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Name of the function that we're binding 16 | UPROPERTY() 17 | FName FunctionNameToBind = NAME_None; 18 | }; 19 | 20 | /** 21 | * Class to handle binding to a view model changing at runtime 22 | */ 23 | UCLASS() 24 | class MDVIEWMODEL_API UMDViewModelChangedBinding : public UMDVMBlueprintBindingBase 25 | { 26 | GENERATED_BODY() 27 | 28 | public: 29 | UPROPERTY() 30 | TArray ViewModelChangedBindings; 31 | 32 | private: 33 | virtual void OnViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel, int32 EntryIndex, TWeakObjectPtr BoundObject) const override; 34 | 35 | virtual const FMDViewModeBindingEntryBase* GetEntry(int32 Index) const override { return ViewModelChangedBindings.IsValidIndex(Index) ? &ViewModelChangedBindings[Index] : nullptr; } 36 | virtual int32 GetNumEntries() const override { return ViewModelChangedBindings.Num(); } 37 | }; 38 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Bindings/MDViewModelDelegateBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMBlueprintBindingBase.h" 4 | #include "MDViewModelDelegateBinding.generated.h" 5 | 6 | class UMDViewModelBase; 7 | 8 | /** Entry for a delegate to assign after a blueprint has been instanced */ 9 | USTRUCT() 10 | struct MDVIEWMODEL_API FMDViewModelDelegateBindingEntry : public FMDViewModeBindingEntryBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Name of the delegate on the viewmodel we're going to bind to 16 | UPROPERTY() 17 | FName DelegatePropertyName = NAME_None; 18 | 19 | // Name of the function that we're binding to the delegate 20 | UPROPERTY() 21 | FName FunctionNameToBind = NAME_None; 22 | }; 23 | 24 | /** 25 | * Class to handle binding to viewmodel events at runtime 26 | */ 27 | UCLASS() 28 | class MDVIEWMODEL_API UMDViewModelDelegateBinding : public UMDVMBlueprintBindingBase 29 | { 30 | GENERATED_BODY() 31 | 32 | public: 33 | UPROPERTY() 34 | TArray ViewModelDelegateBindings; 35 | 36 | protected: 37 | virtual void OnViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel, int32 EntryIndex, TWeakObjectPtr BoundObject) const override; 38 | 39 | virtual const FMDViewModeBindingEntryBase* GetEntry(int32 Index) const override { return ViewModelDelegateBindings.IsValidIndex(Index) ? &ViewModelDelegateBindings[Index] : nullptr; } 40 | virtual int32 GetNumEntries() const override { return ViewModelDelegateBindings.Num(); } 41 | }; 42 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Bindings/MDViewModelFieldNotifyBinding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Runtime/Launch/Resources/Version.h" 4 | 5 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 3 6 | #include "FieldNotificationId.h" 7 | #else 8 | #include "FieldNotification/FieldId.h" 9 | #endif 10 | #include "MDVMBlueprintBindingBase.h" 11 | #include "MDViewModelFieldNotifyBinding.generated.h" 12 | 13 | class UMDViewModelBase; 14 | 15 | /** Entry for a field notify to assign after a blueprint has been instanced */ 16 | USTRUCT() 17 | struct MDVIEWMODEL_API FMDViewModelFieldNotifyBindingEntry : public FMDViewModeBindingEntryBase 18 | { 19 | GENERATED_BODY() 20 | 21 | public: 22 | // Name of the field notify property/function on the viewmodel we're going to bind to 23 | UPROPERTY() 24 | FName FieldNotifyName = NAME_None; 25 | 26 | // Name of the function that we're binding to the delegate 27 | UPROPERTY() 28 | FName FunctionNameToBind = NAME_None; 29 | }; 30 | 31 | /** 32 | * Class to handle binding to view model field notify properties/functions at runtime 33 | */ 34 | UCLASS() 35 | class MDVIEWMODEL_API UMDViewModelFieldNotifyBinding : public UMDVMBlueprintBindingBase 36 | { 37 | GENERATED_BODY() 38 | 39 | public: 40 | UPROPERTY() 41 | TArray ViewModelFieldNotifyBindings; 42 | 43 | protected: 44 | virtual void OnViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel, int32 EntryIndex, TWeakObjectPtr BoundObject) const override; 45 | 46 | virtual const FMDViewModeBindingEntryBase* GetEntry(int32 Index) const override { return ViewModelFieldNotifyBindings.IsValidIndex(Index) ? &ViewModelFieldNotifyBindings[Index] : nullptr; } 47 | virtual int32 GetNumEntries() const override { return ViewModelFieldNotifyBindings.Num(); } 48 | 49 | private: 50 | void OnFieldValueChanged(UObject* ViewModel, UE::FieldNotification::FFieldId Field, int32 EntryIndex, TWeakObjectPtr BoundObject) const; 51 | 52 | mutable TMap>, FDelegateHandle> BoundDelegates; 53 | }; 54 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Components/MDVMPCDynamicDelegateIntermediate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/ActorComponent.h" 4 | #include "MDVMPCDynamicDelegateIntermediate.generated.h" 5 | 6 | class APawn; 7 | class APlayerController; 8 | 9 | /* 10 | * Specific component used as an intermediate for dynamic delegates on APlayerController 11 | */ 12 | UCLASS() 13 | class MDVIEWMODEL_API UMDVMPCDynamicDelegateIntermediate : public UActorComponent 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | static UMDVMPCDynamicDelegateIntermediate* FindOrAddListener(APlayerController* Owner); 19 | 20 | virtual void BeginPlay() override; 21 | virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; 22 | 23 | FSimpleMulticastDelegate OnPawnChanged; 24 | private: 25 | UFUNCTION() 26 | void OnPCPawnChanged(APawn* OldPawn, APawn* NewPawn); 27 | }; 28 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Components/MDVMPCUpdatePollingComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/ActorComponent.h" 4 | #include "MDVMPCUpdatePollingComponent.generated.h" 5 | 6 | class APlayerController; 7 | 8 | /* 9 | * Component to poll a Player Controller for changes to properties 10 | * 11 | * Not all the objects we need to bind to have delegates to notify us of them updating, 12 | * so we have this component poll to check for changes 13 | * 14 | * TODO - Figure out a way for games to provide events in-place of using polling (eg. UCommonLocalPlayer's OnPlayerStateSet) 15 | */ 16 | UCLASS() 17 | class MDVIEWMODEL_API UMDVMPCUpdatePollingComponent : public UActorComponent 18 | { 19 | GENERATED_BODY() 20 | 21 | public: 22 | static UMDVMPCUpdatePollingComponent* FindOrAddPollingComponent(APlayerController* Owner); 23 | 24 | UMDVMPCUpdatePollingComponent(); 25 | 26 | virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; 27 | 28 | FDelegateHandle BindOnHUDChanged(FSimpleDelegate&& Delegate); 29 | void UnbindOnHUDChanged(const FDelegateHandle& Handle); 30 | 31 | FDelegateHandle BindOnPlayerStateChanged(FSimpleDelegate&& Delegate); 32 | void UnbindOnPlayerStateChanged(const FDelegateHandle& Handle); 33 | 34 | protected: 35 | void UpdateShouldTick(); 36 | 37 | FSimpleMulticastDelegate OnHUDChanged; 38 | TWeakObjectPtr CachedHUDObject; 39 | 40 | FSimpleMulticastDelegate OnPlayerStateChanged; 41 | TWeakObjectPtr CachedPlayerStateObject; 42 | }; 43 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Components/MDVMPSDynamicDelegateIntermediate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/ActorComponent.h" 4 | #include "MDVMPSDynamicDelegateIntermediate.generated.h" 5 | 6 | class APawn; 7 | class APlayerState; 8 | 9 | 10 | UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) 11 | class MDVIEWMODEL_API UMDVMPSDynamicDelegateIntermediate : public UActorComponent 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | static UMDVMPSDynamicDelegateIntermediate* FindOrAddListener(APlayerState* Owner); 17 | 18 | virtual void BeginPlay() override; 19 | virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; 20 | 21 | FSimpleMulticastDelegate OnPawnChanged; 22 | private: 23 | UFUNCTION() 24 | void OnPSPawnChanged(APlayerState* Player, APawn* NewPawn, APawn* OldPawn); 25 | }; 26 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Components/MDVMPawnUpdatePollingComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/ActorComponent.h" 4 | #include "MDVMPawnUpdatePollingComponent.generated.h" 5 | 6 | class APlayerController; 7 | 8 | /* 9 | * Component to poll a Pawn for changes to properties 10 | * 11 | * Not all the objects we need to bind to have delegates to notify us of them updating, 12 | * so we have this component poll to check for changes 13 | * 14 | * TODO - Figure out a way for games to provide events in-place of using polling (eg. UCommonLocalPlayer's OnPlayerStateSet) 15 | */ 16 | UCLASS() 17 | class MDVIEWMODEL_API UMDVMPawnUpdatePollingComponent : public UActorComponent 18 | { 19 | GENERATED_BODY() 20 | 21 | public: 22 | static UMDVMPawnUpdatePollingComponent* FindOrAddPollingComponent(APawn* Owner); 23 | 24 | UMDVMPawnUpdatePollingComponent(); 25 | 26 | virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; 27 | 28 | FDelegateHandle BindOnPlayerStateChanged(FSimpleDelegate&& Delegate); 29 | void UnbindOnPlayerStateChanged(const FDelegateHandle& Handle); 30 | 31 | protected: 32 | void UpdateShouldTick(); 33 | 34 | FSimpleMulticastDelegate OnPlayerStateChanged; 35 | TWeakObjectPtr CachedPlayerStateObject; 36 | }; 37 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Components/MDViewModelAssignmentComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/ActorComponent.h" 4 | #include "Interfaces/MDVMCompiledAssignmentsInterface.h" 5 | #include "Interfaces/MDViewModelRuntimeInterface.h" 6 | #include "Util/MDViewModelAssignment.h" 7 | #include "Util/MDViewModelAssignmentData.h" 8 | #include "Util/MDViewModelAssignmentReference.h" 9 | #include "MDViewModelAssignmentComponent.generated.h" 10 | 11 | class UBlueprintGeneratedClass; 12 | 13 | // Auto-generated component to track view model assignments and instances on an actor 14 | UCLASS(Hidden, meta=(BlueprintSpawnableComponent)) 15 | class MDVIEWMODEL_API UMDViewModelAssignmentComponent : public UActorComponent, public IMDVMCompiledAssignmentsInterface, public IMDViewModelRuntimeInterface 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | virtual void BeginDestroy() override; 21 | 22 | virtual UObject* GetOwningObject() const override; 23 | 24 | virtual UGameInstance* ResolveGameInstance() const override; 25 | virtual UWorld* ResolveWorld() const override; 26 | virtual ULocalPlayer* ResolveOwningLocalPlayer() const override; 27 | virtual APlayerController* ResolveOwningPlayer() const override; 28 | 29 | virtual void SetAssignments(const TMap& InAssignments) override; 30 | virtual const TMap& GetAssignments() const override; 31 | 32 | protected: 33 | virtual void BeginPlay() override; 34 | virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; 35 | 36 | virtual TMap>& GetViewModels() override; 37 | 38 | private: 39 | static void BindDelegates(IMDViewModelRuntimeInterface& Object, UBlueprintGeneratedClass* Class); 40 | static void UnbindDelegates(IMDViewModelRuntimeInterface& Object, UBlueprintGeneratedClass* Class); 41 | 42 | // The compiled assignments for the owning actor 43 | UPROPERTY(VisibleAnywhere, DuplicateTransient, Category = "View Model Component") 44 | TMap Assignments; 45 | 46 | // The runtime view model instances for the owning actor 47 | UPROPERTY(VisibleAnywhere, Transient, Category = "View Model Component") 48 | TMap> ViewModels; 49 | }; 50 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Components/MDViewModelCacheComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/ActorComponent.h" 4 | #include "Interfaces/MDViewModelCacheInterface.h" 5 | #include "MDViewModelCacheComponent.generated.h" 6 | 7 | class UMDViewModelBase; 8 | 9 | UCLASS() 10 | class MDVIEWMODEL_API UMDViewModelCacheComponent : public UActorComponent, public IMDViewModelCacheInterface 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | static UMDViewModelCacheComponent* FindOrAddCache(AActor* Owner); 16 | 17 | virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; 18 | 19 | protected: 20 | virtual UObject* GetViewModelOwner() const override; 21 | virtual TMap>& GetViewModelCache() override { return CachedViewModels; } 22 | virtual FString GetCacheDebugName() const override; 23 | 24 | private: 25 | UPROPERTY(VisibleAnywhere, Transient, Category = "View Model") 26 | TMap> CachedViewModels; 27 | }; 28 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Interfaces/MDVMCompiledAssignmentsInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayTagContainer.h" 4 | #include "Templates/SubclassOf.h" 5 | #include "UObject/Interface.h" 6 | #include "MDVMCompiledAssignmentsInterface.generated.h" 7 | 8 | class UMDViewModelBase; 9 | struct FMDViewModelAssignment; 10 | struct FMDViewModelAssignmentData; 11 | 12 | UINTERFACE() 13 | class UMDVMCompiledAssignmentsInterface : public UInterface 14 | { 15 | GENERATED_BODY() 16 | }; 17 | 18 | // Interface for an object that stores compiled view model assignments 19 | class MDVIEWMODEL_API IMDVMCompiledAssignmentsInterface 20 | { 21 | GENERATED_BODY() 22 | 23 | public: 24 | virtual void SetAssignments(const TMap& InAssignments) = 0; 25 | virtual const TMap& GetAssignments() const = 0; 26 | 27 | bool HasAssignments() const; 28 | void SearchAssignments(TMap& OutViewModelAssignments, TSubclassOf ViewModelClass = nullptr, const FGameplayTag& ProviderTag = FGameplayTag::EmptyTag, const FName& ViewModelName = NAME_None) const; 29 | 30 | }; 31 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Interfaces/MDViewModelCacheInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "InstancedStruct.h" 4 | #include "Runtime/Launch/Resources/Version.h" 5 | #include "UObject/Interface.h" 6 | #include "UObject/WeakInterfacePtr.h" 7 | #include "Util/MDViewModelInstanceKey.h" 8 | #include "MDViewModelCacheInterface.generated.h" 9 | 10 | class UMDViewModelBase; 11 | 12 | UINTERFACE(meta=(CannotImplementInterfaceInBlueprint)) 13 | class UMDViewModelCacheInterface : public UInterface 14 | { 15 | GENERATED_BODY() 16 | }; 17 | 18 | /** 19 | * Interface for classes that act as a View Model Cache 20 | */ 21 | class MDVIEWMODEL_API IMDViewModelCacheInterface 22 | { 23 | GENERATED_BODY() 24 | 25 | public: 26 | UMDViewModelBase* GetOrCreateViewModel(const UObject* WorldContextObject, const FName& CachedViewModelKey, TSubclassOf ViewModelClass, const FInstancedStruct& ViewModelSettings = {}); 27 | 28 | UMDViewModelBase* GetViewModel(const FName& CachedViewModelKey, TSubclassOf ViewModelClass) const; 29 | 30 | bool IsShutdown() const { return bIsShutdown; } 31 | 32 | virtual UObject* GetViewModelOwner() const = 0; 33 | 34 | FSimpleMulticastDelegate OnShuttingDown; 35 | 36 | protected: 37 | void BroadcastShutdown(); 38 | 39 | virtual TMap>& GetViewModelCache() = 0; 40 | 41 | virtual FString GetCacheDebugName() const = 0; 42 | 43 | virtual const TMap>& GetViewModelCache() const; 44 | 45 | virtual FName CreateDebugViewModelNameBase() const; 46 | 47 | private: 48 | bool bIsShutdown = false; 49 | 50 | #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) 51 | const FName& GetDebugViewModelNameBase(); 52 | 53 | FName DebugViewModelNameBase = NAME_None; 54 | #endif 55 | }; 56 | 57 | #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 1 58 | FORCEINLINE uint32 GetTypeHash(const TWeakInterfacePtr& WeakInterfacePtr) 59 | { 60 | return GetTypeHash(WeakInterfacePtr.GetWeakObjectPtr()); 61 | } 62 | #else 63 | FORCEINLINE uint32 GetTypeHash(const TWeakInterfacePtr& WeakInterfacePtr) 64 | { 65 | return WeakInterfacePtr.GetWeakObjectPtr().GetWeakPtrTypeHash(); 66 | } 67 | #endif 68 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Interfaces/MDViewModelSupportedInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelRuntimeInterface.h" 4 | #include "MDVMCompiledAssignmentsInterface.h" 5 | #include "UObject/Interface.h" 6 | #include "MDViewModelSupportedInterface.generated.h" 7 | 8 | /* 9 | * Add view model support to any blueprintable object, also requires IMDVMCompiledAssignmentsInterface 10 | * 11 | * Usage example: 12 | * 13 | * UCLASS(Blueprintable) 14 | * class UMyClassWithViewModels : public UObject, public IMDViewModelSupportedInterface, public IMDVMCompiledAssignmentsInterface 15 | * { 16 | * GENERATED_BODY() 17 | * 18 | * public: 19 | * // Something like BeginPlay 20 | * void SomeInitializeFunction() 21 | * { 22 | * InitializeViewModelSupport(); 23 | * } 24 | * 25 | * virtual void BeginDestroy() override 26 | * { 27 | * OnBeginDestroy.Broadcast(); 28 | * 29 | * Super::BeginDestroy(); 30 | * } 31 | * 32 | * virtual void SetAssignments(const TMap& InAssignments) override { Assignments = InAssignments; } 33 | * virtual const TMap& GetAssignments() const override { return Assignments; } 34 | * 35 | * protected: 36 | * virtual TMap>& GetViewModels() override { return ViewModels; } 37 | * 38 | * private: 39 | * // The compiled view model assignments for this object, only exists on the CDO 40 | * UPROPERTY(DuplicateTransient) 41 | * TMap Assignments; 42 | * 43 | * // The runtime view model instances for this object 44 | * UPROPERTY(Transient) 45 | * TMap> ViewModels; 46 | * }; 47 | * 48 | */ 49 | 50 | UINTERFACE(meta=(CannotImplementInterfaceInBlueprint)) 51 | class MDVIEWMODEL_API UMDViewModelSupportedInterface : public UMDViewModelRuntimeInterface 52 | { 53 | GENERATED_BODY() 54 | }; 55 | 56 | /** 57 | * Interface that adds view model support to Blueprints of classes that implement it 58 | */ 59 | class MDVIEWMODEL_API IMDViewModelSupportedInterface : public IMDViewModelRuntimeInterface 60 | { 61 | GENERATED_BODY() 62 | 63 | public: 64 | void InitializeViewModelSupport(); 65 | 66 | virtual UObject* GetOwningObject() const override; 67 | 68 | virtual UGameInstance* ResolveGameInstance() const override; 69 | virtual UWorld* ResolveWorld() const override; 70 | virtual ULocalPlayer* ResolveOwningLocalPlayer() const override; 71 | virtual APlayerController* ResolveOwningPlayer() const override; 72 | 73 | protected: 74 | virtual TMap>& GetViewModels() override = 0; 75 | 76 | }; 77 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Subsystems/MDGlobalViewModelCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces/MDViewModelCacheInterface.h" 4 | #include "Subsystems/GameInstanceSubsystem.h" 5 | #include "Util/MDViewModelInstanceKey.h" 6 | #include "MDGlobalViewModelCache.generated.h" 7 | 8 | class UMDViewModelBase; 9 | 10 | /** 11 | * Caches view models relative to the game instance 12 | */ 13 | UCLASS() 14 | class MDVIEWMODEL_API UMDGlobalViewModelCache : public UGameInstanceSubsystem, public IMDViewModelCacheInterface 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | virtual bool ShouldCreateSubsystem(UObject* Outer) const override; 20 | 21 | virtual void Deinitialize() override; 22 | 23 | protected: 24 | virtual UObject* GetViewModelOwner() const override; 25 | virtual TMap>& GetViewModelCache() override { return CachedViewModels; } 26 | virtual FString GetCacheDebugName() const override { return TEXT("Global Cache"); } 27 | 28 | private: 29 | UPROPERTY(VisibleAnywhere, Transient, Category = "View Model") 30 | TMap> CachedViewModels; 31 | }; 32 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Subsystems/MDLocalPlayerViewModelCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces/MDViewModelCacheInterface.h" 4 | #include "Subsystems/LocalPlayerSubsystem.h" 5 | #include "Util/MDViewModelInstanceKey.h" 6 | #include "MDLocalPlayerViewModelCache.generated.h" 7 | 8 | class UMDViewModelBase; 9 | 10 | /** 11 | * Caches view models relative to a local player 12 | */ 13 | UCLASS() 14 | class MDVIEWMODEL_API UMDLocalPlayerViewModelCache : public ULocalPlayerSubsystem, public IMDViewModelCacheInterface 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | virtual bool ShouldCreateSubsystem(UObject* Outer) const override; 20 | 21 | virtual void Deinitialize() override; 22 | 23 | protected: 24 | virtual UObject* GetViewModelOwner() const override; 25 | virtual TMap>& GetViewModelCache() override { return CachedViewModels; } 26 | virtual FString GetCacheDebugName() const override; 27 | 28 | private: 29 | UPROPERTY(VisibleAnywhere, Transient, Category = "View Model") 30 | TMap> CachedViewModels; 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Subsystems/MDObjectViewModelCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces/MDViewModelCacheInterface.h" 4 | #include "Subsystems/GameInstanceSubsystem.h" 5 | #include "MDObjectViewModelCache.generated.h" 6 | 7 | class FMDObjectViewModelCache : public IMDViewModelCacheInterface 8 | { 9 | public: 10 | void AddReferencedObjects(FReferenceCollector& Collector); 11 | 12 | void HandleObjectDestroyed(); 13 | 14 | TWeakObjectPtr Object; 15 | 16 | protected: 17 | virtual UObject* GetViewModelOwner() const override { return Object.Get(); } 18 | 19 | virtual TMap>& GetViewModelCache() override { return CachedViewModels; } 20 | 21 | virtual FString GetCacheDebugName() const override; 22 | 23 | private: 24 | TMap> CachedViewModels; 25 | }; 26 | 27 | /** 28 | * Caches view models relative to any UObject 29 | */ 30 | UCLASS() 31 | class MDVIEWMODEL_API UMDObjectViewModelCacheSystem : public UGameInstanceSubsystem 32 | { 33 | GENERATED_BODY() 34 | 35 | public: 36 | static UMDObjectViewModelCacheSystem* Get(const UObject* WorldContextObject); 37 | 38 | virtual bool ShouldCreateSubsystem(UObject* Outer) const override; 39 | 40 | virtual void Initialize(FSubsystemCollectionBase& Collection) override; 41 | virtual void Deinitialize() override; 42 | 43 | static IMDViewModelCacheInterface* ResolveCacheForObject(UObject* Object, const UObject* WorldContextObject); 44 | static IMDViewModelCacheInterface* ResolveCacheForObject(const UObject* Object, const UObject* WorldContextObject); 45 | 46 | static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector); 47 | 48 | protected: 49 | virtual void CheckCacheForDestroyedObjects(); 50 | 51 | private: 52 | TMap, TSharedPtr> ObjectCacheMap; 53 | }; 54 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Subsystems/MDWorldViewModelCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces/MDViewModelCacheInterface.h" 4 | #include "Subsystems/WorldSubsystem.h" 5 | #include "Util/MDViewModelInstanceKey.h" 6 | #include "MDWorldViewModelCache.generated.h" 7 | 8 | class UMDViewModelBase; 9 | 10 | /** 11 | * Caches view models relative to a world 12 | */ 13 | UCLASS() 14 | class MDVIEWMODEL_API UMDWorldViewModelCache : public UWorldSubsystem, public IMDViewModelCacheInterface 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | virtual bool ShouldCreateSubsystem(UObject* Outer) const override; 20 | 21 | virtual void Deinitialize() override; 22 | 23 | protected: 24 | virtual UObject* GetViewModelOwner() const override; 25 | virtual TMap>& GetViewModelCache() override { return CachedViewModels; } 26 | virtual FString GetCacheDebugName() const override; 27 | 28 | private: 29 | UPROPERTY(VisibleAnywhere, Transient, Category = "View Model") 30 | TMap> CachedViewModels; 31 | }; 32 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDVMAssignmentObjectKey.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Runtime/Launch/Resources/Version.h" 4 | #include "MDViewModelAssignment.h" 5 | #include "UObject/WeakInterfacePtr.h" 6 | 7 | class IMDViewModelRuntimeInterface; 8 | 9 | // Each assignment on an object needs to be individually tracked, this struct can serve as a key for it 10 | struct MDVIEWMODEL_API FMDVMAssignmentObjectKey 11 | { 12 | FMDViewModelAssignment Assignment; 13 | 14 | // TODO - Make TInterfaceKey or TObjectKey accept IInterface 15 | TWeakInterfacePtr ObjectPtr; 16 | 17 | bool operator==(const FMDVMAssignmentObjectKey& Other) const; 18 | 19 | bool operator!=(const FMDVMAssignmentObjectKey& Other) const 20 | { 21 | return !(*this == Other); 22 | } 23 | }; 24 | 25 | #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION == 1 26 | FORCEINLINE uint32 GetTypeHash(const FMDVMAssignmentObjectKey& Key) 27 | { 28 | return HashCombine(GetTypeHash(Key.Assignment), GetTypeHash(Key.ObjectPtr.GetWeakObjectPtr())); 29 | } 30 | #else 31 | FORCEINLINE uint32 GetTypeHash(const FMDVMAssignmentObjectKey& Key) 32 | { 33 | return HashCombine(GetTypeHash(Key.Assignment), Key.ObjectPtr.GetWeakObjectPtr().GetWeakPtrTypeHash()); 34 | } 35 | #endif 36 | 37 | MDVIEWMODEL_API FCbWriter& operator<<(FCbWriter& Writer, const FMDVMAssignmentObjectKey& Key); 38 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelAssignment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayTagContainer.h" 4 | #include "MDViewModelUtils.h" 5 | #include "Templates/SubclassOf.h" 6 | #include "ViewModelProviders/MDViewModelProvider_Manual.h" 7 | #include "MDViewModelAssignment.generated.h" 8 | 9 | class UMDViewModelBase; 10 | 11 | /** 12 | * Data to track the assignments of view model classes 13 | */ 14 | USTRUCT() 15 | struct MDVIEWMODEL_API FMDViewModelAssignment 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | UPROPERTY() 21 | TSubclassOf ViewModelClass; 22 | 23 | UPROPERTY() 24 | FGameplayTag ProviderTag = TAG_MDVMProvider_Manual; 25 | 26 | UPROPERTY() 27 | FName ViewModelName = MDViewModelUtils::DefaultViewModelName; 28 | 29 | #if WITH_EDITORONLY_DATA 30 | // Store class name so that this Assignment is still unique if ViewModelClass is renamed/deleted 31 | UPROPERTY() 32 | FName ViewModelClassName = NAME_None; 33 | 34 | void UpdateViewModelClassName(); 35 | #endif 36 | 37 | bool IsValid() const; 38 | 39 | void PostSerialize(const FArchive& Ar); 40 | 41 | bool operator==(const FMDViewModelAssignment& Other) const; 42 | 43 | bool operator!=(const FMDViewModelAssignment& Other) const 44 | { 45 | return !(*this == Other); 46 | } 47 | }; 48 | 49 | inline uint32 GetTypeHash(const FMDViewModelAssignment& Assignment) 50 | { 51 | return HashCombine( 52 | HashCombine(GetTypeHash(Assignment.ViewModelClass), GetTypeHash(Assignment.ProviderTag)), 53 | GetTypeHash(Assignment.ViewModelName)); 54 | } 55 | 56 | template<> 57 | struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 58 | { 59 | enum 60 | { 61 | WithPostSerialize = true 62 | }; 63 | }; 64 | 65 | MDVIEWMODEL_API FCbWriter& operator<<(FCbWriter& Writer, const FMDViewModelAssignment& Assignment); 66 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelAssignmentData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "InstancedStruct.h" 4 | #include "MDViewModelAssignmentData.generated.h" 5 | 6 | /** 7 | * Data linked to an FMDViewModelAssignment, setup at design/compile time and used at runtime 8 | */ 9 | USTRUCT() 10 | struct MDVIEWMODEL_API FMDViewModelAssignmentData 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | UPROPERTY() 16 | FInstancedStruct ProviderSettings; 17 | 18 | UPROPERTY() 19 | FInstancedStruct ViewModelSettings; 20 | }; 21 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelAssignmentReference.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelUtils.h" 4 | #include "UObject/Object.h" 5 | #include "MDViewModelAssignmentReference.generated.h" 6 | 7 | struct FMDViewModelAssignment; 8 | class UMDViewModelBase; 9 | 10 | 11 | /** 12 | * Helper struct to store a reference to a widget's view model assignment. 13 | * Has an editor customization to make selecting the view model user-friendly 14 | */ 15 | USTRUCT(BlueprintType) 16 | struct MDVIEWMODEL_API FMDViewModelAssignmentReference 17 | { 18 | GENERATED_BODY() 19 | 20 | public: 21 | PRAGMA_DISABLE_DEPRECATION_WARNINGS 22 | FMDViewModelAssignmentReference() = default; 23 | FMDViewModelAssignmentReference(const FMDViewModelAssignmentReference& Other) = default; 24 | PRAGMA_ENABLE_DEPRECATION_WARNINGS 25 | explicit FMDViewModelAssignmentReference(const FMDViewModelAssignment& Assignment); 26 | FMDViewModelAssignmentReference(TSubclassOf ViewModelClass, const FName& ViewModelName); 27 | 28 | // The view model class to reference 29 | UPROPERTY(EditAnywhere, Category = "View Model") 30 | TSoftClassPtr ViewModelClass; 31 | 32 | // The name of the view model instance to reference 33 | UPROPERTY(EditAnywhere, Category = "View Model") 34 | FName ViewModelName = MDViewModelUtils::DefaultViewModelName; 35 | 36 | bool IsAssignmentValid() const; 37 | 38 | void PostSerialize(const FArchive& Ar); 39 | 40 | #if WITH_EDITOR 41 | // Only used for editor customization 42 | DECLARE_DELEGATE_RetVal(UClass*, FMDViewModelReferenceGetObjectClass); 43 | UE_DEPRECATED(All, "OnGetWidgetClass is deprecated, bind to OnGetBoundObjectClass instead.") 44 | FMDViewModelReferenceGetObjectClass OnGetWidgetClass; 45 | FMDViewModelReferenceGetObjectClass OnGetBoundObjectClass; 46 | 47 | UClass* GetBoundObjectClass() const 48 | { 49 | if (OnGetBoundObjectClass.IsBound()) 50 | { 51 | return OnGetBoundObjectClass.Execute(); 52 | } 53 | 54 | PRAGMA_DISABLE_DEPRECATION_WARNINGS 55 | if (OnGetWidgetClass.IsBound()) 56 | { 57 | return OnGetWidgetClass.Execute(); 58 | } 59 | PRAGMA_ENABLE_DEPRECATION_WARNINGS 60 | 61 | return nullptr; 62 | } 63 | 64 | FText GetDisplayText() const; 65 | #endif 66 | 67 | FMDViewModelAssignmentReference& operator=(const FMDViewModelAssignmentReference& Other); 68 | 69 | bool operator==(const FMDViewModelAssignmentReference& Other) const; 70 | 71 | friend uint32 GetTypeHash(const FMDViewModelAssignmentReference& AssignmentReference) 72 | { 73 | return HashCombine(GetTypeHash(AssignmentReference.ViewModelName), GetTypeHash(AssignmentReference.ViewModelClass)); 74 | } 75 | }; 76 | 77 | template<> 78 | struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 79 | { 80 | enum 81 | { 82 | WithCopy = true, 83 | WithPostSerialize = true 84 | }; 85 | }; 86 | 87 | MDVIEWMODEL_API FCbWriter& operator<<(FCbWriter& Writer, const FMDViewModelAssignmentReference& Assignment); 88 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Engine/DeveloperSettings.h" 4 | #include "GameplayTagContainer.h" 5 | #include "MDViewModelConfig.generated.h" 6 | 7 | /** 8 | * Project-wide settings for MDViewModel 9 | */ 10 | UCLASS(DefaultConfig, Config = ViewModel) 11 | class MDVIEWMODEL_API UMDViewModelConfig : public UDeveloperSettings 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | UMDViewModelConfig(); 17 | 18 | virtual void PostInitProperties() override; 19 | 20 | // The default lifetime to set when adding a new view model assignment 21 | UPROPERTY(EditDefaultsOnly, Config, Category = "Providers|Cached", meta = (Categories = "MDVM.Provider.Cached.Lifetimes")) 22 | FGameplayTag DefaultViewModelLifetime; 23 | }; 24 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelInstanceKey.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Templates/SubclassOf.h" 4 | #include "MDViewModelInstanceKey.generated.h" 5 | 6 | class UMDViewModelBase; 7 | 8 | USTRUCT() 9 | struct MDVIEWMODEL_API FMDViewModelInstanceKey 10 | { 11 | GENERATED_BODY() 12 | 13 | public: 14 | UPROPERTY(VisibleAnywhere, Category = "View Model") 15 | FName ViewModelName = NAME_None; 16 | 17 | UPROPERTY(VisibleAnywhere, Category = "View Model") 18 | TSubclassOf ViewModelClass; 19 | 20 | bool IsValid() const; 21 | 22 | bool operator==(const FMDViewModelInstanceKey& Other) const; 23 | 24 | friend uint32 GetTypeHash(const FMDViewModelInstanceKey& Key) 25 | { 26 | return HashCombine(GetTypeHash(Key.ViewModelName), GetTypeHash(Key.ViewModelClass)); 27 | } 28 | }; 29 | 30 | MDVIEWMODEL_API FCbWriter& operator<<(FCbWriter& Writer, const FMDViewModelInstanceKey& Key); 31 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelLog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Logging/LogMacros.h" 4 | 5 | MDVIEWMODEL_API DECLARE_LOG_CATEGORY_EXTERN(LogMDViewModel, Display, All); 6 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Util/MDViewModelUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayTagContainer.h" 4 | #include "Templates/SubclassOf.h" 5 | #include "UObject/NameTypes.h" 6 | 7 | class IMDViewModelRuntimeInterface; 8 | struct FGameplayTag; 9 | struct FMDViewModelAssignmentData; 10 | struct FMDViewModelAssignment; 11 | 12 | class IMDVMCompiledAssignmentsInterface; 13 | class UClass; 14 | class UGameInstance; 15 | class UMDViewModelBase; 16 | class UMDViewModelProviderBase; 17 | 18 | namespace MDViewModelUtils 19 | { 20 | // The default name given to view models 21 | MDVIEWMODEL_API extern const FName DefaultViewModelName; 22 | 23 | MDVIEWMODEL_API UMDViewModelProviderBase* FindViewModelProvider(const FGameplayTag& ProviderTag); 24 | 25 | MDVIEWMODEL_API void GetViewModelAssignments(UClass* ObjectClass, TMap& OutViewModelAssignments); 26 | MDVIEWMODEL_API void SearchViewModelAssignments(UClass* ObjectClass, TMap& OutViewModelAssignments, TSubclassOf ViewModelClass = nullptr, const FGameplayTag& ProviderTag = FGameplayTag::EmptyTag, const FName& ViewModelName = NAME_None); 27 | MDVIEWMODEL_API bool HasViewModelAssignments(UClass* ObjectClass); 28 | 29 | MDVIEWMODEL_API IMDVMCompiledAssignmentsInterface* GetCompiledAssignmentsInterface(UClass* ObjectClass); 30 | MDVIEWMODEL_API IMDViewModelRuntimeInterface* GetViewModelRuntimeInterface(const UObject* Object); 31 | MDVIEWMODEL_API IMDViewModelRuntimeInterface* GetOrCreateViewModelRuntimeInterface(UObject* Object); 32 | 33 | MDVIEWMODEL_API const FProperty* GetFunctionReturnProperty(const UFunction* Function); 34 | } 35 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/ViewModelProviders/MDViewModelProvider_Manual.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelProviderBase.h" 4 | #include "NativeGameplayTags.h" 5 | #include "MDViewModelProvider_Manual.generated.h" 6 | 7 | MDVIEWMODEL_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_MDVMProvider_Manual); 8 | 9 | /** 10 | * Special case provider that does not actually provide view models. 11 | * Used to indicate that a view model assignment exists but the actual view model will 12 | * be set manually using something like UMDViewModelFunctionLibrary::SetViewModel in an external system. 13 | */ 14 | UCLASS() 15 | class MDVIEWMODEL_API UMDViewModelProvider_Manual : public UMDViewModelProviderBase 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | virtual UMDViewModelBase* SetViewModel(IMDViewModelRuntimeInterface& Object, const FMDViewModelAssignment& Assignment, const FMDViewModelAssignmentData& Data) override; 21 | 22 | virtual bool DoesSupportViewModelSettings() const override { return false; } 23 | virtual bool DoesAllowManualSetting() const override { return true; } 24 | 25 | virtual FGameplayTag GetProviderTag() const override { return TAG_MDVMProvider_Manual; } 26 | 27 | #if WITH_EDITOR 28 | virtual bool DoesCreateViewModels() const override { return false; } 29 | virtual FText GetDisplayName() const override { return INVTEXT("Manual Set"); } 30 | virtual FText GetDescription(const FInstancedStruct& ProviderSettings) const override { return INVTEXT("The view model will have to be manually set on the object at runtime."); } 31 | #endif 32 | }; 33 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/ViewModelProviders/MDViewModelProvider_Unique.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelProviderBase.h" 4 | #include "NativeGameplayTags.h" 5 | #include "ViewModel/MDViewModelBase.h" 6 | #include "MDViewModelProvider_Unique.generated.h" 7 | 8 | MDVIEWMODEL_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_MDVMProvider_Unique); 9 | 10 | /** 11 | * This provider will create a unique instance of the selected viewmodel for each assigned object. 12 | */ 13 | UCLASS() 14 | class MDVIEWMODEL_API UMDViewModelProvider_Unique : public UMDViewModelProviderBase 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | virtual UMDViewModelBase* SetViewModel(IMDViewModelRuntimeInterface& Object, const FMDViewModelAssignment& Assignment, const FMDViewModelAssignmentData& Data) override; 20 | 21 | virtual FGameplayTag GetProviderTag() const override { return TAG_MDVMProvider_Unique; } 22 | 23 | #if WITH_EDITOR 24 | virtual FText GetDisplayName() const override { return INVTEXT("Unique Instance"); } 25 | virtual FText GetDescription(const FInstancedStruct& ProviderSettings) const override { return INVTEXT("A unique view model instance will be created for the assigned object."); } 26 | virtual void GetExpectedContextObjectTypes(const FInstancedStruct& ProviderSettings, const FInstancedStruct& ViewModelSettings, UBlueprint* Blueprint, TArray>& OutContextObjectClasses) const override; 27 | #endif 28 | 29 | private: 30 | void OnBoundObjectViewModelChanged(UMDViewModelBase* OldViewModel, UMDViewModelBase* NewViewModel); 31 | 32 | TSet> UniqueVMs; 33 | }; 34 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/WidgetExtensions/MDViewModelWidgetClassExtension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelWidgetExtension.h" 4 | #include "Extensions/WidgetBlueprintGeneratedClassExtension.h" 5 | #include "Interfaces/MDVMCompiledAssignmentsInterface.h" 6 | #include "Util/MDViewModelAssignment.h" 7 | #include "Util/MDViewModelAssignmentData.h" 8 | #include "MDViewModelWidgetClassExtension.generated.h" 9 | 10 | 11 | /** 12 | * 13 | */ 14 | UCLASS() 15 | class MDVIEWMODEL_API UMDViewModelWidgetClassExtension : public UWidgetBlueprintGeneratedClassExtension, public IMDVMCompiledAssignmentsInterface 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | virtual void BeginDestroy() override; 21 | virtual void Initialize(UUserWidget* UserWidget) override; 22 | 23 | #if WITH_EDITOR 24 | virtual void Construct(UUserWidget* UserWidget) override; 25 | #endif 26 | 27 | virtual void SetAssignments(const TMap& InAssignments) override; 28 | virtual const TMap& GetAssignments() const override { return Assignments; } 29 | 30 | // Used to listen for changes before the specified widget's viewmodel extension is created 31 | void QueueListenForChanges(UUserWidget* Widget, FMDVMOnViewModelSet::FDelegate&& Delegate, const FMDViewModelAssignmentReference& Assignment); 32 | 33 | protected: 34 | UPROPERTY() 35 | TMap Assignments; 36 | 37 | private: 38 | struct QueuedListenerData 39 | { 40 | FMDVMOnViewModelSet::FDelegate Delegate; 41 | FMDViewModelAssignmentReference Assignment; 42 | }; 43 | 44 | TMap, TArray> QueuedDelegates; 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/WidgetExtensions/MDViewModelWidgetExtension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Extensions/UserWidgetExtension.h" 4 | #include "Interfaces/MDViewModelRuntimeInterface.h" 5 | #include "Templates/SubclassOf.h" 6 | #include "UObject/Package.h" 7 | #include "Util/MDViewModelAssignmentReference.h" 8 | #include "MDViewModelWidgetExtension.generated.h" 9 | 10 | struct FGameplayTag; 11 | struct FInstancedStruct; 12 | class UMDViewModelBase; 13 | 14 | /** 15 | * A widget extension to track a widget's view models 16 | */ 17 | UCLASS(BlueprintType) 18 | class MDVIEWMODEL_API UMDViewModelWidgetExtension : public UUserWidgetExtension, public IMDViewModelRuntimeInterface 19 | { 20 | GENERATED_BODY() 21 | 22 | public: 23 | virtual void Construct() override; 24 | virtual void Destruct() override; 25 | virtual void BeginDestroy() override; 26 | 27 | static UMDViewModelWidgetExtension* GetOrCreate(UUserWidget* Widget); 28 | 29 | virtual UObject* GetOwningObject() const override; 30 | 31 | virtual UGameInstance* ResolveGameInstance() const override; 32 | virtual UWorld* ResolveWorld() const override; 33 | virtual ULocalPlayer* ResolveOwningLocalPlayer() const override; 34 | virtual APlayerController* ResolveOwningPlayer() const override; 35 | 36 | protected: 37 | virtual TMap>& GetViewModels() override; 38 | 39 | private: 40 | UPROPERTY(Transient) 41 | TMap> ViewModels; 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Widgets/MDVMDynamicEntryBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/DynamicEntryBox.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMDynamicEntryBox.generated.h" 6 | 7 | class UMDViewModelBase; 8 | 9 | /** 10 | * A dynamic entry box that can be populated by a list of view models 11 | */ 12 | UCLASS(meta = (DisplayName = "Dynamic Entry Box (View Model)")) 13 | class MDVIEWMODEL_API UMDVMDynamicEntryBox : public UDynamicEntryBox 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEntryDynamicEvent, UUserWidget*, Widget, UMDViewModelBase*, ViewModel); 19 | 20 | virtual void PostInitProperties() override; 21 | virtual void PostLoad() override; 22 | virtual TSharedRef RebuildWidget() override; 23 | 24 | #if WITH_EDITOR 25 | virtual const FText GetPaletteCategory() override; 26 | virtual void ValidateCompiledDefaults(class IWidgetCompilerLog& CompileLog) const override; 27 | virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override; 28 | #endif 29 | 30 | UFUNCTION(BlueprintCallable, Category = "DynamicEntryBox") 31 | void PopulateItems(const TArray& ViewModels); 32 | 33 | // Event triggered for each entry when PopulateItems is called, before Construct is called on new entries. 34 | UPROPERTY(BlueprintAssignable, Category = "DynamicEntryBox") 35 | FOnEntryDynamicEvent OnEntryGenerated; 36 | 37 | // Event triggered right before removing entries in PopulateItems, usually due to a smaller list being passed in than was last populated. 38 | UPROPERTY(BlueprintAssignable, Category = "DynamicEntryBox") 39 | FOnEntryDynamicEvent OnEntryRemoved; 40 | 41 | protected: 42 | virtual void SynchronizeProperties() override; 43 | virtual void AddEntryChild(UUserWidget& ChildWidget) override; 44 | 45 | UPROPERTY() 46 | FMDViewModelAssignmentReference ViewModelAssignment; 47 | 48 | // The view model(s) to set on the entry widgets when populating this list 49 | // If multiple are specified, the assignments that match the view model instance's class will be set and the rest will be cleared 50 | // If the view model instance is nullptr, all of these assignments will be cleared on it 51 | UPROPERTY(EditAnywhere, Category = "EntryLayout", meta = (DisplayAfter = "EntryWidgetClass", TitleProperty = "{ViewModelClass} ({ViewModelName})")) 52 | TArray ViewModelAssignments; 53 | 54 | // At least this many widgets will display when calling PopulateItems, setting null view models to make up the difference in items if necessary 55 | // Also acts as a lower limit for `NumDesignerPreviewEntries` 56 | UPROPERTY(EditAnywhere, Category = "DynamicEntryBox", meta = (DisplayAfter = "NumDesignerPreviewEntries", ClampMin = 0)) 57 | int32 MinimumEntriesToDisplay = 0; 58 | 59 | private: 60 | #if WITH_EDITOR 61 | UClass* GetEditorTimeEntryWidgetClass() const; 62 | #endif 63 | 64 | void PopulateEntryWidget(UUserWidget* EntryWidget) const; 65 | 66 | // The current view model being constructed, for injecting set view models before Entry Widget construction in AddEntryChild 67 | TWeakObjectPtr CurrentViewModel; 68 | 69 | // View models that were populated before the slate widget was constructed 70 | TArray> PendingViewModels; 71 | bool bUsePendingList = false; 72 | 73 | }; 74 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Widgets/MDViewModelComboBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/Widget.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "ViewModel/MDViewModelBase.h" 6 | #include "Widgets/Input/SComboBox.h" 7 | #include "MDViewModelComboBox.generated.h" 8 | 9 | /** 10 | * Combo box widget that can be populated by a list of view models 11 | */ 12 | UCLASS(DisplayName="ComboBox (View Model)") 13 | class MDVIEWMODEL_API UMDViewModelComboBox : public UWidget 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | UMDViewModelComboBox(); 19 | 20 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnItemSelectedDynamic, UMDViewModelBase*, Item); 21 | DECLARE_MULTICAST_DELEGATE_OneParam(FOnItemSelected, UMDViewModelBase*); 22 | 23 | UFUNCTION(BlueprintCallable , Category = "Combo Box") 24 | void PopulateItems(const TArray& InViewModels); 25 | 26 | // 'Setter' functions require UFUNCTION markup until 5.2 27 | UFUNCTION() 28 | void SetSelectedItem(UMDViewModelBase* ViewModel); 29 | 30 | virtual void ReleaseSlateResources(bool bReleaseChildren) override; 31 | 32 | virtual void PostInitProperties() override; 33 | 34 | #if WITH_EDITOR 35 | virtual const FText GetPaletteCategory() override; 36 | virtual void ValidateCompiledDefaults(class IWidgetCompilerLog& CompileLog) const override; 37 | #endif 38 | 39 | UPROPERTY(EditAnywhere, Category = "Combo Box") 40 | TSubclassOf EntryWidgetClass; 41 | 42 | UPROPERTY(EditAnywhere, Category = "Combo Box") 43 | FMDViewModelAssignmentReference ViewModelAssignment; 44 | 45 | UPROPERTY(EditAnywhere, Category = "Interaction") 46 | bool bIsFocusable = true; 47 | 48 | UPROPERTY(EditAnywhere, Category = "Style", meta=(DisplayName="Style", DesignerRebuild)) 49 | FComboBoxStyle WidgetStyle; 50 | 51 | UPROPERTY(EditAnywhere, Category = "Style", meta=(DesignerRebuild)) 52 | FTableRowStyle EntryStyle; 53 | 54 | UPROPERTY(EditAnywhere, Category = "Style", meta=(DesignerRebuild)) 55 | FScrollBarStyle ScrollBarStyle; 56 | 57 | UPROPERTY(BlueprintAssignable, DisplayName = "On Item Selected", Category = "Combo Box") 58 | FOnItemSelectedDynamic BP_OnItemSelected; 59 | FOnItemSelected OnItemSelected; 60 | 61 | protected: 62 | virtual TSharedRef RebuildWidget() override; 63 | 64 | TSharedRef GenerateEntryWidget(UMDViewModelBase* Item) const; 65 | void OnSelectionChanged(UMDViewModelBase* Item, ESelectInfo::Type SelectType); 66 | 67 | void UpdateSelectedItemWidget(); 68 | 69 | UClass* GetEntryWidgetClass() const; 70 | 71 | TSharedPtr> MyComboBox; 72 | TSharedPtr ComboBoxContent; 73 | 74 | UPROPERTY(BlueprintReadWrite, FieldNotify, Setter, Transient, Category = "Combo Box") 75 | TObjectPtr SelectedItem; 76 | 77 | UPROPERTY(Transient) 78 | TArray> ViewModels; 79 | }; 80 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Widgets/MDViewModelSwitcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/WidgetSwitcher.h" 4 | #include "UObject/Object.h" 5 | #include "MDViewModelSwitcher.generated.h" 6 | 7 | class UMDViewModelBase; 8 | /** 9 | * Widget that will switch to the first child that accepts the provided view model 10 | * Using this widget requires knowledge of which types of viewmodels will be passed to it to be used effectively. 11 | */ 12 | UCLASS(meta = (DisplayName = "Widget Switcher (View Model)")) 13 | class MDVIEWMODEL_API UMDViewModelSwitcher : public UWidgetSwitcher 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | UFUNCTION(BlueprintCallable, Category = "View Model") 19 | void SetViewModel(UMDViewModelBase* ViewModel); 20 | 21 | #if WITH_EDITOR 22 | virtual const FText GetPaletteCategory() override; 23 | virtual void ValidateCompiledDefaults(IWidgetCompilerLog& CompileLog) const override; 24 | #endif 25 | 26 | protected: 27 | virtual UClass* GetSlotClass() const override; 28 | }; 29 | -------------------------------------------------------------------------------- /Source/MDViewModel/Public/Widgets/MDViewModelSwitcherSlot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Components/WidgetSwitcherSlot.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "Util/MDViewModelUtils.h" 6 | #include "MDViewModelSwitcherSlot.generated.h" 7 | 8 | /** 9 | * 10 | */ 11 | UCLASS(meta = (DisplayName = "Widget Switcher Slot (View Model)")) 12 | class MDVIEWMODEL_API UMDViewModelSwitcherSlot : public UWidgetSwitcherSlot 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | virtual void PostInitProperties() override; 18 | 19 | bool DoesSupportChildViewModelClasses() const { return bSupportChildViewModelClasses; } 20 | 21 | const FMDViewModelAssignmentReference& GetViewModelAssignment() const { return ViewModelAssignment; } 22 | 23 | protected: 24 | // Whether or not to switch to this widget for child viewmodel classes that it supports, otherwise requiring exact viewmodel-class matching. 25 | UPROPERTY(EditAnywhere, Category="Layout|Widget Switcher Slot") 26 | bool bSupportChildViewModelClasses = false; 27 | 28 | // Which assignment to use to assign view models to this widget 29 | UPROPERTY(EditAnywhere, Category="Layout|Widget Switcher Slot") 30 | FMDViewModelAssignmentReference ViewModelAssignment; 31 | 32 | private: 33 | #if WITH_EDITOR 34 | UClass* GetContentWidgetClass() const; 35 | #endif 36 | }; 37 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/MDViewModelEditor.Build.cs: -------------------------------------------------------------------------------- 1 | using UnrealBuildTool; 2 | 3 | public class MDViewModelEditor : ModuleRules 4 | { 5 | public MDViewModelEditor(ReadOnlyTargetRules Target) : base(Target) 6 | { 7 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 8 | 9 | PublicDependencyModuleNames.AddRange( 10 | new string[] 11 | { 12 | "Core", 13 | "GameplayTags", 14 | "MDViewModel", 15 | "StructUtilsEditor" 16 | } 17 | ); 18 | 19 | #if UE_5_3_OR_LATER 20 | PublicDependencyModuleNames.Add("FieldNotification"); 21 | #endif 22 | 23 | PrivateDependencyModuleNames.AddRange( 24 | new string[] 25 | { 26 | "ApplicationCore", 27 | "BlueprintGraph", 28 | "CoreUObject", 29 | "DeveloperSettings", 30 | "Engine", 31 | "GraphEditor", 32 | "InputCore", 33 | "Kismet", 34 | "MDViewModelGraph", 35 | "PropertyEditor", 36 | "SharedSettingsWidgets", 37 | "Slate", 38 | "SlateCore", 39 | "SourceControl", 40 | "StructUtils", 41 | "ToolWidgets", 42 | "UMG", 43 | "UMGEditor", 44 | "UnrealEd" 45 | } 46 | ); 47 | } 48 | } -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/MDViewModelEditorConfig.cpp: -------------------------------------------------------------------------------- 1 | #include "MDViewModelEditorConfig.h" 2 | 3 | #include "ClassViewerModule.h" 4 | #include "GameplayTagsManager.h" 5 | #include "Kismet2/KismetEditorUtilities.h" 6 | #include "MDViewModelEditorModule.h" 7 | #include "ViewModel/MDViewModelBlueprintBase.h" 8 | 9 | UMDViewModelEditorConfig::UMDViewModelEditorConfig() 10 | { 11 | CategoryName = TEXT("Plugins"); 12 | SectionName = TEXT("View Model Editor"); 13 | } 14 | 15 | void UMDViewModelEditorConfig::PostInitProperties() 16 | { 17 | Super::PostInitProperties(); 18 | 19 | UGameplayTagsManager::Get().CallOrRegister_OnDoneAddingNativeTagsDelegate( 20 | FSimpleMulticastDelegate::FDelegate::CreateWeakLambda(this, [this]() { ReloadConfig(); })); 21 | } 22 | 23 | void UMDViewModelEditorConfig::PostCDOContruct() 24 | { 25 | Super::PostCDOContruct(); 26 | 27 | UpdateViewModelBPDefaultEventNodes(); 28 | } 29 | 30 | void UMDViewModelEditorConfig::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) 31 | { 32 | Super::PostEditChangeProperty(PropertyChangedEvent); 33 | 34 | UpdateViewModelBPDefaultEventNodes(); 35 | } 36 | 37 | EClassViewerNameTypeToDisplay UMDViewModelEditorConfig::GetNameTypeToDisplay() const 38 | { 39 | switch (NameTypeToDisplay) 40 | { 41 | case EMDVMClassViewerNameTypeToDisplay::Dynamic: 42 | return EClassViewerNameTypeToDisplay::Dynamic; 43 | case EMDVMClassViewerNameTypeToDisplay::ClassName: 44 | return EClassViewerNameTypeToDisplay::ClassName; 45 | case EMDVMClassViewerNameTypeToDisplay::DisplayName: 46 | return EClassViewerNameTypeToDisplay::DisplayName; 47 | default: 48 | checkf(false, TEXT("Unhandled EMDVMClassViewerNameTypeToDisplay type")); 49 | } 50 | 51 | return EClassViewerNameTypeToDisplay::DisplayName; 52 | } 53 | 54 | void UMDViewModelEditorConfig::UpdateViewModelBPDefaultEventNodes() const 55 | { 56 | if (FMDViewModelEditorModule* EditorModule = FModuleManager::GetModulePtr("MDViewModelEditor")) 57 | { 58 | if (bAutoCreateDefaultEvents) 59 | { 60 | FKismetEditorUtilities::RegisterAutoGeneratedDefaultEvent(EditorModule, UMDViewModelBlueprintBase::StaticClass(), TEXT("BP_InitializeViewModel")); 61 | FKismetEditorUtilities::RegisterAutoGeneratedDefaultEvent(EditorModule, UMDViewModelBlueprintBase::StaticClass(), TEXT("BP_ShutdownViewModel")); 62 | } 63 | else 64 | { 65 | FKismetEditorUtilities::UnregisterAutoBlueprintNodeCreation(EditorModule); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/MDViewModelEditorConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Engine/DeveloperSettings.h" 4 | #include "GameplayTagContainer.h" 5 | #include "MDViewModelEditorConfig.generated.h" 6 | 7 | enum class EClassViewerNameTypeToDisplay: uint8; 8 | 9 | UENUM() 10 | enum class EMDVMClassViewerNameTypeToDisplay : uint8 11 | { 12 | /** Display both the display name and class name if they're available and different. */ 13 | Dynamic, 14 | /** Always use the display name */ 15 | DisplayName, 16 | /** Always use the class name */ 17 | ClassName, 18 | }; 19 | 20 | /** 21 | * Settings 22 | */ 23 | UCLASS(DefaultConfig, Config = MDViewModelEditor, meta = (DisplayName = "View Model Editor")) 24 | class MDVIEWMODELEDITOR_API UMDViewModelEditorConfig : public UDeveloperSettings 25 | { 26 | GENERATED_BODY() 27 | 28 | public: 29 | UMDViewModelEditorConfig(); 30 | 31 | virtual FName GetContainerName() const override { return TEXT("Editor"); } 32 | 33 | virtual void PostInitProperties() override; 34 | 35 | virtual void PostCDOContruct() override; 36 | 37 | virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; 38 | 39 | // How the view model classes are displayed in the class selection list 40 | UPROPERTY(EditDefaultsOnly, Config, Category = "View Model Dialog") 41 | EMDVMClassViewerNameTypeToDisplay NameTypeToDisplay = EMDVMClassViewerNameTypeToDisplay::DisplayName; 42 | 43 | // If true, a gameplay tag selector will be used instead of a text field to enter view model instance names 44 | UPROPERTY(EditDefaultsOnly, Config, Category = "View Model Dialog") 45 | bool bUseGameplayTagsForViewModelNaming = false; 46 | 47 | // If set, view model name tag selection is limited to children of this tag. 48 | UPROPERTY(EditDefaultsOnly, Config, Category = "View Model Dialog", meta = (EditCondition = "bUseGameplayTagsForViewModelNaming", EditConditionHides)) 49 | FGameplayTag ViewModelNameRootTag; 50 | 51 | // If true, the view model editor will be enabled in actor blueprints. 52 | // Any existing view model assignments will continue to work even if the editor is disabled. 53 | UPROPERTY(EditDefaultsOnly, Config, Category = "Actor View Models") 54 | bool bEnableViewModelsInActorBlueprints = true; 55 | 56 | // If true, the view model editor will call functions that appear in the Properties list and display the values of the result in the view model editor 57 | // This only happens when an object with a valid view model is selected in the blueprint editor 58 | UPROPERTY(EditDefaultsOnly, Config, Category = "View Model Debugger") 59 | bool bEnableReturnValuePreviewing = true; 60 | 61 | // If true, new View Model blueprints will pre-populate with the Initialize and Shutdown event nodes 62 | UPROPERTY(EditDefaultsOnly, Config, Category = "View Model Blueprints") 63 | bool bAutoCreateDefaultEvents = true; 64 | 65 | EClassViewerNameTypeToDisplay GetNameTypeToDisplay() const; 66 | 67 | void UpdateViewModelBPDefaultEventNodes() const; 68 | }; 69 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/Util/MDVMEditorUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDVMEditorUtils.h" 2 | 3 | #include "Framework/Notifications/NotificationManager.h" 4 | #include "ISourceControlModule.h" 5 | #include "HAL/PlatformFileManager.h" 6 | #include "SSettingsEditorCheckoutNotice.h" 7 | #include "ViewModel/MDViewModelBase.h" 8 | #include "Widgets/Notifications/SNotificationList.h" 9 | 10 | void MDVMEditorUtils::SaveViewModelConfig(UMDViewModelBase* ViewModelCDO) 11 | { 12 | if (IsValid(ViewModelCDO) && ViewModelCDO->IsTemplate()) 13 | { 14 | const bool bIsUsingSourceControl = ISourceControlModule::Get().IsEnabled(); 15 | const FString ConfigFilePath = FPaths::ConvertRelativePathToFull(ViewModelCDO->GetDefaultConfigFilename()); 16 | const bool bIsNewFile = !FPlatformFileManager::Get().GetPlatformFile().FileExists(*ConfigFilePath); 17 | if (!bIsNewFile && !SettingsHelpers::IsCheckedOut(ConfigFilePath)) 18 | { 19 | if (!bIsUsingSourceControl) 20 | { 21 | SettingsHelpers::MakeWritable(ConfigFilePath); 22 | } 23 | else if (!SettingsHelpers::CheckOutOrAddFile(ConfigFilePath, true)) 24 | { 25 | FNotificationInfo Info = FNotificationInfo(FText::Format(INVTEXT("Could not check out config file {0}"), FText::FromString(FPaths::GetCleanFilename(ConfigFilePath)))); 26 | Info.ExpireDuration = 6.0f; 27 | FSlateNotificationManager::Get().AddNotification(Info); 28 | 29 | SettingsHelpers::MakeWritable(ConfigFilePath); 30 | } 31 | } 32 | 33 | ViewModelCDO->TryUpdateDefaultConfigFile(); 34 | 35 | if (bIsNewFile && bIsUsingSourceControl) 36 | { 37 | SettingsHelpers::CheckOutOrAddFile(ConfigFilePath, true); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/Util/MDViewModelClassFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelClassFilter.h" 2 | 3 | #include "ViewModel/MDViewModelBase.h" 4 | #include "ViewModel/MDViewModelBlueprintBase.h" 5 | #include "ViewModelProviders/MDViewModelProviderBase.h" 6 | 7 | FMDViewModelClassFilter::FMDViewModelClassFilter(UMDViewModelProviderBase* Provider) 8 | { 9 | ProviderSupportedViewModelClasses = TArray{}; 10 | 11 | if (IsValid(Provider)) 12 | { 13 | Provider->GetSupportedViewModelClasses(ProviderSupportedViewModelClasses.GetValue()); 14 | bAllowAbstract = !Provider->DoesCreateViewModels(); 15 | } 16 | } 17 | 18 | FMDViewModelClassFilter::FMDViewModelClassFilter(bool bAllowAbstract) 19 | : bAllowAbstract(bAllowAbstract) 20 | { 21 | } 22 | 23 | bool FMDViewModelClassFilter::IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef InFilterFuncs) 24 | { 25 | if (InClass == UMDViewModelBase::StaticClass()) 26 | { 27 | return true; 28 | } 29 | 30 | if (InClass == UMDViewModelBlueprintBase::StaticClass() || !InClass->IsChildOf()) 31 | { 32 | return false; 33 | } 34 | 35 | const bool bHasValidFlags = !InClass->HasAnyClassFlags(CLASS_Hidden | CLASS_HideDropDown | CLASS_Deprecated); 36 | if (bHasValidFlags && (bAllowAbstract || !InClass->HasAnyClassFlags(CLASS_Abstract))) 37 | { 38 | if (!ProviderSupportedViewModelClasses.IsSet()) 39 | { 40 | return true; 41 | } 42 | 43 | for (const FMDViewModelSupportedClass& SupportedClass : ProviderSupportedViewModelClasses.GetValue()) 44 | { 45 | if (SupportedClass.Class == InClass || (SupportedClass.bAllowChildClasses && InClass->IsChildOf(SupportedClass.Class))) 46 | { 47 | return true; 48 | } 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | 55 | bool FMDViewModelClassFilter::IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef InUnloadedClassData, TSharedRef InFilterFuncs) 56 | { 57 | if (!InUnloadedClassData->IsChildOf(UMDViewModelBase::StaticClass())) 58 | { 59 | return false; 60 | } 61 | 62 | const bool bHasValidFlags = !InUnloadedClassData->HasAnyClassFlags(CLASS_Hidden | CLASS_HideDropDown | CLASS_Deprecated); 63 | if (bHasValidFlags && (bAllowAbstract || !InUnloadedClassData->HasAnyClassFlags(CLASS_Abstract))) 64 | { 65 | if (!ProviderSupportedViewModelClasses.IsSet()) 66 | { 67 | return true; 68 | } 69 | 70 | for (const FMDViewModelSupportedClass& SupportedClass : ProviderSupportedViewModelClasses.GetValue()) 71 | { 72 | if (SupportedClass.bAllowChildClasses && InUnloadedClassData->IsChildOf(SupportedClass.Class)) 73 | { 74 | return true; 75 | } 76 | } 77 | } 78 | 79 | return false; 80 | } 81 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMDragAndDropWrapperButton.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMDragAndDropWrapperButton.h" 2 | 3 | #include "Editor.h" 4 | #include "Editor/EditorEngine.h" 5 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropActionBase.h" 6 | #include "ViewModelTab/FieldInspector/MDViewModelDebugLineItemBase.h" 7 | 8 | void SMDVMDragAndDropWrapperButton::Construct(const FArguments& InArgs) 9 | { 10 | bCanDrag = InArgs._bCanDrag; 11 | OnGetDragAndDropAction = InArgs._OnGetDragAndDropAction; 12 | 13 | SButton::Construct(SButton::FArguments(InArgs._ButtonArguments) 14 | [ 15 | InArgs._Content.Widget 16 | ]); 17 | } 18 | 19 | TOptional SMDVMDragAndDropWrapperButton::GetCursor() const 20 | { 21 | return CanDrag() ? EMouseCursor::GrabHand : SCompoundWidget::GetCursor(); 22 | } 23 | 24 | FReply SMDVMDragAndDropWrapperButton::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) 25 | { 26 | FReply Reply = SButton::OnMouseButtonDown(MyGeometry, MouseEvent); 27 | if (CanDrag() && MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) 28 | { 29 | Reply = Reply.DetectDrag(AsShared(), EKeys::LeftMouseButton); 30 | } 31 | 32 | return Reply; 33 | } 34 | 35 | FReply SMDVMDragAndDropWrapperButton::OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) 36 | { 37 | if (CanDrag()) 38 | { 39 | return FReply::Handled().BeginDragDrop(OnGetDragAndDropAction.Execute()); 40 | } 41 | 42 | return FReply::Unhandled(); 43 | } 44 | 45 | bool SMDVMDragAndDropWrapperButton::CanDrag() const 46 | { 47 | return !GEditor->bIsSimulatingInEditor && GEditor->PlayWorld == nullptr && OnGetDragAndDropAction.IsBound() && bCanDrag.Get(false); 48 | } 49 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropActionBase.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropActionBase.h" 2 | 3 | #include "EdGraphSchema_K2.h" 4 | #include "Styling/AppStyle.h" 5 | #include "ViewModel/MDViewModelBase.h" 6 | 7 | 8 | FReply FMDVMInspectorDragAndDropActionBase::DroppedOnPin(FVector2D ScreenPosition, FVector2D GraphPosition) 9 | { 10 | UEdGraph* Graph = GetHoveredGraph(); 11 | if (Graph != nullptr && VMAssignment.IsAssignmentValid()) 12 | { 13 | if (UEdGraphNode* ResultNode = CreateNodeOnDrop(*Graph, GraphPosition)) 14 | { 15 | if (UEdGraphPin* FromPin = GetHoveredPin()) 16 | { 17 | ResultNode->AutowireNewNode(FromPin); 18 | } 19 | else if (const UEdGraphNode* FromNode = GetHoveredNode()) 20 | { 21 | const UEdGraphSchema_K2* Schema = GetDefault(); 22 | if (UEdGraphPin* FromNodeIn = Schema->FindExecutionPin(*FromNode, EGPD_Input)) 23 | { 24 | ResultNode->AutowireNewNode(FromNodeIn); 25 | } 26 | else if (UEdGraphPin* FromNodeOut = Schema->FindExecutionPin(*FromNode, EGPD_Output)) 27 | { 28 | ResultNode->AutowireNewNode(FromNodeOut); 29 | } 30 | } 31 | } 32 | } 33 | 34 | return FReply::Handled(); 35 | } 36 | 37 | FReply FMDVMInspectorDragAndDropActionBase::DroppedOnNode(FVector2D ScreenPosition, FVector2D GraphPosition) 38 | { 39 | return DroppedOnPin(ScreenPosition, GraphPosition); 40 | } 41 | 42 | FReply FMDVMInspectorDragAndDropActionBase::DroppedOnPanel(const TSharedRef& Panel, FVector2D ScreenPosition, FVector2D GraphPosition, UEdGraph& Graph) 43 | { 44 | HoveredPanelWidget = Panel; 45 | return DroppedOnPin(ScreenPosition, GraphPosition); 46 | } 47 | 48 | bool FMDVMInspectorDragAndDropActionBase::IsSupportedBySchema(const UEdGraphSchema* Schema) const 49 | { 50 | return Schema != nullptr && Schema->IsA(); 51 | } 52 | 53 | void FMDVMInspectorDragAndDropActionBase::HoverTargetChanged() 54 | { 55 | const UEdGraph* Graph = GetHoveredGraph(); 56 | if (Graph != nullptr && IsSupportedBySchema(Graph->GetSchema())) 57 | { 58 | const FSlateBrush* StatusSymbol = FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK")); 59 | SetSimpleFeedbackMessage(StatusSymbol, FLinearColor::White, FText::Format(INVTEXT("Place Node: {0}"), GetNodeTitle())); 60 | } 61 | else 62 | { 63 | const FSlateBrush* StatusSymbol = FAppStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); 64 | SetSimpleFeedbackMessage(StatusSymbol, FLinearColor::White, FText::Format(INVTEXT("Cannot place [{0}] here"), GetNodeTitle())); 65 | } 66 | } 67 | 68 | FText FMDVMInspectorDragAndDropActionBase::GetNodeTitle() const 69 | { 70 | const FText VMClassName = (VMAssignment.ViewModelClass.Get() != nullptr) ? VMAssignment.ViewModelClass.Get()->GetDisplayNameText() : INVTEXT("NULL"); 71 | return FText::Format(INVTEXT("{0} from {1} ({2})"), GetActionTitle(), VMClassName, FText::FromName(VMAssignment.ViewModelName)); 72 | } 73 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropChanged.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropChanged.h" 2 | 3 | #include "EdGraphSchema_K2_Actions.h" 4 | #include "Nodes/MDVMNode_ViewModelChanged.h" 5 | 6 | 7 | TSharedRef FMDVMInspectorDragAndDropChanged::Create(const FMDViewModelAssignmentReference& InVMAssignment) 8 | { 9 | TSharedRef Action = MakeShared(); 10 | Action->VMAssignment = InVMAssignment; 11 | Action->MouseCursor = EMouseCursor::GrabHandClosed; 12 | Action->Construct(); 13 | return Action; 14 | } 15 | 16 | FText FMDVMInspectorDragAndDropChanged::GetActionTitle() const 17 | { 18 | #if WITH_EDITORONLY_DATA 19 | if (VMAssignment.IsAssignmentValid()) 20 | { 21 | return VMAssignment.GetDisplayText(); 22 | } 23 | #endif 24 | 25 | return FMDVMInspectorDragAndDropActionBase::GetActionTitle(); 26 | } 27 | 28 | UEdGraphNode* FMDVMInspectorDragAndDropChanged::CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) 29 | { 30 | return FEdGraphSchemaAction_K2NewNode::CreateNode( 31 | &Graph, 32 | TArrayView(), 33 | GraphPosition, 34 | [](UEdGraph* InParentGraph)->UK2Node* 35 | { 36 | return NewObject(InParentGraph, UMDVMNode_ViewModelChanged::StaticClass()); 37 | }, 38 | [this](UK2Node* NewNode) 39 | { 40 | if (UMDVMNode_ViewModelChanged* ChangedNode = Cast(NewNode)) 41 | { 42 | ChangedNode->InitializeViewModelChangedParams(VMAssignment); 43 | } 44 | }, 45 | EK2NewNodeFlags::SelectNewNode 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropCommand.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropCommand.h" 2 | 3 | #include "Nodes/MDVMNode_CallCommand.h" 4 | 5 | 6 | TSubclassOf FMDVMInspectorDragAndDropCommand::GetNodeClass() const 7 | { 8 | return UMDVMNode_CallCommand::StaticClass(); 9 | } 10 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropEvent.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropEvent.h" 2 | 3 | #include "EdGraphSchema_K2_Actions.h" 4 | #include "Nodes/MDVMNode_ViewModelEvent.h" 5 | 6 | 7 | TSharedRef FMDVMInspectorDragAndDropEvent::Create(TWeakFieldPtr InEventPropertyPtr, const FMDViewModelAssignmentReference& InVMAssignment) 8 | { 9 | TSharedRef Action = MakeShared(); 10 | Action->EventPropertyPtr = InEventPropertyPtr; 11 | Action->VMAssignment = InVMAssignment; 12 | Action->MouseCursor = EMouseCursor::GrabHandClosed; 13 | Action->Construct(); 14 | return Action; 15 | } 16 | 17 | FText FMDVMInspectorDragAndDropEvent::GetActionTitle() const 18 | { 19 | #if WITH_EDITORONLY_DATA 20 | if (const FMulticastDelegateProperty* EventProperty = EventPropertyPtr.Get()) 21 | { 22 | return EventProperty->GetDisplayNameText(); 23 | } 24 | #endif 25 | 26 | return FMDVMInspectorDragAndDropActionBase::GetActionTitle(); 27 | } 28 | 29 | UEdGraphNode* FMDVMInspectorDragAndDropEvent::CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) 30 | { 31 | if (!EventPropertyPtr.IsValid()) 32 | { 33 | return nullptr; 34 | } 35 | 36 | return FEdGraphSchemaAction_K2NewNode::CreateNode( 37 | &Graph, 38 | TArrayView(), 39 | GraphPosition, 40 | [](UEdGraph* InParentGraph)->UK2Node* 41 | { 42 | return NewObject(InParentGraph, UMDVMNode_ViewModelEvent::StaticClass()); 43 | }, 44 | [this](UK2Node* NewNode) 45 | { 46 | if (UMDVMNode_ViewModelEvent* EventNode = Cast(NewNode)) 47 | { 48 | EventNode->InitializeViewModelEventParams(VMAssignment, EventPropertyPtr.Get()->GetFName()); 49 | } 50 | }, 51 | EK2NewNodeFlags::SelectNewNode 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropFieldNotify.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropFieldNotify.h" 2 | 3 | #include "EdGraphSchema_K2_Actions.h" 4 | #include "Nodes/MDVMNode_ViewModelFieldNotify.h" 5 | 6 | 7 | TSharedRef FMDVMInspectorDragAndDropFieldNotify::Create(FFieldVariant InField, const FMDViewModelAssignmentReference& InVMAssignment) 8 | { 9 | TSharedRef Action = MakeShared(); 10 | Action->Field = InField; 11 | Action->VMAssignment = InVMAssignment; 12 | Action->MouseCursor = EMouseCursor::GrabHandClosed; 13 | Action->Construct(); 14 | return Action; 15 | } 16 | 17 | FText FMDVMInspectorDragAndDropFieldNotify::GetActionTitle() const 18 | { 19 | #if WITH_EDITORONLY_DATA 20 | if (const FProperty* Property = Field.Get()) 21 | { 22 | return Property->GetDisplayNameText(); 23 | } 24 | else if (const UFunction* Function = Field.Get()) 25 | { 26 | return Function->GetDisplayNameText(); 27 | } 28 | #endif 29 | 30 | return FMDVMInspectorDragAndDropActionBase::GetActionTitle(); 31 | } 32 | 33 | UEdGraphNode* FMDVMInspectorDragAndDropFieldNotify::CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) 34 | { 35 | if (!Field.IsValid()) 36 | { 37 | return nullptr; 38 | } 39 | 40 | return FEdGraphSchemaAction_K2NewNode::CreateNode( 41 | &Graph, 42 | TArrayView(), 43 | GraphPosition, 44 | [](UEdGraph* InParentGraph)->UK2Node* 45 | { 46 | return NewObject(InParentGraph, UMDVMNode_ViewModelFieldNotify::StaticClass()); 47 | }, 48 | [this](UK2Node* NewNode) 49 | { 50 | if (UMDVMNode_ViewModelFieldNotify* FieldNotifyNode = Cast(NewNode)) 51 | { 52 | FieldNotifyNode->InitializeViewModelFieldNotifyParams(VMAssignment, Field.GetFName()); 53 | } 54 | }, 55 | EK2NewNodeFlags::SelectNewNode 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropFunctionBase.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropFunctionBase.h" 2 | 3 | #include "EdGraphSchema_K2_Actions.h" 4 | #include "Nodes/MDVMNode_CallFunctionBase.h" 5 | 6 | FText FMDVMInspectorDragAndDropFunctionBase::GetActionTitle() const 7 | { 8 | #if WITH_EDITORONLY_DATA 9 | if (const UFunction* Func = FunctionPtr.Get()) 10 | { 11 | return Func->GetDisplayNameText(); 12 | } 13 | #endif 14 | 15 | return FMDVMInspectorDragAndDropActionBase::GetActionTitle(); 16 | } 17 | 18 | UEdGraphNode* FMDVMInspectorDragAndDropFunctionBase::CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) 19 | { 20 | if (!FunctionPtr.IsValid()) 21 | { 22 | return nullptr; 23 | } 24 | 25 | return FEdGraphSchemaAction_K2NewNode::CreateNode( 26 | &Graph, 27 | TArrayView(), 28 | GraphPosition, 29 | [NodeClass = GetNodeClass()](UEdGraph* InParentGraph)->UK2Node* 30 | { 31 | return NewObject(InParentGraph, NodeClass); 32 | }, 33 | [this](UK2Node* NewNode) 34 | { 35 | if (UMDVMNode_CallFunctionBase* FuncNode = Cast(NewNode)) 36 | { 37 | FuncNode->InitializeViewModelFunctionParams(VMAssignment, FunctionPtr.Get()); 38 | } 39 | }, 40 | EK2NewNodeFlags::SelectNewNode 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropGetter.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropGetter.h" 2 | 3 | #include "Nodes/MDVMNode_CallGetter.h" 4 | 5 | 6 | TSubclassOf FMDVMInspectorDragAndDropGetter::GetNodeClass() const 7 | { 8 | return UMDVMNode_CallGetter::StaticClass(); 9 | } 10 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropHelper.h" 2 | 3 | #include "Nodes/MDVMNode_CallHelper.h" 4 | 5 | 6 | TSubclassOf FMDVMInspectorDragAndDropHelper::GetNodeClass() const 7 | { 8 | return UMDVMNode_CallHelper::StaticClass(); 9 | } 10 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Private/ViewModelTab/MDViewModelEditorCommands.cpp: -------------------------------------------------------------------------------- 1 | #include "ViewModelTab/MDViewModelEditorCommands.h" 2 | 3 | void FMDViewModelEditorCommands::RegisterCommands() 4 | { 5 | FUICommandInfo::MakeCommandInfo( 6 | AsShared(), 7 | Edit, 8 | TEXT("Edit"), 9 | INVTEXT("Edit Assignment"), 10 | INVTEXT("Opens the view model assignment dialog to edit the selected assignment."), 11 | FSlateIcon(FAppStyle::GetAppStyleSetName(), TEXT("Icons.Edit")), 12 | EUserInterfaceActionType::Button, 13 | FInputChord() 14 | ); 15 | 16 | FUICommandInfo::MakeCommandInfo( 17 | AsShared(), 18 | GoToDefinition, 19 | TEXT("GoToDefinition"), 20 | INVTEXT("Go To Definition"), 21 | INVTEXT("Open the C++ file or Blueprint where this item is defined."), 22 | FSlateIcon(FAppStyle::GetAppStyleSetName(), TEXT("Icons.ArrowRight")), 23 | EUserInterfaceActionType::Button, 24 | FInputChord(EModifierKey::Alt, EKeys::G) 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/Customizations/MDViewModelAssignmentComponentCustomization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IDetailCustomization.h" 4 | #include "Input/Reply.h" 5 | 6 | struct FMDViewModelAssignment; 7 | struct FMDViewModelAssignmentData; 8 | class UMDViewModelAssignmentComponent; 9 | 10 | /** 11 | * Customization for UMDViewModelAssignmentComponent 12 | */ 13 | class FMDViewModelAssignmentComponentCustomization : public IDetailCustomization 14 | { 15 | public: 16 | static TSharedRef MakeInstance() 17 | { 18 | return MakeShared(); 19 | } 20 | 21 | virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; 22 | 23 | virtual void CustomizeDetails(const TSharedPtr& DetailBuilder) override 24 | { 25 | CachedDetailBuilder = DetailBuilder; 26 | CustomizeDetails(*DetailBuilder); 27 | } 28 | 29 | private: 30 | void HideDefaultCategories(); 31 | void TryAddViewModelEditorButton(); 32 | void AddViewModelDetails(); 33 | 34 | FReply OpenViewModelEditorTab() const; 35 | 36 | UMDViewModelAssignmentComponent* GetComponent() const; 37 | 38 | void RequestRefresh(); 39 | 40 | TWeakPtr CachedDetailBuilder; 41 | }; 42 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/Customizations/MDViewModelAssignmentEditorObjectCustomization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayTagContainer.h" 4 | #include "IDetailCustomization.h" 5 | #include "Input/Reply.h" 6 | #include "Layout/Visibility.h" 7 | 8 | 9 | class UMDViewModelAssignmentEditorObject; 10 | class SWidget; 11 | class SMDViewModelAssignmentDialog; 12 | 13 | /** 14 | * Customization for UMDViewModelAssignmentEditorObject 15 | */ 16 | class MDVIEWMODELEDITOR_API FMDViewModelAssignmentEditorObjectCustomization : public IDetailCustomization 17 | { 18 | public: 19 | static TSharedRef MakeInstance(TSharedRef Dialog) 20 | { 21 | return MakeShared(Dialog); 22 | } 23 | 24 | FMDViewModelAssignmentEditorObjectCustomization(TSharedRef InDialog); 25 | 26 | virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; 27 | 28 | virtual void CustomizeDetails(const TSharedPtr& DetailBuilder) override 29 | { 30 | CachedDetailBuilder = DetailBuilder; 31 | CustomizeDetails(*DetailBuilder); 32 | } 33 | 34 | private: 35 | FText GetSelectedProviderName() const; 36 | 37 | FText GetSelectedProviderToolTip() const; 38 | 39 | TSharedRef OnGetProviderMenuContent() const; 40 | 41 | void OnProviderSelected(FGameplayTag Tag) const; 42 | 43 | void OnViewModelClassPicked(UClass* ViewModelClass) const; 44 | 45 | UClass* GetCurrentViewModelClass() const; 46 | 47 | FReply OnClassPickerButtonClicked() const; 48 | 49 | FText GetSelectedClassText() const; 50 | 51 | FText GetSelectedClassToolTipText() const; 52 | 53 | void OnConfigPropertyChanged(const FPropertyChangedEvent& Event) const; 54 | 55 | void RefreshDetails() const; 56 | 57 | void OnProviderPropertyChanged() const; 58 | void OnViewModelPropertyChanged() const; 59 | 60 | void OnAssignmentUpdated() const; 61 | 62 | EVisibility GetViewModelNameVisibility() const; 63 | EVisibility GetViewModelTagVisibility() const; 64 | 65 | TWeakPtr CachedDetailBuilder; 66 | TWeakObjectPtr EditorObjectPtr; 67 | TSharedRef Dialog; 68 | }; -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/Customizations/MDViewModelAssignmentReferenceCustomization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IPropertyTypeCustomization.h" 4 | #include "Input/Reply.h" 5 | #include "SGraphPin.h" 6 | #include "Util/MDViewModelAssignment.h" 7 | 8 | class SWidget; 9 | struct FMDViewModelAssignmentReference; 10 | 11 | /** 12 | * Customizes FMDViewModelAssignmentReference properties to display a selector for the viewmodel 13 | */ 14 | class FMDViewModelAssignmentReferenceCustomization : public IPropertyTypeCustomization 15 | { 16 | public: 17 | static TSharedRef MakeInstance(); 18 | 19 | virtual void CustomizeHeader(TSharedRef PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils) override; 20 | virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; 21 | 22 | protected: 23 | FMDViewModelAssignmentReference* GetAssignmentReference() const; 24 | UClass* GetBoundObjectClass() const; 25 | 26 | TSharedRef MakeAssignmentMenu(); 27 | void SetSelectedAssignment(FMDViewModelAssignment Assignment) const; 28 | 29 | FText GetSelectedAssignmentText() const; 30 | 31 | TSharedPtr StructHandle; 32 | TSharedPtr ClassHandle; 33 | }; 34 | 35 | /** 36 | * Customizes FMDViewModelAssignmentReference pins to display a selector for the viewmodel 37 | */ 38 | class SMDViewModelAssignmentReferenceGraphPin : public SGraphPin 39 | { 40 | public: 41 | using SGraphPin::Construct; 42 | 43 | virtual TSharedRef GetDefaultValueWidget() override; 44 | virtual void Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime ) override; 45 | 46 | private: 47 | void GetWidgetViewModelAssignments(TMap& OutViewModelAssignments) const; 48 | const UEdGraphPin* GetWidgetPin() const; 49 | const UEdGraphPin* GetViewModelPin() const; 50 | 51 | UClass* GetConnectedObjectClass() const; 52 | TSubclassOf GetConnectedViewModelClass() const; 53 | 54 | TSharedRef MakeAssignmentMenu(); 55 | void SetSelectedAssignment(FMDViewModelAssignment Assignment) const; 56 | 57 | FMDViewModelAssignmentReference GetSelectedAssignment() const; 58 | FText GetSelectedAssignmentText() const; 59 | 60 | void ValidateDefaultValue() const; 61 | }; 62 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/MDViewModelEditorModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Templates/SubclassOf.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | class SMDVMConfigEditor; 7 | class FBlueprintEditor; 8 | class FLayoutExtender; 9 | class FMDViewModelGraphPanelPinFactory; 10 | class FWidgetBlueprintApplicationMode; 11 | class FWorkflowAllowedTabSet; 12 | class UBlueprint; 13 | class UMDViewModelBase; 14 | 15 | class FMDViewModelEditorModule : public IModuleInterface 16 | { 17 | public: 18 | virtual void StartupModule() override; 19 | virtual void ShutdownModule() override; 20 | 21 | void UnregisterConfigEditor(); 22 | 23 | private: 24 | void HandleRegisterBlueprintEditorTab(const FWidgetBlueprintApplicationMode& InApplicationMode, FWorkflowAllowedTabSet& TabFactories); 25 | 26 | void HandleActivateMode(FWidgetBlueprintApplicationMode& InApplicationMode); 27 | 28 | void HandleDeactivateMode(FWidgetBlueprintApplicationMode& InApplicationMode); 29 | 30 | void RegisterBlueprintEditorLayout(FLayoutExtender& Extender); 31 | void RegisterBlueprintEditorTab(FWorkflowAllowedTabSet& TabFactories, FName InModeName, TSharedPtr BlueprintEditor); 32 | void RegisterBlueprintEditorDrawer(UObject* Asset); 33 | 34 | void RegisterConfigEditor(); 35 | 36 | TSharedPtr ViewModelGraphPanelPinFactory; 37 | TSharedPtr ViewModelConfigEditor; 38 | }; 39 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/Util/MDVMEditorUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "UObject/NameTypes.h" 4 | 5 | class UMDViewModelBase; 6 | 7 | namespace MDVMEditorUtils 8 | { 9 | MDVIEWMODELEDITOR_API void SaveViewModelConfig(UMDViewModelBase* ViewModelCDO); 10 | }; 11 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/Util/MDViewModelClassFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ClassViewerFilter.h" 4 | #include "ViewModelProviders/MDViewModelProviderBase.h" 5 | 6 | class UMDViewModelProviderBase; 7 | 8 | class MDVIEWMODELEDITOR_API FMDViewModelClassFilter : public IClassViewerFilter 9 | { 10 | public: 11 | explicit FMDViewModelClassFilter(UMDViewModelProviderBase* Provider); 12 | explicit FMDViewModelClassFilter(bool bAllowAbstract); 13 | 14 | virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< class FClassViewerFilterFuncs > InFilterFuncs) override; 15 | virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const class IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< class FClassViewerFilterFuncs > InFilterFuncs) override; 16 | 17 | private: 18 | bool bAllowAbstract = false; 19 | TOptional> ProviderSupportedViewModelClasses; 20 | }; 21 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMDragAndDropWrapperButton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Widgets/Input/SButton.h" 4 | 5 | class FMDViewModelDebugLineItemBase; 6 | class FMDViewModelFunctionDebugLineItem; 7 | class FMDVMInspectorDragAndDropActionBase; 8 | 9 | class SMDVMDragAndDropWrapperButton : public SButton 10 | { 11 | inline static const FButtonStyle DefaultButtonStyle = []() 12 | { 13 | FButtonStyle ButtonStyle; 14 | ButtonStyle.Normal = FSlateBrush(FSlateNoResource()); 15 | ButtonStyle.Pressed = FSlateBrush(FSlateNoResource()); 16 | ButtonStyle.Hovered = FSlateBrush(FSlateNoResource()); 17 | ButtonStyle.Disabled = FSlateBrush(FSlateNoResource()); 18 | ButtonStyle.NormalPadding = FMargin(0); 19 | ButtonStyle.PressedPadding = FMargin(0); 20 | return ButtonStyle; 21 | }(); 22 | 23 | public: 24 | DECLARE_DELEGATE_RetVal(TSharedRef, FOnGetDragAndDropAction); 25 | 26 | SLATE_BEGIN_ARGS(SMDVMDragAndDropWrapperButton) 27 | : _bCanDrag(false) 28 | , _ButtonArguments(SButton::FArguments().ContentPadding(0).ButtonStyle(&DefaultButtonStyle)) 29 | {} 30 | SLATE_DEFAULT_SLOT(FArguments, Content) 31 | SLATE_ATTRIBUTE(bool, bCanDrag) 32 | SLATE_EVENT(FOnGetDragAndDropAction, OnGetDragAndDropAction) 33 | SLATE_ARGUMENT(SButton::FArguments, ButtonArguments) 34 | SLATE_END_ARGS() 35 | 36 | void Construct(const FArguments& InArgs); 37 | 38 | virtual TOptional GetCursor() const override; 39 | 40 | virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 41 | 42 | virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override; 43 | 44 | private: 45 | bool CanDrag() const; 46 | 47 | TAttribute bCanDrag; 48 | FOnGetDragAndDropAction OnGetDragAndDropAction; 49 | }; 50 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropActionBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GraphEditorDragDropAction.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | 6 | 7 | class FMDVMInspectorDragAndDropActionBase : public FGraphEditorDragDropAction 8 | { 9 | public: 10 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropActionBase, FGraphEditorDragDropAction) 11 | 12 | virtual FReply DroppedOnPin(FVector2D ScreenPosition, FVector2D GraphPosition) override; 13 | virtual FReply DroppedOnNode(FVector2D ScreenPosition, FVector2D GraphPosition) override; 14 | virtual FReply DroppedOnPanel( const TSharedRef< SWidget >& Panel, FVector2D ScreenPosition, FVector2D GraphPosition, UEdGraph& Graph) override; 15 | 16 | virtual bool IsSupportedBySchema(const UEdGraphSchema* Schema) const override; 17 | virtual void HoverTargetChanged() override; 18 | 19 | virtual FText GetNodeTitle() const; 20 | virtual FText GetActionTitle() const { return INVTEXT("INVALID"); } 21 | 22 | virtual UEdGraphNode* CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) { return nullptr; } 23 | 24 | protected: 25 | FMDViewModelAssignmentReference VMAssignment; 26 | TWeakPtr HoveredPanelWidget; 27 | }; 28 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropChanged.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropActionBase.h" 4 | #include "UObject/WeakFieldPtr.h" 5 | 6 | class UMDVMNode_ViewModelChanged; 7 | 8 | class FMDVMInspectorDragAndDropChanged : public FMDVMInspectorDragAndDropActionBase 9 | { 10 | public: 11 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropChanged, FMDVMInspectorDragAndDropActionBase) 12 | 13 | static TSharedRef Create(const FMDViewModelAssignmentReference& InVMAssignment); 14 | 15 | virtual FText GetActionTitle() const override; 16 | 17 | virtual UEdGraphNode* CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) override; 18 | }; 19 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropCommand.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropFunctionBase.h" 4 | 5 | 6 | class FMDVMInspectorDragAndDropCommand : public FMDVMInspectorDragAndDropFunctionBase 7 | { 8 | public: 9 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropCommand, FMDVMInspectorDragAndDropFunctionBase) 10 | 11 | protected: 12 | virtual TSubclassOf GetNodeClass() const override; 13 | }; 14 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropEvent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropActionBase.h" 4 | #include "UObject/WeakFieldPtr.h" 5 | 6 | 7 | class UMDVMNode_ViewModelEvent; 8 | 9 | class FMDVMInspectorDragAndDropEvent : public FMDVMInspectorDragAndDropActionBase 10 | { 11 | public: 12 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropEvent, FMDVMInspectorDragAndDropActionBase) 13 | 14 | static TSharedRef Create(TWeakFieldPtr InEventPropertyPtr, const FMDViewModelAssignmentReference& InVMAssignment); 15 | 16 | virtual FText GetActionTitle() const override; 17 | 18 | virtual UEdGraphNode* CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) override; 19 | 20 | private: 21 | TWeakFieldPtr EventPropertyPtr; 22 | }; 23 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropFieldNotify.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropActionBase.h" 4 | 5 | 6 | class UMDVMNode_ViewModelFieldNotify; 7 | 8 | class FMDVMInspectorDragAndDropFieldNotify : public FMDVMInspectorDragAndDropActionBase 9 | { 10 | public: 11 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropFieldNotify, FMDVMInspectorDragAndDropActionBase) 12 | 13 | static TSharedRef Create(FFieldVariant InField, const FMDViewModelAssignmentReference& InVMAssignment); 14 | 15 | virtual FText GetActionTitle() const override; 16 | 17 | virtual UEdGraphNode* CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) override; 18 | 19 | private: 20 | FFieldVariant Field; 21 | }; 22 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropFunctionBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropActionBase.h" 4 | 5 | 6 | class UMDVMNode_CallFunctionBase; 7 | 8 | class MDVIEWMODELEDITOR_API FMDVMInspectorDragAndDropFunctionBase : public FMDVMInspectorDragAndDropActionBase 9 | { 10 | public: 11 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropFunctionBase, FMDVMInspectorDragAndDropActionBase) 12 | 13 | virtual FText GetActionTitle() const override; 14 | 15 | virtual UEdGraphNode* CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) override; 16 | 17 | template 18 | friend TSharedRef CreateMDVMDragAndDrop(TWeakObjectPtr InFunctionPtr, const FMDViewModelAssignmentReference& InVMAssignment); 19 | 20 | protected: 21 | virtual TSubclassOf GetNodeClass() const = 0; 22 | 23 | TWeakObjectPtr FunctionPtr; 24 | }; 25 | 26 | template 27 | TSharedRef CreateMDVMDragAndDrop(TWeakObjectPtr InFunctionPtr, const FMDViewModelAssignmentReference& InVMAssignment) 28 | { 29 | static_assert(TIsDerivedFrom::Value, "T must derive from FMDVMInspectorDragAndDropFunctionBase"); 30 | 31 | TSharedRef Action = MakeShared(); 32 | Action->FunctionPtr = InFunctionPtr; 33 | Action->VMAssignment = InVMAssignment; 34 | Action->MouseCursor = EMouseCursor::GrabHandClosed; 35 | Action->Construct(); 36 | return Action; 37 | } 38 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropGetter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropFunctionBase.h" 4 | 5 | 6 | class FMDVMInspectorDragAndDropGetter : public FMDVMInspectorDragAndDropFunctionBase 7 | { 8 | public: 9 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropGetter, FMDVMInspectorDragAndDropFunctionBase) 10 | 11 | protected: 12 | virtual TSubclassOf GetNodeClass() const override; 13 | }; 14 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMInspectorDragAndDropFunctionBase.h" 4 | 5 | 6 | class FMDVMInspectorDragAndDropHelper : public FMDVMInspectorDragAndDropFunctionBase 7 | { 8 | public: 9 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropHelper, FMDVMInspectorDragAndDropFunctionBase) 10 | 11 | protected: 12 | virtual TSubclassOf GetNodeClass() const override; 13 | }; 14 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/DragAndDrop/MDVMInspectorDragAndDropProperty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MDVMInspectorDragAndDropActionBase.h" 3 | #include "UObject/WeakFieldPtr.h" 4 | 5 | struct FMDVMCachedViewModelPropertyNodeParams 6 | { 7 | FMDViewModelAssignmentReference VMAssignment; 8 | TWeakFieldPtr PropertyPtr; 9 | FVector2D GraphPosition = FVector2D(0); 10 | TWeakObjectPtr Graph; 11 | TWeakObjectPtr Node; 12 | FEdGraphPinReference Pin; 13 | }; 14 | 15 | class FMDVMInspectorDragAndDropProperty : public FMDVMInspectorDragAndDropActionBase 16 | { 17 | public: 18 | DRAG_DROP_OPERATOR_TYPE(FMDVMInspectorDragAndDropProperty, FMDVMInspectorDragAndDropActionBase) 19 | 20 | static TSharedRef Create(TWeakFieldPtr InPropertyPtr, const FMDViewModelAssignmentReference& InVMAssignment); 21 | 22 | static void CreateGetter(FMDVMCachedViewModelPropertyNodeParams Params); 23 | static void CreateSetter(FMDVMCachedViewModelPropertyNodeParams Params); 24 | static void FinalizeNode(UEdGraphNode* NewNode, const FMDVMCachedViewModelPropertyNodeParams& Params); 25 | 26 | virtual FReply DroppedOnPin(FVector2D ScreenPosition, FVector2D GraphPosition) override; 27 | 28 | virtual UEdGraphNode* CreateNodeOnDrop(UEdGraph& Graph, const FVector2D& GraphPosition) override; 29 | 30 | virtual FText GetActionTitle() const override; 31 | 32 | void SetAltDrag(bool InIsAltDrag) { bAltDrag = InIsAltDrag; } 33 | void SetCtrlDrag(bool InIsCtrlDrag) { bControlDrag = InIsCtrlDrag; } 34 | void SetCanSet(bool InCanSet); 35 | 36 | protected: 37 | TWeakFieldPtr PropertyPtr; 38 | 39 | private: 40 | TOptional bIsGetter; 41 | bool bCanSet = true; 42 | bool bControlDrag = false; 43 | bool bAltDrag = false; 44 | }; 45 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/MDViewModelChangedDebugLineItem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelDebugLineItemBase.h" 4 | 5 | class FMDViewModelChangedDebugLineItem : public FMDViewModelDebugLineItemBase 6 | { 7 | public: 8 | FMDViewModelChangedDebugLineItem(const TWeakPtr& BlueprintEditorPtr, const FMDViewModelAssignmentReference& Assignment); 9 | 10 | virtual bool Compare(const FDebugLineItem* BaseOther) const override; 11 | 12 | virtual bool CanHaveChildren() override { return false; } 13 | 14 | virtual bool HasChildren() const override { return false; } 15 | 16 | virtual TSharedRef GetNameIcon() override; 17 | 18 | virtual TSharedRef GenerateValueWidget(TSharedPtr InSearchString) override; 19 | 20 | virtual bool CanDrag() const override; 21 | 22 | virtual TSharedRef CreateDragAndDropAction() const override; 23 | 24 | protected: 25 | virtual FDebugLineItem* Duplicate() const override; 26 | 27 | virtual bool CanCreateNodes() const override; 28 | 29 | virtual FName GetTypeName() const override { return TEXT("Changed"); } 30 | 31 | private: 32 | FReply OnAddOrViewBoundVMChangedFunctionClicked() const; 33 | int32 GetAddOrViewBoundVMChangedFunctionIndex() const; 34 | }; 35 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/MDViewModelDebugLineItemBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Debugging/SKismetDebugTreeView.h" 4 | #include "Runtime/Launch/Resources/Version.h" 5 | #include "Templates/SubclassOf.h" 6 | #include "Util/MDViewModelAssignmentReference.h" 7 | 8 | class FBlueprintEditor; 9 | class FMDVMInspectorDragAndDropActionBase; 10 | class UMDViewModelBase; 11 | class UBlueprint; 12 | 13 | class FMDViewModelDebugLineItemBase : public FDebugLineItem 14 | { 15 | public: 16 | FMDViewModelDebugLineItemBase(const TWeakPtr& BlueprintEditorPtr, const FMDViewModelAssignmentReference& Assignment); 17 | 18 | void UpdateViewModel(const FMDViewModelAssignmentReference& InAssignment); 19 | void UpdateDebugging(bool InIsDebugging, TWeakObjectPtr InDebugViewModel); 20 | 21 | void SetDisplayText(const FText& Name, const FText& Desc); 22 | 23 | virtual bool Compare(const FDebugLineItem* BaseOther) const override 24 | { 25 | const FMDViewModelDebugLineItemBase* Other = static_cast(BaseOther); 26 | return GetTypeName() == Other->GetTypeName() && Assignment == Other->Assignment; 27 | } 28 | 29 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 3 30 | virtual uint32 GetHash() const override 31 | #else 32 | virtual uint32 GetHash() override 33 | #endif 34 | { 35 | return HashCombine(GetTypeHash(Assignment), GetTypeHash(GetTypeName())); 36 | } 37 | 38 | virtual TSharedRef CreateDragAndDropAction() const; 39 | 40 | virtual bool CanDrag() const; 41 | 42 | const FMDViewModelAssignmentReference& GetViewModelAssignmentReference() const { return Assignment; } 43 | 44 | protected: 45 | virtual void UpdateCachedChildren() const {}; 46 | 47 | virtual bool HasChildren() const override; 48 | 49 | virtual FName GetTypeName() const { return TEXT("Base"); } 50 | 51 | virtual void ExtendContextMenu(FMenuBuilder& MenuBuilder, bool bInDebuggerTab) override; 52 | 53 | virtual void GatherChildrenBase(TArray& OutChildren, const FString& InSearchString, bool bRespectSearch) override; 54 | 55 | virtual TSharedRef GenerateNameWidget(TSharedPtr InSearchString) override; 56 | 57 | virtual FText GetDisplayName() const override; 58 | 59 | virtual FText GetDescription() const override; 60 | 61 | virtual void OnDebuggingChanged() {} 62 | 63 | virtual bool CanCreateNodes() const; 64 | 65 | virtual FString GenerateSearchString() const { return {}; } 66 | 67 | virtual FFieldVariant GetFieldForDefinitionNavigation() const { return {}; } 68 | 69 | EVisibility GetIsConfigFieldVisibility() const; 70 | 71 | void OnFindReferencesClicked() const; 72 | 73 | void NavigateToDefinitionField() const; 74 | 75 | FText GeneratePropertyDisplayValue(const FProperty* Property, void* ValuePtr) const; 76 | 77 | mutable TOptional> CachedChildren; 78 | 79 | mutable TMap CachedPropertyItems; 80 | 81 | TWeakPtr BlueprintEditorPtr; 82 | FMDViewModelAssignmentReference Assignment; 83 | 84 | FText DisplayName; 85 | FText Description; 86 | 87 | TWeakObjectPtr BlueprintPtr; 88 | 89 | bool bIsDebugging = false; 90 | TWeakObjectPtr DebugViewModel; 91 | }; 92 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/MDViewModelEventDebugLineItem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelFunctionDebugLineItem.h" 4 | #include "UObject/WeakFieldPtr.h" 5 | 6 | class FMDViewModelEventDebugLineItem : public FMDViewModelFunctionDebugLineItem 7 | { 8 | public: 9 | FMDViewModelEventDebugLineItem(const TWeakPtr& BlueprintEditorPtr, const FMDViewModelAssignmentReference& Assignment, const FMulticastDelegateProperty* Prop); 10 | 11 | virtual bool Compare(const FDebugLineItem* BaseOther) const override 12 | { 13 | const FMDViewModelEventDebugLineItem* Other = static_cast(BaseOther); 14 | return FMDViewModelFunctionDebugLineItem::Compare(BaseOther) && WeakDelegateProp.Get() == Other->WeakDelegateProp.Get(); 15 | } 16 | 17 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 3 18 | virtual uint32 GetHash() const override 19 | #else 20 | virtual uint32 GetHash() override 21 | #endif 22 | { 23 | return HashCombine(GetTypeHash(WeakDelegateProp), FMDViewModelFunctionDebugLineItem::GetHash()); 24 | } 25 | 26 | virtual TSharedRef GenerateValueWidget(TSharedPtr InSearchString) override; 27 | 28 | protected: 29 | virtual FDebugLineItem* Duplicate() const override; 30 | 31 | virtual bool CanCreateNodes() const override; 32 | 33 | virtual FString GenerateSearchString() const override; 34 | 35 | virtual FFieldVariant GetFieldForDefinitionNavigation() const override; 36 | 37 | virtual FName GetTypeName() const override { return TEXT("Event"); } 38 | 39 | virtual bool CanDisplayReturnValue() const override { return false; } 40 | 41 | virtual bool CanDrag() const override; 42 | 43 | virtual TSharedRef CreateDragAndDropAction() const override; 44 | 45 | private: 46 | FReply OnAddOrViewBoundFunctionClicked() const; 47 | int32 GetAddOrViewBoundFunctionIndex() const; 48 | 49 | TWeakFieldPtr WeakDelegateProp; 50 | }; 51 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/MDViewModelFieldDebugLineItem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelDebugLineItemBase.h" 4 | #include "UObject/WeakFieldPtr.h" 5 | 6 | class FMDViewModelFieldDebugLineItem : public FMDViewModelDebugLineItemBase 7 | { 8 | public: 9 | FMDViewModelFieldDebugLineItem(const TWeakPtr& BlueprintEditorPtr, const FMDViewModelAssignmentReference& Assignment, const FProperty* Property, void* InValuePtr, bool bIsFieldNotify = false); 10 | 11 | virtual bool Compare(const FDebugLineItem* BaseOther) const override 12 | { 13 | const FMDViewModelFieldDebugLineItem* Other = static_cast(BaseOther); 14 | return FMDViewModelDebugLineItemBase::Compare(BaseOther) && PropertyPtr.Get() == Other->PropertyPtr.Get() && ValuePtr == Other->ValuePtr; 15 | } 16 | 17 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 3 18 | virtual uint32 GetHash() const override 19 | #else 20 | virtual uint32 GetHash() override 21 | #endif 22 | { 23 | return HashCombine(FMDViewModelDebugLineItemBase::GetHash(), HashCombine(GetTypeHash(PropertyPtr), GetTypeHash(ValuePtr))); 24 | } 25 | 26 | virtual bool CanHaveChildren() override { return true; } 27 | 28 | virtual TSharedRef GetNameIcon() override; 29 | 30 | virtual TSharedRef GenerateValueWidget(TSharedPtr InSearchString) override; 31 | 32 | virtual TSharedRef CreateDragAndDropAction() const override; 33 | 34 | TSharedRef CreateBindingDragAndDropAction() const; 35 | 36 | FText GetDisplayValue() const; 37 | 38 | const FProperty* GetProperty() const { return PropertyPtr.Get(); } 39 | void* GetValuePtr() const { return ValuePtr; } 40 | 41 | void UpdateValuePtr(void* InValuePtr); 42 | 43 | virtual bool CanDrag() const override; 44 | 45 | protected: 46 | virtual void UpdateCachedChildren() const override; 47 | 48 | virtual FDebugLineItem* Duplicate() const override; 49 | 50 | virtual bool CanCreateNodes() const override; 51 | 52 | virtual FString GenerateSearchString() const override; 53 | 54 | virtual FFieldVariant GetFieldForDefinitionNavigation() const override; 55 | 56 | virtual FName GetTypeName() const override { return TEXT("Field"); } 57 | 58 | private: 59 | int32 GetShouldDisplayFieldNotifyIndex() const; 60 | FReply OnAddOrViewBoundFunctionClicked() const; 61 | bool CanAddBoundFunction() const; 62 | int32 GetAddOrViewBoundFunctionIndex() const; 63 | 64 | TWeakFieldPtr PropertyPtr; 65 | void* ValuePtr = nullptr; 66 | 67 | bool bIsFieldNotify = false; 68 | }; 69 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/MDViewModelFieldInspector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GraphEditorDragDropAction.h" 4 | #include "MDViewModelFunctionDebugLineItem.h" 5 | #include "SPinValueInspector.h" 6 | #include "Templates/SubclassOf.h" 7 | #include "UObject/UnrealType.h" 8 | #include "UObject/WeakFieldPtr.h" 9 | #include "Util/MDViewModelAssignmentReference.h" 10 | 11 | class FBlueprintEditor; 12 | class FMDViewModelChangedDebugLineItem; 13 | class FMDViewModelEventDebugLineItem; 14 | class FMDViewModelFunctionDebugLineItem; 15 | class FMDViewModelFieldDebugLineItem; 16 | class UMDVMNode_ViewModelEvent; 17 | class UMDViewModelBase; 18 | 19 | enum class EMDViewModelFieldInspectorType : uint8 20 | { 21 | None, 22 | Properties, 23 | Events, 24 | Commands, 25 | Helpers 26 | }; 27 | 28 | /** 29 | * Widget that displays all the exposed properties of a viewmodel and their values when debugging 30 | */ 31 | class MDVIEWMODELEDITOR_API SMDViewModelFieldInspector : public SPinValueInspector 32 | { 33 | public: 34 | SLATE_BEGIN_ARGS(SMDViewModelFieldInspector) 35 | { 36 | } 37 | SLATE_ARGUMENT(EMDViewModelFieldInspectorType, InspectorType) 38 | SLATE_END_ARGS() 39 | 40 | void Construct(const FArguments& InArgs, const TSharedPtr& BlueprintEditor); 41 | 42 | void SetReferences(const FMDViewModelAssignmentReference& InAssignment, bool InIsDebugging, UMDViewModelBase* InDebugViewModel); 43 | 44 | void RefreshList(); 45 | 46 | protected: 47 | virtual void PopulateTreeView() override; 48 | virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; 49 | 50 | // We can't support search since that requires inheriting from FLineItemWithChildren but that's private 51 | virtual EVisibility GetSearchFilterVisibility() const override { return EVisibility::Collapsed; } 52 | 53 | private: 54 | void GetDragAndDropCreatorForFunction(const UFunction& Func, bool bIsFieldNotify, FMDVMDragAndDropCreatorFunc& DragAndDropCreatorFunc) const; 55 | 56 | TMap> PropertyTreeItems; 57 | TMap> FunctionTreeItems; 58 | TMap> EventTreeItems; 59 | TSharedPtr VMChangedItem; 60 | 61 | FMDViewModelAssignmentReference Assignment; 62 | TWeakObjectPtr DebugViewModel; 63 | bool bIsDebugging = false; 64 | TWeakPtr BlueprintEditorPtr; 65 | 66 | EMDViewModelFieldInspectorType InspectorType = EMDViewModelFieldInspectorType::None; 67 | }; 68 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/FieldInspector/MDViewModelFunctionDebugLineItem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "MDViewModelDebugLineItemBase.h" 3 | 4 | class FMDVMInspectorDragAndDropCommand; 5 | 6 | using FMDVMDragAndDropCreatorFunc = TDelegate(TWeakObjectPtr, const FMDViewModelAssignmentReference&)>; 7 | 8 | class FMDViewModelFunctionDebugLineItem : public FMDViewModelDebugLineItemBase 9 | { 10 | public: 11 | FMDViewModelFunctionDebugLineItem(const TWeakPtr& BlueprintEditorPtr, const FMDViewModelAssignmentReference& Assignment, const UFunction* Function, const FMDVMDragAndDropCreatorFunc& DragAndDropCreator = {}, bool bIsFieldNotify = false); 12 | virtual ~FMDViewModelFunctionDebugLineItem() override; 13 | 14 | virtual bool Compare(const FDebugLineItem* BaseOther) const override 15 | { 16 | const FMDViewModelFunctionDebugLineItem* Other = static_cast(BaseOther); 17 | return FMDViewModelDebugLineItemBase::Compare(BaseOther) && FunctionPtr == Other->FunctionPtr; 18 | } 19 | 20 | #if ENGINE_MAJOR_VERSION > 5 || ENGINE_MINOR_VERSION >= 3 21 | virtual uint32 GetHash() const override 22 | #else 23 | virtual uint32 GetHash() override 24 | #endif 25 | { 26 | return HashCombine(GetTypeHash(FunctionPtr), FMDViewModelDebugLineItemBase::GetHash()); 27 | } 28 | 29 | virtual bool CanHaveChildren() override { return true; } 30 | 31 | virtual TSharedRef GetNameIcon() override; 32 | 33 | virtual TSharedRef GenerateValueWidget(TSharedPtr InSearchString) override; 34 | 35 | virtual TSharedRef CreateDragAndDropAction() const override; 36 | 37 | TSharedRef CreateBindingDragAndDropAction() const; 38 | 39 | const UFunction* GetFunction() const { return FunctionPtr.Get(); } 40 | 41 | protected: 42 | virtual void UpdateCachedChildren() const override; 43 | 44 | virtual FDebugLineItem* Duplicate() const override; 45 | 46 | virtual bool CanCreateNodes() const override; 47 | 48 | virtual FString GenerateSearchString() const override; 49 | 50 | virtual FFieldVariant GetFieldForDefinitionNavigation() const override; 51 | 52 | virtual FName GetTypeName() const override { return TEXT("Function"); } 53 | 54 | virtual FText GetDisplayValue() const; 55 | 56 | virtual bool CanDisplayReturnValue() const; 57 | 58 | virtual void OnDebuggingChanged() override; 59 | 60 | virtual bool CanDrag() const override; 61 | 62 | private: 63 | int32 GetShouldDisplayFieldNotifyIndex() const; 64 | FReply OnAddOrViewBoundFieldNotifyFunctionClicked() const; 65 | bool CanAddBoundFieldNotifyFunction() const; 66 | int32 GetAddOrViewBoundFieldNotifyFunctionIndex() const; 67 | 68 | void TryUpdateGetterReturnValue() const; 69 | void CleanUpGetterReturnValue() const; 70 | 71 | TWeakObjectPtr FunctionPtr; 72 | FMDVMDragAndDropCreatorFunc DragAndDropCreator; 73 | 74 | bool bIsFieldNotify = false; 75 | mutable void* GetterReturnValuePtr = nullptr; 76 | }; 77 | 78 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelAssignmentDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "UObject/StrongObjectPtr.h" 4 | #include "UObject/WeakInterfacePtr.h" 5 | #include "ViewModelTab/MDViewModelAssignmentEditorObject.h" 6 | #include "Widgets/SCompoundWidget.h" 7 | 8 | class IMDViewModelAssignableInterface; 9 | class UBlueprint; 10 | struct FMDViewModelEditorAssignment; 11 | struct FMDViewModelClassItem; 12 | 13 | enum class EMDVMDialogMode : uint8 14 | { 15 | Add, 16 | Edit, 17 | Duplicate 18 | }; 19 | 20 | /** 21 | * 22 | */ 23 | class MDVIEWMODELEDITOR_API SMDViewModelAssignmentDialog : public SCompoundWidget 24 | { 25 | public: 26 | SLATE_BEGIN_ARGS(SMDViewModelAssignmentDialog) 27 | : _Mode(EMDVMDialogMode::Add) 28 | { 29 | } 30 | 31 | SLATE_ARGUMENT(EMDVMDialogMode, Mode) 32 | SLATE_ARGUMENT(UBlueprint*, Blueprint) 33 | SLATE_ARGUMENT(TSharedPtr, EditorItem) 34 | 35 | SLATE_END_ARGS() 36 | 37 | /** Constructs this widget with InArgs */ 38 | void Construct(const FArguments& InArgs, const TSharedRef& InParentWindow); 39 | 40 | UBlueprint* GetBlueprint() const; 41 | 42 | DECLARE_MULTICAST_DELEGATE_OneParam(FOnAssignmentAdded, const FMDViewModelEditorAssignment&); 43 | FOnAssignmentAdded OnAssignmentAdded; 44 | 45 | static void OpenAssignmentDialog(UBlueprint* Blueprint); 46 | static void OpenEditDialog(UBlueprint* Blueprint, TSharedPtr EditorItem); 47 | static void OpenDuplicateDialog(UBlueprint* Blueprint, TSharedPtr EditorItem); 48 | 49 | static TSharedPtr GetActiveDialog(); 50 | 51 | private: 52 | static void OpenDialog_Internal(UBlueprint* Blueprint, TSharedPtr EditorItem = nullptr, bool bDuplicateItem = false); 53 | static void OnDialogClosed(const TSharedRef& Window); 54 | static TWeakPtr ActiveDialogWindowPtr; 55 | 56 | EVisibility GetAddVisibility() const; 57 | EVisibility GetSaveVisibility() const; 58 | EVisibility GetAssignmentErrorVisibility() const; 59 | 60 | FReply OnAddClicked() const; 61 | FReply OnSaveClicked() const; 62 | 63 | bool DoesAssignmentHaveError() const; 64 | FText GetAssignmentError() const; 65 | 66 | IMDViewModelAssignableInterface* GetExtension(bool bCreateIfNecessary = false) const; 67 | 68 | EMDVMDialogMode Mode = EMDVMDialogMode::Add; 69 | 70 | TSharedPtr EditorItem; 71 | 72 | TSharedPtr ParentWindow; 73 | TStrongObjectPtr EditorObject; 74 | TWeakObjectPtr BlueprintPtr; 75 | TOptional OriginalAssignmentName; 76 | TOptional> OriginalAssignedClass; 77 | }; 78 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelAssignmentEditorObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayTagContainer.h" 4 | #include "InstancedStruct.h" 5 | #include "Templates/SubclassOf.h" 6 | #include "UObject/Object.h" 7 | #include "Util/MDViewModelEditorAssignment.h" 8 | #include "MDViewModelAssignmentEditorObject.generated.h" 9 | 10 | class UMDViewModelBase; 11 | class UBlueprint; 12 | 13 | /** 14 | * Editor-time object used a proxy to display the settings when assigning a view model to a widget 15 | */ 16 | UCLASS(CollapseCategories) 17 | class MDVIEWMODELEDITOR_API UMDViewModelAssignmentEditorObject : public UObject 18 | { 19 | GENERATED_BODY() 20 | 21 | public: 22 | void PopulateFromAssignment(const FMDViewModelEditorAssignment& Assignment, UBlueprint* Blueprint); 23 | 24 | virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; 25 | 26 | FMDViewModelEditorAssignment CreateAssignment() const; 27 | 28 | // How will the viewmodel be provided to this widget? 29 | UPROPERTY(EditAnywhere, Category = "View Model") 30 | FGameplayTag ViewModelProvider; 31 | 32 | // Settings for the specified view model provider 33 | UPROPERTY(EditAnywhere, NoClear, Category = "View Model", meta = (StructTypeConst)) 34 | FInstancedStruct ProviderSettings; 35 | 36 | UPROPERTY(EditAnywhere, Category = "View Model", meta = (InlineEditConditionToggle)) 37 | bool bOverrideName = false; 38 | 39 | // A name to give the selected view model assignment. Must be unique for the selected view model class for this widget. 40 | UPROPERTY(EditAnywhere, Category = "View Model", DisplayName = "View Model Assignment Name", meta = (EditCondition = "bOverrideName")) 41 | FName ViewModelInstanceName = MDViewModelUtils::DefaultViewModelName; 42 | 43 | // A name to give the selected view model assignment. Must be unique for the selected view model class for this widget. 44 | UPROPERTY(EditAnywhere, Category = "View Model", DisplayName = "View Model Assignment Name", meta = (EditCondition = "bOverrideName")) 45 | FGameplayTag ViewModelInstanceTag; 46 | 47 | UPROPERTY(EditAnywhere, Category = "View Model") 48 | TSubclassOf ViewModelClass; 49 | 50 | // Settings for the specified view model class 51 | UPROPERTY(EditAnywhere, NoClear, Category = "View Model", meta = (StructTypeConst)) 52 | FInstancedStruct ViewModelSettings; 53 | 54 | UFUNCTION() 55 | TArray GetRelativePropertyNames() const; 56 | 57 | UPROPERTY(Transient) 58 | TSubclassOf BPSkeletonClass = nullptr; 59 | 60 | TWeakObjectPtr BlueprintPtr; 61 | }; 62 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelDetails.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Styling/SlateBrush.h" 4 | #include "Templates/SubclassOf.h" 5 | #include "Util/MDViewModelAssignmentReference.h" 6 | #include "Widgets/SCompoundWidget.h" 7 | 8 | class FBlueprintEditor; 9 | class UMDViewModelBase; 10 | class SMDViewModelFieldInspector; 11 | 12 | /** 13 | * 14 | */ 15 | class MDVIEWMODELEDITOR_API SMDViewModelDetails : public SCompoundWidget 16 | { 17 | public: 18 | SLATE_BEGIN_ARGS(SMDViewModelDetails) 19 | {} 20 | 21 | SLATE_END_ARGS() 22 | 23 | void Construct(const FArguments& InArgs, const TSharedPtr& BlueprintEditor); 24 | 25 | void UpdateViewModel(const FMDViewModelAssignmentReference& Assignment, bool bIsDebugging, UMDViewModelBase* DebugViewModel); 26 | 27 | private: 28 | TSharedPtr PropertyInspector; 29 | TSharedPtr EventInspector; 30 | TSharedPtr CommandInspector; 31 | TSharedPtr HelperInspector; 32 | }; 33 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "EditorUndoClient.h" 4 | #include "Templates/SubclassOf.h" 5 | #include "Util/MDViewModelAssignmentReference.h" 6 | #include "Widgets/SCompoundWidget.h" 7 | 8 | class FBlueprintEditor; 9 | struct FMDViewModelEditorAssignment; 10 | class SMDViewModelDetails; 11 | class SMDViewModelList; 12 | class UMDViewModelBase; 13 | 14 | /** 15 | * 16 | */ 17 | class MDVIEWMODELEDITOR_API SMDViewModelEditor : public SCompoundWidget, public FSelfRegisteringEditorUndoClient 18 | { 19 | public: 20 | SLATE_BEGIN_ARGS(SMDViewModelEditor) 21 | { 22 | } 23 | 24 | SLATE_END_ARGS() 25 | 26 | virtual ~SMDViewModelEditor() override; 27 | 28 | void Construct(const FArguments& InArgs, const TSharedPtr& BlueprintEditor); 29 | 30 | virtual void PostUndo(bool bSuccess) override; 31 | virtual void PostRedo(bool bSuccess) override; 32 | 33 | virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; 34 | 35 | private: 36 | void OnSetObjectBeingDebugged(UObject* Object); 37 | void OnViewModelSelected(FMDViewModelEditorAssignment* Assignment); 38 | 39 | void OnViewModelChanged(); 40 | void OnBlueprintCompiled(UBlueprint* BP); 41 | 42 | void OnAssetRemoved(const FAssetData& AssetData); 43 | void OnAssetRenamed(const FAssetData& AssetData, const FString& OldName); 44 | 45 | void OnRenameVariable(UBlueprint* Blueprint, UClass* VariableClass, const FName& OldVariableName, const FName& NewVariableName); 46 | 47 | void RefreshEditor(bool bRefreshDetails); 48 | 49 | bool bIsDebugging = false; 50 | 51 | TWeakObjectPtr ObjectBeingDebugged; 52 | FMDViewModelAssignmentReference SelectedAssignment; 53 | 54 | TSharedPtr ViewModelListWidget; 55 | TSharedPtr ViewModelDetailsWidget; 56 | 57 | TWeakObjectPtr EditedBlueprintPtr; 58 | }; 59 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelEditorCommands.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Styling/CoreStyle.h" 4 | #include "Framework/Commands/Commands.h" 5 | 6 | class MDVIEWMODELEDITOR_API FMDViewModelEditorCommands : public TCommands 7 | { 8 | public: 9 | FMDViewModelEditorCommands() 10 | : TCommands(TEXT("MDViewModelEditorCommands"), NSLOCTEXT("MDViewModelEditorCommands", "ViewModelEditorCommands", "View Model Commands"), NAME_None, FCoreStyle::Get().GetStyleSetName()) 11 | {} 12 | 13 | virtual void RegisterCommands() override; 14 | 15 | TSharedPtr Edit; 16 | TSharedPtr GoToDefinition; 17 | }; 18 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Templates/SubclassOf.h" 4 | #include "Widgets/SCompoundWidget.h" 5 | #include "Widgets/Views/SListView.h" 6 | 7 | class FBlueprintEditor; 8 | struct FMDViewModelEditorAssignment; 9 | class FUICommandList; 10 | class IMDViewModelAssignableInterface; 11 | 12 | class SMDViewModelList : public SCompoundWidget 13 | { 14 | public: 15 | DECLARE_DELEGATE_OneParam(FOnViewModelSelected, FMDViewModelEditorAssignment*); 16 | 17 | SLATE_BEGIN_ARGS(SMDViewModelList) 18 | { 19 | } 20 | 21 | SLATE_EVENT(FOnViewModelSelected, OnViewModelSelected) 22 | 23 | SLATE_END_ARGS() 24 | 25 | virtual ~SMDViewModelList() override; 26 | 27 | void Construct(const FArguments& InArgs, const TSharedPtr& InBlueprintEditor); 28 | 29 | void RefreshList(); 30 | 31 | virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override; 32 | 33 | private: 34 | void SetupCommands(); 35 | 36 | void OnItemSelected(TSharedPtr Item, ESelectInfo::Type SelectInfo); 37 | TSharedRef OnGenerateRow(TSharedPtr Item, const TSharedRef& OwningTable); 38 | TSharedPtr OnContextMenuOpening(); 39 | void PopulateAssignments(); 40 | 41 | void OnAssignmentsChanged(UBlueprint* Blueprint); 42 | 43 | void AddViewModelAssignment(); 44 | FReply OnAddViewModel(); 45 | bool CanAddViewModel() const; 46 | void OnAssignmentAdded(const FMDViewModelEditorAssignment& Assignment); 47 | 48 | bool IsSelectedAssignmentValid() const; 49 | bool IsSelectedAssignmentValidAndNotPIE() const; 50 | bool IsNotPIE() const; 51 | 52 | void EditSelectedAssignment(); 53 | bool CanEditSelectedAssignment() const; 54 | void CopySelectedAssignment(); 55 | void PasteAssignment(); 56 | bool CanPasteAssignment() const; 57 | void DuplicateSelectedAssignment(); 58 | void DeleteSelectedAssignment(); 59 | void OnGoToSelectedAssignmentDefinitionClicked() const; 60 | bool CanGoToSelectedAssignmentDefinition() const; 61 | 62 | void OnItemDoubleClicked(TSharedPtr Item); 63 | 64 | UBlueprint* GetBlueprint() const; 65 | UClass* GetGeneratedClass() const; 66 | 67 | TSharedPtr GetSelectedAssignment() const; 68 | 69 | TSharedPtr>> AssignmentList; 70 | TArray> Assignments; 71 | FOnViewModelSelected OnViewModelSelected; 72 | TWeakPtr BlueprintEditorPtr; 73 | TSharedPtr CommandList; 74 | }; 75 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/ViewModelTab/MDViewModelTab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "WidgetDrawerConfig.h" 4 | #include "WorkflowOrientedApp/WorkflowTabFactory.h" 5 | 6 | class SMDViewModelEditor; 7 | class FBlueprintEditor; 8 | 9 | struct FMDViewModelSummoner : public FWorkflowTabFactory 10 | { 11 | static const FName TabID; 12 | static const FName DrawerID; 13 | 14 | FMDViewModelSummoner(const TSharedPtr& BlueprintEditor, bool bIsDrawer); 15 | 16 | virtual TSharedRef CreateTabBody(const FWorkflowTabSpawnInfo& Info) const override; 17 | TSharedRef GetOrCreateViewModelEditor() const; 18 | 19 | static TSharedRef StaticSpawnTab(const FSpawnTabArgs& Args, TWeakPtr WeakBlueprintEditor); 20 | static FWidgetDrawerConfig CreateDrawerConfig(const TSharedRef& BlueprintEditor); 21 | 22 | private: 23 | TWeakPtr WeakBlueprintEditor; 24 | const bool bIsDrawer; 25 | 26 | mutable TSharedPtr ViewModelEditor; 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /Source/MDViewModelEditor/Public/Widgets/SMDVMConfigEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Misc/NotifyHook.h" 4 | #include "Widgets/SBoxPanel.h" 5 | #include "Widgets/SCompoundWidget.h" 6 | 7 | class IDetailsView; 8 | 9 | class MDVIEWMODELEDITOR_API SMDVMConfigEditor : public SCompoundWidget, public FNotifyHook 10 | { 11 | public: 12 | SLATE_BEGIN_ARGS(SMDVMConfigEditor) 13 | { 14 | } 15 | 16 | SLATE_END_ARGS() 17 | 18 | void Construct(const FArguments& InArgs); 19 | 20 | virtual void NotifyPostChange(const FPropertyChangedEvent& PropertyChangedEvent, FProperty* PropertyThatChanged) override; 21 | virtual int32 OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const override; 22 | 23 | private: 24 | void OnClassPicked(UClass* Class); 25 | 26 | TSharedPtr ViewModelDetails; 27 | SVerticalBox::FSlot* ClassViewerSlot = nullptr; 28 | }; 29 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/MDViewModelGraph.Build.cs: -------------------------------------------------------------------------------- 1 | using UnrealBuildTool; 2 | 3 | public class MDViewModelGraph : ModuleRules 4 | { 5 | public MDViewModelGraph(ReadOnlyTargetRules Target) : base(Target) 6 | { 7 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 8 | 9 | PublicDependencyModuleNames.AddRange( 10 | new string[] 11 | { 12 | "Core", 13 | "BlueprintGraph", 14 | "Kismet" 15 | } 16 | ); 17 | 18 | #if UE_5_3_OR_LATER 19 | PrivateDependencyModuleNames.Add("FieldNotification"); 20 | #endif 21 | 22 | PrivateDependencyModuleNames.AddRange( 23 | new string[] 24 | { 25 | "CoreUObject", 26 | "Engine", 27 | "GameplayTags", 28 | "KismetCompiler", 29 | "MDViewModel", 30 | "Slate", 31 | "SlateCore", 32 | "StructUtils", 33 | "ToolMenus", 34 | "UMG", 35 | "UMGEditor", 36 | "UnrealEd" 37 | } 38 | ); 39 | } 40 | } -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/BlueprintExtensions/MDViewModelSupportedBlueprintExtension.cpp: -------------------------------------------------------------------------------- 1 | #include "BlueprintExtensions/MDViewModelSupportedBlueprintExtension.h" 2 | 3 | void UMDViewModelSupportedBlueprintExtension::BeginDestroy() 4 | { 5 | Super::BeginDestroy(); 6 | 7 | // Work around issue where ~FInstancedStruct would crash when calling DestroyStruct on partially destroyed UserDefinedStructs 8 | Assignments.Empty(); 9 | } 10 | 11 | void UMDViewModelSupportedBlueprintExtension::PostLoad() 12 | { 13 | Super::PostLoad(); 14 | 15 | for (FMDViewModelEditorAssignment& Assignment : Assignments) 16 | { 17 | Assignment.Assignment.UpdateViewModelClassName(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/BlueprintExtensions/MDViewModelWidgetBlueprintExtension.cpp: -------------------------------------------------------------------------------- 1 | #include "BlueprintExtensions/MDViewModelWidgetBlueprintExtension.h" 2 | 3 | #include "Util/MDViewModelEditorAssignment.h" 4 | 5 | 6 | void UMDViewModelWidgetBlueprintExtension::BeginDestroy() 7 | { 8 | Super::BeginDestroy(); 9 | 10 | // Work around issue where ~FInstancedStruct would crash when calling DestroyStruct on partially destroyed UserDefinedStructs 11 | Assignments.Empty(); 12 | } 13 | 14 | void UMDViewModelWidgetBlueprintExtension::PostLoad() 15 | { 16 | Super::PostLoad(); 17 | 18 | for (FMDViewModelEditorAssignment& Assignment : Assignments) 19 | { 20 | Assignment.Assignment.UpdateViewModelClassName(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/MDViewModelGraph.cpp: -------------------------------------------------------------------------------- 1 | #include "BlueprintCompilationManager.h" 2 | #include "BlueprintExtensions/MDViewModelAssignableInterface.h" 3 | #include "BlueprintExtensions/MDViewModelBlueprintCompilerExtension.h" 4 | #include "Editor.h" 5 | #include "Interfaces/MDViewModelSupportedInterface.h" 6 | #include "Modules/ModuleManager.h" 7 | #include "Util/MDViewModelGraphStatics.h" 8 | 9 | 10 | class FMDViewModelGraphModule : public IModuleInterface 11 | { 12 | virtual void StartupModule() override 13 | { 14 | FCoreDelegates::OnPostEngineInit.AddLambda([this]() 15 | { 16 | if (GEditor != nullptr) 17 | { 18 | PreCompileHandle = GEditor->OnBlueprintPreCompile().AddRaw(this, &FMDViewModelGraphModule::OnBlueprintPreCompile); 19 | } 20 | }); 21 | 22 | CompilerExtensionPtr = NewObject(); 23 | CompilerExtensionPtr->AddToRoot(); 24 | 25 | FBlueprintCompilationManager::RegisterCompilerExtension(UBlueprint::StaticClass(), CompilerExtensionPtr.Get()); 26 | } 27 | 28 | virtual void ShutdownModule() override 29 | { 30 | FCoreDelegates::OnPostEngineInit.RemoveAll(this); 31 | if (GEditor != nullptr) 32 | { 33 | GEditor->OnBlueprintPreCompile().Remove(PreCompileHandle); 34 | PreCompileHandle.Reset(); 35 | } 36 | 37 | if (UMDViewModelBlueprintCompilerExtension* CompilerExtension = CompilerExtensionPtr.Get()) 38 | { 39 | CompilerExtension->RemoveFromRoot(); 40 | CompilerExtension = nullptr; 41 | } 42 | } 43 | 44 | void OnBlueprintPreCompile(UBlueprint* Blueprint) 45 | { 46 | if (IsValid(Blueprint) && IsValid(Blueprint->ParentClass)) 47 | { 48 | if (const UMDViewModelBlueprintCompilerExtension* CompilerExtension = CompilerExtensionPtr.Get()) 49 | { 50 | IMDViewModelAssignableInterface* Extension = FMDViewModelGraphStatics::GetAssignableInterface(Blueprint); 51 | if (Extension == nullptr || Extension->GetAssignments().IsEmpty()) 52 | { 53 | return; 54 | } 55 | 56 | if (Blueprint->ParentClass->IsChildOf()) 57 | { 58 | CompilerExtension->HandleActorBlueprintPreCompile(Extension, Cast(Blueprint->GeneratedClass)); 59 | } 60 | else if (Blueprint->ParentClass->ImplementsInterface(UMDViewModelSupportedInterface::StaticClass())) 61 | { 62 | CompilerExtension->HandleGeneralBlueprintPreCompile(Extension, Cast(Blueprint->GeneratedClass)); 63 | } 64 | } 65 | } 66 | } 67 | 68 | FDelegateHandle PreCompileHandle; 69 | 70 | // Use a weak ptr even though we add it to root, it can be destroyed before the module shuts down 71 | TWeakObjectPtr CompilerExtensionPtr = nullptr; 72 | }; 73 | 74 | IMPLEMENT_MODULE(FMDViewModelGraphModule, MDViewModelGraph) -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Nodes/MDVMNode_CallCommand.cpp: -------------------------------------------------------------------------------- 1 | #include "Nodes/MDVMNode_CallCommand.h" 2 | 3 | #include "Nodes/MDViewModelNodeSpawner.h" 4 | 5 | FText UMDVMNode_CallCommand::GetFunctionContextFormat() const 6 | { 7 | return INVTEXT("Command on {ViewModelClass} ({ViewModelName})"); 8 | } 9 | 10 | bool UMDVMNode_CallCommand::IsFunctionValidForNode(const UFunction& Func) const 11 | { 12 | return Super::IsFunctionValidForNode(Func) && Func.HasAllFunctionFlags(FUNC_BlueprintCallable) && !Func.HasAnyFunctionFlags(FUNC_BlueprintPure | FUNC_Static | FUNC_Delegate); 13 | } 14 | 15 | UBlueprintNodeSpawner* UMDVMNode_CallCommand::CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const UFunction* Function, const UBlueprint* Blueprint) const 16 | { 17 | return UMDViewModelNodeSpawner::Create(UMDVMNode_CallCommand::StaticClass(), INVTEXT("View Model Commands"), AssignmentReference, Function, Blueprint); 18 | } 19 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Nodes/MDVMNode_CallGetter.cpp: -------------------------------------------------------------------------------- 1 | #include "Nodes/MDVMNode_CallGetter.h" 2 | 3 | #include "Nodes/MDViewModelNodeSpawner.h" 4 | 5 | FText UMDVMNode_CallGetter::GetFunctionContextFormat() const 6 | { 7 | return INVTEXT("Getter on {ViewModelClass} ({ViewModelName})"); 8 | } 9 | 10 | bool UMDVMNode_CallGetter::IsFunctionValidForNode(const UFunction& Func) const 11 | { 12 | if (!Func.HasAllFunctionFlags(FUNC_BlueprintCallable) || Func.HasAnyFunctionFlags(FUNC_Static)) 13 | { 14 | return false; 15 | } 16 | 17 | return Super::IsFunctionValidForNode(Func) && Func.NumParms == 1 && MDViewModelUtils::GetFunctionReturnProperty(&Func) != nullptr; 18 | } 19 | 20 | UBlueprintNodeSpawner* UMDVMNode_CallGetter::CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const UFunction* Function, const UBlueprint* Blueprint) const 21 | { 22 | return UMDViewModelNodeSpawner::Create(UMDVMNode_CallGetter::StaticClass(), INVTEXT("View Model Getters"), AssignmentReference, Function, Blueprint); 23 | } 24 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Nodes/MDVMNode_CallHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "Nodes/MDVMNode_CallHelper.h" 2 | 3 | #include "Nodes/MDViewModelNodeSpawner.h" 4 | 5 | FText UMDVMNode_CallHelper::GetFunctionContextFormat() const 6 | { 7 | return INVTEXT("Helper on {ViewModelClass} ({ViewModelName})"); 8 | } 9 | 10 | bool UMDVMNode_CallHelper::IsFunctionValidForNode(const UFunction& Func) const 11 | { 12 | return Super::IsFunctionValidForNode(Func) && Func.HasAllFunctionFlags(FUNC_BlueprintCallable | FUNC_BlueprintPure) && !Func.HasAnyFunctionFlags(FUNC_Static); 13 | } 14 | 15 | UBlueprintNodeSpawner* UMDVMNode_CallHelper::CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const UFunction* Function, const UBlueprint* Blueprint) const 16 | { 17 | return UMDViewModelNodeSpawner::Create(UMDVMNode_CallHelper::StaticClass(), INVTEXT("View Model Helpers"), AssignmentReference, Function, Blueprint); 18 | } 19 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Nodes/MDVMNode_DynamicBindingBase.cpp: -------------------------------------------------------------------------------- 1 | #include "Nodes/MDVMNode_DynamicBindingBase.h" 2 | 3 | #include "BlueprintExtensions/MDViewModelAssignableInterface.h" 4 | #include "Kismet2/BlueprintEditorUtils.h" 5 | #include "Util/MDViewModelGraphStatics.h" 6 | #include "ViewModel/MDViewModelBase.h" 7 | 8 | void UMDVMNode_DynamicBindingBase::ReconstructNode() 9 | { 10 | UpdateDeprecatedProperties(); 11 | 12 | Super::ReconstructNode(); 13 | } 14 | 15 | void UMDVMNode_DynamicBindingBase::AllocateDefaultPins() 16 | { 17 | Super::AllocateDefaultPins(); 18 | 19 | BindAssignmentChanges(); 20 | } 21 | 22 | void UMDVMNode_DynamicBindingBase::BeginDestroy() 23 | { 24 | UnbindAssignmentChanges(); 25 | 26 | Super::BeginDestroy(); 27 | } 28 | 29 | FString UMDVMNode_DynamicBindingBase::GetFindReferenceSearchString() const 30 | { 31 | return FString::Printf(TEXT("\"%s\""), *GetNodeTitle(ENodeTitleType::FullTitle).ToString()); 32 | } 33 | 34 | void UMDVMNode_DynamicBindingBase::PostLoad() 35 | { 36 | UpdateDeprecatedProperties(); 37 | 38 | Super::PostLoad(); 39 | } 40 | 41 | FText UMDVMNode_DynamicBindingBase::GetViewModelClassName() const 42 | { 43 | const UClass* VMClass = Assignment.ViewModelClass.LoadSynchronous(); 44 | return IsValid(VMClass) ? VMClass->GetDisplayNameText() : INVTEXT("NULL"); 45 | } 46 | void UMDVMNode_DynamicBindingBase::OnAssignmentChanged() 47 | { 48 | CachedNodeTitle.MarkDirty(); 49 | } 50 | 51 | void UMDVMNode_DynamicBindingBase::BindAssignmentChanges() 52 | { 53 | const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNode(this); 54 | if (IMDViewModelAssignableInterface* Assignments = FMDViewModelGraphStatics::GetAssignableInterface(Blueprint)) 55 | { 56 | if (!Assignments->OnAssignmentChanged.IsBoundToObject(this)) 57 | { 58 | Assignments->OnAssignmentChanged.AddUObject(this, &UMDVMNode_DynamicBindingBase::OnAssignmentChanged); 59 | } 60 | } 61 | } 62 | 63 | void UMDVMNode_DynamicBindingBase::OnAssignmentChanged(const FMDViewModelAssignmentReference& Old, const FMDViewModelAssignmentReference& New) 64 | { 65 | if (Assignment == Old) 66 | { 67 | Modify(); 68 | Assignment = New; 69 | OnAssignmentChanged(); 70 | ReconstructNode(); 71 | } 72 | } 73 | 74 | void UMDVMNode_DynamicBindingBase::UnbindAssignmentChanges() 75 | { 76 | const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNode(this); 77 | if (IMDViewModelAssignableInterface* Assignments = FMDViewModelGraphStatics::GetAssignableInterface(Blueprint)) 78 | { 79 | Assignments->OnAssignmentChanged.RemoveAll(this); 80 | } 81 | } 82 | 83 | void UMDVMNode_DynamicBindingBase::UpdateDeprecatedProperties() 84 | { 85 | if (ViewModelClass != nullptr && ViewModelName != NAME_None && !Assignment.IsAssignmentValid()) 86 | { 87 | Assignment.ViewModelClass = ViewModelClass; 88 | Assignment.ViewModelName = ViewModelName; 89 | ViewModelClass = nullptr; 90 | ViewModelName = NAME_None; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Nodes/MDVMNode_SetViewModel.cpp: -------------------------------------------------------------------------------- 1 | #include "Nodes/MDVMNode_SetViewModel.h" 2 | 3 | #include "BlueprintActionDatabaseRegistrar.h" 4 | #include "BlueprintNodeSpawner.h" 5 | #include "EdGraphSchema_K2.h" 6 | #include "Util/MDViewModelFunctionLibrary.h" 7 | #include "ViewModel/MDViewModelBase.h" 8 | 9 | UMDVMNode_SetViewModel::UMDVMNode_SetViewModel() 10 | { 11 | FunctionReference.SetExternalMember(GET_FUNCTION_NAME_CHECKED(UMDViewModelFunctionLibrary, BP_SetViewModel), UMDViewModelFunctionLibrary::StaticClass()); 12 | } 13 | 14 | void UMDVMNode_SetViewModel::GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const 15 | { 16 | const UClass* ActionKey = GetClass(); 17 | if (InActionRegistrar.IsOpenForRegistration(ActionKey)) 18 | { 19 | UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass()); 20 | check(NodeSpawner != nullptr); 21 | 22 | InActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner); 23 | } 24 | } 25 | 26 | void UMDVMNode_SetViewModel::AutowireNewNode(UEdGraphPin* FromPin) 27 | { 28 | // If FromPin is a view model output, auto connect it to our View Model pin, otherwise the Super call will connect it to the Object pin 29 | UEdGraphPin* ViewModelPin = FindPin(TEXT("ViewModel")); 30 | if (FromPin != nullptr && FromPin->Direction == EGPD_Output && FromPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object) 31 | { 32 | const UClass* PinTypeClass = Cast(FromPin->PinType.PinSubCategoryObject.Get()); 33 | if (IsValid(PinTypeClass) && PinTypeClass->IsChildOf()) 34 | { 35 | const UEdGraphSchema_K2* K2Schema = CastChecked(GetSchema()); 36 | if (K2Schema->TryCreateConnection(FromPin, ViewModelPin)) 37 | { 38 | if (FromPin->GetOwningNode() != nullptr) 39 | { 40 | FromPin->GetOwningNode()->NodeConnectionListChanged(); 41 | return; 42 | } 43 | } 44 | } 45 | } 46 | 47 | Super::AutowireNewNode(FromPin); 48 | } 49 | 50 | void UMDVMNode_SetViewModel::AllocateDefaultPins() 51 | { 52 | Super::AllocateDefaultPins(); 53 | 54 | if (PendingAssignment.IsAssignmentValid()) 55 | { 56 | SetDefaultAssignment(PendingAssignment); 57 | PendingAssignment = {}; 58 | } 59 | } 60 | 61 | void UMDVMNode_SetViewModel::SetDefaultAssignment(const FMDViewModelAssignmentReference& Assignment) 62 | { 63 | if (UEdGraphPin* AssignmentPin = FindPin(TEXT("Assignment"))) 64 | { 65 | FString AssignmentValue; 66 | FMDViewModelAssignmentReference::StaticStruct()->ExportText(AssignmentValue, &Assignment, &Assignment, nullptr, PPF_SerializedAsImportText, nullptr); 67 | 68 | if (AssignmentValue != AssignmentPin->GetDefaultAsString()) 69 | { 70 | AssignmentPin->GetSchema()->TrySetDefaultValue(*AssignmentPin, AssignmentValue); 71 | } 72 | } 73 | else 74 | { 75 | PendingAssignment = Assignment; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Subsystems/MDViewModelGraphSubsystem.cpp: -------------------------------------------------------------------------------- 1 | #include "Subsystems/MDViewModelGraphSubsystem.h" 2 | #include "Engine/Blueprint.h" 3 | #include "Engine/Engine.h" 4 | 5 | void UMDViewModelGraphSubsystem::BroadcastBlueprintViewModelAssignmentsChanged(UBlueprint* Blueprint) 6 | { 7 | if (IsValid(Blueprint) && IsValid(GEngine)) 8 | { 9 | GEngine->GetEngineSubsystem()->OnAssignmentsChanged.Broadcast(Blueprint); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Private/Util/MDViewModelEditorAssignment.cpp: -------------------------------------------------------------------------------- 1 | #include "Util/MDViewModelEditorAssignment.h" 2 | 3 | bool FMDViewModelEditorAssignment::operator==(const FMDViewModelEditorAssignment& Other) const 4 | { 5 | return Other.Assignment == Assignment; 6 | } 7 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/BlueprintExtensions/MDViewModelAssignableInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "GameplayTagContainer.h" 4 | #include "Templates/SubclassOf.h" 5 | #include "UObject/Interface.h" 6 | #include "MDViewModelAssignableInterface.generated.h" 7 | 8 | struct FMDViewModelAssignmentReference; 9 | class UMDViewModelBase; 10 | struct FMDViewModelAssignmentData; 11 | struct FMDViewModelAssignment; 12 | struct FMDViewModelEditorAssignment; 13 | 14 | UINTERFACE() 15 | class UMDViewModelAssignableInterface : public UInterface 16 | { 17 | GENERATED_BODY() 18 | }; 19 | 20 | // Interface for an object that can be assigned view models 21 | class MDVIEWMODELGRAPH_API IMDViewModelAssignableInterface 22 | { 23 | GENERATED_BODY() 24 | 25 | public: 26 | virtual TArray& GetAssignments() = 0; 27 | 28 | virtual UBlueprint* GetBlueprint() const; 29 | 30 | void ModifyObject(); 31 | 32 | const TArray& GetAssignments() const; 33 | void GetAllAssignments(TMap& OutViewModelAssignments) const; 34 | 35 | void AddAssignment(FMDViewModelEditorAssignment&& Assignment); 36 | void UpdateAssignment(const FMDViewModelEditorAssignment& Assignment, FMDViewModelEditorAssignment&& UpdatedAssignment); 37 | void RemoveAssignment(const FMDViewModelEditorAssignment& Assignment); 38 | 39 | bool DoesContainViewModelAssignment(TSubclassOf ViewModelClass = nullptr, const FGameplayTag& ProviderTag = FGameplayTag::EmptyTag, const FName& ViewModelName = NAME_None) const; 40 | bool HasAssignments() const; 41 | 42 | DECLARE_MULTICAST_DELEGATE_TwoParams(FOnViewModelAssignmentChanged, const FMDViewModelAssignmentReference& /*OldAssignment*/, const FMDViewModelAssignmentReference& /*NewAssignment*/); 43 | FOnViewModelAssignmentChanged OnAssignmentChanged; 44 | 45 | protected: 46 | void GetParentAssignments(TMap& OutViewModelAssignments) const; 47 | void SearchParentAssignments(TMap& OutViewModelAssignments, TSubclassOf ViewModelClass = nullptr, const FGameplayTag& ProviderTag = FGameplayTag::EmptyTag, const FName& ViewModelName = NAME_None) const; 48 | }; 49 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/BlueprintExtensions/MDViewModelBlueprintCompilerExtension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BlueprintCompilerExtension.h" 4 | #include "MDViewModelBlueprintCompilerExtension.generated.h" 5 | 6 | class IMDViewModelAssignableInterface; 7 | class UWidgetBlueprint; 8 | 9 | /** 10 | * Blueprint Compiler Extension to inject View Model assignments when compiling Blueprints 11 | * Widget Blueprints: Injects MDViewModelClassExtensions when compiling widgets with super classes that have view model assignments 12 | * Actor Blueprints: Adds a UMDViewModelAssignmentComponent to the Actor if the parent doesn't have one, and adds the view model assignments to it 13 | */ 14 | UCLASS() 15 | class MDVIEWMODELGRAPH_API UMDViewModelBlueprintCompilerExtension : public UBlueprintCompilerExtension 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | virtual void ProcessBlueprintCompiled(const FKismetCompilerContext& CompilationContext, const FBlueprintCompiledData& Data) override; 21 | 22 | void HandleActorBlueprintPreCompile(IMDViewModelAssignableInterface* Extension, UBlueprintGeneratedClass* BPClass) const; 23 | void HandleGeneralBlueprintPreCompile(IMDViewModelAssignableInterface* Extension, UBlueprintGeneratedClass* BPClass) const; 24 | 25 | private: 26 | void HandleWidgetBlueprintCompiled(IMDViewModelAssignableInterface* Extension, UWidgetBlueprint& WidgetBP, const FKismetCompilerContext& CompilationContext) const; 27 | void HandleActorBlueprintCompiled(IMDViewModelAssignableInterface* Extension, UBlueprint& Blueprint, const FKismetCompilerContext& CompilationContext) const; 28 | void HandleGeneralBlueprintCompiled(IMDViewModelAssignableInterface* Extension, UBlueprint& Blueprint, const FKismetCompilerContext& CompilationContext) const; 29 | }; 30 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/BlueprintExtensions/MDViewModelSupportedBlueprintExtension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Blueprint/BlueprintExtension.h" 4 | #include "MDViewModelAssignableInterface.h" 5 | #include "Util/MDViewModelEditorAssignment.h" 6 | #include "MDViewModelSupportedBlueprintExtension.generated.h" 7 | 8 | /** 9 | * Editor-only class that holds design-time assigned view models for non-Widget Blueprints 10 | * Assignment compilation happens in UMDViewModelBlueprintCompilerExtension::HandleActorBlueprintPreCompile/HandleGeneralBlueprintPreCompile 11 | */ 12 | UCLASS() 13 | class MDVIEWMODELGRAPH_API UMDViewModelSupportedBlueprintExtension : public UBlueprintExtension, public IMDViewModelAssignableInterface 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | virtual void BeginDestroy() override; 19 | virtual void PostLoad() override; 20 | 21 | virtual TArray& GetAssignments() override { return Assignments; } 22 | 23 | protected: 24 | UPROPERTY() 25 | TArray Assignments; 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/BlueprintExtensions/MDViewModelWidgetBlueprintExtension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDViewModelAssignableInterface.h" 4 | #include "WidgetBlueprintExtension.h" 5 | #include "Util/MDViewModelEditorAssignment.h" 6 | #include "MDViewModelWidgetBlueprintExtension.generated.h" 7 | 8 | class UMDViewModelBase; 9 | struct FMDViewModelEditorAssignment; 10 | 11 | /** 12 | * Editor-only class that holds design-time assigned view models for widgets 13 | */ 14 | UCLASS() 15 | class MDVIEWMODELGRAPH_API UMDViewModelWidgetBlueprintExtension : public UWidgetBlueprintExtension, public IMDViewModelAssignableInterface 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | virtual void BeginDestroy() override; 21 | virtual void PostLoad() override; 22 | 23 | virtual TArray& GetAssignments() override { return Assignments; } 24 | 25 | protected: 26 | UPROPERTY() 27 | TArray Assignments; 28 | }; 29 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_CallCommand.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMNode_CallFunctionBase.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | 6 | #include "MDVMNode_CallCommand.generated.h" 7 | 8 | class UBlueprint; 9 | 10 | /** 11 | * Node to shortcut getting a view model instance and calling an impure function on it 12 | */ 13 | UCLASS() 14 | class MDVIEWMODELGRAPH_API UMDVMNode_CallCommand : public UMDVMNode_CallFunctionBase 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | virtual FText GetFunctionContextFormat() const override; 20 | 21 | protected: 22 | virtual bool IsFunctionValidForNode(const UFunction& Func) const override; 23 | 24 | virtual UBlueprintNodeSpawner* CreateNodeSpawner(const FMDViewModelAssignmentReference& Assignment, const UFunction* Function, const UBlueprint* Blueprint) const override; 25 | }; 26 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_CallFunctionBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_CallFunction.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMNode_CallFunctionBase.generated.h" 6 | 7 | class UBlueprint; 8 | 9 | // Base class for calling functions on assigned view models 10 | UCLASS(Abstract) 11 | class MDVIEWMODELGRAPH_API UMDVMNode_CallFunctionBase : public UK2Node_CallFunction 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | virtual void BeginDestroy() override; 17 | 18 | virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const override; 19 | virtual bool IsActionFilteredOut(const FBlueprintActionFilter& Filter) override; 20 | virtual void GetNodeContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const override; 21 | virtual bool IncludeParentNodeContextMenu() const override { return true; } 22 | 23 | virtual void AllocateDefaultPins() override; 24 | virtual void PinConnectionListChanged(UEdGraphPin* Pin) override; 25 | 26 | virtual bool IsNodePure() const override { return bIsSetPure; } 27 | 28 | virtual void GetPinHoverText(const UEdGraphPin& Pin, FString& HoverTextOut) const override; 29 | 30 | virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; 31 | virtual FText GetFunctionContextString() const override; 32 | virtual FText GetFunctionContextFormat() const; 33 | virtual FString GetFindReferenceSearchString() const override; 34 | 35 | virtual FNodeHandlingFunctor* CreateNodeHandler(FKismetCompilerContext& CompilerContext) const override; 36 | virtual void ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override; 37 | virtual void ValidateNodeDuringCompilation(FCompilerResultsLog& MessageLog) const override; 38 | 39 | void InitializeViewModelFunctionParams(const FMDViewModelAssignmentReference& VMAssignment, const UFunction* Function, const UBlueprint* Blueprint = nullptr); 40 | 41 | protected: 42 | virtual bool IsFunctionValidForNode(const UFunction& Func) const; 43 | virtual bool CanTogglePurity() const; 44 | 45 | virtual UBlueprintNodeSpawner* CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const UFunction* Function, const UBlueprint* Blueprint) const { return nullptr;} 46 | 47 | private: 48 | void BindAssignmentChanges(); 49 | void OnAssignmentChanged(const FMDViewModelAssignmentReference& Old, const FMDViewModelAssignmentReference& New); 50 | void UnbindAssignmentChanges(); 51 | 52 | void TogglePurity(); 53 | 54 | UPROPERTY() 55 | FMDViewModelAssignmentReference Assignment; 56 | 57 | UPROPERTY() 58 | TWeakObjectPtr ExpectedBlueprintPtr; 59 | 60 | UPROPERTY() 61 | bool bIsSetPure = false; 62 | }; 63 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_CallGetter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMNode_CallFunctionBase.h" 4 | #include "MDVMNode_CallGetter.generated.h" 5 | 6 | /** 7 | * 8 | */ 9 | UCLASS() 10 | class MDVIEWMODELGRAPH_API UMDVMNode_CallGetter : public UMDVMNode_CallFunctionBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | virtual FText GetFunctionContextFormat() const override; 16 | 17 | protected: 18 | virtual bool IsFunctionValidForNode(const UFunction& Func) const override; 19 | 20 | virtual UBlueprintNodeSpawner* CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const UFunction* Function, const UBlueprint* Blueprint) const override; 21 | }; 22 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_CallHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMNode_CallFunctionBase.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | 6 | #include "MDVMNode_CallHelper.generated.h" 7 | 8 | class UBlueprint; 9 | 10 | /** 11 | * Node to shortcut getting a view model instance and calling a pure function on it 12 | */ 13 | UCLASS() 14 | class MDVIEWMODELGRAPH_API UMDVMNode_CallHelper : public UMDVMNode_CallFunctionBase 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | virtual FText GetFunctionContextFormat() const override; 20 | 21 | protected: 22 | virtual bool IsFunctionValidForNode(const UFunction& Func) const override; 23 | 24 | virtual UBlueprintNodeSpawner* CreateNodeSpawner(const FMDViewModelAssignmentReference& Assignment, const UFunction* Function, const UBlueprint* Blueprint) const override; 25 | }; 26 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_DynamicBindingBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_Event.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMNode_DynamicBindingBase.generated.h" 6 | 7 | class UMDViewModelBase; 8 | 9 | UCLASS(Abstract) 10 | class MDVIEWMODELGRAPH_API UMDVMNode_DynamicBindingBase : public UK2Node_Event 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | virtual void ReconstructNode() override; 16 | virtual void AllocateDefaultPins() override; 17 | virtual void BeginDestroy() override; 18 | 19 | virtual FString GetFindReferenceSearchString() const override; 20 | 21 | virtual void PostLoad() override; 22 | 23 | FText GetViewModelClassName() const; 24 | 25 | UPROPERTY() 26 | FMDViewModelAssignmentReference Assignment; 27 | 28 | protected: 29 | FNodeTextCache CachedNodeTitle; 30 | 31 | virtual void OnAssignmentChanged(); 32 | 33 | private: 34 | void BindAssignmentChanges(); 35 | void OnAssignmentChanged(const FMDViewModelAssignmentReference& Old, const FMDViewModelAssignmentReference& New); 36 | void UnbindAssignmentChanges(); 37 | 38 | void UpdateDeprecatedProperties(); 39 | 40 | // Deprecated for Assignment 41 | UPROPERTY() 42 | TSubclassOf ViewModelClass; 43 | // Deprecated for Assignment 44 | UPROPERTY() 45 | FName ViewModelName = NAME_None; 46 | }; 47 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_GetProperty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_VariableGet.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMNode_GetProperty.generated.h" 6 | 7 | class UBlueprint; 8 | 9 | /** 10 | * Custom node for getting a variable from a view model with built-in view model validation 11 | */ 12 | UCLASS() 13 | class MDVIEWMODELGRAPH_API UMDVMNode_GetProperty : public UK2Node_VariableGet 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | virtual void AllocateDefaultPins() override; 19 | virtual void ReallocatePinsDuringReconstruction(TArray& OldPins) override; 20 | virtual void BeginDestroy() override; 21 | 22 | virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const override; 23 | virtual bool IsActionFilteredOut(const FBlueprintActionFilter& Filter) override; 24 | 25 | virtual bool DrawNodeAsVariable() const override { return false; } 26 | virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; 27 | virtual void GetNodeContextMenuActions(class UToolMenu* Menu, class UGraphNodeContextMenuContext* Context) const override; 28 | 29 | virtual void ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override; 30 | virtual void ValidateNodeDuringCompilation(FCompilerResultsLog& MessageLog) const override; 31 | 32 | void InitializeViewModelPropertyParams(const FMDViewModelAssignmentReference& VMAssignment, const FProperty* Property, const UBlueprint* Blueprint = nullptr); 33 | 34 | protected: 35 | UBlueprintNodeSpawner* CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const FProperty* Property, const UBlueprint* Blueprint) const; 36 | 37 | private: 38 | void BindAssignmentChanges(); 39 | void OnAssignmentChanged(const FMDViewModelAssignmentReference& Old, const FMDViewModelAssignmentReference& New); 40 | void UnbindAssignmentChanges(); 41 | 42 | bool IsPropertyValidForNode(const FProperty* Property) const; 43 | 44 | void ToggleValidation(); 45 | 46 | UPROPERTY() 47 | FMDViewModelAssignmentReference Assignment; 48 | 49 | UPROPERTY() 50 | TWeakObjectPtr ExpectedBlueprintPtr; 51 | 52 | FNodeTextCache TitleCache; 53 | }; 54 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_GetViewModel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_CallFunction.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMNode_GetViewModel.generated.h" 6 | 7 | /** 8 | * Custom node for UMDViewModelFunctionLibrary::BP_GetViewModel to auto-cast the return value to the assigned view model class and optionally provide validation 9 | */ 10 | UCLASS() 11 | class MDVIEWMODELGRAPH_API UMDVMNode_GetViewModel : public UK2Node_CallFunction 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | UMDVMNode_GetViewModel(); 17 | 18 | virtual void AllocateDefaultPins() override; 19 | virtual void ReconstructNode() override; 20 | virtual void PostReconstructNode() override; 21 | virtual void PinDefaultValueChanged(UEdGraphPin* Pin) override; 22 | virtual void ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const override; 23 | 24 | virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const override; 25 | virtual void GetNodeContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const override; 26 | virtual bool IncludeParentNodeContextMenu() const override { return true; } 27 | 28 | virtual bool IsNodePure() const override { return bIsPureGet; } 29 | 30 | UEdGraphPin* GetTruePin() const; 31 | UEdGraphPin* GetFalsePin() const; 32 | UEdGraphPin* GetIsValidPin() const; 33 | 34 | virtual ERedirectType DoPinsMatchForReconstruction(const UEdGraphPin* NewPin, int32 NewPinIndex, const UEdGraphPin* OldPin, int32 OldPinIndex) const override; 35 | 36 | virtual FText GetPinDisplayName(const UEdGraphPin* Pin) const override; 37 | 38 | void SetDefaultAssignment(const FMDViewModelAssignmentReference& Assignment); 39 | 40 | void SetIsPureGet(bool InIsPure); 41 | 42 | private: 43 | void UpdateReturnPin() const; 44 | void TogglePurity(); 45 | 46 | UPROPERTY() 47 | FMDViewModelAssignmentReference PendingAssignment; 48 | 49 | UPROPERTY() 50 | bool bIsPureGet = false; 51 | 52 | mutable bool bDoesNeedOutputRemapping = false; 53 | }; 54 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_SetProperty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_VariableSet.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMNode_SetProperty.generated.h" 6 | 7 | /** 8 | * Custom node for setting a variable on a view model with built-in view model validation 9 | */ 10 | UCLASS() 11 | class MDVIEWMODELGRAPH_API UMDVMNode_SetProperty : public UK2Node_Variable 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | virtual void AllocateDefaultPins() override; 17 | virtual void ReallocatePinsDuringReconstruction(TArray& OldPins) override; 18 | virtual void BeginDestroy() override; 19 | 20 | virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const override; 21 | virtual bool IsActionFilteredOut(const FBlueprintActionFilter& Filter) override; 22 | 23 | virtual bool DrawNodeAsVariable() const override { return false; } 24 | virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; 25 | 26 | virtual void ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override; 27 | virtual void ValidateNodeDuringCompilation(FCompilerResultsLog& MessageLog) const override; 28 | 29 | void InitializeViewModelPropertyParams(const FMDViewModelAssignmentReference& VMAssignment, const FProperty* Property, const UBlueprint* Blueprint = nullptr); 30 | 31 | protected: 32 | UBlueprintNodeSpawner* CreateNodeSpawner(const FMDViewModelAssignmentReference& AssignmentReference, const FProperty* Property, const UBlueprint* Blueprint) const; 33 | 34 | private: 35 | void BindAssignmentChanges(); 36 | void OnAssignmentChanged(const FMDViewModelAssignmentReference& Old, const FMDViewModelAssignmentReference& New); 37 | void UnbindAssignmentChanges(); 38 | 39 | bool IsPropertyValidForNode(const FProperty* Property) const; 40 | 41 | UPROPERTY() 42 | FMDViewModelAssignmentReference Assignment; 43 | 44 | UPROPERTY() 45 | TWeakObjectPtr ExpectedBlueprintPtr; 46 | 47 | FNodeTextCache TitleCache; 48 | }; 49 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_SetViewModel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_CallFunction.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDVMNode_SetViewModel.generated.h" 6 | 7 | /** 8 | * Custom node for UMDViewModelFunctionLibrary::BP_SetViewModel to support pre-populating the view model assignment 9 | */ 10 | UCLASS() 11 | class MDVIEWMODELGRAPH_API UMDVMNode_SetViewModel : public UK2Node_CallFunction 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | UMDVMNode_SetViewModel(); 17 | 18 | virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const override; 19 | 20 | virtual void AutowireNewNode(UEdGraphPin* FromPin) override; 21 | 22 | virtual void AllocateDefaultPins() override; 23 | 24 | void SetDefaultAssignment(const FMDViewModelAssignmentReference& Assignment); 25 | 26 | private: 27 | UPROPERTY() 28 | FMDViewModelAssignmentReference PendingAssignment; 29 | }; 30 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_SetViewModelOfClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "K2Node_CallFunction.h" 4 | #include "MDVMNode_SetViewModelOfClass.generated.h" 5 | 6 | struct FMDViewModelAssignmentReference; 7 | 8 | /** 9 | * Custom node for UMDViewModelFunctionLibrary::BP_SetViewModelOfClass to auto-cast the return value and validate the settings 10 | */ 11 | UCLASS() 12 | class MDVIEWMODELGRAPH_API UMDVMNode_SetViewModelOfClass : public UK2Node_CallFunction 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | UMDVMNode_SetViewModelOfClass(); 18 | 19 | virtual void PostReconstructNode() override; 20 | virtual void PinDefaultValueChanged(UEdGraphPin* Pin) override; 21 | virtual void AllocateDefaultPins() override; 22 | virtual void PinConnectionListChanged(UEdGraphPin* Pin) override; 23 | 24 | virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& InActionRegistrar) const override; 25 | 26 | virtual void ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const override; 27 | 28 | virtual ERedirectType DoPinsMatchForReconstruction(const UEdGraphPin* NewPin, int32 NewPinIndex, const UEdGraphPin* OldPin, int32 OldPinIndex) const override; 29 | 30 | private: 31 | void UpdateAssignmentBasedData(); 32 | 33 | void GetAssignmentFromPinDefaults(FMDViewModelAssignmentReference& OutAssignment) const; 34 | 35 | UPROPERTY() 36 | bool bAreViewModelSettingsValid = true; 37 | 38 | UPROPERTY() 39 | FText ViewModelSettingsDisplayName; 40 | }; 41 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_ViewModelChanged.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMNode_DynamicBindingBase.h" 4 | #include "MDVMNode_ViewModelChanged.generated.h" 5 | 6 | /** 7 | * Custom node for binding to view models changing 8 | */ 9 | UCLASS() 10 | class MDVIEWMODELGRAPH_API UMDVMNode_ViewModelChanged : public UMDVMNode_DynamicBindingBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Name of the function that we're binding to 16 | UPROPERTY() 17 | FName FunctionNameToBind = NAME_None; 18 | 19 | //~ Begin UObject Interface 20 | virtual bool Modify(bool bAlwaysMarkDirty = true) override; 21 | //~ End UObject Interface 22 | 23 | //~ Begin UEdGraphNode Interface 24 | virtual void ReconstructNode() override; 25 | virtual bool CanPasteHere(const UEdGraph* TargetGraph) const override { return false; } 26 | virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; 27 | virtual FText GetTooltipText() const override; 28 | virtual void AllocateDefaultPins() override; 29 | //~ End UEdGraphNode Interface 30 | 31 | //~ Begin K2Node Interface 32 | virtual bool NodeCausesStructuralBlueprintChange() const override { return true; } 33 | virtual UClass* GetDynamicBindingClass() const override; 34 | virtual void RegisterDynamicBinding(UDynamicBlueprintBinding* BindingObject) const override; 35 | virtual void ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const override; 36 | virtual bool IsFunctionEntryCompatible(const class UK2Node_FunctionEntry* EntryNode) const override; 37 | //~ End K2Node Interface 38 | 39 | void InitializeViewModelChangedParams(const FMDViewModelAssignmentReference& InAssignment); 40 | 41 | protected: 42 | virtual void OnAssignmentChanged() override; 43 | }; 44 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_ViewModelEvent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMNode_DynamicBindingBase.h" 4 | #include "MDVMNode_ViewModelEvent.generated.h" 5 | 6 | /** 7 | * Custom node for binding to delegates on View Models 8 | */ 9 | UCLASS() 10 | class MDVIEWMODELGRAPH_API UMDVMNode_ViewModelEvent : public UMDVMNode_DynamicBindingBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Name of the delegate on the viewmodel we're going to bind to 16 | UPROPERTY() 17 | FName DelegatePropertyName = NAME_None; 18 | 19 | // Name of the function that we're binding to the delegate 20 | UPROPERTY() 21 | FName FunctionNameToBind = NAME_None; 22 | 23 | //~ Begin UObject Interface 24 | virtual bool Modify(bool bAlwaysMarkDirty = true) override; 25 | //~ End UObject Interface 26 | 27 | //~ Begin UEdGraphNode Interface 28 | virtual void ReconstructNode() override; 29 | virtual bool CanPasteHere(const UEdGraph* TargetGraph) const override { return false; } 30 | virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; 31 | virtual FText GetTooltipText() const override; 32 | virtual bool HasDeprecatedReference() const override; 33 | virtual FEdGraphNodeDeprecationResponse GetDeprecationResponse(EEdGraphNodeDeprecationType DeprecationType) const override; 34 | //~ End UEdGraphNode Interface 35 | 36 | //~ Begin K2Node Interface 37 | virtual bool NodeCausesStructuralBlueprintChange() const override { return true; } 38 | virtual UClass* GetDynamicBindingClass() const override; 39 | virtual void RegisterDynamicBinding(UDynamicBlueprintBinding* BindingObject) const override; 40 | virtual void HandleVariableRenamed(UBlueprint* InBlueprint, UClass* InVariableClass, UEdGraph* InGraph, const FName& InOldVarName, const FName& InNewVarName) override; 41 | virtual void ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const override; 42 | //~ End K2Node Interface 43 | 44 | virtual bool IsUsedByAuthorityOnlyDelegate() const override; 45 | 46 | // Return the delegate property that this event is bound to 47 | FMulticastDelegateProperty* GetTargetDelegateProperty() const; 48 | 49 | // Gets the proper display name for the property 50 | FText GetTargetDelegateDisplayName() const; 51 | 52 | void InitializeViewModelEventParams(const FMDViewModelAssignmentReference& InAssignment, const FName& InDelegatePropertyName); 53 | 54 | protected: 55 | virtual void OnAssignmentChanged() override; 56 | }; 57 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDVMNode_ViewModelFieldNotify.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MDVMNode_DynamicBindingBase.h" 4 | #include "MDVMNode_ViewModelFieldNotify.generated.h" 5 | 6 | /** 7 | * Custom node for binding to Field Notify properties/functions on View Models 8 | */ 9 | UCLASS() 10 | class MDVIEWMODELGRAPH_API UMDVMNode_ViewModelFieldNotify : public UMDVMNode_DynamicBindingBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Name of the field notify property/function on the viewmodel we're going to bind to 16 | UPROPERTY() 17 | FName FieldNotifyName = NAME_None; 18 | 19 | // Name of the function that we're binding to the delegate 20 | UPROPERTY() 21 | FName FunctionNameToBind = NAME_None; 22 | 23 | //~ Begin UObject Interface 24 | virtual bool Modify(bool bAlwaysMarkDirty = true) override; 25 | //~ End UObject Interface 26 | 27 | //~ Begin UEdGraphNode Interface 28 | virtual void ReconstructNode() override; 29 | virtual bool CanPasteHere(const UEdGraph* TargetGraph) const override { return false; } 30 | virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; 31 | virtual FText GetTooltipText() const override; 32 | virtual bool HasDeprecatedReference() const override; 33 | virtual FEdGraphNodeDeprecationResponse GetDeprecationResponse(EEdGraphNodeDeprecationType DeprecationType) const override; 34 | virtual void AllocateDefaultPins() override; 35 | //~ End UEdGraphNode Interface 36 | 37 | //~ Begin K2Node Interface 38 | virtual bool NodeCausesStructuralBlueprintChange() const override { return true; } 39 | virtual UClass* GetDynamicBindingClass() const override; 40 | virtual void RegisterDynamicBinding(UDynamicBlueprintBinding* BindingObject) const override; 41 | virtual void HandleVariableRenamed(UBlueprint* InBlueprint, UClass* InVariableClass, UEdGraph* InGraph, const FName& InOldVarName, const FName& InNewVarName) override; 42 | virtual void ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const override; 43 | virtual bool IsFunctionEntryCompatible(const class UK2Node_FunctionEntry* EntryNode) const override; 44 | //~ End K2Node Interface 45 | 46 | virtual bool IsUsedByAuthorityOnlyDelegate() const override; 47 | 48 | FFieldVariant GetTargetFieldNotify() const; 49 | const FProperty* ResolveFieldNotifyPropertyType() const; 50 | 51 | // Gets the proper display name for the property 52 | FText GetTargetFieldNotifyDisplayName() const; 53 | 54 | void InitializeViewModelFieldNotifyParams(const FMDViewModelAssignmentReference& InAssignment, const FName& InFieldNotifyName); 55 | 56 | protected: 57 | virtual void OnAssignmentChanged() override; 58 | 59 | private: 60 | UPROPERTY() 61 | FMemberReference FieldNotifyReference; 62 | }; 63 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Nodes/MDViewModelNodeSpawner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BlueprintFieldNodeSpawner.h" 4 | #include "Util/MDViewModelAssignmentReference.h" 5 | #include "MDViewModelNodeSpawner.generated.h" 6 | 7 | class UBlueprint; 8 | 9 | UCLASS() 10 | class MDVIEWMODELGRAPH_API UMDViewModelNodeSpawner : public UBlueprintFieldNodeSpawner 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | static UMDViewModelNodeSpawner* Create(TSubclassOf NodeClass, const FText& Category, const FMDViewModelAssignmentReference& Assignment, FFieldVariant Field, const UBlueprint* Blueprint, const FText& NameFormat = INVTEXT("{0}")); 16 | 17 | virtual FBlueprintNodeSignature GetSpawnerSignature() const override; 18 | virtual UEdGraphNode* Invoke(UEdGraph* ParentGraph, const FBindingSet& Bindings, const FVector2D Location) const override; 19 | 20 | protected: 21 | UPROPERTY() 22 | FMDViewModelAssignmentReference Assignment; 23 | 24 | UPROPERTY() 25 | TWeakObjectPtr BlueprintPtr; 26 | }; 27 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Subsystems/MDViewModelGraphSubsystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Subsystems/EngineSubsystem.h" 4 | #include "MDViewModelGraphSubsystem.generated.h" 5 | 6 | UCLASS() 7 | class MDVIEWMODELGRAPH_API UMDViewModelGraphSubsystem : public UEngineSubsystem 8 | { 9 | GENERATED_BODY() 10 | 11 | public: 12 | static void BroadcastBlueprintViewModelAssignmentsChanged(UBlueprint* Blueprint); 13 | 14 | DECLARE_MULTICAST_DELEGATE_OneParam(FOnBlueprintViewModelAssignmentsChanged, UBlueprint*) 15 | FOnBlueprintViewModelAssignmentsChanged OnAssignmentsChanged; 16 | }; 17 | -------------------------------------------------------------------------------- /Source/MDViewModelGraph/Public/Util/MDViewModelEditorAssignment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Util/MDViewModelAssignment.h" 4 | #include "Util/MDViewModelAssignmentData.h" 5 | #include "MDViewModelEditorAssignment.generated.h" 6 | 7 | /** 8 | * 9 | */ 10 | USTRUCT() 11 | struct MDVIEWMODELGRAPH_API FMDViewModelEditorAssignment 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | // The actual assignment 17 | UPROPERTY() 18 | FMDViewModelAssignment Assignment; 19 | 20 | // Additional data the user set in the editor 21 | UPROPERTY() 22 | FMDViewModelAssignmentData Data; 23 | 24 | // The class that this assignment is from, if this assignment is from a parent 25 | UPROPERTY(Transient) 26 | TObjectPtr SuperAssignmentOwner; 27 | 28 | bool operator==(const FMDViewModelEditorAssignment& Other) const; 29 | }; 30 | --------------------------------------------------------------------------------