4.7 C++ Transition Guide

[Edited]:

I am apologies! I had semicolon in the end of line!


bool TestWindow::IsActorSelected(ATriggerBox* actor);
{
	return actor == _boundsActor;
}

It’s my fault!

Thank you! :slight_smile:

Does anybody know how to use the new DelegateHandles for OnlineSubsystem? I just can’t get it refactored properly.


warning C4996: 'TBaseMulticastDelegate<void,EOnJoinSessionCompleteResult::Type>::RemoveUObject': RemoveUObject is deprecated - please remove delegates using the FDelegateHandle returned by the Add function. Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.

I have a FDelegateHandle returned by the add function, but I can’t find a remove-function that accepts the handle.

EDIT: fixed it, had to use Delegate.Remove(FDelegateHandle) instead of .RemoveUObject()

Thanks for sharing your research DennyR !

:slight_smile:

Rama

If you get errors that the definition for FKey can’t be found make sure to add InputCore to the appropriate build cs!

LoadingScreenModules coming from ShooterGame/Platformer examples tend to have this issue

Rama

**Scene Proxies in 4.7

How To Get the PDI for Drawing Purposes**

If you want to do custom drawing for a component’s scene proxy that you used to do with DrawDynamicElements prior to 4.7,

here is the code you can use in 4.7!

DrawDynamicElements no longer exists, but you can use GetDynamicElements and the Collector to get the PDI!



FPrimitiveSceneProxy* UJoyDrawComp::CreateSceneProxy()
{
	class JoyDrawSceneProxy : public FPrimitiveSceneProxy
	{
	public:
		JoyDrawSceneProxy(UJoyDrawComp* InComponent)
			:	FPrimitiveSceneProxy(InComponent),
				JoyDraw(InComponent)
		{
			bWillEverBeLit = false;
		}

		//Draw Dynamic Elements is not used any more
		virtual void GetDynamicMeshElements(
			const TArray<const FSceneView*>& Views, 
			const FSceneViewFamily& ViewFamily, 
			uint32 VisibilityMap, 
			class FMeshElementCollector& Collector
		) const override
		{   
			//See SphereComponent.cpp for reference
			for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
			{
				if (VisibilityMap & (1 << ViewIndex))
				{
					const FSceneView* View = Views[ViewIndex];
					FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
					if(!PDI)
					{
						continue;
					}
					
					//Draw to PDI !!!
					JoyDraw->DrawToPDI(PDI);
				}
			}
		}
		
		//Should Draw?
		virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) override
		{
			FPrimitiveViewRelevance Result;
			
			//~~~ Guarantee It Will Be Drawn ~~~ 
			Result.bDrawRelevance 		= true;
			Result.bDynamicRelevance 	= true;
			Result.bShadowRelevance 	= false; 	//no shadow
			//~~~~~~~~~~~~~~~~~~~~~~~~~
			
			return Result;
		}
		
		//SceneProxy
		virtual uint32 GetMemoryFootprint( void ) const override { return( sizeof( *this ) + GetAllocatedSize() ); }
		uint32 GetAllocatedSize( void ) const { return( FPrimitiveSceneProxy::GetAllocatedSize() ); }

	private:
		UJoyDrawComp* JoyDraw;
	};

	return new JoyDrawSceneProxy( this );
}


This is the code I am using in 4.7 to do custom component rendering in the Editor for The Solus Project

I found the 4.7 MoveToActor() Bug.

It seems that when you set bUsePathFinding=false in MoveToActor(), the AI will no longer update its destination on Moving Actor.

Spent the whole day rewriting our AI code to find the bug. Hope someone help clear this bug soon…

hi,

just for you information, I had a confirmation of how the timerhandle works now:

“If you have two different timerhandles referencing the same function then each one will have a unique id that can be used independently of each other.”

That’s mean that each handle manage its own timer. So if you are overring a class and want to put a timer on a function, you may look at the main class level to see if no one set a timerhandle on it or you will have some surprise that it will be called twice.
As a principle, I encourage you to set your timer as protected and not private, so you can reuse it in child class.

For those who are stuck on “Introduction to UE4 Programming - 3 - Creating the Base Pickup Class” here is the source code for 4.7. Works for me so hopefully it works for you also.

PickUp.h

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

#pragma once

#include “GameFramework/Actor.h”
#include “PickUp.generated.h”

