bool FSpriteGeometryEditMode::InputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event)
{
	bool bHandled = false;
	FInputEventState InputState(Viewport, Key, Event);

	// Handle marquee tracking in source region edit mode
	if (IsEditingGeometry())
	{
		if (SpriteGeometryHelper.IsAddingPolygon())
		{
			if (Key == EKeys::LeftMouseButton)
			{
				const int32 HitX = Viewport->GetMouseX();
				const int32 HitY = Viewport->GetMouseY();

				// Calculate the texture space position of the mouse click
				FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags));
				FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily);
				const FVector WorldPoint = View->PixelToWorld(HitX, HitY, 0);
				const FVector2D TexturePoint = SpriteGeometryHelper.GetEditorContext()->WorldSpaceToTextureSpace(WorldPoint);

				// Add or close the polygon (depending on where the click happened and how)
				const bool bMakeSubtractiveIfAllowed = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl);
				SpriteGeometryHelper.HandleAddPolygonClick(TexturePoint, bMakeSubtractiveIfAllowed, *View, Event);
			}
			else if ((Key == EKeys::BackSpace) && (Event == IE_Pressed))
			{
				SpriteGeometryHelper.DeleteLastVertexFromAddPolygonMode();
			}			
			else if (Key == EKeys::Enter)
			{
				SpriteGeometryHelper.ResetAddPolygonMode();
			}
			else if (Key == EKeys::Escape)
			{
				SpriteGeometryHelper.AbandonAddPolygonMode();
			}
		}
		else
		{
 			if (ProcessMarquee(Viewport, Key, Event, true))
 			{
 				const bool bAddingToSelection = InputState.IsShiftButtonPressed(); //@TODO: control button moves widget? Hopefully make this more consistent when that is changed
 				SelectVerticesInMarquee(ViewportClient, Viewport, bAddingToSelection);
 			}
		}
	}

	//@TODO: Support select-and-drag in a single operation (may involve InputAxis and StartTracking)

	// Pass keys to standard controls, if we didn't consume input
	return bHandled ? true : FEdMode::InputKey(ViewportClient, Viewport, Key, Event);
}
void FSpriteGeometryEditingHelper::DeleteSelectedItems()
{
	// Determine which vertices or entire shapes should be deleted
	TSet<FShapeVertexPair> CompositeIndicesSet;
	TSet<int32> ShapesToDeleteSet;

	if (IsEditingGeometry())
	{
		FSpriteGeometryCollection& Geometry = GetGeometryChecked();

		for (TSharedPtr<FSelectedItem> SelectionIt : GetSelectionSet())
		{
			if (const FSpriteSelectedVertex* SelectedVertex = SelectionIt->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex))
			{
				CompositeIndicesSet.Add(FShapeVertexPair(SelectedVertex->ShapeIndex, SelectedVertex->VertexIndex));

				if (SelectedVertex->IsA(FSelectionTypes::Edge)) // add the "next" point for the edge
				{
					const int32 NextIndex = (SelectedVertex->VertexIndex + 1) % Geometry.Shapes[SelectedVertex->ShapeIndex].Vertices.Num();
					CompositeIndicesSet.Add(FShapeVertexPair(SelectedVertex->ShapeIndex, NextIndex));
				}
			}
			else if (const FSpriteSelectedShape* SelectedShape = SelectionIt->CastTo<const FSpriteSelectedShape>(FSelectionTypes::GeometryShape))
			{
				ShapesToDeleteSet.Add(SelectedShape->ShapeIndex);
			}
		}
	}

	// See if anything else can be deleted
	bool bCanDeleteNonGeometry = false;
	for (const TSharedPtr<FSelectedItem> SelectedItem : GetSelectionSet())
	{
		if (SelectedItem->CanBeDeleted())
		{
			bCanDeleteNonGeometry = true;
			break;
		}
	}

	// Now delete the stuff that was selected in the correct order so that indices aren't messed up
	const bool bDeletingGeometry = (CompositeIndicesSet.Num() > 0) || (ShapesToDeleteSet.Num() > 0);
	if (bDeletingGeometry || bCanDeleteNonGeometry)
	{
		EditorContext->BeginTransaction(LOCTEXT("DeleteSelectionTransaction", "Delete Selection"));
		EditorContext->MarkTransactionAsDirty();

		if (bDeletingGeometry)
		{
			FSpriteGeometryCollection& Geometry = GetGeometryChecked();

			// Delete the selected vertices first, as they may cause entire shapes to need to be deleted (sort so we delete from the back first)
			TArray<FShapeVertexPair> CompositeIndices = CompositeIndicesSet.Array();
			CompositeIndices.Sort([](const FShapeVertexPair& A, const FShapeVertexPair& B) { return (A.VertexIndex > B.VertexIndex); });
			for (const FShapeVertexPair& Composite : CompositeIndices)
			{
				const int32 ShapeIndex = Composite.ShapeIndex;
				const int32 VertexIndex = Composite.VertexIndex;
				if (DeleteVertexInPolygonInternal(Geometry, ShapeIndex, VertexIndex))
				{
					ShapesToDeleteSet.Add(ShapeIndex);
				}
			}

			// Delete the selected shapes (plus any shapes that became empty due to selected vertices)
			if (ShapesToDeleteSet.Num() > 0)
			{
				// Sort so we delete from the back first
				TArray<int32> ShapesToDeleteIndicies = ShapesToDeleteSet.Array();
				ShapesToDeleteIndicies.Sort([](const int32& A, const int32& B) { return (A > B); });
				for (const int32 ShapeToDeleteIndex : ShapesToDeleteIndicies)
				{
					Geometry.Shapes.RemoveAt(ShapeToDeleteIndex);
				}
			}

			Geometry.GeometryType = ESpritePolygonMode::FullyCustom;
		}

		// Delete everything else
		if (bCanDeleteNonGeometry)
		{
			for (TSharedPtr<FSelectedItem> SelectedItem : GetSelectionSet())
			{
				if (SelectedItem->CanBeDeleted())
				{
					SelectedItem->DeleteThisItem();
				}
			}
		}

		EditorContext->EndTransaction();
	}

	ClearSelectionSet();
	ResetAddPolygonMode();
}
bool FSpriteGeometryEditMode::HandleClick(FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FViewportClick& Click)
{
	FViewport* Viewport = InViewportClient->Viewport;

	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;

	const bool bAllowSelectVertex = !(IsEditingGeometry() && SpriteGeometryHelper.IsAddingPolygon()) && !bIsShiftKeyDown;

	const bool bClearSelectionModifier = bIsCtrlKeyDown;
	const bool bDeleteClickedVertex = bIsAltKeyDown;
	const bool bInsertVertexModifier = bIsShiftKeyDown;
	HSpriteSelectableObjectHitProxy* SelectedItemProxy = HitProxyCast<HSpriteSelectableObjectHitProxy>(HitProxy);

	if (bAllowSelectVertex && (SelectedItemProxy != nullptr))
	{
		if (!bClearSelectionModifier)
		{
			SpriteGeometryHelper.ClearSelectionSet();
		}

		if (bDeleteClickedVertex)
		{
			// Delete selection
			if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemProxy->Data->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex))
			{
				SpriteGeometryHelper.ClearSelectionSet();
				SpriteGeometryHelper.AddPolygonVertexToSelection(SelectedVertex->ShapeIndex, SelectedVertex->VertexIndex);
				SpriteGeometryHelper.DeleteSelectedItems();
			}
			else if (const FSpriteSelectedShape* SelectedShape = SelectedItemProxy->Data->CastTo<const FSpriteSelectedShape>(FSelectionTypes::GeometryShape))
			{
				SpriteGeometryHelper.ClearSelectionSet();
				SpriteGeometryHelper.AddShapeToSelection(SelectedShape->ShapeIndex);
				SpriteGeometryHelper.DeleteSelectedItems();
			}
		}
		else if (Click.GetEvent() == EInputEvent::IE_DoubleClick)
		{
			// Double click to select a polygon
			if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemProxy->Data->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex))
			{
				SpriteGeometryHelper.ClearSelectionSet();
				SpriteGeometryHelper.AddShapeToSelection(SelectedVertex->ShapeIndex);
			}
		}
		else
		{
			//@TODO: This needs to be generalized!
			if (const FSpriteSelectedEdge* SelectedEdge = SelectedItemProxy->Data->CastTo<const FSpriteSelectedEdge>(FSelectionTypes::Edge))
			{
				// Add the next vertex defined by this edge
				SpriteGeometryHelper.AddPolygonEdgeToSelection(SelectedEdge->ShapeIndex, SelectedEdge->VertexIndex);
			}
			else if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemProxy->Data->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex))
			{
				SpriteGeometryHelper.AddPolygonVertexToSelection(SelectedVertex->ShapeIndex, SelectedVertex->VertexIndex);
			}
			else if (const FSpriteSelectedShape* SelectedShape = SelectedItemProxy->Data->CastTo<const FSpriteSelectedShape>(FSelectionTypes::GeometryShape))
			{
				SpriteGeometryHelper.AddShapeToSelection(SelectedShape->ShapeIndex);
			}
			else
			{
				SpriteGeometryHelper.SelectItem(SelectedItemProxy->Data);
			}
		}

		bHandled = true;
	}
	// 	else if (HWidgetUtilProxy* PivotProxy = HitProxyCast<HWidgetUtilProxy>(HitProxy))
	// 	{
	// 		//const bool bUserWantsPaint = bIsLeftButtonDown && ( !GetDefault<ULevelEditorViewportSettings>()->bLeftMouseDragMovesCamera ||  bIsCtrlDown );
	// 		//findme
	// 		WidgetAxis = WidgetProxy->Axis;
	// 
	// 			// Calculate the screen-space directions for this drag.
	// 			FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( Viewport, GetScene(), EngineShowFlags ));
	// 			FSceneView* View = CalcSceneView(&ViewFamily);
	// 			WidgetProxy->CalcVectors(View, FViewportClick(View, this, Key, Event, HitX, HitY), LocalManipulateDir, WorldManipulateDir, DragX, DragY);
	// 			bHandled = true;
	// 	}
	else
	{
		if (IsEditingGeometry() && !SpriteGeometryHelper.IsAddingPolygon())
		{
			FSpriteGeometryCollection* Geometry = SpriteGeometryHelper.GetGeometryBeingEdited();

			if (bInsertVertexModifier)
			{
				const FPlane SpritePlane(PaperAxisX, FVector::ZeroVector, PaperAxisY);
				const FVector WorldPoint = FMath::LinePlaneIntersection(Click.GetOrigin(), Click.GetOrigin() + Click.GetDirection(), SpritePlane);
				const FVector2D SpriteSpaceClickPoint = SpriteGeometryHelper.GetEditorContext()->WorldSpaceToTextureSpace(WorldPoint);

				// find a polygon to add vert to
				bool bFoundShapeToAddTo = false;
				for (TSharedPtr<FSelectedItem> SelectedItemPtr : SpriteGeometryHelper.GetSelectionSet())
				{
					if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemPtr->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex)) //@TODO:  Inflexible?
					{
						SpriteGeometryHelper.AddPointToGeometry(SpriteSpaceClickPoint, SelectedVertex->ShapeIndex);
						bFoundShapeToAddTo = true;
						break;
					}
				}

				if (!bFoundShapeToAddTo)
				{
					SpriteGeometryHelper.AddPointToGeometry(SpriteSpaceClickPoint);
				}
				bHandled = true;
			}
		}
		else if (!IsEditingGeometry())
		{
			// Clicked on the background (missed any proxies), deselect the socket or whatever was selected
			SpriteGeometryHelper.ClearSelectionSet();
		}
	}

	return bHandled ? true : FEdMode::HandleClick(InViewportClient, HitProxy, Click);
}