diff --git a/catroid/src/androidTest/java/org/catrobat/catroid/test/embroidery/SewUpActionTest.kt b/catroid/src/androidTest/java/org/catrobat/catroid/test/embroidery/SewUpActionTest.kt new file mode 100644 index 00000000000..f3d968d8544 --- /dev/null +++ b/catroid/src/androidTest/java/org/catrobat/catroid/test/embroidery/SewUpActionTest.kt @@ -0,0 +1,125 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2026 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.test.embroidery + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.catrobat.catroid.content.Look +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.content.actions.SewUpAction +import org.catrobat.catroid.embroidery.DSTPatternManager +import org.catrobat.catroid.embroidery.EmbroideryPatternManager +import org.catrobat.catroid.stage.StageActivity +import org.catrobat.catroid.stage.StageListener +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock +import kotlin.math.cos +import kotlin.math.sin + +@RunWith(AndroidJUnit4::class) +class SewUpActionTest { + private lateinit var sprite: Sprite + private lateinit var spriteLook: Look + private lateinit var embroideryPatternManager: EmbroideryPatternManager + + @Before + fun setUp() { + sprite = Sprite("testSprite") + spriteLook = mock(Look::class.java) + sprite.look = spriteLook + embroideryPatternManager = DSTPatternManager() + StageActivity.stageListener = StageListener().apply { + embroideryPatternManager = this@SewUpActionTest.embroideryPatternManager + } + } + + @After + fun tearDown() { + StageActivity.stageListener = null + } + + @Test + fun testVerticalSewUp() { + sprite.actionFactory.createSewUpAction(sprite).act(1f) + + val stitches = StageActivity.stageListener?.embroideryPatternManager?.embroideryPatternList + ?: throw IllegalStateException("StageActivity.stageListener or embroideryPatternManager is null") + + val expectedStitchesX = mutableListOf() + val expectedStitchesY = mutableListOf() + val x = sprite.look?.xInUserInterfaceDimensionUnit ?: 0f + val y = sprite.look?.yInUserInterfaceDimensionUnit ?: 0f + + expectedStitchesX.add(x) + expectedStitchesY.add(y) + expectedStitchesX.add(x) + expectedStitchesY.add(y + SewUpAction.STEPS) + expectedStitchesX.add(x) + expectedStitchesY.add(y) + expectedStitchesX.add(x) + expectedStitchesY.add(y - SewUpAction.STEPS) + expectedStitchesX.add(x) + expectedStitchesY.add(y) + + for (i in expectedStitchesX.indices) { + assertEquals(expectedStitchesX[i], stitches[i].x, 0.01f) + assertEquals(expectedStitchesY[i], stitches[i].y, 0.01f) + } + } + + @Test + fun testAngledSewUp() { + val look = sprite.look ?: throw IllegalStateException("Sprite look is null") + look.setMotionDirectionInUserInterfaceDimensionUnit(137f) + sprite.actionFactory.createSewUpAction(sprite).act(1f) + + val stitches = StageActivity.stageListener?.embroideryPatternManager?.embroideryPatternList + ?: throw IllegalStateException("StageActivity.stageListener or embroideryPatternManager is null") + + val expectedStitchesX = mutableListOf() + val expectedStitchesY = mutableListOf() + val x = look.xInUserInterfaceDimensionUnit + val y = look.yInUserInterfaceDimensionUnit + val radians = Math.toRadians(look.motionDirectionInUserInterfaceDimensionUnit.toDouble()) + + expectedStitchesX.add(x) + expectedStitchesY.add(y) + expectedStitchesX.add(x + SewUpAction.STEPS * sin(radians).toFloat()) + expectedStitchesY.add(y + SewUpAction.STEPS * cos(radians).toFloat()) + expectedStitchesX.add(x) + expectedStitchesY.add(y) + expectedStitchesX.add(x - (SewUpAction.STEPS * sin(radians)).toFloat()) + expectedStitchesY.add(y - (SewUpAction.STEPS * cos(radians)).toFloat()) + expectedStitchesX.add(x) + expectedStitchesY.add(y) + + for (i in expectedStitchesX.indices) { + assertEquals(expectedStitchesX[i], stitches[i].x, 0.01f) + assertEquals(expectedStitchesY[i], stitches[i].y, 0.01f) + } + } +} diff --git a/catroid/src/androidTest/java/org/catrobat/catroid/test/embroidery/SewUpTest.java b/catroid/src/androidTest/java/org/catrobat/catroid/test/embroidery/SewUpTest.java deleted file mode 100644 index 333b3a914fb..00000000000 --- a/catroid/src/androidTest/java/org/catrobat/catroid/test/embroidery/SewUpTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2025 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package org.catrobat.catroid.test.embroidery; - -import org.catrobat.catroid.content.Look; -import org.catrobat.catroid.content.Sprite; -import org.catrobat.catroid.content.actions.SewUpAction; -import org.catrobat.catroid.embroidery.DSTPatternManager; -import org.catrobat.catroid.embroidery.EmbroideryPatternManager; -import org.catrobat.catroid.embroidery.StitchPoint; -import org.catrobat.catroid.stage.StageActivity; -import org.catrobat.catroid.stage.StageListener; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; - -import java.util.ArrayList; -import java.util.List; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import static org.junit.Assert.assertEquals; -@RunWith(AndroidJUnit4.class) -public class SewUpTest { - private Sprite sprite; - private Look spriteLook; - private EmbroideryPatternManager embroideryPatternManager; - - @Before - public void setUp() { - sprite = new Sprite("testSprite"); - spriteLook = Mockito.mock(Look.class); - sprite.look = spriteLook; - embroideryPatternManager = new DSTPatternManager(); - StageActivity.stageListener = new StageListener(); - StageActivity.stageListener.embroideryPatternManager = embroideryPatternManager; - } - - @After - public void tearDown() { - StageActivity.stageListener = null; - } - - @Test - public void testVerticalSewUp() { - sprite.getActionFactory().createSewUpAction(sprite).act(1f); - - List stitches = - StageActivity.stageListener.embroideryPatternManager.getEmbroideryPatternList(); - - ArrayList expectedStitchesX = new ArrayList<>(); - ArrayList expectedStitchesY = new ArrayList<>(); - float x = sprite.look.getXInUserInterfaceDimensionUnit(); - float y = sprite.look.getYInUserInterfaceDimensionUnit(); - - expectedStitchesX.add(x); - expectedStitchesY.add(y); - expectedStitchesX.add(x); - expectedStitchesY.add(y + SewUpAction.STEPS); - expectedStitchesX.add(x); - expectedStitchesY.add(y); - expectedStitchesX.add(x); - expectedStitchesY.add(y - SewUpAction.STEPS); - expectedStitchesX.add(x); - expectedStitchesY.add(y); - - for (int i = 0; i < expectedStitchesX.size(); i++) { - assertEquals(stitches.get(i).getX(), expectedStitchesX.get(i), 0.01); - assertEquals(stitches.get(i).getY(), expectedStitchesY.get(i), 0.01); - } - } - - @Test - public void testAngledSewUp() { - sprite.look.setMotionDirectionInUserInterfaceDimensionUnit(137); - sprite.getActionFactory().createSewUpAction(sprite).act(1f); - - List stitches = - StageActivity.stageListener.embroideryPatternManager.getEmbroideryPatternList(); - - ArrayList expectedStitchesX = new ArrayList<>(); - ArrayList expectedStitchesY = new ArrayList<>(); - float x = sprite.look.getXInUserInterfaceDimensionUnit(); - float y = sprite.look.getYInUserInterfaceDimensionUnit(); - double radians = Math.toRadians(sprite.look.getMotionDirectionInUserInterfaceDimensionUnit()); - - expectedStitchesX.add(x); - expectedStitchesY.add(y); - expectedStitchesX.add(x + SewUpAction.STEPS * (float) Math.sin(radians)); - expectedStitchesY.add(y + SewUpAction.STEPS * (float) Math.cos(radians)); - expectedStitchesX.add(x); - expectedStitchesY.add(y); - expectedStitchesX.add(x - SewUpAction.STEPS * (float) Math.sin(radians)); - expectedStitchesY.add(y - SewUpAction.STEPS * (float) Math.cos(radians)); - expectedStitchesX.add(x); - expectedStitchesY.add(y); - - for (int i = 0; i < expectedStitchesX.size(); i++) { - assertEquals(stitches.get(i).getX(), expectedStitchesX.get(i), 0.01); - assertEquals(stitches.get(i).getY(), expectedStitchesY.get(i), 0.01); - } - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/content/actions/SewUpAction.java b/catroid/src/main/java/org/catrobat/catroid/content/actions/SewUpAction.java deleted file mode 100644 index 6c51ee631bf..00000000000 --- a/catroid/src/main/java/org/catrobat/catroid/content/actions/SewUpAction.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Catroid: An on-device visual programming system for Android devices - * Copyright (C) 2010-2025 The Catrobat Team - * () - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * An additional term exception under section 7 of the GNU Affero - * General Public License, version 3, is available at - * http://developer.catrobat.org/license_additional_term - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.catrobat.catroid.content.actions; - -import com.badlogic.gdx.scenes.scene2d.actions.TemporalAction; - -import org.catrobat.catroid.content.Sprite; -import org.catrobat.catroid.embroidery.DSTStitchCommand; -import org.catrobat.catroid.stage.StageActivity; - -public class SewUpAction extends TemporalAction { - - private Sprite sprite; - public static final int STEPS = 3; - - protected void begin() { - double radians = Math.toRadians(sprite.look.getMotionDirectionInUserInterfaceDimensionUnit()); - - sprite.runningStitch.pause(); - - float x = sprite.look.getXInUserInterfaceDimensionUnit(); - float y = sprite.look.getYInUserInterfaceDimensionUnit(); - StageActivity.stageListener.embroideryPatternManager.addStitchCommand(new DSTStitchCommand(x, y, - sprite.look.getZIndex(), sprite, sprite.getEmbroideryThreadColor())); - - x += STEPS * Math.sin(radians); - y += STEPS * Math.cos(radians); - StageActivity.stageListener.embroideryPatternManager.addStitchCommand(new DSTStitchCommand(x, y, - sprite.look.getZIndex(), sprite, sprite.getEmbroideryThreadColor())); - - x -= STEPS * Math.sin(radians); - y -= STEPS * Math.cos(radians); - StageActivity.stageListener.embroideryPatternManager.addStitchCommand(new DSTStitchCommand(x, y, - sprite.look.getZIndex(), sprite, sprite.getEmbroideryThreadColor())); - - x -= STEPS * Math.sin(radians); - y -= STEPS * Math.cos(radians); - StageActivity.stageListener.embroideryPatternManager.addStitchCommand(new DSTStitchCommand(x, y, - sprite.look.getZIndex(), sprite, sprite.getEmbroideryThreadColor())); - - x += STEPS * Math.sin(radians); - y += STEPS * Math.cos(radians); - StageActivity.stageListener.embroideryPatternManager.addStitchCommand(new DSTStitchCommand(x, y, - sprite.look.getZIndex(), sprite, sprite.getEmbroideryThreadColor())); - - sprite.runningStitch.setStartCoordinates(sprite.look.getXInUserInterfaceDimensionUnit(), - sprite.look.getYInUserInterfaceDimensionUnit()); - sprite.runningStitch.resume(); - } - - public void setSprite(Sprite sprite) { - this.sprite = sprite; - } - - @Override - protected void update(float delta) { - } -} diff --git a/catroid/src/main/java/org/catrobat/catroid/content/actions/SewUpAction.kt b/catroid/src/main/java/org/catrobat/catroid/content/actions/SewUpAction.kt new file mode 100644 index 00000000000..b8250c433b0 --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/content/actions/SewUpAction.kt @@ -0,0 +1,91 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2026 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.content.actions + +import com.badlogic.gdx.scenes.scene2d.actions.TemporalAction +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.embroidery.DSTStitchCommand +import org.catrobat.catroid.stage.StageActivity +import kotlin.math.cos +import kotlin.math.sin + +class SewUpAction : TemporalAction() { + lateinit var sprite: Sprite + + override fun begin() { + val look = sprite.look ?: throw IllegalStateException("Sprite look is null") + val radians = Math.toRadians(look.motionDirectionInUserInterfaceDimensionUnit.toDouble()) + + sprite.runningStitch?.pause() + + val embroideryPatternManager = StageActivity.stageListener?.embroideryPatternManager + ?: throw IllegalStateException("StageActivity.stageListener or embroideryPatternManager is null") + + var x = look.xInUserInterfaceDimensionUnit + var y = look.yInUserInterfaceDimensionUnit + val zIndex = look.zIndex + val threadColor = sprite.embroideryThreadColor + + embroideryPatternManager.addStitchCommand( + DSTStitchCommand(x, y, zIndex, sprite, threadColor) + ) + + x += (STEPS * sin(radians)).toFloat() + y += (STEPS * cos(radians)).toFloat() + embroideryPatternManager.addStitchCommand( + DSTStitchCommand(x, y, zIndex, sprite, threadColor) + ) + + x -= (STEPS * sin(radians)).toFloat() + y -= (STEPS * cos(radians)).toFloat() + embroideryPatternManager.addStitchCommand( + DSTStitchCommand(x, y, zIndex, sprite, threadColor) + ) + + x -= (STEPS * sin(radians)).toFloat() + y -= (STEPS * cos(radians)).toFloat() + embroideryPatternManager.addStitchCommand( + DSTStitchCommand(x, y, zIndex, sprite, threadColor) + ) + + x += (STEPS * sin(radians)).toFloat() + y += (STEPS * cos(radians)).toFloat() + embroideryPatternManager.addStitchCommand( + DSTStitchCommand(x, y, zIndex, sprite, threadColor) + ) + + sprite.runningStitch?.apply { + setStartCoordinates(look.xInUserInterfaceDimensionUnit, look.yInUserInterfaceDimensionUnit) + resume() + } + } + + override fun update(delta: Float) { + // Intentionally empty + } + + companion object { + const val STEPS = 3 + } +}