void FTileSetEditorViewportClient::Draw(FViewport* InViewport, FCanvas* Canvas) { // Clear the viewport Canvas->Clear(GetBackgroundColor()); // Can only proceed if we have a valid tile set UPaperTileSet* TileSet = TileSetBeingEdited.Get(); if (TileSet == nullptr) { return; } if (UTexture2D* Texture = TileSet->GetTileSheetTexture()) { const bool bUseTranslucentBlend = Texture->HasAlphaChannel(); // Fully stream in the texture before drawing it. Texture->SetForceMipLevelsToBeResident(30.0f); Texture->WaitForStreaming(); FLinearColor TextureDrawColor = FLinearColor::White; { // Draw the tile sheet texture const float XPos = -ZoomPos.X * ZoomAmount; const float YPos = -ZoomPos.Y * ZoomAmount; const float Width = Texture->GetSurfaceWidth() * ZoomAmount; const float Height = Texture->GetSurfaceHeight() * ZoomAmount; Canvas->DrawTile(XPos, YPos, Width, Height, 0.0f, 0.0f, 1.0f, 1.0f, TextureDrawColor, Texture->Resource, bUseTranslucentBlend); } const FLinearColor BorderRectangleColor(0.3f, 0.3f, 0.3f, 1.0f); { const FIntPoint TextureSize = Texture->GetImportedSize(); const FIntMargin BorderSize = TileSet->GetMargin(); const FIntRect TileSetRegion(BorderSize.Left, BorderSize.Top, TextureSize.X - BorderSize.Right, TextureSize.Y - BorderSize.Bottom); const float X = (TileSetRegion.Min.X - ZoomPos.X) * ZoomAmount; const float Y = (TileSetRegion.Min.Y - ZoomPos.Y) * ZoomAmount; const float W = TileSetRegion.Width() * ZoomAmount; const float H = TileSetRegion.Height() * ZoomAmount; FCanvasBoxItem BoxItem(FVector2D(X, Y), FVector2D(W, H)); BoxItem.SetColor(BorderRectangleColor); Canvas->DrawItem(BoxItem); } if (bShowTilesWithCollision || bShowTilesWithMetaData) { // Draw an overlay rectangle on top of any tiles that have collision or metadata geometry const int32 NumTiles = TileSet->GetTileCount(); const FLinearColor CollisionOverlayColor(0.0f, 0.7f, 1.0f, 0.5f); const FLinearColor MetaDataOverlayColor(1.0f, 0.2f, 0.0f, 0.5f); const FLinearColor InfoOverlayColor = bShowTilesWithCollision ? CollisionOverlayColor : MetaDataOverlayColor; const FIntPoint TileSetTileSize(TileSet->GetTileSize()); const float Width = (TileSetTileSize.X - 2) * ZoomAmount; const float Height = (TileSetTileSize.Y - 2) * ZoomAmount; for (int32 TileIndex = 0; TileIndex < NumTiles; ++TileIndex) { if (const FPaperTileMetadata* TileMetadata = TileSet->GetTileMetadata(TileIndex)) { const bool bShowDueToCollision = TileMetadata->HasCollision() && bShowTilesWithCollision; const bool bShowDueToMetaData = TileMetadata->HasMetaData() && bShowTilesWithMetaData; if (bShowDueToCollision || bShowDueToMetaData) { FVector2D TileUV; TileSet->GetTileUV(TileIndex, /*out*/ TileUV); const float XPos = (TileUV.X + 1 - ZoomPos.X) * ZoomAmount; const float YPos = (TileUV.Y + 1 - ZoomPos.Y) * ZoomAmount; Canvas->DrawTile(XPos, YPos, Width, Height, 0.0f, 0.0f, 1.0f, 1.0f, InfoOverlayColor, GWhiteTexture, /*bUseTranslucentBlend=*/ true); } } } } } // Overlay the selection rectangles DrawSelectionRectangles(InViewport, Canvas); if (bHasValidPaintRectangle) { const FViewportSelectionRectangle& Rect = ValidPaintRectangle; const float X = (Rect.TopLeft.X - ZoomPos.X) * ZoomAmount; const float Y = (Rect.TopLeft.Y - ZoomPos.Y) * ZoomAmount; const float W = Rect.Dimensions.X * ZoomAmount; const float H = Rect.Dimensions.Y * ZoomAmount; FCanvasBoxItem BoxItem(FVector2D(X, Y), FVector2D(W, H)); BoxItem.SetColor(Rect.Color); Canvas->DrawItem(BoxItem); } if (CurrentSelectedTileIndex != INDEX_NONE) { const FString TileIndexString = FString::Printf(TEXT("Tile# %d"), CurrentSelectedTileIndex); int32 XL; int32 YL; StringSize(GEngine->GetLargeFont(), XL, YL, *TileIndexString); const float DrawX = 4.0f; const float DrawY = FMath::FloorToFloat(InViewport->GetSizeXY().Y - YL - 4.0f); Canvas->DrawShadowedString(DrawX, DrawY, *TileIndexString, GEngine->GetLargeFont(), FLinearColor::White); } }
void FTextureEditorViewportClient::Draw(FViewport* Viewport, FCanvas* Canvas) { if (!TextureEditorPtr.IsValid()) { return; } UTexture* Texture = TextureEditorPtr.Pin()->GetTexture(); FVector2D Ratio = FVector2D(GetViewportHorizontalScrollBarRatio(), GetViewportVerticalScrollBarRatio()); FVector2D ViewportSize = FVector2D(TextureEditorViewportPtr.Pin()->GetViewport()->GetSizeXY().X, TextureEditorViewportPtr.Pin()->GetViewport()->GetSizeXY().Y); FVector2D ScrollBarPos = GetViewportScrollBarPositions(); int32 YOffset = (Ratio.Y > 1.0f)? ((ViewportSize.Y - (ViewportSize.Y / Ratio.Y)) * 0.5f): 0; int32 YPos = YOffset - ScrollBarPos.Y; int32 XOffset = (Ratio.X > 1.0f)? ((ViewportSize.X - (ViewportSize.X / Ratio.X)) * 0.5f): 0; int32 XPos = XOffset - ScrollBarPos.X; UpdateScrollBars(); const UTextureEditorSettings& Settings = *GetDefault<UTextureEditorSettings>(); Canvas->Clear( Settings.BackgroundColor ); TextureEditorPtr.Pin()->PopulateQuickInfo(); // Get the rendering info for this object FThumbnailRenderingInfo* RenderInfo = GUnrealEd->GetThumbnailManager()->GetRenderingInfo(Texture); // If there is an object configured to handle it, draw the thumbnail if (RenderInfo != NULL && RenderInfo->Renderer != NULL) { UTexture2D* Texture2D = Cast<UTexture2D>(Texture); UTextureCube* TextureCube = Cast<UTextureCube>(Texture); UTextureRenderTarget2D* TextureRT2D = Cast<UTextureRenderTarget2D>(Texture); UTextureRenderTargetCube* RTTextureCube = Cast<UTextureRenderTargetCube>(Texture); // Fully stream in the texture before drawing it. if (Texture2D) { Texture2D->SetForceMipLevelsToBeResident(30.0f); Texture2D->WaitForStreaming(); } // Figure out the size we need uint32 Width, Height; TextureEditorPtr.Pin()->CalculateTextureDimensions(Width, Height); TRefCountPtr<FBatchedElementParameters> BatchedElementParameters; if (GMaxRHIFeatureLevel >= ERHIFeatureLevel::SM4) { if (TextureCube || RTTextureCube) { BatchedElementParameters = new FMipLevelBatchedElementParameters((float)TextureEditorPtr.Pin()->GetMipLevel(), false); } else if (Texture2D) { float MipLevel = (float)TextureEditorPtr.Pin()->GetMipLevel(); bool bIsNormalMap = Texture2D->IsNormalMap(); bool bIsSingleChannel = Texture2D->CompressionSettings == TC_Grayscale || Texture2D->CompressionSettings == TC_Alpha; BatchedElementParameters = new FBatchedElementTexture2DPreviewParameters(MipLevel, bIsNormalMap, bIsSingleChannel); } else if (TextureRT2D) { float MipLevel = (float)TextureEditorPtr.Pin()->GetMipLevel(); BatchedElementParameters = new FBatchedElementTexture2DPreviewParameters(MipLevel, false, false); } else { // Default to treating any UTexture derivative as a 2D texture resource float MipLevel = (float)TextureEditorPtr.Pin()->GetMipLevel(); BatchedElementParameters = new FBatchedElementTexture2DPreviewParameters(MipLevel, false, false); } } // Draw the background checkerboard pattern in the same size/position as the render texture so it will show up anywhere // the texture has transparency if (Settings.Background == TextureEditorBackground_CheckeredFill) { Canvas->DrawTile( 0.0f, 0.0f, Viewport->GetSizeXY().X, Viewport->GetSizeXY().Y, 0.0f, 0.0f, (Viewport->GetSizeXY().X / CheckerboardTexture->GetSizeX()), (Viewport->GetSizeXY().Y / CheckerboardTexture->GetSizeY()), FLinearColor::White, CheckerboardTexture->Resource); } else if (Settings.Background == TextureEditorBackground_Checkered) { Canvas->DrawTile( XPos, YPos, Width, Height, 0.0f, 0.0f, (Width / CheckerboardTexture->GetSizeX()), (Height / CheckerboardTexture->GetSizeY()), FLinearColor::White, CheckerboardTexture->Resource); } float Exposure = FMath::Pow(2.0f, (float)TextureEditorViewportPtr.Pin()->GetExposureBias()); FCanvasTileItem TileItem( FVector2D( XPos, YPos ), Texture->Resource, FVector2D( Width, Height ), FLinearColor(Exposure, Exposure, Exposure) ); TileItem.BlendMode = TextureEditorPtr.Pin()->GetColourChannelBlendMode(); TileItem.BatchedElementParameters = BatchedElementParameters; Canvas->DrawItem( TileItem ); // Draw a white border around the texture to show its extents if (Settings.TextureBorderEnabled) { FCanvasBoxItem BoxItem( FVector2D(XPos, YPos), FVector2D(Width , Height ) ); BoxItem.SetColor( Settings.TextureBorderColor ); Canvas->DrawItem( BoxItem ); } } }
/** * * @param Item the stat to render * @param Canvas the render interface to draw with * @param X the X location to start drawing at * @param Y the Y location to start drawing at * @param Indent Indentation of this cycles, used when rendering hierarchy * @param bStackStat If false, this is a non-stack cycle counter, don't render the call count column */ static int32 RenderCycle( const FComplexStatMessage& Item, class FCanvas* Canvas, int32 X, int32 Y, const int32 Indent, const bool bStackStat ) { FColor Color = GetStatRenderGlobals().StatColor; check(Item.NameAndInfo.GetFlag(EStatMetaFlags::IsCycle)); const bool bIsInitialized = Item.NameAndInfo.GetField<EStatDataType>() == EStatDataType::ST_int64; const int32 IndentWidth = Indent*8; if( bIsInitialized ) { const float InMs = FPlatformTime::ToMilliseconds(Item.GetValue_Duration(EComplexStatField::IncAve)); // Color will be determined by the average value of history // If show inclusive and and show exclusive is on, then it will choose color based on inclusive average // @TODO yrx 2014-08-21 This is slow, fix this. FString CounterName = Item.GetShortName().ToString(); CounterName.RemoveFromStart(TEXT("STAT_")); GEngine->GetStatValueColoration(CounterName, InMs, Color); const float MaxMeter = 33.3f; // the time of a "full bar" in ms const int32 MeterWidth = GetStatRenderGlobals().AfterNameColumnOffset; int32 BarWidth = int32((InMs / MaxMeter) * MeterWidth); if (BarWidth > 2) { if (BarWidth > MeterWidth ) { BarWidth = MeterWidth; } FCanvasBoxItem BoxItem( FVector2D(X + MeterWidth - BarWidth, Y + .4f * GetStatRenderGlobals().GetFontHeight()), FVector2D(BarWidth, 0.2f * GetStatRenderGlobals().GetFontHeight()) ); BoxItem.SetColor( FLinearColor::Red ); BoxItem.Draw( Canvas ); } } Canvas->DrawShadowedString(X + IndentWidth, Y, *ShortenName(*Item.GetDescription()), GetStatRenderGlobals().StatFont, Color); int32 CurrX = X + GetStatRenderGlobals().AfterNameColumnOffset; // Now append the call count if( bStackStat ) { if (Item.NameAndInfo.GetFlag(EStatMetaFlags::IsPackedCCAndDuration) && bIsInitialized) { RightJustify(Canvas,CurrX,Y,*FString::Printf(TEXT("%u"), Item.GetValue_CallCount(EComplexStatField::IncAve)),Color); } CurrX += GetStatRenderGlobals().InterColumnOffset; } // Add the two inclusive columns if asked if( bIsInitialized ) { RightJustify(Canvas,CurrX,Y,*FString::Printf(TEXT("%1.2f ms"),FPlatformTime::ToMilliseconds(Item.GetValue_Duration(EComplexStatField::IncAve))),Color); } CurrX += GetStatRenderGlobals().InterColumnOffset; if( bIsInitialized ) { RightJustify(Canvas,CurrX,Y,*FString::Printf(TEXT("%1.2f ms"),FPlatformTime::ToMilliseconds(Item.GetValue_Duration(EComplexStatField::IncMax))),Color); } CurrX += GetStatRenderGlobals().InterColumnOffset; if( bStackStat ) { // And the exclusive if asked if( bIsInitialized ) { RightJustify(Canvas,CurrX,Y,*FString::Printf(TEXT("%1.2f ms"),FPlatformTime::ToMilliseconds(Item.GetValue_Duration(EComplexStatField::ExcAve))),Color); } CurrX += GetStatRenderGlobals().InterColumnOffset; if( bIsInitialized ) { RightJustify(Canvas,CurrX,Y,*FString::Printf(TEXT("%1.2f ms"),FPlatformTime::ToMilliseconds(Item.GetValue_Duration(EComplexStatField::ExcMax))),Color); } CurrX += GetStatRenderGlobals().InterColumnOffset; } return GetStatRenderGlobals().GetFontHeight(); }
void FCanvasItemTestbed::Draw( class FViewport* Viewport, class FCanvas* Canvas ) { bTestState = !bTestState; if( !bShowTestbed ) { return; } // A little ott for a testbed - but I wanted to draw several lines to ensure it worked :) if( TestLine.bTestSet == false ) { TestLine.bTestSet = true; TestLine.LineStart.X = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().X ); TestLine.LineStart.Y = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().Y ); TestLine.LineEnd.X = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().X ); TestLine.LineEnd.Y = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().Y ); TestLine.LineMove.X = FMath::FRandRange( 0.0f, 32.0f ); TestLine.LineMove.Y = FMath::FRandRange( 0.0f, 32.0f ); TestLine.LineMove2.X = FMath::FRandRange( 0.0f, 32.0f ); TestLine.LineMove2.Y = FMath::FRandRange( 0.0f, 32.0f ); } else { TestLine.LineStart += TestLine.LineMove; TestLine.LineEnd += TestLine.LineMove2; if( TestLine.LineStart.X < 0 ) { TestLine.LineMove.X = -TestLine.LineMove.X; } if( TestLine.LineStart.Y < 0 ) { TestLine.LineMove.Y = -TestLine.LineMove.Y; } if( TestLine.LineEnd.X < 0 ) { TestLine.LineMove2.X = -TestLine.LineMove2.X; } if( TestLine.LineEnd.Y < 0 ) { TestLine.LineMove2.Y = -TestLine.LineMove2.Y; } if( TestLine.LineStart.X > Viewport->GetSizeXY().X ) { TestLine.LineMove.X = -TestLine.LineMove.X; } if( TestLine.LineStart.Y > Viewport->GetSizeXY().Y ) { TestLine.LineMove.Y = -TestLine.LineMove.Y; } if( TestLine.LineEnd.X > Viewport->GetSizeXY().X ) { TestLine.LineMove2.X = -TestLine.LineMove2.X; } if( TestLine.LineEnd.Y > Viewport->GetSizeXY().Y ) { TestLine.LineMove2.Y = -TestLine.LineMove2.Y; } } // Text float CenterX = 0.0f; float YTest = 16.0f; FCanvasTextItem TextItem( FVector2D( CenterX, YTest ), LOCTEXT( "stringhere", "String Here" ), GEngine->GetSmallFont(), FLinearColor::Red ); TextItem.Draw( Canvas ); // Shadowed text TextItem.Position.Y += TextItem.DrawnSize.Y; TextItem.Scale.X = 2.0f; TextItem.EnableShadow( FLinearColor::Green, FVector2D( 2.0f, 2.0f ) ); TextItem.Text = LOCTEXT( "Scaled String here", "Scaled String here" ); TextItem.Draw( Canvas ); TextItem.DisableShadow(); TextItem.Position.Y += TextItem.DrawnSize.Y;; TextItem.Text = LOCTEXT( "CenterdStringhere", "CenterdStringhere" ); TextItem.Scale.X = 1.0f; TextItem.bCentreX = true; TextItem.Draw( Canvas ); // Outlined text TextItem.Position.Y += TextItem.DrawnSize.Y; TextItem.Text = LOCTEXT( "ScaledCentredStringhere", "Scaled Centred String here" ); TextItem.OutlineColor = FLinearColor::Black; TextItem.bOutlined = true; TextItem.Scale = FVector2D( 2.0f, 2.0f ); TextItem.SetColor( FLinearColor::Green ); TextItem.Text = LOCTEXT( "ScaledCentredOutlinedStringhere", "Scaled Centred Outlined String here" ); TextItem.Draw( Canvas ); // a line FCanvasLineItem LineItem( TestLine.LineStart, TestLine.LineEnd ); LineItem.Draw( Canvas ); // some boxes FCanvasBoxItem BoxItem( FVector2D( 88.0f, 88.0f ), FVector2D( 188.0f, 188.0f ) ); BoxItem.SetColor( FLinearColor::Yellow ); BoxItem.Draw( Canvas ); BoxItem.SetColor( FLinearColor::Red ); BoxItem.Position = FVector2D( 256.0f, 256.0f ); BoxItem.Draw( Canvas ); BoxItem.SetColor( FLinearColor::Blue ); BoxItem.Position = FVector2D( 6.0f, 6.0f ); BoxItem.Size = FVector2D( 48.0f, 96.0f ); BoxItem.Draw( Canvas ); // Triangle FCanvasTriangleItem TriItem( FVector2D( 48.0f, 48.0f ), FVector2D( 148.0f, 48.0f ), FVector2D( 48.0f, 148.0f ), GWhiteTexture ); TriItem.Draw( Canvas ); // Triangle list TArray< FCanvasUVTri > TriangleList; FCanvasUVTri SingleTri; SingleTri.V0_Pos = FVector2D( 128.0f, 128.0f ); SingleTri.V1_Pos = FVector2D( 248.0f, 108.0f ); SingleTri.V2_Pos = FVector2D( 100.0f, 348.0f ); SingleTri.V0_UV = FVector2D::ZeroVector; SingleTri.V1_UV = FVector2D::ZeroVector; SingleTri.V2_UV = FVector2D::ZeroVector; TriangleList.Add( SingleTri ); SingleTri.V0_Pos = FVector2D( 348.0f, 128.0f ); SingleTri.V1_Pos = FVector2D( 448.0f, 148.0f ); SingleTri.V2_Pos = FVector2D( 438.0f, 308.0f ); TriangleList.Add( SingleTri ); FCanvasTriangleItem TriItemList( TriangleList, GWhiteTexture ); TriItemList.SetColor( FLinearColor::Red ); TriItemList.Draw( Canvas ); // FCanvasNGonItem NGon( FVector2D( 256.0f, 256.0f ), FVector2D( 256.0f, 256.0f ), 6, GWhiteTexture, FLinearColor::White ); // NGon.Draw( Canvas ); // // FCanvasNGonItem NGon2( FVector2D( 488, 666.0f ), FVector2D( 256.0f, 256.0f ), 16, GWhiteTexture, FLinearColor::Green ); // NGon2.Draw( Canvas ); // Texture UTexture* SelectedTexture = GEditor->GetSelectedObjects()->GetTop<UTexture>(); if( SelectedTexture ) { // Plain tex FCanvasTileItem TileItem( FVector2D( 128.0f,128.0f ), SelectedTexture->Resource, FLinearColor::White ); TileItem.Draw( Canvas ); TileItem.Size = FVector2D( 32.0f,32.0f ); TileItem.Position = FVector2D( 16.0f,16.0f ); TileItem.Draw( Canvas ); // UV TileItem.Size = FVector2D( 64.0f,64.0f ); TileItem.UV0 = FVector2D( 0.0f, 0.0f ); TileItem.UV1 = FVector2D( 1.0f, 1.0f ); TileItem.Position = FVector2D( 256.0f,16.0f ); TileItem.Draw( Canvas ); // UV TileItem.Size = FVector2D( 64.0f,64.0f ); TileItem.UV0 = FVector2D( 0.0f, 0.0f ); TileItem.UV1 = FVector2D( 1.0f, -1.0f ); TileItem.Position = FVector2D( 356.0f,16.0f ); TileItem.Draw( Canvas ); // UV TileItem.Size = FVector2D( 64.0f,64.0f ); TileItem.UV0 = FVector2D( 0.0f, 0.0f ); TileItem.UV1 = FVector2D( -1.0f, 1.0f ); TileItem.Position = FVector2D( 456.0f,16.0f ); TileItem.Draw( Canvas ); // UV TileItem.Size = FVector2D( 64.0f,64.0f ); TileItem.UV0 = FVector2D( 0.0f, 0.0f ); TileItem.UV1 = FVector2D( -1.0f, -1.0f ); TileItem.Position = FVector2D( 556.0f,16.0f ); TileItem.Draw( Canvas ); // Rotate top/left pivot TileItem.Size = FVector2D( 96.0f,96.0f ); TileItem.UV0 = FVector2D( 0.0f, 0.0f ); TileItem.UV1 = FVector2D( 1.0f, 1.0f ); TileItem.Position = FVector2D( 400.0f,264.0f ); TileItem.Rotation.Yaw = TestLine.Testangle; TileItem.Draw( Canvas ); // Rotate center pivot TileItem.Size = FVector2D( 128.0f, 128.0f ); TileItem.UV0 = FVector2D( 0.0f, 0.0f ); TileItem.UV1 = FVector2D( 1.0f, 1.0f ); TileItem.Position = FVector2D( 600.0f,264.0f ); TileItem.Rotation.Yaw = 360.0f - TestLine.Testangle; TileItem.PivotPoint = FVector2D( 0.5f, 0.5f ); TileItem.Draw( Canvas ); TestLine.Testangle = FMath::Fmod( TestLine.Testangle + 2.0f, 360.0f ); // textured tri FCanvasTriangleItem TriItemTex( FVector2D( 48.0f, 48.0f ), FVector2D( 148.0f, 48.0f ), FVector2D( 48.0f, 148.0f ), FVector2D( 0.0f, 0.0f ), FVector2D( 1.0f, 0.0f ), FVector2D( 0.0f, 1.0f ), SelectedTexture->Resource ); TriItem.Texture = GWhiteTexture; TriItemTex.Draw( Canvas ); // moving tri (only 1 point moves !) TriItemTex.Position = TestLine.LineStart; TriItemTex.Draw( Canvas ); } }