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; }
bool FLuaScriptCodeGenerator::CanExportClass(UClass* Class) { bool bCanExport = FScriptCodeGeneratorBase::CanExportClass(Class); if (bCanExport) { const FString ClassNameCPP = GetClassNameCPP(Class); // No functions to export? Don't bother exporting the class. bool bHasMembersToExport = false; for (TFieldIterator<UFunction> FuncIt(Class); !bHasMembersToExport && FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (CanExportFunction(ClassNameCPP, Class, Function)) { bHasMembersToExport = true; } } // Check properties too if (!bHasMembersToExport) { for (TFieldIterator<UProperty> PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); !bHasMembersToExport && PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; if (CanExportProperty(ClassNameCPP, Class, Property)) { bHasMembersToExport = true; } } } bCanExport = bHasMembersToExport; } return bCanExport; }
void FLuaScriptCodeGenerator::ExportClass(UClass* Class, const FString& SourceHeaderFilename, const FString& GeneratedHeaderFilename, bool bHasChanged) { if (!CanExportClass(Class)) { return; } UE_LOG(LogScriptGenerator, Log, TEXT("Exporting class %s"), *Class->GetName()); ExportedClasses.Add(Class->GetFName()); LuaExportedClasses.Add(Class); AllSourceClassHeaders.Add(SourceHeaderFilename); const FString ClassGlueFilename = GetScriptHeaderForClass(Class); AllScriptHeaders.Add(ClassGlueFilename); const FString ClassNameCPP = GetClassNameCPP(Class); FString GeneratedGlue(TEXT("#pragma once\r\n\r\n")); // Export all functions for (TFieldIterator<UFunction> FuncIt(Class /*, EFieldIteratorFlags::ExcludeSuper*/); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (CanExportFunction(ClassNameCPP, Class, Function)) { GeneratedGlue += ExportFunction(ClassNameCPP, Class, Function); } } // Export properties that are owned by this class int32 PropertyIndex = 0; for (TFieldIterator<UProperty> PropertyIt(Class /*, EFieldIteratorFlags::ExcludeSuper*/); PropertyIt; ++PropertyIt, ++PropertyIndex) { UProperty* Property = *PropertyIt; if (CanExportProperty(ClassNameCPP, Class, Property)) { UE_LOG(LogScriptGenerator, Log, TEXT(" %s %s"), *Property->GetClass()->GetName(), *Property->GetName()); GeneratedGlue += ExportProperty(ClassNameCPP, Class, Property, PropertyIndex); } } GeneratedGlue += ExportAdditionalClassGlue(ClassNameCPP, Class); SaveHeaderIfChanged(ClassGlueFilename, GeneratedGlue); }
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 FEditorUtilityInstanceDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayoutBuilder) { SelectedObjectsList = DetailLayoutBuilder.GetDetailsView().GetSelectedObjects(); // Hide some useless categories //@TODO: How to hide Actors, Layers, etc...? // Build a list of unique selected blutilities TArray<UClass*> UniqueBlutilityClasses; bool bFoundAnyCDOs = false; for (auto SelectedObjectIt = SelectedObjectsList.CreateConstIterator(); SelectedObjectIt; ++SelectedObjectIt) { UObject* Object = (*SelectedObjectIt).Get(); if (!Object->HasAnyFlags(RF_ClassDefaultObject)) { UClass* ObjectClass = Object->GetClass(); if (UEditorUtilityBlueprint* Blutility = Cast<UEditorUtilityBlueprint>(ObjectClass->ClassGeneratedBy)) { UniqueBlutilityClasses.Add(ObjectClass); } } else { bFoundAnyCDOs = true; } } // Run thru each one UniqueBlutilityClasses.Sort(FCompareClassNames()); for (auto ClassIt = UniqueBlutilityClasses.CreateIterator(); ClassIt; ++ClassIt) { UClass* Class = *ClassIt; FString CategoryName = FString::Printf(TEXT("%sActions"), *Class->ClassGeneratedBy->GetName()); IDetailCategoryBuilder& ActionsCategory = DetailLayoutBuilder.EditCategory(*CategoryName); const APlacedEditorUtilityBase* PlacedActorCDO = Cast<const APlacedEditorUtilityBase>(Class->GetDefaultObject()); if (PlacedActorCDO) { ActionsCategory.AddCustomRow( PlacedActorCDO->HelpText ) [ SNew(STextBlock) .Text(PlacedActorCDO->HelpText) ]; } const UGlobalEditorUtilityBase* GlobalBlutilityCDO = Cast<const UGlobalEditorUtilityBase>(Class->GetDefaultObject()); if (GlobalBlutilityCDO) { ActionsCategory.AddCustomRow( GlobalBlutilityCDO->HelpText ) [ SNew(STextBlock) .Text(GlobalBlutilityCDO->HelpText) ]; } TSharedRef<SWrapBox> WrapBox = SNew(SWrapBox).UseAllottedWidth(true); int32 NumButtons = 0; for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::IncludeSuper); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; const bool bCanExecute = (Function->NumParms == 0) && Function->HasAllFunctionFlags(FUNC_Exec); if (bCanExecute) { ++NumButtons; const FString ButtonCaption = FName::NameToDisplayString(*Function->GetName(), false); //@TODO: Expose the code in UK2Node_CallFunction::GetUserFacingFunctionName / etc... FString Tooltip = Function->GetToolTipText().ToString(); if (Tooltip.IsEmpty()) { Tooltip = Function->GetName(); } TWeakObjectPtr<UFunction> WeakFunctionPtr(Function); WrapBox->AddSlot() [ SNew(SButton) .Text(ButtonCaption) .OnClicked( FOnClicked::CreateSP(this, &FEditorUtilityInstanceDetails::OnExecuteAction, WeakFunctionPtr) ) .ToolTipText(Tooltip) ]; } } if (NumButtons > 0) { ActionsCategory.AddCustomRow(TEXT("")) [ WrapBox ]; } } // Hide the hint property if (!bFoundAnyCDOs) { DetailLayoutBuilder.HideProperty(TEXT("HelpText")); } }
//------------------------------------------------------------------------------ int32 FBlueprintActionDatabaseRegistrar::RegisterClassFactoryActions(const UClass* TargetType, const FMakeFuncSpawnerDelegate& MakeActionCallback) { struct RegisterClassFactoryActions_Utils { static bool IsFactoryMethod(const UFunction* Function, const UClass* InTargetType) { if (!Function->HasAnyFunctionFlags(FUNC_Static)) { return false; } UObjectProperty* ReturnProperty = Cast<UObjectProperty>(Function->GetReturnProperty()); // see if the function is a static factory method bool const bIsFactoryMethod = (ReturnProperty != nullptr) && ReturnProperty->PropertyClass->IsChildOf(InTargetType); return bIsFactoryMethod; } }; int32 RegisteredCount = 0; if (const UObject* RegistrarTarget = GetActionKeyFilter()) { if (const UClass* TargetClass = Cast<UClass>(RegistrarTarget)) { if (!TargetClass->HasAnyClassFlags(CLASS_Abstract) && !TargetClass->IsChildOf(TargetType)) { for (TFieldIterator<UFunction> FuncIt(TargetClass, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (!RegisterClassFactoryActions_Utils::IsFactoryMethod(Function, TargetType)) { continue; } else if (UBlueprintNodeSpawner* NewAction = MakeActionCallback.Execute(Function)) { RegisteredCount += (int32)AddBlueprintAction(Function, NewAction); } } } } } else { // 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 give separate modules // the opportunity to add their own actions per class func for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* Class = *ClassIt; if (Class->HasAnyClassFlags(CLASS_Abstract) || !Class->IsChildOf(TargetType)) { continue; } for (TFieldIterator<UFunction> FuncIt(Class, EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt) { UFunction* Function = *FuncIt; if (!RegisterClassFactoryActions_Utils::IsFactoryMethod(Function, TargetType)) { continue; } else if (UBlueprintNodeSpawner* NewAction = MakeActionCallback.Execute(Function)) { RegisteredCount += (int32)AddBlueprintAction(Function, NewAction); } } } } return 0; }