// Sort predicate operator bool operator()(UPaperSprite& LHS, UPaperSprite& RHS) const { FString LeftString; int32 LeftNumber; ExtractSpriteNumber(LHS.GetName(), /*out*/ LeftString, /*out*/ LeftNumber); FString RightString; int32 RightNumber; ExtractSpriteNumber(RHS.GetName(), /*out*/ RightString, /*out*/ RightNumber); return (LeftString == RightString) ? (LeftNumber < RightNumber) : (LeftString < RightString); }
void FSpriteEditorViewportClient::NotifySpriteBeingEditedHasChanged() { //@TODO: Ideally we do this before switching EndTransaction(); // Refresh the viewport in case we were not in realtime mode Invalidate(); // Update components to know about the new sprite being edited UPaperSprite* Sprite = GetSpriteBeingEdited(); RenderSpriteComponent->SetSprite(Sprite); UpdateSourceTextureSpriteFromSprite(Sprite); InternalActivateNewMode(CurrentMode); //@TODO: Only do this if the sprite isn't visible (may consider doing a flashing pulse around the source region rect?) RequestFocusOnSelection(/*bInstant=*/ true); if (Sprite != nullptr) { // Create and display a notification about the new sprite being edited const FText NotificationErrorText = FText::Format(LOCTEXT("SwitchingToSprite", "Editing {0}"), FText::AsCultureInvariant(Sprite->GetName())); FNotificationInfo Info(NotificationErrorText); Info.ExpireDuration = 2.0f; FSlateNotificationManager::Get().AddNotification(Info); } }
void FPaperSpriteSheetAssetTypeActions::ExecuteCreateFlipbooks(TArray<TWeakObjectPtr<UPaperSpriteSheet>> Objects) { for (int SpriteSheetIndex = 0; SpriteSheetIndex < Objects.Num(); ++SpriteSheetIndex) { UPaperSpriteSheet* SpriteSheet = Objects[SpriteSheetIndex].Get(); if (SpriteSheet != nullptr) { const FString PackagePath = FPackageName::GetLongPackagePath(SpriteSheet->GetOutermost()->GetPathName()); FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools"); FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser"); check(SpriteSheet->SpriteNames.Num() == SpriteSheet->Sprites.Num()); bool useSpriteNames = (SpriteSheet->SpriteNames.Num() == SpriteSheet->Sprites.Num()); // Create a list of sprites and sprite names to feed into paper flipbook helpers TMap<FString, TArray<UPaperSprite*> > SpriteFlipbookMap; { TArray<UPaperSprite*> Sprites; TArray<FString> SpriteNames; for (int SpriteIndex = 0; SpriteIndex < SpriteSheet->Sprites.Num(); ++SpriteIndex) { auto SpriteAssetPtr = SpriteSheet->Sprites[SpriteIndex]; FStringAssetReference SpriteStringRef = SpriteAssetPtr.ToStringReference(); UPaperSprite* Sprite = nullptr; if (!SpriteStringRef.ToString().IsEmpty()) { Sprite = Cast<UPaperSprite>(StaticLoadObject(UPaperSprite::StaticClass(), nullptr, *SpriteStringRef.ToString(), nullptr, LOAD_None, nullptr)); } if (Sprite != nullptr) { const FString SpriteName = useSpriteNames ? SpriteSheet->SpriteNames[SpriteIndex] : Sprite->GetName(); Sprites.Add(Sprite); SpriteNames.Add(SpriteName); } } FPaperFlipbookHelpers::ExtractFlipbooksFromSprites(/*out*/ SpriteFlipbookMap, Sprites, SpriteNames); } // Create one flipbook for every grouped flipbook name if (SpriteFlipbookMap.Num() > 0) { UPaperFlipbookFactory* FlipbookFactory = NewObject<UPaperFlipbookFactory>(); GWarn->BeginSlowTask(NSLOCTEXT("Paper2D", "Paper2D_CreateFlipbooks", "Creating flipbooks from selection"), true, true); int Progress = 0; int TotalProgress = SpriteFlipbookMap.Num(); TArray<UObject*> ObjectsToSync; for (auto It : SpriteFlipbookMap) { GWarn->UpdateProgress(Progress++, TotalProgress); const FString& FlipbookName = It.Key; TArray<UPaperSprite*>& Sprites = It.Value; const FString TentativePackagePath = PackageTools::SanitizePackageName(PackagePath + TEXT("/") + FlipbookName); FString DefaultSuffix; FString AssetName; FString PackageName; AssetToolsModule.Get().CreateUniqueAssetName(TentativePackagePath, DefaultSuffix, /*out*/ PackageName, /*out*/ AssetName); FlipbookFactory->KeyFrames.Empty(); for (int32 SpriteIndex = 0; SpriteIndex < Sprites.Num(); ++SpriteIndex) { FPaperFlipbookKeyFrame* KeyFrame = new (FlipbookFactory->KeyFrames) FPaperFlipbookKeyFrame(); KeyFrame->Sprite = Sprites[SpriteIndex]; KeyFrame->FrameRun = 1; } if (UObject* NewAsset = AssetToolsModule.Get().CreateAsset(AssetName, PackagePath, UPaperFlipbook::StaticClass(), FlipbookFactory)) { ObjectsToSync.Add(NewAsset); } if (GWarn->ReceivedUserCancel()) { break; } } GWarn->EndSlowTask(); if (ObjectsToSync.Num() > 0) { ContentBrowserModule.Get().SyncBrowserToAssets(ObjectsToSync); } } } } }
void FSpriteEditorViewportClient::DrawSourceRegion(FViewport& InViewport, FSceneView& View, FCanvas& Canvas, const FLinearColor& GeometryVertexColor) { const bool bIsHitTesting = Canvas.IsHitTesting(); UPaperSprite* Sprite = GetSpriteBeingEdited(); const float CornerCollisionVertexSize = 8.0f; const float EdgeCollisionVertexSize = 6.0f; const FLinearColor GeometryLineColor(GeometryVertexColor.R, GeometryVertexColor.G, GeometryVertexColor.B, 0.5f * GeometryVertexColor.A); const bool bDrawEdgeHitProxies = true; const bool bDrawCornerHitProxies = true; FVector2D BoundsVertices[4]; BoundsVertices[0] = SourceTextureSpaceToScreenSpace(View, Sprite->SourceUV); BoundsVertices[1] = SourceTextureSpaceToScreenSpace(View, Sprite->SourceUV + FVector2D(Sprite->SourceDimension.X, 0)); BoundsVertices[2] = SourceTextureSpaceToScreenSpace(View, Sprite->SourceUV + FVector2D(Sprite->SourceDimension.X, Sprite->SourceDimension.Y)); BoundsVertices[3] = SourceTextureSpaceToScreenSpace(View, Sprite->SourceUV + FVector2D(0, Sprite->SourceDimension.Y)); if (bShowNamesForSprites) { const FVector2D TextPos = SourceTextureSpaceToScreenSpace(View, Sprite->SourceUV + FVector2D(Sprite->SourceDimension.X*0.5f, Sprite->SourceDimension.Y*0.5f)); const FText AssetNameText = FText::AsCultureInvariant(Sprite->GetName()); FCanvasTextItem TextItem(TextPos, AssetNameText, GEngine->GetSmallFont(), FLinearColor::White); TextItem.EnableShadow(FLinearColor::Black); TextItem.bCentreX = true; TextItem.bCentreY = true; TextItem.Draw(&Canvas); } for (int32 VertexIndex = 0; VertexIndex < 4; ++VertexIndex) { const int32 NextVertexIndex = (VertexIndex + 1) % 4; // Draw the edge if (bIsHitTesting) { TSharedPtr<FSpriteSelectedSourceRegion> Data = MakeShareable(new FSpriteSelectedSourceRegion()); Data->SpritePtr = Sprite; Data->VertexIndex = 4 + VertexIndex; Canvas.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } FCanvasLineItem LineItem(BoundsVertices[VertexIndex], BoundsVertices[NextVertexIndex]); LineItem.SetColor(GeometryVertexColor); Canvas.DrawItem(LineItem); // Add edge hit proxy if (bDrawEdgeHitProxies) { const FVector2D MidPoint = (BoundsVertices[VertexIndex] + BoundsVertices[NextVertexIndex]) * 0.5f; Canvas.DrawTile(MidPoint.X - EdgeCollisionVertexSize*0.5f, MidPoint.Y - EdgeCollisionVertexSize*0.5f, EdgeCollisionVertexSize, EdgeCollisionVertexSize, 0.f, 0.f, 1.f, 1.f, GeometryVertexColor, GWhiteTexture); } if (bIsHitTesting) { Canvas.SetHitProxy(nullptr); } // Add corner hit proxy if (bDrawCornerHitProxies) { const FVector2D CornerPoint = BoundsVertices[VertexIndex]; if (bIsHitTesting) { TSharedPtr<FSpriteSelectedSourceRegion> Data = MakeShareable(new FSpriteSelectedSourceRegion()); Data->SpritePtr = Sprite; Data->VertexIndex = VertexIndex; Canvas.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } Canvas.DrawTile(CornerPoint.X - CornerCollisionVertexSize * 0.5f, CornerPoint.Y - CornerCollisionVertexSize * 0.5f, CornerCollisionVertexSize, CornerCollisionVertexSize, 0.f, 0.f, 1.f, 1.f, GeometryVertexColor, GWhiteTexture); if (bIsHitTesting) { Canvas.SetHitProxy(nullptr); } } } }