Announcement

Collapse
No announcement yet.

Get all children classes of a BP in a function library

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Get all children classes of a BP in a function library

    I'm brand new to the Unreal 4 API and C++ is still a new language to me, so I do most of my work in blueprints and my team does _all_ of their work in blueprints.

    Everything is going fine until we came across the problem that for an item crafting system for an RPG we need a way to get all children classes of a blueprint class.

    Basically my jr scripter created the core setup for the crafting system by creating a BP_masterCraftingRecipie class from the actor class. It holds a struct with all the information such as an unlocked bool, class to spawn, barsIron needed int, craftinLvlRqd int etc.

    So he went ahead and created about 50 children classes that all inherit from that master class for all the items we currently have craftable.

    Then onto me, the GUI guy. So I set it up so that we have an unlocked and locked "recipie list" in scrollboxes. Obviously I dont want to manually add hundreds of widgets and the logic associated with them 1 button by 1 button at a time. I'd rather just basically


    pseduo BP script

    Code:
    OnConstruct()
    {
    RecipieArray ChildClass = GetAllChildClasses(BP_masterCraftingRecipie)
    forEach(ChildClass)
    {
    if(Unlocked == true) { AddToChild(ScrollBoxWidget, RecipieButton) }
    else { AddToChild(ScrollBoxWidgetLocked, RecipieButton) }
    }
    }
    And for the recipie button widget it would go something like



    pseduo BP script

    Code:
    forEach(ChildClass""...
    Break craftingRecipeStruct & getRecipeName
    set ButtonText = getRecipieName



    So that basically everytime the game is run, it iterates through every BP child class of BP_masterCraftingRecipie, gets the "recipieName" member of the strut variable it holds (inherited from the master class) set the button text to it (this widget is just a sizebox, button, and text on the button).

    Then when the crafting screen is opened, it adds each recipie button widget with its respective name and when its clicked it gets that specific childs class struct info and displays it.

    So where I'm stuck on, is how to get all the children class so that I can set the button names (to start, later to get all the rest of the structs data).

    Since my team works purely in BP and I work 99.9% in it, I thought a Function Library c++ class with BlueprintCallable would be best or BlueprintPure i guess doesnt matter. I've seen a couple examples online I'll have to test, but since I'm so new to the API and to C++ (only C# and JS experience before UE4) but any tips on getting the children class of a master parent class when none of them are in the world would be great. Any tips at all would be great.

    I'm willing to send the project to anyone thats really intrested in helping.


    Heres a picture of the prototype screen setup I came up with to better illustrate what Im trying to do, instead of manually adding each recipie as it gets created (plus just the fact of doing it manually) i want to future proof it by using the struct data and child widgets, while retaining BP functionality for my team and I.



    Thanks.

    Edit: Heres another one, of how I'd build the array of recipes obviously i'm going to need a C++ function that is Blueprintcallable or ""pure.

    Click image for larger version

Name:	U5a9v6J.png
Views:	1
Size:	235.2 KB
ID:	1151097


    So far this is all I can find, I'll do some playing around with it and see if it can be added to a function library and be callable. But my UE4 APi and CPP knowledge is so low, its almost unreadable

    Code:
     FClass* FClasses::FindClass(const TCHAR* ClassName) const
     {
         check(ClassName);
     
         UObject* ClassPackage = ANY_PACKAGE;
     
         if (UClass* Result = FindObject<UClass>(ClassPackage, ClassName))
             return (FClass*)Result;
     
         if (UObjectRedirector* RenamedClassRedirector = FindObject<UObjectRedirector>(ClassPackage, ClassName))
             return (FClass*)CastChecked<UClass>(RenamedClassRedirector->DestinationObject);
     
         return nullptr;
     }

    And something like this obviously only returns the BP_craftingMaster since its hidden in the level.
    Click image for larger version

Name:	KAr9eTi.png
Views:	1
Size:	302.3 KB
ID:	1151102

    I take it the code above searches through all the classes and looks for any that point to the ClassName parameter? I'll need to figure out how to make it BP callable and return a TArray<UClasses>


    Edit: I found this much simpiler attempt, might have a go at playing with its statments anyone know if its viable? I'll play with it later but it looks like somone checking for stuff already in the level and thus accessable.


    Code:
     void AMNCharacter::CheckForInteractables(){
         TArray<AActor*> ThingsImTouching;
         GetOverlappingActors(ThingsImTouching);
         for (AActor* Thing : ThingsImTouching)
         {
             if (Thing->GetActorClass() == AMNPickup)
             {
     
             }
     
         }
     }
    Last edit before I stop googleing for now: https://answers.unrealengine.com/que...m-a-class.html
    that is exactly my problem, trying to populate a GUI with classes derived from a master class. And this answer seems perfect, does anyone know whats been long depreciated and needs replacing, I should be able to figure out how to return an array of all the classes it finds this way, its alot more readable than what I've found so far, but its from 4.3

    Code:
         FAssetRegistryModule* AssetRegistryModule = &FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
         
         TArray<FAssetData> AssetData;
         FARFilter Filter;
         Filter.ClassNames.Add( UBlueprint::StaticClass()->GetFName() ); //get blueprints
         Filter.PackagePaths.Add("/Game/Blueprints/RoomModel"); //from location
         AssetRegistryModule->Get().GetAssets(Filter, AssetData);
         //AssetRegistryModule->Get().GetAssetsByClass(Class->GetFName(), AssetData);
         
         for (TArray<FAssetData>::TConstIterator PkgIter = AssetData.CreateConstIterator(); PkgIter; ++PkgIter)
         {
             FAssetData Asset = *PkgIter;
             UBlueprint* BlueAsset = Cast<UBlueprint>(Asset.GetAsset());
             if (BlueAsset->ParentClass == ARoomConnection::StaticClass()){
                 GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, Asset.AssetName.GetPlainNameString());
             }
         }
    Last edited by Nsomnia; 06-03-2015, 04:49 PM.
    Tek LLC a personal Candaian Company running BlenderTek & UnrealTek is currently looking for help to bring back submarine simulator gaming with a new genre of sub sims: Cold War! (1945-1991) Operation: Trident SubSim Dev Diary Thread - Donations

    #2
    This is as close as I can get copy pasting what I can google and rebuilding for hours trying to follow the errors, but cant even get a single success to test with. I may have to approach this a different way. I'd love to be able to use datatables and class names as one of the columns but it seems 4.9 before thats supported visually.

    .h
    Code:
    // (C) ANTek Studios
    
    #pragma once
    
    #include "Kismet/BlueprintFunctionLibrary.h"
    #include "HelperBPFuncLib.generated.h"
    
    /*Helpful Functions
     * Helpful Functions
     */
    UCLASS()
    class CONTINUITY_API UHelperBPFuncLib : public UBlueprintFunctionLibrary
    {
    	GENERATED_BODY()
    
    public:
    	//Return an array of UClasses that are children classes of an input class
    	UFUNCTION(BlueprintPure, Category = "Utilites|Cpp Helper Functions|Classes")
    		static TArray<UClass*> GetAllChildClasses(FName(TEXT("/Game/Blueprints/Crafting/BP_masterCrafting_C")) const ClassName);
    	
    	
    	
    };
    .cpp
    Code:
    TArray<FClass*> UHelperBPFuncLIB::GetAllChildClasses(FName(TEXT("/Game/Blueprints/Crafting/BP_masterCrafting_C") const ClassName) 
    {
    	check(ClassName);
    
    	UObject* ClassPackage = ANY_PACKAGE;
    
    	if (UClass* Result = FindObject<UClass>(ClassPackage, ClassName))
    		return (FClass*)Result;
    
    	if (UObjectRedirector* RenamedClassRedirector = FindObject<UObjectRedirector>(ClassPackage, ClassName))
    		return (FClass*)CastChecked<UClass>(RenamedClassRedirector->DestinationObject);
    
    	return nullptr;
    }
    Gets me

    HelperBPFuncLib.h(19): error : In HelperBPFuncLib: Missing variable name
    1>Error : Failed to generate code for ContinuityEditor - error code: OtherCompilationError (2)

    I thought ClassName was my variable name.

    I tried replacing the whole parements with a simple FString ClassName and then in the cpp settings ClassName to "\path\to\bp_C" but I get a boat load of errors starting with

    HelperBPFuncLib.h(14): error C2679: binary '=' : no operator found which takes a right-hand operand of type 'TArray<UClass *,FDefaultAllocator>' (or there is no acceptable conversion)F:\UnrealProjects\SURVIVAL_INTERMEDIATE\Continuity\Source\Continuity\HelperBPFuncLib.h(14) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'TArray<UClass *,FDefaultAllocator>' (or there is no acceptable conversion)


    I'm so lost with the API and C++ in general this may be far, far, out of my league.
    Last edited by Nsomnia; 06-04-2015, 05:07 PM.
    Tek LLC a personal Candaian Company running BlenderTek & UnrealTek is currently looking for help to bring back submarine simulator gaming with a new genre of sub sims: Cold War! (1945-1991) Operation: Trident SubSim Dev Diary Thread - Donations

    Comment


      #3
      Did you figure it out?

      Because I tried almost every result from google, and get no results, because of the errors, mostly.
      English is not my native language. So yeaaah. :3

      Comment

      Working...
      X