Files
UnrealEngineUWP/Engine/Source/Editor/AnimGraph/Private/AnimGraphNode_SubInstance.cpp

465 lines
13 KiB
C++
Raw Normal View History

Copying //UE4/Dev-Framework to //UE4/Dev-Main (Source: //UE4/Dev-Framework @ 3038004) #rb None #lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 3021479 on 2016/06/21 by Marc.Audy Fix child actor properties set in the parent's construction script from being wiped out (4.12) #jira UE-31956 Change 3021703 on 2016/06/21 by Marc.Audy Fix crash due to copying properties to registered components and then reregistering them. (4.12) #jira UE-31973 Change 3022105 on 2016/06/21 by Jeremy.Ernst -new test assets for James for PSD node Change 3022621 on 2016/06/22 by James.Golding Add AnimBP for testing PSD Change 3022622 on 2016/06/22 by James.Golding Only restrict anim asset selection for UAnimGraphNode_AssetPlayerBase derived nodes Change 3022656 on 2016/06/22 by James.Golding UE-30537 Fix solid collision geom drawing not working when mirrored Change 3022657 on 2016/06/22 by James.Golding Don't crash in FAnimGraphNodeDetails::OnShouldFilterAnimAsset if AnimAsset doesn't have Skeleton asset registry tag (shouldn't happen, but shouldn't crash) Change 3022663 on 2016/06/22 by James.Golding UE-31283 Additional extensibility for anim and physics PR #2434: Morpheme integration changes (Contributed by NaturalMotionTechnology) Change 3022683 on 2016/06/22 by James.Golding - Change OrientationDriver to always use PoseAsset for target poses - Remove NumPoses from PoseAsset and use GetAssetRegistryTags instead Change 3022891 on 2016/06/22 by mason.seay Test asset for component hit Change 3023203 on 2016/06/22 by mason.seay Updated map to use more noticeable sound assets Change 3023335 on 2016/06/22 by Marc.Audy Use AddReferencedObjects instead of iterating array manuallly Change 3023351 on 2016/06/22 by Ori.Cohen Fix the case where physics hit events were passing the wrong component's bone info to the hit event. #JIRA UE-32376 Change 3023368 on 2016/06/22 by mason.seay Renamed actors in World Outliner Change 3023425 on 2016/06/22 by mason.seay Moved asset to new folder and fixed deprecated node Change 3023429 on 2016/06/22 by mason.seay Disabled collision on proc mesh Change 3023553 on 2016/06/22 by Jon.Nabozny Fix issue where MaxAngularVelocity resets to default on UPrimitiveComponent->BodyInstance. Replicated from CL 3009477. #JIRA UE-31670 Change 3024669 on 2016/06/23 by James.Golding Update PSD test assets (removing unused) Change 3024864 on 2016/06/23 by Marc.Audy Audio Threading! Change 3024877 on 2016/06/23 by James.Golding PR #2375: Allow the creation of custom IStreamingManager (Contributed by bozaro) Change 3024880 on 2016/06/23 by James.Golding PR #2209: Fix UGameplayStatics::*Game*Slot documentation (Contributed by Lectem) Change 3024939 on 2016/06/23 by James.Golding - Add SwingOnly options to OrientationDriver - Move EBoneAxis from AnimNode_RotationMultiplier.h to AnimTypes.h - Calculate gaussian radius per pose, not globally Change 3024940 on 2016/06/23 by James.Golding PoseAsset editor improvements - Replace pose edit box with inline-editable style (with validation) - Add filter highlight - Show curve values for each pose when selected - Add different background for curve list - Filter box only searches pose list, moved location to indicate that Change 3024949 on 2016/06/23 by James.Golding Small update to PSD test AnimBP Change 3025002 on 2016/06/23 by Ori.Cohen Fix the case where fixed frame rate combined with t.maxfps would lead to negative delta time. We now take the min of t.maxfps and fixed frame rate. #JIRA UE-32219 Change 3025214 on 2016/06/23 by mason.seay Updated Character Movement Map Change 3025319 on 2016/06/23 by Ori.Cohen Make sure changing skeletal mesh updates the bone index on body instances already created. Change 3025435 on 2016/06/23 by Ori.Cohen Fix welded bodies not updating their collision profile when calling SetCollisionProfile #JIRA UE-32394 Change 3025581 on 2016/06/23 by mason.seay Test asset for slicing procedural mesh Change 3026483 on 2016/06/24 by Marc.Audy Don't reschedule multiple times tick functions used as prerequisites #jira UE-32414 Change 3026498 on 2016/06/24 by mason.seay Updating blueprint for bug repro Change 3026547 on 2016/06/24 by Thomas.Sarkanen Fixed crash in FKismetDebugUtilities::GetWatchText() Crash reported by this UDN: https://udn.unrealengine.com/questions/300110/crash-in-kismetdebugutilities-when-printing-watchp.html Change 3026598 on 2016/06/24 by James.Golding Double clicking on poses now toggles them between 1.0 and 0.0 strength Change 3026768 on 2016/06/24 by Marc.Audy Change up suspend audio thread cvar sink warning about disabled threading to avoid inappropriate warnings #jira UE-32468 Change 3026802 on 2016/06/24 by Lina.Halper #Pose Asset work # additive blending change : additive scale is saved to [targetscale/sourcescale - 1] where it used to be [targetscale/sourcescale] since blending doesn't work with it - Blending should work once we save to [targetscale/sourcescale - 1] as normal - i.e. if you blend 0.3, it should not shrink the mesh because you applyed additive to 0.3 - When apply the scale to base, it should multiply [additive scale + 1 ] where additive scale is [targetscale/sourcescale - 1] - Changed FTransform::Blend to FTransform::Lerp since it's literally just Lerp. Name Blend should be used for Accumulate but changing the name now is dangerous, so I'm keeping Accumulate but changed Blend to Lerp # pose asset preview fix - made sure it adds to curve, so you don't have to use delegate to apply - PreviewOverride is now added to output curve, so we don't have to apply that curve later - only reason of anim instance delegate is now for normal anim blueprint. #pose asset change - Curve extraction happens with ExtractContext, the output curve is stricly output curve - Pose Asset supports Shrink now, but only shrink if full pose - Added PoseHandler to handle most of common stuff between different pose nodes - Still have to work on how to update pose asset - wip - todo: clean up single node player to handle pose asset in a function #code review:Martin.Wilson, James.Golding Change 3026978 on 2016/06/24 by Lina.Halper - Delete DrivePose Curve type - Renamed TriggerEvent to DriveAttribute for consistency - Replaced drive pose to drive attribute - right now it can't have 0 curve type flags, so everything is DriveAttribute #code review: James.Golding, Martin.Wilson Change 3027113 on 2016/06/24 by mason.seay Test Pose Assets Change 3027454 on 2016/06/24 by Aaron.McLeran UE-32492 Fix for cleaning up xaudio2 source voices and xaudio2 buffers if the source fails to initialize https://answers.unrealengine.com/questions/441080/audio-crash.html http://crashreporter/Crashes/Show/5689478 Change 3027519 on 2016/06/24 by Lina.Halper Reverted FTransform name change as that causes compile errors due to lack of deprecated messages - not worth to keep the old functions and add new one #code review: Martin.Wilson Change 3027887 on 2016/06/25 by Lina.Halper Fix clang build warning Change 3028703 on 2016/06/27 by Lukasz.Furman gameplay debugger config improvements, categories and extensions can now be toggled while PIE/simulate is active #ue4 Change 3028792 on 2016/06/27 by Lukasz.Furman compilation fix for gameplay debugger Change 3028950 on 2016/06/27 by Lukasz.Furman compilation fix for gameplay debugger Change 3029003 on 2016/06/27 by Ori.Cohen Added PhysicalAnimation component that allows us to physically drive skeletal mesh from animation Change 3029019 on 2016/06/27 by Lina.Halper Update pose from source asset Change 3029094 on 2016/06/27 by Marc.Audy If Player->StartSpot is null disregard ShouldSpawnAtStartPoint returned true. Change 3029308 on 2016/06/27 by Jeremy.Ernst -adding test animation for PSD node. Has morphs built in to compare against driver result Change 3029372 on 2016/06/27 by Marc.Audy Fix compile error after merge Also just fix the logic to be explicit rather than using suppression for static analysis warning Change 3029493 on 2016/06/27 by Ori.Cohen Move PhysicsAsset.h out of public engine header. Change 3029550 on 2016/06/27 by Lina.Halper Fix crash with Nan when additive blending of poses\ Change 3029659 on 2016/06/27 by Aaron.McLeran Adding new minor feature to add new concurrency mode - stop by lowest priorty but prevent new rather than stop oldest. Change 3029673 on 2016/06/27 by Aaron.McLeran #JIRA FORT-24936 Disable EQ on AMD machines since it is causing them to stall and starve other important threads. This is only a temporary solution until a better one is found. Implementation in CL 3024124 Change 3030470 on 2016/06/28 by Ori.Cohen Fix OnConstraintBrokenWrapper being accidently wrapped with if WITH_CLOTHING #JIRA UE-32561 Change 3030586 on 2016/06/28 by Lina.Halper Preview curve fix from anim curve viewer #code review: Martin.Wilson Change 3031054 on 2016/06/28 by Aaron.McLeran #jira UE-32566 Incorrectly copied CL 3024124 to Dev-Framework Change 3031535 on 2016/06/28 by mason.seay Re-saving concurrency asset Change 3031691 on 2016/06/28 by Marc.Audy Fix stat sounds not turning on correctly unless a sort was specified #jira UE-32597 Change 3031883 on 2016/06/28 by Zak.Middleton #ue4 - Prevent bNotifyJumpApex from being editable, and clean up comments. Change 3031898 on 2016/06/28 by Zak.Middleton #ue4 - Fix mesh smoothing on clients popping briefly when crouching. This was due to the change in 4.12 where we started smoothing Z location rather than always zeroing it (in certain movement modes). #udn https://udn.unrealengine.com/questions/300494/networked-crouching-jitter.html Change 3032539 on 2016/06/29 by Marc.Audy Don't destroy AudioDevices before draining audio commands and stopping audio thread #jira UE-32611 Change 3032633 on 2016/06/29 by Marc.Audy In the same way that SpawnActor doesn't work during world teardown, don't allow new components to be added which could introduce recursion within the destroy logic. #jira UE-32574 Change 3032644 on 2016/06/29 by Lina.Halper - Fixed issue where pose node evaluator doesn't show up in the menu with asset - it showed twice of pose node (none) - jira UE-32358 - Fixed issue where anim evaluator/pose asset by name/blend space evaluator failed to display assets properly - jira UE-32359 - support create pose menu from create asset - UE-32596 - added create pose asset from current pose - update source should refresh list - UE-32576 - fixed blendspace to be in the blendspaces category Change 3032847 on 2016/06/29 by Tom.Looman Added PredictProjectilePath and SuggestProjectileVelocity_MediumArc utilities to UGameplayStatics. Updated SuggestProjectileVelocity to avoid floating point precision errors on gravity value comparison. #jira UE-32103 Change 3033124 on 2016/06/29 by Jon.Nabozny Fix issue where InstancedStaticMeshComponent InstanceBodies don't move when the mesh is updated. #JIRA: UE-13673 Change 3033155 on 2016/06/29 by Lina.Halper - montage is playing and montage is pure - made montage parameter to be mostly const (except play), and made it consistently pointer Change 3033157 on 2016/06/29 by Lina.Halper Check in missing file Change 3033456 on 2016/06/29 by Lukasz.Furman fixed path following changes broken by merge #ue4 Change 3033956 on 2016/06/30 by bruce.nesbit PR #2483: Fix/Improvment Move Component To Rotation (Contributed by Nachtmahr87) #test PIE Change 3034019 on 2016/06/30 by Benn.Gallagher Anim blueprint sub-instances, allowing anim blueprints to run within anim blueprints and expose parameters back to the "parent" instance. Caveats: - Slots and state machine names are unique and boxed per instance, meaning playing a montage on a slot will only affect slots in the outermost instance and state machine getters are local to their instance. #jira UEFW-1 Change 3034085 on 2016/06/30 by Benn.Gallagher Missed LOCTEXT_NAMESPACE undefs from the subinstance checkin, for some reason doesn't get caught on windows, likely how the unity files are stuck together. Change 3034162 on 2016/06/30 by Martin.Wilson Refactor bone reference widget so that selection tree can be used seperately Change 3034205 on 2016/06/30 by Lina.Halper #ANIM: fix issue with addiitve blending with non-full weight applying wrong scale #jira: UE-32643, UE-32593 Change 3034339 on 2016/06/30 by James.Golding Moving functionality from Skeleton Curves tab into Anim Curve Viewer tab Change 3034426 on 2016/06/30 by Martin.Wilson CIS Fix Change 3034629 on 2016/06/30 by Lina.Halper Support non-zero curves to be stippred out upon importing Change 3035863 on 2016/07/01 by Marc.Audy When pasting components in to a blueprint, make the relative position and rotation of the root 0,0,0 #jira UE-31344 Change 3035916 on 2016/07/01 by Jon.Nabozny Fixed PaperGroupedSprite doesn't update InstanceBodies data in physics. This change is related to CL-3033124 Change 3035973 on 2016/07/01 by Lukasz.Furman fixed hash function for FRecastDebugPathfindingNode #ue4 Change 3036024 on 2016/07/01 by Zak.Middleton #ue4 - Avoid filling in array in AActor::FixupNativeActorComponents() unless we detect a null scene component. Avoid copying TWeakObjectPtr in ValidateDeferredTransformCache(). Change 3036157 on 2016/07/01 by Marc.Audy Protect against running commands on game thread when the audio device has already been freed #jira UE-32611 Change 3036178 on 2016/07/01 by Marc.Audy Don't bitpack the gamethread specific boolean. Change 3036906 on 2016/07/04 by bruce.nesbit Fixed a typo in HasDefaultBuildSettings - (bCompi8leLeanAndMeanUE should be bCompileLeanAndMeanUE) #tests Compiled Change 3036929 on 2016/07/04 by James.Golding UE-32405 Label Rotator components X/Y/Z instead of Roll/Pitch/Yaw Change 3036930 on 2016/07/04 by James.Golding UE-30414 Move constraint warnings to Message Log Change 3036931 on 2016/07/04 by James.Golding PR #2427: SkeletalMeshMerge now can transform the UVs of the source meshes. (Contributed by Bogustus) Change 3037123 on 2016/07/04 by Ori.Cohen Added physical animation preview in PhAT as well as physical animation profiles. Change 3037420 on 2016/07/05 by Jurre.deBaare Moved BodySetup_DEPRECATED out of WITH_EDITORONLY_DATA since it's being used in postload (fixes shipping builds) #jira UE-32771 Change 3037702 on 2016/07/05 by Thomas.Sarkanen Copying change 3037701 from Release-4.12: Fixed crash when viewing uncompressed animation Made sure that objects required by the animation evaluation are set up when performing game-thread side work in the editor. #jira UE-32715 - Crash when selecting "show" > "uncompressed animation" in Persona Change 3037837 on 2016/07/05 by Marc.Audy sound stats will now still be displayed when creating a new audio device #jira UE-32743 [CL 3038035 by Marc Audy in Main branch]
2016-07-05 14:25:57 -04:00
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "AnimGraphPrivatePCH.h"
#include "AnimGraphNode_SubInstance.h"
#include "CompilerResultsLog.h"
#include "PropertyEditing.h"
#include "IPropertyUtilities.h"
#include "Animation/AnimNode_SubInput.h"
#include "PropertyCustomizationHelpers.h"
#include "ScopedTransaction.h"
#include "Animation/AnimInstance.h"
#define LOCTEXT_NAMESPACE "SubInstanceNode"
namespace SubInstanceGraphNodeConstants
{
FLinearColor TitleColor(0.2f, 0.2f, 0.8f);
}
FLinearColor UAnimGraphNode_SubInstance::GetNodeTitleColor() const
{
return SubInstanceGraphNodeConstants::TitleColor;
}
FText UAnimGraphNode_SubInstance::GetTooltipText() const
{
return LOCTEXT("ToolTip", "Runs a sub-anim instance to process animation");
}
FText UAnimGraphNode_SubInstance::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
UClass* TargetClass = *Node.InstanceClass;
FFormatNamedArguments Args;
Args.Add(TEXT("NodeTitle"), LOCTEXT("Title", "Sub Anim Instance"));
Args.Add(TEXT("TargetClass"), TargetClass ? FText::FromString(TargetClass->GetName()) : LOCTEXT("ClassNone", "None"));
if(TitleType == ENodeTitleType::MenuTitle)
{
return LOCTEXT("NodeTitle", "Sub Anim Instance");
}
if(TitleType == ENodeTitleType::ListView)
{
return FText::Format(LOCTEXT("TitleFormat", "{NodeTitle} - Target Class: {TargetClass}"), Args);
}
else
{
return FText::Format(LOCTEXT("TitleFormat", "{NodeTitle}\nTarget Class: {TargetClass}"), Args);
}
}
void UAnimGraphNode_SubInstance::ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog)
{
UAnimBlueprint* AnimBP = CastChecked<UAnimBlueprint>(GetBlueprint());
UObject* OriginalNode = MessageLog.FindSourceObject(this);
// Check we have a class set
if(!*Node.InstanceClass)
{
MessageLog.Error(TEXT("Sub instance node @@ has no valid instance class to spawn."), this);
}
// Check for cycles from other sub instance nodes
TArray<UEdGraph*> Graphs;
AnimBP->GetAllGraphs(Graphs);
for(UEdGraph* Graph : Graphs)
{
TArray<UAnimGraphNode_SubInstance*> SubInstanceNodes;
Graph->GetNodesOfClass(SubInstanceNodes);
for(UAnimGraphNode_SubInstance* SubInstanceNode : SubInstanceNodes)
{
if(SubInstanceNode == OriginalNode)
{
continue;
}
FAnimNode_SubInstance& InnerNode = SubInstanceNode->Node;
if(*InnerNode.InstanceClass && *InnerNode.InstanceClass == *Node.InstanceClass)
{
MessageLog.Error(TEXT("Node @@ and node @@ both target the same class @@, causing a sub instance loop."), this, SubInstanceNode, *Node.InstanceClass);
}
}
}
// Check we don't try to spawn our own blueprint
if(*Node.InstanceClass == AnimBP->GetAnimBlueprintGeneratedClass())
{
MessageLog.Error(TEXT("Sub instance node @@ targets instance class @@ which it is inside, this would cause a loop."), this, AnimBP->GetAnimBlueprintGeneratedClass());
}
}
void UAnimGraphNode_SubInstance::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
{
Super::ReallocatePinsDuringReconstruction(OldPins);
UClass* TargetClass = *Node.InstanceClass;
if(!TargetClass)
{
// Nothing to search for properties
return;
}
// Need the schema to extract pin types
const UEdGraphSchema_K2* Schema = CastChecked<UEdGraphSchema_K2>(GetSchema());
bool bShowPose = false;
// Scan the target class for a sub input node, we only want to show the pose input if
// we have that node available
for(TFieldIterator<UProperty> It(TargetClass); It; ++It)
{
UProperty* CurrentProp = *It;
if(UStructProperty* StructProp = Cast<UStructProperty>(CurrentProp))
{
if(StructProp->Struct->IsChildOf(FAnimNode_SubInput::StaticStruct()))
{
// Found a pose input
bShowPose = true;
break;
}
}
}
if(bShowPose)
{
if(UProperty* PoseProperty = FindField<UProperty>(FAnimNode_SubInstance::StaticStruct(), GET_MEMBER_NAME_CHECKED(FAnimNode_SubInstance, InPose)))
{
FEdGraphPinType PinType;
if(Schema->ConvertPropertyToPinType(PoseProperty, PinType))
{
UEdGraphPin* NewPin = CreatePin(EEdGraphPinDirection::EGPD_Input, PinType, PoseProperty->GetName());
NewPin->PinFriendlyName = PoseProperty->GetDisplayNameText();
CustomizePinData(NewPin, PoseProperty->GetFName(), INDEX_NONE);
}
}
}
// Grab the list of properties we can expose
TArray<UProperty*> ExposablePropeties;
GetExposableProperties(ExposablePropeties);
// We'll track the names we encounter by removing from this list, if anything remains the properties
// have been removed from the target class and we should remove them too
TArray<FName> BeginExposableNames = KnownExposableProperties;
for(UProperty* Property : ExposablePropeties)
{
FName PropertyName = Property->GetFName();
BeginExposableNames.Remove(PropertyName);
if(!KnownExposableProperties.Contains(PropertyName))
{
// New property added to the target class
KnownExposableProperties.Add(PropertyName);
}
if(ExposedPropertyNames.Contains(PropertyName))
{
FEdGraphPinType PinType;
verify(Schema->ConvertPropertyToPinType(Property, PinType));
UEdGraphPin* NewPin = CreatePin(EEdGraphPinDirection::EGPD_Input, PinType, Property->GetName());
NewPin->PinFriendlyName = Property->GetDisplayNameText();
CustomizePinData(NewPin, PropertyName, INDEX_NONE);
}
}
// Remove any properties that no longer exist on the target class
for(FName& RemovedPropertyName : BeginExposableNames)
{
KnownExposableProperties.Remove(RemovedPropertyName);
ExposedPropertyNames.Remove(RemovedPropertyName);
}
}
void UAnimGraphNode_SubInstance::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
bool bRequiresNodeReconstruct = false;
UProperty* ChangedProperty = PropertyChangedEvent.Property;
if(ChangedProperty)
{
if(ChangedProperty->GetFName() == GET_MEMBER_NAME_CHECKED(FAnimNode_SubInstance, InstanceClass))
{
bRequiresNodeReconstruct = true;
RebuildExposedProperties(*Node.InstanceClass);
}
}
if(bRequiresNodeReconstruct)
{
ReconstructNode();
}
}
void UAnimGraphNode_SubInstance::GetInstancePinProperty(const UClass* InOwnerInstanceClass, UEdGraphPin* InInputPin, UProperty*& OutProperty)
{
// The actual name of the instance property
FString FullName = GetPinTargetVariableName(InInputPin);
if(UProperty* Property = FindField<UProperty>(InOwnerInstanceClass, *FullName))
{
OutProperty = Property;
}
else
{
OutProperty = nullptr;
}
}
FString UAnimGraphNode_SubInstance::GetPinTargetVariableName(const UEdGraphPin* InPin) const
{
return TEXT("__SUBINSTANCE_") + InPin->PinName + TEXT("_") + NodeGuid.ToString();
}
void UAnimGraphNode_SubInstance::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
Super::CustomizeDetails(DetailBuilder);
TArray<UProperty*> ExposableProperties;
GetExposableProperties(ExposableProperties);
if(ExposableProperties.Num() > 0)
{
IDetailCategoryBuilder& CategoryBuilder = DetailBuilder.EditCategory(FName(TEXT("Sub Instance Properties")));
for(UProperty* Property : ExposableProperties)
{
FDetailWidgetRow& WidgetRow = CategoryBuilder.AddCustomRow(FText::FromString(Property->GetName()));
FName PropertyName = Property->GetFName();
FText PropertyTypeText = GetPropertyTypeText(Property);
FFormatNamedArguments Args;
Args.Add(TEXT("PropertyName"), FText::FromName(PropertyName));
Args.Add(TEXT("PropertyType"), PropertyTypeText);
FText TooltipText = FText::Format(LOCTEXT("PropertyTooltipText", "{PropertyName}\nType: {PropertyType}"), Args);
WidgetRow.NameContent()
[
SNew(STextBlock)
.Text(FText::FromString(Property->GetName()))
.ToolTipText(TooltipText)
];
WidgetRow.ValueContent()
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text(LOCTEXT("ExposePropertyValue", "Expose: "))
]
+SHorizontalBox::Slot()
[
SNew(SCheckBox)
.IsChecked_UObject(this, &UAnimGraphNode_SubInstance::IsPropertyExposed, PropertyName)
.OnCheckStateChanged_UObject(this, &UAnimGraphNode_SubInstance::OnPropertyExposeCheckboxChanged, PropertyName)
]
];
}
}
TSharedRef<IPropertyHandle> ClassHandle = DetailBuilder.GetProperty(TEXT("Node.InstanceClass"), GetClass());
if(ClassHandle->IsValidHandle())
{
ClassHandle->SetOnPropertyValueChanged(FSimpleDelegate::CreateUObject(this, &UAnimGraphNode_SubInstance::OnInstanceClassChanged, &DetailBuilder));
}
ClassHandle->MarkHiddenByCustomization();
IDetailCategoryBuilder& CategoryBuilder = DetailBuilder.EditCategory(FName(TEXT("Settings")));
FDetailWidgetRow& ClassWidgetRow = CategoryBuilder.AddCustomRow(LOCTEXT("FilterString", "Instance Class"));
ClassWidgetRow.NameContent()
[
ClassHandle->CreatePropertyNameWidget()
];
ClassWidgetRow.ValueContent()
[
SNew(SObjectPropertyEntryBox)
.ObjectPath_UObject(this, &UAnimGraphNode_SubInstance::GetCurrentInstanceBlueprintPath)
.AllowedClass(UAnimBlueprint::StaticClass())
.NewAssetFactories(TArray<UFactory*>())
.OnShouldFilterAsset(FOnShouldFilterAsset::CreateUObject(this, &UAnimGraphNode_SubInstance::OnShouldFilterInstanceBlueprint))
.OnObjectChanged(FOnSetObject::CreateUObject(this, &UAnimGraphNode_SubInstance::OnSetInstanceBlueprint, ClassHandle))
];
}
FText UAnimGraphNode_SubInstance::GetPropertyTypeText(UProperty* Property)
{
FText PropertyTypeText;
if(UStructProperty* StructProperty = Cast<UStructProperty>(Property))
{
PropertyTypeText = StructProperty->Struct->GetDisplayNameText();
}
else if(UObjectProperty* ObjectProperty = Cast<UObjectProperty>(Property))
{
PropertyTypeText = ObjectProperty->PropertyClass->GetDisplayNameText();
}
else if(UClass* PropClass = Property->GetClass())
{
PropertyTypeText = PropClass->GetDisplayNameText();
}
else
{
PropertyTypeText = LOCTEXT("PropertyTypeUnknown", "Unknown");
}
return PropertyTypeText;
}
void UAnimGraphNode_SubInstance::RebuildExposedProperties(UClass* InNewClass)
{
ExposedPropertyNames.Empty();
KnownExposableProperties.Empty();
if(InNewClass)
{
TArray<UProperty*> ExposableProperties;
GetExposableProperties(ExposableProperties);
for(UProperty* Property : ExposableProperties)
{
KnownExposableProperties.Add(Property->GetFName());
}
}
}
ECheckBoxState UAnimGraphNode_SubInstance::IsPropertyExposed(FName PropertyName) const
{
return ExposedPropertyNames.Contains(PropertyName) ? ECheckBoxState::Checked : ECheckBoxState::Unchecked;
}
void UAnimGraphNode_SubInstance::OnPropertyExposeCheckboxChanged(ECheckBoxState NewState, FName PropertyName)
{
if(NewState == ECheckBoxState::Checked)
{
ExposedPropertyNames.AddUnique(PropertyName);
}
else if(NewState == ECheckBoxState::Unchecked)
{
ExposedPropertyNames.Remove(PropertyName);
}
ReconstructNode();
}
void UAnimGraphNode_SubInstance::OnInstanceClassChanged(IDetailLayoutBuilder* DetailBuilder)
{
if(DetailBuilder)
{
DetailBuilder->ForceRefreshDetails();
}
}
FString UAnimGraphNode_SubInstance::GetCurrentInstanceBlueprintPath() const
{
UClass* InstanceClass = *Node.InstanceClass;
if(InstanceClass)
{
UBlueprint* ActualBlueprint = UBlueprint::GetBlueprintFromClass(InstanceClass);
if(ActualBlueprint)
{
return ActualBlueprint->GetPathName();
}
}
return FString();
}
bool UAnimGraphNode_SubInstance::OnShouldFilterInstanceBlueprint(const FAssetData& AssetData) const
{
if(const FString* SkeletonName = AssetData.TagsAndValues.Find(TEXT("TargetSkeleton")))
{
if(UAnimBlueprint* CurrentBlueprint = Cast<UAnimBlueprint>(GetBlueprint()))
{
FString TargetSkeletonName = FString::Printf(TEXT("%s'%s'"), *CurrentBlueprint->TargetSkeleton->GetClass()->GetName(), *CurrentBlueprint->TargetSkeleton->GetPathName());
return *SkeletonName != TargetSkeletonName;
}
}
return false;
}
void UAnimGraphNode_SubInstance::OnSetInstanceBlueprint(const FAssetData& AssetData, TSharedRef<IPropertyHandle> InstanceClassPropHandle)
{
if(UAnimBlueprint* Blueprint = Cast<UAnimBlueprint>(AssetData.GetAsset()))
{
FScopedTransaction Transaction(LOCTEXT("SetBP", "Set Instance Blueprint"));
Modify();
InstanceClassPropHandle->SetValue(Blueprint->GetAnimBlueprintGeneratedClass());
}
}
UObject* UAnimGraphNode_SubInstance::GetJumpTargetForDoubleClick() const
{
UClass* InstanceClass = *Node.InstanceClass;
if(InstanceClass)
{
return InstanceClass->ClassGeneratedBy;
}
return nullptr;
}
bool UAnimGraphNode_SubInstance::HasExternalDependencies(TArray<class UStruct*>* OptionalOutput /*= NULL*/) const
{
UClass* InstanceClassToUse = *Node.InstanceClass;
// Add our instance class... If that changes we need a recompile
if(InstanceClassToUse && OptionalOutput)
{
OptionalOutput->AddUnique(InstanceClassToUse);
}
bool bSuperResult = Super::HasExternalDependencies(OptionalOutput);
return InstanceClassToUse || bSuperResult;
}
void UAnimGraphNode_SubInstance::GetExposableProperties(TArray<UProperty*>& OutExposableProperties) const
{
OutExposableProperties.Empty();
UClass* TargetClass = *Node.InstanceClass;
if(TargetClass)
{
const UEdGraphSchema_K2* Schema = CastChecked<UEdGraphSchema_K2>(GetSchema());
for(TFieldIterator<UProperty> It(TargetClass, EFieldIteratorFlags::IncludeSuper); It; ++It)
{
UProperty* CurProperty = *It;
FEdGraphPinType PinType;
if(CurProperty->HasAllPropertyFlags(CPF_Edit | CPF_BlueprintVisible) && CurProperty->HasAllFlags(RF_Public) && Schema->ConvertPropertyToPinType(CurProperty, PinType))
{
OutExposableProperties.Add(CurProperty);
}
}
}
}
#undef LOCTEXT_NAMESPACE