コード例 #1
0
// Extract the sprites based on SpriteExtractSettings->Mode
void SPaperExtractSpritesDialog::PreviewExtractedSprites()
{
	FScopedSlowTask SlowTask(2, NSLOCTEXT("Paper2D", "Paper2D_ExtractingSprites", "Extracting Sprites"));
	SlowTask.MakeDialog(false);
	SlowTask.EnterProgressFrame();

	const FString DefaultSuffix = TEXT("Sprite");
	if (ExtractSpriteSettings->Mode == ESpriteExtractMode::Auto)
	{
		ExtractedSprites.Empty();

		// First extract the rects from the texture
		TArray<FIntRect> ExtractedRects;
		UPaperSprite::ExtractRectsFromTexture(SourceTexture, /*out*/ ExtractedRects);

		// Sort the rectangles by approximate row
		struct FRectangleSortHelper
		{
			FRectangleSortHelper(TArray<FIntRect>& InOutSprites)
			{
				// Sort by Y, then by X (top left corner), descending order (so we can use it as a stack from the top row down)
				TArray<FIntRect> SpritesLeft = InOutSprites;
				SpritesLeft.Sort([](const FIntRect& A, const FIntRect& B) { return (A.Min.Y == B.Min.Y) ? (A.Min.X > B.Min.X) : (A.Min.Y > B.Min.Y); });
				InOutSprites.Reset();

				// Start pulling sprites out, the first one in each row will dominate remaining ones and cause them to get labeled
				TArray<FIntRect> DominatedSprites;
				DominatedSprites.Empty(SpritesLeft.Num());
				while (SpritesLeft.Num())
				{
					FIntRect DominatingSprite = SpritesLeft.Pop();
					DominatedSprites.Add(DominatingSprite);

					// Find the sprites that are dominated (intersect the infinite horizontal band described by the dominating sprite)
					for (int32 Index = 0; Index < SpritesLeft.Num();)
					{
						const FIntRect& CurElement = SpritesLeft[Index];
						if ((CurElement.Min.Y <= DominatingSprite.Max.Y) && (CurElement.Max.Y >= DominatingSprite.Min.Y))
						{
							DominatedSprites.Add(CurElement);
							SpritesLeft.RemoveAt(Index, /*Count=*/ 1, /*bAllowShrinking=*/ false);
						}
						else
						{
							++Index;
						}
					}

					// Sort the sprites in the band by X and add them to the result
					DominatedSprites.Sort([](const FIntRect& A, const FIntRect& B) { return (A.Min.X < B.Min.X); });
					InOutSprites.Append(DominatedSprites);
					DominatedSprites.Reset();
				}
			}
		};
		FRectangleSortHelper RectSorter(ExtractedRects);

		int32 ExtractedRectIndex = 0;
		for (FIntRect Rect : ExtractedRects)
		{
			FPaperExtractedSprite* Sprite = new(ExtractedSprites)FPaperExtractedSprite();
			Sprite->Rect = Rect;
			Sprite->Name = FString::Printf(TEXT("%s_%d"), *DefaultSuffix, ExtractedRectIndex);
			ExtractedRectIndex++;
		}
	}
	else
	{
		// Calculate rects
		ExtractedSprites.Empty();
		if (SourceTexture != nullptr)
		{
			int32 ExtractedRectIndex = 0;
			int32 TextureWidth = SourceTexture->GetSizeX();
			int32 TextureHeight = SourceTexture->GetSizeY();
			for (int32 Y = ExtractSpriteSettings->Margin; Y + ExtractSpriteSettings->GridHeight <= TextureHeight; Y += ExtractSpriteSettings->GridHeight + ExtractSpriteSettings->Spacing)
			{
				for (int32 X = ExtractSpriteSettings->Margin; X + ExtractSpriteSettings->GridWidth <= TextureWidth; X += ExtractSpriteSettings->GridWidth + ExtractSpriteSettings->Spacing)
				{
					FPaperExtractedSprite* Sprite = new(ExtractedSprites)FPaperExtractedSprite();
					Sprite->Rect = FIntRect(X, Y, X + ExtractSpriteSettings->GridWidth, Y + ExtractSpriteSettings->GridHeight);
					Sprite->Name = FString::Printf(TEXT("%s_%d"), *DefaultSuffix, ExtractedRectIndex);
					ExtractedRectIndex++;
				}
			}
		}
	}
}
コード例 #2
0
	void CreateSpritesFromTextures(TArray<UTexture2D*>& Textures)
	{
		const FString DefaultSuffix = TEXT("_Sprite");

		FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>("AssetTools");
		FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");

		TArray<UObject*> ObjectsToSync;

		for (auto TextureIt = Textures.CreateConstIterator(); TextureIt; ++TextureIt)
		{
			UTexture2D* Texture = *TextureIt;

			// Create the factory used to generate the sprite
			UPaperSpriteFactory* SpriteFactory = ConstructObject<UPaperSpriteFactory>(UPaperSpriteFactory::StaticClass());
			SpriteFactory->InitialTexture = Texture;

			// Create the sprite
			FString Name;
			FString PackageName;

			if (!bExtractSprites)
			{
				// Get a unique name for the sprite
				AssetToolsModule.Get().CreateUniqueAssetName(Texture->GetOutermost()->GetName(), DefaultSuffix, /*out*/ PackageName, /*out*/ Name);
				const FString PackagePath = FPackageName::GetLongPackagePath(PackageName);

				if (UObject* NewAsset = AssetToolsModule.Get().CreateAsset(Name, PackagePath, UPaperSprite::StaticClass(), SpriteFactory))
				{
					ObjectsToSync.Add(NewAsset);
				}
			}
			else
			{
				FScopedSlowTask Feedback(1, NSLOCTEXT("Paper2D", "Paper2D_ExtractSpritesFromTexture", "Extracting Sprites From Texture"));
				Feedback.MakeDialog(true);

				// First extract the rects from the texture
				TArray<FIntRect> ExtractedRects;
				UPaperSprite::ExtractRectsFromTexture(Texture, /*out*/ ExtractedRects);

				// Sort the rectangles by approximate row
				struct FRectangleSortHelper
				{
					FRectangleSortHelper(TArray<FIntRect>& InOutSprites)
					{
						// Sort by Y, then by X (top left corner), descending order (so we can use it as a stack from the top row down)
						TArray<FIntRect> SpritesLeft = InOutSprites;
						SpritesLeft.Sort([](const FIntRect& A, const FIntRect& B) { return (A.Min.Y == B.Min.Y) ? (A.Min.X > B.Min.X) : (A.Min.Y > B.Min.Y); });
						InOutSprites.Reset();

						// Start pulling sprites out, the first one in each row will dominate remaining ones and cause them to get labeled
						TArray<FIntRect> DominatedSprites;
						DominatedSprites.Empty(SpritesLeft.Num());
 						while (SpritesLeft.Num())
 						{
							FIntRect DominatingSprite = SpritesLeft.Pop();
							DominatedSprites.Add(DominatingSprite);

							// Find the sprites that are dominated (intersect the infinite horizontal band described by the dominating sprite)
							for (int32 Index = 0; Index < SpritesLeft.Num();)
							{
								const FIntRect& CurElement = SpritesLeft[Index];
								if ((CurElement.Min.Y <= DominatingSprite.Max.Y) && (CurElement.Max.Y >= DominatingSprite.Min.Y))
								{
									DominatedSprites.Add(CurElement);
									SpritesLeft.RemoveAt(Index, /*Count=*/ 1, /*bAllowShrinking=*/ false);
								}
								else
								{
									++Index;
								}
							}

							// Sort the sprites in the band by X and add them to the result
							DominatedSprites.Sort([](const FIntRect& A, const FIntRect& B) { return (A.Min.X < B.Min.X); });
							InOutSprites.Append(DominatedSprites);
							DominatedSprites.Reset();
 						}
					}
				};
				FRectangleSortHelper RectSorter(ExtractedRects);

				Feedback.TotalAmountOfWork = ExtractedRects.Num();

				for (int ExtractedRectIndex = 0; ExtractedRectIndex < ExtractedRects.Num(); ++ExtractedRectIndex)
				{
					Feedback.EnterProgressFrame(1, NSLOCTEXT("Paper2D", "Paper2D_ExtractSpritesFromTexture", "Extracting Sprites From Texture"));

					FIntRect& ExtractedRect = ExtractedRects[ExtractedRectIndex];
					SpriteFactory->bUseSourceRegion = true;
					SpriteFactory->InitialSourceUV = FVector2D(ExtractedRect.Min.X, ExtractedRect.Min.Y);
					SpriteFactory->InitialSourceDimension = FVector2D(ExtractedRect.Width(), ExtractedRect.Height());

					// Get a unique name for the sprite
					const FString Suffix = FString::Printf(TEXT("%s_%d"), *DefaultSuffix, ExtractedRectIndex);
					AssetToolsModule.Get().CreateUniqueAssetName(Texture->GetOutermost()->GetName(), Suffix, /*out*/ PackageName, /*out*/ Name);
					const FString PackagePath = FPackageName::GetLongPackagePath(PackageName);

					if (UObject* NewAsset = AssetToolsModule.Get().CreateAsset(Name, PackagePath, UPaperSprite::StaticClass(), SpriteFactory))
					{
						ObjectsToSync.Add(NewAsset);
					}

					if (GWarn->ReceivedUserCancel()) 
					{
						break;
					}
				}
			}
		}

		if (ObjectsToSync.Num() > 0)
		{
			ContentBrowserModule.Get().SyncBrowserToAssets(ObjectsToSync);
		}
	}