Setting values for PaperFlipbookComponent in C++

I’m now looking for a way to set the SourceFlipbook of the UPaperFlipbookComponent in its constructor in C++.
The setting location on BP is “SourceFlipbook” in the attached image. I have confirmed that the internal name is also “SourceFlipbook”.

UPaperFlipbookComponent* PaperFlipbookComponent = GetSprite();
UPaperFlipbook* myFlipbook = LoadObject<UPaperFlipbook>(nullptr, TEXT("/Game/PaperAssets/Characters/Red/FB_Idle_D.FB_Idle_D"));

PaperFlipbookComponent->SourceFlipbook = myFlipbook;

If you define C++ like this, a compilation error will occur. If you check PaperFlipbookComponent.h, it seems that SourceFlipbook is in protected and cannot be accessed.

protected:
	/** Flipbook currently being played */
	UPROPERTY(Category=Sprite, EditAnywhere, meta=(DisplayThumbnail = "true"), ReplicatedUsing=OnRep_SourceFlipbook)
	TObjectPtr<UPaperFlipbook> SourceFlipbook;

I know there is a public SetFlipbook, but I want to set it in the constructor. To be honest, I want to understand the behavior of C++ for future development. Is it possible to set SourceFlipbook in C++? I would appreciate your help.

1 Like

in paperflipbookcomponent.cpp you have a setter

bool UPaperFlipbookComponent::SetFlipbook(class UPaperFlipbook* NewFlipbook)
{
	if (NewFlipbook != SourceFlipbook)
	{
		// Don't allow changing the sprite if we are "static".
		AActor* ComponentOwner = GetOwner();
		if ((ComponentOwner == nullptr) || AreDynamicDataChangesAllowed())
		{
			SourceFlipbook = NewFlipbook;

			// We need to also reset the frame and time also
			AccumulatedTime = 0.0f;
			CalculateCurrentFrame();

			// Need to send this to render thread at some point
			MarkRenderStateDirty();

			// Update physics representation right away
			FlipbookChangedPhysicsState();

			// Update this component streaming data.
			IStreamingManager::Get().NotifyPrimitiveUpdated(this);

			// Since we have new mesh, we need to update bounds
			UpdateBounds();

			return true;
		}
	}

	return false;
}

You can also outright access the pointer to the flipbook via the getter

UPaperFlipbook* UPaperFlipbookComponent::GetFlipbook()
{
	return SourceFlipbook;
}
2 Likes

As I thought, it was correct that the variable could not be accessed directly. The information on how to investigate was also very helpful!

I’m still a beginner, but it seems like it would be best to investigate the variables/functions in the class it inherits from from the included .h and make a judgment.

I’ll give it a try later and see if it solves the problem. Thank you!

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


#include "Red.h"
#include "PaperCharacter.h"
#include "PaperFlipbookComponent.h"
#include "PaperFlipbook.h"

ARed::ARed()
{
	
	PrimaryActorTick.bCanEverTick = true;

	PaperFlipbookComponent = GetSprite();
	UPaperFlipbook* myFlipbook = LoadObject<UPaperFlipbook>(nullptr, TEXT("/Script/Paper2D.PaperFlipbook'/Game/PaperAssets/Characters/Red/FB_Idle_D.FB_Idle_D'"));
	PaperFlipbookComponent->SetFlipbook(myFlipbook);
	
	PaperFlipbookComponent->SetWorldRotation(FRotator(0.f, 90.f, 0.f));
}

void ARed::BeginPlay()
{
	Super::BeginPlay();
}

As expected, it is not applied. The compilation itself passes normally. I thought that there might be some other problem with the C++ compilation not being reflected, so I tried adding a function to change the rotation, but the rotation did not change.

This may be a different problem from the first question, but the code is very simple so I don’t know what to try… As I understand it, this code just does the initial setup.


No change even with SetRelativeRotation

SetRelativeRotation
1 Like
ARed::ARed()
{

	PrimaryActorTick.bCanEverTick = true;
	PaperFlipbookComponent = GetSprite();
	UPaperFlipbook* myFlipbook = LoadObject<UPaperFlipbook>(nullptr, TEXT("/Script/Paper2D.PaperFlipbook'/Game/PaperAssets/Characters/Red/FB_Idle.FB_Idle'"));
	PaperFlipbookComponent->SetFlipbook(myFlipbook);
	PaperFlipbookComponent->SetWorldRotation(FRotator(0.f, 90.f, 0.f));		
}


void ARed::PostInitializeComponents() {
	Super::PostInitializeComponents();	
	PaperFlipbookComponent->MarkRenderStateDirty();
}

and in header of ARed add the override

virtual void PostInitializeComponents() override;

The new actor will have the rotated component and have the sprite flipbook loaded.

Make sure your FB_Idle path is correct and that it evaluates to an asset on load and not a null

Video of it in action from source project

1 Like

Thank you for your advice. I hypothesized that this simple approach should not be a difficult problem, so I compiled the code you advised me on in an initialized project, and I was able to confirm that the problem was resolved! Thank you so much.

Even in a newly created environment, the problem could not be resolved when compiling with hot reload, but I was able to confirm that the problem was resolved when compiling with live coding. I think the problem I was facing was originally a code problem, but I think the problem I’m facing now is a different problem.

I will try to isolate the compilation problem and work on it! I will treat this problem as resolved. Thank you for your support.

I also solved the build issue, so I’m posting it here. The problem I ran into seemed to be a typical issue that occurs when doing hot reload with the UE Editor open.

To be precise, it seems that editing header files with the Editor open is not recommended.

Closing the Editor and compiling from the IDE achieved my goal without any issues. But as others have said, this is a development experience that significantly worsens the development lifecycle. I’m going to move forward again, having learned a lot of the knowledge already shared, such as Live++ and exposing variables to Blueprints.