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); }
void FSpriteEditorViewportClient::ActivateEditMode() { // Activate the sprite geometry edit mode ModeTools->SetToolkitHost(SpriteEditorPtr.Pin()->GetToolkitHost()); ModeTools->SetDefaultMode(FSpriteGeometryEditMode::EM_SpriteGeometry); ModeTools->ActivateDefaultMode(); FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry); check(GeometryEditMode); GeometryEditMode->SetEditorContext(this); GeometryEditMode->BindCommands(SpriteEditorViewportPtr.Pin()->GetCommandList()); ModeTools->SetWidgetMode(FWidget::WM_Translate); }
void FSingleTileEditorViewportClient::ActivateEditMode(TSharedPtr<FUICommandList> InCommandList) { // Activate the sprite geometry edit mode //@TODO: ModeTools->SetToolkitHost(SpriteEditorPtr.Pin()->GetToolkitHost()); ModeTools->SetDefaultMode(FSpriteGeometryEditMode::EM_SpriteGeometry); ModeTools->ActivateDefaultMode(); ModeTools->SetWidgetMode(FWidget::WM_Translate); FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry); check(GeometryEditMode); GeometryEditMode->SetEditorContext(this); GeometryEditMode->BindCommands(InCommandList /*SpriteEditorViewportPtr.Pin()->GetCommandList()*/); const FLinearColor CollisionShapeColor(0.0f, 0.7f, 1.0f, 1.0f); //@TODO: Duplicated constant from SpriteEditingConstants GeometryEditMode->SetGeometryColors(CollisionShapeColor, FLinearColor::White); }
void FSpriteEditorViewportClient::InternalActivateNewMode(ESpriteEditorMode::Type NewMode) { CurrentMode = NewMode; Viewport->InvalidateHitProxy(); UPaperSprite* Sprite = GetSpriteBeingEdited(); FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry); check(GeometryEditMode); // Note: This has side effects (clearing the selection set, ensuring the geometry is correct if the sprite being edited changed, etc...). // Do not skip even if the mode is not really changing. GeometryEditMode->SetGeometryBeingEdited(nullptr, /*bAllowCircles=*/ false, /*bAllowSubtractivePolygons=*/ false); switch (CurrentMode) { case ESpriteEditorMode::ViewMode: break; case ESpriteEditorMode::EditSourceRegionMode: UpdateRelatedSpritesList(); break; case ESpriteEditorMode::EditCollisionMode: GeometryEditMode->SetGeometryColors(SpriteEditingConstants::CollisionShapeColor, FLinearColor::White); if (Sprite != nullptr) { GeometryEditMode->SetGeometryBeingEdited(&(Sprite->CollisionGeometry), /*bAllowCircles=*/ true, /*bAllowSubtractivePolygons=*/ false); } break; case ESpriteEditorMode::EditRenderingGeomMode: GeometryEditMode->SetGeometryColors(SpriteEditingConstants::RenderShapeColor, SpriteEditingConstants::SubtractiveRenderShapeColor); if (Sprite != nullptr) { GeometryEditMode->SetGeometryBeingEdited(&(Sprite->RenderGeometry), /*bAllowCircles=*/ false, /*bAllowSubtractivePolygons=*/ true); } break; } }
void FSingleTileEditorViewportClient::SetTileIndex(int32 InTileIndex) { const int32 OldTileIndex = TileBeingEditedIndex; const bool bNewIndexValid = (InTileIndex >= 0) && (InTileIndex < TileSet->GetTileCount()); TileBeingEditedIndex = bNewIndexValid ? InTileIndex : INDEX_NONE; FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry); check(GeometryEditMode); FSpriteGeometryCollection* GeomToEdit = nullptr; if (TileBeingEditedIndex != INDEX_NONE) { if (FPaperTileMetadata* Metadata = TileSet->GetMutableTileMetadata(InTileIndex)) { GeomToEdit = &(Metadata->CollisionData); } } // Tell the geometry editor about the new tile (if it exists) GeometryEditMode->SetGeometryBeingEdited(GeomToEdit, /*bAllowCircles=*/ true, /*bAllowSubtractivePolygons=*/ false); // Update the visual representation UPaperSprite* DummySprite = nullptr; if (TileBeingEditedIndex != INDEX_NONE) { DummySprite = NewObject<UPaperSprite>(); DummySprite->SpriteCollisionDomain = ESpriteCollisionMode::None; DummySprite->PivotMode = ESpritePivotMode::Center_Center; DummySprite->CollisionGeometry.GeometryType = ESpritePolygonMode::SourceBoundingBox; DummySprite->RenderGeometry.GeometryType = ESpritePolygonMode::SourceBoundingBox; FSpriteAssetInitParameters SpriteReinitParams; SpriteReinitParams.Texture = TileSet->GetTileSheetTexture(); //@TODO: Should analyze the texture (*at a higher level, not per tile click!*) to pick the correct material FVector2D UV; TileSet->GetTileUV(TileBeingEditedIndex, /*out*/ UV); SpriteReinitParams.Offset = FIntPoint((int32)UV.X, (int32)(UV.Y)); SpriteReinitParams.Dimension = TileSet->GetTileSize(); SpriteReinitParams.SetPixelsPerUnrealUnit(1.0f); DummySprite->InitializeSprite(SpriteReinitParams); } PreviewTileSpriteComponent->SetSprite(DummySprite); // Update the default geometry bounds const FVector2D HalfTileSize(TileSet->GetTileSize().X * 0.5f, TileSet->GetTileSize().Y * 0.5f); FBox2D DesiredBounds(ForceInitToZero); DesiredBounds.Min = -HalfTileSize; DesiredBounds.Max = HalfTileSize; GeometryEditMode->SetNewGeometryPreferredBounds(DesiredBounds); // Zoom to fit when we start editing a tile and weren't before, but leave it alone if we just changed tiles, in case they zoomed in or out further if ((TileBeingEditedIndex != INDEX_NONE) && (OldTileIndex == INDEX_NONE)) { RequestFocusOnSelection(/*bInstant=*/ true); } // Trigger a details panel customization rebuild OnSingleTileIndexChanged.Broadcast(TileBeingEditedIndex, OldTileIndex); // Redraw the viewport Invalidate(); }
bool FSpriteEditorViewportClient::ConvertMarqueeToSourceTextureSpace(/*out*/ FIntPoint& OutStartPos, /*out*/ FIntPoint& OutDimension) { FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry); check(GeometryEditMode); const FVector2D MarqueeStartPos = GeometryEditMode->GetMarqueeStartPos(); const FVector2D MarqueeEndPos = GeometryEditMode->GetMarqueeEndPos(); bool bSuccessful = false; UPaperSprite* Sprite = SourceTextureViewComponent->GetSprite(); UTexture2D* SpriteSourceTexture = Sprite->GetSourceTexture(); if (SpriteSourceTexture != nullptr) { // Calculate world space positions FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(Viewport, GetScene(), EngineShowFlags)); FSceneView* View = CalcSceneView(&ViewFamily); const FVector StartPos = View->PixelToWorld(MarqueeStartPos.X, MarqueeStartPos.Y, 0); const FVector EndPos = View->PixelToWorld(MarqueeEndPos.X, MarqueeEndPos.Y, 0); // Convert to source texture space to work out the pixels dragged FVector2D TextureSpaceStartPos = Sprite->ConvertWorldSpaceToTextureSpace(StartPos); FVector2D TextureSpaceEndPos = Sprite->ConvertWorldSpaceToTextureSpace(EndPos); if (TextureSpaceStartPos.X > TextureSpaceEndPos.X) { Swap(TextureSpaceStartPos.X, TextureSpaceEndPos.X); } if (TextureSpaceStartPos.Y > TextureSpaceEndPos.Y) { Swap(TextureSpaceStartPos.Y, TextureSpaceEndPos.Y); } const FIntPoint SourceTextureSize(SpriteSourceTexture->GetImportedSize()); const int32 SourceTextureWidth = SourceTextureSize.X; const int32 SourceTextureHeight = SourceTextureSize.Y; FIntPoint TSStartPos; TSStartPos.X = FMath::Clamp<int32>((int32)TextureSpaceStartPos.X, 0, SourceTextureWidth - 1); TSStartPos.Y = FMath::Clamp<int32>((int32)TextureSpaceStartPos.Y, 0, SourceTextureHeight - 1); FIntPoint TSEndPos; TSEndPos.X = FMath::Clamp<int32>((int32)TextureSpaceEndPos.X, 0, SourceTextureWidth - 1); TSEndPos.Y = FMath::Clamp<int32>((int32)TextureSpaceEndPos.Y, 0, SourceTextureHeight - 1); const FIntPoint TextureSpaceDimensions = TSEndPos - TSStartPos; if ((TextureSpaceDimensions.X > 0) || (TextureSpaceDimensions.Y > 0)) { OutStartPos = TSStartPos; OutDimension = TextureSpaceDimensions; bSuccessful = true; } } return bSuccessful; }