Binary ‘==’: no operator found? FTransform == FTransform

The guy is eating his computer :smile:
For not solving it. If he converts his data outside ftransform data then he can compare it without problems.

2 Likes


compiler says no instance of overload function Add

yep then it only works in unreal components for meshes then for those classes.

You can use a capture then to capture the int index, I doubt a simple convertion in raw c++ will work with Fvectors and Frotators, because they are modified I think from normal Vectors from c++

Are you still running into the FTransform comparison issue? quite a few posts made while I was away. If the library example I made for you generates the error that a property is not accessible, then use the public methods on FTransform. I see now it also got existing methods for testing for equality with tolerances, making the library obsolete.
Just check the FTransform header file it explains itself.

	// Test if A's rotation equals B's rotation, within a tolerance. Preferred over "A.GetRotation().Equals(B.GetRotation())" because it is faster on some platforms.
	FORCEINLINE static bool AreRotationsEqual(const FTransform& A, const FTransform& B, float Tolerance=KINDA_SMALL_NUMBER)
	{
		return A.Private_RotationEquals(B.Rotation, ScalarRegister(Tolerance));
	}

	// Test if A's translation equals B's translation, within a tolerance. Preferred over "A.GetTranslation().Equals(B.GetTranslation())" because it avoids VectorRegister->FVector conversion.
	FORCEINLINE static bool AreTranslationsEqual(const FTransform& A, const FTransform& B, float Tolerance=KINDA_SMALL_NUMBER)
	{
		return A.Private_TranslationEquals(B.Translation, ScalarRegister(Tolerance));
	}

	// Test if A's scale equals B's scale, within a tolerance. Preferred over "A.GetScale3D().Equals(B.GetScale3D())" because it avoids VectorRegister->FVector conversion.
	FORCEINLINE static bool AreScale3DsEqual(const FTransform& A, const FTransform& B, float Tolerance=KINDA_SMALL_NUMBER)
	{
		return A.Private_Scale3DEquals(B.Scale3D, ScalarRegister(Tolerance));
	}


	// Test if this Transform's rotation equals another's rotation, within a tolerance. Preferred over "GetRotation().Equals(Other.GetRotation())" because it is faster on some platforms.
	FORCEINLINE bool RotationEquals(const FTransform& Other, float Tolerance=KINDA_SMALL_NUMBER) const
	{
		return AreRotationsEqual(*this, Other, Tolerance);
	}

	// Test if this Transform's translation equals another's translation, within a tolerance. Preferred over "GetTranslation().Equals(Other.GetTranslation())" because it avoids VectorRegister->FVector conversion.
	FORCEINLINE bool TranslationEquals(const FTransform& Other, float Tolerance=KINDA_SMALL_NUMBER) const
	{
		return AreTranslationsEqual(*this, Other, Tolerance);
	}

	// Test if this Transform's scale equals another's scale, within a tolerance. Preferred over "GetScale3D().Equals(Other.GetScale3D())" because it avoids VectorRegister->FVector conversion.
	FORCEINLINE bool Scale3DEquals(const FTransform& Other, float Tolerance=KINDA_SMALL_NUMBER) const
	{
		return AreScale3DsEqual(*this, Other, Tolerance);
	}

	// Test if all components of the transforms are equal, within a tolerance.
	FORCEINLINE bool Equals(const FTransform& Other, float Tolerance=KINDA_SMALL_NUMBER) const
	{
		const ScalarRegister ToleranceRegister(Tolerance);
		return Private_TranslationEquals(Other.Translation, ToleranceRegister) && Private_RotationEquals(Other.Rotation, ToleranceRegister) && Private_Scale3DEquals(Other.Scale3D, ToleranceRegister);
	}

	// Test if all components of the transform property are equal.
	FORCEINLINE bool Identical(const FTransform* Other, uint32 PortFlags) const
	{
		return Equals(*Other, 0.f);
	}
1 Like

The capture works like this.

SomeVectorArray[index] = FVector(X, Y, Z);

Since they are stored already inside the array you can try.

SomeVectorArray[index] = FVector(The_otherVector_Array);

And now you have the vector array with index points.

[Index] Is the int array, and there for you capture it inside the vector as int index point , same go’s with the arrays.
This is outside components.

Note depending what you want to do, you have to have a return function maybe that says X+Y and maybe + Z and then store them inside the int array, then put the int array as capture [index]

Your int array is named let’s say [index]
If you have x,y,z in the array you could try without the return function, I don’t know what you have, a grid, if you have a mesh in there already then you don’t need to I think. So you just throw the index array with [] in front of the fvector or Ftransform.

