from normal C++ class to UCLASS

hiho @ all :slight_smile:

I´m new at UE4, so if I do something horrible wrong, tell it to me. I´m happy about everything I can learn

The question: is it Possible to make a Blueprint out of a normal C++ class? … it should… with the right includes …
because I made a C++ class “Graph” for the University, and I like to implement it in to a game as base of a Skill-Tree.
It should be “UCLASS(Blueprintable)” to make it simple and clear to read. And also Native, course I do the Garbage collection for the System :slight_smile:

The code is this:



#include <iostream>
#include <list>

template<class T>
class Graph
{


public:
    T element;
    std::list<Graph<T>*> childs;
    std::list<Graph<T>*> parents;
    Graph();
    Graph(T);
    ~Graph();
    Graph<T>* makeNewChild(T);
    bool pushChildtoParent(Graph<T>*);
    Graph<T>* makeNewChild(Graph<T>*);
    bool deleteChild(Graph<T>*);
    bool makeParent(Graph<T>*);
    T getElement();
    bool leaf;
};

template<class T>
Graph<T>::Graph()
{
    leaf = true;
    element = nullptr;
}

template<class T>
Graph<T>::Graph(T element) : element(element)
{
    leaf = true;
}

template<class T>
Graph<T>::~Graph()
{
    if(!leaf)
        {
            for (auto it = childs.begin(); it != childs.end();)
            {
                // wenn das kind nicht mehrere Väter hat, denen ich es nicht weg nehmen will
                if ((**it).parents.size()<2)
                {
                     delete *it ++;
                }
                else{
                    (**it).parents.remove(this);
                    it ++;
                }
            }
        }
    if (!(*this).parents.empty())
    {
         for (auto it = parents.begin(); it != parents.end(); it++)
        {
            //alle Väter vergessen dieses Kind, damit es ohne folgen beseitigt werden kann
            (**it).deleteChild(this);
        }
    }
}

template<class T>
T Graph<T>::getElement()
{
    return (*this).element;
}

template<class T>
bool Graph<T>::deleteChild(Graph<T>* tokill)
{
    for (auto it = childs.begin(); it != childs.end(); it++)
    {
        if( (*it)==tokill){
            childs.erase(it);
            return true;
        }
    }
    // Error code hier einfügen
    std::cout<<"Leider dieses Kind nicht gefunden. Error main2.h at line 61"<<std::endl;
    return false;
}

//eingane der zu setzende Vater. Wenn setzen des Vaters gelingt, wird er in die Liste der Väter aufgenommen

template<class T>
bool Graph<T>::makeParent (Graph<T>* newParent){
    if ((*newParent).pushChildtoParent(this)){
        parents.push_back(newParent);
        return true;
    }
    else{
        //Error code hier einfügen
        std::cout<<"das Erzeugen dieses Kindes bei dem Vater war nicht möglich. Error main2.h at line 76"<<std::endl;
        return false;
    }
}

template<class T>
bool Graph<T>::pushChildtoParent(Graph<T>* inTree){
    childs.push_back(inTree);
    leaf = false;
    return true;
}

template<class T>
Graph<T>* Graph<T>::makeNewChild(T inValue)
{
    Graph<T>* contain = new Graph<T>(inValue);
    childs.push_back(contain);
    (*contain).parents.push_back(this);
    leaf = false;
    return contain;
}

template<class T>
Graph<T>* Graph<T>::makeNewChild(Graph<T>* inTree)
{
    childs.push_back(inTree);
    (*inTree).parents.push_back(this);
    leaf = false;
    return inTree;
}


Or should I rewrite it, with out the Template?
course I´m sure, the type T will be " Skill* "

I think making on this point Blueprints will make the effort for the after develop balancing from skills and so on better, faster and easy to handle.

It would be nice if you can help me on this point :slight_smile:

Kind regards
EvD

Ps.: I hope I´m right hear, and should not post it under the blue print section :slight_smile:

This is your 3rd post on the same thing and yet this is a different login.

I delete them all…
I thought something was wrong course the Post was not appear after 4 hours xD
So I try it again and again

Sorry for this

I don’t believe you can use templates with UCLASS (at least, not without a lot of macro customization). However, if you remove the template, the rest should be trivial. Use TList instead of std::list and then just go from there.

hiho

now I use TArray instead of std::list …
but now UE4 Crashes xD

my Code:

SkiGr.h




UCLASS(Blueprintable, BlueprintType)
class DYNAMO_API USkiGr : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()

