void UEdGraphPin::MakeLinkTo(UEdGraphPin* ToPin) { Modify(); if (ToPin != NULL) { ToPin->Modify(); // Make sure we don't already link to it if (!LinkedTo.Contains(ToPin)) { UEdGraphNode* MyNode = GetOwningNode(); // Check that the other pin does not link to us ensureMsg(!ToPin->LinkedTo.Contains(this), *GetLinkInfoString( LOCTEXT("MakeLinkTo", "MakeLinkTo").ToString(), LOCTEXT("IsLinked", "is linked with pin").ToString(), ToPin)); ensureMsg(MyNode->GetOuter() == ToPin->GetOwningNode()->GetOuter(), *GetLinkInfoString( LOCTEXT("MakeLinkTo", "MakeLinkTo").ToString(), LOCTEXT("OuterMismatch", "has a different outer than pin").ToString(), ToPin)); // Ensure both pins belong to the same graph // Add to both lists LinkedTo.Add(ToPin); ToPin->LinkedTo.Add(this); GraphPinHelpers::EnableAllConnectedNodes(MyNode); GraphPinHelpers::EnableAllConnectedNodes(ToPin->GetOwningNode()); } } }
void UAnimSequenceBase::UpdateAnimNotifyTrackCache() { SortNotifies(); for (int32 TrackIndex=0; TrackIndex<AnimNotifyTracks.Num(); ++TrackIndex) { AnimNotifyTracks[TrackIndex].Notifies.Empty(); } for (int32 NotifyIndex = 0; NotifyIndex<Notifies.Num(); ++NotifyIndex) { int32 TrackIndex = Notifies[NotifyIndex].TrackIndex; if (AnimNotifyTracks.IsValidIndex(TrackIndex)) { AnimNotifyTracks[TrackIndex].Notifies.Add(&Notifies[NotifyIndex]); } else { // this notifyindex isn't valid, delete // this should not happen, but if it doesn, find best place to add ensureMsg(0, TEXT("AnimNotifyTrack: Wrong indices found")); AnimNotifyTracks[0].Notifies.Add(&Notifies[NotifyIndex]); } } // notification broadcast OnNotifyChanged.Broadcast(); }
FPinConnectionResponse UEdGraphSchema::CopyPinLinks(UEdGraphPin& CopyFromPin, UEdGraphPin& CopyToPin, bool bIsIntermediateCopy) const { #if WITH_EDITOR ensureMsg(bIsIntermediateCopy || !CopyToPin.GetOwningNode()->GetGraph()->HasAnyFlags(RF_Transient), TEXT("When copying to an Intermediate pin, use FKismetCompilerContext::CopyPinLinksToIntermediate() instead of UEdGraphSchema::CopyPinLinks()")); #endif // #if WITH_EDITOR FPinConnectionResponse FinalResponse = FPinConnectionResponse(CONNECT_RESPONSE_MAKE, TEXT("")); for (int32 i=0; i<CopyFromPin.LinkedTo.Num(); i++) { UEdGraphPin* NewLink = CopyFromPin.LinkedTo[i]; FPinConnectionResponse Response = CanCreateConnection(&CopyToPin, NewLink); if (Response.CanSafeConnect()) { CopyToPin.MakeLinkTo(NewLink); } else { FinalResponse = Response; } } CopyToPin.DefaultValue = CopyFromPin.DefaultValue; CopyToPin.DefaultObject = CopyFromPin.DefaultObject; CopyToPin.DefaultTextValue = CopyFromPin.DefaultTextValue; return FinalResponse; }
FPinConnectionResponse UEdGraphSchema::MovePinLinks(UEdGraphPin& MoveFromPin, UEdGraphPin& MoveToPin, bool bIsIntermediateMove) const { #if WITH_EDITOR ensureMsg(bIsIntermediateMove || !MoveToPin.GetOwningNode()->GetGraph()->HasAnyFlags(RF_Transient), TEXT("When moving to an Intermediate pin, use FKismetCompilerContext::MovePinLinksToIntermediate() instead of UEdGraphSchema::MovePinLinks()")); #endif // #if WITH_EDITOR FPinConnectionResponse FinalResponse = FPinConnectionResponse(CONNECT_RESPONSE_MAKE, TEXT("")); // First copy the current set of links TArray<UEdGraphPin*> CurrentLinks = MoveFromPin.LinkedTo; // Then break all links at pin we are moving from MoveFromPin.BreakAllPinLinks(); // Try and make each new connection for (int32 i=0; i<CurrentLinks.Num(); i++) { UEdGraphPin* NewLink = CurrentLinks[i]; FPinConnectionResponse Response = CanCreateConnection(&MoveToPin, NewLink); if(Response.CanSafeConnect()) { MoveToPin.MakeLinkTo(NewLink); } else { FinalResponse = Response; } } // Move over the default values MoveToPin.DefaultValue = MoveFromPin.DefaultValue; MoveToPin.DefaultObject = MoveFromPin.DefaultObject; MoveToPin.DefaultTextValue = MoveFromPin.DefaultTextValue; return FinalResponse; }
void SGraphEditorImpl::SelectAllNodes() { FGraphPanelSelectionSet NewSet; for (int32 NodeIndex = 0; NodeIndex < EdGraphObj->Nodes.Num(); ++NodeIndex) { UEdGraphNode* Node = EdGraphObj->Nodes[NodeIndex]; ensureMsg(Node->IsValidLowLevel(), TEXT("Node is invalid")); NewSet.Add(Node); } GraphPanel->SelectionManager.SetSelectionSet(NewSet); }
void UAnimInstance::ApplyAdditiveSequence(const struct FA2Pose& BasePose,const struct FA2Pose& AdditivePose,float Alpha,struct FA2Pose& Blended) { if (Blended.Bones.Num() < BasePose.Bones.Num()) { // see if this happens ensureMsg (false, TEXT("BasePose has more bones than Blended pose")); //@hack Blended.Bones.AddUninitialized(BasePose.Bones.Num() - Blended.Bones.Num()); } float BlendWeight = FMath::Clamp<float>(Alpha, 0.f, 1.f); FAnimationRuntime::BlendAdditivePose(BasePose.Bones, AdditivePose.Bones, BlendWeight, RequiredBones, Blended.Bones); }
void UEdGraphPin::BreakLinkTo(UEdGraphPin* ToPin) { Modify(); if (ToPin != NULL) { ToPin->Modify(); // If we do indeed link to the passed in pin... if (LinkedTo.Contains(ToPin)) { LinkedTo.Remove(ToPin); // Check that the other pin links to us ensureMsg(ToPin->LinkedTo.Contains(this), *GetLinkInfoString( LOCTEXT("BreakLinkTo", "BreakLinkTo").ToString(), LOCTEXT("NotLinked", "not reciprocally linked with pin").ToString(), ToPin) ); ToPin->LinkedTo.Remove(this); } else { // Check that the other pin does not link to us ensureMsg(!ToPin->LinkedTo.Contains(this), *GetLinkInfoString( LOCTEXT("MakeLinkTo", "MakeLinkTo").ToString(), LOCTEXT("IsLinked", "is linked with pin").ToString(), ToPin)); } } }
void UAnimInstance::BlendSequences(const FA2Pose& Pose1, const FA2Pose& Pose2, float Alpha, FA2Pose& Result) { SCOPE_CYCLE_COUNTER(STAT_AnimNativeBlendPoses); const FTransformArrayA2* Children[2]; float Weights[2]; Children[0] = &(Pose1.Bones); Children[1] = &(Pose2.Bones); Alpha = FMath::Clamp<float>(Alpha, 0.0f, 1.0f); Weights[0] = 1.0f - Alpha; Weights[1] = Alpha; if (Result.Bones.Num() < Pose1.Bones.Num()) { ensureMsg (false, TEXT("Source Pose has more bones than Target Pose")); //@hack Result.Bones.AddUninitialized(Pose1.Bones.Num() - Result.Bones.Num()); } FAnimationRuntime::BlendPosesTogether(2, Children, Weights, RequiredBones, /*out*/ Result.Bones); }
//------------------------------------------------------------------------------ bool FBlueprintActionDatabaseRegistrar::AddActionToDatabase(UObject const* ActionKey, UBlueprintNodeSpawner* NodeSpawner) { ensureMsg(NodeSpawner->NodeClass == GeneratingClass, TEXT("We expect a nodes to add only spawners for its own type... Maybe a sub-class is adding nodes it shouldn't?")); if (IsOpenForRegistration(ActionKey)) { ActionKey = BlueprintActionDatabaseRegistrarImpl::ResolveActionKey(ActionKey); if (ActionKey == nullptr) { ActionKey = GeneratingClass; } FBlueprintActionDatabase::FActionList& ActionList = ActionDatabase.FindOrAdd(ActionKey); int32* QueuedIndex = ActionPrimingQueue.Find(ActionKey); if (QueuedIndex == nullptr) { int32 PrimingIndex = ActionList.Num(); ActionPrimingQueue.Add(ActionKey, PrimingIndex); } ActionList.Add(NodeSpawner); return true; } return false; }
void SKismetInspector::UpdateFromObjects(const TArray<UObject*>& PropertyObjects, struct FKismetSelectionInfo& SelectionInfo, const FShowDetailsOptions& Options) { // If we're using the unified blueprint editor, there's not an explicit point where // we ender a kind of component editing mode, so instead, just look at what we're selecting. // If we select a component, then enable the customization. if ( GetDefault<UEditorExperimentalSettings>()->bUnifiedBlueprintEditor ) { bool bEnableComponentCustomization = false; TSharedPtr<FBlueprintEditor> BlueprintEditor = BlueprintEditorPtr.Pin(); if ( BlueprintEditor.IsValid() ) { if ( BlueprintEditor->CanAccessComponentsMode() ) { for ( UObject* PropertyObject : PropertyObjects ) { if ( PropertyObject->IsA<UActorComponent>() ) { bEnableComponentCustomization = true; break; } } } } EnableComponentDetailsCustomization(bEnableComponentCustomization); } PropertyView->OnFinishedChangingProperties().Clear(); PropertyView->OnFinishedChangingProperties().Add( UserOnFinishedChangingProperties ); if (!Options.bForceRefresh) { // Early out if the PropertyObjects and the SelectedObjects are the same bool bEquivalentSets = (PropertyObjects.Num() == SelectedObjects.Num()); if (bEquivalentSets) { // Verify the elements of the sets are equivalent for (int32 i = 0; i < PropertyObjects.Num(); i++) { if (PropertyObjects[i] != SelectedObjects[i].Get()) { bEquivalentSets = false; break; } } } if (bEquivalentSets) { return; } } // Proceed to update SelectedObjects.Empty(); for (auto ObjectIt = PropertyObjects.CreateConstIterator(); ObjectIt; ++ObjectIt) { if (UObject* Object = *ObjectIt) { if (!Object->IsValidLowLevel()) { ensureMsg(false, TEXT("Object in KismetInspector is invalid, see TTP 281915")); continue; } SelectedObjects.Add(Object); if (USCS_Node* SCSNode = Cast<USCS_Node>(Object)) { // Edit the component template UActorComponent* NodeComponent = SCSNode->ComponentTemplate; if (NodeComponent != NULL) { SelectionInfo.ObjectsForPropertyEditing.Add(NodeComponent); SelectionInfo.EditableComponentTemplates.Add(NodeComponent); } } else if (UK2Node* K2Node = Cast<UK2Node>(Object)) { // Edit the component template if it exists if (UActorComponent* Template = K2Node->GetTemplateFromNode()) { SelectionInfo.ObjectsForPropertyEditing.Add(Template); SelectionInfo.EditableComponentTemplates.Add(Template); } // See if we should edit properties of the node if (K2Node->ShouldShowNodeProperties()) { SelectionInfo.ObjectsForPropertyEditing.Add(Object); } } else if (UActorComponent* ActorComponent = Cast<UActorComponent>(Object)) { AActor* Owner = ActorComponent->GetOwner(); if(Owner != NULL && Owner->HasAnyFlags(RF_ClassDefaultObject)) { // We're editing a component that's owned by a CDO, so set the CDO to the property editor (so that propagation works) and then filter to just the component property that we want to edit SelectionInfo.ObjectsForPropertyEditing.AddUnique(Owner); SelectionInfo.EditableComponentTemplates.Add(ActorComponent); } else { // We're editing a component that exists outside of a CDO, so just edit the component instance directly SelectionInfo.ObjectsForPropertyEditing.AddUnique(ActorComponent); } } else { // Editing any UObject* SelectionInfo.ObjectsForPropertyEditing.AddUnique(Object); } } } // By default, no property filtering SelectedObjectProperties.Empty(); // Add to the property filter list for any editable component templates if(SelectionInfo.EditableComponentTemplates.Num()) { for(auto CompIt = SelectionInfo.EditableComponentTemplates.CreateIterator(); CompIt; ++CompIt) { UActorComponent* EditableComponentTemplate = *CompIt; check(EditableComponentTemplate != NULL); // Add all properties belonging to the component template class for(TFieldIterator<UProperty> PropIt(EditableComponentTemplate->GetClass()); PropIt; ++PropIt) { UProperty* Property = *PropIt; check(Property != NULL); AddPropertiesRecursive(Property); } // Attempt to locate a matching property for the current component template for(auto ObjIt = SelectionInfo.ObjectsForPropertyEditing.CreateIterator(); ObjIt; ++ObjIt) { UObject* Object = *ObjIt; check(Object != NULL); if(Object != EditableComponentTemplate) { for(TFieldIterator<UObjectProperty> ObjPropIt(Object->GetClass()); ObjPropIt; ++ObjPropIt) { UObjectProperty* ObjectProperty = *ObjPropIt; check(ObjectProperty != NULL); // If the property value matches the current component template, add it as a selected property for filtering if(EditableComponentTemplate == ObjectProperty->GetObjectPropertyValue_InContainer(Object)) { SelectedObjectProperties.Add(ObjectProperty); } } } } } } PropertyViewTitle = Options.ForcedTitle; bShowComponents = Options.bShowComponents; // Update our context-sensitive editing widget ContextualEditingBorderWidget->SetContent( MakeContextualEditingWidget(SelectionInfo, Options) ); }
void FModuleManager::AddModule(const FName InModuleName) { // Do we already know about this module? If not, we'll create information for this module now. if (!((ensureMsg(InModuleName != NAME_None, TEXT("FModuleManager::AddModule() was called with an invalid module name (empty string or 'None'.) This is not allowed.")) && !Modules.Contains(InModuleName)))) { return; } TSharedRef<FModuleInfo> ModuleInfo(new FModuleInfo()); // Make sure module info is added to known modules and proper delegates are fired on exit. ON_SCOPE_EXIT { FModuleManager::Get().AddModuleToModulesList(InModuleName, ModuleInfo); }; #if !IS_MONOLITHIC FString ModuleNameString = InModuleName.ToString(); TMap<FName, FString> ModulePathMap; FindModulePaths(*ModuleNameString, ModulePathMap); if (ModulePathMap.Num() != 1) { return; } // Add this module to the set of modules that we know about ModuleInfo->OriginalFilename = TMap<FName, FString>::TConstIterator(ModulePathMap).Value(); ModuleInfo->Filename = ModuleInfo->OriginalFilename; // When iterating on code during development, it's possible there are multiple rolling versions of this // module's DLL file. This can happen if the programmer is recompiling DLLs while the game is loaded. In // this case, we want to load the newest iteration of the DLL file, so that behavior is the same after // restarting the application. // NOTE: We leave this enabled in UE_BUILD_SHIPPING editor builds so module authors can iterate on custom modules #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) || (UE_BUILD_SHIPPING && WITH_EDITOR) // In some cases, sadly, modules may be loaded before appInit() is called. We can't cleanly support rolling files for those modules. // First, check to see if the module we added already exists on disk const FDateTime OriginalModuleFileTime = IFileManager::Get().GetTimeStamp(*ModuleInfo->OriginalFilename); if (OriginalModuleFileTime == FDateTime::MinValue()) { return; } const FString ModuleName = *InModuleName.ToString(); const int32 MatchPos = ModuleInfo->OriginalFilename.Find(ModuleName, ESearchCase::IgnoreCase, ESearchDir::FromEnd); if (!ensureMsgf(MatchPos != INDEX_NONE, TEXT("Could not find module name '%s' in module filename '%s'"), *ModuleName, *ModuleInfo->OriginalFilename)) { return; } const int32 SuffixPos = MatchPos + ModuleName.Len(); const FString Prefix = ModuleInfo->OriginalFilename.Left(SuffixPos); const FString Suffix = ModuleInfo->OriginalFilename.Right(ModuleInfo->OriginalFilename.Len() - SuffixPos); const FString ModuleFileSearchString = FString::Printf(TEXT("%s-*%s"), *Prefix, *Suffix); // Search for module files TArray<FString> FoundFiles; IFileManager::Get().FindFiles(FoundFiles, *ModuleFileSearchString, true, false); if (FoundFiles.Num() == 0) { return; } const FString ModuleFileSearchDirectory = FPaths::GetPath(ModuleFileSearchString); FString NewestModuleFilename; bool bFoundNewestFile = FindNewestModuleFile(FoundFiles, OriginalModuleFileTime, ModuleFileSearchDirectory, Prefix, Suffix, NewestModuleFilename); // Did we find a variant of the module file that is newer than our original file? if (!bFoundNewestFile) { // No variants were found that were newer than the original module file name, so // we'll continue to use that! return; } // Update the module working file name to the most recently-modified copy of that module const FString NewestModuleFilePath = ModuleFileSearchDirectory.IsEmpty() ? NewestModuleFilename : (ModuleFileSearchDirectory / NewestModuleFilename); ModuleInfo->Filename = NewestModuleFilePath; #endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST) #endif // !IS_MONOLITHIC }