The idea is to dump the data inside another array to get rid of Ftransform, to try to dump Ftransform maybe into a regular Fvector array, I don’t know if that works. Even so it should work to get a capture, if you get restrictions then that even for this then that is that.

There are restricted things that still accept some things in c++

1 Like

It’s a hint you don’t have to use Ftransform to transform local to world and then verify, I’m only helping you with your code.

You can use Fvectors directly with a function from the unreal classes.
It’s done all with Fvectors.

1 Like

First check if the type is defined/available for conversion to process the index comparison in integers using operator == , to use the operator, it must be overload for the specified type or define a conversion to a type for which the operator is defined.

hope it helps
cheers!

1 Like

don’t know how to overload but this bp library works, compiles and nice, but I don’t like it, I am trying to define conversion type but I cannot access protected member , variables of class TransformVectorized.h

How to use the public method on FTransform? i have problems accessing the property

now i found this working, generated native blueprint code and filtered 130 lines of code , but this is still not efficient, locations are not correct as expected

if (::IsValid(ItemGroupRef))
    {
        ItemGroupRef->GetAllTransforms(Available);
    }
RandomLocation(Available, Location);
int32 Index = FCustomThunkTemplates::Array_Find(UsedLocations, Location);
bool bIndexDuplicated = UKismetMathLibrary::EqualEqual_IntInt(Index, -1);
	if (!bIndexDuplicated)
	{
		RandomLocation(Available, Location);
	}
	else
		{
			SpawnLocation = Location;
			UsedLocations.Add(SpawnLocation);
		}

I’m removing the track of this thread though

1 Like

its mean already trying public method. but no access

class MyUtils {
public:
	static bool IsEqual_Transform(const FTransform& A, const FTransform& B);
};

why don’t you review your code and dump the Ftransform and find another way from the very start. If you are transforming positions from local relative space to world space then you can use vectors. FVectors with functions that transform back and forth non inverse, and inverse functions.

What are you building anyway ?

Also a return function for the index X+Y = index point at x, y coordinate to calculate where the index is. Or in your case x+y+z.

sort of

function (int x, int y]
function body is.
return x + y

then call on the function before you use the capture and store to int array from the call an x and a y. You may have to create x and y vars for your call, because you need to specify params for the function call.

if you get index points then you can use that to compare between index points.

Blue prints uses the same method.
Notice here it’s called vector to index point on the blueprint scheme with the return node at the end.

1 Like

I’m not sure why is this thread still opened after 75 posts and why are you trying to rewrite a function already present in the engine (that I linked in the 10th post), I tried to read everything and I hope I didn’t miss anything important.

Said that, you are really reinventing the wheel:

.h File
	TArray<FTransform> ArrayOfTransforms;
	TArray<FTransform> UsedLocations;
	FTransform SpawnLocation;

	bool FindRandomSpawnLocation();
.cpp File
bool ATransformTest::FindRandomSpawnLocation()
{
	FTransform RandomLocation = ArrayOfTransforms[FMath::RandRange(0, ArrayOfTransforms.Num() - 1)];

	for (auto CurrentTransform : UsedLocations)
	{
		if(UKismetMathLibrary::EqualEqual_TransformTransform(RandomLocation, CurrentTransform))
		{
			UE_LOG(LogTemp, Warning, TEXT("Location already used"));
			return false;
		}
	}

	SpawnLocation = RandomLocation;
	UsedLocations.Add(RandomLocation);
	return true;
}

The function FindRandomSpawnLocation() gets a random value in the transform array (you should replace it with your GetAllTransform function).
It returns false if the location is already present in UsedLocations, otherwise it sets the SpawnLocations and adds it to the UsedLocations.

You can re-call the function if it returns false, but be careful because if all locations are used you could enter an infinite loop.

A more efficent way would be probably to use an array called “AvailableLocations” and get a random value from it, then remove it, so you don’t have to check every time if it’s used.

1 Like

GetAllTransforms is just getting the world transforms of all group actors and returning it.
not checking anything == or != in this function.
the checking takes place in RandomLocation and on beginplay.

GroupActor.cpp

