Skip to content

CATROID-1647 Feat: Resize and rotate object when placing in stage#5189

Open
harshsomankar123-tech wants to merge 15 commits intoCatrobat:developfrom
harshsomankar123-tech:feature/IDE-217-resize-rotate-object-in-stage
Open

CATROID-1647 Feat: Resize and rotate object when placing in stage#5189
harshsomankar123-tech wants to merge 15 commits intoCatrobat:developfrom
harshsomankar123-tech:feature/IDE-217-resize-rotate-object-in-stage

Conversation

@harshsomankar123-tech
Copy link
Copy Markdown
Member

@harshsomankar123-tech harshsomankar123-tech commented Apr 7, 2026

Related Jira Ticket

(https://catrobat.atlassian.net/browse/CATROID-1647)

Summary

This PR introduces multi-touch support to the VisualPlacementActivity, allowing users to intuitively resize and rotate a sprite while positioning it on the stage.

To provide clear visual feedback, a new bounding box overlay with corner handles has been implemented. Additionally, the IDE now automatically handles data persistence by inserting SetSizeToBrick and PointInDirectionBrick into the sprite's script upon confirmation, streamlining the creation workflow.

Technical Changes

  • ResizeRotateGestureDetector.kt: New gesture detector for handling pinch-to-scale and two-finger rotation math.
  • BoundingBoxOverlay.kt: Custom View that draws a dynamic blue outline and curved-arrow handles around the active sprite.
  • VisualPlacementTouchListener.java: Updated to coordinate between single-finger dragging and multi-finger transformations.
  • TransformationInterface.kt: Extends the existing interface to include scale and rotation setters.
  • ProjectActivity.kt: Added logic to automatically append the relevant bricks to the script based on the visual placement results.

Screen Recording

Screenrecorder-2026-04-07-15-56-57-229.mp4

Your checklist for this pull request

Please review the contributing guidelines and wiki pages of this repository.

  • Include the name of the Jira ticket in the PR’s title
  • Include a summary of the changes plus the relevant context
  • Choose the proper base branch (develop)
  • Confirm that the changes follow the project’s coding guidelines
  • Verify that the changes generate no compiler or linter warnings
  • Perform a self-review of the changes
  • Verify to commit no other files than the intentionally changed ones
  • Include reasonable and readable tests verifying the added or changed behavior
  • Confirm that new and existing unit tests pass locally
  • Check that the commits’ message style matches the project’s guideline
  • Stick to the project’s gitflow workflow
  • Verify that your changes do not have any conflicts with the base branch
  • After the PR, verify that all CI checks have passed
  • Post a message in the catroid-stage or catroid-ide Slack channel and ask for a code reviewer

Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Fixed
Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Fixed
@harshsomankar123-tech harshsomankar123-tech marked this pull request as draft April 7, 2026 06:46
@harshsomankar123-tech harshsomankar123-tech marked this pull request as ready for review April 7, 2026 10:29
@harshsomankar123-tech harshsomankar123-tech added the Active Member Tickets that are assigned to members that are still currently active label Apr 8, 2026
@wslany wslany requested a review from Copilot April 10, 2026 13:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds multi-touch transformation support to the visual placement flow so users can resize and rotate a sprite while placing it on the stage, with a bounding-box overlay for visual feedback and persistence of the result back into the project.

Changes:

  • Introduces a new two-finger gesture detector for pinch-to-scale and rotation, and integrates it into visual placement touch handling.
  • Adds a bounding box overlay view (with corner-handle vector drawable) that updates during placement interactions.
  • Persists placement scale/rotation back to the calling activities and (for new sprites) appends corresponding bricks to the generated script.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
catroid/src/main/java/org/catrobat/catroid/visualplacement/ResizeRotateGestureDetector.kt New detector for scaling/rotation math and gesture state.
catroid/src/main/java/org/catrobat/catroid/visualplacement/BoundingBoxOverlay.kt New overlay view rendering a rotated bounding box + handles around the placed sprite.
catroid/src/main/res/drawable/ic_corner_handle.xml New corner-handle vector drawable used by the overlay.
catroid/src/main/java/org/catrobat/catroid/visualplacement/VisualPlacementTouchListener.java Adds multi-touch routing and overlay updates in the touch pipeline.
catroid/src/main/java/org/catrobat/catroid/visualplacement/VisualPlacementActivity.java Wires detector + overlay into placement UI and returns scale/rotation via result extras.
catroid/src/main/java/org/catrobat/catroid/visualplacement/TransformationInterface.kt Extends placement callback contract to include scale/rotation setters.
catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java Applies returned scale/rotation from visual placement to the current sprite look.
catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt For new sprites, creates a StartScript and appends PlaceAt/SetSize/PointInDirection bricks from placement results.
catroid/src/test/java/org/catrobat/catroid/test/visualplacement/ResizeRotateGestureDetectorTest.kt Unit tests for detector helper math and initial state.
catroid/src/test/java/org/catrobat/catroid/test/visualplacement/VisualPlacementResizeRotateTest.kt Tests for integration expectations (drag still works, overlay update, detector state).
catroid/src/test/java/org/catrobat/catroid/test/visualplacement/VisualPlacementTouchListenerTest.java Updates mocks for new pointer-count logic.
catroid/src/test/java/org/catrobat/catroid/test/visualplacement/VisualPlacementPositionCorrectionTest.java Updates mocks for new pointer-count/pointer-id checks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java Outdated
Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Outdated
Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Outdated
@wslany wslany changed the title IDE-217 Feat: Resize and rotate object when placing in stage CATROID-1647 Feat: Resize and rotate object when placing in stage Apr 11, 2026
Copy link
Copy Markdown
Member

@wslany wslany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feature. I found a couple of interaction edge cases around rotation handling and the transition back from multi-touch to single-touch, plus two smaller cleanup items. The generated APK builds and the focused visual-placement unit tests pass locally, but I think the P2 items should be fixed before merge.

Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Outdated
Comment thread catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java
…uch baseline reset, and direction comparison; update copyrights and merge nested ifs
Copy link
Copy Markdown
Member

@wslany wslany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick follow-up. I still see a couple of actionable issues in the latest head, mainly around the pointer-up reset path and missing regression coverage for the review fixes.

Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Outdated
- Resolved P2 issue in VisualPlacementTouchListener where pointer-up events caused stale touch baselines.
- Removed unused DEFAULT_ROTATION in ProjectActivity and fixed default rotation extra read.
- Added regression tests for angle normalization and multi-touch transition resets.
Copy link
Copy Markdown
Member

@wslany wslany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One remaining coverage request: we want full coverage for new behavior from now on. The focused unit coverage improved for the gesture/touch code, but the activity result/script-creation path still lacks direct regression coverage.

Comment thread catroid/src/main/java/org/catrobat/catroid/ui/ProjectActivity.kt Outdated
…ton (IDE-217)

- Fix SpriteActivity: default placementRotation to DEGREE_UI_OFFSET (90°) and only apply rotation when changed
- Fix VisualPlacementActivity: set correct defaults for rotationMode and initialLookRotation when loading from look list
- Fix default initialSpriteRotation to DEGREE_UI_OFFSET to prevent unwanted PointInDirectionBrick
- Add ScreenValueHandler.updateScreenWidthAndHeight() for correct layout sizing
- Use existing LayoutParams instead of creating new ones
- Add two-finger panning with frame-to-frame delta tracking
- Add velocity-based rotation snapping to 90° increments
- Add Reset toolbar button to restore initial transformations
private var lastRotationTime: Long = 0
private var lastRotationAngle: Float = 0f

fun onTouchEvent(event: MotionEvent): Boolean {
}

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360
}

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360
}

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360
val snapAngles = floatArrayOf(0f, 90f, 180f, 270f, 360f)

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360
val snapAngles = floatArrayOf(0f, 90f, 180f, 270f, 360f)

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360
val snapAngles = floatArrayOf(0f, 90f, 180f, 270f, 360f)

private fun getSnappedAngle(angle: Float): Float {
val normalizedRotation = (angle % 360 + 360) % 360
val snapAngles = floatArrayOf(0f, 90f, 180f, 270f, 360f)
- Add ic_rotate_90 drawable (circular arrow icon)
- Add rotate_90 menu item between reset and confirm
- Implement rotateBy90Degrees() in VisualPlacementActivity
- Add rotate_90 string resource
- Add testCumulativeRotationForRotate90Feature test
- Add testSetCumulativeRotationAndScaleForResetScenario test
- Update test listeners to implement onPan interface
@sonarqubecloud
Copy link
Copy Markdown

case R.id.confirm:
finishWithResult();
break;
case R.id.reset:
case R.id.reset:
resetTransformations();
break;
case R.id.rotate_90:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Active Member Tickets that are assigned to members that are still currently active

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants