terça-feira, 5 de janeiro de 2021

TMap: Maps in C++

TMap is another type of container widely used in Unreal Engine. The elements of a Map are key-value pairs. The type of the key can be different from the type of the value. Duplicate keys are not allowed. The search for elements is done using the key value.

This code creates a TMap that can be modified in the editor. The type of the key is FString and the type of the value is float.

UPROPERTY(EditAnywhere, Category=MapExample)
TMap<FString, float> PriceTable;

To add elements to a TMap, use the Add() function passing the key and the value as parameters.

PriceTable.Add( TEXT("Axe"), 37.5f );
PriceTable.Add( TEXT("Hammer"), 25.0f );
PriceTable.Add( TEXT("Spear"), 18.0f );

Use the Remove() function passing the key as a parameter to remove an element from a TMap.

PriceTable.Remove( TEXT("Hammer") );

The Empty() function removes all elements from a TMap.

PriceTable.Empty();

The number of elements in a TMap is obtained using the Num() function. 

int32 NumberOfElements = PriceTable.Num();

The Find() function takes the key as a parameter and returns a pointer to the value associated with the key. If the key is not found, a null pointer is returned (nullptr).

float* PtrPrice = PriceTable.Find( TEXT("Spear") );

Iterating on a TMap can be done using a ranged-based for loop. An element of a TMap is of type TPair that has the variables Key and Value. For simplicity, you can use the C++ auto keyword together with the & operator to define the reference to a TMap element as shown in the code below.

for (auto& ItemPrice : PriceTable)
{
  UE_LOG(LogTemp, Warning, TEXT("%s - %.2f"), *(ItemPrice.Key), ItemPrice.Value);
}

The special character %s will be replaced by the contents of the ItemPrice.Key variable. It is necessary to place the * operator before variables of type FString. The value of ItemPrice.Value will replace the characters %.2f and will be displayed with two decimal digits.


Example usage:

Create a C++ class with the name TestTMap using the Actor class as the parent class. In the TestTMap.h file, add the declaration of the components and of the TMap:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestTMap.generated.h"

UCLASS()
class TUTOPROJECT_API ATestTMap : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATestTMap();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(VisibleAnywhere)
	USceneComponent* RootScene;

	UPROPERTY(VisibleAnywhere)
	UStaticMeshComponent* StaticMesh;
	
	UPROPERTY(EditAnywhere, Category=MapExample)
	TMap<FString, float> PriceTable;
};

A ranged-based for loop will be used in the BeginPlay() function to write on the screen the name and price of the TMap elements. The contents of the TestTMap.cpp file look like this:

#include "TestTMap.h"

ATestTMap::ATestTMap()
{
  // Set this actor to call Tick() every frame.
  PrimaryActorTick.bCanEverTick = true;

  RootScene = CreateDefaultSubobject<USceneComponent>("RootScene");
  RootComponent = RootScene;

  StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>("StaticMesh");
  StaticMesh->SetupAttachment(RootScene);
}

// Called when the game starts or when spawned
void ATestTMap::BeginPlay()
{
  Super::BeginPlay();

  FString Message;
  
  if(PriceTable.Num() > 0)
  {
    Message = FString::Printf(TEXT("Number of elements in the Map: %d"),
                              PriceTable.Num());

    if(GEngine)
    {	
     GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, Message);
	  
	  
     for(auto& ItemPrice : PriceTable)
     {
      Message = FString::Printf(TEXT("%s - %.2f"), *(ItemPrice.Key), ItemPrice.Value);
		
      GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, Message);
     }
    }	  
  }	    
}

// Called every frame
void ATestTMap::Tick(float DeltaTime)
{
  Super::Tick(DeltaTime);
}

Compile the C++ code and add an instance of TestTMap at the level. Add elements to TMap using the Details tab of the instance. You will not be able to add a duplicate key.


Start the game and see on the screen the names and prices of the elements added to the TMap:


Table of Contents C++