FString UInterfaceProperty::GetCPPTypeForwardDeclaration() const { checkSlow(InterfaceClass); UClass* ExportClass = InterfaceClass; while (ExportClass && !ExportClass->HasAnyClassFlags(CLASS_Native)) { ExportClass = ExportClass->GetSuperClass(); } check(ExportClass); check(ExportClass->HasAnyClassFlags(CLASS_Interface)); return FString::Printf(TEXT("class I%s;"), *ExportClass->GetName()); }
/** * Returns the text to use for exporting this property to header file. * * @param ExtendedTypeText for property types which use templates, will be filled in with the type * @param CPPExportFlags flags for modifying the behavior of the export */ FString UInterfaceProperty::GetCPPMacroType( FString& ExtendedTypeText ) const { checkSlow(InterfaceClass); UClass* ExportClass = InterfaceClass; while ( ExportClass && !ExportClass->HasAnyClassFlags(CLASS_Native) ) { ExportClass = ExportClass->GetSuperClass(); } check(ExportClass); check(ExportClass->HasAnyClassFlags(CLASS_Interface)); ExtendedTypeText = FString::Printf(TEXT("I%s"), *ExportClass->GetName()); return TEXT("TINTERFACE"); }
FString FComponentEditorUtils::GenerateValidVariableNameFromAsset(UObject* Asset, AActor* ComponentOwner) { int32 Counter = 1; FString AssetName = Asset->GetName(); UClass* Class = Cast<UClass>(Asset); if (Class) { if (!Class->HasAnyClassFlags(CLASS_CompiledFromBlueprint)) { AssetName.RemoveFromEnd(TEXT("Component")); } else { AssetName.RemoveFromEnd("_C"); } } // Try to create a name without any numerical suffix first FString ComponentInstanceName = AssetName; if (ComponentOwner) { while (!IsComponentNameAvailable(ComponentInstanceName, ComponentOwner)) { // Assign the lowest possible numerical suffix ComponentInstanceName = FString::Printf(TEXT("%s%d"), *AssetName, Counter++); } } return ComponentInstanceName; }
UFunction* FindNetServiceFunctionById(int16 RPCId) { UFunction** Function = RPCFunctionMap.Find(RPCId); if (!Function) { for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (Class->IsChildOf(AActor::StaticClass()) && !(Class->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated))) { for (TFieldIterator<UFunction> FuncIt(Class); FuncIt; ++FuncIt) { UFunction* CurFunc = *FuncIt; if (CurFunc->RPCId > 0) { RPCFunctionMap.Add(CurFunc->RPCId, CurFunc); } } } } Function = RPCFunctionMap.Find(RPCId); } return *Function; }
FPrimaryAssetId AAFCueActor::GetPrimaryAssetId() const { FName dupa1 = FPackageName::GetShortFName(GetOutermost()->GetFName()); const AAFCueActor* A = this; return FPrimaryAssetId(FPrimaryAssetType("ActorCue"), dupa1); //if (HasAnyFlags(RF_ClassDefaultObject)) { UClass* SearchNativeClass = GetClass(); while (SearchNativeClass && !SearchNativeClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic)) { SearchNativeClass = SearchNativeClass->GetSuperClass(); } if (SearchNativeClass && SearchNativeClass != GetClass()) { // If blueprint, return native class and asset name } // Native CDO, return nothing return FPrimaryAssetId(); } // Data assets use Class and ShortName by default, there's no inheritance so class works fine //return FPrimaryAssetId(GetClass()->GetFName(), GetFName()); }
void FBlueprintCompileReinstancer::UpdateBytecodeReferences() { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_UpdateBytecodeReferences); if(ClassToReinstance != NULL) { TMap<UObject*, UObject*> FieldMappings; GenerateFieldMappings(FieldMappings); for( auto DependentBP = Dependencies.CreateIterator(); DependentBP; ++DependentBP ) { UClass* BPClass = (*DependentBP)->GeneratedClass; // Skip cases where the class is junk, or haven't finished serializing in yet if( (BPClass == ClassToReinstance) || (BPClass->GetOutermost() == GetTransientPackage()) || BPClass->HasAnyClassFlags(CLASS_NewerVersionExists) || (BPClass->ClassGeneratedBy && BPClass->ClassGeneratedBy->HasAnyFlags(RF_NeedLoad|RF_BeingRegenerated)) ) { continue; } // For each function defined in this blueprint, run through the bytecode, and update any refs from the old properties to the new for( TFieldIterator<UFunction> FuncIter(BPClass, EFieldIteratorFlags::ExcludeSuper); FuncIter; ++FuncIter ) { UFunction* CurrentFunction = *FuncIter; if( CurrentFunction->Script.Num() > 0 ) { FArchiveReplaceObjectRef<UObject> ReplaceAr(CurrentFunction, FieldMappings, /*bNullPrivateRefs=*/ false, /*bIgnoreOuterRef=*/ true, /*bIgnoreArchetypeRef=*/ true); } } } } }
bool UOnlineHotfixManager::HotfixPakIniFile(const FString& FileName) { FConfigFile* ConfigFile = GetConfigFile(FileName); ConfigFile->Combine(FileName); UE_LOG(LogHotfixManager, Log, TEXT("Hotfix merged INI (%s) found in a PAK file"), *FileName); FName IniFileName(*FileName, FNAME_Find); int32 NumObjectsReloaded = 0; const double StartTime = FPlatformTime::Seconds(); // Now that we have a list of classes to update, we can iterate objects and // reload if they match the INI file that was changed for (FObjectIterator It; It; ++It) { UClass* Class = It->GetClass(); if (Class->HasAnyClassFlags(CLASS_Config) && Class->ClassConfigName == IniFileName) { // Force a reload of the config vars It->ReloadConfig(); NumObjectsReloaded++; } } UE_LOG(LogHotfixManager, Log, TEXT("Updating config from %s took %f seconds reloading %d objects"), *FileName, FPlatformTime::Seconds() - StartTime, NumObjectsReloaded); return true; }
void AActor::ResetPropertiesForConstruction() { // Get class CDO AActor* Default = GetClass()->GetDefaultObject<AActor>(); // RandomStream struct name to compare against const FName RandomStreamName(TEXT("RandomStream")); // We don't want to reset references to world object const bool bIsLevelScriptActor = IsA(ALevelScriptActor::StaticClass()); // Iterate over properties for( TFieldIterator<UProperty> It(GetClass()) ; It ; ++It ) { UProperty* Prop = *It; UStructProperty* StructProp = Cast<UStructProperty>(Prop); UClass* PropClass = CastChecked<UClass>(Prop->GetOuter()); // get the class that added this property // First see if it is a random stream, if so reset before running construction script if( (StructProp != NULL) && (StructProp->Struct != NULL) && (StructProp->Struct->GetFName() == RandomStreamName) ) { FRandomStream* StreamPtr = StructProp->ContainerPtrToValuePtr<FRandomStream>(this); StreamPtr->Reset(); } // If it is a blueprint added variable that is not editable per-instance, reset to default before running construction script else if( !bIsLevelScriptActor && Prop->HasAnyPropertyFlags(CPF_DisableEditOnInstance) && PropClass->HasAnyClassFlags(CLASS_CompiledFromBlueprint) && !Prop->IsA(UDelegateProperty::StaticClass()) && !Prop->IsA(UMulticastDelegateProperty::StaticClass()) ) { Prop->CopyCompleteValue_InContainer(this, Default); } } }
void UK2Node_AddComponent::ValidateNodeDuringCompilation(FCompilerResultsLog& MessageLog) const { Super::ValidateNodeDuringCompilation(MessageLog); UActorComponent* Template = GetTemplateFromNode(); if (Template) { UClass* TemplateClass = Template->GetClass(); if (!TemplateClass->IsChildOf(UActorComponent::StaticClass()) || TemplateClass->HasAnyClassFlags(CLASS_Abstract) || !TemplateClass->HasMetaData(FBlueprintMetadata::MD_BlueprintSpawnableComponent) ) { FFormatNamedArguments Args; Args.Add(TEXT("TemplateClass"), FText::FromString(TemplateClass->GetName())); Args.Add(TEXT("NodeTitle"), GetNodeTitle(ENodeTitleType::FullTitle)); MessageLog.Error(*FText::Format(NSLOCTEXT("KismetCompiler", "InvalidComponentTemplate_Error", "Invalid class '{TemplateClass}' used as template by '{NodeTitle}' for @@"), Args).ToString(), this); } if (UChildActorComponent const* ChildActorComponent = Cast<UChildActorComponent const>(Template)) { UBlueprint const* Blueprint = GetBlueprint(); UClass const* ChildActorClass = ChildActorComponent->GetChildActorClass(); if (ChildActorClass == Blueprint->GeneratedClass) { UEdGraph const* ParentGraph = GetGraph(); UEdGraphSchema_K2 const* K2Schema = GetDefault<UEdGraphSchema_K2>(); if (K2Schema->IsConstructionScript(ParentGraph)) { FFormatNamedArguments Args; Args.Add(TEXT("ChildActorClass"), FText::FromString(ChildActorClass->GetName())); MessageLog.Error(*FText::Format(NSLOCTEXT("KismetCompiler", "AddSelfComponent_Error", "@@ cannot add a '{ChildActorClass}' component in the construction script (could cause infinite recursion)."), Args).ToString(), this); } } else if (ChildActorClass != nullptr) { AActor const* ChildActor = Cast<AActor>(ChildActorClass->ClassDefaultObject); check(ChildActor != nullptr); USceneComponent* RootComponent = ChildActor->GetRootComponent(); if ((RootComponent != nullptr) && (RootComponent->Mobility == EComponentMobility::Static) && (ChildActorComponent->Mobility != EComponentMobility::Static)) { FFormatNamedArguments Args; Args.Add(TEXT("ChildActorClass"), FText::FromString(ChildActorClass->GetName())); MessageLog.Error(*FText::Format(NSLOCTEXT("KismetCompiler", "AddStaticChildActorComponent_Error", "@@ cannot add a '{ChildActorClass}' component as it has static mobility, and the ChildActorComponent does not."), Args).ToString(), this); } } } } else { FFormatNamedArguments Args; Args.Add(TEXT("NodeTitle"), GetNodeTitle(ENodeTitleType::FullTitle)); MessageLog.Error(*FText::Format(NSLOCTEXT("KismetCompiler", "MissingComponentTemplate_Error", "Unknown template referenced by '{NodeTitle}' for @@"), Args).ToString(), this); } }
UClass* FClassArchiveProxy::CreateClass(const FUHTMakefile& UHTMakefile) const { UObject* Outer = UHTMakefile.GetObjectByIndex(OuterIndex); FName ClassName = Name.CreateName(UHTMakefile); UClass* Class = FindObject<UClass>(Outer, *ClassName.ToString()); if (Class == nullptr || !Class->HasAnyClassFlags(CLASS_Native)) { Class = new(EC_InternalUseOnlyConstructor, Outer, ClassName, (EObjectFlags)ObjectFlagsUint32) UClass(FObjectInitializer(), nullptr); } PostConstruct(Class); return Class; }
/** * Returns the text to use for exporting this property to header file. * * @param ExtendedTypeText for property types which use templates, will be filled in with the type * @param CPPExportFlags flags for modifying the behavior of the export */ FString UInterfaceProperty::GetCPPType( FString* ExtendedTypeText/*=NULL*/, uint32 CPPExportFlags/*=0*/ ) const { checkSlow(InterfaceClass); if ( ExtendedTypeText != NULL ) { UClass* ExportClass = InterfaceClass; if (0 == (CPPF_BlueprintCppBackend & CPPExportFlags)) { while (ExportClass && !ExportClass->HasAnyClassFlags(CLASS_Native)) { ExportClass = ExportClass->GetSuperClass(); } } check(ExportClass); check(ExportClass->HasAnyClassFlags(CLASS_Interface) || 0 != (CPPF_BlueprintCppBackend & CPPExportFlags)); *ExtendedTypeText = FString::Printf(TEXT("<I%s>"), *ExportClass->GetName()); } return TEXT("TScriptInterface"); }
void FGameplayCueTranslationManager::RefreshNameSwaps() { AllNameSwaps.Reset(); TArray<UGameplayCueTranslator*> CDOList; // Gather CDOs for( TObjectIterator<UClass> It ; It ; ++It ) { UClass* Class = *It; if( !Class->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated) ) { if( Class->IsChildOf(UGameplayCueTranslator::StaticClass()) ) { UGameplayCueTranslator* CDO = Class->GetDefaultObject<UGameplayCueTranslator>(); if (CDO->IsEnabled()) { CDOList.Add(CDO); } } } } // Sort and get translated names CDOList.Sort([](const UGameplayCueTranslator& A, const UGameplayCueTranslator& B) { return (A.GetPriority() > B.GetPriority()); }); for (UGameplayCueTranslator* CDO : CDOList) { FNameSwapData& Data = AllNameSwaps[AllNameSwaps.AddDefaulted()]; CDO->GetTranslationNameSpawns(Data.NameSwaps); if (Data.NameSwaps.Num() > 0) { Data.ClassCDO = CDO; } else { AllNameSwaps.Pop(false); } } #if WITH_EDITOR // Give UniqueID to each rule int32 ID=1; for (FNameSwapData& GroupData : AllNameSwaps) { for (FGameplayCueTranslationNameSwap& SwapData : GroupData.NameSwaps) { SwapData.EditorData.UniqueID = ID++; } } #endif }
TOptional<ECurrentState> FAutoReimportManager::ProcessAdditions(const FTimeLimit& TimeLimit) { // Override the global feedback context while we do this to avoid popping up dialogs TGuardValue<FFeedbackContext*> ScopedContextOverride(GWarn, FeedbackContextOverride.Get()); TGuardValue<bool> ScopedAssetChangesGuard(bGuardAssetChanges, true); FeedbackContextOverride->GetContent()->SetMainText(GetProgressText()); TMap<FString, TArray<UFactory*>> Factories; TArray<FString> FactoryExtensions; FactoryExtensions.Reserve(16); // Get the list of valid factories for (TObjectIterator<UClass> It ; It ; ++It) { UClass* CurrentClass = (*It); if (CurrentClass->IsChildOf(UFactory::StaticClass()) && !(CurrentClass->HasAnyClassFlags(CLASS_Abstract))) { UFactory* Factory = Cast<UFactory>(CurrentClass->GetDefaultObject()); if (Factory->bEditorImport && Factory->ImportPriority >= 0) { FactoryExtensions.Reset(); Factory->GetSupportedFileExtensions(FactoryExtensions); for (const auto& Ext : FactoryExtensions) { auto& Array = Factories.FindOrAdd(Ext); Array.Add(Factory); } } } } for (auto& Pair : Factories) { Pair.Value.Sort([](const UFactory& A, const UFactory& B) { return A.ImportPriority > B.ImportPriority; }); } const IAssetRegistry& Registry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get(); for (auto& Monitor : DirectoryMonitors) { Monitor.ProcessAdditions(Registry, TimeLimit, PackagesToSave, Factories, *FeedbackContextOverride); yield TOptional<ECurrentState>(); } return ECurrentState::ProcessModifications; }
/** Callback for creating a new level sequence asset in the level. */ static void OnCreateActorInLevel() { // Create a new level sequence IAssetTools& AssetTools = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get(); UObject* NewAsset = nullptr; // Attempt to create a new asset for (TObjectIterator<UClass> It ; It ; ++It) { UClass* CurrentClass = *It; if (CurrentClass->IsChildOf(UFactory::StaticClass()) && !(CurrentClass->HasAnyClassFlags(CLASS_Abstract))) { UFactory* Factory = Cast<UFactory>(CurrentClass->GetDefaultObject()); if (Factory->CanCreateNew() && Factory->ImportPriority >= 0 && Factory->SupportedClass == ULevelSequence::StaticClass()) { NewAsset = AssetTools.CreateAsset(ULevelSequence::StaticClass(), Factory); break; } } } if (!NewAsset) { return; } // Spawn an actor at the origin, and either move infront of the camera or focus camera on it (depending on the viewport) and open for edit UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass(ALevelSequenceActor::StaticClass()); if (!ensure(ActorFactory)) { return; } ALevelSequenceActor* NewActor = CastChecked<ALevelSequenceActor>(GEditor->UseActorFactory(ActorFactory, FAssetData(NewAsset), &FTransform::Identity)); if (GCurrentLevelEditingViewportClient != nullptr && GCurrentLevelEditingViewportClient->IsPerspective()) { GEditor->MoveActorInFrontOfCamera(*NewActor, GCurrentLevelEditingViewportClient->GetViewLocation(), GCurrentLevelEditingViewportClient->GetViewRotation().Vector()); } else { GEditor->MoveViewportCamerasToActor(*NewActor, false); } FAssetEditorManager::Get().OpenEditorForAsset(NewAsset); }
void FClassBrowseHelper::BuildClassGraph() { UClass* RootNodeClass = UBTNode::StaticClass(); TArray<TSharedPtr<FClassDataNode> > NodeList; RootNode.Reset(); // gather all native classes for (TObjectIterator<UClass> It; It; ++It) { UClass* TestClass = *It; if (TestClass->HasAnyClassFlags(CLASS_Native) && TestClass->IsChildOf(RootNodeClass)) { TSharedPtr<FClassDataNode> NewNode = MakeShareable(new FClassDataNode); NewNode->ParentClassName = TestClass->GetSuperClass()->GetName(); FClassData NewData(TestClass); NewNode->Data = NewData; if (TestClass == RootNodeClass) { RootNode = NewNode; } NodeList.Add(NewNode); } } // gather all blueprints FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); TArray<FAssetData> BlueprintList; FARFilter Filter; Filter.ClassNames.Add(UBlueprint::StaticClass()->GetFName()); AssetRegistryModule.Get().GetAssets(Filter, BlueprintList); for (int32 i = 0; i < BlueprintList.Num(); i++) { TSharedPtr<FClassDataNode> NewNode = CreateClassDataNode(BlueprintList[i]); NodeList.Add(NewNode); } // build class tree AddClassGraphChildren(RootNode, NodeList); }
FFindHeadersToInclude(FGatherConvertedClassDependencies& InDependencies) : FGatherConvertedClassDependenciesHelperBase(InDependencies) { FindReferences(Dependencies.GetActualStruct()); // special case - literal enum UBlueprintGeneratedClass* BPGC = Cast<UBlueprintGeneratedClass>(Dependencies.GetActualStruct()); UBlueprint* BP = BPGC ? Cast<UBlueprint>(BPGC->ClassGeneratedBy) : nullptr; if (BP) { TArray<UEdGraph*> Graphs; BP->GetAllGraphs(Graphs); for (UEdGraph* Graph : Graphs) { if (Graph) { TArray<UK2Node_EnumLiteral*> LiteralEnumNodes; Graph->GetNodesOfClass<UK2Node_EnumLiteral>(LiteralEnumNodes); for (UK2Node_EnumLiteral* LiteralEnumNode : LiteralEnumNodes) { UEnum* Enum = LiteralEnumNode ? LiteralEnumNode->Enum : nullptr; IncludeTheHeaderInBody(Enum); } } } } // Include classes of native subobjects if (BPGC) { UClass* NativeSuperClass = BPGC->GetSuperClass(); for (; NativeSuperClass && !NativeSuperClass->HasAnyClassFlags(CLASS_Native); NativeSuperClass = NativeSuperClass->GetSuperClass()) {} UObject* NativeCDO = NativeSuperClass ? NativeSuperClass->GetDefaultObject(false) : nullptr; if (NativeCDO) { TArray<UObject*> DefaultSubobjects; NativeCDO->GetDefaultSubobjects(DefaultSubobjects); for (UObject* DefaultSubobject : DefaultSubobjects) { IncludeTheHeaderInBody(DefaultSubobject ? DefaultSubobject->GetClass() : nullptr); } } } }
//------------------------------------------------------------------------------ bool FBlueprintNodeSpawnerUtils::IsStaleFieldAction(UBlueprintNodeSpawner const* BlueprintAction) { bool bHasStaleAssociatedField= false; const UField* AssociatedField = GetAssociatedField(BlueprintAction); if (AssociatedField != nullptr) { UClass* ClassOwner = AssociatedField->GetOwnerClass(); if (ClassOwner != nullptr) { // check to see if this field belongs to a TRASH or REINST class, // maybe to a class that was thrown out because of a hot-reload? bHasStaleAssociatedField = ClassOwner->HasAnyClassFlags(CLASS_NewerVersionExists) || (ClassOwner->GetOutermost() == GetTransientPackage()); } } return bHasStaleAssociatedField; }
void UEdGraphSchema::GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const { #if WITH_EDITOR // Run thru all nodes and add any menu items they want to add for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (Class->IsChildOf(UEdGraphNode::StaticClass()) && !Class->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated)) { const UEdGraphNode* ClassCDO = Class->GetDefaultObject<UEdGraphNode>(); if (ClassCDO->CanCreateUnderSpecifiedSchema(this)) { ClassCDO->GetMenuEntries(ContextMenuBuilder); } } } #endif }
UClass* FGatherConvertedClassDependencies::GetFirstNativeOrConvertedClass(UClass* InClass, bool bExcludeBPDataOnly) const { check(InClass); for (UClass* ItClass = InClass; ItClass; ItClass = ItClass->GetSuperClass()) { UBlueprintGeneratedClass* BPGC = Cast<UBlueprintGeneratedClass>(ItClass); if (ItClass->HasAnyClassFlags(CLASS_Native) || WillClassBeConverted(BPGC)) { if (bExcludeBPDataOnly) { UBlueprint* BP = BPGC ? Cast<UBlueprint>(BPGC->ClassGeneratedBy) : nullptr; if (BP && FBlueprintEditorUtils::IsDataOnlyBlueprint(BP)) { continue; } } return ItClass; } } check(false); return nullptr; };
void AActor::PostEditUndo(TSharedPtr<ITransactionObjectAnnotation> TransactionAnnotation) { CurrentTransactionAnnotation = StaticCastSharedPtr<FActorTransactionAnnotation>(TransactionAnnotation); // Check if this Actor needs to be re-instanced UClass* OldClass = GetClass(); if (OldClass->HasAnyClassFlags(CLASS_NewerVersionExists)) { UClass* NewClass = OldClass->GetAuthoritativeClass(); if (!ensure(NewClass != OldClass)) { UE_LOG(LogActor, Warning, TEXT("WARNING: %s is out of date and is the same as its AuthoritativeClass during PostEditUndo!"), *OldClass->GetName()); }; // Early exit, letting anything more occur would be invalid due to the REINST_ class return; } // Notify LevelBounds actor that level bounding box might be changed if (!IsTemplate()) { GetLevel()->MarkLevelBoundsDirty(); } // Restore OwnedComponents array if (!IsPendingKill()) { ResetOwnedComponents(); // notify navigation system UNavigationSystem::UpdateActorAndComponentsInNavOctree(*this); } else { UNavigationSystem::ClearNavOctreeAll(this); } Super::PostEditUndo(TransactionAnnotation); }
TArray<FFactoryItem> FindFactoriesInCategory(EAssetTypeCategories::Type AssetTypeCategory) { TArray<FFactoryItem> FactoriesInThisCategory; for (TObjectIterator<UClass> It; It; ++It) { UClass* Class = *It; if (Class->IsChildOf(UFactory::StaticClass()) && !Class->HasAnyClassFlags(CLASS_Abstract)) { UFactory* Factory = Class->GetDefaultObject<UFactory>(); if (Factory->ShouldShowInNewMenu() && ensure(!Factory->GetDisplayName().IsEmpty())) { uint32 FactoryCategories = Factory->GetMenuCategories(); if (FactoryCategories & AssetTypeCategory) { new(FactoriesInThisCategory)FFactoryItem(Factory, Factory->GetDisplayName()); } } } } return FactoriesInThisCategory; }
FString FClassData::ToString() const { UClass* MyClass = Class.Get(); if (MyClass) { FString ClassDesc = MyClass->GetName(); if (MyClass->HasAnyClassFlags(CLASS_CompiledFromBlueprint)) { return ClassDesc.LeftChop(2); } const int32 ShortNameIdx = ClassDesc.Find(TEXT("_")); if (ShortNameIdx != INDEX_NONE) { ClassDesc = ClassDesc.Mid(ShortNameIdx + 1); } return ClassDesc; } return AssetName; }
void UGameplayTagsManager::ConstructGameplayTagTree() { if (!GameplayRootTag.IsValid()) { GameplayRootTag = MakeShareable(new FGameplayTagNode()); for (auto It(GameplayTagTables.CreateIterator()); It; It++) { PopulateTreeFromDataTable(*It); } if (ShouldImportTagsFromINI()) { // Load any GameplayTagSettings from config (their default object) for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (!Class->IsChildOf<UGameplayTagsSettings>() || Class->HasAnyClassFlags(CLASS_Abstract)) { continue; } for (FString TagStr : Class->GetDefaultObject<UGameplayTagsSettings>()->GameplayTags) { FGameplayTagTableRow TableRow; TableRow.Tag = TagStr; AddTagTableRow(TableRow); } } GameplayRootTag->GetChildTagNodes().Sort(FCompareFGameplayTagNodeByTag()); } GameplayTagTreeChangedEvent.Broadcast(); } }
FString FAutoReimportManager::GetAllFactoryExtensions() { FString AllExtensions; // Use a scratch buffer to avoid unnecessary re-allocation FString Scratch; Scratch.Reserve(32); for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (Class->IsChildOf(UFactory::StaticClass()) && !Class->HasAnyClassFlags(CLASS_Abstract)) { UFactory* Factory = Cast<UFactory>(Class->GetDefaultObject()); if (Factory->bEditorImport) { for (const FString& Format : Factory->Formats) { int32 Index = INDEX_NONE; if (Format.FindChar(';', Index) && Index > 0) { Scratch.GetCharArray().Reset(); // Include the ; Scratch.AppendChars(*Format, Index + 1); if (AllExtensions.Find(Scratch) == INDEX_NONE) { AllExtensions += Scratch; } } } } } } return AllExtensions; }
bool FComponentEditorUtils::CanCopyComponents(const TArray<UActorComponent*>& ComponentsToCopy) { bool bCanCopy = ComponentsToCopy.Num() > 0; if (bCanCopy) { for (int32 i = 0; i < ComponentsToCopy.Num() && bCanCopy; ++i) { // Check for the default scene root; that cannot be copied/duplicated UActorComponent* Component = ComponentsToCopy[i]; bCanCopy = Component != nullptr && Component->GetFName() != USceneComponent::GetDefaultSceneRootVariableName(); if (bCanCopy) { UClass* ComponentClass = Component->GetClass(); check(ComponentClass != nullptr); // Component class cannot be abstract and must also be tagged as BlueprintSpawnable bCanCopy = !ComponentClass->HasAnyClassFlags(CLASS_Abstract) && ComponentClass->HasMetaData(FBlueprintMetadata::MD_BlueprintSpawnableComponent); } } } return bCanCopy; }
void UK2Node_LatentAbilityCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const { // these nested loops are combing over the same classes/functions the // FBlueprintActionDatabase does; ideally we save on perf and fold this in // with FBlueprintActionDatabase, but we want to keep the modules separate for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (!Class->IsChildOf<UAbilityTask>() || Class->HasAnyClassFlags(CLASS_Abstract)) { continue; } for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (!Function->HasAnyFunctionFlags(FUNC_Static)) { continue; } // to keep from needlessly instantiating a UBlueprintNodeSpawner, first // check to make sure that the registrar is looking for actions of this type // (could be regenerating actions for a specific asset, and therefore the // registrar would only accept actions corresponding to that asset) if (!ActionRegistrar.IsOpenForRegistration(Function)) { continue; } UObjectProperty* ReturnProperty = Cast<UObjectProperty>(Function->GetReturnProperty()); // see if the function is a static factory method for online proxies bool const bIsProxyFactoryMethod = (ReturnProperty != nullptr) && ReturnProperty->PropertyClass->IsChildOf<UAbilityTask>(); if (bIsProxyFactoryMethod) { UBlueprintNodeSpawner* NodeSpawner = UBlueprintFunctionNodeSpawner::Create(Function); check(NodeSpawner != nullptr); NodeSpawner->NodeClass = GetClass(); auto CustomizeAcyncNodeLambda = [](UEdGraphNode* NewNode, bool bIsTemplateNode, TWeakObjectPtr<UFunction> FunctionPtr) { UK2Node_LatentAbilityCall* AsyncTaskNode = CastChecked<UK2Node_LatentAbilityCall>(NewNode); if (FunctionPtr.IsValid()) { UFunction* Func = FunctionPtr.Get(); UObjectProperty* ReturnProp = CastChecked<UObjectProperty>(Func->GetReturnProperty()); AsyncTaskNode->ProxyFactoryFunctionName = Func->GetFName(); AsyncTaskNode->ProxyFactoryClass = Func->GetOuterUClass(); AsyncTaskNode->ProxyClass = ReturnProp->PropertyClass; } }; TWeakObjectPtr<UFunction> FunctionPtr = Function; NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(CustomizeAcyncNodeLambda, FunctionPtr); // @TODO: since this can't be folded into FBlueprintActionDatabase, we // need a way to associate these spawners with a certain class ActionRegistrar.AddBlueprintAction(Function, NodeSpawner); } } } }
void FBlueprintCompileReinstancer::ReplaceInstancesOfClass(UClass* OldClass, UClass* NewClass, UObject* OriginalCDO, TSet<UObject*>* ObjectsThatShouldUseOldStuff) { USelection* SelectedActors; bool bSelectionChanged = false; TArray<UObject*> ObjectsToReplace; const bool bLogConversions = false; // for debugging // Map of old objects to new objects TMap<UObject*, UObject*> OldToNewInstanceMap; TMap<UClass*, UClass*> OldToNewClassMap; OldToNewClassMap.Add(OldClass, NewClass); TMap<FStringAssetReference, UObject*> ReinstancedObjectsWeakReferenceMap; // actors being replace TArray<FActorReplacementHelper> ReplacementActors; // A list of objects (e.g. Blueprints) that potentially have editors open that we need to refresh TArray<UObject*> PotentialEditorsForRefreshing; // A list of component owners that need their construction scripts re-ran (because a component of theirs has been reinstanced) TSet<AActor*> OwnersToReconstruct; // Set global flag to let system know we are reconstructing blueprint instances TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true); struct FObjectRemappingHelper { void OnObjectsReplaced(const TMap<UObject*, UObject*>& InReplacedObjects) { ReplacedObjects.Append(InReplacedObjects); } TMap<UObject*, UObject*> ReplacedObjects; } ObjectRemappingHelper; FDelegateHandle OnObjectsReplacedHandle = GEditor->OnObjectsReplaced().AddRaw(&ObjectRemappingHelper,&FObjectRemappingHelper::OnObjectsReplaced); { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplaceInstancesOfClass); const bool bIncludeDerivedClasses = false; GetObjectsOfClass(OldClass, ObjectsToReplace, bIncludeDerivedClasses); SelectedActors = GEditor->GetSelectedActors(); SelectedActors->BeginBatchSelectOperation(); SelectedActors->Modify(); // Then fix 'real' (non archetype) instances of the class for (UObject* OldObject : ObjectsToReplace) { // Skip non-archetype instances, EXCEPT for component templates const bool bIsComponent = NewClass->IsChildOf(UActorComponent::StaticClass()); if ((!bIsComponent && OldObject->IsTemplate()) || OldObject->IsPendingKill()) { continue; } UBlueprint* CorrespondingBlueprint = Cast<UBlueprint>(OldObject->GetClass()->ClassGeneratedBy); UObject* OldBlueprintDebugObject = nullptr; // If this object is being debugged, cache it off so we can preserve the 'object being debugged' association if ((CorrespondingBlueprint != nullptr) && (CorrespondingBlueprint->GetObjectBeingDebugged() == OldObject)) { OldBlueprintDebugObject = OldObject; } AActor* OldActor = Cast<AActor>(OldObject); UObject* NewUObject = nullptr; // if the object to replace is an actor... if (OldActor != nullptr) { FVector Location = FVector::ZeroVector; FRotator Rotation = FRotator::ZeroRotator; if (USceneComponent* OldRootComponent = OldActor->GetRootComponent()) { Location = OldActor->GetActorLocation(); Rotation = OldActor->GetActorRotation(); } // If this actor was spawned from an Archetype, we spawn the new actor from the new version of that archetype UObject* OldArchetype = OldActor->GetArchetype(); UWorld* World = OldActor->GetWorld(); AActor* NewArchetype = Cast<AActor>(OldToNewInstanceMap.FindRef(OldArchetype)); // Check that either this was an instance of the class directly, or we found a new archetype for it check(OldArchetype == OldClass->GetDefaultObject() || NewArchetype); // Spawn the new actor instance, in the same level as the original, but deferring running the construction script until we have transferred modified properties ULevel* ActorLevel = OldActor->GetLevel(); UClass** MappedClass = OldToNewClassMap.Find(OldActor->GetClass()); UClass* SpawnClass = MappedClass ? *MappedClass : NewClass; FActorSpawnParameters SpawnInfo; SpawnInfo.OverrideLevel = ActorLevel; SpawnInfo.Template = NewArchetype; SpawnInfo.bNoCollisionFail = true; SpawnInfo.bDeferConstruction = true; // Temporarily remove the deprecated flag so we can respawn the Blueprint in the level const bool bIsClassDeprecated = SpawnClass->HasAnyClassFlags(CLASS_Deprecated); SpawnClass->ClassFlags &= ~CLASS_Deprecated; AActor* NewActor = World->SpawnActor(SpawnClass, &Location, &Rotation, SpawnInfo); // Reassign the deprecated flag if it was previously assigned if (bIsClassDeprecated) { SpawnClass->ClassFlags |= CLASS_Deprecated; } check(NewActor != nullptr); NewUObject = NewActor; // store the new actor for the second pass (NOTE: this detaches // OldActor from all child/parent attachments) // // running the NewActor's construction-script is saved for that // second pass (because the construction-script may reference // another instance that hasn't been replaced yet). ReplacementActors.Add(FActorReplacementHelper(NewActor, OldActor)); ReinstancedObjectsWeakReferenceMap.Add(OldObject, NewUObject); OldActor->DestroyConstructedComponents(); // don't want to serialize components from the old actor // Unregister native components so we don't copy any sub-components they generate for themselves (like UCameraComponent does) OldActor->UnregisterAllComponents(); // Unregister any native components, might have cached state based on properties we are going to overwrite NewActor->UnregisterAllComponents(); UEditorEngine::CopyPropertiesForUnrelatedObjects(OldActor, NewActor); // reset properties/streams NewActor->ResetPropertiesForConstruction(); // register native components NewActor->RegisterAllComponents(); // // clean up the old actor (unselect it, remove it from the world, etc.)... if (OldActor->IsSelected()) { GEditor->SelectActor(OldActor, /*bInSelected =*/false, /*bNotify =*/false); bSelectionChanged = true; } if (GEditor->Layers.IsValid()) // ensure(NULL != GEditor->Layers) ?? While cooking the Layers is NULL. { GEditor->Layers->DisassociateActorFromLayers(OldActor); } World->EditorDestroyActor(OldActor, /*bShouldModifyLevel =*/true); OldToNewInstanceMap.Add(OldActor, NewActor); } else { FName OldName(OldObject->GetFName()); OldObject->Rename(NULL, OldObject->GetOuter(), REN_DoNotDirty | REN_DontCreateRedirectors); NewUObject = NewObject<UObject>(OldObject->GetOuter(), NewClass, OldName); check(NewUObject != nullptr); UEditorEngine::CopyPropertiesForUnrelatedObjects(OldObject, NewUObject); if (UAnimInstance* AnimTree = Cast<UAnimInstance>(NewUObject)) { // Initialising the anim instance isn't enough to correctly set up the skeletal mesh again in a // paused world, need to initialise the skeletal mesh component that contains the anim instance. if (USkeletalMeshComponent* SkelComponent = Cast<USkeletalMeshComponent>(AnimTree->GetOuter())) { SkelComponent->InitAnim(true); } } OldObject->RemoveFromRoot(); OldObject->MarkPendingKill(); OldToNewInstanceMap.Add(OldObject, NewUObject); if (bIsComponent) { UActorComponent* Component = Cast<UActorComponent>(NewUObject); AActor* OwningActor = Component->GetOwner(); if (OwningActor) { OwningActor->ResetOwnedComponents(); // Check to see if they have an editor that potentially needs to be refreshed if (OwningActor->GetClass()->ClassGeneratedBy) { PotentialEditorsForRefreshing.AddUnique(OwningActor->GetClass()->ClassGeneratedBy); } // we need to keep track of actor instances that need // their construction scripts re-ran (since we've just // replaced a component they own) OwnersToReconstruct.Add(OwningActor); } } } // If this original object came from a blueprint and it was in the selected debug set, change the debugging to the new object. if ((CorrespondingBlueprint) && (OldBlueprintDebugObject) && (NewUObject)) { CorrespondingBlueprint->SetObjectBeingDebugged(NewUObject); } if (bLogConversions) { UE_LOG(LogBlueprint, Log, TEXT("Converted instance '%s' to '%s'"), *OldObject->GetPathName(), *NewUObject->GetPathName()); } } } GEditor->OnObjectsReplaced().Remove(OnObjectsReplacedHandle); // Now replace any pointers to the old archetypes/instances with pointers to the new one TArray<UObject*> SourceObjects; TArray<UObject*> DstObjects; OldToNewInstanceMap.GenerateKeyArray(SourceObjects); OldToNewInstanceMap.GenerateValueArray(DstObjects); // Also look for references in new spawned objects. SourceObjects.Append(DstObjects); FReplaceReferenceHelper::IncludeCDO(OldClass, NewClass, OldToNewInstanceMap, SourceObjects, OriginalCDO); FReplaceReferenceHelper::FindAndReplaceReferences(SourceObjects, ObjectsThatShouldUseOldStuff, ObjectsToReplace, OldToNewInstanceMap, ReinstancedObjectsWeakReferenceMap); { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplacementConstruction); // the process of setting up new replacement actors is split into two // steps (this here, is the second)... // // the "finalization" here runs the replacement actor's construction- // script and is left until late to account for a scenario where the // construction-script attempts to modify another instance of the // same class... if this were to happen above, in the ObjectsToReplace // loop, then accessing that other instance would cause an assert in // UProperty::ContainerPtrToValuePtrInternal() (which appropriatly // complains that the other instance's type doesn't match because it // hasn't been replaced yet... that's why we wait until after // FArchiveReplaceObjectRef to run construction-scripts). for (FActorReplacementHelper& ReplacementActor : ReplacementActors) { ReplacementActor.Finalize(ObjectRemappingHelper.ReplacedObjects); } } SelectedActors->EndBatchSelectOperation(); if (bSelectionChanged) { GEditor->NoteSelectionChange(); } if (GEditor) { // Refresh any editors for objects that we've updated components for for (auto BlueprintAsset : PotentialEditorsForRefreshing) { FBlueprintEditor* BlueprintEditor = static_cast<FBlueprintEditor*>(FAssetEditorManager::Get().FindEditorForAsset(BlueprintAsset, /*bFocusIfOpen =*/false)); if (BlueprintEditor) { BlueprintEditor->RefreshEditors(); } } } // in the case where we're replacing component instances, we need to make // sure to re-run their owner's construction scripts for (AActor* ActorInstance : OwnersToReconstruct) { ActorInstance->RerunConstructionScripts(); } }
void SAnimationCompressionPanel::Construct(const FArguments& InArgs) { AnimSequences = InArgs._AnimSequences; CurrentCompressionChoice = 0; for ( TObjectIterator<UClass> It ; It ; ++It ) { UClass* Class = *It; if( !Class->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated) ) { if ( Class->IsChildOf(UAnimCompress::StaticClass()) ) { UAnimCompress* NewAlgorithm = ConstructObject<UAnimCompress>( Class ); AnimationCompressionAlgorithms.Add( NewAlgorithm ); } } } TSharedRef<SVerticalBox> Box = SNew(SVerticalBox) +SVerticalBox::Slot() .AutoHeight() .Padding(8.0f, 4.0f, 8.0f, 4.0f) [ SNew( STextBlock ) .Text( LOCTEXT("AnimCompressionLabel", "Compression Algorithms") ) ] +SVerticalBox::Slot() .AutoHeight() .Padding(8.0f, 4.0f, 8.0f, 4.0f) [ SNew(SSeparator) ]; for( int32 i = 0 ; i < AnimationCompressionAlgorithms.Num() ; ++i ) { UAnimCompress* Alg = AnimationCompressionAlgorithms[i]; (*Box).AddSlot() .Padding(8.0f, 4.0f, 8.0f, 4.0f) [ CreateRadioButton( FText::FromString( Alg->Description ), i) ]; } (*Box) .AddSlot() .AutoHeight() .Padding(8.0f, 4.0f, 4.0f, 8.0f) [ SNew(SSeparator) ]; (*Box) .AddSlot() .Padding(4.0f) .HAlign(HAlign_Right) .VAlign(VAlign_Bottom) .AutoHeight() [ SNew(SUniformGridPanel) .SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding")) .MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth")) .MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight")) +SUniformGridPanel::Slot(0,0) [ SNew(SButton) .Text(LOCTEXT("AnimCompressionApply", "Apply").ToString()) .HAlign(HAlign_Center) .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) .OnClicked(this, &SAnimationCompressionPanel::ApplyClicked) ] ]; this->ChildSlot[Box]; }
void SPropertyEditorAsset::Construct( const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor ) { PropertyEditor = InPropertyEditor; PropertyHandle = InArgs._PropertyHandle; OnSetObject = InArgs._OnSetObject; OnShouldFilterAsset = InArgs._OnShouldFilterAsset; UProperty* Property = nullptr; if(PropertyEditor.IsValid()) { Property = PropertyEditor->GetPropertyNode()->GetProperty(); UObjectPropertyBase* ObjectProperty = Cast<UObjectPropertyBase>(Property); check(ObjectProperty); bAllowClear = !(Property->PropertyFlags & CPF_NoClear); ObjectClass = ObjectProperty->PropertyClass; bIsActor = ObjectProperty->PropertyClass->IsChildOf( AActor::StaticClass() ); } else { bAllowClear = InArgs._AllowClear; ObjectPath = InArgs._ObjectPath; ObjectClass = InArgs._Class; bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() ); if (PropertyHandle.IsValid() && PropertyHandle->IsValidHandle()) { Property = PropertyHandle->GetProperty(); } else { CustomClassFilters.Add(ObjectClass); } } // Account for the allowed classes specified in the property metadata if (Property) { FString ClassFilterString; if (UArrayProperty* ArrayParent = Cast<UArrayProperty>(Property->GetOuter())) { ClassFilterString = ArrayParent->GetMetaData("AllowedClasses"); } else { ClassFilterString = Property->GetMetaData("AllowedClasses"); } if (ClassFilterString.IsEmpty()) { CustomClassFilters.Add(ObjectClass); } else { TArray<FString> CustomClassFilterNames; ClassFilterString.ParseIntoArray(CustomClassFilterNames, TEXT(","), true); for (auto It = CustomClassFilterNames.CreateConstIterator(); It; ++It) { const FString& ClassName = *It; UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName); if (!Class) { Class = LoadObject<UClass>(nullptr, *ClassName); } if (Class) { // If the class is an interface, expand it to be all classes in memory that implement the class. if (Class->HasAnyClassFlags(CLASS_Interface)) { for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* const ClassWithInterface = (*ClassIt); if (ClassWithInterface->ImplementsInterface(Class)) { CustomClassFilters.Add(ClassWithInterface); } } } else { CustomClassFilters.Add(Class); } } } } } if (InArgs._NewAssetFactories.IsSet()) { NewAssetFactories = InArgs._NewAssetFactories.GetValue(); } else if (CustomClassFilters.Num() > 1 || !CustomClassFilters.Contains(UObject::StaticClass())) { NewAssetFactories = PropertyCustomizationHelpers::GetNewAssetFactoriesForClasses(CustomClassFilters); } TSharedPtr<SHorizontalBox> ValueContentBox = NULL; ChildSlot [ SNew( SAssetDropTarget ) .OnIsAssetAcceptableForDrop( this, &SPropertyEditorAsset::OnAssetDraggedOver ) .OnAssetDropped( this, &SPropertyEditorAsset::OnAssetDropped ) [ SAssignNew( ValueContentBox, SHorizontalBox ) ] ]; TAttribute<bool> IsEnabledAttribute(this, &SPropertyEditorAsset::CanEdit); TAttribute<FText> TooltipAttribute(this, &SPropertyEditorAsset::OnGetToolTip); if (Property && Property->HasAllPropertyFlags(CPF_DisableEditOnTemplate)) { // There are some cases where editing an Actor Property is not allowed, such as when it is contained within a struct or a CDO TArray<UObject*> ObjectList; PropertyEditor->GetPropertyHandle()->GetOuterObjects(ObjectList); // If there is no objects, that means we must have a struct asset managing this property if (ObjectList.Num() == 0) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplate", "Editing this value in structure's defaults is not allowed")); } else { // Go through all the found objects and see if any are a CDO, we can't set an actor in a CDO default. for (UObject* Obj : ObjectList) { if (Obj->HasAllFlags(RF_ClassDefaultObject)) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplateTooltip", "Editing this value in a Class Default Object is not allowed")); break; } } } } AssetComboButton = SNew(SComboButton) .ToolTipText(TooltipAttribute) .ButtonStyle( FEditorStyle::Get(), "PropertyEditor.AssetComboStyle" ) .ForegroundColor(FEditorStyle::GetColor("PropertyEditor.AssetName.ColorAndOpacity")) .OnGetMenuContent( this, &SPropertyEditorAsset::OnGetMenuContent ) .OnMenuOpenChanged( this, &SPropertyEditorAsset::OnMenuOpenChanged ) .IsEnabled( IsEnabledAttribute ) .ContentPadding(2.0f) .ButtonContent() [ // Show the name of the asset or actor SNew(STextBlock) .TextStyle( FEditorStyle::Get(), "PropertyEditor.AssetClass" ) .Font( FEditorStyle::GetFontStyle( PropertyEditorConstants::PropertyFontStyle ) ) .Text(this,&SPropertyEditorAsset::OnGetAssetName) ]; TSharedRef<SHorizontalBox> ButtonBox = SNew( SHorizontalBox ); TSharedPtr<SVerticalBox> CustomContentBox; if( ShouldDisplayThumbnail(InArgs) ) { FObjectOrAssetData Value; GetValue( Value ); AssetThumbnail = MakeShareable( new FAssetThumbnail( Value.AssetData, InArgs._ThumbnailSize.X, InArgs._ThumbnailSize.Y, InArgs._ThumbnailPool ) ); ValueContentBox->AddSlot() .Padding( 0.0f, 0.0f, 2.0f, 0.0f ) .AutoWidth() [ SAssignNew( ThumbnailBorder, SBorder ) .Padding( 5.0f ) .BorderImage( this, &SPropertyEditorAsset::GetThumbnailBorder ) .OnMouseDoubleClick( this, &SPropertyEditorAsset::OnAssetThumbnailDoubleClick ) [ SNew( SBox ) .ToolTipText(TooltipAttribute) .WidthOverride( InArgs._ThumbnailSize.X ) .HeightOverride( InArgs._ThumbnailSize.Y ) [ AssetThumbnail->MakeThumbnailWidget() ] ] ]; ValueContentBox->AddSlot() [ SNew( SBox ) .VAlign( VAlign_Center ) [ SAssignNew( CustomContentBox, SVerticalBox ) + SVerticalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SVerticalBox::Slot() .AutoHeight() .Padding( 0.0f, 2.0f, 4.0f, 2.0f ) [ ButtonBox ] ] ]; } else { ValueContentBox->AddSlot() [ SAssignNew( CustomContentBox, SVerticalBox ) +SVerticalBox::Slot() .VAlign( VAlign_Center ) [ SNew( SHorizontalBox ) + SHorizontalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SHorizontalBox::Slot() .AutoWidth() .Padding( 4.f, 0.f ) [ ButtonBox ] ] ]; } if( InArgs._CustomContentSlot.Widget != SNullWidget::NullWidget ) { CustomContentBox->AddSlot() .VAlign( VAlign_Center ) .Padding( FMargin( 0.0f, 2.0f ) ) [ InArgs._CustomContentSlot.Widget ]; } if( !bIsActor && InArgs._DisplayUseSelected ) { ButtonBox->AddSlot() .VAlign(VAlign_Center) .AutoWidth() .Padding( 2.0f, 0.0f ) [ PropertyCustomizationHelpers::MakeUseSelectedButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnUse ), FText(), IsEnabledAttribute ) ]; } if( InArgs._DisplayBrowse ) { ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ PropertyCustomizationHelpers::MakeBrowseButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnBrowse ), TAttribute<FText>( this, &SPropertyEditorAsset::GetOnBrowseToolTip ) ) ]; } if( bIsActor ) { TSharedRef<SWidget> ActorPicker = PropertyCustomizationHelpers::MakeInteractiveActorPicker( FOnGetAllowedClasses::CreateSP(this, &SPropertyEditorAsset::OnGetAllowedClasses), FOnShouldFilterActor(), FOnActorSelected::CreateSP( this, &SPropertyEditorAsset::OnActorSelected ) ); ActorPicker->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ActorPicker ]; } if( InArgs._ResetToDefaultSlot.Widget != SNullWidget::NullWidget ) { TSharedRef<SWidget> ResetToDefaultWidget = InArgs._ResetToDefaultSlot.Widget; ResetToDefaultWidget->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 4.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ResetToDefaultWidget ]; } }
void UGameplayTagsManager::ConstructGameplayTagTree() { if (!GameplayRootTag.IsValid()) { GameplayRootTag = MakeShareable(new FGameplayTagNode()); { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: Construct from data asset")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif for (auto It(GameplayTagTables.CreateIterator()); It; It++) { if (*It) { PopulateTreeFromDataTable(*It); } } } if (ShouldImportTagsFromINI()) { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: ImportINI")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif // Update path: Check for old tags in DefaultEngine.ini (we'll push them to the UGameplayTagSettings class). TArray<FString> EngineConfigTags; GConfig->GetArray(TEXT("/Script/GameplayTags.GameplayTagsSettings"), TEXT("GameplayTags"), EngineConfigTags, GEngineIni); if (EngineConfigTags.Num() > 0) { UGameplayTagsSettings* MutableDefault = GetMutableDefault<UGameplayTagsSettings>(); if (MutableDefault->GameplayTags.Num() == 0) { MutableDefault->GameplayTags.Append(EngineConfigTags); } } // Load any GameplayTagSettings from config (their default object) for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (!Class->IsChildOf<UGameplayTagsSettings>() || Class->HasAnyClassFlags(CLASS_Abstract)) { continue; } #if WITH_EDITOR Class->GetDefaultObject<UGameplayTagsSettings>()->SortTags(); #endif for (FString TagStr : Class->GetDefaultObject<UGameplayTagsSettings>()->GameplayTags) { FGameplayTagTableRow TableRow; TableRow.Tag = TagStr; AddTagTableRow(TableRow); } } GameplayRootTag->GetChildTagNodes().Sort(FCompareFGameplayTagNodeByTag()); } if (ShouldUseFastReplication()) { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: Reconstruct NetIndex")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif ConstructNetIndex(); } { #if STATS FString PerfMessage = FString::Printf(TEXT("UGameplayTagsManager::ConstructGameplayTagTree: GameplayTagTreeChangedEvent.Broadcast")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif GameplayTagTreeChangedEvent.Broadcast(); } // Update the TagRedirects map TagRedirects.Empty(); FConfigSection* PackageRedirects = GConfig->GetSectionPrivate(TEXT("/Script/Engine.Engine"), false, true, GEngineIni); for (FConfigSection::TIterator It(*PackageRedirects); It; ++It) { if (It.Key() == TEXT("GameplayTagRedirects")) { FName OldTagName = NAME_None; FName NewTagName; if (FParse::Value(*It.Value(), TEXT("OldTagName="), OldTagName)) { if (FParse::Value(*It.Value(), TEXT("NewTagName="), NewTagName)) { if (ensureMsgf(!TagRedirects.Contains(OldTagName), TEXT("Old tag %s is being redirected to more than one tag. Please remove all the redirections except for one."), *OldTagName.ToString())) { FGameplayTag OldTag = RequestGameplayTag(OldTagName, false); //< This only succeeds if OldTag is in the Table! if (OldTag.IsValid()) { UE_LOG(LogGameplayTags, Warning, TEXT("Old tag (%s) which is being redirected still exists in the table! Generally you should " TEXT("remove the old tags from the table when you are redirecting to new tags, or else users will ") TEXT("still be able to add the old tags to containers.")), *OldTagName.ToString() ); } FGameplayTag NewTag = (NewTagName != NAME_None) ? RequestGameplayTag(NewTagName, false) : FGameplayTag(); if (!NewTag.IsValid() && NewTagName != NAME_None) { UE_LOG(LogGameplayTags, Warning, TEXT("Invalid new tag %s! Cannot replace old tag %s."), *NewTagName.ToString(), *OldTagName.ToString()); } else { // Populate the map TagRedirects.Add(OldTagName, NewTag); } } } } } } }