How to handle motion controllers in 4.20 ?

Hi everyone,

I’m trying to make a VR template but in C++. My question is how to do that now that everything in MotionControllers.h is in private ? I suspect a little mistake from the Epic Team or just a way to force you to use BP Programming.

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Components/PrimitiveComponent.h"
#include "SceneViewExtension.h"
#include "IMotionController.h"
#include "LateUpdateManager.h"
#include "IIdentifiableXRDevice.h" // for FXRDeviceId
#include "MotionControllerComponent.generated.h"

class FPrimitiveSceneInfo;
class FRHICommandListImmediate;
class FSceneView;
class FSceneViewFamily;

UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = MotionController)
class HEADMOUNTEDDISPLAY_API UMotionControllerComponent : public UPrimitiveComponent
{
	GENERATED_UCLASS_BODY()

	void BeginDestroy() override;

	/** Which player index this motion controller should automatically follow */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter = SetAssociatedPlayerIndex, Category = "MotionController")
	int32 PlayerIndex;

	/** DEPRECATED (use MotionSource instead) Which hand this component should automatically follow */
	UPROPERTY(BlueprintSetter = SetTrackingSource, BlueprintGetter = GetTrackingSource, Category = "MotionController")
	EControllerHand Hand_DEPRECATED;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter = SetTrackingMotionSource, Category = "MotionController")
	FName MotionSource;

	/** If false, render transforms within the motion controller hierarchy will be updated a second time immediately before rendering. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MotionController")
	uint32 bDisableLowLatencyUpdate:1;

	/** The tracking status for the device (e.g. full tracking, inertial tracking only, no tracking) */
	UPROPERTY(BlueprintReadOnly, Category = "MotionController")
	ETrackingStatus CurrentTrackingStatus;

	void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;

	/** Whether or not this component had a valid tracked device this frame */
	UFUNCTION(BlueprintPure, Category = "MotionController")
	bool IsTracked() const
	{
		return bTracked;
	}

	/** Used to automatically render a model associated with the set hand. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter=SetShowDeviceModel, Category="Visualization")
	bool bDisplayDeviceModel;

	UFUNCTION(BlueprintSetter)
	void SetShowDeviceModel(const bool bShowControllerModel);

	/** Determines the source of the desired model. By default, the active XR system(s) will be queried and (if available) will provide a model for the associated device. NOTE: this may fail if there's no default model; use 'Custom' to specify your own. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter=SetDisplayModelSource, Category="Visualization", meta=(editcondition="bDisplayDeviceModel"))
	FName DisplayModelSource;

	static FName CustomModelSourceId;
	UFUNCTION(BlueprintSetter)
	void SetDisplayModelSource(const FName NewDisplayModelSource);

	/** A mesh override that'll be displayed attached to this MotionController. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, BlueprintSetter=SetCustomDisplayMesh, Category="Visualization", meta=(editcondition="bDisplayDeviceModel"))
	UStaticMesh* CustomDisplayMesh;

	UFUNCTION(BlueprintSetter)
	void SetCustomDisplayMesh(UStaticMesh* NewDisplayMesh);

	/** Material overrides for the specified display mesh. */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Visualization", meta=(editcondition="bDisplayDeviceModel"))
	TArray<UMaterialInterface*> DisplayMeshMaterialOverrides;

	UFUNCTION(BlueprintSetter, meta = (DeprecatedFunction, DeprecationMessage = "Please use the Motion Source property instead of Hand"))
	void SetTrackingSource(const EControllerHand NewSource);

	UFUNCTION(BlueprintGetter, meta = (DeprecatedFunction, DeprecationMessage = "Please use the Motion Source property instead of Hand"))
	EControllerHand GetTrackingSource() const;

	UFUNCTION(BlueprintSetter)
	void SetTrackingMotionSource(const FName NewSource);

	UFUNCTION(BlueprintSetter)
	void SetAssociatedPlayerIndex(const int32 NewPlayer);

public:
	//~ UObject interface
	virtual void Serialize(FArchive& Ar) override;

#if WITH_EDITOR
	virtual void PreEditChange(UProperty* PropertyAboutToChange) override;
	virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif 

public:
	//~ UActorComponent interface
	virtual void OnRegister() override;
	virtual void InitializeComponent() override;
	virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override;

protected:
	//~ Begin UActorComponent Interface.
	virtual void CreateRenderState_Concurrent() override;
	virtual void SendRenderTransform_Concurrent() override;
	//~ End UActorComponent Interface.

	void RefreshDisplayComponent(const bool bForceDestroy = false);

	// Cached Motion Controller that can be read by GetParameterValue. Only valid for the duration of OnMotionControllerUpdated
	IMotionController* InUseMotionController;

	/** Blueprint Implementable function for reponding to updated data from a motion controller (so we can use custom paramater values from it) */
	UFUNCTION(BlueprintImplementableEvent, Category = "Motion Controller Update")
	void OnMotionControllerUpdated();

	// Returns the value of a custom parameter on the current in use Motion Controller (see member InUseMotionController). Only valid for the duration of OnMotionControllerUpdated 
	UFUNCTION(BlueprintCallable, Category = "Motion Controller Update")
	float GetParameterValue(FName InName, bool& bValueFound);

// .......

In the documentation everything is at minimum protected not private.

We can no longer configure Motion Controllers in C++ so what should I do ? Without modifying the engine and recompiling it (If we can)?

Best regards,

Alexandre

edit
Think I misunderstood you, so my solution wont work, since all properties etc. under the Generated Macro are private (thought protected)

Well, if you say that all Methods/Properties are public or protected, so why don’t you just derive from the Controller class? I’m not familiar with what you want to do, and I never used this Controller class, so my suggestion is based on a general way to solve such problems.

No problem :slight_smile: I’ve tried some VRTemplates C++ found on GitHub, no one compile now because of this.

If you think its a bug, send a Bug report, so it gets fixed :smiley: Unreal Engine Community

It’s done :slight_smile: