Здравствуйте, меня зовут Дмитрий. Я занимаюсь созданием компьютерных игр на Unreal Engine в качестве хобби. Итак, сегодня я продолжу создание системы расстановки объектов. После того, как я её сделал я подумал, что добавление окна пред просмотра позволит ускорить процесс расстановки объектов. Об этом я сегодня и расскажу.
Если вы не читали первую часть, то рекомендую сделать это (статья). Здесь я буду приводить только код, который был изменен, для экономии места. Исходники, как всегда, можно скачать по ссылкам в конце статьи.
Сначала нужно добавить ещё одну вкладку в окно редактора файл CustAssetEditor.cpp:
const TSharedRef<FTabManager::FLayout> 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)
)
)
)
);
Важно: Если добавляете или убираете вкладку, то необходимо менять название слоя.
После этого создаем новый объект PreviewViewport.
TPreviewViewport = SNew(SCustomEditorViewport)
.CustomEditor(SharedThis(this))
.ObjectToEdit(PropBeingEdited);
class SCustomEditorViewport : public SEditorViewport//, public FGCObject
{
public:
SLATE_BEGIN_ARGS(SCustomEditorViewport){}
SLATE_ARGUMENT(TWeakPtr<FCustAssetEditor>, CustomEditor)
SLATE_ARGUMENT(UMyObject*, ObjectToEdit)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
~SCustomEditorViewport();
void SetParentTab(TSharedRef<SDockTab> InParentTab) { ParentTab = InParentTab; }
EVisibility GetToolbarVisibility() const;
FReply OnRebildScen();
FReply OnShowPropertyPreview();
void RebildScen();
protected:
/** SEditorViewport interface */
virtual TSharedRef<FEditorViewportClient> MakeEditorViewportClient() override;
virtual EVisibility OnGetViewportContentVisibility() const override;
virtual void OnFocusViewportToSelection() override;
virtual TSharedPtr<SWidget> MakeViewportToolbar() override;
private:
bool IsVisible() const;
void DestroyActors();
FName ActorTag;
TWeakPtr<FCustAssetEditor> CustomEditorPtr;
UMyObject* ObjectToEdit;
TWeakPtr<SDockTab> ParentTab;
TSharedPtr<class FEditorViewportClient> EditorViewportClient;
TSharedPtr<FPreviewScene> PreviewScene;
USkyLightComponent* Skylight;
UAtmosphericFogComponent* AtmosphericFog;
};
Здесь наиболее интересным для нас является метод MakeEditorViewportClient(). В этом методе создается объект FEditorViewportClient, которому нужно передать указатель на FPreviewScene (этот объект создан в методе Construct). Теперь, если получить указатель на мир при помощи этого объекта, а потом использовать его при создании объекта Actor, то Actor появится не в окне редактора, а в окне предпросмотра.
World = PreviewScene->GetWorld();
World->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));
В методе MakeViewportToolbar(), как вы наверно догадались, создается панель инструментов окна предпросмотра. Здесь я создал две кнопки: одна обновляет окно предпросмотра, другая отображает свойства этого окна. Свойства окна предпросмотра аналогичны свойствам TestActor. Свойства эти хранятся не в объекте PreviewViewport, (поскольку он живет только когда открыт редактор ассета), а в объекте MyObjekt (файл MyObjekt.h).
UCLASS()
class UCustomEditorViewportProperties : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FRoot> 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
};
Собственно на этом все, что касается окна предпросмотра. Кроме этого, для большего удобства редактирования, я добавил возможность открывать редактор правил для нод, по двойному щелчку на эти ноды (надо только выбрать какое-нибудь правило).
void FCustAssetEditor::OnNodeDoubleClicked(class UEdGraphNode* Node)
{
((UCustomNodeBase*)Node)->DoubleClicke();
}
void URuleNode::DoubleClicke()
{
FStreamableManager AssetLoader;
TArray<FString> Name;
if (Rule)
{
Name.Add(Rule->GetPathName());
FAssetEditorManager::Get().OpenEditorsForAssets(Name);
}
}
На этом все.
Проект с исходным кодом здесь.