Modifying Append Array

Hi guys,

I’m trying to make a custom version of the Append array BP node that returns the resulted merged array as an output (the original has no outputs). It’s supposed to be very easy, but as a C++ newbie, I keep failing without fully understanding the code. Could somebody please help me out?

The original function seems to be defined in KismetArrayLibrary.h:


   UFUNCTION(BlueprintCallable, CustomThunk, meta=(DisplayName = "Append Array", CompactNodeTitle = "APPEND", ArrayParm = "TargetArray,SourceArray", ArrayTypeDependentParams = "SourceArray"), Category="Utilities|Array")
    static void Array_Append(const TArray<int32>& TargetArray, const TArray<int32>& SourceArray);


But here’s when the problems begin. First, for some reason, the declaration takes in value type, even if the blueprint accepts all array types. The function also doesn’t seem to have a definition in KismetArrayLibrary.cpp as usual—the .cpp only has some complex convoluted internal GenericArray_Append() function instead (which seems to more relevant but doesn’t seem to be exposed to BP and has different parameters than the BP node). However, it seems to be related to this template in GeneratedCodeHelpers.h:


    template<typename T, typename U>
    static void Array_Append(const TArray<T>& TargetArray, const TArray<U>& SourceArray)
    {
        const_cast<TArray<T>*>(&TargetArray)->Append(SourceArray);
    }

This is where my limited knowledge of C++ fails me. I don’t know how make a modified copy of the function that takes generic TArray types and returns generic TArray output. Once I define the type sd , the function works, but now it can only operate on integers, not generic arrays:


  **TArray<int32>** void Array_Append(const TArray<int32>& TargetArray, const TArray<int32>& SourceArray);
{
const_cast<TArray<int32>*>(&TargetArray)->Append(SourceArray);
return TargetArray;
}


Could somebody who understands what is going on here please help me out? Any feedback at all will be extremely welcome.

Hi, there. It is intended to do what it says! If you consult the Array.h file, you will find a routine



   /**
     * Adds an initializer list of elements to the end of the TArray.
     *
     * @param InitList The initializer list of elements to add.
     * @see Add, Insert
     */
    FORCEINLINE void Append(std::initializer_list<ElementType> InitList)
    {
        int32 Count = (int32)InitList.size();

        int32 Pos = AddUninitialized(Count);
        ConstructItems<ElementType>(GetData() + Pos, InitList.begin(), Count);
    }


Thus the code



 (&TargetArray)->Append(SourceArray) 

essentially adds the SourceArray at the end of TargetArray. Finally the appended TArray (TargetArray) pointer is returned by “casting away” the constness (for more information on const_cast, see here).

I’m having a problem with duplicating the full functionality of the function and making its exposed version take generic array types, just like the original BP node does. I rewrote the second part of my original post to be more intelligible. Sorry for not being clear enough from the start. 100% my fault.

Add Followed code to Blueprint Function Library class(.h file) and

/**
*Append an array to another array
*
*@param TargetArray The array to add the source array to
*@param SourceArray The array to add to the target array
*/
UFUNCTION(BlueprintCallable, CustomThunk, meta = (DisplayName = "Append Array", CompactNodeTitle = "APPEND", ArrayParm = "TargetArray,SourceArray,AppendArray", ArrayTypeDependentParams = "SourceArray,AppendArray"), Category = "Utilities|Array")
static void Array_AppendV2(const TArray<int32>& TargetArray, const TArray<int32>& SourceArray, TArray<int32>& AppendArray);

DECLARE_FUNCTION(execArray_AppendV2)
{
// Retrieve the target array
Stack.MostRecentProperty = nullptr;
Stack.StepCompiledIn<UArrayProperty>(NULL);
void* TargetArrayAddr = Stack.MostRecentPropertyAddress;
UArrayProperty* TargetArrayProperty = Cast<UArrayProperty>(Stack.MostRecentProperty);
if (!TargetArrayProperty)
{
Stack.bArrayContextFailed = true;
return;
}
// Retrieve the source array
Stack.MostRecentProperty = nullptr;
Stack.StepCompiledIn<UArrayProperty>(NULL);
void* SourceArrayAddr = Stack.MostRecentPropertyAddress;
UArrayProperty* SourceArrayProperty = Cast<UArrayProperty>(Stack.MostRecentProperty);
if (!SourceArrayProperty)
{
Stack.bArrayContextFailed = true;
return;
}

// Retrieve the source array
Stack.MostRecentProperty = nullptr;
Stack.StepCompiledIn<UArrayProperty>(NULL);
void* AppendArrayAddr = Stack.MostRecentPropertyAddress;
UArrayProperty* AppendArrayProperty = Cast<UArrayProperty>(Stack.MostRecentProperty);
if (!AppendArrayProperty)
{
Stack.bArrayContextFailed = true;
return;
}

if (AppendArrayProperty->SameType(TargetArrayProperty))
{
AppendArrayProperty->CopyValuesInternal(AppendArrayAddr, TargetArrayAddr, 1);
}
else
{
return;
}

P_FINISH;
P_NATIVE_BEGIN;
UKismetArrayLibrary::GenericArray_Append(AppendArrayAddr, AppendArrayProperty, SourceArrayAddr, SourceArrayProperty);
P_NATIVE_END;
}

After build visual studio

https://forums.unrealengine.com/core/image/gif;base64
241de94bc21cd51736199518c748cdf8845c2aee.jpeg