UCLASS()
class TUTORIAL_102_API APickUp : public AActor
{
GENERATED_BODY()

public:

APickUp(const FObjectInitializer& ObjectInitializer);
// Sets default values for this actor’s properties
APickUp();

// True when the pickup is able to be picked up, false if something deactivates the pickup
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = PickUp)
bool bIsActive;

// Simple collision primitive to use as the root component
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = PickUp)
USphereComponent* BaseCollisionComponent;

// StaticMeshComponent to represent the pickup in the level
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = PickUp)
UStaticMeshComponent* PickupMesh;

// Function to call when the pickup is collected
UFUNCTION(BlueprintNativeEvent)
void OnPickedUp();

// Declare Blueprint Native Event
virtual void OnPickedUp_Implementation();

};

PickUp.cpp

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

#include “Tutorial_102.h”
#include “PickUp.h”

// Sets default values
APickUp::APickUp(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{

// The pickup is valid when it is created
bIsActive = true;

// Create the root SphereComponent to handle the pickup’s collision
BaseCollisionComponent = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT(“BaseSphereComponent”));

// Set the SphereComponent as the root component
RootComponent = BaseCollisionComponent;

// Create the static mesh component
PickupMesh = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT(“PickupMesh”));

// Turn physic on for the static mesh
PickupMesh->SetSimulatePhysics(true);

//Attach the StaticMeshComponent to the root component
PickupMesh->AttachTo(RootComponent);

// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don’t need it.
PrimaryActorTick.bCanEverTick = true;

}

void APickUp::OnPickedUp_Implementation(){
// There is no default behaviour for a pickup when it is picked up
}

UFactory is one that has not been updated (still uses GENERATED_UCLASS_BODY) so I had to use GENERATED_UCLASS_BODY also in our class that extends it, otherwise I found not way of having a constructor. Either the body was already created or there was no appropriate constructor.

S!

They also forgot to add public: in HGGamePlayStatics.h after GENERATED_BODY() so all the helper functions are now private :D.

You can mix and match the construction macros in an inheritance hierarchy. It’s just that since GENERATED_UCLASS_BODY autogenerates only a FObjectInitializer constructor, your derived class has to call the superclass constructor with it somehow. When using GENERATED_BODY(), you can either declare a FObjectInitializer constructor of your own or statically obtain it. It’s worth knowing that even if your constructor doesn’t have a FObjectInitializer argument, it is still used behind the scenes and you can obtain it using FObjectInitializer::Get().

So, providing your own:


UCLASS()
class UMyFactory : public UFactory
{
	GENERATED_BODY()

public:
	UMyFactory( const FObjectInitializer& ObjectInitializer )
		: Super( FObjectInitializer )
	{
	}
}

Static Get:


UCLASS()
class UMyFactory : public UFactory
{
	GENERATED_BODY()

public:
	UMyFactory()
		: Super( FObjectInitializer::Get() )
	{
	}
}

The new GENERATED_BODY() macro gives you more control over what’s autogenerated, so it’d be a shame to not use it to its full extents. :slight_smile:

That did it, thanks :).

Thanks for sharing your research Elvince!

That’s what this thread is for! :slight_smile:

Wow this is some great info!

Thanks for sharing !

[FONT=Comic Sans MS]:heart:

Rama

Sorry for the necro but I had a doubt on this.

If 2 different FTimerHandle are used on the same function, then 2 instances of that function will be executed right?

I will just quote my answer to this:

Thanks for confirming this…

I’m here to say a big “thank you!” to Rama and all those who contributed to this thread.

We were holding off from updating to 4.7, but on the 14th we decided that 4.7.x contained fixes that would save us time and effort, so went against our original plan and went to it.

First stop was here.

The only issue we’ve ended up having - C++ wise - was the classic “Everything worked first time… ****”.

Blueprint wise, we’ve had some misc issues - the outer is a placeholder warning - that mysteriously fixed themselves.
For anyone experiencing that issue, it seems that running a stand alone version of the game and/or rebuilding the projects solution file sorted it for us.
Though I don’t know why :stuck_out_tongue:

http://en.docsity.com/wordpress/wp-content/uploads/sites/2/2014/02/programmers-be-like.jpg

You’re welcome Kris!

I am very happy this thread helped speed up your transition to 4.7!

Have fun today!

:slight_smile:

Rama