Creating a system for arranging objects by level using the blueprint editor. Part 2: adding a preview window

  • Tutorial
image

Hello, my name is Dmitry. I make computer games on the Unreal Engine as a hobby. So, today I will continue to create a system for arranging objects. After I made it, I thought that adding a preview window would speed up the process of arranging objects. I’ll talk about this today.

If you have not read the first part, then I recommend doing this ( article ). Here I will cite only the code that has been changed to save space. Sources, as always, can be downloaded from the links at the end of the article.

First, add one more tab to the editor window, the file CustAssetEditor.cpp:

const TSharedRef StandaloneDefaultLayout = FTabManager::NewLayout("CustomEditor_Layout_2")
		->AddArea
		(
			FTabManager::NewPrimaryArea()
			->SetOrientation(Orient_Vertical)
			->Split
			(
				FTabManager::NewStack()
				->SetSizeCoefficient(0.1f)
				->SetHideTabWell(true)
				->AddTab(GetToolbarTabId(), ETabState::OpenedTab)
			)
			->Split
			(
				FTabManager::NewSplitter()
				->SetOrientation(Orient_Horizontal)
				->SetSizeCoefficient(0.2f)
				->Split
				(
					FTabManager::NewStack()
					->SetSizeCoefficient(0.75f)
					->SetHideTabWell(true)
					->AddTab(FCustomEditorTabs::ViewportID, ETabState::OpenedTab)
				)
				->Split
				(
					FTabManager::NewSplitter()
					->SetOrientation(Orient_Vertical)
					->SetSizeCoefficient(0.25f)
					->Split
					(
						FTabManager::NewStack()
						->SetSizeCoefficient(0.35f)
						->SetHideTabWell(true)
						->AddTab(FCustomEditorTabs::DetailsID, ETabState::OpenedTab)
					)
					->Split
					(
						FTabManager::NewStack()
						->SetSizeCoefficient(0.65f)
						->SetHideTabWell(true)
						->AddTab(FCustomEditorTabs::PreviewID, ETabState::OpenedTab)
					)
				)
			)
		);

Important: If you add or remove a tab, you must change the name of the layer.

After that, create a new PreviewViewport object.

TPreviewViewport = SNew(SCustomEditorViewport)
		.CustomEditor(SharedThis(this))
		.ObjectToEdit(PropBeingEdited);
class SCustomEditorViewport : public SEditorViewport//, public FGCObject
{
public:
	SLATE_BEGIN_ARGS(SCustomEditorViewport){}
		SLATE_ARGUMENT(TWeakPtr, CustomEditor)
		SLATE_ARGUMENT(UMyObject*, ObjectToEdit)
	SLATE_END_ARGS()
	void Construct(const FArguments& InArgs);
	~SCustomEditorViewport();
	void SetParentTab(TSharedRef InParentTab) { ParentTab = InParentTab; }
	EVisibility GetToolbarVisibility() const;
	FReply OnRebildScen();
	FReply OnShowPropertyPreview();
	void RebildScen();
protected:
	/** SEditorViewport interface */
	virtual TSharedRef MakeEditorViewportClient() override;
	virtual EVisibility OnGetViewportContentVisibility() const override;
	virtual void OnFocusViewportToSelection() override;
	virtual TSharedPtr MakeViewportToolbar() override;
private:
	bool IsVisible() const;
        void DestroyActors();
	FName ActorTag;
	TWeakPtr CustomEditorPtr;
	UMyObject* ObjectToEdit;
	TWeakPtr ParentTab;
	TSharedPtr EditorViewportClient;
	TSharedPtr PreviewScene;
	USkyLightComponent* Skylight;
	UAtmosphericFogComponent* AtmosphericFog;
};

The most interesting for us here is the MakeEditorViewportClient () method. This method creates an FEditorViewportClient object to which you need to pass a pointer to FPreviewScene (this object was created in the Construct method). Now, if you get a pointer to the world using this object, and then use it when creating the Actor object, then Actor will appear not in the editor window, but in the preview window.

World = PreviewScene->GetWorld();
World->SpawnActor(AStaticMeshActor::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));

In the MakeViewportToolbar () method, as you probably guessed, a preview window toolbar is created. Here I created two buttons: one updates the preview window, the other displays the properties of this window. The properties of the preview window are similar to the properties of TestActor. These properties are not stored in the PreviewViewport object (since it only lives when the asset editor is open), but in the MyObjekt object (file MyObjekt.h).


UCLASS()
class UCustomEditorViewportProperties : public UObject
{
	GENERATED_BODY()
public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		TArray Roots;
};
UCLASS(Blueprintable)
class UICUSTOM_API UMyObject : public UObject
{
	GENERATED_UCLASS_BODY()
public:
	UPROPERTY(EditAnywhere, Category = "My Object Properties")
		FString Name;
	URootNode* FindRootFromType(ERootType RootType);
	UPROPERTY()
	UEdGraph* UpdateGraph;
#if WITH_EDITORONLY_DATA
	UPROPERTY()
		UCustomEditorViewportProperties* PreviewViewportProperties;
#endif // WITH_EDITORONLY_DATA
};

Actually that's all with regard to the preview window. In addition, for greater editing convenience, I added the ability to open the rules editor for nodes by double-clicking on these nodes (you just need to select some rule).

void FCustAssetEditor::OnNodeDoubleClicked(class UEdGraphNode* Node)
{
	((UCustomNodeBase*)Node)->DoubleClicke();
}
void URuleNode::DoubleClicke()
{
	FStreamableManager AssetLoader;
	TArray Name;
	if (Rule)
	{
		Name.Add(Rule->GetPathName());
		FAssetEditorManager::Get().OpenEditorsForAssets(Name);
	}
}

That's all.

The source code project is here .

Also popular now: