// Disassemble all functions in any classes that have matching names. void FKismetBytecodeDisassembler::DisassembleAllFunctionsInClasses(FOutputDevice& Ar, const FString& ClassnameSubstring) { FKismetBytecodeDisassembler Disasm(Ar); for (TObjectIterator<UClass> ClassIter; ClassIter; ++ClassIter) { UClass* Class = *ClassIter; FString ClassName = Class->GetName(); if (FCString::Strfind(*ClassName, *ClassnameSubstring)) { Ar.Logf(TEXT("Processing class %s"), *ClassName); for (TFieldIterator<UFunction> FunctionIter(Class, EFieldIteratorFlags::ExcludeSuper); FunctionIter; ++FunctionIter) { UFunction* Function = *FunctionIter; FString FunctionName = Function->GetName(); Ar.Logf(TEXT(" Processing function %s (%d bytes)"), *FunctionName, Function->Script.Num()); Disasm.DisassembleStructure(Function); Ar.Logf(TEXT("")); } Ar.Logf(TEXT("")); Ar.Logf(TEXT("-----------")); Ar.Logf(TEXT("")); } } }
/** * Finds the event version of a UFunction for a given Blueprint * * @param InBlueprint The Blueprint to find the function within * @param InFunction The Function to find an event version of * * @return Event Function used by the given Blueprint for the given Function */ UFunction* FindEventFunctionForClass(const UBlueprint* InBlueprint, const UFunction* InFunction) { // Look at all of the Blueprint parent's functions for an event for (TFieldIterator<UFunction> FunctionIt(InBlueprint->ParentClass, EFieldIteratorFlags::IncludeSuper); FunctionIt; ++FunctionIt) { UFunction* Function = *FunctionIt; if(Function->GetName() == InFunction->GetName()) { return Function; } } return NULL; }
CefRefPtr<CefDictionaryValue> FWebJSScripting::ConvertObject(UObject* Object) { CefRefPtr<CefDictionaryValue> Result = CefDictionaryValue::Create(); RetainBinding(Object); UClass* Class = Object->GetClass(); CefRefPtr<CefListValue> MethodNames = CefListValue::Create(); int32 MethodIndex = 0; for (TFieldIterator<UFunction> FunctionIt(Class, EFieldIteratorFlags::IncludeSuper); FunctionIt; ++FunctionIt) { UFunction* Function = *FunctionIt; MethodNames->SetString(MethodIndex++, *Function->GetName()); } Result->SetString("$type", "uobject"); Result->SetString("$id", *PtrToGuid(Object).ToString(EGuidFormats::Digits)); Result->SetList("$methods", MethodNames); return Result; }
/** * Checks if the passed in function is available as an event for the Blueprint * * @param InBlueprint The Blueprint to check for validity with * @param InFunction The Function to check for being available as an event * * @return Returns true if the function is available as an event in the Blueprint */ bool IsFunctionAvailableAsEvent(const UBlueprint* InBlueprint, const UFunction* InFunction) { // Build a list of all interface classes either implemented by this blueprint or through inheritance TArray<UClass*> InterfaceClasses; FBlueprintEditorUtils::FindImplementedInterfaces(InBlueprint, true, InterfaceClasses); InterfaceClasses.Add(InBlueprint->ParentClass); // Grab the list of events to be excluded from the override list const FString ExclusionListKeyName = TEXT("KismetHideOverrides"); TArray<FString> ExcludedEventNames; if( InBlueprint->ParentClass->HasMetaData(*ExclusionListKeyName) ) { const FString ExcludedEventNameString = InBlueprint->ParentClass->GetMetaData(*ExclusionListKeyName); ExcludedEventNameString.ParseIntoArray(ExcludedEventNames, TEXT(","), true); } const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); if (K2Schema->FunctionCanBePlacedAsEvent(InFunction) && !ExcludedEventNames.Contains(InFunction->GetName())) { // Check all potential interface events using the class list we build above for(auto It = InterfaceClasses.CreateConstIterator(); It; It++) { const UClass* Interface = (*It); for (TFieldIterator<UFunction> FunctionIt(Interface, EFieldIteratorFlags::IncludeSuper); FunctionIt; ++FunctionIt) { UFunction* Function = *FunctionIt; if(Function->GetName() == InFunction->GetName()) { return true; } } } } return false; }
void UConsole::BuildRuntimeAutoCompleteList(bool bForce) { #if !UE_BUILD_SHIPPING if (!bForce) { // unless forced delay updating until needed bIsRuntimeAutoCompleteUpToDate = false; return; } // clear the existing tree //@todo - probably only need to rebuild the tree + partial command list on level load for (int32 Idx = 0; Idx < AutoCompleteTree.ChildNodes.Num(); Idx++) { FAutoCompleteNode *Node = AutoCompleteTree.ChildNodes[Idx]; delete Node; } AutoCompleteTree.ChildNodes.Empty(); const UConsoleSettings* ConsoleSettings = GetDefault<UConsoleSettings>(); // copy the manual list first AutoCompleteList.Empty(); AutoCompleteList.AddZeroed(ConsoleSettings->ManualAutoCompleteList.Num()); for (int32 Idx = 0; Idx < ConsoleSettings->ManualAutoCompleteList.Num(); Idx++) { AutoCompleteList[Idx] = ConsoleSettings->ManualAutoCompleteList[Idx]; } // console variables { IConsoleManager::Get().ForEachConsoleObject( FConsoleObjectVisitor::CreateStatic< TArray<struct FAutoCompleteCommand>& >( &FConsoleVariableAutoCompleteVisitor::OnConsoleVariable, AutoCompleteList ) ); } // iterate through script exec functions and append to the list int32 ScriptExecCnt = 0; for (TObjectIterator<UFunction> It; It; ++It) { UFunction *Func = *It; // Determine whether or not this is a level script event that we can call (must be defined in the level script actor and not in parent, and has no return value) const UClass* FuncOuter = Cast<UClass>(Func->GetOuter()); const bool bIsLevelScriptFunction = FuncOuter && (FuncOuter->IsChildOf(ALevelScriptActor::StaticClass())) && (FuncOuter != ALevelScriptActor::StaticClass()) && (Func->ReturnValueOffset == MAX_uint16) && (Func->GetSuperFunction() == NULL); // exec functions that either have no parent, level script events, or are in the global state (filtering some unnecessary dupes) if ( (Func->HasAnyFunctionFlags(FUNC_Exec) && (Func->GetSuperFunction() == NULL || FuncOuter)) || bIsLevelScriptFunction) { FString FuncName = Func->GetName(); if(FDefaultValueHelper::HasWhitespaces(FuncName)) { FuncName = FString::Printf(TEXT("\"%s\""), *FuncName); } if( bIsLevelScriptFunction ) { FuncName = FString(TEXT("ce ")) + FuncName; } int32 NewIdx = AutoCompleteList.AddZeroed(1); AutoCompleteList[NewIdx].Command = FuncName; // build a help string // append each property (and it's type) to the help string for (TFieldIterator<UProperty> PropIt(Func); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt) { UProperty *Prop = *PropIt; FuncName = FString::Printf(TEXT("%s %s[%s]"),*FuncName,*Prop->GetName(),*Prop->GetCPPType()); } AutoCompleteList[NewIdx].Desc = FuncName; ScriptExecCnt++; } } // enumerate maps TArray<FString> Packages; for (int32 PathIdx = 0; PathIdx < ConsoleSettings->AutoCompleteMapPaths.Num(); ++PathIdx) { FPackageName::FindPackagesInDirectory(Packages, FString::Printf(TEXT("%s%s"), *FPaths::GameDir(), *ConsoleSettings->AutoCompleteMapPaths[PathIdx])); } // also include maps in this user's developer dir FPackageName::FindPackagesInDirectory(Packages, FPaths::GameUserDeveloperDir()); for (int32 PackageIndex = 0; PackageIndex < Packages.Num(); PackageIndex++) { FString Pkg = Packages[PackageIndex]; int32 ExtIdx = Pkg.Find(*FPackageName::GetMapPackageExtension(),ESearchCase::IgnoreCase, ESearchDir::FromEnd); FString MapName; if (ExtIdx != INDEX_NONE && Pkg.Split(TEXT("/"),NULL,&MapName,ESearchCase::CaseSensitive, ESearchDir::FromEnd)) { // try to peel off the extension FString TrimmedMapName; if (!MapName.Split(TEXT("."),&TrimmedMapName,NULL,ESearchCase::CaseSensitive, ESearchDir::FromEnd)) { TrimmedMapName = MapName; } int32 NewIdx; // put _P maps at the front so that they match early, since those are generally the maps we want to actually open if (TrimmedMapName.EndsWith(TEXT("_P"))) { NewIdx = 0; AutoCompleteList.InsertZeroed(0,3); } else { NewIdx = AutoCompleteList.AddZeroed(3); } AutoCompleteList[NewIdx].Command = FString::Printf(TEXT("open %s"),*TrimmedMapName); AutoCompleteList[NewIdx].Desc = FString::Printf(TEXT("open %s"),*TrimmedMapName); AutoCompleteList[NewIdx+1].Command = FString::Printf(TEXT("travel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+1].Desc = FString::Printf(TEXT("travel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+2].Command = FString::Printf(TEXT("servertravel %s"),*TrimmedMapName); AutoCompleteList[NewIdx+2].Desc = FString::Printf(TEXT("servertravel %s"),*TrimmedMapName); //MapNames.AddItem(Pkg); } } // misc commands { int32 NewIdx = AutoCompleteList.AddZeroed(1); AutoCompleteList[NewIdx].Command = FString(TEXT("open 127.0.0.1")); AutoCompleteList[NewIdx].Desc = FString(TEXT("open 127.0.0.1 (opens connection to localhost)")); } #if STATS // stat commands { const TSet<FName>& StatGroupNames = FStatGroupGameThreadNotifier::Get().StatGroupNames; int32 NewIdx = AutoCompleteList.AddZeroed(StatGroupNames.Num()); for (const FName& StatGroupName : StatGroupNames) { FString Command = FString(TEXT("Stat ")); Command += StatGroupName.ToString().RightChop(sizeof("STATGROUP_") - 1); AutoCompleteList[NewIdx].Command = Command; AutoCompleteList[NewIdx].Desc = FString(); NewIdx++; } } #endif // build the magic tree! for (int32 ListIdx = 0; ListIdx < AutoCompleteList.Num(); ListIdx++) { FString Command = AutoCompleteList[ListIdx].Command.ToLower(); FAutoCompleteNode *Node = &AutoCompleteTree; for (int32 Depth = 0; Depth < Command.Len(); Depth++) { int32 Char = Command[Depth]; int32 FoundNodeIdx = INDEX_NONE; TArray<FAutoCompleteNode*> &NodeList = Node->ChildNodes; for (int32 NodeIdx = 0; NodeIdx < NodeList.Num(); NodeIdx++) { if (NodeList[NodeIdx]->IndexChar == Char) { FoundNodeIdx = NodeIdx; Node = NodeList[FoundNodeIdx]; NodeList[FoundNodeIdx]->AutoCompleteListIndices.Add(ListIdx); break; } } if (FoundNodeIdx == INDEX_NONE) { FAutoCompleteNode *NewNode = new FAutoCompleteNode(Char); NewNode->AutoCompleteListIndices.Add(ListIdx); Node->ChildNodes.Add(NewNode); Node = NewNode; } } } bIsRuntimeAutoCompleteUpToDate = true; //PrintNode(&AutoCompleteTree); #endif }
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")); } }
void FBlueprintStatsModule::DumpBlueprintStats() { TArray<FBlueprintStatRecord> Records; for (TObjectIterator<UBlueprint> BlueprintIt; BlueprintIt; ++BlueprintIt) { UBlueprint* Blueprint = *BlueprintIt; new (Records) FBlueprintStatRecord(Blueprint); } // Now merge them FBlueprintStatRecord Aggregate(NULL); for (const FBlueprintStatRecord& SourceRecord : Records) { Aggregate.MergeAnotherRecordIn(SourceRecord); } // Sort the lists Aggregate.NodeCount.ValueSort(TGreater<int32>()); Aggregate.FunctionCount.ValueSort(TGreater<int32>()); Aggregate.FunctionOwnerCount.ValueSort(TGreater<int32>()); Aggregate.RemoteMacroCount.ValueSort(TGreater<int32>()); // Print out the merged record UE_LOG(LogBlueprintStats, Log, TEXT("Blueprint stats for %d blueprints in %s"), Records.Num(), GGameName); UE_LOG(LogBlueprintStats, Log, TEXT("%s"), *Aggregate.ToString(true)); UE_LOG(LogBlueprintStats, Log, TEXT("%s"), *Aggregate.ToString(false)); UE_LOG(LogBlueprintStats, Log, TEXT("\n")); // Print out the node list UE_LOG(LogBlueprintStats, Log, TEXT("NodeClass,NumInstances")); for (const auto& NodePair : Aggregate.NodeCount) { UE_LOG(LogBlueprintStats, Log, TEXT("%s,%d"), *(NodePair.Key->GetName()), NodePair.Value); } UE_LOG(LogBlueprintStats, Log, TEXT("\n")); // Print out the function list UE_LOG(LogBlueprintStats, Log, TEXT("FunctionPath,ClassName,FunctionName,NumInstances")); for (const auto& FunctionPair : Aggregate.FunctionCount) { UFunction* Function = FunctionPair.Key; UE_LOG(LogBlueprintStats, Log, TEXT("%s,%s,%s,%d"), *(Function->GetPathName()), *(Function->GetOuterUClass()->GetName()), *(Function->GetName()), FunctionPair.Value); } UE_LOG(LogBlueprintStats, Log, TEXT("\n")); // Print out the macro list UE_LOG(LogBlueprintStats, Log, TEXT("MacroPath,MacroName,NumInstances")); for (const auto& MacroPair : Aggregate.RemoteMacroCount) { UEdGraph* MacroGraph = MacroPair.Key; UE_LOG(LogBlueprintStats, Log, TEXT("%s,%s,%d"), *(MacroGraph->GetPathName()), *(MacroGraph->GetName()), MacroPair.Value); } UE_LOG(LogBlueprintStats, Log, TEXT("\n")); }