void AItemGroup::CreateStaticMeshComponents()
{
	//Override the Existing Scene component
	NewScene = CreateDefaultSubobject <USceneComponent>("Scene Component");
	RootComponent = NewScene;

	FVector StaticMesh01Location(-44.814232, -77.620117,  -0.000031);
	FRotator StaticMesh01Rotation(0.000000, 0.000000, 0.000000);
	FVector StaticMesh01Scale(1.000000, 1.000000, 1.000000);
	StaticMesh01 = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh01"));
	StaticMesh01->AttachToComponent(NewScene, FAttachmentTransformRules::KeepRelativeTransform);
	StaticMesh01->SetRelativeLocation(StaticMesh01Location);
	StaticMesh01->SetRelativeRotation(StaticMesh01Rotation);

	FVector StaticMesh02Location(100.352554, -36.545986, -0.001999);
	FRotator StaticMesh02Rotation(0.000000, 90.000000, 0.000000);
	FVector StaticMesh02Scale(1.000000, 1.000000, 1.000000);
	StaticMesh02 = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh02"));
	StaticMesh02->AttachToComponent(NewScene, FAttachmentTransformRules::KeepRelativeTransform);
	StaticMesh02->SetRelativeLocation(StaticMesh02Location);
	StaticMesh02->SetRelativeRotation(StaticMesh02Rotation);

	FVector StaticMesh03Location(-41.113689, 0.000000, -0.000015);
	FRotator StaticMesh03Rotation(0.000000, 0.000000, 0.000000);
	FVector StaticMesh03Scale(1.000000, 1.000000, 1.000000);
	StaticMesh03 = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh03"));
	StaticMesh03->AttachToComponent(NewScene, FAttachmentTransformRules::KeepRelativeTransform);
	StaticMesh03->SetRelativeLocation(StaticMesh03Location);
	StaticMesh03->SetRelativeRotation(StaticMesh03Rotation);

	FVector StaticMesh04Location(-107.150299, 25.726238, -0.001434);
	FRotator StaticMesh04Rotation(0.000000, -90.000000, 0.000000);
	FVector StaticMesh04Scale(1.000000, 1.000000, 1.000000);
	StaticMesh04 = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh04"));
	StaticMesh04->AttachToComponent(NewScene, FAttachmentTransformRules::KeepRelativeTransform);
	StaticMesh04->SetRelativeLocation(StaticMesh04Location);
	StaticMesh04->SetRelativeRotation(StaticMesh04Rotation);

	FVector StaticMesh05Location(17.254007, 82.015709,  0.001145);
	FRotator StaticMesh05Rotation(0.000000, 180.000000, 0.000000);
	FVector StaticMesh05Scale(1.000000, 1.000000, 1.000000);
	StaticMesh05 = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh05"));
	StaticMesh05->AttachToComponent(NewScene, FAttachmentTransformRules::KeepRelativeTransform);
	StaticMesh05->SetRelativeLocation(StaticMesh05Location);
	StaticMesh05->SetRelativeRotation(StaticMesh05Rotation);
}

void AItemGroup::GetAllTransforms(/*Out*/ TArray<FTransform>& Transform)
{
	FTransform GetWorldTransform_0{};
	FTransform GetWorldTransform_1{};
	FTransform GetWorldTransform_2{};
	FTransform GetWorldTransform_3{};
	FTransform GetWorldTransform_4{};
	TArray<FTransform> MakeArray{};
	if (::IsValid(StaticMesh01))
	{
		GetWorldTransform_0 = StaticMesh01->GetComponentToWorld();
	}
	if (::IsValid(StaticMesh02))
	{
		GetWorldTransform_1 = StaticMesh02->USceneComponent::GetComponentToWorld();
	}
	if (::IsValid(StaticMesh03))
	{
		GetWorldTransform_2 = StaticMesh03->USceneComponent::GetComponentToWorld();
	}
	if (::IsValid(StaticMesh04))
	{
		GetWorldTransform_3 = StaticMesh04->USceneComponent::GetComponentToWorld();
	}
	if (::IsValid(StaticMesh05))
	{
		GetWorldTransform_4 = StaticMesh05->USceneComponent::GetComponentToWorld();
	}

	MakeArray.SetNum(5, true);
	MakeArray[0] = GetWorldTransform_0;
	MakeArray[1] = GetWorldTransform_1;
	MakeArray[2] = GetWorldTransform_2;
	MakeArray[3] = GetWorldTransform_3;
	MakeArray[4] = GetWorldTransform_4;
	Transform = MakeArray;
}

This groupactor has a refference casted in beginplay of mygamemode and later called the function GetAllTransforms.

in blueprint the group actor looks like


every mesh has different transforms so they don’t overlap each other when replacing with random items in the level to be generated/spawn, this group actor is placed in the level and later the meshes will be replaces dynamically randomly by available items.

the whole image in once shows everything, for those already experienced with this thread.

SOLUTION LINK

Issue is solved, Sir you can look at the solution , notifying you because you also need to use it :slight_smile: