terça-feira, 5 de janeiro de 2021

TMap: Maps em C++

TMap é outro tipo de container muito usado na Unreal Engine. Os elementos de um Map são pares de chave-valor. O tipo da chave pode ser diferente do tipo do valor. Não é permitido ter chaves duplicadas. A busca por elementos é feita usando o valor da chave.

Este código cria um TMap que pode ser modificado no editor. O tipo da chave é FString e o tipo do valor é float.

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

Para adicionar elementos em um TMap, use a função Add() passando como parâmetros a chave e o valor.

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

Use a função Remove() passando a chave como parâmetro para remover um elemento de um TMap.

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

A função Empty() remove todos os elementos de um TMap.

PriceTable.Empty();

A quantidade de elementos de um TMap é obtido usando a função Num()

int32 NumberOfElements = PriceTable.Num();

A função Find() recebe como parâmetro a chave e retorna um ponteiro para o valor associado à chave. Se a chave não for encontrada será retornado um ponteiro nulo (nullptr).

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

A iteração em um TMap pode ser feita usando um ranged-based for loop. Um elemento de um TMap é do tipo TPair que possui as variáveis Key e Value. Para simplificar, você pode usar a palavra chave C++ auto junto com o operador & para definir a referência para um elemento do TMap como mostra o código abaixo.

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

O caractere especial %s será substituído pelo conteúdo da variável ItemPrice.Key. É necessário colocar o operador * antes de variáveis do tipo FString. O valor de ItemPrice.Value substituirá os caracteres %.2f e será exibido com duas casas decimais.


Exemplo de uso:

Crie uma classe C++ com o nome TestTMap usando como classe pai a classe Actor. No arquivo TestTMap.h, adicione a declaração dos componentes e do 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;
};

Será usado um ranged-based for loop na função BeginPlay() para escrever na tela o nome e preço dos elementos do TMap. O conteúdo do arquivo TestTMap.cpp fica assim:

#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 o código C++ e adicione uma instância de TestTMap no nível. Adicione elementos no TMap usando a aba Details da instância. Você não conseguirá adicionar uma chave duplicada.


Inicie o jogo e veja na tela os nomes e preços dos elementos adicionados ao TMap:


Sumário C++