public:
    ASkill * element;
    TArray<USkiGr*> childs;
    TArray<USkiGr*> parents;
    USkiGr();
    USkiGr(ASkill* );
    ~USkiGr();
    USkiGr* makeNewChild(USkiGr* inTree);
    UFUNCTION(BlueprintCallable, category = "Own|Graph")
    USkiGr* makeNewChild(ASkill* inValue);
    bool pushChildtoParent(USkiGr* );
    UFUNCTION()
    bool deleteChild(USkiGr* );
    UFUNCTION(BlueprintCallable, category = "Own|Graph")
    bool makeParent(USkiGr* newParent);
    UFUNCTION(BlueprintCallable, category = "Own|Graph")
    ASkill* getElement();
    bool leaf;

};



and SkiGr.cpp



// Fill out your copyright notice in the Description page of Project Settings.

#include "SkiGr.h"


USkiGr::USkiGr()
{
    leaf = true;
    element = nullptr;
}


USkiGr::USkiGr(ASkill* element) : element(element)
{
    leaf = true;
}


USkiGr::~USkiGr()
{
    if (!leaf)
    {
        for (int it = childs.Num()-1; it>=0 ;it--)
        {
            // wenn das kind nicht mehrere Väter hat, denen ich es nicht weg nehmen will
            if ((*childs[it]).parents.Num()<2)
            {
                childs[it]->ConditionalBeginDestroy();
                childs[it] = nullptr;
                childs.Remove(childs[it]);
            }
            else {
                (*childs[it]).parents.Remove(this);
                it++;
            }
        }
    }
    if (!(*this).parents.Emplace())
    {
        for (int it = 0; it < parents.Num(); it++)
        {
            //alle Väter vergessen dieses Kind, damit es ohne folgen beseitigt werden kann
            (*parents[it]).deleteChild(this);
        }
    }
}


ASkill* USkiGr::getElement()
{
    return (*this).element;
}


bool USkiGr::deleteChild(USkiGr* tokill)
{

    {
        for (int it = 0; it < childs.Num(); it++)
        {
            if (childs[it] == tokill) {
                childs.Remove(childs[it]);
                return true;
            }
        }
    }
    // Error code hier einfügen
    return false;
}

//eingane der zu setzende Vater. Wenn setzen des Vaters gelingt, wird er in die Liste der Väter aufgenommen


bool USkiGr::makeParent(USkiGr* newParent) {
    if ((*newParent).pushChildtoParent(this)) {
        parents.Add(newParent);
        return true;
    }
    else {
        //Error code hier einfügen
        return false;
    }
}


bool USkiGr::pushChildtoParent(USkiGr* inTree) {
    childs.Add(inTree);
    leaf = false;
    return true;
}


USkiGr* USkiGr::makeNewChild(ASkill* inValue)
{
    USkiGr* contain = NewObject<USkiGr>(inValue);
    childs.Add(contain);
    (*contain).parents.Add(this);
    leaf = false;
    return contain;
}


USkiGr* USkiGr::makeNewChild(USkiGr* inTree)
{
    childs.Add(inTree);
    (*inTree).parents.Add(this);
    leaf = false;
    return inTree;
}


I think, it shoud be a Memory-Problem that I miss something with the GC, ore It crash curse of the TArray :confused:
it would be nice, if you can help me at this point …

The only help, UE4 tell me is this
Unbenannt2.PNG
and if I start it at VS, this is all I get

Unbenannt2.PNG
(Triggered exception: read access violation “this” was a “nptr”)
(it is not possible to make it at VS English curse I have to Download the Language and I have at the moment only 0,01Mb/s, if I have WLAN at all xD)

it would be nice, if you can help me :slight_smile:

Best wishes
EvD

By looking at the screenshot, my guess would be that you should check if the array has at least 1 element before trying to access the first element.
That means you should be doing something like :


if(childs.Num() > 0 && childs[0] != nullptr)
{
...
}

It’s worth nothing that if those TArray’s are the only reference to the objects you are creating, it’s possible they are being garbage collected because the arrays are not tagged with UPROPERTY(). Marking a variable with UPROPERTY() will prevent it from being Garbage Collected - and when you set the value to null, the Garbage Collector should come and pick it up (providing it’s a UObject).

However, it’s worth pointing out that you’re class is a child of a BlueprintFunctionLibrary which is not design to store member variables at all (you can, but I don’t know if UHT will throw an error if you try to store variables there). I’m not sure what USkiGr is meant to be but a normal UObject would probably suffice in this case.