I want to create a custom viewport (to edit UVs). I looked at SStaticMeshEditorViewport
and FStaticMeshEditorViewportClient
.
I made a Viewport
which inherits from SEditorViewport
, and a ViewportClient
which inherits from FEditorViewportClient
.
When I create the viewport, I add some meshes to its PreviewScene
with PreviewScene.AddComponent(Component, Transform);
. The problem is that they do not appear on the viewport. Why?
Here is my code:
STextureViewport.h:
// [...] #includes
class STextureViewport : public SEditorViewport, public FGCObject, public ICommonEditorViewportToolbarInfoProvider
{
public:
SLATE_BEGIN_ARGS(STextureViewport){}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
~STextureViewport();
virtual void AddReferencedObjects( FReferenceCollector& Collector ) override;
void RefreshViewport();
void SetPreviewMesh();
/** @return The editor viewport client */
class FEditorViewportClient& GetViewportClient();
/** Set the parent tab of the viewport for determining visibility */
void SetParentTab( TSharedRef<SDockTab> InParentTab ) { ParentTab = InParentTab; }
// ICommonEditorViewportToolbarInfoProvider interface
virtual TSharedRef<class SEditorViewport> GetViewportWidget() override;
virtual TSharedPtr<FExtender> GetExtenders() const override;
virtual void OnFloatingButtonClicked() override;
// End of ICommonEditorViewportToolbarInfoProvider interface
protected:
/** SEditorViewport interface */
virtual TSharedRef<FEditorViewportClient> MakeEditorViewportClient() override;
virtual EVisibility OnGetViewportContentVisibility() const override;
virtual void BindCommands() override;
virtual void OnFocusViewportToSelection() override;
virtual TSharedPtr<SWidget> MakeViewportToolbar() override;
private:
// /** Callback for updating preview socket meshes if the static mesh or socket has been modified. */
void OnObjectPropertyChanged(UObject* ObjectBeingModified, FPropertyChangedEvent& PropertyChangedEvent);
private:
/** The parent tab where this viewport resides */
TWeakPtr<SDockTab> ParentTab;
/** The scene for this viewport. */
FPreviewScene PreviewScene;
/** Editor viewport client */
TSharedPtr<class FTextureViewportClient> TextureViewportClient;
/** Pointer to the vertical box into which the overlay text items are added */
TSharedPtr<SVerticalBox> OverlayTextVerticalBox;
};
STextureViewport.cpp:
// […] #includes
// In-viewport toolbar widget used in the static mesh editor
class STextureViewportToolbar : public SCommonEditorViewportToolbarBase
{
public:
SLATE_BEGIN_ARGS(STextureViewportToolbar) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs, TSharedPtr<class ICommonEditorViewportToolbarInfoProvider> InInfoProvider)
{
SCommonEditorViewportToolbarBase::Construct(SCommonEditorViewportToolbarBase::FArguments(), InInfoProvider);
}
// SCommonEditorViewportToolbarBase interface
virtual TSharedRef<SWidget> GenerateShowMenu() const override
{
GetInfoProvider().OnFloatingButtonClicked();
TSharedRef<SEditorViewport> ViewportRef = GetInfoProvider().GetViewportWidget();
const bool bInShouldCloseWindowAfterMenuSelection = true;
FMenuBuilder ShowMenuBuilder(bInShouldCloseWindowAfterMenuSelection, ViewportRef->GetCommandList());
return ShowMenuBuilder.MakeWidget();
}
// End of SCommonEditorViewportToolbarBase
};
void STextureViewport::Construct(const FArguments& InArgs)
{
SEditorViewport::Construct( SEditorViewport::FArguments() );
SetPreviewMesh();
ViewportOverlay->AddSlot()
.VAlign(VAlign_Top)
.HAlign(HAlign_Left)
.Padding(FMargin(10.0f, 40.0f, 10.0f, 10.0f))
[
SAssignNew(OverlayTextVerticalBox, SVerticalBox)
];
}
STextureViewport::~STextureViewport()
{
FCoreUObjectDelegates::OnObjectPropertyChanged.RemoveAll(this);
if (TextureViewportClient.IsValid())
{
TextureViewportClient->Viewport = NULL;
}
}
TSharedRef<class SEditorViewport> STextureViewport::GetViewportWidget()
{
return SharedThis(this);
}
TSharedPtr<FExtender> STextureViewport::GetExtenders() const
{
TSharedPtr<FExtender> Result(MakeShareable(new FExtender));
return Result;
}
void STextureViewport::OnFloatingButtonClicked()
{
}
void STextureViewport::AddReferencedObjects( FReferenceCollector& Collector )
{
}
void STextureViewport::RefreshViewport()
{
// Invalidate the viewport's display.
SceneViewport->Invalidate();
}
void STextureViewport::SetPreviewMesh(/*UStaticMesh* InStaticMesh*/)
{
FTransform Transform = FTransform::Identity;
for(TActorIterator<AActor> ActorItr(ProBuilder::World.Get()); ActorItr; ++ActorItr)
{
for(UActorComponent* Component:ActorItr->GetComponents())
{
FComponentReregisterContext ReregisterContext( Component);
PreviewScene.AddComponent(Component, Transform);
}
}
}
FEditorViewportClient& STextureViewport::GetViewportClient()
{
return *TextureViewportClient;
}
TSharedRef<FEditorViewportClient> STextureViewport::MakeEditorViewportClient()
{
TextureViewportClient = MakeShareable(new FTextureViewportClient(SharedThis(this), PreviewScene));
TextureViewportClient->bSetListenerPosition = false;
TextureViewportClient->SetRealtime( false );
TextureViewportClient->VisibilityDelegate.BindSP( this, &STextureViewport::IsVisible );
return TextureViewportClient.ToSharedRef();
}
TSharedPtr<SWidget> STextureViewport::MakeViewportToolbar()
{
return SNew(STextureViewportToolbar, SharedThis(this));
}
EVisibility STextureViewport::OnGetViewportContentVisibility() const
{
return IsVisible() ? EVisibility::Visible : EVisibility::Collapsed;
}
void STextureViewport::BindCommands()
{
SEditorViewport::BindCommands();
}
void STextureViewport::OnFocusViewportToSelection()
{
}
TextureViewportClient.h:
class STextureViewport;
/** Viewport Client for the preview viewport */
class FTextureViewportClient : public FEditorViewportClient, public TSharedFromThis<FTextureViewportClient>
{
public:
FTextureViewportClient(const TSharedRef<STextureViewport>& InTextureViewport, FPreviewScene& InPreviewScene);
virtual void Tick(float DeltaSeconds) override;
virtual void Draw(const FSceneView* View,FPrimitiveDrawInterface* PDI) override;
virtual void DrawCanvas( FViewport& InViewport, FSceneView& View, FCanvas& Canvas ) override;
virtual FSceneView* CalcSceneView(FSceneViewFamily* ViewFamily) override;
TWeakPtr<STextureViewport> TextureViewportPtr;
};
TextureViewportClient.cpp:
namespace {
static const float AutoViewportOrbitCameraTranslate = 256.0f;
static float AmbientCubemapIntensity = 0.4f;
}
FTextureViewportClient::FTextureViewportClient(const TSharedRef<STextureViewport>& InTextureViewport, FPreviewScene& InPreviewScene)
: FEditorViewportClient(nullptr, &InPreviewScene, StaticCastSharedRef<SEditorViewport>(InTextureViewport))
{
SetViewMode(VMI_Lit);
EngineShowFlags.DisableAdvancedFeatures();
EngineShowFlags.SetSnap(0);
EngineShowFlags.CompositeEditorPrimitives = true;
OverrideNearClipPlane(1.0f);
bUsingOrbitCamera = true;
}
void FTextureViewportClient::Tick(float DeltaSeconds)
{
FEditorViewportClient::Tick(DeltaSeconds);
// Tick the preview scene world.
if (!GIntraFrameDebuggingGameThread)
{
PreviewScene->GetWorld()->Tick(LEVELTICK_All, DeltaSeconds);
}
}
void FTextureViewportClient::Draw(const FSceneView* View,FPrimitiveDrawInterface* PDI)
{
FEditorViewportClient::Draw(View, PDI);
}
void FTextureViewportClient::DrawCanvas( FViewport& InViewport, FSceneView& View, FCanvas& Canvas )
{
auto TextureViewport = TextureViewportPtr.Pin();
if (!TextureViewport.IsValid())
{
return;
}
}
FSceneView* FTextureViewportClient::CalcSceneView(FSceneViewFamily* ViewFamily)
{
FSceneView* SceneView = FEditorViewportClient::CalcSceneView(ViewFamily);
FFinalPostProcessSettings::FCubemapEntry& CubemapEntry = *new(SceneView->FinalPostProcessSettings.ContributingCubemaps) FFinalPostProcessSettings::FCubemapEntry;
CubemapEntry.AmbientCubemap = GUnrealEd->GetThumbnailManager()->AmbientCubemap;
CubemapEntry.AmbientCubemapTintMulScaleValue = FLinearColor::White * AmbientCubemapIntensity;
return SceneView;
}