From 4ebdb975307a6c0bd5bfdf4dbe443995a9be40e7 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 29 Jul 2020 13:10:26 +0200 Subject: [PATCH 001/189] CATROID-608 Stacking Vibration Bricks The problem was the already queued up vibration time was not considered when vibrating again. --- .../Vibration/testVibrationBrick.catrobat | Bin 0 -> 34956 bytes .../catroid/content/actions/VibrateAction.java | 9 +++++++-- .../catrobat/catroid/utils/VibrationUtil.java | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 catroid/src/androidTest/assets/catrobatTests/bricks/motion/Vibration/testVibrationBrick.catrobat diff --git a/catroid/src/androidTest/assets/catrobatTests/bricks/motion/Vibration/testVibrationBrick.catrobat b/catroid/src/androidTest/assets/catrobatTests/bricks/motion/Vibration/testVibrationBrick.catrobat new file mode 100644 index 0000000000000000000000000000000000000000..40dd31033508931b3780a905f55d6bbd21f5e507 GIT binary patch literal 34956 zcmeGlO>7%gdIBl+R%*A1NM%b8Bky6k#N#+WIAUV39haD-Ng9vSm0)qlGtbVn;~6tE zt{N6;D-NsO%kE{lAjFB)-YT>b5*I{~kU$6_Zp&q*9CpPbl`EW<^1b)w*)z$wO;Xwf z`c0ehyl=kmy*J-{@B4Yq_hohQ;n6WEl}bs?j&fd#9H-#AW)O$S6N=T*+r(Egj@u!o zrH@F`ty`;$M^hC2NJz7~tDbzf=a~EMNrth+ob+DccJ#n98ouEX;`keGkm)+@kyF$E z`}EJN%g-G@cKR6LAFnRVuSwEqUXoHzrXB&vldaK<@G;`AJy(*he}3j`XpH)$ss?OG zy_z!rBuTPVoiA!v-@N%{@wg7`$t zf%CI(eF$8U{(}wV0m=cc1=I(q6VWc9IYgHL-6C`i(LKfx0V5-fj4(37$Ot1NjEpcc z!pI0CBaDnNGTKXI^x~D9*G6d|@x`rweUl3Q2$#QqjeZC5DnCgH*Wso1T-$Lbm5F7$T1WcTra3Dwx~8lZ3#?3V*yM^u$AWL*WQ(+v3Ke3 z0-)VQyNPxa?IzmIEl`$dH!;XUw*f=!B(DiQCG?cgQ$kM(Jtg#%&{4cEyYZJkKCwW( z^3nhQ;opCGw*4M%{wMC|pl5=f$phkt)S3CB|>!&aMSA7Pq0^A;ufa?4tQ=;50-SN-GeMYaTf^Lp(?{LIK8O{M6)`i z-nCub1O{#cgjfWU^sFvrHbsfF#QiIlLD-`d9n*6yQ?AV~%1wANf!uOE`D%WK()F=8 zndO&tKUnqLOT-8YE#3BkH*p|Gv_Ud_L+_Gvz&?Q(2XaJ~-?#*GaeOKbu_njp+Ij#p z>J-9>s!AUcM-ZIM%??lmEX3rpIT$V!Rso1%G3Ers57w=w$HmsOjLXnB?hg|*m7aLa8{VOp~MKw$TQasW$rE?w(-RzT7+ zC7Vl^bmMZ{qiL<_0RfQMu6vpG!sbFX4n0(s|C#`1t0O)r$7eUhz=7@sH3o@|#W0&x z8g}+DxFGc;@3>LDBB8x+%%c5uN$&;X10z(F! zLfWpkIhS59u2qYrrAp#77!755;cR`mtW{T*K}={fVRVLjMYnr^TwJPERE0MZQB@_J zYf?}Bo5LPNr6MSp7_zk<0f8wZz+u~Zg{{-Mw9)e+S$W7K#(GPd4|_6`wDg`Gkx2@T z9xB(4>y!hFWV0|eJ=@IBG;`y+Ihh-u%1@c&&8eA*@tN7?v}tCI=CqL$Dz#6P$SgVv zUok}Y?9H<4fXT4q%O*M#h7Zd6HWTKnSg@LD*+<*31k|5xqhxxS=*I*&t^bz-6Q3WYDMLo)z<3w z&xCrUMLdY-z@5ru6!_0{IP>&`jY!A*D6ZUg_p)$Zgr=ac>i1y>cE{@4&)>H^1nc63 z-0$|gG{V=IWb4(KdmqNqF<8twWPuz+^l@2Id6+M}uOA~`iHEz1R%DM;50%HhqLpfC zt*BKR^L6-uaO57@x5)#xZ$%#hn4t1<4|Y@zgG*7Y)hcURqjJ6ukzJ$m+to^0tIQ|L z0)4sMqu5i(cz4Shh76@C64}NlT`X%b`8!Ox4v*Oo5%I2kp?E}gpia?)Cp34t&v0;3 z6ANt)RA|mxj^%IEVDIn8-HjUJuiRVvCv4(&^Qt;6L(|(79P?shJ3sz5OB&l_+TkE` zJIi|Hm)vD$fIBhB))YMdoDIGoh09)4INXNf#*rfa)`<7%{Er43g49# zED~*s#$lB8u(?ee;UybaeElP$h z-=>{7`Do^i(~|T${0#p#?Q!@j4C@u{CD#!chAGm>15A;|6lqi&pbW8U3i5#dN-@d- z@&M%kT|;yY(KSTZ5X~XF1Xx!TcS>-#=tDGzXb#aFqB%T7<`C-@f;eLBMPLG!o&+Xf z_9H3nGY8<>DKzJUn|HNMeS zqOC+*iMA4L7q#54-!f+j@l~4~ Date: Wed, 9 Sep 2020 14:59:48 +0200 Subject: [PATCH 002/189] CATROID-626 Add a set of face detection sensors for a second face FaceDetector can now easier be extended with additional sensors if necessary --- catroid/config/detekt.yml | 2 +- .../test/formulaeditor/SensorHandlerTest.kt | 38 ++++++++-- .../catrobat/catroid/camera/FaceDetector.kt | 74 ++++++++++++++----- .../InternFormulaKeyboardAdapter.java | 8 ++ .../InternToExternGenerator.java | 14 +++- .../catroid/formulaeditor/SensorHandler.java | 72 +++++++++++++----- .../catroid/formulaeditor/Sensors.java | 4 +- .../common/FormulaElementResources.kt | 6 +- .../fragment/CategoryListFragment.java | 4 + catroid/src/main/res/values/strings.xml | 12 ++- 10 files changed, 182 insertions(+), 52 deletions(-) diff --git a/catroid/config/detekt.yml b/catroid/config/detekt.yml index f2a5304b169..b06a9c457a2 100644 --- a/catroid/config/detekt.yml +++ b/catroid/config/detekt.yml @@ -67,7 +67,7 @@ complexity: threshold: 600 LongMethod: active: true - threshold: 60 + threshold: 80 LongParameterList: active: true threshold: 6 diff --git a/catroid/src/androidTest/java/org/catrobat/catroid/test/formulaeditor/SensorHandlerTest.kt b/catroid/src/androidTest/java/org/catrobat/catroid/test/formulaeditor/SensorHandlerTest.kt index d7335c6bacc..196563259e9 100644 --- a/catroid/src/androidTest/java/org/catrobat/catroid/test/formulaeditor/SensorHandlerTest.kt +++ b/catroid/src/androidTest/java/org/catrobat/catroid/test/formulaeditor/SensorHandlerTest.kt @@ -27,6 +27,7 @@ import android.graphics.Point import androidx.test.annotation.UiThreadTest import androidx.test.core.app.ApplicationProvider import androidx.test.rule.GrantPermissionRule +import com.google.mlkit.vision.face.Face import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.camera.FaceDetector import org.catrobat.catroid.content.Project @@ -71,20 +72,41 @@ class SensorHandlerTest { } @Test - fun testFaceDetection() { + fun testFirstFaceDetection() { SensorHandler.startSensorListener(ApplicationProvider.getApplicationContext()) compareToSensor(0, Sensors.FACE_DETECTED) compareToSensor(0, Sensors.FACE_SIZE) - val size = 50 - val position = Point(15, -15) - FaceDetector.updateDetectionStatus(true) - FaceDetector.onFaceDetected(position, size) + val firstFaceSize = 50 + val firstFacePosition = Point(15, -15) + FaceDetector.facesForSensors[0] = Mockito.mock(Face::class.java) + + FaceDetector.updateDetectionStatus() + FaceDetector.onFaceDetected(firstFacePosition, firstFaceSize, 0) compareToSensor(1, Sensors.FACE_DETECTED) - compareToSensor(size, Sensors.FACE_SIZE) - compareToSensor(position.x, Sensors.FACE_X_POSITION) - compareToSensor(position.y, Sensors.FACE_Y_POSITION) + compareToSensor(firstFaceSize, Sensors.FACE_SIZE) + compareToSensor(firstFacePosition.x, Sensors.FACE_X_POSITION) + compareToSensor(firstFacePosition.y, Sensors.FACE_Y_POSITION) + } + + @Test + fun testSecondFaceDetection() { + SensorHandler.startSensorListener(ApplicationProvider.getApplicationContext()) + compareToSensor(0, Sensors.SECOND_FACE_DETECTED) + compareToSensor(0, Sensors.SECOND_FACE_SIZE) + + val secondFaceSize = 50 + val secondFacePosition = Point(15, -15) + FaceDetector.facesForSensors[1] = Mockito.mock(Face::class.java) + + FaceDetector.updateDetectionStatus() + FaceDetector.onFaceDetected(secondFacePosition, secondFaceSize, 1) + + compareToSensor(1, Sensors.SECOND_FACE_DETECTED) + compareToSensor(secondFaceSize, Sensors.SECOND_FACE_SIZE) + compareToSensor(secondFacePosition.x, Sensors.SECOND_FACE_X_POSITION) + compareToSensor(secondFacePosition.y, Sensors.SECOND_FACE_Y_POSITION) } @Test diff --git a/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt b/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt index fe2e7e1a429..686dd400c10 100644 --- a/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt +++ b/catroid/src/main/java/org/catrobat/catroid/camera/FaceDetector.kt @@ -47,7 +47,11 @@ import kotlin.math.roundToInt object FaceDetector : ImageAnalysis.Analyzer { private const val MAX_FACE_SIZE = 100 + private const val FACE_SENSORS = 2 private val sensorListeners = mutableSetOf() + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + var facesForSensors: Array = Array(FACE_SENSORS) { _ -> null } + private var faceIds: IntArray = IntArray(FACE_SENSORS) { _ -> -1 } private val detectionClient by lazy { FaceDetection.getClient( FaceDetectorOptions.Builder() @@ -81,7 +85,7 @@ object FaceDetector : ImageAnalysis.Analyzer { imageProxy.close() } .addOnFailureListener { e -> - updateDetectionStatus(false) + updateDetectionStatus() val context = CatroidApplication.getAppContext() StageActivity.messageHandler.obtainMessage( StageActivity.SHOW_TOAST, @@ -93,15 +97,39 @@ object FaceDetector : ImageAnalysis.Analyzer { } private fun updateSensorValues(faces: List, imageWidth: Int, imageHeight: Int) { - val detected = faces.isNotEmpty() + handleAlreadyExistingFaces(faces) + facesForSensors.forEachIndexed { index, face -> + if (face == null) { + attachNewFaceIfExisting(faces, index) + } + } + updateDetectionStatus() + facesForSensors.forEachIndexed { index, face -> + face?.let { translateFaceToSensorValues(face, index, imageWidth, imageHeight) } + } + facesForSensors.fill(null) + } - updateDetectionStatus(detected) - if (detected) { - translateFaceToSensorValues(faces[0], imageWidth, imageHeight) + private fun handleAlreadyExistingFaces(faces: List) { + for (face in faces) { + when (face.trackingId) { + faceIds[0] -> facesForSensors[0] = face + faceIds[1] -> facesForSensors[1] = face + } } } - private fun translateFaceToSensorValues(face: Face, imageWidth: Int, imageHeight: Int) { + private fun attachNewFaceIfExisting(faces: List, index: Int) { + for (face in faces) { + if (face.trackingId?.let { faceIds.contains(it) } == false) { + faceIds[index] = face.trackingId ?: -1 + facesForSensors[index] = face + break + } + } + } + + private fun translateFaceToSensorValues(face: Face, faceNumber: Int, imageWidth: Int, imageHeight: Int) { val frontCamera = StageActivity.getActiveCameraManager().isCameraFacingFront val oldAPI = Build.VERSION.SDK_INT < Build.VERSION_CODES.M val aspectRatio = imageWidth.toFloat() / imageHeight @@ -128,7 +156,7 @@ object FaceDetector : ImageAnalysis.Analyzer { val relativeFaceSize = (faceBounds.height().toFloat() / imageHeight).coerceAtMost(1f) val faceSize = (MAX_FACE_SIZE * relativeFaceSize).roundToInt() - onFaceDetected(facePosition, faceSize) + onFaceDetected(facePosition, faceSize, faceNumber) } private fun coordinatesFromRelativePosition( @@ -142,23 +170,35 @@ object FaceDetector : ImageAnalysis.Analyzer { ) @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun updateDetectionStatus(faceDetected: Boolean) { - val sensorValue = if (faceDetected) 1f else 0f + fun updateDetectionStatus() { + val firstSensorValue = if (facesForSensors[0] != null) 1f else 0f + val secondSensorValue = if (facesForSensors[1] != null) 1f else 0f sensorListeners.forEach { it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_DETECTED, floatArrayOf(sensorValue))) + SensorCustomEvent(Sensors.FACE_DETECTED, floatArrayOf(firstSensorValue))) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.SECOND_FACE_DETECTED, floatArrayOf(secondSensorValue))) } } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun onFaceDetected(position: Point, size: Int) { + fun onFaceDetected(position: Point, size: Int, faceNumber: Int) { sensorListeners.forEach { - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_X_POSITION, floatArrayOf(position.x.toFloat()))) - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_Y_POSITION, floatArrayOf(position.y.toFloat()))) - it.onCustomSensorChanged( - SensorCustomEvent(Sensors.FACE_SIZE, floatArrayOf(size.toFloat()))) + if (faceNumber == 0) { + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_X_POSITION, floatArrayOf(position.x.toFloat()))) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_Y_POSITION, floatArrayOf(position.y.toFloat()))) + it.onCustomSensorChanged( + SensorCustomEvent(Sensors.FACE_SIZE, floatArrayOf(size.toFloat()))) + } else if (faceNumber == 1) { + it.onCustomSensorChanged(SensorCustomEvent( + Sensors.SECOND_FACE_X_POSITION, floatArrayOf(position.x.toFloat()))) + it.onCustomSensorChanged(SensorCustomEvent( + Sensors.SECOND_FACE_Y_POSITION, floatArrayOf(position.y.toFloat()))) + it.onCustomSensorChanged(SensorCustomEvent( + Sensors.SECOND_FACE_SIZE, floatArrayOf(size.toFloat()))) + } } } } diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java index ab5e1dc6e2a..394d0822f4d 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java @@ -232,6 +232,14 @@ public List createInternTokenListByResourceId(int resource, String return buildSensor(Sensors.FACE_X_POSITION); case R.string.formula_editor_sensor_face_y_position: return buildSensor(Sensors.FACE_Y_POSITION); + case R.string.formula_editor_sensor_second_face_detected: + return buildSensor(Sensors.SECOND_FACE_DETECTED); + case R.string.formula_editor_sensor_second_face_size: + return buildSensor(Sensors.SECOND_FACE_SIZE); + case R.string.formula_editor_sensor_second_face_x_position: + return buildSensor(Sensors.SECOND_FACE_X_POSITION); + case R.string.formula_editor_sensor_second_face_y_position: + return buildSensor(Sensors.SECOND_FACE_Y_POSITION); case R.string.formula_editor_phiro_sensor_front_left: return buildSensor(Sensors.PHIRO_FRONT_LEFT); case R.string.formula_editor_phiro_sensor_front_right: diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java index c7fecece970..304dda75bfa 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java @@ -121,8 +121,18 @@ public class InternToExternGenerator { INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.FACE_DETECTED.name(), R.string.formula_editor_sensor_face_detected); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.FACE_SIZE.name(), R.string.formula_editor_sensor_face_size); - INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.FACE_X_POSITION.name(), R.string.formula_editor_sensor_face_x_position); - INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.FACE_Y_POSITION.name(), R.string.formula_editor_sensor_face_y_position); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.FACE_X_POSITION.name(), + R.string.formula_editor_sensor_face_x_position); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.FACE_Y_POSITION.name(), + R.string.formula_editor_sensor_face_y_position); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.SECOND_FACE_DETECTED.name(), + R.string.formula_editor_sensor_second_face_detected); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.SECOND_FACE_SIZE.name(), + R.string.formula_editor_sensor_second_face_size); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.SECOND_FACE_X_POSITION.name(), + R.string.formula_editor_sensor_second_face_x_position); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.SECOND_FACE_Y_POSITION.name(), + R.string.formula_editor_sensor_second_face_y_position); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.TEXT_FROM_CAMERA.name(), R.string.formula_editor_sensor_text_from_camera); diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java index 8e7833d3dcf..6d91d20de66 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java @@ -82,10 +82,14 @@ public final class SensorHandler implements SensorEventListener, SensorCustomEve private float linearAccelerationY = 0f; private float linearAccelerationZ = 0f; private float loudness = 0f; - private float faceDetected = 0f; - private float faceSize = 0f; - private float facePositionX = 0f; - private float facePositionY = 0f; + private float firstFaceDetected = 0f; + private float firstFaceSize = 0f; + private float firstFacePositionX = 0f; + private float firstFacePositionY = 0f; + private float secondFaceDetected = 0f; + private float secondFaceSize = 0f; + private float secondFacePositionX = 0f; + private float secondFacePositionY = 0f; private float textBlocksNumber = 0f; private String textFromCamera = "0"; @@ -445,20 +449,36 @@ public static Object getSensorValue(Sensors sensor) { } } case FACE_DETECTED: - return (double) instance.faceDetected; + return (double) instance.firstFaceDetected; case FACE_SIZE: - return (double) instance.faceSize; + return (double) instance.firstFaceSize; case FACE_X_POSITION: if ((rotate = rotateOrientation()) != 0) { - return (double) ((-instance.facePositionY) * rotate); + return (double) ((-instance.firstFacePositionY) * rotate); } else { - return (double) instance.facePositionX; + return (double) instance.firstFacePositionX; } case FACE_Y_POSITION: if ((rotate = rotateOrientation()) != 0) { - return (double) instance.facePositionX * rotate; + return (double) instance.firstFacePositionX * rotate; } else { - return (double) instance.facePositionY; + return (double) instance.firstFacePositionY; + } + case SECOND_FACE_DETECTED: + return (double) instance.secondFaceDetected; + case SECOND_FACE_SIZE: + return (double) instance.secondFaceSize; + case SECOND_FACE_X_POSITION: + if ((rotate = rotateOrientation()) != 0) { + return (double) ((-instance.secondFaceDetected) * rotate); + } else { + return (double) instance.secondFacePositionX; + } + case SECOND_FACE_Y_POSITION: + if ((rotate = rotateOrientation()) != 0) { + return (double) instance.secondFacePositionX * rotate; + } else { + return (double) instance.secondFacePositionY; } case TEXT_FROM_CAMERA: return instance.textFromCamera; @@ -606,10 +626,14 @@ public static void setListeningLanguageSensor(String listeningLanguageTag) { public static void clearFaceDetectionValues() { if (instance != null) { - instance.faceDetected = 0f; - instance.faceSize = 0f; - instance.facePositionX = 0f; - instance.facePositionY = 0f; + instance.firstFaceDetected = 0f; + instance.firstFaceSize = 0f; + instance.firstFacePositionX = 0f; + instance.firstFacePositionY = 0f; + instance.secondFaceDetected = 0f; + instance.secondFaceSize = 0f; + instance.secondFacePositionX = 0f; + instance.secondFacePositionY = 0f; instance.textFromCamera = "0"; instance.textBlocksNumber = 0f; } @@ -691,16 +715,28 @@ public void onCustomSensorChanged(SensorCustomEvent event) { instance.loudness = event.values[0]; break; case FACE_DETECTED: - instance.faceDetected = event.values[0]; + instance.firstFaceDetected = event.values[0]; break; case FACE_SIZE: - instance.faceSize = event.values[0]; + instance.firstFaceSize = event.values[0]; break; case FACE_X_POSITION: - instance.facePositionX = event.values[0]; + instance.firstFacePositionX = event.values[0]; break; case FACE_Y_POSITION: - instance.facePositionY = event.values[0]; + instance.firstFacePositionY = event.values[0]; + break; + case SECOND_FACE_DETECTED: + instance.secondFaceDetected = event.values[0]; + break; + case SECOND_FACE_SIZE: + instance.secondFaceSize = event.values[0]; + break; + case SECOND_FACE_X_POSITION: + instance.secondFacePositionX = event.values[0]; + break; + case SECOND_FACE_Y_POSITION: + instance.secondFacePositionY = event.values[0]; break; case TEXT_BLOCKS_NUMBER: instance.textBlocksNumber = event.values[0]; diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java index 61fadd857c6..25a07604f25 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java @@ -28,7 +28,9 @@ public enum Sensors { X_ACCELERATION, Y_ACCELERATION, Z_ACCELERATION, COMPASS_DIRECTION, X_INCLINATION, Y_INCLINATION, LOUDNESS, LATITUDE, LONGITUDE, LOCATION_ACCURACY, ALTITUDE, USER_LANGUAGE, DATE_YEAR, DATE_MONTH, DATE_DAY, DATE_WEEKDAY, TIME_HOUR, TIME_MINUTE, TIME_SECOND, - FACE_DETECTED, FACE_SIZE, FACE_X_POSITION, FACE_Y_POSITION, OBJECT_X(true), OBJECT_Y(true), + FACE_DETECTED, FACE_SIZE, FACE_X_POSITION, FACE_Y_POSITION, + SECOND_FACE_DETECTED, SECOND_FACE_SIZE, SECOND_FACE_X_POSITION, SECOND_FACE_Y_POSITION, + OBJECT_X(true), OBJECT_Y(true), OBJECT_TRANSPARENCY(true), OBJECT_BRIGHTNESS(true), OBJECT_COLOR(true), OBJECT_SIZE(true), OBJECT_ROTATION(true), OBJECT_LAYER(true), OBJECT_DISTANCE_TO(true), NXT_SENSOR_1, NXT_SENSOR_2, NXT_SENSOR_3, NXT_SENSOR_4, diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/common/FormulaElementResources.kt b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/common/FormulaElementResources.kt index 88397e9c0c7..8b3551b34f2 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/common/FormulaElementResources.kt +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/common/FormulaElementResources.kt @@ -47,7 +47,11 @@ object FormulaElementResources { Sensors.FACE_DETECTED, Sensors.FACE_SIZE, Sensors.FACE_X_POSITION, - Sensors.FACE_Y_POSITION -> Brick.FACE_DETECTION + Sensors.FACE_Y_POSITION, + Sensors.SECOND_FACE_DETECTED, + Sensors.SECOND_FACE_SIZE, + Sensors.SECOND_FACE_X_POSITION, + Sensors.SECOND_FACE_Y_POSITION -> Brick.FACE_DETECTION Sensors.NXT_SENSOR_1, Sensors.NXT_SENSOR_2, diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java index e4f0f5b26e4..b578e3b46a9 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java @@ -165,6 +165,10 @@ public class CategoryListFragment extends Fragment implements CategoryListRVAdap private static final List SENSORS_VISUAL_DETECTION = asList(R.string.formula_editor_sensor_face_detected, R.string.formula_editor_sensor_face_size, R.string.formula_editor_sensor_face_x_position, R.string.formula_editor_sensor_face_y_position, + R.string.formula_editor_sensor_second_face_detected, + R.string.formula_editor_sensor_second_face_size, + R.string.formula_editor_sensor_second_face_x_position, + R.string.formula_editor_sensor_second_face_y_position, R.string.formula_editor_sensor_text_from_camera, R.string.formula_editor_sensor_text_blocks_number, R.string.formula_editor_function_text_block_x, diff --git a/catroid/src/main/res/values/strings.xml b/catroid/src/main/res/values/strings.xml index 30b14168584..e5f78e8e5c1 100644 --- a/catroid/src/main/res/values/strings.xml +++ b/catroid/src/main/res/values/strings.xml @@ -1969,10 +1969,14 @@ needs read and write access to it. You can always change permissions through you expression current items Make it a list - face is visible - face size - face x position - face y position + first face is visible + first face size + first face x position + first face y position + second face is visible + second face size + second face x position + second face y position text from camera number of text blocks text block x from camera From afa64c377c8f6ab5570124ad519c0a898d396fb4 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 21 Jul 2020 16:56:25 +0200 Subject: [PATCH 003/189] CATROID-625 Timer / Reset timer brick --- .../device/ResetTimer/testResetTimer.catrobat | Bin 0 -> 59822 bytes .../catroid/test/BricksHelpUrlTest.java | 2 + .../content/bricks/BrickCategoryTest.java | 7 ++- .../catroid/content/ActionFactory.java | 5 ++ .../content/actions/ResetTimerAction.java | 37 ++++++++++++ .../content/bricks/ResetTimerBrick.java | 43 ++++++++++++++ .../InternFormulaKeyboardAdapter.java | 2 + .../InternToExternGenerator.java | 1 + .../catroid/formulaeditor/SensorHandler.java | 4 ++ .../catroid/formulaeditor/Sensors.java | 2 +- ...wardCompatibleCatrobatLanguageXStream.java | 4 ++ .../catroid/io/XstreamSerializer.java | 2 + .../stage/StageLifeCycleController.java | 4 ++ .../catrobat/catroid/stage/StageListener.java | 2 + .../catroid/ui/dialogs/StageDialog.java | 7 ++- .../ui/fragment/CategoryBricksFactory.java | 2 + .../fragment/CategoryListFragment.java | 9 +-- .../src/main/res/layout/brick_reset_timer.xml | 54 ++++++++++++++++++ catroid/src/main/res/values/strings.xml | 4 ++ catroid/src/main/res/values/styles.xml | 7 ++- 20 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 catroid/src/androidTest/assets/catrobatTests/bricks/device/ResetTimer/testResetTimer.catrobat create mode 100644 catroid/src/main/java/org/catrobat/catroid/content/actions/ResetTimerAction.java create mode 100644 catroid/src/main/java/org/catrobat/catroid/content/bricks/ResetTimerBrick.java create mode 100644 catroid/src/main/res/layout/brick_reset_timer.xml diff --git a/catroid/src/androidTest/assets/catrobatTests/bricks/device/ResetTimer/testResetTimer.catrobat b/catroid/src/androidTest/assets/catrobatTests/bricks/device/ResetTimer/testResetTimer.catrobat new file mode 100644 index 0000000000000000000000000000000000000000..3943afda1d96276b3cc40a739e344c24ec4158e3 GIT binary patch literal 59822 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 data() { AskBrick.class, AskSpeechBrick.class, StartListeningBrick.class)}, - {"Device", Arrays.asList(WhenBrick.class, + {"Device", Arrays.asList(ResetTimerBrick.class, + WhenBrick.class, WhenTouchDownBrick.class, WebRequestBrick.class, LookRequestBrick.class, @@ -386,8 +388,7 @@ public static Collection data() { WriteListOnDeviceBrick.class, ReadListFromDeviceBrick.class, TapAtBrick.class, - TapForBrick.class) - }, + TapForBrick.class)}, {"Lego NXT", Arrays.asList(LegoNxtMotorTurnAngleBrick.class, LegoNxtMotorStopBrick.class, LegoNxtMotorMoveBrick.class, diff --git a/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java b/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java index 9200091d024..5e5d2480be1 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/ActionFactory.java @@ -129,6 +129,7 @@ import org.catrobat.catroid.content.actions.RepeatParameterizedAction; import org.catrobat.catroid.content.actions.RepeatUntilAction; import org.catrobat.catroid.content.actions.ReplaceItemInUserListAction; +import org.catrobat.catroid.content.actions.ResetTimerAction; import org.catrobat.catroid.content.actions.RunningStitchAction; import org.catrobat.catroid.content.actions.SceneStartAction; import org.catrobat.catroid.content.actions.SceneTransitionAction; @@ -819,6 +820,10 @@ public Action createReplaceItemInUserListAction(Sprite sprite, Formula userListF return action; } + public Action createResetTimerAction() { + return Actions.action(ResetTimerAction.class); + } + public Action createThinkSayBubbleAction(Sprite sprite, Formula text, int type) { ThinkSayBubbleAction action = action(ThinkSayBubbleAction.class); action.setText(text); diff --git a/catroid/src/main/java/org/catrobat/catroid/content/actions/ResetTimerAction.java b/catroid/src/main/java/org/catrobat/catroid/content/actions/ResetTimerAction.java new file mode 100644 index 00000000000..d46380782e3 --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/content/actions/ResetTimerAction.java @@ -0,0 +1,37 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2018 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 android.os.SystemClock; + +import com.badlogic.gdx.scenes.scene2d.actions.TemporalAction; + +import org.catrobat.catroid.formulaeditor.SensorHandler; + +public class ResetTimerAction extends TemporalAction { + + @Override + protected void update(float percent) { + SensorHandler.timerReferenceValue = SystemClock.uptimeMillis(); + } +} diff --git a/catroid/src/main/java/org/catrobat/catroid/content/bricks/ResetTimerBrick.java b/catroid/src/main/java/org/catrobat/catroid/content/bricks/ResetTimerBrick.java new file mode 100644 index 00000000000..cbfdeff685c --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/content/bricks/ResetTimerBrick.java @@ -0,0 +1,43 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2018 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.bricks; + +import org.catrobat.catroid.R; +import org.catrobat.catroid.content.Sprite; +import org.catrobat.catroid.content.actions.ScriptSequenceAction; + +public class ResetTimerBrick extends BrickBaseType { + + public ResetTimerBrick() { + } + + @Override + public int getViewResource() { + return R.layout.brick_reset_timer; + } + + @Override + public void addActionToSequence(Sprite sprite, ScriptSequenceAction sequence) { + sequence.addAction(sprite.getActionFactory().createResetTimerAction()); + } +} diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java index ab5e1dc6e2a..429ee33a929 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java @@ -244,6 +244,8 @@ public List createInternTokenListByResourceId(int resource, String return buildSensor(Sensors.PHIRO_BOTTOM_LEFT); case R.string.formula_editor_phiro_sensor_bottom_right: return buildSensor(Sensors.PHIRO_BOTTOM_RIGHT); + case R.string.formula_editor_sensor_timer: + return buildSensor(Sensors.TIMER); case R.string.formula_editor_sensor_date_year: return buildSensor(Sensors.DATE_YEAR); case R.string.formula_editor_sensor_date_month: diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java index c7fecece970..bf2ccd8562a 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java @@ -166,6 +166,7 @@ public class InternToExternGenerator { INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.NFC_TAG_ID.name(), R.string.formula_editor_nfc_tag_id); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.NFC_TAG_MESSAGE.name(), R.string.formula_editor_nfc_tag_message); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.LOUDNESS.name(), R.string.formula_editor_sensor_loudness); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.TIMER.name(), R.string.formula_editor_sensor_timer); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.DATE_YEAR.name(), R.string.formula_editor_sensor_date_year); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.DATE_MONTH.name(), R.string.formula_editor_sensor_date_month); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.DATE_DAY.name(), R.string.formula_editor_sensor_date_day); diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java index 8e7833d3dcf..4fc5d4d9623 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/SensorHandler.java @@ -102,6 +102,8 @@ public final class SensorHandler implements SensorEventListener, SensorCustomEve private float locationAccuracy = 0f; private double altitude = 0d; private static String userLocaleTag = Locale.getDefault().toLanguageTag(); + public static double timerReferenceValue = 0d; + public static double timerPauseValue = 0d; private static String listeningLanguageSensor; @@ -466,6 +468,8 @@ public static Object getSensorValue(Sensors sensor) { return (double) instance.textBlocksNumber; case LOUDNESS: return (double) instance.loudness; + case TIMER: + return (SystemClock.uptimeMillis() - timerReferenceValue) / 1000d; case DATE_YEAR: return Double.valueOf(Calendar.getInstance().get(Calendar.YEAR)); case DATE_MONTH: diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java index 61fadd857c6..8bc8e3fa20c 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java @@ -27,7 +27,7 @@ public enum Sensors { X_ACCELERATION, Y_ACCELERATION, Z_ACCELERATION, COMPASS_DIRECTION, X_INCLINATION, Y_INCLINATION, LOUDNESS, LATITUDE, LONGITUDE, LOCATION_ACCURACY, ALTITUDE, USER_LANGUAGE, - DATE_YEAR, DATE_MONTH, DATE_DAY, DATE_WEEKDAY, TIME_HOUR, TIME_MINUTE, TIME_SECOND, + TIMER, DATE_YEAR, DATE_MONTH, DATE_DAY, DATE_WEEKDAY, TIME_HOUR, TIME_MINUTE, TIME_SECOND, FACE_DETECTED, FACE_SIZE, FACE_X_POSITION, FACE_Y_POSITION, OBJECT_X(true), OBJECT_Y(true), OBJECT_TRANSPARENCY(true), OBJECT_BRIGHTNESS(true), OBJECT_COLOR(true), OBJECT_SIZE(true), OBJECT_ROTATION(true), OBJECT_LAYER(true), OBJECT_DISTANCE_TO(true), diff --git a/catroid/src/main/java/org/catrobat/catroid/io/BackwardCompatibleCatrobatLanguageXStream.java b/catroid/src/main/java/org/catrobat/catroid/io/BackwardCompatibleCatrobatLanguageXStream.java index 4e1a68aefbb..c8edd8a5d42 100644 --- a/catroid/src/main/java/org/catrobat/catroid/io/BackwardCompatibleCatrobatLanguageXStream.java +++ b/catroid/src/main/java/org/catrobat/catroid/io/BackwardCompatibleCatrobatLanguageXStream.java @@ -115,6 +115,7 @@ import org.catrobat.catroid.content.bricks.RaspiPwmBrick; import org.catrobat.catroid.content.bricks.RaspiSendDigitalValueBrick; import org.catrobat.catroid.content.bricks.RepeatBrick; +import org.catrobat.catroid.content.bricks.ResetTimerBrick; import org.catrobat.catroid.content.bricks.SayBubbleBrick; import org.catrobat.catroid.content.bricks.SayForBubbleBrick; import org.catrobat.catroid.content.bricks.SceneStartBrick; @@ -276,6 +277,9 @@ private void initializeBrickInfoMap() { brickInfo.addBrickFieldToMap("yMovement", BrickField.Y_POSITION_CHANGE); brickInfoMap.put("changeYByNBrick", brickInfo); + brickInfo = new BrickInfo(ResetTimerBrick.class.getSimpleName()); + brickInfoMap.put("resetTimerBrick", brickInfo); + brickInfo = new BrickInfo(ClearGraphicEffectBrick.class.getSimpleName()); brickInfoMap.put("clearGraphicEffectBrick", brickInfo); diff --git a/catroid/src/main/java/org/catrobat/catroid/io/XstreamSerializer.java b/catroid/src/main/java/org/catrobat/catroid/io/XstreamSerializer.java index dd8b7fdc995..27557c37ef4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/io/XstreamSerializer.java +++ b/catroid/src/main/java/org/catrobat/catroid/io/XstreamSerializer.java @@ -174,6 +174,7 @@ import org.catrobat.catroid.content.bricks.RepeatBrick; import org.catrobat.catroid.content.bricks.RepeatUntilBrick; import org.catrobat.catroid.content.bricks.ReplaceItemInUserListBrick; +import org.catrobat.catroid.content.bricks.ResetTimerBrick; import org.catrobat.catroid.content.bricks.RunningStitchBrick; import org.catrobat.catroid.content.bricks.SayBubbleBrick; import org.catrobat.catroid.content.bricks.SayForBubbleBrick; @@ -502,6 +503,7 @@ private void prepareXstream(Class projectClass, Class sceneClass) { xstream.alias("brick", StopScriptBrick.class); xstream.alias("brick", WebRequestBrick.class); xstream.alias("brick", StoreCSVIntoUserListBrick.class); + xstream.alias("brick", ResetTimerBrick.class); xstream.alias("brick", WhenNfcBrick.class); xstream.alias("brick", SetNfcTagBrick.class); diff --git a/catroid/src/main/java/org/catrobat/catroid/stage/StageLifeCycleController.java b/catroid/src/main/java/org/catrobat/catroid/stage/StageLifeCycleController.java index 7cb900ce79b..c83b4a56cd4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/stage/StageLifeCycleController.java +++ b/catroid/src/main/java/org/catrobat/catroid/stage/StageLifeCycleController.java @@ -25,6 +25,7 @@ import android.content.pm.ActivityInfo; import android.graphics.PixelFormat; +import android.os.SystemClock; import android.util.Log; import android.view.SurfaceView; import android.view.WindowManager; @@ -135,6 +136,9 @@ static void stagePause(final StageActivity stageActivity) { } } SpeechRecognitionHolder.Companion.getInstance().destroy(); + + SensorHandler.timerPauseValue = SystemClock.uptimeMillis(); + SensorHandler.stopSensorListeners(); SoundManager.getInstance().pause(); StageActivity.stageListener.menuPause(); diff --git a/catroid/src/main/java/org/catrobat/catroid/stage/StageListener.java b/catroid/src/main/java/org/catrobat/catroid/stage/StageListener.java index dbb24947c58..b872eeeb1af 100644 --- a/catroid/src/main/java/org/catrobat/catroid/stage/StageListener.java +++ b/catroid/src/main/java/org/catrobat/catroid/stage/StageListener.java @@ -66,6 +66,7 @@ import org.catrobat.catroid.content.eventids.GamepadEventId; import org.catrobat.catroid.embroidery.DSTPatternManager; import org.catrobat.catroid.embroidery.EmbroideryPatternManager; +import org.catrobat.catroid.formulaeditor.SensorHandler; import org.catrobat.catroid.formulaeditor.UserDataWrapper; import org.catrobat.catroid.io.SoundManager; import org.catrobat.catroid.physics.PhysicsDebugSettings; @@ -247,6 +248,7 @@ private void createNewStage() { } stage = new Stage(viewPort, batch); + SensorHandler.timerReferenceValue = SystemClock.uptimeMillis(); } private void initActors(List sprites) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/dialogs/StageDialog.java b/catroid/src/main/java/org/catrobat/catroid/ui/dialogs/StageDialog.java index bbd6906193e..b1718aef766 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/dialogs/StageDialog.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/dialogs/StageDialog.java @@ -25,6 +25,7 @@ import android.app.Dialog; import android.os.AsyncTask; import android.os.Bundle; +import android.os.SystemClock; import android.util.Log; import android.view.View; import android.view.WindowManager.LayoutParams; @@ -38,6 +39,7 @@ import org.catrobat.catroid.content.Scene; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.embroidery.DSTFileGenerator; +import org.catrobat.catroid.formulaeditor.SensorHandler; import org.catrobat.catroid.stage.StageActivity; import org.catrobat.catroid.stage.StageLifeCycleController; import org.catrobat.catroid.stage.StageListener; @@ -162,18 +164,17 @@ private void shareEmbroideryFile() { } public void onContinuePressed() { - if (ProjectManager.getInstance().getCurrentProject().isCastProject() && !CastManager.getInstance().isConnected()) { ToastUtil.showError(getContext(), stageActivity.getResources().getString(R.string.cast_error_not_connected_msg)); return; } dismiss(); + SensorHandler.timerReferenceValue += SystemClock.uptimeMillis() - SensorHandler.timerPauseValue; StageLifeCycleController.stageResume(stageActivity); } public void onRestartPressed() { - if (ProjectManager.getInstance().getCurrentProject().isCastProject() && !CastManager.getInstance().isConnected()) { ToastUtil.showError(getContext(), stageActivity.getResources().getString(R.string.cast_error_not_connected_msg)); @@ -182,11 +183,11 @@ public void onRestartPressed() { clearBroadcastMaps(); dismiss(); + SensorHandler.timerReferenceValue = SystemClock.uptimeMillis(); restartProject(); } private void makeScreenshot() { - if (ProjectManager.getInstance().getCurrentProject().isCastProject() && !CastManager.getInstance().isConnected()) { ToastUtil.showError(getContext(), stageActivity.getResources().getString(R.string.cast_error_not_connected_msg)); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/fragment/CategoryBricksFactory.java b/catroid/src/main/java/org/catrobat/catroid/ui/fragment/CategoryBricksFactory.java index 00b2a8b3c50..266ab5bf6f1 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/fragment/CategoryBricksFactory.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/fragment/CategoryBricksFactory.java @@ -146,6 +146,7 @@ import org.catrobat.catroid.content.bricks.RepeatBrick; import org.catrobat.catroid.content.bricks.RepeatUntilBrick; import org.catrobat.catroid.content.bricks.ReplaceItemInUserListBrick; +import org.catrobat.catroid.content.bricks.ResetTimerBrick; import org.catrobat.catroid.content.bricks.RunningStitchBrick; import org.catrobat.catroid.content.bricks.SayBubbleBrick; import org.catrobat.catroid.content.bricks.SayForBubbleBrick; @@ -614,6 +615,7 @@ protected List setupDataCategoryList(Context context, boolean isBackgroun protected List setupDeviceCategoryList(Context context, boolean isBackgroundSprite) { List deviceBrickList = new ArrayList<>(); + deviceBrickList.add(new ResetTimerBrick()); deviceBrickList.add(new WhenBrick()); deviceBrickList.add(new WhenTouchDownBrick()); if (SettingsFragment.isNfcSharedPreferenceEnabled(context)) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java index e4f0f5b26e4..9d8b7fccddf 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java @@ -170,10 +170,11 @@ public class CategoryListFragment extends Fragment implements CategoryListRVAdap R.string.formula_editor_function_text_block_x, R.string.formula_editor_function_text_block_y, R.string.formula_editor_function_text_block_size); - private static final List SENSORS_DATE_TIME = asList(R.string.formula_editor_sensor_date_year, - R.string.formula_editor_sensor_date_month, R.string.formula_editor_sensor_date_day, - R.string.formula_editor_sensor_date_weekday, R.string.formula_editor_sensor_time_hour, - R.string.formula_editor_sensor_time_minute, R.string.formula_editor_sensor_time_second); + private static final List SENSORS_DATE_TIME = asList(R.string.formula_editor_sensor_timer, + R.string.formula_editor_sensor_date_year, R.string.formula_editor_sensor_date_month, + R.string.formula_editor_sensor_date_day, R.string.formula_editor_sensor_date_weekday, + R.string.formula_editor_sensor_time_hour, R.string.formula_editor_sensor_time_minute, + R.string.formula_editor_sensor_time_second); private static final List SENSORS_NXT = asList(R.string.formula_editor_sensor_lego_nxt_touch, R.string.formula_editor_sensor_lego_nxt_sound, R.string.formula_editor_sensor_lego_nxt_light, R.string.formula_editor_sensor_lego_nxt_light_active, diff --git a/catroid/src/main/res/layout/brick_reset_timer.xml b/catroid/src/main/res/layout/brick_reset_timer.xml new file mode 100644 index 00000000000..200874545cf --- /dev/null +++ b/catroid/src/main/res/layout/brick_reset_timer.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/catroid/src/main/res/values/strings.xml b/catroid/src/main/res/values/strings.xml index 30b14168584..c86192e9f90 100644 --- a/catroid/src/main/res/values/strings.xml +++ b/catroid/src/main/res/values/strings.xml @@ -1092,6 +1092,9 @@ embroidery.dst + + Reset timer + When scene starts When tapped @@ -1847,6 +1850,7 @@ needs read and write access to it. You can always change permissions through you inclination x inclination y loudness + timer year month day diff --git a/catroid/src/main/res/values/styles.xml b/catroid/src/main/res/values/styles.xml index 494b94f19ca..e5a5af053d5 100644 --- a/catroid/src/main/res/values/styles.xml +++ b/catroid/src/main/res/values/styles.xml @@ -283,7 +283,12 @@ - + + From fbbfcc4fbb96cb48a4ab0d918b3724913422e239 Mon Sep 17 00:00:00 2001 From: David Andrawes Date: Thu, 3 Sep 2020 22:43:06 +0200 Subject: [PATCH 004/189] CATROID-706 Add catrobat language test for sine function --- .../formula/testSineFunction.catrobat | Bin 0 -> 15944 bytes .../formula/testSinusFunction.catrobat | Bin 3113 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 catroid/src/androidTest/assets/catrobatTests/formula/testSineFunction.catrobat delete mode 100644 catroid/src/androidTest/assets/catrobatTests/formula/testSinusFunction.catrobat diff --git a/catroid/src/androidTest/assets/catrobatTests/formula/testSineFunction.catrobat b/catroid/src/androidTest/assets/catrobatTests/formula/testSineFunction.catrobat new file mode 100644 index 0000000000000000000000000000000000000000..460c76c3e9dfa4c3eae37c7a52d75afb4733c595 GIT binary patch literal 15944 zcmeHOTXWh*6edm6dh(o3Ul|@dQwwslGb6}gj2qV&hy_U>I+Iz@g4GC#>XM1uztM-j z=cPZRGyP%d*_%K{utzv?oK|FlrQNe<&z}9xw`V1`e{%cFd!?P7ozm}7_jzgQ^DSIk zzfq5tYewkDo*f#yoF(Q^d+VL~ z^FQWOxGKM)LFo8iy;9q)R?5@^5yzX>E5pIj_xqJ{7!l7VuJ6%$<${Kl^3%p$a~}B9 zfXo_q%VqPN5}O9>5^l(R?mA-aqTXd(S~Vc7O!a$&qkoGn$bwqWH%dJ%xS}> zqjpjsGIFWih=Le=l`d0q0j1tE>P*k0M(xRca6C-d zqG(x)yVDw+wFj+dN{p8+3%zvg=)6&@?kAc=iI9oNGz44uA5jtqE)=kDc^}f?8BCzd zW+YzRK&@#k0@(~{6afi@29IztG^v8$h-+x%vG|rmXBzyD_XJh`h(W32gpra?3d<2h zYrSI411F-DGHX_^9FXzrX~4L$vS=8rRJf;G>1$JRszZT}z zuJJs-2v|0+NkSHh2rd-3yageJoZu>hzeGw&mC&CxeOMc`yd{DE?1ex|+#y2wq1M^;T(5e^W~*rTv+lKPc%D2}_N>cNH%@y}S*&6?o`3A_ zRrhMu$9wy=+WzAkzocnF$MZXs6kr%Br@{!69I*b`M*{jGykFB~qg+}aOF%M35JZhFbVBP`e7Neg@B+ z_0zCLtbHE)$NZ0Hw4g%Jdmi4DSk~o^2{mOs>q;vB&$}|jMgvJ(IY5(e(SuKzT3OG} zbeSCnw0fGz$J7$px?}`H&|C1+RdWFt>vg=P$$>TLPwksl%v|$saT$C;P&_@*fkFS% zMGQe_jhTS)RvzjAopP^?$m$RtKyC7b zfw)O3C>8NjS_~>+rgJcFf(tG8eio=K$e&S7@=@!2cJj=`l*HO!(CWz_jW!wLo8Jm1 z34hjZ0AcS3`^9fA+Isj%_Z%6+sReoysd)$$1#%ph=2_p-tNTreFO1K@ zMQCE-U{Mdwbb*NTz3RSr_stdw)Y+9I$8*AS3r@Sy4|@D+P4BWeiyX|V9Dnvk}fcG68uR@@si+QdyJeRi}hmL2tso<#|Hc;52q42aa=IEJh;R zCTB4l?40y>-#q&BFSAs72mkvgx4yVnN}st_XQ-1;M32eNQA3>i|a_R8(WhKj2 e@}u2}DSyC~I(OYax$_mPxDEgQhQC3b-Tez`{&+Y5 literal 0 HcmV?d00001 diff --git a/catroid/src/androidTest/assets/catrobatTests/formula/testSinusFunction.catrobat b/catroid/src/androidTest/assets/catrobatTests/formula/testSinusFunction.catrobat deleted file mode 100644 index 252c08473a9d014e945c6fab39e37b63f0c324ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3113 zcmbVOPjA~c6jz&d$a2|$71&kKZHG#Zm((6At8hGL3F10lWOut2v_#unBuXQxAUO`$ z=h$iAr03oD1@;Mc-C>WUXj``8x?^C4{Jr1%!$&@nqpO2Yo?F)8q4iJn+t7mcRDPg+ z1-~%D6x+uhNzoj0&!t(4V}cH>(OzmiD`>o*+81ly_Hpw$@N>*k!a2z(cg4L}Mg^iT z(buDY-(SA}`!mauzeB*HEXMAAn)t8bW8YyWH9O9++i+}5K}zVn<4nfqFWQdH1)?!Z zGKxFS1LltXIymxkmdzPTgCpDa7Z}Bu$u0~~o+l(i0t}uNB#DP8#ewhD!jEVa=@iU0 zYLv8OOHKJ0Wzj7bb`Pdj(Nw}MmA87%LBsvlJ#AJLj7aOiR9H4eVu0wpfTcH5P=t2s zdyf&cdW-}flN3+#BttPIVgo2ym`9A{GHH^sHZt-%5@9uy!S^pN+AT;w zj9B(Fjzlm+35P^fK}}3xJ$Zz3{04Gmh*eM%)eawkXUgRoR)(69CrHdPmIhrKvy8;P zw?wK0leXr|6~$mBQ}3viyK;*epu$qA5SWXQ(1M>AG?KXk)7r?|nlqe|`|BBmZ+hAg zm-Wp16ipKx2Z9xltSV-B3}bqM$$TM#=F1lB6Zz3` z)Ij$^iOLEM_3`F=YNR}YD4WW?G$33U_7b$kLk}7vr+(+ zB+G846%~s-CS>!~nOFm>Qm8uBd?hfB1!5vpNX3_8P8o@m!}TbnM264iuBlnwA+Z}} zRA4GxrO4ebhrEjZF9j6QnY2|p-NLtAD;H6greF=n*Tu3BD_EId6;S!{Wf>I-+Mc&z z8HNqf<9Ws&I!-qX`#0lv{U0XXLHMr!)2QDY_rI$RN(Cm@EErDSob_*DkI6wzB#L>5 zk^;-qv3=5Rv|6X%G>)6iM%(wapjOTI$~n|q{b2mv-WcZbc=QRLiQWS4lzRIgH$&J7 zdMa(G!yS_Xp7%k=zRKnKWY`;DUJv(5ZFmX19e#Hvb1AIfExz}^Hu-j1eN_+T=07Kt z@I?qm6IL}*yHI{*pO=?V1>4#>zNfrwdN1L+8GfV_bN{f)H1m@%^P>fL2TzIs=ULf05EZ{S_p@(sLd tze9K9MXZz$APLawUc^cOpFe*66TaqsJi2=Jsgyi}zgJHz>#rj@`VadPND}}6 From cf72aa75a95235f9b26760c48902920c0f13c299 Mon Sep 17 00:00:00 2001 From: Nur Date: Sun, 18 Oct 2020 02:21:49 +0200 Subject: [PATCH 005/189] CATROID-797: Android Material Components --- build.gradle | 2 +- catroid/build.gradle | 4 +-- catroid/src/main/res/values/styles.xml | 38 +++++++++++++------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index 1c91b41384c..b7b2d61ea0b 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.60' + ext.kotlin_version = '1.4.10' repositories { google() jcenter() diff --git a/catroid/build.gradle b/catroid/build.gradle index efd7c775823..2798821689a 100644 --- a/catroid/build.gradle +++ b/catroid/build.gradle @@ -338,10 +338,10 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8' // Support libraries - implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.mediarouter:mediarouter:1.1.0' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'com.google.android.material:material:1.0.0' + implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.browser:browser:1.2.0' implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion" diff --git a/catroid/src/main/res/values/styles.xml b/catroid/src/main/res/values/styles.xml index fb4eb4205f5..9347ea71b0a 100644 --- a/catroid/src/main/res/values/styles.xml +++ b/catroid/src/main/res/values/styles.xml @@ -23,7 +23,7 @@ - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - +repeat + + + diff --git a/catroid/src/main/assets/catblocks/media/sprites.png b/catroid/src/main/assets/catblocks/media/sprites.png new file mode 100644 index 0000000000000000000000000000000000000000..20aadb6c4c31f4a46f0a3316241788687c2fc444 GIT binary patch literal 2595 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 literal 0 HcmV?d00001 diff --git a/catroid/src/main/assets/catblocks/media/sprites.svg b/catroid/src/main/assets/catblocks/media/sprites.svg new file mode 100644 index 00000000000..3f09ef3a4d6 --- /dev/null +++ b/catroid/src/main/assets/catblocks/media/sprites.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/catroid/src/main/java/org/catrobat/catroid/common/Constants.java b/catroid/src/main/java/org/catrobat/catroid/common/Constants.java index 89fc0fe000e..84e8ec12507 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/Constants.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/Constants.java @@ -39,7 +39,7 @@ public final class Constants { - public static final double CURRENT_CATROBAT_LANGUAGE_VERSION = 0.99999997; + public static final double CURRENT_CATROBAT_LANGUAGE_VERSION = 0.99999998; public static final String REMOTE_DISPLAY_APP_ID = "CEBB9229"; public static final int CAST_CONNECTION_TIMEOUT = 5000; //in milliseconds diff --git a/catroid/src/main/java/org/catrobat/catroid/content/Script.java b/catroid/src/main/java/org/catrobat/catroid/content/Script.java index dfe27631a08..1239cc577c4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/content/Script.java +++ b/catroid/src/main/java/org/catrobat/catroid/content/Script.java @@ -22,6 +22,8 @@ */ package org.catrobat.catroid.content; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + import org.catrobat.catroid.content.actions.ScriptSequenceAction; import org.catrobat.catroid.content.bricks.Brick; import org.catrobat.catroid.content.bricks.CompositeBrick; @@ -35,6 +37,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.UUID; public abstract class Script implements Serializable, Cloneable { @@ -43,6 +46,13 @@ public abstract class Script implements Serializable, Cloneable { protected List brickList = new ArrayList<>(); protected boolean commentedOut = false; + @XStreamAsAttribute + protected float posX; + @XStreamAsAttribute + protected float posY; + + protected UUID scriptId = UUID.randomUUID(); + protected transient ScriptBrick scriptBrick; public List getBrickList() { @@ -62,9 +72,32 @@ public Script clone() throws CloneNotSupportedException { clone.commentedOut = commentedOut; clone.scriptBrick = null; + clone.posX = posX; + clone.posY = posY; + clone.scriptId = UUID.randomUUID(); return clone; } + public float getPosX() { + return posX; + } + + public void setPosX(float posX) { + this.posX = posX; + } + + public float getPosY() { + return posY; + } + + public void setPosY(float posY) { + this.posY = posY; + } + + public UUID getScriptId() { + return scriptId; + } + public boolean isCommentedOut() { return commentedOut; } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/BottomBar.kt b/catroid/src/main/java/org/catrobat/catroid/ui/BottomBar.kt index 301c4caec2b..1cbbe9d0e4e 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/BottomBar.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/BottomBar.kt @@ -42,6 +42,11 @@ object BottomBar { activity?.findViewById(R.id.button_add)?.visibility = View.VISIBLE } + @JvmStatic + fun hideAddButton(activity: Activity?) { + activity?.findViewById(R.id.button_add)?.visibility = View.GONE + } + @JvmStatic fun showPlayButton(activity: Activity?) { activity?.findViewById(R.id.button_play)?.visibility = View.VISIBLE diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivityOnTabSelectedListener.kt b/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivityOnTabSelectedListener.kt index e4d0e4c6ee5..5de3f1d69ed 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivityOnTabSelectedListener.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivityOnTabSelectedListener.kt @@ -31,13 +31,18 @@ import androidx.fragment.app.FragmentTransaction import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout.OnTabSelectedListener import com.google.android.material.tabs.TabLayout.Tab +import org.catrobat.catroid.BuildConfig +import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R import org.catrobat.catroid.ui.SpriteActivity.FRAGMENT_LOOKS import org.catrobat.catroid.ui.SpriteActivity.FRAGMENT_SCRIPTS import org.catrobat.catroid.ui.SpriteActivity.FRAGMENT_SOUNDS +import org.catrobat.catroid.ui.recyclerview.fragment.CatblocksScriptFragment +import org.catrobat.catroid.ui.recyclerview.fragment.CatblocksScriptFragment.Companion.TAG import org.catrobat.catroid.ui.recyclerview.fragment.LookListFragment import org.catrobat.catroid.ui.recyclerview.fragment.ScriptFragment import org.catrobat.catroid.ui.recyclerview.fragment.SoundListFragment +import org.catrobat.catroid.ui.settingsfragments.SettingsFragment import kotlin.reflect.KFunction1 @SuppressWarnings("EmptyFunctionBlock") @@ -79,14 +84,45 @@ fun SpriteActivity.loadFragment(fragmentPosition: Int) { } when (fragmentPosition) { - FRAGMENT_SCRIPTS -> fragmentTransaction.replace(R.id.fragment_container, ScriptFragment(), ScriptFragment.TAG) - FRAGMENT_LOOKS -> fragmentTransaction.replace(R.id.fragment_container, LookListFragment(), LookListFragment.TAG) - FRAGMENT_SOUNDS -> fragmentTransaction.replace(R.id.fragment_container, SoundListFragment(), SoundListFragment.TAG) + FRAGMENT_SCRIPTS -> showScripts(fragmentTransaction) + FRAGMENT_LOOKS -> fragmentTransaction.replace( + R.id.fragment_container, + LookListFragment(), + LookListFragment.TAG + ) + FRAGMENT_SOUNDS -> fragmentTransaction.replace( + R.id.fragment_container, + SoundListFragment(), + SoundListFragment.TAG + ) else -> throw IllegalArgumentException("Invalid fragmentPosition in Activity.") } + fragmentTransaction.commit() } +private fun SpriteActivity.showScripts(fragmentTransaction: FragmentTransaction) { + val currentProject = ProjectManager.getInstance().currentProject + if (!BuildConfig.FEATURE_CATBLOCKS_ENABLED || !SettingsFragment.useCatBlocks(this)) { + // Classic 1D view + fragmentTransaction.replace( + R.id.fragment_container, ScriptFragment(currentProject), + ScriptFragment.TAG + ) + } else { + // start with 2D view + val currentSprite = ProjectManager.getInstance().currentSprite + val currentScene = ProjectManager.getInstance().currentlyEditedScene + fragmentTransaction.replace( + R.id.fragment_container, + CatblocksScriptFragment( + currentProject, currentScene, + currentSprite, 0 + ), + TAG + ) + } +} fun Fragment?.getTabPositionInSpriteActivity(): Int = when (this) { is ScriptFragment -> FRAGMENT_SCRIPTS is LookListFragment -> FRAGMENT_LOOKS diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt new file mode 100644 index 00000000000..e007d9167d7 --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt @@ -0,0 +1,249 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2020 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.ui.recyclerview.fragment + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.webkit.JavascriptInterface +import android.webkit.ValueCallback +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.webkit.WebViewAssetLoader +import org.catrobat.catroid.BuildConfig +import org.catrobat.catroid.R +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.io.XstreamSerializer +import org.catrobat.catroid.ui.BottomBar +import org.catrobat.catroid.ui.settingsfragments.SettingsFragment +import java.util.Locale +import java.util.UUID + +class CatblocksScriptFragment( + private val currentProject: Project?, + private val currentScene: Scene?, + private val currentSprite: Sprite?, + private val currentScriptIndex: Int +) : Fragment() { + + private var webview: WebView? = null + + companion object { + val TAG: String = CatblocksScriptFragment::class.java.simpleName + } + + override fun onPrepareOptionsMenu(menu: Menu) { + super.onPrepareOptionsMenu(menu) + menu.removeItem(R.id.backpack) + menu.removeItem(R.id.copy) + menu.removeItem(R.id.delete) + menu.removeItem(R.id.rename) + menu.removeItem(R.id.show_details) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == R.id.catblocks) { + SettingsFragment.setUseCatBlocks(context, false) + + val fragmentTransaction = parentFragmentManager?.beginTransaction() + fragmentTransaction?.replace( + R.id.fragment_container, ScriptFragment(currentProject), + ScriptFragment.TAG + ) + fragmentTransaction?.commit() + + return true + } else if (item.itemId == R.id.catblocks_reorder_scripts) { + val callback = ReorderCallback() + webview!!.evaluateJavascript("javascript:CatBlocks.reorderCurrentScripts();", callback) + } + return super.onOptionsItemSelected(item) + } + + override fun onResume() { + super.onResume() + + val actionBar = (activity as AppCompatActivity?)!!.supportActionBar + actionBar?.title = currentProject?.name + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + BottomBar.showBottomBar(activity) + BottomBar.showPlayButton(activity) + BottomBar.hideAddButton(activity) + + setHasOptionsMenu(true) + + val view = View.inflate(activity, R.layout.fragment_catblocks, null) + val webView = view.findViewById(R.id.catblocksWebView) + initWebView(webView) + this.webview = webView + return view + } + + @SuppressLint("SetJavaScriptEnabled") + private fun initWebView(catblocksWebView: WebView) { + catblocksWebView.settings.javaScriptEnabled = true + + if (BuildConfig.FEATURE_CATBLOCKS_DEBUGABLE) { + WebView.setWebContentsDebuggingEnabled(true) + } + + val assetLoader: WebViewAssetLoader = WebViewAssetLoader.Builder() + .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(requireActivity())) + .addPathHandler("/res/", WebViewAssetLoader.ResourcesPathHandler(requireActivity())) + .build() + + catblocksWebView.addJavascriptInterface( + JSInterface( + currentProject, + currentScene, + currentSprite, + currentScriptIndex + ), "Android" + ) + + catblocksWebView.webViewClient = object : WebViewClient() { + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest + ): WebResourceResponse? { + return assetLoader.shouldInterceptRequest(request.url) + } + } + catblocksWebView.loadUrl("https://appassets.androidplatform.net/assets/catblocks/index.html") + } + + class ReorderCallback : ValueCallback { + + override fun onReceiveValue(value: String?) { // do nothing + } + } + + class JSInterface( + private val project: Project?, + private val scene: Scene?, + private val sprite: Sprite?, + private val script: Int + ) { + + @JavascriptInterface + fun getCurrentProject(): String { + val projectXml = XstreamSerializer.getInstance().getXmlAsStringFromProject(project) + return "\n$projectXml" + } + + @JavascriptInterface + fun getCurrentLanguage(): String = + Locale.getDefault().toString().replace("_", "-") + + @JavascriptInterface + fun isRTL(): Boolean { + val directionality = Character.getDirectionality(Locale.getDefault().displayName[0]) + return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT || + directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC + } + + @JavascriptInterface + fun getSceneNameToDisplay(): String? { + if (scene != null) { + return scene.name.trim() + } + return null + } + + @JavascriptInterface + fun getSpriteNameToDisplay(): String? { + if (sprite != null) { + return sprite.name.trim() + } + return null + } + + @JavascriptInterface + fun getScriptIndexToDisplay(): Int = script + + @SuppressLint + @JavascriptInterface + fun updateScriptPosition(strScriptId: String, x: String, y: String) { + if (project == null) { + return + } + + val scriptId = UUID.fromString(strScriptId) + val posX = x.toFloat() + val posY = y.toFloat() + + for (scene in project.sceneList) { + if (updateScriptPositionInScene(scriptId, posX, posY, scene)) { + return + } + } + } + + private fun updateScriptPositionInScene( + scriptId: UUID, + x: Float, + y: Float, + scene: Scene + ): Boolean { + for (sprite in scene.spriteList) { + if (updateScriptPositionInSprite(scriptId, x, y, sprite)) { + return true + } + } + return false + } + + private fun updateScriptPositionInSprite( + scriptId: UUID, + x: Float, + y: Float, + sprite: Sprite + ): Boolean { + for (script in sprite.scriptList) { + if (script.scriptId == scriptId) { + script.posX = x + script.posY = y + return true + } + } + return false + } + } +} diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java index 666e13940d1..e28ec210733 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.os.Bundle; import android.util.Log; +import android.view.Menu; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; @@ -65,6 +66,14 @@ protected void initializeAdapter() { onAdapterReady(); } + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + + menu.findItem(R.id.catblocks_reorder_scripts).setVisible(false); + menu.findItem(R.id.catblocks).setVisible(false); + } + @Override protected void packItems(List selectedItems) { setShowProgressBar(true); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index 4b8d903957f..0e423130db6 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -35,6 +35,7 @@ import android.view.View; import android.view.ViewGroup; +import org.catrobat.catroid.BuildConfig; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; import org.catrobat.catroid.content.Project; @@ -63,6 +64,7 @@ import org.catrobat.catroid.ui.recyclerview.controller.ScriptController; import org.catrobat.catroid.ui.recyclerview.dialog.TextInputDialog; import org.catrobat.catroid.ui.recyclerview.dialog.textwatcher.UniqueStringTextWatcher; +import org.catrobat.catroid.ui.settingsfragments.SettingsFragment; import org.catrobat.catroid.utils.SnackbarUtil; import org.catrobat.catroid.utils.ToastUtil; @@ -76,6 +78,7 @@ import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.ListFragment; public class ScriptFragment extends ListFragment implements @@ -86,15 +89,22 @@ public class ScriptFragment extends ListFragment implements public static final String TAG = ScriptFragment.class.getSimpleName(); @Retention(RetentionPolicy.SOURCE) - @IntDef({NONE, BACKPACK, COPY, DELETE, COMMENT}) + @IntDef({NONE, BACKPACK, COPY, DELETE, COMMENT, CATBLOCKS}) @interface ActionModeType { } + public ScriptFragment(Project currentProject) { + this.currentProject = currentProject; + } + + private Project currentProject; + private static final int NONE = 0; private static final int BACKPACK = 1; private static final int COPY = 2; private static final int DELETE = 3; private static final int COMMENT = 4; + private static final int CATBLOCKS = 5; @ActionModeType private int actionModeType = NONE; @@ -136,6 +146,8 @@ public boolean onCreateActionMode(ActionMode mode, Menu menu) { adapter.setCheckBoxMode(NONE); actionMode.finish(); return false; + case CATBLOCKS: + break; } return true; } @@ -184,6 +196,8 @@ private void handleContextualAction() { break; case NONE: throw new IllegalStateException("ActionModeType not set correctly"); + case CATBLOCKS: + break; } } @@ -263,6 +277,10 @@ public void onPause() { public void onPrepareOptionsMenu(Menu menu) { menu.findItem(R.id.show_details).setVisible(false); menu.findItem(R.id.rename).setVisible(false); + menu.findItem(R.id.catblocks_reorder_scripts).setVisible(false); + if (!BuildConfig.FEATURE_CATBLOCKS_ENABLED) { + menu.findItem(R.id.catblocks).setVisible(false); + } super.onPrepareOptionsMenu(menu); } @@ -291,6 +309,9 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.comment_in_out: prepareActionMode(COMMENT); break; + case R.id.catblocks: + switchToCatblocks(); + break; default: return super.onOptionsItemSelected(item); } @@ -395,6 +416,8 @@ public void onSelectionChanged(int selectedItemCnt) { break; case NONE: throw new IllegalStateException("ActionModeType not set Correctly"); + case CATBLOCKS: + break; } } @@ -659,6 +682,38 @@ private void switchToBackpack() { startActivity(intent); } + private void switchToCatblocks() { + if (!BuildConfig.FEATURE_CATBLOCKS_ENABLED) { + return; + } + + int scriptIndex = -1; + + int firstVisible = listView.getFirstVisiblePosition(); + + if (firstVisible >= 0) { + Object firstBrick = listView.getItemAtPosition(firstVisible); + if (firstBrick instanceof Brick) { + Script scriptOfBrick = ((Brick) firstBrick).getScript(); + scriptIndex = + ProjectManager.getInstance().getCurrentSprite().getScriptIndex(scriptOfBrick); + } + } + + Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); + Scene currentScene = ProjectManager.getInstance().getCurrentlyEditedScene(); + + SettingsFragment.setUseCatBlocks(getContext(), true); + + CatblocksScriptFragment catblocksFragment = new CatblocksScriptFragment(currentProject, + currentScene, currentSprite, scriptIndex); + + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction.replace(R.id.fragment_container, catblocksFragment, + CatblocksScriptFragment.Companion.getTAG()); + fragmentTransaction.commit(); + } + private void copy(List selectedBricks) { Sprite sprite = ProjectManager.getInstance().getCurrentSprite(); brickController.copy(selectedBricks, sprite); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java index ead43a22d69..f1e3428e358 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.util.Log; +import android.view.Menu; import org.catrobat.catroid.BuildConfig; import org.catrobat.catroid.ProjectManager; @@ -63,6 +64,14 @@ protected void initializeAdapter() { onAdapterReady(); } + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + + menu.findItem(R.id.catblocks_reorder_scripts).setVisible(false); + menu.findItem(R.id.catblocks).setVisible(false); + } + @Override protected void packItems(List selectedItems) { setShowProgressBar(true); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/settingsfragments/SettingsFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/settingsfragments/SettingsFragment.java index 48a26ec9263..0530fce8ac3 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/settingsfragments/SettingsFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/settingsfragments/SettingsFragment.java @@ -112,6 +112,8 @@ public class SettingsFragment extends PreferenceFragment { public static final String SETTINGS_CRASH_REPORTS = "setting_enable_crash_reports"; public static final String TAG = SettingsFragment.class.getSimpleName(); + public static final String SETTINGS_USE_CATBLOCKS = "settings_use_catblocks"; + @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { @@ -486,4 +488,14 @@ public static void removeLanguageSharedPreference(Context context) { .remove(LANGUAGE_TAG_KEY) .apply(); } + + public static boolean useCatBlocks(Context context) { + return getBooleanSharedPreference(false, SETTINGS_USE_CATBLOCKS, context); + } + + public static void setUseCatBlocks(Context context, boolean useCatBlocks) { + getSharedPreferences(context).edit() + .putBoolean(SETTINGS_USE_CATBLOCKS, useCatBlocks) + .apply(); + } } diff --git a/catroid/src/main/res/layout/fragment_catblocks.xml b/catroid/src/main/res/layout/fragment_catblocks.xml new file mode 100644 index 00000000000..f564ae99573 --- /dev/null +++ b/catroid/src/main/res/layout/fragment_catblocks.xml @@ -0,0 +1,37 @@ + + + + + + + + \ No newline at end of file diff --git a/catroid/src/main/res/menu/menu_script_activity.xml b/catroid/src/main/res/menu/menu_script_activity.xml index 5fcd1cc71a4..20db13970dc 100644 --- a/catroid/src/main/res/menu/menu_script_activity.xml +++ b/catroid/src/main/res/menu/menu_script_activity.xml @@ -58,4 +58,13 @@ android:title="@string/comment_in_out" android:visible="false" app:showAsAction="never" /> + + diff --git a/catroid/src/main/res/values/strings.xml b/catroid/src/main/res/values/strings.xml index 816c84856da..ba01fa4beff 100644 --- a/catroid/src/main/res/values/strings.xml +++ b/catroid/src/main/res/values/strings.xml @@ -799,6 +799,8 @@ Disable script Help Disable/enable + Toggle 2D + Clean up scripts diff --git a/catroid/src/test/java/org/catrobat/catroid/test/xmlformat/ScriptsXmlSerializerTest.java b/catroid/src/test/java/org/catrobat/catroid/test/xmlformat/ScriptsXmlSerializerTest.java index 0e817bc6fbc..853e1ef7379 100644 --- a/catroid/src/test/java/org/catrobat/catroid/test/xmlformat/ScriptsXmlSerializerTest.java +++ b/catroid/src/test/java/org/catrobat/catroid/test/xmlformat/ScriptsXmlSerializerTest.java @@ -22,6 +22,8 @@ */ package org.catrobat.catroid.test.xmlformat; +import com.thoughtworks.xstream.converters.basic.FloatConverter; + import org.catrobat.catroid.content.Script; import org.catrobat.catroid.io.XstreamSerializer; import org.junit.Test; @@ -68,7 +70,12 @@ public static Iterable data() { public void testScriptAlias() throws IllegalAccessException, InstantiationException { Script script = (Script) scriptClass.newInstance(); String xml = XstreamSerializer.getInstance().getXstream().toXML(script); - assertThat(xml, startsWith(" diff --git a/catroid/src/main/assets/catblocks/main.css b/catroid/src/main/assets/catblocks/main.css index 6fb934dc153..9b34d40f6a8 100644 --- a/catroid/src/main/assets/catblocks/main.css +++ b/catroid/src/main/assets/catblocks/main.css @@ -1,79 +1,3 @@ -.card { - border-radius: 0; - box-shadow: 0 2px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 4px 0 rgba(0, 0, 0, 0.12); -} - -.card-header { - background: none; - font-size: 0.9rem; - border-bottom: 0; -} - -.card-header.collapsed { - border-bottom: 2px solid #eee; -} - -.card-body { - padding: 0; -} - -.card-body .card-header { - font-size: 0.8rem; - padding-left: 3.5em; -} - -.card-body .card-body { - padding: 0; -} - -.card-header[aria-expanded='true'], -.collapse.show .card-header, -.collapse.show .card-body { - background: rgba(0, 0, 0, 0.04); - transition: 0.5s background ease; -} - -.catro-tabs .nav-tabs { - padding: 0; - border-bottom: 1px solid #e0e0e0; - background: rgba(0, 0, 0, 0.04); -} - -.catro-tabs .nav-link { - text-decoration: none; - padding: 0.9em; - border: 0; - color: rgba(0, 0, 0, 0.8); - font-size: 0.8em; -} - -.catro-tabs .nav-link.active { - font-weight: 700; - border-bottom: 2px solid #00acc1; - color: black; - background: none; -} - -img { - border-radius: 10%; -} - -.list-group-item { - font-size: 0.8em; - border-bottom: 0; - background: none; - display: flex; - align-items: center; -} - -.tab-pane { - background: none; -} - -.material-icons { - vertical-align: middle; -} - .blocklyText { fill: #fff; font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, sans-serif; @@ -97,76 +21,32 @@ img { fill: #fff !important; } -.card-header { - cursor: pointer; -} - -.catblocks-tab-script { - height: 2rem; -} - -.catblocks-tab-icon { - height: 2rem; - font-size: 2rem; -} - -.catblocks-script { - padding: 0 20px; -} - -.catblocks-script + .catblocks-script { - margin-top: 20px; -} - -.catblocks-empty-text { - padding: 20px; -} - -.catblocks-object-sound-item { - width: 100%; -} - -[data-toggle='collapse'][aria-expanded='true'] .rotate-left { - transform: rotate(-90deg); -} - -.rotate-left { - transition: 0.3s transform ease; - transition-property: transform; - transition-duration: 0.3s; - transition-timing-function: ease; - transition-delay: 0s; -} - -[data-toggle='collapse'][aria-expanded='true'] .header-title { - font-weight: bold; -} - .search { border: none; } -#catblocks-program-container { - overflow-x: hidden; - overflow-y: auto; -} - #formulaPopupContent { word-wrap: break-word; } -.catblocks-script-modifiable { - height: 80vh; +.catblockls-blockly-invisible > .blocklyPath { + fill-opacity: 0; + stroke-opacity: 0; +} + +html, +body { + height: 100vh; width: 100%; } -.catblocks-script-modifiable.blocklySvg { - height: 80vh; +#catroid-catblocks-container { + height: 100vh; width: 100%; } -.catblockls-blockly-invisible > .blocklyPath { - fill-opacity: 0; - stroke-opacity: 0; +#catroid-catblocks-container.blocklySvg { + height: 100vh; + width: 100%; } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt index d510f59bf01..c6cbc6d50fe 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt @@ -43,8 +43,6 @@ import com.google.gson.Gson import org.catrobat.catroid.BuildConfig import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R -import org.catrobat.catroid.content.Scene -import org.catrobat.catroid.content.Sprite import org.catrobat.catroid.content.bricks.Brick import org.catrobat.catroid.content.bricks.EmptyEventBrick import org.catrobat.catroid.content.bricks.ScriptBrick @@ -204,7 +202,7 @@ class CatblocksScriptFragment( @SuppressLint @JavascriptInterface fun updateScriptPosition(strScriptId: String, x: String, y: String) { - if (projectManager.currentProject == null) { + if (projectManager.currentSprite == null) { return } @@ -212,41 +210,13 @@ class CatblocksScriptFragment( val posX: Float = x.toFloat() val posY: Float = y.toFloat() - for (scene in projectManager.currentProject.sceneList) { - if (updateScriptPositionInScene(scriptId, posX, posY, scene)) { - return - } - } - } - - private fun updateScriptPositionInScene( - scriptId: UUID, - x: Float, - y: Float, - scene: Scene - ): Boolean { - for (sprite in scene.spriteList) { - if (updateScriptPositionInSprite(scriptId, x, y, sprite)) { - return true - } - } - return false - } - - private fun updateScriptPositionInSprite( - scriptId: UUID, - x: Float, - y: Float, - sprite: Sprite - ): Boolean { - for (script in sprite.scriptList) { + for (script in projectManager.currentSprite.scriptList) { if (script.scriptId == scriptId) { - script.posX = x - script.posY = y - return true + script.posX = posX + script.posY = posY + break } } - return false } @JavascriptInterface From b771939aa7ae88f857302984674644e45b9af35b Mon Sep 17 00:00:00 2001 From: Bernhard Prattes Date: Fri, 19 Feb 2021 14:42:15 +0100 Subject: [PATCH 103/189] CATROID-931 tag all strings used by Catblocks --- catroid/src/main/res/values/strings.xml | 934 ++++++++++++------------ 1 file changed, 467 insertions(+), 467 deletions(-) diff --git a/catroid/src/main/res/values/strings.xml b/catroid/src/main/res/values/strings.xml index 99dfaa37c85..9084a5e4069 100644 --- a/catroid/src/main/res/values/strings.xml +++ b/catroid/src/main/res/values/strings.xml @@ -27,8 +27,8 @@ Stage Play Settings - Redo - Undo + Redo + Undo new… edit… @@ -44,7 +44,7 @@ OK Done - Close + Close Assistant @@ -88,8 +88,8 @@ Logout successful - degrees - Background + degrees + Background landscape portrait unknown @@ -100,7 +100,7 @@ Continue project New project Projects on device - Help + Help Catrobat community Upload project @@ -344,7 +344,7 @@ Pack Unpack Copy - Delete + Delete Rename Convert Merge @@ -566,8 +566,8 @@ Scan NFC tags to add them - as record type - Wait for next NFC tag to write + as record type + Wait for next NFC tag to write www.catrobat.org NFC tag Empty @@ -713,7 +713,7 @@ Move brick Move script Move this definition - Delete brick + Delete brick Copy brick Copy script Edit formula @@ -843,26 +843,26 @@ - Categories - Embroidery - Motion - Looks - Pen - Sound - Control - Event - Your bricks - Data - Device - Lego NXT - Lego EV3 - AR.Drone 2.0 - Jumping Sumo - Phiro - Arduino - Chromecast - Raspberry Pi - Testing + Categories + Embroidery + Motion + Looks + Pen + Sound + Control + Event + Your bricks + Data + Device + Lego NXT + Lego EV3 + AR.Drone 2.0 + Jumping Sumo + Phiro + Arduino + Chromecast + Raspberry Pi + Testing @@ -877,187 +877,187 @@ A brick with these labels already exists. Please add more labels or inputs. - Define - as + Define + as Tap \"+\" to add your own new bricks. - "Place at" + "Place at" Place visually - "x:" - "y:" - "Set x to" - "Set y to" - "Change x by" - "Change y by" - Go back - "Set rotation style" - left-right only - all-around - don\'t rotate + "x:" + "y:" + "Set x to" + "Set y to" + "Change x by" + "Change y by" + Go back + "Set rotation style" + left-right only + all-around + don\'t rotate layer layers - Go to front - If on edge, bounce - Move + Go to front + If on edge, bounce + Move step steps - Turn left - Turn right - Point in direction - Point towards - Glide - to x: - Go to + Turn left + Turn right + Point in direction + Point towards + Glide + to x: + Go to touch position random position - Set your motion type to - moving and bouncing under gravity - not moving under gravity, but others bounce off you under gravity - not moving or bouncing under gravity (default) - "Set mass to" - kilogram - "Set gravity for all actors and objects to" - steps/second² - "Set velocity to" - steps/second - degrees/second - "Set friction to" - "Set bounce factor to" - "Spin left" - "Spin right" + Set your motion type to + moving and bouncing under gravity + not moving under gravity, but others bounce off you under gravity + not moving or bouncing under gravity (default) + "Set mass to" + kilogram + "Set gravity for all actors and objects to" + steps/second² + "Set velocity to" + steps/second + degrees/second + "Set friction to" + "Set bounce factor to" + "Spin left" + "Spin right" - Switch to look - Switch to look with number + Switch to look + Switch to look with number and wait - Set background - Set background and wait - Set background to number - When background changes to - Set size to - Change size by - Hide - Show - "Set transparency" - "Change transparency" - "Set brightness" - "Change brightness" - "Set color" - "Change color" - by - to - Clear graphic effects - Next look + Set background + Set background and wait + Set background to number + When background changes to + Set size to + Change size by + Hide + Show + "Set transparency" + "Change transparency" + "Set brightness" + "Change brightness" + "Set color" + "Change color" + by + to + Clear graphic effects + Next look Next background - Previous look + Previous look Previous background - Edit look + Edit look Edit background - Delete look + Delete look Delete background - Turn flashlight - on - off - Vibrate for - Ask - and store written answer in + Turn flashlight + on + off + Vibrate for + Ask + and store written answer in What\'s your name? "Enter your answer:" Submit answer - Ask - and store spoken answer in + Ask + and store spoken answer in What\'s your name? - Paint new look + Paint new look Paint new background "name of new look" - Copy look and name it + Copy look and name it name of copied look Copy background and name it - Pen down - Pen up - Set pen size to - Set pen color to - Clear - Stamp + Pen down + Pen up + Set pen size to + Set pen color to + Clear + Stamp - Start sound - Start sound and wait - Stop sound - Stop all sounds - Set volume to - Change volume by - Speak + Start sound + Start sound and wait + Stop sound + Stop all sounds + Set volume to + Change volume by + Speak Hello! - and wait - Start listening to voice and store spoken words in + and wait + Start listening to voice and store spoken words in Speech recognition isn\'t available. Missing offline data Offline speech recognition for %s is missing or needs to be updated. Would you like to download or update it now? - Set listening language to - Set instrument to - Set tempo to - Change tempo by - Pause for - Play drum - beats - Play note - for + Set listening language to + Set instrument to + Set tempo to + Change tempo by + Pause for + Play drum + beats + Play note + for - Stitch - Start running stitch with length - Start zigzag stitch with length - and width - Start triple stitch with length - Stop current stitch - Write embroidery data to file + Stitch + Start running stitch with length + Start zigzag stitch with length + and width + Start triple stitch with length + Stop current stitch + Write embroidery data to file embroidery.dst - Sew up + Sew up - Reset timer - Open - in browser + Reset timer + Open + in browser - When scene starts - When tapped - When - becomes true - Wait - Wait until - is true - When gamepad button - tapped - When NFC - Stop - this script - all scripts - other scripts of this actor or object + When scene starts + When tapped + When + becomes true + Wait + Wait until + is true + When gamepad button + tapped + When NFC + Stop + this script + all scripts + other scripts of this actor or object @@ -1065,46 +1065,46 @@ "seconds" - When you bounce off + When you bounce off any edge, actor, or object - When you receive - Broadcast - Broadcast and wait - Continue scene - Start scene - Note - Think - Say - for - Forever - For values from - For each value from - in - to - Repeat - Repeat until - When stage is tapped - Create clone of + When you receive + Broadcast + Broadcast and wait + Continue scene + Start scene + Note + Think + Say + for + Forever + For values from + For each value from + in + to + Repeat + Repeat until + When stage is tapped + Create clone of yourself - When you start as a clone - Delete this clone - - Assert - equals expected - Wait until all other scripts have stopped - "Single tap at" - "Touch at" - "for" - "Touch and slide" - "from x:" - Finish stage - Finish tests - Assert lists - Actual: - Expected: - assert - equals to expected item of + When you start as a clone + Delete this clone + + Assert + equals expected + Wait until all other scripts have stopped + "Single tap at" + "Touch at" + "for" + "Touch and slide" + "from x:" + Finish stage + Finish tests + Assert lists + Actual: + Expected: + assert + equals to expected item of For each item of @@ -1127,44 +1127,44 @@ End of loop - If - is true then - Else + If + is true then + Else End if - Set variable - Change variable - Write variable on device - Read variable from device - Write variable - to file + Set variable + Change variable + Write variable on device + Read variable from device + Write variable + to file variable.txt "Data successfully written to %1$s" - Read variable - from file - and + Read variable + from file + and keep the file delete the file - Write list on device - Read list from device + Write list on device + Read list from device add comment here… Hmmmm! Hello! "new message" - Add - to list - Delete all items from list - Delete item from list - at position - Insert - into list - at position - Replace item in list - at position - with - - Send web request to + Add + to list + Delete all items from list + Delete item from list + at position + Insert + into list + at position + Replace item in list + at position + with + + Send web request to https://catrob.at/joke - and store answer in + and store answer in Allow web access? Be very careful before allowing access, since the link may expose your personal information, such as your precise geographical location or any text @@ -1180,19 +1180,19 @@ later, you can remove the entry from the list of trusted domains in the settings of this app. - Get image from + Get image from https://catrob.at/penguin https://catrob.at/HalloweenPortrait https://catrob.at/HalloweenLandscape - and use as current look - and use as current background + and use as current look + and use as current background "Get image from %1$s returned HTTP error %2$s" "Get image from %1$s could not retrieve a recognized image format" - Store column - of the - comma-separated values - into list + Store column + of the + comma-separated values + into list kitty,cute\npuppy,naughty\noctopus,intelligent @@ -1412,21 +1412,21 @@ needs read and write access to it. You can always change permissions through you - Set Arduino digital pin - Set Arduino PWM~ pin - to + Set Arduino digital pin + Set Arduino PWM~ pin + to - Set Raspberry Pi pin - to - If Raspberry Pi pin - is true then - When Raspberry Pi pin - changes to + Set Raspberry Pi pin + to + If Raspberry Pi pin + is true then + When Raspberry Pi pin + changes to high low - Set Raspberry Pi PWM pin + Set Raspberry Pi PWM pin @@ -1436,16 +1436,16 @@ needs read and write access to it. You can always change permissions through you - Set NXT motor - to - speed - Turn NXT motor - by - Stop NXT motor - Play NXT tone - Duration - Frequency - ×100Hz + Set NXT motor + to + speed + Turn NXT motor + by + Stop NXT motor + Play NXT tone + Duration + Frequency + ×100Hz A B @@ -1516,19 +1516,19 @@ needs read and write access to it. You can always change permissions through you B+C All - Play EV3 tone - for - Volume - % + Play EV3 tone + for + Volume + % - Stop EV3 motor + Stop EV3 motor - Set EV3 motor + Set EV3 motor - Turn EV3 motor - by + Turn EV3 motor + by - Set EV3 LED status + Set EV3 LED status Off Green Red @@ -1542,81 +1542,81 @@ needs read and write access to it. You can always change permissions through you - Take off / land AR.Drone 2.0 - Play AR.Drone 2.0 flash animation - Flip AR.Drone 2.0 - Move AR.Drone 2.0 left - Move AR.Drone 2.0 right - Move AR.Drone 2.0 forward - Move AR.Drone 2.0 backward - Move AR.Drone 2.0 up - Move AR.Drone 2.0 down - Emergency AR.Drone 2.0 - Turn AR.Drone 2.0 right - Turn AR.Drone 2.0 left + Take off / land AR.Drone 2.0 + Play AR.Drone 2.0 flash animation + Flip AR.Drone 2.0 + Move AR.Drone 2.0 left + Move AR.Drone 2.0 right + Move AR.Drone 2.0 forward + Move AR.Drone 2.0 backward + Move AR.Drone 2.0 up + Move AR.Drone 2.0 down + Emergency AR.Drone 2.0 + Turn AR.Drone 2.0 right + Turn AR.Drone 2.0 left Set config AR.Drone 2.0 - Switch AR.Drone 2.0 camera + Switch AR.Drone 2.0 camera Altitude limit Vertical speed limit Rotation speed limit Tilt limit - with - power + with + power - Blink green red - Blink green - Blink red - Blink orange - Snake green red - Fire - Standard - Red - Green - Red snake - Blank - Right missile - Left missile - Double missile - Front left green others red - Front right green others red - Rear right green others red - Rear left green others red - Left green right red - Left red right green - Blink standard + Blink green red + Blink green + Blink red + Blink orange + Snake green red + Fire + Standard + Red + Green + Red snake + Blank + Right missile + Left missile + Double missile + Front left green others red + Front right green others red + Rear right green others red + Rear left green others red + Left green right red + Left red right green + Blink standard - Move Jumping Sumo forward - Move Jumping Sumo backward - Animations Jumping Sumo - No Jumping Sumo sound - Jump Jumping Sumo long - Jump Jumping Sumo high - Turn Jumping Sumo left - Turn Jumping Sumo right - degrees - Flip Jumping Sumo - Taking picture Jumping Sumo + Move Jumping Sumo forward + Move Jumping Sumo backward + Animations Jumping Sumo + No Jumping Sumo sound + Jump Jumping Sumo long + Jump Jumping Sumo high + Turn Jumping Sumo left + Turn Jumping Sumo right + degrees + Flip Jumping Sumo + Taking picture Jumping Sumo - Sound + Sound - Spin - Tab - Slowshake - Metronome - Ondulation - Spinjump - Spiral - Slalom + Spin + Tab + Slowshake + Metronome + Ondulation + Spinjump + Spiral + Slalom - Volume + Volume Normal Robot Insect @@ -1625,26 +1625,26 @@ needs read and write access to it. You can always change permissions through you - Stop Phiro motor - Move Phiro motor forward - Move Phiro motor backward - Speed + Stop Phiro motor + Move Phiro motor forward + Move Phiro motor backward + Speed - If Phiro - is activated + If Phiro + is activated - Play Phiro music\n - Duration - tone - seconds + Play Phiro music\n + Duration + tone + seconds - Set Phiro light - Red - Green - Blue + Set Phiro light + Red + Green + Blue @@ -1687,7 +1687,7 @@ needs read and write access to it. You can always change permissions through you Data true false - . + . Formula editor Changes saved. Changes discarded! @@ -1697,62 +1697,62 @@ needs read and write access to it. You can always change permissions through you Properties of this actor or object ( ) - sine + sine (90) - cosine + cosine (360) - tangent + tangent (45) - natural logarithm + natural logarithm (2.718281828459) - decimal logarithm + decimal logarithm (10) - pi + pi - color - square root + color + square root (4) - random value from to + random value from to (1,6) - absolute value + absolute value (1) - round + round (1.6) - modulo + modulo (3,2) - arcsine + arcsine (0.5) - arccosine + arccosine (0) - arctangent + arctangent (1) - arctangent2 + arctangent2 (-1, 0) - exponent + exponent (1) - power + power (2,3) - floor + floor (0.7) - ceiling + ceiling (0.3) - maximum of + maximum of (5,4) - minimum of + minimum of (7,2) if then else (false, 2, 3) - true - false - length + true + false + length (\'hello world\') - letter + letter (1,\'hello world\') - join + join (\'hello\',\' world\') join (\'hello\',\' world\',\'!\') - regular expression + regular expression (\' an? ([^ .]+)\',\'I am a panda.\') Regular expression assistant @@ -1761,76 +1761,76 @@ needs read and write access to it. You can always change permissions through you More information The keyword could not be found. JSON extractor - arduino digital pin - arduino analog pin - raspberry pi pin + arduino digital pin + arduino analog pin + raspberry pi pin (3) - stage touch x - stage touch y - stage is touched - stage touch x - stage touch y - stage is touched - last stage touch index + stage touch x + stage touch y + stage is touched + stage touch x + stage touch y + stage is touched + last stage touch index number of current touches index of current touch (1) - item + item (1,*list name*) - contains + contains (*list name*,1) - item\'s index + item\'s index (1,*list name*) - number of items + number of items (*list name*) touches actor or object - touches edge - touches finger + touches edge + touches finger touches color (\'#ff0000\') color touches color (\'#ff0000\',\'#00ff00\') color at x y (100,200) - acceleration x - acceleration y - acceleration z - compass direction - latitude - longitude - location accuracy - altitude + acceleration x + acceleration y + acceleration z + compass direction + latitude + longitude + location accuracy + altitude user language - inclination x - inclination y - loudness + inclination x + inclination y + loudness timer - year - month - day - weekday - hour - minute - second - drone battery status - drone emergency state - drone flying - drone initialized - drone usb active - drone usb remaining time - drone camera ready - drone record ready - drone camera recording - drone camera number of frames - NXT sensor 1 - NXT sensor 2 - NXT sensor 3 - NXT sensor 4 - EV3 sensor 1 - EV3 sensor 2 - EV3 sensor 3 - EV3 sensor 4 + year + month + day + weekday + hour + minute + second + drone battery status + drone emergency state + drone flying + drone initialized + drone usb active + drone usb remaining time + drone camera ready + drone record ready + drone camera recording + drone camera number of frames + NXT sensor 1 + NXT sensor 2 + NXT sensor 3 + NXT sensor 4 + EV3 sensor 1 + EV3 sensor 2 + EV3 sensor 3 + EV3 sensor 4 NXT touch NXT sound NXT light @@ -1848,35 +1848,35 @@ needs read and write access to it. You can always change permissions through you EV3 NXT light active EV3 NXT sound EV3 NXT ultrasonic - gamepad A pressed - gamepad B pressed - gamepad up pressed - gamepad down pressed - gamepad left pressed - gamepad right pressed - phiro front left sensor - phiro front right sensor - phiro side left sensor - phiro side right sensor - phiro bottom left sensor - phiro bottom right sensor - nfc tag id - nfc tag message - position x - position y - transparency - brightness - size - direction - layer - x velocity - y velocity - angular velocity - look number - look name - background number - background name - distance to touch position + gamepad A pressed + gamepad B pressed + gamepad up pressed + gamepad down pressed + gamepad left pressed + gamepad right pressed + phiro front left sensor + phiro front right sensor + phiro side left sensor + phiro side right sensor + phiro bottom left sensor + phiro bottom right sensor + nfc tag id + nfc tag message + position x + position y + transparency + brightness + size + direction + layer + x velocity + y velocity + angular velocity + look number + look name + background number + background name + distance to touch position Compute Properties Functions @@ -1902,20 +1902,20 @@ needs read and write access to it. You can always change permissions through you NFC Chromecast Abc - - < - > - and - or - not - - - = - × - + - - - ÷ - ^ + + < + > + and + or + not + + + = + × + + + - + ÷ + ^ delete color picker toggle functions @@ -1930,10 +1930,10 @@ needs read and write access to it. You can always change permissions through you expression current items Make it a list - first face is visible - first face size - first face x position - first face y position + first face is visible + first face size + first face x position + first face y position second face is visible second face size second face x position @@ -1982,27 +1982,27 @@ needs read and write access to it. You can always change permissions through you - Show variable - Hide variable - at - size: - color: - aligned - centered - left - right + Show variable + Hide variable + at + size: + color: + aligned + centered + left + right Pick color Pick note - Turn camera - on - off - Use camera - front - rear + Turn camera + on + off + Use camera + front + rear Something went wrong while trying to use the camera. @@ -2070,7 +2070,7 @@ needs read and write access to it. You can always change permissions through you % - ㎠+ ㎠sans_serif serif From 1be4da6765e5c5e3e205b5c67a23e492c35462f2 Mon Sep 17 00:00:00 2001 From: Dev Sebastian Date: Sat, 20 Feb 2021 19:59:11 +0530 Subject: [PATCH 104/189] CATROID-732 Add the OCR sensors for text block and language of text block (#3919) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ticket: https://jira.catrob.at/browse/CATROID-732 Add the OCR sensors for text block and language of text block ### Your checklist for this pull request Please review the [contributing guidelines](https://github.com/Catrobat/Catroid/blob/develop/README.md) and [wiki pages](https://github.com/Catrobat/Catroid/wiki/) of this repository. - [x] Include the name of the Jira ticket in the PR’s title - [x] Include a summary of the changes plus the relevant context - [x] Choose the proper base branch (*develop*) - [x] Confirm that the changes follow the project’s coding guidelines - [x] Verify that the changes generate no compiler or linter warnings - [x] Perform a self-review of the changes - [x] Verify to commit no other files than the intentionally changed ones - [ ] Include reasonable and readable tests verifying the added or changed behavior - [x] Confirm that new and existing unit tests pass locally - [x] Check that the commits’ message style matches the [project’s guideline](https://github.com/Catrobat/Catroid/wiki/Commit-Message-Guidelines) - [x] Stick to the project’s gitflow workflow - [x] Verify that your changes do not have any conflicts with the base branch - [ ] After the PR, verify that all CI checks have passed - [x] Post a message in the *catroid-stage* or *catroid-ide* [Slack channel](https://catrobat.slack.com) and ask for a code reviewer --- catroid/build.gradle | 1 + .../catrobat/catroid/common/Constants.java | 2 +- .../catroid/formulaeditor/FormulaElement.java | 9 ++++- .../catroid/formulaeditor/Functions.java | 3 +- .../InternFormulaKeyboardAdapter.java | 6 +++ .../InternToExternGenerator.java | 4 ++ .../catroid/formulaeditor/Sensors.java | 2 +- .../function/TextBlockFunctionProvider.java | 10 +++++ .../fragment/CategoryListFragment.java | 23 ++++++++++- .../catrobat/catroid/utils/TextBlockUtil.java | 40 +++++++++++++++++++ catroid/src/main/res/values/strings.xml | 3 ++ 11 files changed, 97 insertions(+), 6 deletions(-) diff --git a/catroid/build.gradle b/catroid/build.gradle index 3ceda92626e..70c6d51b42a 100644 --- a/catroid/build.gradle +++ b/catroid/build.gradle @@ -415,6 +415,7 @@ dependencies { // ML Kit implementation 'com.google.android.gms:play-services-mlkit-face-detection:16.0.0' implementation 'com.google.android.gms:play-services-mlkit-text-recognition:16.1.0' + implementation 'com.google.mlkit:language-id:16.1.0' // libGDX implementation "com.badlogicgames.gdx:gdx:$gdxVersion" diff --git a/catroid/src/main/java/org/catrobat/catroid/common/Constants.java b/catroid/src/main/java/org/catrobat/catroid/common/Constants.java index 0e1b73a3d1f..0f348bc6186 100644 --- a/catroid/src/main/java/org/catrobat/catroid/common/Constants.java +++ b/catroid/src/main/java/org/catrobat/catroid/common/Constants.java @@ -39,7 +39,7 @@ public final class Constants { - public static final double CURRENT_CATROBAT_LANGUAGE_VERSION = 0.999999996; + public static final double CURRENT_CATROBAT_LANGUAGE_VERSION = 0.999999997; public static final String REMOTE_DISPLAY_APP_ID = "CEBB9229"; public static final int CAST_CONNECTION_TIMEOUT = 5000; //in milliseconds diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/FormulaElement.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/FormulaElement.java index 0f871990c22..6ffdda7510f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/FormulaElement.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/FormulaElement.java @@ -105,9 +105,12 @@ public enum ElementType { private transient FormulaElement parent; private transient Map formulaFunctions; + TextBlockFunctionProvider textBlockFunctionProvider; + protected FormulaElement() { + textBlockFunctionProvider = new TextBlockFunctionProvider(); List functionProviders = Arrays.asList(new ArduinoFunctionProvider(), new RaspiFunctionProvider(), - new MathFunctionProvider(), new TouchFunctionProvider(), new TextBlockFunctionProvider()); + new MathFunctionProvider(), new TouchFunctionProvider(), textBlockFunctionProvider); formulaFunctions = new EnumMap<>(Functions.class); initFunctionMap(functionProviders, formulaFunctions); @@ -431,6 +434,10 @@ private Object interpretFunction(Functions function, Sprite sprite, Project curr .tryInterpretFunctionColorTouchesColor(arguments.get(0), arguments.get(1))); case COLOR_AT_XY: return Double.NaN; + case TEXT_BLOCK_FROM_CAMERA: + return textBlockFunctionProvider.interpretFunctionTextBlock(Double.parseDouble(arguments.get(0).toString())); + case TEXT_BLOCK_LANGUAGE_FROM_CAMERA: + return textBlockFunctionProvider.interpretFunctionTextBlockLanguage(Double.parseDouble(arguments.get(0).toString())); default: return interpretFormulaFunction(function, arguments); } diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Functions.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Functions.java index ca0260ebb90..1c4a62bce46 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Functions.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Functions.java @@ -34,7 +34,8 @@ public enum Functions { LETTER, JOIN, JOIN3, REGEX, LIST_ITEM, CONTAINS, INDEX_OF_ITEM, NUMBER_OF_ITEMS, ARDUINOANALOG, ARDUINODIGITAL, RASPIDIGITAL, MULTI_FINGER_X, MULTI_FINGER_Y, MULTI_FINGER_TOUCHED, INDEX_CURRENT_TOUCH, COLLIDES_WITH_COLOR, - COLOR_TOUCHES_COLOR, COLOR_AT_XY, TEXT_BLOCK_X, TEXT_BLOCK_Y, TEXT_BLOCK_SIZE, IF_THEN_ELSE; + COLOR_TOUCHES_COLOR, COLOR_AT_XY, TEXT_BLOCK_X, TEXT_BLOCK_Y, TEXT_BLOCK_SIZE, + TEXT_BLOCK_FROM_CAMERA, TEXT_BLOCK_LANGUAGE_FROM_CAMERA, IF_THEN_ELSE; private static final String TAG = Functions.class.getSimpleName(); public static final EnumSet TEXT = EnumSet.of(LENGTH, LETTER, JOIN, JOIN3, REGEX); diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java index 9f8f531cd5e..e8e8b0ac921 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternFormulaKeyboardAdapter.java @@ -425,6 +425,12 @@ public List createInternTokenListByResourceId(int resource, String case R.string.formula_editor_function_text_block_size: return buildSingleParameterFunction(Functions.TEXT_BLOCK_SIZE, InternTokenType.NUMBER, "1"); + case R.string.formula_editor_function_text_block_from_camera: + return buildSingleParameterFunction(Functions.TEXT_BLOCK_FROM_CAMERA, + InternTokenType.NUMBER, "1"); + case R.string.formula_editor_function_text_block_language_from_camera: + return buildSingleParameterFunction(Functions.TEXT_BLOCK_LANGUAGE_FROM_CAMERA, + InternTokenType.NUMBER, "1"); case R.string.formula_editor_function_collides_with_color: return buildSingleParameterFunction(Functions.COLLIDES_WITH_COLOR, STRING, "#ff0000"); case R.string.formula_editor_function_color_touches_color: diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java index c684d3781a9..f1f4c3acba4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/InternToExternGenerator.java @@ -153,6 +153,10 @@ public class InternToExternGenerator { R.string.formula_editor_function_text_block_y); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.TEXT_BLOCK_SIZE.name(), R.string.formula_editor_function_text_block_size); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.TEXT_BLOCK_FROM_CAMERA.name(), + R.string.formula_editor_function_text_block_from_camera); + INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.TEXT_BLOCK_LANGUAGE_FROM_CAMERA.name(), + R.string.formula_editor_function_text_block_language_from_camera); INTERN_EXTERN_LANGUAGE_CONVERTER_MAP.put(Sensors.GAMEPAD_A_PRESSED.name(), R.string.formula_editor_sensor_gamepad_a_pressed); diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java index b2a879a4b55..f8bf208e330 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/Sensors.java @@ -45,7 +45,7 @@ LAST_FINGER_INDEX, FINGER_X, FINGER_Y, FINGER_TOUCHED, NUMBER_CURRENT_TOUCHES, O NFC_TAG_ID(true), NFC_TAG_MESSAGE(true), GAMEPAD_A_PRESSED, GAMEPAD_B_PRESSED, GAMEPAD_UP_PRESSED, GAMEPAD_DOWN_PRESSED, GAMEPAD_LEFT_PRESSED, GAMEPAD_RIGHT_PRESSED, TEXT_FROM_CAMERA, TEXT_BLOCKS_NUMBER, TEXT_BLOCK_X, TEXT_BLOCK_Y, - TEXT_BLOCK_SIZE, SPEECH_RECOGNITION_LANGUAGE; + TEXT_BLOCK_SIZE, TEXT_BLOCK_FROM_CAMERA, TEXT_BLOCK_LANGUAGE_FROM_CAMERA, SPEECH_RECOGNITION_LANGUAGE; public final boolean isObjectSensor; public static final String TAG = Sensors.class.getSimpleName(); diff --git a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/function/TextBlockFunctionProvider.java b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/function/TextBlockFunctionProvider.java index 903697151c5..350d690d8f7 100644 --- a/catroid/src/main/java/org/catrobat/catroid/formulaeditor/function/TextBlockFunctionProvider.java +++ b/catroid/src/main/java/org/catrobat/catroid/formulaeditor/function/TextBlockFunctionProvider.java @@ -51,6 +51,16 @@ public void checkTextDetectionEnabled() { } } + public String interpretFunctionTextBlock(double argument) { + checkTextDetectionEnabled(); + return TextBlockUtil.getTextBlock((int) argument); + } + + public String interpretFunctionTextBlockLanguage(double argument) { + checkTextDetectionEnabled(); + return TextBlockUtil.getTextBlockLanguage((int) argument); + } + private double interpretFunctionTextBlockX(double argument) { checkTextDetectionEnabled(); return TextBlockUtil.getCenterCoordinates((int) argument).x; diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java index 8312e4a21fc..4885cd1aea4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CategoryListFragment.java @@ -187,7 +187,25 @@ public class CategoryListFragment extends Fragment implements CategoryListRVAdap R.string.formula_editor_sensor_text_blocks_number, R.string.formula_editor_function_text_block_x, R.string.formula_editor_function_text_block_y, - R.string.formula_editor_function_text_block_size); + R.string.formula_editor_function_text_block_size, + R.string.formula_editor_function_text_block_from_camera, + R.string.formula_editor_function_text_block_language_from_camera); + private static final List SENSORS_VISUAL_DETECTION_PARAMS = + asList(R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_no_parameter, + R.string.formula_editor_function_text_block_parameter, + R.string.formula_editor_function_text_block_parameter, + R.string.formula_editor_function_text_block_parameter, + R.string.formula_editor_function_text_block_parameter, + R.string.formula_editor_function_text_block_parameter); private static final List SENSORS_DATE_TIME = asList(R.string.formula_editor_sensor_timer, R.string.formula_editor_sensor_date_year, R.string.formula_editor_sensor_date_month, R.string.formula_editor_sensor_date_day, R.string.formula_editor_sensor_date_weekday, @@ -635,7 +653,8 @@ private List getTouchDetectionSensorItems() { } private List getVisualSensorItems() { - return addHeader(toCategoryListItems(SENSORS_VISUAL_DETECTION), getString(R.string.formula_editor_device_visual_detection)); + return addHeader(toCategoryListItems(SENSORS_VISUAL_DETECTION, SENSORS_VISUAL_DETECTION_PARAMS), + getString(R.string.formula_editor_device_visual_detection)); } private List getDateTimeSensorItems() { diff --git a/catroid/src/main/java/org/catrobat/catroid/utils/TextBlockUtil.java b/catroid/src/main/java/org/catrobat/catroid/utils/TextBlockUtil.java index 635a16be388..6cb3e63f3e5 100644 --- a/catroid/src/main/java/org/catrobat/catroid/utils/TextBlockUtil.java +++ b/catroid/src/main/java/org/catrobat/catroid/utils/TextBlockUtil.java @@ -27,11 +27,14 @@ import android.graphics.Rect; import android.util.Log; +import com.google.mlkit.nl.languageid.LanguageIdentification; +import com.google.mlkit.nl.languageid.LanguageIdentifier; import com.google.mlkit.vision.text.Text; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.stage.StageActivity; +import java.util.ArrayList; import java.util.List; import static org.catrobat.catroid.common.Constants.COORDINATE_TRANSFORMATION_OFFSET; @@ -40,9 +43,11 @@ public final class TextBlockUtil { private static List textBlocks; + private static List textBlockLanguages; private static int imageWidth; private static int imageHeight; private static final int MAX_TEXT_SIZE = 100; + private static LanguageIdentifier identifier; private TextBlockUtil() { // static class, nothing to do @@ -52,6 +57,41 @@ public static void setTextBlocks(List text, int width, int heigh textBlocks = text; imageWidth = width; imageHeight = height; + if (textBlockLanguages != null) { + textBlockLanguages.clear(); + } else { + textBlockLanguages = new ArrayList<>(); + } + + if (identifier == null) { + identifier = LanguageIdentification.getClient(); + } + + for (int i = 0; i < text.size(); i++) { + Text.TextBlock textBlock = text.get(i); + int finalIndex = i; + identifier.identifyLanguage(textBlock.getText()).addOnSuccessListener(langCode -> { + if (finalIndex < textBlocks.size() - 1) { + textBlockLanguages.add(finalIndex, langCode); + } else { + textBlockLanguages.add(langCode); + } + }); + } + } + + public static String getTextBlock(int index) { + if (textBlocks != null && (textBlocks.size() > (index - 1)) && index >= 1) { + return textBlocks.get(index - 1).getText(); + } + return "0"; + } + + public static String getTextBlockLanguage(int index) { + if (textBlockLanguages != null && (textBlockLanguages.size() > (index - 1)) && index >= 1) { + return textBlockLanguages.get(index - 1); + } + return "0"; } public static Point getCenterCoordinates(int index) { diff --git a/catroid/src/main/res/values/strings.xml b/catroid/src/main/res/values/strings.xml index 99dfaa37c85..08fd411d7cb 100644 --- a/catroid/src/main/res/values/strings.xml +++ b/catroid/src/main/res/values/strings.xml @@ -1943,6 +1943,9 @@ needs read and write access to it. You can always change permissions through you text block x from camera text block y from camera text block size from camera + text block from camera + text block language from camera + (1) Formula editor With the formula editor you can create mathematical and logical formulas that you can use in your bricks.\n\nYou can continue through this little intro by tapping From 834bb063e5af9b852b0857976bba712b0874faf7 Mon Sep 17 00:00:00 2001 From: Dev Sebastian Date: Sat, 20 Feb 2021 19:03:47 +0530 Subject: [PATCH 105/189] CATROID-922 Very high frequency crash in catroid.ui.SpriteActivity.onCreate --- .../fragment/CatblocksScriptFragment.kt | 4 +-- .../fragment/LookListFragment.java | 4 +++ .../recyclerview/fragment/ScriptFragment.java | 30 ++++++++++++++++--- .../fragment/SoundListFragment.java | 4 +++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt index d510f59bf01..771709d2f0e 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/CatblocksScriptFragment.kt @@ -158,9 +158,9 @@ class CatblocksScriptFragment( scriptFragment = if (brickToFocus == null) { ScriptFragment() } else if (brickToFocus is ScriptBrick) { - ScriptFragment((brickToFocus as ScriptBrick).script) + ScriptFragment.newInstance((brickToFocus as ScriptBrick).script) } else { - ScriptFragment(brickToFocus) + ScriptFragment.newInstance(brickToFocus) } val fragmentTransaction = parentFragmentManager.beginTransaction() diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java index 37e3ffcc837..8b7a0a07c5e 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.java @@ -67,6 +67,10 @@ public class LookListFragment extends RecyclerViewFragment { private LookData currentItem; + public LookListFragment() { + // required empty constructor + } + @Override protected void initializeAdapter() { SnackbarUtil.showHintSnackbar(getActivity(), R.string.hint_looks); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index c34ec658dd8..3d3d08004de 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -80,6 +80,7 @@ import java.util.List; import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; @@ -99,6 +100,8 @@ public class ScriptFragment extends ListFragment implements ProjectLoadTask.ProjectLoadListener { public static final String TAG = ScriptFragment.class.getSimpleName(); + private static final String BRICK_TAG = "brickToFocus"; + private static final String SCRIPT_TAG = "scriptToFocus"; @Retention(RetentionPolicy.SOURCE) @IntDef({NONE, BACKPACK, COPY, DELETE, COMMENT, CATBLOCKS}) @@ -129,15 +132,34 @@ public class ScriptFragment extends ListFragment implements private Brick brickToFocus; private Script scriptToFocus; - public ScriptFragment(Brick brickToFocus) { - this.brickToFocus = brickToFocus; + public static ScriptFragment newInstance(Brick brickToFocus) { + ScriptFragment scriptFragment = new ScriptFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable(BRICK_TAG, brickToFocus); + scriptFragment.setArguments(bundle); + return scriptFragment; + } + + public static ScriptFragment newInstance(Script scriptToFocus) { + ScriptFragment scriptFragment = new ScriptFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable(SCRIPT_TAG, scriptToFocus); + scriptFragment.setArguments(bundle); + return scriptFragment; } public ScriptFragment() { + // required empty constructor } - public ScriptFragment(Script scriptToFocus) { - this.scriptToFocus = scriptToFocus; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle bundle = getArguments(); + if (bundle != null) { + this.brickToFocus = (Brick) bundle.get(BRICK_TAG); + this.scriptToFocus = (Script) bundle.get(SCRIPT_TAG); + } } @Override diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java index 83d3807630e..ce9df4cf47b 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.java @@ -54,6 +54,10 @@ public class SoundListFragment extends RecyclerViewFragment { private SoundController soundController = new SoundController(); + public SoundListFragment() { + // required empty constructor + } + @Override protected void initializeAdapter() { SnackbarUtil.showHintSnackbar(getActivity(), R.string.hint_sounds); From aba5d793eb6731efcd1286dca3ddf9b960a922d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=B6glehner=20Martin?= Date: Thu, 21 Jan 2021 14:28:39 +0100 Subject: [PATCH 106/189] CATROID-824 Copy connected bricks only --- .../uiespresso/ui/fragment/CopyBrickTest.java | 221 ++++++++++++++++++ .../ui/recyclerview/adapter/BrickAdapter.java | 70 +++++- .../recyclerview/fragment/ScriptFragment.java | 2 +- 3 files changed, 290 insertions(+), 3 deletions(-) create mode 100644 catroid/src/androidTest/java/org/catrobat/catroid/uiespresso/ui/fragment/CopyBrickTest.java diff --git a/catroid/src/androidTest/java/org/catrobat/catroid/uiespresso/ui/fragment/CopyBrickTest.java b/catroid/src/androidTest/java/org/catrobat/catroid/uiespresso/ui/fragment/CopyBrickTest.java new file mode 100644 index 00000000000..b81f82c3a02 --- /dev/null +++ b/catroid/src/androidTest/java/org/catrobat/catroid/uiespresso/ui/fragment/CopyBrickTest.java @@ -0,0 +1,221 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2021 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.uiespresso.ui.fragment; + +import org.catrobat.catroid.ProjectManager; +import org.catrobat.catroid.R; +import org.catrobat.catroid.content.Project; +import org.catrobat.catroid.content.Script; +import org.catrobat.catroid.content.Sprite; +import org.catrobat.catroid.content.StartScript; +import org.catrobat.catroid.content.bricks.ChangeXByNBrick; +import org.catrobat.catroid.content.bricks.GlideToBrick; +import org.catrobat.catroid.content.bricks.IfLogicBeginBrick; +import org.catrobat.catroid.content.bricks.SetVariableBrick; +import org.catrobat.catroid.content.bricks.SetXBrick; +import org.catrobat.catroid.test.utils.TestUtils; +import org.catrobat.catroid.ui.SpriteActivity; +import org.catrobat.catroid.uiespresso.util.rules.FragmentActivityTestRule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.espresso.DataInteraction; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import static org.catrobat.catroid.uiespresso.content.brick.utils.BrickDataInteractionWrapper.onBrickAtPosition; +import static org.hamcrest.Matchers.not; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.Espresso.openContextualActionModeOverflowMenu; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isChecked; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +@RunWith(AndroidJUnit4.class) +public class CopyBrickTest { + + int firstScriptEndIndex = 7; + int secondScriptEndIndex = 9; + int firstIndexComposite = 1; + int lastIndexComposite = 5; + + @Rule + public FragmentActivityTestRule baseActivityTestRule = new + FragmentActivityTestRule<>(SpriteActivity.class, SpriteActivity.EXTRA_FRAGMENT_POSITION, + SpriteActivity.FRAGMENT_SCRIPTS); + + @Before + public void setUp() throws Exception { + createProject(); + baseActivityTestRule.launchActivity(); + } + + @After + public void tearDown() throws IOException { + baseActivityTestRule.getActivity().finish(); + TestUtils.deleteProjects(CopyBrickTest.class.getSimpleName()); + } + + @Test + public void testNoItemSelected() { + openContextualActionModeOverflowMenu(); + onView(withText(R.string.copy)) + .check(matches(isDisplayed())); + + onView(withText(R.string.copy)) + .perform(click()); + + for (int brickIndex = 0; brickIndex <= secondScriptEndIndex; brickIndex++) { + getCheckbox(brickIndex) + .check(matches(isEnabled())) + .check(matches(not(isChecked()))); + } + } + + @Test + public void testSelectWholeScript() { + openContextualActionModeOverflowMenu(); + onView(withText(R.string.copy)).perform(click()); + + int brickIndex = 0; + getCheckbox(brickIndex) + .perform(click()) + .check(matches(isChecked())); + + for (brickIndex++; brickIndex <= firstScriptEndIndex; brickIndex++) { + getCheckbox(brickIndex) + .check(matches(not(isEnabled()))) + .check(matches(isChecked())); + } + for (; brickIndex <= secondScriptEndIndex; brickIndex++) { + getCheckbox(brickIndex) + .check(matches(not(isEnabled()))) + .check(matches(not(isChecked()))); + } + } + + @Test + public void testSelectSingleBrick() { + openContextualActionModeOverflowMenu(); + onView(withText(R.string.copy)).perform(click()); + + int brickIndex = 6; + getCheckbox(brickIndex) + .perform(click()) + .check(matches(isChecked())) + .check(matches(isEnabled())); + + getCheckbox(brickIndex - 1) + .check(matches(isEnabled())) + .check(matches(not(isChecked()))); + + getCheckbox(brickIndex + 1) + .check(matches(isEnabled())) + .check(matches(not(isChecked()))); + + getCheckbox(brickIndex) + .perform(click()) + .check(matches(not(isChecked()))) + .check(matches(isEnabled())); + + getCheckbox(brickIndex + 1) + .perform(click()) + .check(matches(isChecked())) + .check(matches(isEnabled())); + + getCheckbox(brickIndex + 2) + .perform(click()) + .check(matches(not(isChecked()))) + .check(matches(not(isEnabled()))); + } + + @Test + public void testSelectCompositeBrick() { + openContextualActionModeOverflowMenu(); + onView(withText(R.string.copy)).perform(click()); + + getCheckbox(lastIndexComposite) + .perform(click()) + .check(matches(isChecked())) + .check(matches(isEnabled())); + + getCheckbox(firstIndexComposite) + .check(matches(isChecked())) + .check(matches(isEnabled())); + + for (int brickIndex = firstIndexComposite + 1; brickIndex < lastIndexComposite; brickIndex++) { + getCheckbox(brickIndex) + .check(matches(isChecked())) + .check(matches(not(isEnabled()))); + } + + getCheckbox(firstIndexComposite - 1) + .check(matches(isEnabled())) + .check(matches(not(isChecked()))); + getCheckbox(lastIndexComposite + 1) + .check(matches(isEnabled())) + .check(matches(not(isChecked()))); + } + + private DataInteraction getCheckbox(int brickIndex) { + return onBrickAtPosition(brickIndex).onChildView(withId(R.id.brick_checkbox)); + } + + private void createProject() { + Project project = new Project(ApplicationProvider.getApplicationContext(), CopyBrickTest.class.getSimpleName()); + + Sprite sprite = new Sprite("testSprite"); + project.getDefaultScene().addSprite(sprite); + + Script startScript = new StartScript(); + IfLogicBeginBrick ifBrick = new IfLogicBeginBrick(); + ifBrick.addBrickToIfBranch(new SetXBrick()); + ifBrick.addBrickToElseBranch(new ChangeXByNBrick()); + startScript.addBrick(ifBrick); + startScript.addBrick(new SetVariableBrick()); + startScript.addBrick(new GlideToBrick()); + startScript.setParents(); + + Script secondScript = new StartScript(); + SetXBrick setXBrick = new SetXBrick(); + secondScript.addBrick(setXBrick); + secondScript.setParents(); + + sprite.addScript(startScript); + sprite.addScript(secondScript); + + ProjectManager.getInstance().setCurrentProject(project); + ProjectManager.getInstance().setCurrentSprite(sprite); + } +} diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/BrickAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/BrickAdapter.java index fc3c1b98d47..cf2e2f77cba 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/BrickAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/BrickAdapter.java @@ -58,17 +58,20 @@ public class BrickAdapter extends BaseAdapter implements public static final float DISABLED_BRICK_ALPHA = .8f; @Retention(RetentionPolicy.SOURCE) - @IntDef({NONE, ALL, SCRIPTS_ONLY}) + @IntDef({NONE, ALL, SCRIPTS_ONLY, CONNECTED_ONLY}) @interface CheckBoxMode {} public static final int NONE = 0; public static final int ALL = 1; public static final int SCRIPTS_ONLY = 2; + public static final int CONNECTED_ONLY = 3; @CheckBoxMode private int checkBoxMode = NONE; private List