bool FSpriteEditorViewportClient::InputKey(FViewport* Viewport, int32 ControllerId, FKey Key, EInputEvent Event, float AmountDepressed, bool bGamepad)
{
	bool bHandled = false;
	FInputEventState InputState(Viewport, Key, Event);

	// Handle marquee tracking in source region edit mode
	if (IsInSourceRegionEditMode())
	{
		FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry);
		check(GeometryEditMode);

		const bool bMarqueeStartModifier = InputState.IsCtrlButtonPressed();
		if (GeometryEditMode->ProcessMarquee(Viewport, Key, Event, bMarqueeStartModifier))
		{
			FIntPoint TextureSpaceStartPos;
			FIntPoint TextureSpaceDimensions;
			if (ConvertMarqueeToSourceTextureSpace(/*out*/TextureSpaceStartPos, /*out*/TextureSpaceDimensions))
			{
				//@TODO: Warn if overlapping with another sprite
				CreateNewSprite(TextureSpaceStartPos, TextureSpaceDimensions);
			}
		}
	}
	
	// Pass keys to standard controls, if we didn't consume input
	return (bHandled) ? true : FEditorViewportClient::InputKey(Viewport, ControllerId, Key, Event, AmountDepressed, bGamepad);
}
bool UHGGifFactory::GenerateSprites(const TArray<UTexture2D*>& Textures, /*out*/TArray<UPaperSprite*>& OutSprites, UObject* InParent, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
	FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>("AssetTools");
	FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");

	TArray<UObject*> ObjectsToSync;

	for (UTexture2D* Texture : Textures)
	{
		if (Texture != nullptr)
		{
			FString Name;
			FString PackageName;

			const FString DefaultSuffix = TEXT("_Sprite");
			AssetToolsModule.Get().CreateUniqueAssetName(Texture->GetName(), DefaultSuffix, /*out*/ PackageName, /*out*/ Name);

			UPaperSprite* NewAsset = CreateNewSprite(Texture, UPaperSprite::StaticClass(), InParent, *Name, Flags, Context, Warn);
			ObjectsToSync.Add(NewAsset);
			OutSprites.Add(NewAsset);
		}
	}

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

	return false;
}
void FSpriteEditorViewportClient::ProcessClick(FSceneView& View, HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY)
{
	const FViewportClick Click(&View, this, Key, Event, HitX, HitY);
	const bool bIsCtrlKeyDown = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl);
	const bool bIsShiftKeyDown = Viewport->KeyState(EKeys::LeftShift) || Viewport->KeyState(EKeys::RightShift);
	const bool bIsAltKeyDown = Viewport->KeyState(EKeys::LeftAlt) || Viewport->KeyState(EKeys::RightAlt);
	bool bHandled = false;

	HSpriteSelectableObjectHitProxy* SelectedItemProxy = HitProxyCast<HSpriteSelectableObjectHitProxy>(HitProxy);

	if (IsInSourceRegionEditMode())
	{
		if ((Event == EInputEvent::IE_DoubleClick) && (Key == EKeys::LeftMouseButton))
		{
			FVector4 WorldPoint = View.PixelToWorld(HitX, HitY, 0);
			UPaperSprite* Sprite = GetSpriteBeingEdited();
			FVector2D TexturePoint = SourceTextureViewComponent->GetSprite()->ConvertWorldSpaceToTextureSpace(WorldPoint);
			if (bIsCtrlKeyDown)
			{
				const FVector2D StartingUV = Sprite->GetSourceUV();
				const FVector2D StartingSize = Sprite->GetSourceSize();

				if (UPaperSprite* NewSprite = CreateNewSprite(FIntPoint((int32)StartingUV.X, (int32)StartingUV.Y), FIntPoint((int32)StartingSize.X, (int32)StartingSize.Y)))
				{
					NewSprite->ExtractSourceRegionFromTexturePoint(TexturePoint);
					bHandled = true;
				}
			}
			else
			{
				Sprite->ExtractSourceRegionFromTexturePoint(TexturePoint);
				bHandled = true;
			}
		}
		else if ((Event == EInputEvent::IE_Released) && (Key == EKeys::LeftMouseButton))
		{
			FVector4 WorldPoint = View.PixelToWorld(HitX, HitY, 0);
			FVector2D TexturePoint = SourceTextureViewComponent->GetSprite()->ConvertWorldSpaceToTextureSpace(WorldPoint);
			for (int32 RelatedSpriteIndex = 0; RelatedSpriteIndex < RelatedSprites.Num(); ++RelatedSpriteIndex)
			{
				FRelatedSprite& RelatedSprite = RelatedSprites[RelatedSpriteIndex];
				if ((TexturePoint.X >= RelatedSprite.SourceUV.X) && (TexturePoint.Y >= RelatedSprite.SourceUV.Y) &&
					(TexturePoint.X < (RelatedSprite.SourceUV.X + RelatedSprite.SourceDimension.X)) &&
					(TexturePoint.Y < (RelatedSprite.SourceUV.Y + RelatedSprite.SourceDimension.Y)))
				{
					bHandled = true;

					// Select this sprite
					if (UPaperSprite* LoadedSprite = Cast<UPaperSprite>(RelatedSprite.AssetData.GetAsset()))
					{
						if (SpriteEditorPtr.IsValid())
						{
							SpriteEditorPtr.Pin()->SetSpriteBeingEdited(LoadedSprite);
							break;
						}
					}
				}
			}
		}
	}

	if (!bHandled)
	{
		FPaperEditorViewportClient::ProcessClick(View, HitProxy, Key, Event, HitX, HitY);
	}
}